VPN 클라이언트의 서비스에 도달하기: 역방향 터널인가 DNAT인가
포트 포워딩 없이 OpenVPN 클라이언트의 서비스에 도달하는 방법: 역방향 SSH 터널과 서버 측 DNAT, 그리고 선택을 결정하는 세 가지 조건을 비교합니다.
통신사 NAT 뒤의 노트북도 VPN 서버가 만남의 지점이 되면 동료에게 서비스를 제공할 수 있습니다. 여기에는 두 가지 방식이 있는데, 클라이언트가 바깥으로 연결해 서버에 대기 포트를 유지해 달라고 요청하거나, 서버가 포트를 공개해 터널 안으로 변환하는 것입니다. 둘 다 같은 도달성 문제를 해결하지만 장애, 감독, 로깅에서는 다르게 동작합니다. 세 가지 조건이 어느 쪽이 여러분의 구성에 맞는지 결정합니다.
두 가지 형태, 하나의 만남의 지점
첫 번째 형태에서 클라이언트는 바깥으로 SSH 세션을 열고 서버에 선택한 포트에서 대기해 달라고 요청하며, 각 연결을 그 세션을 통해 되돌려 보냅니다. 서버에서는 아무것도 전달되지 않고 패킷 변환도 일어나지 않으므로 유일한 요구 사항은 SSH 계정, 허용된 포워딩, 포트에 대한 방화벽 규칙입니다. 서비스는 클라이언트의 루프백에 묶인 채로 남아 있으며, 보통 이것이 원하는 상태입니다.
ssh -N -R 8081:127.0.0.1:8080 -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 [email protected]
두 번째 형태에서는 서버가 공개 포트를 소유하고 각 연결을 클라이언트 터널 주소 쪽으로 다시 씁니다. 이를 위해서는 IP 포워딩이 켜져 있어야 하고, 들어올 때 목적지 변환과 나갈 때 출발지 변환이 필요하며, SSH 세션이 없을 때도 계속 동작합니다. 포트는 세션이 아니라 서버에 속하며, 이 속성이 대부분의 실제 사례를 결정합니다.
어느 형태도 구조적으로 더 안전하지는 않습니다. 둘 다 서버의 공개 주소에 도달할 수 있는 누구에게나 서비스 포트 하나를 노출하며, 둘 다 여전히 서비스 자체의 인증에 의존합니다.
조건 하나: 포트가 세션보다 오래 살아야 하는가
역방향 포워딩은 그것을 만든 SSH 세션과 정확히 같은 시간 동안만 살아 있습니다. 링크가 끊기면 대기자가 사라지고 동료는 느린 경로 대신 연결 거부를 보게 됩니다. 명령을 systemd 유닛과 재시작 정책으로 감독하면 해결되고, ExitOnForwardFailure=yes 는 바인딩 실패를 즉시 보이게 하여 포워딩 없이 도는 세션을 남기지 않습니다.
변환된 포트는 규칙이 영구 저장되면 재부팅을 견디지만, 클라이언트가 같은 터널 주소를 유지하는 데 의존합니다. 재연결 후 노트북에 다른 주소를 주는 동적 풀은 규칙을 조용히 아무 데도 아닌 곳으로 향하게 합니다. 먼저 터널 주소를 예약하고, 그다음 규칙을 작성하며, 둘을 하나의 변경으로 다루십시오.
서비스가 아무도 보지 않는 새벽 세 시에 응답해야 한다면, 살아 있어야 하는 유일한 프로세스가 터널 자체이므로 서버가 공개한 포트를 쓰는 형태가 움직이는 부품이 적습니다.
조건 둘: 방화벽과 로그는 누구의 것인가
역방향 형태는 모든 정책을 두 곳에 둡니다. sshd 는 AllowTcpForwarding 를 통해 원격 포워딩이 아예 허용되는지 결정하고, GatewayPorts 는 대기자가 루프백에 묶일지 모든 주소에 묶일지 결정합니다. 기본값 no 에서는 포워딩이 성공했어도 서버 밖의 동료가 포트에 도달할 수 없으며, 이것은 고장 난 터널처럼 보이지만 실제로는 바인딩 주소 문제입니다.
sudo ss -ltn '( sport = :8081 )'
sudo grep -E '^(GatewayPorts|AllowTcpForwarding)' /etc/ssh/sshd_config
변환 형태는 포워딩 활성화와 두 개의 규칙이 필요하며, 두 번째 규칙이 대부분의 절차가 틀리는 지점입니다. 출발지 변환을 conntrack 의 DNAT 상태로 한정한다는 것은 목적지 규칙이 만든 연결만 다시 쓰이고 서버가 터널로 보내는 모든 패킷이 다시 쓰이는 것은 아니라는 뜻입니다.
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8081 -j DNAT --to-destination 10.88.0.6:8080
sudo iptables -t nat -A POSTROUTING -o tun0 -m conntrack --ctstate DNAT -j SNAT --to-source 10.88.0.1
그 재작성은 귀속도 파괴합니다. 이후 클라이언트는 모든 호출자를 서버의 터널 주소로 보게 되어, 주소별 속도 제한이 하나의 버킷으로 뭉개지고 누가 무엇을 보냈는지 가려집니다. 귀속이 중요하다면 서버에서 연결을 종료하거나 허용 결정을 서버에 두고 서비스가 신뢰하는 헤더에 신원을 전달하십시오. 이 두 수정 중 무엇을 고를지는 서비스가 프록시 헤더를 읽는지에 달려 있습니다.
조건 셋: 포트 하나인가 여럿인가, 이름은 누구의 것인가
한 포트에 한 서비스라면 수고 면에서 역방향 포워딩이 이깁니다. 명령 하나, 계정 하나, 방화벽 규칙 하나면 되고 정리는 세션을 끊는 것입니다. 같은 공개 주소에 여러 서비스를 두면, 역방향 포워딩마다 서버 포트가 따로 필요하고 서비스가 늘수록 집합이 커지기 때문에 서버 공개 형태로 밀려납니다.
이름은 더 복잡하게 만듭니다. 역방향 포워딩은 SNI 로 라우팅하는 TCP 프록시 뒤에 둘 수 있지만, 변환된 포트는 보통 서비스당 하나입니다. 서비스가 직접 TLS 를 종료하고 원래 호스트 이름이 필요하다면 프록시 방식은 이를 유지하고, DNAT 방식은 서비스가 그 포트에서 그 이름을 받아들일 때만 유지합니다.
세 조건 중 무엇이 형태를 결정했는지 적어 두십시오. 그렇지 않으면 두 번째 서비스를 추가하는 다음 사람이 더 적은 맥락으로 같은 비교를 다시 열게 됩니다.
결정한 다음 바깥에서 시험하십시오
노트북으로 가는 경로가 없는 네트워크에서 경로를 시험하고, 요청이 실행되는 동안 서버의 카운터를 관찰하십시오. 서버에서 자기 공개 주소로 시험하는 것은, 패킷이 로컬에서 만들어져 들어오는 변환 훅에 결코 닿지 않기 때문에, 실제 경로가 끊겨 있어도 통과할 수 있어 여기서 아무것도 증명하지 못합니다.
sudo iptables -t nat -L PREROUTING -n -v
sudo tcpdump -ni any 'tcp port 8081' -c 20
카운터가 그대로라면 패킷이 규칙에 도달하지 않은 것이며, 이는 공급자나 호스트 방화벽을 가리킵니다. 서비스가 거부하는데 카운터가 움직인다면 클라이언트 자체의 방화벽이나 서비스가 대기하는 주소를 가리킵니다. 패킷을 실어 나르지만 아무것도 돌려주지 않는 터널은 경로나 역방향 경로 문제이며 그리고 이 세 결과 중 어느 것도 클라이언트 어댑터를 편집해 디버깅해서는 안 됩니다. 다음 시험에 그 기준선이 필요하므로 무엇이든 바꾸기 전에 어느 카운터가 움직였는지 적어 두십시오.
형태가 동작하면 포트, 소유자, 감독 방법을 터널 구성 옆에 기록하십시오. 누군가의 셸 기록에만 존재하는 도달성 수정은 재부팅 한 번이면 반복 사고가 됩니다.