iptables Port Forward to another Public IP (TCP Proxy)

(Last Updated On: December 17, 2020)

iptables tcp/udp port forward to another global ip address (also another port) 리눅스 포트 포워딩

iptables로 TCP 로 다른 서버(Public IP또는 물리적으로 동일한 인터페이스에 연결되지 않은 IP주소)에 포워딩 하려면 문제가 발생한다. 보통 포워딩은 DNAT으로 하는데 DNAT을 수행하면 INTERNET으로 트래픽이 빠지지만 해당 패킷이 DNAT을 수행한 본인서버의 Source IP주소가 아니기 때문에 Source IP 검증을하는 방화벽을 거치거나 목적지 서버에 도착하면 인터넷 상에서 패킷이 소멸하게 된다. (목적지 서버가 패킷을 수신하더라도 Source IP 주소가 nat을 수행한 서버의 주소가 아니기 때문이기도 함)

따라서 Source NAT과 Destination NAT 두 번 수행할 필요가 생긴다.

iptables

  • NAT을 수행하는 중간서버(eth0: 203.0.113.57)의 income 포트 : 8080
  • 대상 목적지 서버 (198.51.100.38)의 포트 80

allow firewall

iptables -A INPUT -i eth0 -p tcp -m tcp --dport 8080 -j ACCEPT

DNAT

iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 8080 -j DNAT --to-destination 198.51.100.38:80

SNAT

iptables -t nat -A POSTROUTING -p tcp --destination 198.51.100.38 --dport 80 -o eth0 -j SNAT --to-source 203.0.113.57

conntrack

이미 연결된 세션을 건들지 않게 conntrack 를 최상위 룰로 배치한다.

iptables -I INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

enable ip_forward

이 L4 포워드도 리눅스 ip forward 활성화 대상인지는 정확하겐 모르겠지만 아마 맞겠지???

echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p

문제점

이런식으로 포워딩 하는 경우 문제가 수신자측에 원본 Source IP가 분실된다. 따라서 뭔가 포워드 하려면 IP Tunnel 구성 후 직접 인터페이스를 연결해서 포워드 하는 것이 가장 낫다.

원격지가 높은 RTT의 경우 성능향상 기대없음

위 글에서 나는 RTT가 높은 환경에서 proxy 어플리케이션을 통해 모든 트래픽을 리눅스시스템으로 처리하게끔 변경하였다. 하지만 이 포스트의 경우에는 SNAT/DNAT만 수행하기 때문에 패킷(SEGMENT)만 복제된다. 따라서 TCP 레벨에서 감지되는 RTT는 NAT을 수행하는 중간서버 까지만 감지하는 것이 아니라 ‘중간+원본서버’ 값인것을 확인할 수 있다.

중간서버에서 원본서버까지 거리가 멀 때 중계서버로 사용했을 때의 성능 이점이 없다는 것이다. 따라서 TCP RTT를 줄여 성능향상의 목적이라면 (리버스)프록시를 완벽하게 지원하는 HTTP웹서버등이 적합하다. TCP/UDP 릴레이는 SOCAT