4

I've got a router performing simple NAT translation using iptables iptables -t nat -o -j MASQUERADE

This works fine almost all of the time except for one particular case where some TCP RST and FIN packets are leaving the router un-NAT'd.

In this scenario I setup 1 or 2 client computers streaming Flash video (eg www.nasa.gov/ntv) At the router I then tear down and re-establish the public interface (which is a modem) As expected the Flash streams stall out. After the connection is re-established and I try to refresh the Flash pages, I see some TCP RST and [FIN,ACK] packets leaving the public interface (I assume as Flash attempts to recover its stream).

I don't know how these packets can leave the router non-NAT'd

5 Answers 5

1

Thanks for the tip. I was just what I needed to set me on the right track.

The root cause was unfiltered forwarding between lan and public interface. When the public interface got torn down it cleared the conntrack entries. The clients then tried to revive their connections and ended up sending out RST and FIN packets. Since NAT gets setup only on NEW connections, these packets then left the router unmodified.

I had to change my forwarding rule to only allow NEW,ESTABLISHED,RELATED packets to get forwarded from private lan.

1
  • This tip set me on the right path so I rephrased it in a more direct form. Thanks! May 12, 2021 at 14:39
1

Dropping the [RST,ACK] and [FIN,ACK] will not work. There are many application like ftp upload that will simply fail to ack the completion of the FTP transfer. The comments by gscott are the correct method, but one additional requirement is needed. You must make them strict by applying the policy

iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -P INPUT DROP

With this, you need to specify all your rules, or the packets will be dropped.

0

This might be a bug in the MASQUERADE target of iptables. In your scenario, it appears that you have the following co-inciding events:

  • the packets happen to belong to a connection already present in the state table
  • the state entry includes a NAT address source no longer owned by the system

So an attempt to masquerade the packet might fail due to an invalid address to masquerade to, thus the packet is being routed out unchanged.

The expected behavior from the MASQUERADE target would be to have the according state entries cleared when an interface goes down or gets the address changed, so this situation should not have occurred. But there has been an ancient bug reported for iptables which sounds like it could trigger a similar kind of behavior.

To do some further troubleshooting, note the public IP address of your router, reproduce the issue and take a look at the state table by using egrep 12.34.56.78 /proc/net/ip_conntrack (where 12.34.56.78 is the IP address you previously noted). If you get conntrack lines with the old IP address despite of the public interface address having changed, you probably are running into an iptables bug - consider updating your kernel/iptables and reporting the issue to the netfilter team.

0

FYI

An other way to prevent the FIN,ACK and RST,ACK packages going in the public network is to block them in the outgoing chain

iptables -I OUTPUT -s <internal net> -p tcp --tcp-flags ALL RST,ACK -j DROP
iptables -I OUTPUT -s <internal net> -p tcp --tcp-flags ALL FIN,ACK -j DROP 
iptables -I OUTPUT -s <internal net> -p tcp --tcp-flags ALL FIN -j DROP
iptables -I OUTPUT -s <internal net> -p tcp --tcp-flags ALL RST -j DROP

This helped me to prevent spoofed packages.

1
  • It is undesirable to block all FIN/RST packets. And the INPUT/OUTPUT chains are not typically used for MASQUERADE (those packets go through FORWARD). May 12, 2021 at 14:37
0

The rules in -t nat only work on the first packet in a stream (state NEW). Other packets in that stream then have the same treatment done without any further iptables rules being applied to them. But packets that cannot start a stream (such as FIN and RST, or probably anything except SYN) and which are not associated with a current stream are ignored by -t nat. The iptables state machine classifies these packets as state INVALID. They can be filtered out with:

iptables -A FORWARD -m state --state INVALID -j DROP

Depending on your other rules, this rule may need to be inserted before a -j ACCEPT rule.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .