Need a generic iptables tcp proxy?
Posted by JacobAppelbaum on Tue 13 May 2008 at 10:02
It's as easy as the following three iptables calls:
YourIP=1.2.3.4 YourPort=80 TargetIP=2.3.4.5 TargetPort=22 iptables -t nat -A PREROUTING --dst $YourIP -p tcp --dport $YourPort -j DNAT \ --to-destination $TargetIP:$TargetPort iptables -t nat -A POSTROUTING -p tcp --dst $TargetIP --dport $TargetPort -j SNAT \ --to-source $YourIP iptables -t nat -A OUTPUT --dst $YourIP -p tcp --dport $YourPort -j DNAT \ --to-destination $TargetIP:$TargetPort
In the example above, a user may now ssh to $YourIP (1.2.3.4) on $YourPort (port 80) and they'll be transparently redirected to the $TargetIP (2.3.4.5) on the $TargetPort (22). The remote host ($TargetIP) will see the connection as coming from the server doing the forwarding ($YourIP).
Why bother with this at all? Why not just change the port that sshd listens on?
This is useful when a network filters outgoing connections based on destination ports and you don't control the host you want to connect to. If such a network only allowed outgoing connections to port 80, you'd be able to circumvent their filtering. However, if the firewall is doing stateful layer seven inspection, all bets are off. It's trivial to make this work for any other protocol, there is nothing special about ssh - it's just used as an example.
As a general note, this may invite abuse. It is basically a single hop protocol agnostic TCP proxy in kernel space. It's fast and useful though. You may want to restrict forwarding by source IP addresses if you're worried about letting anyone using you as a single hop bounce. I'll leave that as an exercise for the comments.
We use NAT forwarding for websites we expect that they will be loadbalanced in the future.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
When new clients expects that they need loadbalancing within a year, we don't assign a public IP to the actual webserver, but to the firewall. The firewall will than forward all http trafic to the internal machine (as describes by this article, except that the port doesn't changes). After a year we can assign the public IP to the loadbalancer an add the second webserver to the pool.
About adding the public IP to the local loopback. We have several web applications that connect to their own webservices (SOA design). Say that www.example.org points to 1.2.3.4, than webserver with interface 10.0.0.1 routes to 1.2.3.4 (gateway does masquerading (POSTROUTING) part 1), but than it sees that that 1.2.3.4 points back to 10.0.0.1, that it double masquerades (adding the PREROUTING masquerade). But gateways don't like double forwarding packets. When rf_filter is enabled it will even drop the packet because the request originated from the wrong interface.
To prevent the extensive routing, you can add the 1.2.3.4 IP to your local loopback device and any attempts from the webserver to connect to itself are handled by the loopback device.
firewall gateway:
eth0: 1.2.3.4
eth1: 10.0.0.254
lo: 127.0.0.1
Server A:
eth0: IP 10.0.0.1
lo: 127.0.0.1, 1.2.3.4
--- IF LOADBALANCED
Server B:
eth0: 10.0.0.2
lo: 127.0.0.1, 1.2.3.4
Server C:
eth0: 10.0.0.3
lo: 127.0.0.1, 1.2.3.4
Server D:
eth0: 10.0.0.4
lo: 127.0.0.1, 1.2.3.4
--- END IF
Hope that this make my previous comment a bit clearer.
[ Parent | Reply to this comment ]
"TCP/IP packet repeater in the application layer. It repeats TCP and UDP packets from inside to outside of a firewall, or from outside to inside."
You can basically proxy or forward any tcp or udp connection with one single command. However, learning iptables is always a good idea ;-) !
kind regards, mistersixt.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
===============================================
#!/bin/sh
# TCP Proxy using IPTables
IPTABLES=/sbin/iptables
echo 1 > /proc/sys/net/ipv4/ip_forward
# Flush nat table
$IPTABLES -t nat -F
# tcpproxy LOCAL_IP LOCAL_PORT REMOTE_IP REMOTE_PORT
function tcpproxy {
$IPTABLES -t nat -A PREROUTING --dst $1 -p tcp --dport $2 -j DNAT --to-destination $3:$4
$IPTABLES -t nat -A POSTROUTING --dst $3 -p tcp --dport $4 -j SNAT --to-source $1
$IPTABLES -t nat -A OUTPUT --dst $1 -p tcp --dport $2 -j DNAT --to-destination $3:$4
}
# Example 1
tcpproxy 192.168.40.244 3200 10.10.10.2 3200
# Example 2
tcpproxy 192.168.40.245 3200 192.168.1.30 3200
===============================================
sorry for any spelling errors (english isnt my native language) :)
[ Parent | Reply to this comment ]
-j
belong in that last rule? (sorry if this is a stupid
question. i'm an iptables ignoramus)
[ Parent | Reply to this comment ]
--dummy
[ Parent | Reply to this comment ]