VPN 연결이 끊긴 뒤에도 킬 스위치가 트래픽을 계속 차단한다
킬 스위치 필터와 drop 규칙은 클라이언트보다 오래 남습니다. Windows WFP 상태와 Linux iptables 규칙을 읽고, 가장 좁은 객체를 삭제한 다음, 그것을 되살리는 주인을 찾으세요.
터널은 사라졌고 네트워크 아이콘은 정상으로 보이는데 아무것도 로드되지 않는다. VPN을 끊었거나, 제거했거나, 재부팅했는데, 연결이 끊기는 동안 당신을 보호해야 했던 차단이 여전히 서 있다. 클라이언트 창은 설명하지 못한다. 차단하는 것이 클라이언트가 아니기 때문이다. 결정은 당신의 이름으로 커널에 기록되었고, 그것을 제거할 무엇도 남지 않았다. Windows에서는 그 상태가 Windows Filtering Platform에 있고, Linux에서는 iptables나 nftables의 규칙 집합이며, 흔히 부팅 시 다시 적용되는 스냅샷을 동반한다. 다음은 내가 쓰는 순서다. 상태를 읽고, 실패를 설명하는 가장 좁은 객체를 삭제한 다음, 계속 그것을 되돌려 놓는 것을 찾는다.
킬 스위치는 설정이 아니라 커널 상태다
데스크톱 클라이언트는 터널 밖의 트래픽을 거부하는 필터를 추가해 차단을 구현한다. Windows에서는 connect-redirect 및 transport 계층의 WFP 필터이고, 일부는 영구적이다. Base Filtering Engine 정책 저장소에 기록되어 VPN 소프트웨어가 실행되기 전에 머신 부팅 시 복원된다. 클라이언트마다 정리 시점이 다르다. 어떤 것은 연결 해제 시 필터를 제거하고, 어떤 것은 정상 종료 시에만, 또 어떤 것은 킬 스위치를 먼저 끌 때만 제거한다. 차단이 활성인 상태에서 제거하거나, 프로세스를 죽이면 필터는 남는다.
Linux의 대응물은 출력 경로의 drop 또는 reject 규칙, 때로는 포워딩 규칙, 때로는 변경된 체인 정책이다. 그 규칙들은 커널 상태이기 때문에 추가한 프로세스보다 오래 산다. 클라이언트를 죽이거나, 크래시시키거나, 전원을 끊어도 커널은 계속 패킷을 버리며 되돌릴 것은 남지 않는다. 영속성 패키지는 현재 규칙 집합을 스냅샷해 부팅 시 복원함으로써 두 번째 영속 계층을 더한다. 그래서 다음 시작은 차단이 이미 설치된 상태로 시작된다.
무엇이든 삭제하기 전에 WFP 상태를 읽어라
Windows에는 필요한 도구가 들어 있다. 관리자 권한 프롬프트를 실행해 플랫폼 상태를 덤프하라. 덤프는 작업 디렉터리에 wfpstate.xml 로 저장된다.
netsh wfp show state
netsh wfp show filters
Get-Service bfe
XML에서 떠난 공급업체 이름, Block 작업, 계층을 검색하라. 일반 트래픽을 깨뜨리는 것은 connect-redirect와 transport 필터다. receive-accept 계층의 필터는 보통 원인이 아니다. Base Filtering Engine이 전혀 실행되고 있지 않다면 다른 곳을 봐라. 그 필터를 강제할 다른 것은 없기 때문이다.
일반 방화벽 보기도 교차 확인하라. 대부분은 둘 중 하나만 살피기 때문이다:
netsh advfirewall show allprofiles
Get-NetFirewallProfile | Select-Object Name,Enabled,DefaultInboundAction
내장 프로필이 켜져 있고 실패하는 트래픽에 맞는 규칙이 없다면, 차단은 Windows Firewall이 아니라 타사 공급자에서 온다. 그 구분이 복구에 어떤 도구를 쓸지 결정한다.
삭제에 쓸 구문으로 Linux 규칙을 읽어라
iptables -S 는 규칙을 추가할 때와 같은 형태로 출력하므로 그 출력을 삭제에 바로 재사용할 수 있다. iptables -L -v -n 는 패킷 카운터를 추가하는데, 그 카운터는 규칙이 실제로 실패한 요청과 일치하는지 아니면 체인에 그냥 앉아 있는지를 알려준다.
sudo iptables -S
sudo ip6tables -S
sudo iptables -t nat -S
규칙만이 아니라 체인 정책도 읽어라. -P OUTPUT DROP 는 규칙이 일치하지 않아도 트래픽을 차단한다. IPv6는 따로 점검하라. 두 주소 체계를 모두 설치하는 클라이언트는 IPv4 규칙이 사라진 뒤에도 IPv6 차단을 남길 수 있고, 증상은 애플리케이션이 어느 체계를 선호하는지에 달린다. nftables를 쓰는 곳에서는 nft list ruleset 도 실행하라. 두 도구는 호환 계층을 통해 공존하며, 하나의 목록이 패킷을 버릴 수 있는 모든 규칙을 보여준다고 보장할 수 없다.
실패를 설명하는 가장 좁은 객체를 삭제하라
Windows에서 첫 단계는 여전히 공급업체 자체의 제거 경로다. 설치 프로그램을 다시 실행해 repair 또는 uninstall을 쓰거나, 공급업체가 배포하면 정리 도구를 실행하라. 남은 서비스와 예약 작업은 흔하며, 로그온 시 클라이언트를 시작하는 작업은 다음 부팅에서 필터를 다시 설치한다. 클라이언트의 레지스트리 키를 읽다 실패하는 제거는 보통 서비스나 작업이 아직 그것을 붙들고 있다는 뜻이지 레지스트리가 손상되었다는 뜻이 아니다.
Get-ScheduledTask | Where-Object TaskName -like '*vpn*'
Get-Service | Where-Object DisplayName -like '*vpn*'
영구 필터는 최후의 수단이다. 그것은 HKLM\SYSTEM\CurrentControlSet\Services\BFE\Parameters\Policy\Persistent\Filter 아래에 있고, 필터마다 GUID로 키가 지정된 값 하나씩이다. 먼저 키를 내보내고, 제거할 GUID를 기록하고, 떠난 클라이언트에 속한 값만 삭제한 다음 재부팅해 엔진이 상태를 다시 만들게 하라. 키 전체를 삭제하지 말고 Base Filtering Engine을 비활성화하지도 마라. Windows Firewall과 Defender가 그것에 의존하며, 하나의 장애를 더 나쁜 장애와 바꾸게 된다.
reg export "HKLM\SYSTEM\CurrentControlSet\Services\BFE\Parameters\Policy\Persistent" C:\temp\bfe-backup.reg
Linux에서는 iptables -S 가 출력한 줄을 가져와 -A 를 -D 로 바꿔라. 식별한 규칙 하나를 삭제하는 것이 체인을 비우는 것보다 낫다. 자신의 정책이 그대로 남기 때문이다.
sudo iptables -D OUTPUT -p udp -j REJECT
drop이 사용자 정의 체인에 있다면 먼저 그 체인으로의 점프를 삭제하고 나중에 -X 로 체인을 제거하라. drop 규칙이 남아 있는데 체인 정책을 ACCEPT로 설정하는 것은 정책 결정에 도달하는 패킷에만 도움이 된다. 모든 테이블을 비우는 것은 최후의 수단이다. 다른 이유로 추가한 규칙도 제거되고, ufw가 켜져 있으면 서비스가 더 이상 존재하지 않는 체인을 소유한다고 믿게 만든다.
그것을 되돌려 놓는 주인을 찾아라
즉각적인 복구 후에 상태를 복원할 것을 찾아라. Linux에서는 영속성 유닛이 활성인지, 클라이언트에 로그인 시 방화벽 복원 설정이 있는지, /etc 아래에 저장된 규칙 파일이 있는지 확인하라. Windows에서는 시작 항목, 서비스, 예약 작업을 다시 확인한 다음 재부팅하고 이전과 같은 명령으로 상태를 다시 읽어라.
차단이 돌아온다면 삭제가 해결책이 아니었다. 주인이 해결책이다. 어느 클라이언트나 서비스가 설치하는지 기록하고 거기서 기능을 비활성화하라. 연결이 끊길 때마다 방화벽 계층에서 싸우지 말고.
핑 하나가 아니라 실제 트래픽으로 검증하라
이름 조회, TCP 연결, 새 브라우저 세션을 시험한 다음 재부팅하고 같은 세 가지 점검을 반복하라. HTTPS가 실패하는데 핑이 통하면 네트워크가 아니라 transport 계층 필터를 가리키고, 재부팅 후에만 다시 나타나는 차단은 아직 찾지 못한 주인을 가리킨다.
증거를 남겨라. 내보낸 BFE 키 또는 변경 전에 캡처한 iptables -S 출력이다. 고쳤다고 하기 전에 객체를 제거한 계층, 다시 설치할 수 있는 주인, 한 번 깨끗하게 재부팅한 뒤의 상태, VPN 프로세스가 없는 상태에서 일반 브라우징이 되는지를 확인하라. iptables(8) 매뉴얼 페이지에는 정리를 스크립트로 만들 때 필요한 정확한 삭제 및 정책 구문이 있다.