Wi-Fi가 바뀌거나 Ethernet을 꽂을 때 VPN이 끊기는 이유
'새 SSID, 액세스 포인트 사이의 로밍, 그리고 꽂힌 케이블이 터널을 세 곳에서 각각 다르게 끊습니다. 출발지 주소, 그다음 경로, 그다음 프로토콜을 확인하세요.'
두 가지 일이 하나의 장애로 보고됩니다: 노트북이 다른 Wi-Fi 네트워크로 옮겨간 경우, 또는 Wi-Fi가 살아 있는데 케이블이 꽂힌 경우입니다. 클라이언트는 여전히 연결됨이라고 말하고, 아이콘은 정상으로 보이며, 터널은 아무것도 나르지 않습니다. 그 아래에서 움직일 수 있는 상태는 링크, 로컬 주소, 기본 경로 세 가지뿐이고, 어느 것이 움직였는지가 터널이 스스로 회복될지 재연결이 필요한지를 결정합니다. 저는 계정 설정을 바꿔서 고쳐진 적이 한 번도 없는 이 순서대로 확인합니다.
링크, 주소, 경로는 각자 움직인다
같은 네트워크 안의 액세스 포인트 사이 로밍은 보통 L2 이벤트입니다. 무선이 다시 결합하고, 인터페이스는 주소와 게이트웨이를 유지하며, 터널이 의존하는 것은 아무것도 바뀌지 않습니다. 그래서 큰 사무실을 걸어 다녀도 모르고 지나갈 때가 있습니다. 다른 SSID에 붙는 것은 다르며, 옛 인터페이스가 내려가고 DHCP가 새 주소와 새 게이트웨이, 새 리졸버를 주는 동안 터널이 쓰던 외부 흐름은 더 이상 존재하지 않습니다.
Ethernet은 세 번째 형태를 더합니다. Wi-Fi는 절대 끊기지 않으므로 링크 이벤트가 아예 발생하지 않지만, 유선 인터페이스가 자기 주소를 가지고 나타나며 흔히 메트릭에서 기본 경로를 가져갑니다. 터널은 더 이상 선호되지 않는 경로로 계속 돌거나, 클라이언트가 소켓을 시작했던 무선 네트워크에 고정해 둡니다. 브라우저에서는 둘 다 똑같이 보입니다. 케이블이 딸깍 들어오는 순간 페이지가 멈춥니다.
그래서 첫 질문은 Wi-Fi가 바뀌었느냐가 아닙니다. 터널이 살아 있는 동안 묶여 있는 주소나 엔드포인트로 가는 경로가 바뀌었느냐입니다.
바깥 소켓은 방금 사라진 주소에 고정되어 있습니다
모든 터널은 바깥 흐름입니다. 로컬 주소와 포트가 서버의 주소와 포트와 대화합니다. Linux에서는 옛 출발지에 묶인 UDP 소켓이고, 주소를 가진 인터페이스가 사라지면 전송은 EADDRNOTAVAIL로 실패하거나 서버가 본 적 없는 출발지로 새 인터페이스를 통해 나갑니다.
먼 쪽도 자기 고정을 유지합니다. MOBIKE가 없는 IKEv2 SA는 주소 쌍으로 식별되고, OpenVPN세션은 학습한 피어 주소에 묶이며, NAT 매핑은 그것을 만든 사설 주소와 포트, 공인 주소에 속합니다. 다른 NAT 뒤로 옮기면 모든 응답이 더 이상 존재하지 않는 매핑으로 갑니다. 여러분의 머신에 잘못 설정된 것은 없습니다. 다섯 항목이 떠나온 네트워크를 가리킬 뿐입니다.
이론을 세우기 전에 상태를 읽으세요:
ss -unp각 터널 소켓이 실제로 쥐고 있는 로컬 주소와 포트를 보여줍니다.ip route get 203.0.113.10커널이 지금 엔드포인트에 사용할 출발지 주소와 장치를 출력합니다.wg show wg0 endpoints,swanctl --list-sas또는 클라이언트 로그가 먼 쪽이 대화한다고 믿는 피어 주소를 보여줍니다.
소켓 주소와 경로 조회가 어긋나면 끊긴 지점을 찾은 것이고, 자격 증명 변경으로는 거기에 닿지 않습니다.
새 출발지 주소에 대해 각 프로토콜이 하는 일
클라이언트는 변화를 정도껏 흡수하고, 제가 재연결 동작에서 추측하는 대신 클라이언트 설정과 견주는 것이 이 표입니다.
| Tunnel | Recovery behaviour | Failure signature |
|---|---|---|
| WireGuard | Updates the peer endpoint when an authenticated packet arrives from a new address; no handshake needed if traffic continues. | Handshake current, no return traffic; wg show still lists the old endpoint. |
| IKEv2/IPsec | MOBIKE (RFC 4555) moves the SA to the new address; without it the responder discards packets from an unknown source. | DPD or keepalive timeouts, then a full rekey or a dead SA. |
| OpenVPN over UDP | --float accepts a packet from a new source mid-session; otherwise the session stays tied to the original peer address. | Idle until ping-restart fires, then a visible reconnect. |
| OpenVPN over TCP | The tunnel is a byte stream, so a changed source address breaks it outright. | Immediate reset and a new connection attempt. |
WireGuard의 로밍 규칙은 한 방향으로만 작동합니다. 클라이언트가 먼저 새 주소에서 보내야 합니다. 옛 인터페이스에 묶인 소켓은 그렇게 하지 않으므로, 터널은 살아 보이는데 핸드셰이크 타이머는 늙어 갑니다. 프로토콜 설명 엔드포인트 갱신 조건을 정확히 밝히고 있으며, 설정을 바꾸기 전에 읽어 볼 만합니다.
MOBIKE는 협상되는 것이지 가정되는 것이 아닙니다. 서버가 제공하지 않으면 클라이언트는 다시 세워야 하고, 이것은 SA 목록이나 로그에서 확인하는 사실이며 도는 표시에서 추론할 것이 아닙니다.
경로를 정하는 것은 라우트 우선순위이고 Wi-Fi 아이콘이 아닙니다
두 인터페이스가 모두 올라와 있으면 커널은 메트릭과 프리픽스 길이로 고릅니다. ip route show default 후보를 나열하고 ip route get 203.0.113.10 출발지 주소를 포함한 실제 결정을 풉니다. 메트릭 100의 유선 기본과 600의 무선 기본은 케이블이 자리 잡는 순간 엔드포인트가 움직인다는 뜻이고, 그 전에 소켓을 연 애플리케이션은 옛 출발지를 유지합니다.
Windows도 자동 인터페이스 메트릭으로 같은 일을 하며, 링크 속도에 치우칩니다. Get-NetRoute -DestinationPrefix 0.0.0.0/0 후보를 정렬하고 Find-NetRoute -RemoteIPAddress 203.0.113.10 스택이 고를 인터페이스와 출발지를 돌려줍니다. 바깥 소켓을 한 인터페이스에 묶은 클라이언트는 메트릭이 뒤집힌 뒤에도 그것을 계속 쓰지만, 이는 묶음의 결정이지 라우팅 결함이 아닙니다.
Android는 분리를 눈에 보이게 합니다. ConnectivityManager는 사용 가능한 네트워크와 별도의 기본을 보고하고, 소켓을 Network 객체에 묶는 VPN 앱은 다시 묶을 때까지 그 묶음을 유지합니다. macOS에서는 scutil --nwi 기본 인터페이스와 시스템이 쓸 순서를 출력합니다.
DNS, MTU, IPv6는 연결과 함께 움직인다
새 연결은 새 리졸버를 가져옵니다. systemd-resolved에서는 DNS가 링크별이고, resolvectl status 어느 링크가 이름에 답하는지 보여주며, 자체 리졸버를 나눠 주는 게스트 네트워크는 링크가 다시 선호될 때까지 터널이 밀어 넣은 DNS를 쓰지 않은 채로 둘 수 있습니다. 캡티브 포털은 이를 더 나쁘게 만듭니다. 첫 HTTPS 요청에는 엔드포인트 대신 포털이 답하고, 클라이언트는 죽은 서버를 기록합니다.
경로 MTU도 바뀝니다. Ethernet과 Wi-Fi는 보통 1500바이트를 나르고, PPPoE는 1492, 모바일 링크는 흔히 그보다 적습니다. 더 작은 MTU를 물려받은 터널은 큰 패킷에서 멈추고 작은 요청은 통과하는데, 이는 반쯤 망가진 연결로 읽힙니다. ping -M do -s 1472 203.0.113.10 DF를 세운 1500바이트 패킷을 보내므로, 침묵은 경로가 생각보다 작다는 뜻입니다.
IPv6는 나머지 절반입니다. 새 프리픽스를 주는 네트워크는 이중 스택 클라이언트가 쓸 출발지를 바꾸고, v4 전용 터널은 정책이 따라올 때까지 v6 트래픽을 밖에 둡니다. ip -6 route show default 그리고 ip -6 addr show 새 링크에 v6 경로가 있는지 답합니다.
설명하는 대신 전환을 재현하세요
무해한 요청 하나를 골라 변화의 양쪽에서 같은 세 명령을 실행합니다. ip -br addr, ip route show default, ip route get 203.0.113.10. 그다음 터널이 아직 패킷을 내보내는지 보세요. tcpdump -ni any udp port 51820 WireGuard라면 이것, 그 밖의 것은 해당 포트입니다. 옛 출발지에서 나가는 패킷은 묶음 문제를 뜻합니다. 새 출발지에서 나가는데 응답이 없는 패킷은 먼 쪽이나 중간의 NAT를 뜻합니다.
첫 장애와 동시에 일어난 사건을 적어 두세요: 링크 다운, 주소 변경, 기본 경로 변경입니다. 이들은 서로 다른 담당자를 가리킵니다. 다시 묶어야 하는 클라이언트, 다시 받아야 하는 주소, 또는 영구적 우회 규칙이 아니라 설정 파일에 속한 경로입니다.
고쳐졌다고 하기 전에 직접 트래픽 차단이 틈 동안에도 유지되는지, 이름이 새 연결로 해석되는지 확인하세요. 전환 뒤에도 클라이언트가 옛 엔드포인트를 쥐고 있다면 먼저 로밍이나 float 설정을 고칩니다. 올바르게 로밍하는데도 응답이 없다면 서버의 피어 식별 정보와 경로의 NAT를 살피고, 다음 사람이 비교할 수 있도록 두 네트워크 맥락을 모두 기록에 남기세요.