방화벽이 VPN을 막고 있는가? 단계별 점검
타임아웃은 범인을 지목하지 않는다. 리스너와 경로, 보안 로그를 순서대로 짚어 보고, 증거가 가리킬 때에만 규칙 하나를 바꾼다.
VPN 타임아웃 한 번은 쓸 만한 응답이 오지 않았다는 것만 증명하고, 이유에 대해서는 아무것도 증명하지 않는다. 프로필이 잘못된 포트를 적었을 수도, 서버가 내려가 있을 수도, 요청이 동작하는 반환 경로 없이 도착했을 수도 있다. 각각은 다른 흔적을 남기고, 그 흔적이 어느 규칙을 건드려야 하는지 알려 준다. 아래 네 단계를 순서대로 진행한다. 어느 하나가 증상을 설명하는 즉시 멈춘다.
1단계: 서버와 전송 방식을 확인한다
서버 이름과 전송 방식, 포트는 로컬 수정이 아니라 사업자의 현재 프로필에서 읽는다. 노트북에서 바꾼 포트가 공용 서버에 리스너를 만들 수는 없고, 그 불일치는 차단과 똑같은 타임아웃을 만든다. 프로필이 지원되는 대체 전송 방식을 제공한다면 해결책이 아니라 대비책으로 적어 둔다. 이름을 해석하고 그 답을 사업자가 공개한 주소와 비교한다.
오래된 DNS 레코드는 한 번도 응답하지 않은 호스트로 클라이언트를 보낸다. 이것도 필터를 흉내 내는 또 다른 결함이며, 배제하는 데 질의 하나면 충분하다.
두 값을 모두 티켓에 적는다. 이후의 모든 비교가 이 값을 쓰고, 이것이 없는 티켓은 조사를 처음부터 다시 시작하게 만든다.
2단계: 통제된 비교 한 번으로 경로를 증명한다
기기와 프로필을 그대로 두고 다른 신뢰할 수 있는 접속망에서 시도한다. 거기서 터널이 올라오면 차이는 원래 경로나 그 정책이다. 원래 망에서 두 번째 승인된 기기가 동작하면 차이는 첫 기기다. 이 두 비교 중 하나는 거의 항상 결정적이다.
먼저 정상적인 네트워크 로그인을 마친다. 캡티브 포털은 끝나기 전까지 차단처럼 보인다.
실제로 쓰는 포트를 시험하고, TCP 결과는 TCP에 대한 정보로만 취급한다.
Resolve-DnsName vpn.corp.example
tracert -h 8 -w 500 vpn.corp.example
Test-NetConnection vpn.corp.example -Port 443 -InformationLevel Detailed443 포트에서 TCP 핸드셰이크가 성공했다면 그곳에 리스너가 응답했다는 뜻이다. 51820 포트의 UDP 리스너에 대해서는 아무것도 말하지 않고, 협상이 끝났는지도 말하지 않는다.
3단계: 실패한 순간의 보안 이벤트를 읽는다
방화벽 이벤트는 이용할 수 있는 가장 강한 증거이며, 먼저 밝혀 둘 유의점이 있다. 많은 기본 프로필에서 로깅이 꺼져 있으므로, 빈 로그를 무죄의 증거로 읽기 전에 해당 프로필이 버림을 기록하는지 확인한다. 로깅이 켜져 있으면 이벤트는 규칙과 방향, 주소를 알려 주며 이는 규칙 변경에 꼭 필요한 정보다. 애플리케이션 규칙과 포트 규칙은 별개의 객체이고, 관리 정책이 로컬 설정을 덮어쓸 수 있다. 어떤 규칙이 실제로 어느 클라이언트와 어느 서비스를 포함하는지 확인한다.
프로필 상태와 최근 이벤트는 옆 호스트가 아니라 실패한 기기에서 모은다.
이벤트 시각을 자신의 시험 시각과 맞춰 본다. 규칙 이름이 같아도 시각이 다르면 우연이다.
Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, LogBlocked
Get-NetFirewallRule -Enabled True -Direction Outbound | Where-Object DisplayName -match 'VPN'
Get-WinEvent -LogName 'Microsoft-Windows-Windows Firewall With Advanced Security/Firewall' -MaxEvents 20직접 관리하는 서버에서는 요청이 리스너에 도달했는지부터 묻는다. 응답 없이 도착하는 패킷은 전달이나 반환 경로의 문제다. 전혀 나타나지 않는 요청은 필터링이나 주소 지정의 문제다.
4단계: 터널이 올라온 뒤 전달을 시험한다
방화벽은 세션을 허용하면서도 세션이 도달하려는 모든 것을 거부할 수 있다. 전달 sysctl과 NAT 규칙, 반환 경로는 모두 인증 뒤에 있고, VPN 포트에 대한 넓은 예외는 그중 어느 것도 고치지 않는다. 내부 목적지 하나와 인터넷 목적지 하나를 따로 시험한다. 보통 서로 다른 이유로 실패하기 때문이다. 내부 이름은 실패하는데 주소는 동작한다면, 어떤 규칙보다 먼저 밀어 넣은 DNS를 본다.
클라이언트가 연결되어 실패하는 요청을 시도하는 동안 서버에서 아래 세 가지 점검을 실행한다.
터널 인터페이스의 카운터가 핵심이다. 패킷이 들어왔는지, 무엇이 나갔는지를 보여 준다.
sysctl net.ipv4.ip_forward
nft list ruleset | grep -n -E 'forward|masquerade'
tcpdump -ni tun0 -c 10터널로 패킷이 들어오는데 목적지 쪽으로 아무것도 나가지 않으면 의심 대상은 전달이나 NAT다. 아무것도 들어오지 않으면 세션은 올라와 있지만 클라이언트가 보내지 않는 것이고, 볼 곳은 클라이언트의 라우팅 테이블이다.
수정을 확인하고 도움이 되지 않은 것을 걷어 낸다
승인된 수정 뒤에 실패했던 시험을 그대로 반복하고 같은 프로필과 기기에 대해 결과를 기록한다. 그다음 결과를 바꾸지 않은 임시 예외를 모두 걷어 낸다. 쓰이지 않는 예외는 쌓이고, 그 하나하나가 아무도 기억하지 못하는 결정이기 때문이다. 남는 것은 좁게 유지한다. 목적지 하나, 포트 하나, 방향 하나, 담당자 하나.
같은 명령 세 가지를 다시 실행하고 변경 전에 저장한 출력과 비교한다.
Test-NetConnection vpn.corp.example -Port 443 -InformationLevel Detailed
tracert -h 8 -w 500 vpn.corp.example
Get-NetFirewallRule -Enabled True | Where-Object DisplayName -match 'VPN' | Select-Object DisplayName, Action비교용 망이 동작하고 원래 망이 여전히 실패하며 이벤트가 비어 있다면, 남은 의심 대상은 호스트가 아니라 경로다. 두 비교 결과를 첨부해 네트워크 담당자에게 구체적인 주장으로 넘긴다. 비활성화된 방화벽 프로필보다 여기서 멈추는 편이 낫다.