1

I'm simulating a NAT/router setup inside a network namespace and I've encountered strange behaviour where conntrack entries are being created by packets sent to the router from the external WAN interface. I'm expecting that such conntrack entries should only be created when packets are being forwarded from the internal interface to the external interface (thus performing the NAT function of protecting the internal network from the external network).

Here's my situation:

architecture

Note that the architecture image above is bit outdated. I'm using 192.168.0.1 and 192.168.0.2, not 198.168.X.X.

ip netns add agent1
ip netns add router1
ip netns add router2
ip netns add agent2

# creates an interface a1 (otherside is r1-int)
ip netns exec agent1 ip link add a1 type veth peer name r1-int
# set r1-int to router1
ip netns exec agent1 ip link set r1-int netns router1

# creates an interface r1-ext (otherside is rw-ext)
ip netns exec router1 ip link add r1-ext type veth peer name r2-ext
# sets r2-ext to router2
ip netns exec router1 ip link set r2-ext netns router2

# creates an interface r2-int (otherwisde is a2)
ip netns exec router2 ip link add r2-int type veth peer name a2
# sets a2 to agent2
ip netns exec router2 ip link set a2 netns agent2

# set up interfaces for agent1
ip netns exec agent1 ip link set lo up
ip netns exec agent1 ip link set a1 up
ip netns exec agent1 ip addr add 10.0.0.2/24 dev a1
ip netns exec agent1 ip route add default via 10.0.0.1

# set up interfaces for router1
ip netns exec router1 ip link set lo up
ip netns exec router1 ip link set r1-int up
ip netns exec router1 ip link set r1-ext up
ip netns exec router1 ip addr add 10.0.0.1/24 dev r1-int
ip netns exec router1 ip addr add 192.168.0.1/24 dev r1-ext
ip netns exec router1 ip route add default via 192.168.0.2

# setup interfaces for router2
ip netns exec router2 ip link set lo up
ip netns exec router2 ip link set r2-int up
ip netns exec router2 ip link set r2-ext up
ip netns exec router2 ip addr add 10.0.0.1/24 dev r2-int
ip netns exec router2 ip addr add 192.168.0.2/24 dev r2-ext
ip netns exec router2 ip route add default via 192.168.0.1

# setup interfaces for agent2
ip netns exec agent2 ip link set lo up
ip netns exec agent2 ip link set a2 up
ip netns exec agent2 ip addr add 10.0.0.2/24 dev a2
ip netns exec agent2 ip route add default via 10.0.0.1

# Setting up port-restricted NAT for both routers (mapping will always be to port 55555 for easier testing)
ip netns exec router1 iptables -t nat -A POSTROUTING -p udp -o r1-ext -j MASQUERADE --to-ports 55555
ip netns exec router2 iptables -t nat -A POSTROUTING -p udp -o r2-ext -j MASQUERADE --to-ports 55555

When I send UDP packets from agent1 to router2, this creates conntrack entries in router1 as expected. It fails, because router2 doesn't have anything listening on that.

ip netns exec agent1 nc -u -p 55555 192.168.0.2 55555
> FIRST PACKET

However it is also creating conntrack entries in router2.

$ sudo ip netns exec router1 conntrack -L
udp      17 14 src=10.0.0.2 dst=192.168.0.2 sport=55555 dport=55555 [UNREPLIED] src=192.168.0.2 dst=192.168.0.1 sport=55555 dport=55555 mark=0 use=1
conntrack v1.4.6 (conntrack-tools): 1 flow entries have been shown.

$ sudo ip netns exec router2 conntrack -L
udp      17 16 src=192.168.0.1 dst=192.168.0.2 sport=55555 dport=55555 [UNREPLIED] src=192.168.0.2 dst=192.168.0.1 sport=55555 dport=55555 mark=0 use=1
conntrack v1.4.6 (conntrack-tools): 1 flow entries have been shown.

This additional conntrack entry in router2 is preventing me from sending packets from agent2 to router1.

ip netns exec agent2 nc -u -p 55555 192.168.0.1 55555
> SECOND PACKET

This SECOND PACKET arrives on router2 r2-int interface, then just disappears, it is never sent on r2-ext and never arrives at router1.

I suspect that my iptables rule is too general, and needs to be more selective (https://superuser.com/questions/1706874/iptables-selective-masquerade). However I tried with just -s 10.0.0.0/24 source address match and it also still resulted in the same behaviour.

Am I missing something with the iptables setup? How do I ensure that conntrack entries aren't being created in router2 from packets sent over from agent1?

4
  • ip netns exec router2 iptables -t nat -A POSTROUTING [...] NAT is used on router2 => conntrack gets activated on router2 => router2 will always create conntrack entries by default. Even if that's not what you'd want (I have trouble understanding what you want) that's what happens. I can't tell more without understanding the intent of this experiment.
    – A.B
    Commented Apr 7, 2022 at 18:14
  • I want to experiment with bidirectional NAT punchthrough with UDP. Both agent 1 and agent 2 is supposed to be able to send UDP packets to each other. Once router 1 opens up a port via conntrack I'm expecting that agent 2 can send packets through to agent 1 via the 2 routers. However because a conntrack entry is created in router 2 from agent 1's packet, agent 2's packet gets lost at router 2 and never gets sent to router 1. Commented Apr 8, 2022 at 0:22
  • We found that by dropping packets in the INPUT chain on both routers, the spurious conntrack entry doesn't get created. But this solution seems too broad as it would impact all packets going into the INPUT chain. Commented Apr 8, 2022 at 2:34
  • It could be that dropping packets in the input chains ends up dropping any conntrack entries being created for that packet. So accepting packets selectively on the input chain resolves this problem. Commented Apr 8, 2022 at 4:46

1 Answer 1

1

Partial answer:

I can make it work in both directions on my system with a more general rule and enabling forwarding

echo "1" | ip netns exec router1 tee /proc/sys/net/ipv4/ip_forward
ip netns exec router1 iptables -t nat -A POSTROUTING -o r1-ext -j MASQUERADE 

echo "1" | ip netns exec router2 tee /proc/sys/net/ipv4/ip_forward
ip netns exec router2 iptables -t nat -A POSTROUTING -o r2-ext -j MASQUERADE 

Then I can start nc on both routers (in different xterms) on the external interface:

ip netns exec router1 nc -u -l 192.168.0.1 -p 5555
ip netns exec router2 nc -u -l 192.168.0.2 -p 5555

and have the agents contact the "far" router:

echo foo | sudo ip netns exec agent1 nc -u 192.168.0.2 5555
echo foo | sudo ip netns exec agent2 nc -u 192.168.0.1 5555

Ping also works.

So the "additional" conntrack entry is not "preventing" the reverse packet (and I don't know exactly what went wrong on your machine).

It's also standard practice to only allow forwarding of outgoing connections (as you are doing NAT on outgoing packets):

ip netns exec router1 iptables -P FORWARD DROP
ip netns exec router1 iptables -A FORWARD -i r1-ext -o r1-int -m state --state ESTABLISHED,RELATED -j ACCEPT
ip netns exec router1 iptables -A FORWARD -i r1-int -o r1-ext -j ACCEPT

ip netns exec router2 iptables -P FORWARD DROP
ip netns exec router2 iptables -A FORWARD -i r2-ext -o r2-int -m state --state ESTABLISHED,RELATED -j ACCEPT
ip netns exec router2 iptables -A FORWARD -i r2-int -o r2-ext -j ACCEPT

However, even with those filters, the second conntrack entry still gets created. I don't know exactly why this is, but as it's not preventing anything from working properly, I'd just assume that it is working as intended: The packet is memorized to be able to track a potential connection, even though this connection never happens.

1
  • I believe the --to-ports is causing a problem here where the conntrack entry on router2 prevents utilisation of that port when SECOND PACKET is sent from agent2. So because you removed the --to-ports, it could work. But this doesn't work for our situation since we are simulating a peer to peer system that requires a consistent mapped-port. And the --to-port option is there to simulate the programmer acting as the seed/signalling server enabling bidirectional NAT-punch through. By dropping packets on the input chain, this prevents the spurious conntrack entry. Commented Apr 8, 2022 at 8:29

You must log in to answer this question.

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