Skip to content

Commit 9ca3cc9

Browse files
authored
Fix UDP header in IPSec NAT-Traversal. (#4125)
* Fix UDP header in IPSec NAT-Traversal. * Added tests for IPSec NAT-Traversal.
1 parent 4fefbb0 commit 9ca3cc9

File tree

2 files changed

+86
-4
lines changed

2 files changed

+86
-4
lines changed

scapy/layers/ipsec.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,17 +1046,16 @@ def _encrypt_esp(self, pkt, seq_num=None, iv=None, esn_en=None, esn=None):
10461046
ip_header /= nat_t_header
10471047

10481048
if ip_header.version == 4:
1049-
ip_header.len = len(ip_header) + len(esp)
1049+
del ip_header.len
10501050
del ip_header.chksum
1051-
ip_header = ip_header.__class__(raw(ip_header))
10521051
else:
1053-
ip_header.plen = len(ip_header.payload) + len(esp)
1052+
del ip_header.plen
10541053

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

1059-
return ip_header / esp
1058+
return ip_header.__class__(raw(ip_header / esp))
10601059

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

test/scapy/layers/ipsec.uts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3277,6 +3277,89 @@ try:
32773277
except IPSecIntegrityError as err:
32783278
err
32793279

3280+
###############################################################################
3281+
+ IPv4 / UDP / ESP - NAT-Traversal
3282+
3283+
#######################################
3284+
= IPv4 / UDP / ESP - NAT-Traversal - Tunnel
3285+
~ -crypto
3286+
3287+
p = IP(src='1.1.1.1', dst='2.2.2.2')
3288+
p /= TCP(sport=45012, dport=80)
3289+
p /= Raw('testdata')
3290+
p = IP(raw(p))
3291+
p
3292+
3293+
sa = SecurityAssociation(ESP, spi=0x222,
3294+
crypt_algo='NULL', crypt_key=None,
3295+
auth_algo='NULL', auth_key=None,
3296+
tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'),
3297+
nat_t_header=UDP(dport=5000))
3298+
3299+
e = sa.encrypt(p)
3300+
e
3301+
3302+
assert isinstance(e, IP)
3303+
* after encryption packet should be encapsulated with the given ip tunnel header
3304+
assert e.src == '11.11.11.11' and e.dst == '22.22.22.22'
3305+
assert e.chksum != p.chksum
3306+
* the encrypted packet should have an UDP layer
3307+
assert e.proto == socket.IPPROTO_UDP
3308+
assert e.haslayer(UDP)
3309+
assert e[UDP].sport == 4500
3310+
assert e[UDP].dport == 5000
3311+
assert e[UDP].chksum == 0
3312+
assert e.haslayer(ESP)
3313+
assert not e.haslayer(TCP)
3314+
assert e[ESP].spi == sa.spi
3315+
assert b'testdata' in e[ESP].data
3316+
3317+
d = sa.decrypt(e)
3318+
d
3319+
3320+
* after decryption the original packet payload should be unaltered
3321+
assert d[TCP] == p[TCP]
3322+
3323+
#######################################
3324+
= IPv4 / UDP / ESP - NAT-Traversal - Transport
3325+
~ -crypto
3326+
3327+
import socket
3328+
3329+
p = IP(src='1.1.1.1', dst='2.2.2.2')
3330+
p /= TCP(sport=45012, dport=80)
3331+
p /= Raw('testdata')
3332+
p = IP(raw(p))
3333+
p
3334+
3335+
sa = SecurityAssociation(ESP, spi=0x222,
3336+
crypt_algo='NULL', crypt_key=None,
3337+
auth_algo='NULL', auth_key=None,
3338+
nat_t_header=UDP(dport=5000))
3339+
3340+
e = sa.encrypt(p)
3341+
e
3342+
3343+
assert isinstance(e, IP)
3344+
assert e.src == '1.1.1.1' and e.dst == '2.2.2.2'
3345+
assert e.chksum != p.chksum
3346+
* the encrypted packet should have an UDP layer
3347+
assert e.proto == socket.IPPROTO_UDP
3348+
assert e.haslayer(UDP)
3349+
assert e[UDP].sport == 4500
3350+
assert e[UDP].dport == 5000
3351+
assert e[UDP].chksum == 0
3352+
assert e.haslayer(ESP)
3353+
assert not e.haslayer(TCP)
3354+
assert e[ESP].spi == sa.spi
3355+
assert b'testdata' in e[ESP].data
3356+
3357+
d = sa.decrypt(e)
3358+
d
3359+
3360+
* after decryption the original packet payload should be unaltered
3361+
assert d[TCP] == p[TCP]
3362+
32803363
###############################################################################
32813364
+ IPv6 / ESP
32823365

0 commit comments

Comments
 (0)