NAT 뒤에 있는 WireGuard 피어로의 포트 포워딩: DNAT와 SNAT
DNAT는 요청을 전달하지만 응답은 잘못된 주소에서 나갑니다. 일치하는 SNAT 규칙을 추가하고 터널 구성 후 둘 다 배치하십시오.
브라우저가 https://203.0.113.10:8443 을 요청하고, 프록시가 연결을 수락하며, WireGuard 피어의 서비스는 결코 응답하지 않습니다. DNAT 규칙은 제 역할을 하고 있고, 실패하는 쪽은 응답입니다. 패킷을 두 변환 모두 따라가면 빠진 규칙이 분명해집니다. 해결책은 올바른 훅에 NAT 문을 하나 더 추가하는 것이지 새 터널이 아닙니다.
요청 하나를 처음부터 끝까지 따라가기
요청은 클라이언트의 공인 주소를 출발지로, 프록시 주소를 목적지로 하여 프록시의 공인 인터페이스에 도착합니다. nat PREROUTING에서 DNAT 규칙은 목적지를 피어의 터널 주소인 10.90.0.2로 다시 씁니다. 그다음 라우팅 결정이 패킷을 wg0를 통해 내보내고 포워딩 경로가 완성됩니다.
피어에서 패킷은 아무것도 주소를 다시 쓰지 않았기 때문에 이제 원래의 공인 출발지 주소를 지니고 있습니다. 서비스는 연결을 수락하고 응답을 자체 기본 게이트웨이, 즉 피어 앞의 가정용 라우터로 보냅니다. 그 라우터는 한 번도 본 적 없는 흐름에 대한 상태가 없으므로 패킷을 버리거나 자체 공인 주소로 변환하며, 클라이언트는 이를 받아들이지 않습니다.
비대칭성이 문제의 전부입니다: 요청은 프록시를 지나가고 응답은 직접 가려고 합니다. 프록시의 연결 추적은 응답이 프록시를 통해 돌아올 때만 도움이 되며, 출발지 주소가 원래 클라이언트를 가리키는 동안에는 그리로 돌아갈 수 없습니다.
돌아오는 변환 추가하기
포워딩되는 흐름의 출발지를 피어로 떠나기 전에 프록시의 터널 주소로 다시 쓰십시오. 그러면 서비스는 10.90.0.1로 응답하고, 프록시가 이를 받으며, 패킷이 클라이언트로 돌아가기 전에 연결 추적이 두 변환을 모두 되돌립니다.
iptables -t nat -A PREROUTING -p tcp -m multiport --dports 8080,8443 -j DNAT --to-destination 10.90.0.2
iptables -t nat -A POSTROUTING -d 10.90.0.2 -o wg0 -p tcp -m multiport --dports 8080,8443 -j SNAT --to-source 10.90.0.1POSTROUTING 규칙은 변환된 목적지와 터널 인터페이스에 일치하므로 의도적으로 좁으며, wg0를 통해 우연히 나가는 무관한 트래픽을 다시 쓰지 않습니다. 넓은 masquerade 규칙 도 클라이언트 주소를 숨기겠지만 모든 흐름에 대해 그렇게 하고 NAT 테이블 감사를 어렵게 만듭니다.
터널이 존재하는 곳에 규칙 배치하기
터널 주소나 인터페이스를 참조하는 규칙은 wg-quick이 이를 구성한 뒤에 실행되어야 합니다. 인터페이스는 PreUp 전에 생성되지만 주소, MTU, DNS, 경로는 그 뒤에 적용되며, PostUp은 그 모두가 준비된 뒤에 실행됩니다. 추가는 PostUp에, 삭제는 PreDown에 두십시오.
PostUp = iptables -t nat -A PREROUTING -p tcp -m multiport --dports 8080,8443 -j DNAT --to-destination 10.90.0.2
PostUp = iptables -t nat -A POSTROUTING -d 10.90.0.2 -o wg0 -p tcp -m multiport --dports 8080,8443 -j SNAT --to-source 10.90.0.1
PreDown = iptables -t nat -D PREROUTING -p tcp -m multiport --dports 8080,8443 -j DNAT --to-destination 10.90.0.2
PreDown = iptables -t nat -D POSTROUTING -d 10.90.0.2 -o wg0 -p tcp -m multiport --dports 8080,8443 -j SNAT --to-source 10.90.0.1삭제는 추가와 토큰 단위로 일치해야 하며 multiport와 인터페이스 일치도 포함됩니다. 일치 하나가 다른 삭제는 아무것도 제거하지 못하고, 다음 재연결은 규칙의 두 번째 사본을 추가합니다. 몇 번의 재연결 후 테이블에는 구성 줄에 귀속시키기 어려운 중복이 남습니다.
결과는 iptables -t nat -S 로 재연결 후 확인하십시오. 같은 규칙이 두 번 나타나면 PreDown 줄이 일치하지 않는 것이며 정리가 조용히 실패하고 있습니다.
포워딩, 필터링, 그리고 다른 NAT
IPv4 포워딩을 영구적으로 켜고, 그다음 필터 테이블에서 포워딩되는 흐름을 허용하십시오. DNAT는 FORWARD 체인 전에 일어나므로 필터 규칙은 공인 주소가 아니라 변환된 목적지와 일치합니다. UFW가 방화벽을 관리한다면 허용을 경로 규칙으로 표현하되, 단순한 호스트 규칙은 포워딩되는 트래픽을 다루지 못합니다.
프록시 규칙이 올바르더라도 다른 두 NAT 계층이 경로를 끊을 수 있습니다. 가정 연결에서 공인 주소는 라우터의 것이며, 그 방화벽에서 포트를 여는 것은 그 포트를 프록시로 보내는 포트 포워딩 항목을 만드는 것과 같지 않습니다. 밖에서 열린 것처럼 보이지만 아무것도 응답하지 않는 포트는 흔히 바로 그 매핑이 빠져 있습니다.
NAT VPS에서는 공급자가 공인 포트를 사설 주소에 매핑합니다. 매핑은 알리는 포트와 일치해야 하며, 불일치는 끊긴 터널과 똑같이 보입니다. WireGuard 구성을 바꾸기 전에 공급자의 매핑을 확인하십시오.
돌아오는 경로를 확인하고 비용을 받아들이기
프록시의 LAN이 아닌 네트워크에서 연결한 다음, 연결이 열려 있는 동안 변환 쌍을 검사하십시오:
conntrack -L -p tcp --dport 8080
tcpdump -ni any tcp port 8080conntrack 항목에는 원래 튜플, 변환된 튜플, 응답 방향이 표시되어야 합니다. 응답이 없으면 피어가 터널을 통해 보내지 않는 것이며, 보통 SNAT 규칙이 적용되지 않았거나 피어 자체 방화벽이 흐름을 버렸다는 뜻입니다.
PostUp이 규칙을 다시 적용하는지 증명하기 위해 한 번 재부팅하고, 그다음 터널을 중지하여 PreDown이 규칙을 제거했는지 확인하십시오. 연결이 끊긴 뒤에도 남는 죽은 규칙이 이후 변경이 예측 불가능하게 동작하는 이유입니다.
마지막으로 SNAT의 비용을 받아들이십시오. 서비스는 모든 요청을 프록시에서 온 것으로 보므로 접근 로그, 클라이언트별 속도 제한, 허용 주소 목록이 더 이상 사용자를 구분하지 못합니다. 헤어핀 사례는 프록시의 LAN에 있는 클라이언트를 위해 자체 출발지 변환이 필요합니다. 피어가 실제 클라이언트 주소를 필요로 한다면 대안은 클라이언트 네트워크로의 귀환 경로이며, 작업은 더 많지만 정보는 보존됩니다.