OpenVPN 원격 접속 VPN — 세우고, 길을 놓고, 잠그고, 고친다
VPN 장애를 층으로 자르기
한 줄 요약
VPN 장애 신고는 「안 붙는다」 와 「붙었는데 안 된다」 둘뿐입니다. 그 뒤를 층으로 자릅니다 — 패킷이 서버에 닿나 → TLS 가 끝나나 → 터널 안의 패킷이 게이트웨이를 지나나 → 답이 돌아오나 → 크기와 상관있나.
왜 이게 필요했나
VPN 은 여러 층이 겹친 물건이라, 어느 층이 깨져도 사용자에게는 똑같이 「VPN 이 안 돼요」 로 보입니다. 그런데 처음 떠오르는 조치는 대개 맨 위층의 것입니다 — 인증서를 다시 발급하고, 클라이언트를 다시 깔고, 서버를 재시작합니다. 아래층이 깨졌다면 이 조치는 시간만 씁니다. 층을 아래부터 하나씩 확인하는 습관이 장애 시간을 정합니다.
어떻게 동작하나
1층 — 서버까지 닿나. 클라이언트에 TLS key negotiation failed to occur within 60 seconds 가 찍히면 60초 동안 서버에서 아무 답도 없었다는 뜻입니다. 서버 기록에 그 클라이언트의 주소가 한 줄이라도 있는지 봅니다. 없으면 길(방화벽·보안 그룹·포트)입니다. 방화벽 규칙이 「있다」 와 「닿는다」 는 다릅니다 — nft 는 체인을 위에서부터 읽어 첫 판정에서 끝나므로, drop 뒤에 덧붙인 accept 는 영원히 닿지 않습니다. drop 규칙의 counter 가 늘고 있으면 거기서 막히는 것입니다.
2층 — TLS 가 끝나나. 서버 기록에 주소가 보이는데 연결이 안 되면 인증서입니다. OpenVPN 의 VERIFY 줄은 무엇을 기대했고 무엇을 받았는지 그대로 말합니다 — VERIFY X509NAME ERROR: CN=<받은 것>, must be <기대한 것>. 이때 고칠 곳은 틀린 쪽입니다. 서버 인증서를 갱신하며 이름을 바꿨다면 서버 인증서 한 장을 고치지, 직원 천 명의 이름 확인을 끄지 않습니다. 이름 확인을 끄면 같은 CA 의 다른 인증서로 서버 행세를 하는 문이 열립니다.
3층 — 게이트웨이를 지나나. 터널이 섰는데 아무것도 안 열리면 게이트웨이의 tun 과 사내망 NIC 양쪽에 tcpdump 를 겁니다. tun 에는 보이는데 사내망 NIC 에 안 보이면 포워딩(또는 포워딩 방화벽)입니다. sysctl 값은 /etc/sysctl.d 의 파일들이 이름순으로 적용되고 같은 키는 나중 값이 이기므로, 「켜는 파일이 있다」 로는 부족합니다. systemd-analyze cat-config sysctl.d 가 적용 순서대로 펼쳐 보여 줍니다. 보안 점검 스크립트가 남긴 99 번대 파일이 VPN 서버의 포워딩을 끄는 일은 실제로 흔합니다.
4층 — 답이 돌아오나. 사내 서버에 요청이 닿는데 노트북이 답을 못 받으면 돌아오는 경로입니다. 경로가 「있는데」 안 되면 그 경로가 가리키는 다음 홉을 봅니다 — ip neigh 에 그 주소가 FAILED 면 그런 장비가 그 망에 없습니다. 옛 VPN 장비 주소나 오타가 흔한 원인입니다.
5층 — 크기와 상관있나. 작은 요청은 되는데 큰 내려받기만 멈추면 MTU 입니다. 이 환경의 바깥 경로(세션망 eth1)는 MTU 1450 이고 tun 은 1500 입니다. 꽉 찬 TCP 패킷을 터널에 싸면 바깥 패킷이 1450 을 넘어 IP 조각으로 나뉘고, 그 조각을 중간의 망(집 공유기, 일부 방화벽·로드 밸런서)이 버리면 큰 응답만 사라집니다. 이 환경에서 노트북 쪽이 조각을 버리게 하자 사내 위키의 /whoami 는 바로 오고 4MiB 짜리 /big 은 15초 동안 0바이트였고, 서버 설정에 mssfix 1450 mtu 한 줄을 더하자 같은 4MiB 가 0.07초에 왔습니다. mssfix 는 터널 안을 지나는 TCP 연결의 MSS 를 깎아 애초에 조각이 생기지 않게 합니다(TCP 에만 듣습니다).
층마다 손에 쥘 도구. 1층은 서버의 ss -lun·journalctl -u openvpn-server@… 와 방화벽 nft list chain …(counter), 2층은 양쪽 기록의 VERIFY 줄과 openssl x509 -noout -subject -ext extendedKeyUsage, 3층은 게이트웨이 tun·사내망 NIC 양쪽의 tcpdump -ni <장치> 와 sysctl net.ipv4.ip_forward, 4층은 사내 서버의 ip route get <VPN 주소>·ip neigh·tcpdump -ni any, 5층은 크기를 바꿔 가며 받는 curl 과 조각만 거르는 tcpdump 'ip[6:2] & 0x3fff != 0' 입니다. 증거를 하나 모을 때마다 가설을 하나씩 지우세요.
고칠 자리. 다섯 층 모두 고치는 쪽은 「우리가 책임지는 자리」 입니다. 집 공유기와 직원의 설정은 우리가 고를 수 없는 조건이고, 서버·게이트웨이·사내 경로는 우리 것입니다.
현장에서 만나는 모습
대부분의 VPN 장애 회고는 「바꾼 것이 하나 있었다」 로 시작합니다 — 인증서 갱신, 보안 점검 스크립트, 방화벽 정리, 장비 교체. 그래서 장애를 받으면 첫 질문으로 「어제와 오늘 사이에 무엇이 바뀌었나」 를 묻고, 그다음 층을 아래부터 확인합니다. 장애 보고서에 증상·원인·조치를 따로 적어 두면 같은 장애가 다시 났을 때 30분이 3분이 됩니다.
다음 실습에서 할 것
어제까지 되던 VPN 에 겹쳐 놓은 고장 다섯 개를 증상에서 원인으로 하나씩 찾아 고치고, 다섯 줄 보고서를 씁니다.