OpenVPN 원격 접속 VPN — 세우고, 길을 놓고, 잠그고, 고친다
고장 난 VPN — 증상에서 원인으로 다섯 번
목표
「어제까지 되던」 VPN 이 오늘 아침 안 됩니다. 고장은 다섯 군데에 겹쳐 있고, 하나를 고쳐야 다음 증상이 보입니다. 증상 → 가설 → 확인 → 조치를 다섯 번 돌고 보고서를 씁니다.
왜 중요한가
VPN 장애는 「안 붙는다」 와 「붙었는데 안 된다」 두 가지로만 신고됩니다. 그 둘 뒤에 방화벽·인증서·포워딩·경로·MTU 가 숨어 있고, 층을 하나씩 내려가며 확인하지 않으면 엉뚱한 곳(인증서 다시 발급, 서버 재설치)에서 시간을 씁니다. 그리고 고치는 쪽은 언제나 우리가 책임지는 자리여야 합니다 — 클라이언트의 서버 확인을 끄거나 집 공유기를 탓하는 것은 고친 것이 아닙니다.
단계
- laptop 의 클라이언트 기록(
journalctl -u openvpn-client@alice)의 마지막 40줄을/root/vpn/diag/client.log(gateway)에 저장하세요.TLS key negotiation failed줄이 있어야 합니다(클라이언트가 켜진 뒤 60초가 지나야 찍힙니다). - 원인을 찾아 고치세요. 고친 뒤에는 서버 기록에 laptop(172.30.1.4)의 접속 시도가 찍혀야 합니다. 바깥 방화벽의 원본은
/etc/corp-edge.nft입니다. - 원인을 찾아 고치세요. laptop 의
alice.conf는 바꾸지 않습니다(verify-x509-name vpn.corp.example name그대로). 고친 뒤 laptop 의 tun0 에 10.8.0.x 가 붙고 10.8.0.1 이 응답해야 합니다. - 원인을 찾아 고치세요. 지금 값과 재부팅 뒤의 값 모두
net.ipv4.ip_forward = 1이어야 합니다. 다른 강화 항목은 남겨 두세요. - 원인을 찾아 고치세요. laptop 에서
http://10.10.0.10/whoami가 laptop 의 VPN 주소를 돌려줘야 하고, 고친 것이 재부팅 뒤에도 남아야 합니다(NAT 로 덮지 말 것). - laptop 에서
curl -s -o /dev/null -m 20 -w '%{size_download}' http://10.10.0.10/big이 4194304 바이트를 다 받게 고치세요. laptop 의isp_cpe표(집 공유기 흉내)는 회사가 바꿀 수 없는 바깥 망이므로 지우지 않습니다 — VPN 설정 쪽에서 풀어야 합니다. /root/vpn/diag/report.txt에 고친 순서대로 다섯 줄을<번호>. <증상> → <원인> → <조치>로 적으세요. 각 줄에는 그 고장의 핵심 낱말(1: 1194 또는 방화벽, 2: CN 또는 verify-x509-name, 3: ip_forward, 4: 경로 또는 Gateway, 5: MTU 또는 mssfix)이 들어 있어야 합니다.
참고
- 이 터미널은 gateway 입니다.
ssh laptop·ssh intranet. CA 는/root/ca(EASYRSA_BATCH=1), 서버 설정은/etc/openvpn/server/corp.conf. - 기록: 서버
journalctl -u openvpn-server@corp, 클라이언트ssh laptop journalctl -u openvpn-client@alice, 사내 위키ssh intranet journalctl -u intranet-web. - laptop 의
isp_cpe표와10.0.0.0/8경로, 각 VM 의labhub-platform-routes는 실습 고정 조건입니다. 지우지 마세요.
증상부터 — 노트북의 기록을 모은다
laptop 의 클라이언트 기록(journalctl -u openvpn-client@alice)의 마지막 40줄을 /root/vpn/diag/client.log(gateway)에 저장하세요. TLS key negotiation failed 줄이 있어야 합니다(클라이언트가 켜진 뒤 60초가 지나야 찍힙니다).
「TLS key negotiation failed to occur within 60 seconds」 는 60초 동안 서버에서 아무 답도 못 받았다는 뜻입니다 — 인증서를 따지기 전 단계입니다. 다음 질문은 「서버까지 패킷이 가기는 하나」 입니다. 서버 기록에 laptop(172.30.1.4)이 한 줄이라도 있는지 보세요.
고장 1 — 서버에 패킷이 닿지 않는다
원인을 찾아 고치세요. 고친 뒤에는 서버 기록에 laptop(172.30.1.4)의 접속 시도가 찍혀야 합니다. 바깥 방화벽의 원본은 /etc/corp-edge.nft 입니다.
서버는 1194 에서 듣고 있고(ss -lun), 방화벽 파일에도 1194 허용이 「있습니다」. 그런데 nft 는 체인을 위에서부터 읽어 첫 일치에서 끝납니다. nft list chain inet corp_edge edge_in 의 순서와 drop 의 counter 가 늘어나는지를 보세요. 「규칙이 있다」 와 「규칙에 닿는다」 는 다른 사실입니다. 고친 뒤에도 한동안 아무 일이 없으면 클라이언트의 재시도 간격 때문입니다 — 실패가 쌓이면 간격이 최대 5분까지 늘어나므로 laptop 의 클라이언트를 다시 켜서 확인하세요.
고장 2 — TLS 는 되는데 노트북이 서버를 거절한다
원인을 찾아 고치세요. laptop 의 alice.conf 는 바꾸지 않습니다(verify-x509-name vpn.corp.example name 그대로). 고친 뒤 laptop 의 tun0 에 10.8.0.x 가 붙고 10.8.0.1 이 응답해야 합니다.
클라이언트 기록의 VERIFY X509NAME ERROR 가 무엇을 기대했고 무엇을 받았는지 그대로 말해 줍니다. 직원 천 명의 설정 파일을 고칠 것인가, 서버 인증서 한 장을 고칠 것인가 — 클라이언트의 이름 확인을 끄는 것은 중간자 공격의 문을 여는 일이라 답이 아닙니다. openssl x509 -in /etc/openvpn/server/server.crt -noout -subject.
고장 3 — 터널은 붙었는데 사내 쪽으로 아무것도 안 간다
원인을 찾아 고치세요. 지금 값과 재부팅 뒤의 값 모두 net.ipv4.ip_forward = 1 이어야 합니다. 다른 강화 항목은 남겨 두세요.
gateway 의 tcpdump -ni corp0 에 아무것도 안 보이면 패킷이 게이트웨이에서 멈춘 것입니다. 포워딩을 켜는 파일은 있는데 값은 0 입니다 — sysctl.d 의 파일은 이름순으로 적용되어 뒤의 것이 이깁니다. systemd-analyze cat-config sysctl.d | grep ip_forward 가 적용 순서대로 보여 줍니다.
고장 4 — 요청은 닿는데 답이 안 온다
원인을 찾아 고치세요. laptop 에서 http://10.10.0.10/whoami 가 laptop 의 VPN 주소를 돌려줘야 하고, 고친 것이 재부팅 뒤에도 남아야 합니다(NAT 로 덮지 말 것).
intranet 에서 tcpdump -ni any port 80 과 ip route get 10.8.0.2 를 보세요. 경로는 「있습니다」 — 문제는 그 경로가 어디를 가리키느냐입니다. ip neigh 에 그 주소가 FAILED 로 남아 있다면 그런 장비가 사내망에 없다는 뜻입니다.
고장 5 — 작은 것은 되는데 큰 것만 멈춘다
laptop 에서 curl -s -o /dev/null -m 20 -w '%{size_download}' http://10.10.0.10/big 이 4194304 바이트를 다 받게 고치세요. laptop 의 isp_cpe 표(집 공유기 흉내)는 회사가 바꿀 수 없는 바깥 망이므로 지우지 않습니다 — VPN 설정 쪽에서 풀어야 합니다.
/whoami 는 되고 /big 만 멈추면 크기 문제입니다. 바깥 경로(eth1)의 MTU 는 1450 인데 tun 은 1500 이라, 꽉 찬 TCP 패킷을 싸면 바깥 패킷이 1450 을 넘어 IP 조각으로 나뉩니다. 그 조각을 바깥 망이 버리면 큰 응답만 사라집니다(gateway 에서 tcpdump -ni eth1 'ip[6:2] & 0x3fff != 0'). TCP 의 MSS 를 깎아 애초에 조각이 생기지 않게 하는 OpenVPN 옵션을 찾아보세요 — 값은 바깥 경로 MTU 에 맞춥니다.
장애 보고서 — 다섯 줄
/root/vpn/diag/report.txt 에 고친 순서대로 다섯 줄을 <번호>. <증상> → <원인> → <조치> 로 적으세요. 각 줄에는 그 고장의 핵심 낱말(1: 1194 또는 방화벽, 2: CN 또는 verify-x509-name, 3: ip_forward, 4: 경로 또는 Gateway, 5: MTU 또는 mssfix)이 들어 있어야 합니다.
같은 장애가 다시 나면 이 다섯 줄이 30분을 3분으로 줄입니다. 증상(무엇이 보였나)과 원인(왜)과 조치(무엇을 바꿨나)를 섞지 말고 따로 적으세요.