재부팅은 사람들이 킬 스위치를 시험하는 가장 흔한 방법이며, 가장 자주 거짓말을 하는 시험이기도 합니다. 클라이언트의 체크박스는 선호일 뿐이고, 중요한 것은 네트워크 스택이 올라오는 순간과 터널이 실제로 수립되는 순간 사이에 무언가가 차단을 강제하는지 여부입니다. Windows에서는 보통 Windows Filtering Platform의 필터, Linux에서는 유닛이 불러오는 규칙 집합, macOS에서는 pf 앵커, Android에서는 시스템 자체의 상시 연결과 잠금 플래그가 그 역할을 합니다. 이런 구성은 재부팅을 거치며 매우 다르게 동작하고, 플랫폼 수준의 구성만이 누군가 로그인하기 전에 제자리에 있습니다.

재부팅은 세 가지 별개의 질문을 던진다

질문을 나눠 보세요. 첫째, 정책이 부팅 시 무언가가 읽는 형태로 디스크에 존재하는가? 둘째, 그 판독기가 트래픽이 나가기 전에 실행되는가? 셋째, 정책이 관심 있는 트래픽, 즉 모든 프로세스와 두 주소 체계, 그리고 DNS를 포괄하는가? 첫째에 예, 둘째에 아니오라면 사람들이 재부팅 후에도 살아남지 못하는 킬 스위치라고 보고하는 실패가 그대로 생기며, 부팅 직후 몇 초 동안 트래픽이 새어 나가고 누군가 살펴보기 전까지 아무도 알아채지 못합니다.

계층을 분리해 두세요. 저장된 방화벽 규칙 집합, 부팅 시 시작되는 서비스, 클라이언트 선호는 수명이 각각 다른 세 가지 대상입니다. 선호가 재부팅을 견디는 것은 설정 파일 안의 값이기 때문입니다. 패킷을 막는 것은 규칙뿐이며, 규칙은 그것을 붙잡고 있던 커널과 함께 사라집니다.

차단을 복원하는 대상을 찾는다

Linux에서는 netfilter 규칙이 커널 안에 있습니다. 직접 마련하지 않으면 부팅 시 아무것도 그것을 다시 쓰지 않지만, iptables-save 와 netfilter-persistent, nftables.service 를 불러오는 /etc/nftables.conf 혹은 직접 만든 스크립트를 실행하는 systemd 유닛을 쓰면 자동화할 수 있습니다. 기억나는 설정이 아니라 실제로 활성화된 것을 확인하세요.

systemctl is-enabled nftables netfilter-persistent 2>/dev/null
sudo nft list ruleset
sudo iptables -S OUTPUT

부팅 몇 초 뒤의 빈 규칙 집합이 제목의 질문에 대한 답입니다. Windows에서는 클라이언트 서비스에 어떻게 시작되는지 물은 다음, 터널이 내려가 있는 동안 플랫폼 필터 상태를 덤프하세요.

Get-Service | Where-Object { $_.Name -match 'vpn' } | Select-Object Name, Status, StartType
netsh wfp show state

두 번째 명령은 wfpstate.xml 를 현재 디렉터리에 씁니다. 클라이언트가 연결하기 전에 이미 존재하는 차단 동작의 필터를 찾으세요. Base Filtering Engine은 부팅 초기에 시작되어 영구 플래그로 추가된 필터를 복원하므로, 클라이언트 창이 생기기 전에 트래픽을 막는 킬 스위치도 있고 그렇지 않은 것도 있습니다. macOS에서는 sudo pfctl -s info 가 pf가 켜져 있는지 알려 주고, sudo pfctl -s rules 는 무엇이 적재되었는지 보여 주며, VPN 클라이언트는 보통 메인 규칙 집합이 아니라 앵커에 규칙을 붙입니다.utun3 를 이름으로 지정한 규칙은 다음 부팅 후 다른 인터페이스를 가리킬 수 있는데, 그 번호가 실행 중에 배정되기 때문입니다.

네트워크가 올라온 뒤와 터널이 올라온 뒤의 틈을 보라

위험한 구간은 재부팅 전체가 아니라 그 틈입니다. 인터페이스는 한 시점에 임대와 기본 경로를 받고, VPN 서비스는 다른 시점에 시작하며, 터널은 더 늦게 인증하는데, 사용자가 로그인하고 자격 증명 에이전트가 실행된 뒤에야 하는 경우도 있습니다. 차단이 마지막에 적용되면 그 틈에 있는 모든 것이 평문으로 나갑니다.

systemd 호스트에서는 추측하지 말고 순서를 읽으세요. VPN과 방화벽 유닛에서 실행하는 것은 systemctl cat 이고, After= 또는 Before= 가 network-pre.target 와 network-online.target 에 대해 어떻게 붙는지 보세요. 방화벽 유닛은 network-online.target 뒤에 정렬되면 인터페이스에 지고, network-pre.target 가 요구하고 그 앞에 정렬되면 이깁니다. Windows에서 같은 질문은 서비스의 시작 유형과 종속성인데, Manual로 설정된 서비스는 부팅 시 프로세스를 막을 수 없기 때문입니다. 요구 사항에 로그인 전 트래픽이 포함된다면 그것을 만족하는 것은 기기 수준의 구성뿐이며, Always On VPN 기기 터널이 컴퓨터 인증서로 인증해 사용자가 로그온하기 전에 연결하고, Microsoft는 기기 터널 구성을 문서화합니다 사용자 터널과는 별도로. Android는 다른 길을 가서, 상시 연결 VPN을 강제하고 그것이 없는 연결을 앱 프로세스가 아니라 시스템에서 차단합니다.

시험을 실행하고 두 타임라인을 비교한다

새어 나가도 손해가 없는 목적지로 재부팅하고 상태는 틈이 지난 뒤가 아니라 틈 동안 기록하세요. 가장 깔끔한 방법은 플랫폼이 허용하는 가장 이른 시점에 시작해 기본 경로와 방화벽 상태를 기록하고, 짧은 제한 시간으로 요청 하나를 시도하고, 로컬 파일에 한 줄을 덧붙이는 oneshot 유닛이나 예약 작업이라는 부팅 시점 프로브입니다. 그 기록을 journalctl -b -u 또는 시스템 로그에서 얻은 VPN 서비스 시작 시각과 비교하세요.

그다음 일반적인 시험으로, 터널을 올리고 연결을 끊고 직접 트래픽이 막히는지 보고 복구합니다. 두 번째는 통과하고 첫 번째에서 실패하는 것이 정상적인 결과이며, 강제가 클라이언트 측에 있고 부팅이 아니라 클라이언트가 연결할 때 적용된다는 뜻입니다. 제가 마지막으로 점검한 기기에서는 차단이 NetworkManager 디스패처 스크립트에서 왔고, 존재하고 올바르지만 인터페이스가 올라오기 전 몇 초 동안은 쓸모가 없었습니다. 재부팅을 견뎠다는 사실은 어느 계층이 어느 순간부터 견뎠는지 말할 때에야 의미가 있으므로, 두 결과를 모두 적어 두세요.

돌아갈 길을 끊지 않고 틈을 닫는다

부팅 시 차단이 없다면 두 번째 클라이언트 규칙을 더하는 대신 강제를 한 계층 아래로 내리세요. 규칙 집합을 저장하고 네트워크를 쓸 수 있기 전에 정렬된 유닛에서 불러오며, 그 유닛이 자기가 지켜야 할 DNS 조회나 네트워크 마운트를 필요로 하지 않는지 확인하세요. 범위는 시점만큼 중요해서, 사용자 ID나 cgroup에 맞는 규칙은 모든 시스템 데몬을 차단 밖에 두고, IPv4만 다루는 규칙 집합은 IPv6와 DNS를 그대로 열어 둡니다.

스스로에게 돌아갈 길을 남겨 두세요. 부팅 시 모든 것을 막은 뒤 인증하지 못하는 기기에는 네트워크가 아예 없고, 해결책은 차단을 지우는 것이 아니라 자격 증명이나 순서를 고치는 것입니다. 로컬 콘솔 절차를 문서화해 두고, 터널이 정말로 필요로 하는 것, 예컨대 서버 주소와 터널이 생기기 전에 쓰는 리졸버에는 좁고 의도적인 예외를 두세요.

이 구성을 믿기 전에 네 가지를 순서대로 확인하세요. 정책이 부팅이 읽는 곳에 저장되어 있다. 그 판독기가 인터페이스를 쓸 수 있기 전에 실행된다. 차단이 두 주소 체계와 DNS를 포괄한다. 차단이 활성인 상태에서도 VPN이 인증할 수 있다. 네 가지가 모두 성립하면 재부팅은 아무것도 바꾸지 않습니다.

관련 글