Skip to contentSkip to conversation

Matching IPSEC encapsulated traffic with connection tracking

DISCUSSION Robert Dahlem 3 participants 3 messages Jan 4, 2005 – Jan 6, 2005

lore
Share & tools
lore
#0 lore raw

Hi,

sorry, this is a bit lengthy ...

There seems to be a problem with my understanding of Netfilter connection tracking when encapsulating packets with IPSEC/AH.

My setup is (gory details left apart):

Host A Host B
+--------------+ eth1 eth1 +----------------+
! 10.133.126.6 +-------------+ 10.133.127.197 !
+--------------+ +----------------+

Traffic between A and B must be transported with IPSEC/AH. Host B must be able to initiate SSH connections to Host A. We are only talking about netfilter rules an Host A.

I have a working scenario, where netfilter rules inspect packets whether they belong to an already established connection and accepts them. The only other rule is to accept packets coming from 10.133.127.197 and targeted on port 22. IPSEC is inactive in this scenario.

I have another working scenario, where IPSEC/AH is active and netfilter is inactive. Keys get exchanged, packets became AH-encapsulated.

The problem is to combine these two scenarios: make both netfilter and IPSEC active at the same time.

My rule set is:
======================================================================
IT=/usr/sbin/iptables
INPUT="$IT -A $INPUT"
OUTPUT="$IT -A $OUTPUT"
ESTAB="-m state --state ESTABLISHED,RELATED"

# Debug: Log all Packets
$INPUT -i eth1 -j LOG --log-prefix 'Debug INPUT:' $OUTPUT -o eth1 -j LOG --log-prefix 'Debug OUTPUT:'

# Allow IPSEC/AH traffic
$INPUT -i eth1 -p ah -j ACCEPT
$OUTPUT -o eth1 -p ah -j ACCEPT

# Allow traffic on already established connections $INPUT -i eth1 $ESTAB -j ACCEPT
$OUTPUT -o eth1 $ESTAB -j ACCEPT

# Allow IPSEC key exchange
$INPUT -i eth1 -p udp --sport 500 --dport 500 -j ACCEPT

# Allow incoming SSH from 10.133.127.197
$INPUT -i eth1 -p tcp -s 10.133.127.197 --dport 22 -j ACCEPT

# Log and drop illegal traffic (which means: the rest) $INPUT -i eth1 -j LOG --log-prefix 'Ill. INPUT:' $OUTPUT -o eth1 -j LOG --log-prefix 'Ill. OUTPUT:' $INPUT -i eth1 -j DROP
$OUTPUT -o eth1 -j DROP
======================================================================

Without IPSEC everything works fine. Kernel messages look like this:

======================================================================
# SYN packet
HostA kernel: Debug INPUT:IN=eth1 OUT=

	MAC=00:0a:5e:4d:0f:12:00:0a:5e:4d:10:42:08:00
	SRC=10.133.127.197 DST=10.133.126.6
	LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=5559 DF
	PROTO=TCP SPT=1023 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0

# SYN/ACK packet, ESTABLISHED rule matches
HostA kernel: Debug OUTPUT:IN= OUT=eth1

	SRC=10.133.126.6 DST=10.133.127.197
	LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF
	PROTO=TCP SPT=22 DPT=1023 WINDOW=5792 RES=0x00 ACK SYN URGP=0

# ACK packet, ESTABLISHED rule matches
HostA kernel: Debug INPUT:IN=eth1 OUT=

	MAC=00:0a:5e:4d:0f:12:00:0a:5e:4d:10:42:08:00
	SRC=10.133.127.197 DST=10.133.126.6
	LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=5561 DF
	PROTO=TCP SPT=1023 DPT=22 WINDOW=1460 RES=0x00 ACK URGP=0
# first data packet, ESTABLISHED rule matches
HostA kernel: Debug OUTPUT:IN= OUT=eth1
	SRC=10.133.126.6 DST=10.133.127.197
	LEN=74 TOS=0x00 PREC=0x00 TTL=64 ID=4944 DF
	PROTO=TCP SPT=22 DPT=1023 WINDOW=1448 RES=0x00 ACK PSH URGP=0
======================================================================

By looking at the output of 'iptables -L -v -n' I can see that every packet but one (the initial SYN packet) is accepted by the ESTABLISHED rule.

Now with IPSEC (racoon started, key exchange already done, SA+SP in place):

======================================================================
# SYN packet arriving from net, AH encapsulated
HostA kernel: Debug INPUT:IN=eth1 OUT=

	MAC=00:0a:5e:4d:0f:12:00:0a:5e:4d:10:42:08:00
	SRC=10.133.127.197 DST=10.133.126.6
	LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=57273 DF
	PROTO=AH SPI=0x776227d

# Kernel tries to answer, packet still has to become AH-encapsulated HostA kernel: Debug OUTPUT:IN= OUT=eth1

	SRC=10.133.126.6 DST=10.133.127.197
	LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF
	PROTO=TCP SPT=22 DPT=1023 WINDOW=5792 RES=0x00 ACK SYN URGP=0

# ESTABLISHED rule no longer matches!
# Note that this is the same packet as before, just logged a second

# time because ESTABLISHED rule did not match.
HostA kernel: Ill. OUTPUT:IN= OUT=eth1
	SRC=10.133.126.6 DST=10.133.127.197
	LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF
	PROTO=TCP SPT=22 DPT=1023 WINDOW=5792 RES=0x00 ACK SYN URGP=0
======================================================================

In this case the ESTABLISHED rule does not accept one single packet.

The output of 'iptables -L -v -n' looks like this
(irrelevant parts stripped off, rules numbered):

======================================================================
Chain INPUT (policy ACCEPT 3 packets, 234 bytes)

   pkts target prot source         destination
#i1   1 LOG    all  0.0.0.0/0      0.0.0.0/0 LOG prefix `Debug INPUT:'
#i2   1 ACCEPT ah   0.0.0.0/0      0.0.0.0/0
#i3   0 ACCEPT all  0.0.0.0/0      0.0.0.0/0 state RELATED,ESTABLISHED
#i4   0 ACCEPT udp  0.0.0.0/0      0.0.0.0/0 udp spt:500 dpt:500
#i5   0 ACCEPT tcp  10.133.127.197 0.0.0.0/0 tcp dpt:22
#i6   0 LOG    all  0.0.0.0/0      0.0.0.0/0 LOG prefix `Ill. INPUT:'
#i7   0 DROP   all  0.0.0.0/0      0.0.0.0/0

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)

   pkts target prot source         destination
#o1   1 LOG    all  0.0.0.0/0      0.0.0.0/0 LOG prefix `Debug OUTPUT:'
#o2   0 ACCEPT ah   0.0.0.0/0      0.0.0.0/0
#o3   0 ACCEPT all  0.0.0.0/0      0.0.0.0/0 state RELATED,ESTABLISHED
#o4   1 LOG    all  0.0.0.0/0      0.0.0.0/0 LOG prefix `Ill. OUTPUT:'
#o5   1 DROP   all  0.0.0.0/0      0.0.0.0/0

======================================================================

Note that rule #i5 never matched. It looks like the match by rule #i2 prevents any AH-encapsulated packet from being inspected later, especially by the connection tracking.

The rules mentioned are only an illustrative example of a more complicated situation but they describe the problem exactly. What I would like to achieve is to gain control over the encapsulating IPSEC traffic as well as the encapsulated payload traffic.

Is there any solution for this? Thanks in advance for every helpful pointer.

Kind regards,
Robert

#1 lore raw

Hi,

Quoted 2 lines · Robert Dahlem

The problem is to combine these two scenarios: make both netfilter and IPSEC active at the same time.

[...]

Quoted 6 lines

# SYN packet
HostA kernel: Debug INPUT:IN=eth1 OUT=

    MAC=00:0a:5e:4d:0f:12:00:0a:5e:4d:10:42:08:00
    SRC=10.133.127.197 DST=10.133.126.6
    LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=5559 DF
    PROTO=TCP SPT=1023 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0

This packet causes the problem because the encapsulated TCP (transport mode) or IP packet (tunnel mode) is not inspected and due the connection tracking does not know of.

Robert, you may want to look into the mailing list archive of the developer list (https://lists.netfilter.org/pipermail/netfilter-devel/) and/or the current patch-o-matic. January last year there was a discussion on the developer list with the topic "NAT before IPsec with 2.6" which caused Harald Welte to produce a patch which may be of help to you. I have no idea of the current state of this.

Michael

#2 lore raw
In reply to Robert Dahlem
Quoted 3 lines · Robert Dahlem

Hi,

sorry, this is a bit lengthy ...

<snip>

are you running a 2.6 kernel (i can assume that you are, but you know what that makes us)?

if so, MARK your ESP packets in MANGLE PREROUTING, and use the mark to identify decrypted packets in your filter rules.

hundreds of examples of this can be found through the list archives or google.

-j

--
"Lisa, if you don't like your job you don't strike. You just go in
there every day and do it really half-assed. That's the American way."
--The Simpsons