iptables PREROUTING not in effect

We are running a ubuntu 20.04 in AWS. We are trying to set up an iptables rule so any MySQL traffic with a dummy IP address will be forwarded to the MySql database at 172.31.6.173 in the same VPC. Let me explain:

IP addresses in this task:

Ubuntu server(source): 172.31.0.151

MySql server(destination): 172.31.6.173

MySql Dummy IP: 6.6.6.6

From 172.31.0.151 (source) we will connect to mysql at dummy IP (6.6.6.6), and it will be NAT'd to destination (172.31.6.173).

The rules we used:

sudo iptables -t nat -A PREROUTING -s 172.31.0.151 -d 6.6.6.6 -j DNAT --to-destination 172.31.6.173
sudo iptables -A FORWARD -p tcp -d 172.31.6.173 -j ACCEPT

The first line specifies any traffic from the 172.31.0.151, with destination for 6.6.6.6, will be forwarded to 172.31.6.173

The second line accepts all tcp forward to 172.31.6.173.

These are the only rules in the iptables, if I run sudo iptables -t nat -L, the result is:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT       all  --  172.31.0.151         6.6.6.6              to:172.31.6.173

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

However with these two rules in place, from the source(172.31.0.151) server, when I tried to login MySql at dummy IP:

mysql -h 6.6.6.6 -u username -p

The tcpdump output: (the MySql server is a RDS instance which means I cannot login to run tcpdump, so I can only get the tcpdump from the source server):

13:41:41.768171 IP 172.31.0.151.50374 > 6.6.6.6.mysql: Flags [S], seq 3441229166, win 62727, options [mss 8961,sackOK,TS val 2723434614 ecr 0,nop,wscale 7], length 0

13:41:45.992114 IP 172.31.0.151.50374 > 6.6.6.6.mysql: Flags [S], seq 3441229166, win 62727, options [mss 8961,sackOK,TS val 2723438838 ecr 0,nop,wscale 7], length 0

13:41:54.184186 IP 172.31.0.151.50374 > 6.6.6.6.mysql: Flags [S], seq 3441229166, win 62727, options [mss 8961,sackOK,TS val 2723447030 ecr 0,nop,wscale 7], length 0

The PREROUTING rule does not take effect, the login attempt is still looking for a server at 6.6.6.6, instead of being NAT'd to the actual IP address of 172.31.6.173.

Any advice will be appreciated. Thank you.


Solution 1:

I'm assuming OP's rule was added to the Ubuntu system with IP address 172.31.0.151, the same system that is then initiating mysql connections to a dummy address.

As can be seen in this Netfilter and General Networking schematic: Packet flow in Netfilter and General Networking

  • the first packet in a flow initiated by a local process doesn't traverse nat/PREROUTING,
  • but it does traverse nat/OUTPUT,
  • only the first packet (state NEW) of a connection traverses the nat table (so further packets like replies don't matter here anyway).

So nat/PREROUTING has no effect to redirect a locally initiated connection. This should be done in nat/OUTPUT. As this might change even the interface to use (probably not in OP's case), this triggers a reroute check later to handle such case.

In the end your rule should be added with:

sudo iptables -t nat -A OUTPUT -s 172.31.0.151 -d 6.6.6.6 -j DNAT --to-destination 172.31.6.173

If the system has only one IP address: 172.31.0.151, -s 172.31.0.151 becomes superfluous:

sudo iptables -t nat -A OUTPUT -d 6.6.6.6 -j DNAT --to-destination 172.31.6.173