OpenVPN 원격 접속 VPN — 세우고, 길을 놓고, 잠그고, 고친다
라우팅이냐 NAT 냐, 분할이냐 전체냐
목표
1모듈의 터널(인증서·서버·노트북 연결)이 이미 선 상태에서 시작합니다. 사내 서버로 가는 길을 NAT 와 라우팅 두 방법으로 놓아 차이를 보고, 분할 터널과 전체 터널을 오가며 무엇이 터널로 가고 무엇이 밖으로 가는지를 경로 표로 확인합니다.
왜 중요한가
VPN 설계 회의의 질문 둘이 여기서 나옵니다. 「사내 서버의 기록에 직원이 보여야 하나(라우팅) 아니면 설치가 쉬운 쪽(NAT)인가」, 「직원의 인터넷 트래픽까지 회사가 보고 막아야 하나(전체 터널) 아니면 회사 회선을 아낄 것인가(분할 터널)」. 둘 다 정답이 없고 무엇을 사고 무엇을 내주는지의 문제입니다. AWS Client VPN 의 「분할 터널 켜기」 칸과 경로 표가 바로 이 선택입니다.
단계
- gateway 의 IP 포워딩을 켜고
/etc/sysctl.d/아래 파일로 영구히 남기세요. 그다음 intranet 에서tcpdump -lni any -c 6 'tcp port 80 and net 10.8.0.0/24'를 걸어 둔 채 laptop 에서curl -m 4 http://10.10.0.10/을 한 번 하고, 잡힌 줄을/root/vpn/route/asym.txt에 저장하세요. 요청은corp0 In, 답은enp1s0 Out으로 찍혀야 합니다. - gateway 에 nft 로 사내망 쪽 마스커레이드(
oifname "corp0" ip saddr 10.8.0.0/24 masquerade, 표 이름ip vpn_nat)를 걸고 laptop 에서curl http://10.10.0.10/whoami의 출력을/root/vpn/route/nat.txt에 저장하세요. 사내 서버가 본 출발지는10.10.0.1이어야 합니다. - gateway 의 사내망 쪽 마스커레이드를 걷고, intranet 의
/etc/systemd/network/60-corp0.network에[Route]Destination=10.8.0.0/24Gateway=10.10.0.1을 더해networkctl reload하세요. laptop 에서 다시/whoami를 받아/root/vpn/route/routed.txt에 저장합니다. 이번에는 laptop 의 tun0 주소가 나와야 합니다. - laptop 에서
ip -o route get 10.10.0.10와ip -o route get 1.1.1.1이 고른 장치를/root/vpn/route/split.txt에<목적지> <장치>두 줄로 적으세요. 사내 서버는 tun 으로, 1.1.1.1 은 tun 이 아닌 장치로 나가야 합니다. - 서버 설정에
push "redirect-gateway def1"을 더하고, gateway 에 인터넷 쪽 마스커레이드(oifname "enp1s0" ip saddr 10.8.0.0/24 counter masquerade, 표ip vpn_nat, 원본/etc/vpn-nat.nft)를 걸고 서버를 다시 켜세요. laptop 의ip -o route get 1.1.1.1이 tun 을 고르고curl http://example.com/이 응답하면/root/vpn/route/full.txt에1.1.1.1 <장치>,example.com <코드>두 줄을 적습니다. - 모두에게 밀던
redirect-gateway줄을 서버 설정에서 걷고,client-config-dir ccd를 더한 뒤/etc/openvpn/server/ccd/alice에push "redirect-gateway def1"을 적으세요. 서버를 다시 켠 뒤에도 alice(laptop)는 전체 터널이어야 합니다. - laptop 의
/etc/openvpn/client/alice.conf에route 192.168.0.0 255.255.0.0 net_gateway를 더하고 클라이언트를 다시 켜세요. laptop 에서ip -o route get 192.168.1.10은 tun 이 아닌 장치를,ip -o route get 1.1.1.1은 여전히 tun 을 골라야 합니다.
참고
- 이 터미널은 gateway 입니다.
ssh laptop·ssh intranet. 조리법이 CA·서버·alice 인증서와 연결까지 세워 두었습니다(/root/ca,/etc/openvpn/server, laptop 의/etc/openvpn/client). - 서버를 다시 켜면 클라이언트는
explicit-exit-notify덕에 몇 초 안에 다시 붙습니다. 안 붙으면ssh laptop journalctl -u openvpn-client@alice -n 30. - 노트북의
10.0.0.0/8 via … dev enp1s0은 플랫폼이 세션망을 지키려고 둔 경로입니다. 지우지 마세요.
포워딩만 켜면 — 들어온 NIC 와 나가는 NIC 가 다르다
gateway 의 IP 포워딩을 켜고 /etc/sysctl.d/ 아래 파일로 영구히 남기세요. 그다음 intranet 에서 tcpdump -lni any -c 6 'tcp port 80 and net 10.8.0.0/24' 를 걸어 둔 채 laptop 에서 curl -m 4 http://10.10.0.10/ 을 한 번 하고, 잡힌 줄을 /root/vpn/route/asym.txt 에 저장하세요. 요청은 corp0 In, 답은 enp1s0 Out 으로 찍혀야 합니다.
tcpdump -i any 는 줄마다 인터페이스와 방향(In/Out)을 적어 줍니다. 사내 서버는 10.8.0.x 로 가는 경로가 없어 기본 경로(enp1s0)로 답을 보냅니다 — 그 길 끝에는 노트북이 없습니다. 원격 셸에서 tcpdump 를 뒤에 걸어 두려면 ssh intranet 'nohup timeout 10 tcpdump ... < /dev/null > /tmp/x 2>/dev/null &' 처럼 출력을 파일로 돌립니다.
첫 번째 해법 — 게이트웨이가 NAT 한다
gateway 에 nft 로 사내망 쪽 마스커레이드(oifname "corp0" ip saddr 10.8.0.0/24 masquerade, 표 이름 ip vpn_nat)를 걸고 laptop 에서 curl http://10.10.0.10/whoami 의 출력을 /root/vpn/route/nat.txt 에 저장하세요. 사내 서버가 본 출발지는 10.10.0.1 이어야 합니다.
masquerade 는 나가는 NIC 의 주소로 출발지를 바꿉니다. 사내 서버는 답을 10.10.0.1(gateway)로 보내고, gateway 의 연결 추적이 그것을 노트북으로 되돌립니다. 돌아오는 경로가 필요 없어 설치가 쉽지만, 사내 서버의 기록에는 모든 직원이 한 주소로 남습니다. 표는 nft -f <파일> 로 넣으면 다시 넣어도 겹치지 않게 쓸 수 있습니다.
두 번째 해법 — NAT 를 걷고 돌아오는 경로를 놓는다
gateway 의 사내망 쪽 마스커레이드를 걷고, intranet 의 /etc/systemd/network/60-corp0.network 에 [Route] Destination=10.8.0.0/24 Gateway=10.10.0.1 을 더해 networkctl reload 하세요. laptop 에서 다시 /whoami 를 받아 /root/vpn/route/routed.txt 에 저장합니다. 이번에는 laptop 의 tun0 주소가 나와야 합니다.
실무에서는 사내 서버 하나하나가 아니라 사내 라우터(기본 게이트웨이)에 「10.8.0.0/24 는 VPN 게이트웨이로」 를 한 줄 넣습니다. 여기서는 사내 서버가 곧 그 라우터 역할입니다. networkctl reload 뒤에도 경로가 안 보이면 networkctl reconfigure corp0.
분할 터널 — 사내만 터널로, 나머지는 집 회선으로
laptop 에서 ip -o route get 10.10.0.10 와 ip -o route get 1.1.1.1 이 고른 장치를 /root/vpn/route/split.txt 에 <목적지> <장치> 두 줄로 적으세요. 사내 서버는 tun 으로, 1.1.1.1 은 tun 이 아닌 장치로 나가야 합니다.
지금 서버는 사내망 경로 하나만 밀어 줍니다. 그래서 인터넷 트래픽은 노트북의 원래 기본 경로로 나갑니다 — 회사 회선을 아끼고 빠르지만, 회사는 그 트래픽을 보지 못하고 막지도 못합니다.
전체 터널 — 기본 경로를 터널로, 게이트웨이는 인터넷 쪽으로 NAT
서버 설정에 push "redirect-gateway def1" 을 더하고, gateway 에 인터넷 쪽 마스커레이드(oifname "enp1s0" ip saddr 10.8.0.0/24 counter masquerade, 표 ip vpn_nat, 원본 /etc/vpn-nat.nft)를 걸고 서버를 다시 켜세요. laptop 의 ip -o route get 1.1.1.1 이 tun 을 고르고 curl http://example.com/ 이 응답하면 /root/vpn/route/full.txt 에 1.1.1.1 <장치>, example.com <코드> 두 줄을 적습니다.
def1 은 기본 경로를 지우지 않고 0.0.0.0/1 과 128.0.0.0/1 두 경로를 더합니다 — 둘 다 /0 보다 길어서 이기고, VPN 이 끊기면 원래 기본 경로가 그대로 남아 있습니다. 노트북의 인터넷 트래픽이 게이트웨이로 오므로, 게이트웨이가 그것을 자기 주소로 바꿔 내보내야(NAT) 답이 돌아옵니다. 이 환경에는 플랫폼이 세션망을 지키려고 깔아 둔 10.0.0.0/8 via ... dev enp1s0 경로가 있습니다 — 지우면 노트북이 통째로 끊깁니다.
전체 터널은 한 사람만 — client-config-dir
모두에게 밀던 redirect-gateway 줄을 서버 설정에서 걷고, client-config-dir ccd 를 더한 뒤 /etc/openvpn/server/ccd/alice 에 push "redirect-gateway def1" 을 적으세요. 서버를 다시 켠 뒤에도 alice(laptop)는 전체 터널이어야 합니다.
ccd 파일 이름은 클라이언트 인증서의 CN 입니다. 거기 적은 push 는 그 사람에게만 갑니다 — 관리자·외주 인력만 전체 터널로 두는 식의 정책을 여기서 겁니다. 서버는 권한을 낮춘 뒤에도(3모듈) 이 디렉터리를 연결마다 읽으므로 다른 사람도 읽을 수 있는 권한(644)으로 둡니다.
전체 터널에서도 집 공유기는 터널 밖으로 — net_gateway
laptop 의 /etc/openvpn/client/alice.conf 에 route 192.168.0.0 255.255.0.0 net_gateway 를 더하고 클라이언트를 다시 켜세요. laptop 에서 ip -o route get 192.168.1.10 은 tun 이 아닌 장치를, ip -o route get 1.1.1.1 은 여전히 tun 을 골라야 합니다.
net_gateway 는 「VPN 이 붙기 전의 기본 게이트웨이」 를 가리키는 OpenVPN 의 이름입니다. 전체 터널을 켜면 집의 프린터·NAS(보통 192.168.x)까지 터널로 가 버려 안 보이게 되는데, 이 한 줄로 그 대역만 원래 길로 뺍니다. 서버가 밀어 주는 것이 아니라 노트북 쪽 설정이라는 점에 주의하세요.