2

I amreading the documentation of Iptables about the connection tracking here and I have troubles figuring the following part, highlited by me:

tcp   6 117 SYN_SENT src=192.168.1.6 dst=192.168.1.9 sport=32775 \
 dport=22 [UNREPLIED] src=192.168.1.9 dst=192.168.1.6 sport=22 \
 dport=32775 [ASSURED] use=2

This example contains all the information that the conntrack module maintains to know which state a specific connection is in. First of all, we have a protocol, which in this case is tcp. Next, the same value in normal decimal coding. [...] Lastly, we see what we expect of return packets. The information details the source IP address and destination IP address (which are both inverted, since the packet is to be directed back to us). The same thing goes for the source port and destination port of the connection

I can't understand why it should be useful to keep track of the expected IPs and ports if they are just inverted. When a packet arrives, the lookup can just be done using one pair of IPs and Ports, and if not found it can be done with the same fields but reversed. Is keeping this information some kind of optimization or am I missing some use case in which this is the only way to achieve something?

Thank you

Tu.Ma.
  • 123
  • 1
  • 6

1 Answers1

3

It's useful to track current and expected states. It's most useful when the expected IPs and port aren't just inverted in the reverse direction. This happens for example when NAT is in use, or just when the reverse isn't exactly the same. It will also when relevant, verify that the state transitions are respected (eg: for TCP) Some examples:

Here after a simple ping from 192.0.2.2, the reply is expected to have an ICMP type 0 (echo reply) instead of the initial type 8 (echo request):

icmp     1 12 src=192.0.2.2 dst=8.8.8.8 type=8 code=0 id=26387 src=8.8.8.8 dst=192.0.2.2 type=0 code=0 id=26387 mark=0 use=1

An active (instead of passive) FTP session (tracked with conntrack -E) from an host 10.1.2.3 behind a NAT router with public IP 198.51.100.32 to a FTP server 203.0.113.47. Notice that in the reply, the router's ip is expected instead of the NATed (and non routable over internet) ftp client's ip. The expectation's creation was altered by a SNAT (or MASQUERADE) rule:

    [NEW] tcp      6 120 SYN_SENT src=10.1.2.3 dst=203.0.113.47 sport=47800 dport=21 [UNREPLIED] src=203.0.113.47 dst=198.51.100.32 sport=21 dport=47800 helper=ftp
 [UPDATE] tcp      6 60 SYN_RECV src=10.1.2.3 dst=203.0.113.47 sport=47800 dport=21 src=203.0.113.47 dst=198.51.100.32 sport=21 dport=47800 helper=ftp
 [UPDATE] tcp      6 432000 ESTABLISHED src=10.1.2.3 dst=203.0.113.47 sport=47800 dport=21 src=203.0.113.47 dst=198.51.100.32 sport=21 dport=47800 [ASSURED] helper=ftp

After ls an expectation entry with the destination calculated from the client's ftp PORT command as well as the previous conntrack entry (with nat) was added by the ftp helper in the expectation table, to allow the flow to pass (eg with a RELATED rule in firewall) before further helper processing. This can be read there (but will disappear as soon as a matching connection, meaning the connection is seen, so it can't really be seen unless a firewall delays it):

# cat /proc/net/nf_conntrack_expect
295 l3proto = 2 proto=6 src=203.0.113.47 dst=198.51.100.32 sport=0 dport=41603 ftp

and be further altered by the helper (here DNATed, still using the previous conntrack entry for help) to finally get this new tracked connection:

    [NEW] tcp      6 120 SYN_SENT src=203.0.113.47 dst=198.51.100.32 sport=20 dport=41603 [UNREPLIED] src=10.1.2.3 dst=203.0.113.47 sport=41603 dport=20
 [UPDATE] tcp      6 60 SYN_RECV src=203.0.113.47 dst=198.51.100.32 sport=20 dport=41603 src=10.1.2.3 dst=203.0.113.47 sport=41603 dport=20
 [UPDATE] tcp      6 432000 ESTABLISHED src=203.0.113.47 dst=198.51.100.32 sport=20 dport=41603 src=10.1.2.3 dst=203.0.113.47 sport=41603 dport=20 [ASSURED]
 [UPDATE] tcp      6 120 FIN_WAIT src=203.0.113.47 dst=198.51.100.32 sport=20 dport=41603 src=10.1.2.3 dst=203.0.113.47 sport=41603 dport=20 [ASSURED]
 [UPDATE] tcp      6 60 CLOSE_WAIT src=203.0.113.47 dst=198.51.100.32 sport=20 dport=41603 src=10.1.2.3 dst=203.0.113.47 sport=41603 dport=20 [ASSURED]
 [UPDATE] tcp      6 30 LAST_ACK src=203.0.113.47 dst=198.51.100.32 sport=20 dport=41603 src=10.1.2.3 dst=203.0.113.47 sport=41603 dport=20 [ASSURED]
 [UPDATE] tcp      6 120 TIME_WAIT src=203.0.113.47 dst=198.51.100.32 sport=20 dport=41603 src=10.1.2.3 dst=203.0.113.47 sport=41603 dport=20 [ASSURED]
[DESTROY] tcp      6 src=203.0.113.47 dst=198.51.100.32 sport=20 dport=41603 src=10.1.2.3 dst=203.0.113.47 sport=41603 dport=20 [ASSURED]

Those expectation entries are both used to track flows (conntrack), allowing for example to easily have a stateful firewall by dropping what isn't tracked (don't let an icmp echo reply pass if there wasn't the initial icmp echo ping made before with the same id) and remember how to translate IPs/port (if nat is in use).

A.B
  • 31,762
  • 2
  • 62
  • 101