VPN 서버가 패킷에서 노트북 주소를 읽어 로그에 기록한다고 상상한다. 실제로 읽는 것은 마지막 NAT 홉이 외부 헤더에 넣은 값이며, 테더링한 휴대폰에서는 수백 명의 다른 가입자와 공유되는 주소인 경우가 많다. 내 컴퓨터의 192.168.x.x 는 그 헤더에서 인터넷을 건너지 않으며, 터널 주소는 연결이 이미 설정된 뒤에 서버가 할당한다. 그래서 서버 로그와 노트북의 ip addr 가 서로 다를 때 둘 다 틀린 것이 아니며, 하나의 세션에서 서로 다른 계층을 설명한다.

세 개의 주소, 로그에는 하나만

혼란은 세 주소를 하나로 합치면서 생긴다. 각각 소유자가 다르고, 다른 헤더에 살며, 다른 경로로 서버에 도달한다.

AddressWho assigns itWhere it sitsVisible to the VPN server
Device address, e.g. 192.168.1.24Your router via DHCPOuter header, before translationNo, rewritten in place
Translated address and portRouter, ISP CGNAT, or bothOuter header, after translationYes, this is the tuple it logs
Tunnel address, e.g. 10.8.0.6The VPN server itselfInner header, after decapsulationYes, but it chose it

연결 시점에 알 수 없는 것은 가운데 행뿐이다. 서버는 데몬에 따라 피어 테이블, 상태 파일 또는 플로 로그에 이를 기록하며, WireGuard는 엔드포인트라고 부르고, OpenVPN 상태 파일은 Real Address 로 표시하며, strongSwan은 IKE_SA의 원격 호스트로 보고한다. 이 값은 다른 원본에서 패킷이 올 때마다 갱신되므로 아무도 아무것도 다시 시작하지 않아도 바뀐다.

맨 아래 행은 사람들이 신원 주장으로 잘못 읽는 것이다. 서버 구성의 한 자리를 표시할 뿐 사람이 아니며, 서버가 자기 풀에서 선택했기 때문이다. 두 사용자가 다른 날 같은 터널 주소를 받을 수 있고, 한 사람이 두 기기에서 두 개를 가질 수 있다.

터널이 살아 있는 동안 기록된 튜플이 바뀌는 이유

주소 변환은 타이머가 있는 테이블이지 영구 결속이 아니다. 가정용 공유기는 마지막 패킷 이후 잠시 UDP 매핑을 유지하고, 통신사 게이트웨이는 자체 일정에 따라 포트를 재활용하며, Wi-Fi에서 LTE로 이동한 휴대폰은 완전히 다른 원본으로 돌아온다. 여기서 리눅스 conntrack 기본값이 유용한 기준이 되는데, nf_conntrack_udp_timeout 는 30초이고 스트리밍 변형은 120이므로 조용한 터널은 사용자가 알아차리기 훨씬 전에 매핑을 잃을 수 있다.

터널이 살아남는 것은 프로토콜이 주소가 아니라 피어를 인증하기 때문이다. WireGuard는 핸드셰이크 후 상태가 없으므로 인증된 패킷이 저장된 엔드포인트를 갱신하고 재바인딩은 다음 패킷에서 회복되며, persistent-keepalive = 25 가 있는 이유가 바로 유휴 상태에서 매핑을 따뜻하게 유지하기 위해서다. OpenVPN의 --float 도 같은 역할을 하며 인증된 클라이언트가 새 주소와 포트에서 이어갈 수 있게 한다. float가 기본적으로 꺼진 2.4 및 2.5 빌드에서는 재바인딩이 세션을 재설정하고 클라이언트가 다시 연결한다.

IPsec은 더 많은 가동 부품으로 그곳에 도달한다. IKEv2는 NAT 검출 페이로드에서 원본과 목적지 해시를 비교해 변환을 감지하고, UDP 4500 캡슐화로 전환하며, keepalive를 새 튜플까지 따라간다. keepalive가 차단되면 SA는 서류상 살아 있지만 한 방향 트래픽은 조용히 멈춘다.

서버가 귀속할 수 있는 것과 없는 것

죽일 만한 신화는 변환이 운영자로부터 당신을 숨긴다는 것이다. 바뀌는 것은 라벨이지 관측이 아니다. 통신사 NAT 뒤의 게이트웨이는 100.64.0.0/10 공간 또는 많은 가입자가 공유하는 하나의 공인 주소를 보며, 그래도 흐름을 인증서 주체, WireGuard 공개 키, 할당된 터널 주소, 바이트 카운터, 시간 창에 연결할 수 있다. 그중 어느 것도 당신의 LAN 주소를 필요로 하지 않는다.

한계는 반대 방향으로도 작동한다. 로그의 공유 주소는 가정이 아니라 게이트웨이를 가리키고, 같은 변환 주소의 서로 다른 포트에서 온 두 세션은 다른 기기이며, 포트가 재활용되었다면 서로 다른 두 날의 같은 주소는 무관한 두 가입자일 수 있다. 피어 키만 기록하는 서버는 계정 데이터베이스 없이 이를 고객에게 연결할 수 없고, 주소만 기록하는 서버는 같은 공유기 뒤의 노트북과 휴대폰을 구분할 수 없다.

추측하지 말고 양쪽 끝을 비교하라

무슨 일이 있었는지 확인하려면 같은 연결을 양쪽 끝에서 같은 순간에 캡처하고 주소가 아니라 튜플을 비교한다. 클라이언트에서 어떤 변환도 일어나기 전에:

ss -uapn 'dport = :51820'
ip -4 route get 203.0.113.10
wg show wg0 endpoints

그다음 공유기나 CGNAT 게이트웨이의 변환 항목과 최종적으로 서버에 도착하는 것을 읽는다:

conntrack -L -p udp --dport 51820
tcpdump -ni eth0 udp port 51820

대부분의 불일치는 세 가지 패턴으로 설명된다. 서버의 원본 포트가 로컬 포트와 다르고 목적지가 일치하면 일반 포트 변환이다. 서버의 원본 주소가 내 것이 아닌 ISP 블록에 속하면 최소 한 계층의 NAT가 더 있다. 유휴 후 패킷이 멈추고 새 포트로 다시 시작하면 매핑이 만료된 것이지 라우팅 결함이 아니다. 타임스탬프가 한두 초 이상 떨어져 있으면 서로 다른 두 시도를 비교하는 것이다.

그 차이가 문제를 일으키는 곳

서버 오류처럼 보이는 중단은 보통 여기서 시작된다. 집 주소에 고정된 접근 규칙은 ISP 임대가 바뀐 뒤 실패한다. 변환 주소와 일치하는 fail2ban 규칙은 그 게이트웨이 뒤의 모든 가입자를 한꺼번에 차단한다. 고정 원격 주소를 가진 사이트 간 피어는 모바일 링크가 바뀐 뒤 키 갱신을 멈춘다. 터널 프로토콜은 정상이었지만, 외부 튜플에 대한 가정이 틀렸다.

같은 혼란은 서버 쪽에서도 나타난다. VPN 상자 자체가 NAT 뒤에 있으면 포트 포워딩과 작동하는 포워딩 경로가 필요하며, strongSwan 포워딩 가이드가 IPsec의 그 사례를 다룬다. 사설 주소로만 접근 가능한 서버는 클라이언트가 제시하는 변환된 튜플을 결코 보지 못하며, 이는 클라이언트가 변환되는 것과는 다른 문제다.

다음 네 가지 점검을 순서대로 수행하고 처음 실패하는 지점에서 멈춘다:

  • 양쪽 끝에서 동시에 캡처하고 원본 포트, 목적지 포트, 타임스탬프가 일치하는지 확인한다.
  • 서버의 피어 목록에서 기대한 주소가 아니라 현재 보유한 주소를 읽는다.
  • conntrack 또는 NAT 테이블에서 항목과 남은 수명을 확인한다.
  • 클라이언트의 터널 인터페이스 주소가 LAN 주소가 아니라 서버가 할당한 주소와 일치하는지 확인한다.

두 캡처가 튜플에 동의하는데도 터널이 실패하면 변환은 당신의 문제가 아니므로, 핸드셰이크와 터널 내부의 라우팅 테이블로 넘어간다.

관련 글