Skip to content

Commit

Permalink
Fix UDP header in IPSec NAT-Traversal. (#4125)
Browse files Browse the repository at this point in the history
* Fix UDP header in IPSec NAT-Traversal.

* Added tests for IPSec NAT-Traversal.
  • Loading branch information
ppachocki authored Oct 23, 2023
1 parent 4fefbb0 commit 9ca3cc9
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 4 deletions.
7 changes: 3 additions & 4 deletions scapy/layers/ipsec.py
Original file line number Diff line number Diff line change
Expand Up @@ -1046,17 +1046,16 @@ def _encrypt_esp(self, pkt, seq_num=None, iv=None, esn_en=None, esn=None):
ip_header /= nat_t_header

if ip_header.version == 4:
ip_header.len = len(ip_header) + len(esp)
del ip_header.len
del ip_header.chksum
ip_header = ip_header.__class__(raw(ip_header))
else:
ip_header.plen = len(ip_header.payload) + len(esp)
del ip_header.plen

# sequence number must always change, unless specified by the user
if seq_num is None:
self.seq_num += 1

return ip_header / esp
return ip_header.__class__(raw(ip_header / esp))

def _encrypt_ah(self, pkt, seq_num=None, esn_en=False, esn=0):

Expand Down
83 changes: 83 additions & 0 deletions test/scapy/layers/ipsec.uts
Original file line number Diff line number Diff line change
Expand Up @@ -3277,6 +3277,89 @@ try:
except IPSecIntegrityError as err:
err

###############################################################################
+ IPv4 / UDP / ESP - NAT-Traversal

#######################################
= IPv4 / UDP / ESP - NAT-Traversal - Tunnel
~ -crypto

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw('testdata')
p = IP(raw(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
crypt_algo='NULL', crypt_key=None,
auth_algo='NULL', auth_key=None,
tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'),
nat_t_header=UDP(dport=5000))

e = sa.encrypt(p)
e

assert isinstance(e, IP)
* after encryption packet should be encapsulated with the given ip tunnel header
assert e.src == '11.11.11.11' and e.dst == '22.22.22.22'
assert e.chksum != p.chksum
* the encrypted packet should have an UDP layer
assert e.proto == socket.IPPROTO_UDP
assert e.haslayer(UDP)
assert e[UDP].sport == 4500
assert e[UDP].dport == 5000
assert e[UDP].chksum == 0
assert e.haslayer(ESP)
assert not e.haslayer(TCP)
assert e[ESP].spi == sa.spi
assert b'testdata' in e[ESP].data

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert d[TCP] == p[TCP]

#######################################
= IPv4 / UDP / ESP - NAT-Traversal - Transport
~ -crypto

import socket

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw('testdata')
p = IP(raw(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
crypt_algo='NULL', crypt_key=None,
auth_algo='NULL', auth_key=None,
nat_t_header=UDP(dport=5000))

e = sa.encrypt(p)
e

assert isinstance(e, IP)
assert e.src == '1.1.1.1' and e.dst == '2.2.2.2'
assert e.chksum != p.chksum
* the encrypted packet should have an UDP layer
assert e.proto == socket.IPPROTO_UDP
assert e.haslayer(UDP)
assert e[UDP].sport == 4500
assert e[UDP].dport == 5000
assert e[UDP].chksum == 0
assert e.haslayer(ESP)
assert not e.haslayer(TCP)
assert e[ESP].spi == sa.spi
assert b'testdata' in e[ESP].data

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert d[TCP] == p[TCP]

###############################################################################
+ IPv6 / ESP

Expand Down

0 comments on commit 9ca3cc9

Please sign in to comment.