scapy.layers.ipsec

IPsec layer

Example of use:

>>> sa = SecurityAssociation(ESP, spi=0xdeadbeef, crypt_algo='AES-CBC',
...                          crypt_key=b'sixteenbytes key')
>>> 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
<IP  version=4L ihl=5L tos=0x0 len=48 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0x74c2 src=1.1.1.1 dst=2.2.2.2 options=[] |<TCP  sport=45012 dport=http seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0x1914 urgptr=0 options=[] |<Raw  load='testdata' |>>>  # noqa: E501
>>>
>>> e = sa.encrypt(p)
>>> e
<IP  version=4L ihl=5L tos=0x0 len=76 id=1 flags= frag=0L ttl=64 proto=esp chksum=0x747a src=1.1.1.1 dst=2.2.2.2 |<ESP  spi=0xdeadbeef seq=1 data=b'\xf8\xdb\x1e\x83[T\xab\\\xd2\x1b\xed\xd1\xe5\xc8Y\xc2\xa5d\x92\xc1\x05\x17\xa6\x92\x831\xe6\xc1]\x9a\xd6K}W\x8bFfd\xa5B*+\xde\xc8\x89\xbf{\xa9' |>>  # noqa: E501
>>>
>>> d = sa.decrypt(e)
>>> d
<IP  version=4L ihl=5L tos=0x0 len=48 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0x74c2 src=1.1.1.1 dst=2.2.2.2 |<TCP  sport=45012 dport=http seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0x1914 urgptr=0 options=[] |<Raw  load='testdata' |>>>  # noqa: E501
>>>
>>> d == p
True
class scapy.layers.ipsec.AH(_pkt, /, *, nh=None, payloadlen=None, reserved=None, spi=1, seq=0, icv=None, padding=None)[source]

Bases: Packet

Authentication Header

See https://tools.ietf.org/rfc/rfc4302.txt

aliastypes
fields_desc
Display RFC-like schema
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|       NH      |   PAYLOADLEN  |            RESERVED           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                              SPI                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                              SEQ                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|              ICV              |            PADDING            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                             Fig. AH                              
AH fields

nh

ByteEnumField

None

payloadlen

ByteField

None

reserved

ShortField

None

spi

XIntField

1

seq

IntField

0

icv

XStrLenField

None

padding

XStrLenField

None

payload_guess

Possible sublayers: IP, IPv6

class scapy.layers.ipsec.AuthAlgo(name, mac, digestmod, icv_size, key_size=None)[source]

Bases: object

IPsec integrity algorithm

check_key(key)[source]

Check that the key length is valid.

Parameters:

key – a byte string

new_mac(**kwargs: Any) Any[source]
sign(pkt, key, esn_en=False, esn=0)[source]

Sign an IPsec (ESP or AH) packet with this algo.

Parameters:
  • pkt – a packet that contains a valid encrypted ESP or AH layer

  • key – the authentication key, a byte string

  • esn_en – extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit

  • esn – extended sequence number (32 MSB)

Returns:

the signed packet

verify(pkt, key, esn_en=False, esn=0)[source]

Check that the integrity check value (icv) of a packet is valid.

Parameters:
  • pkt – a packet that contains a valid encrypted ESP or AH layer

  • key – the authentication key, a byte string

  • esn_en – extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit

  • esn – extended sequence number (32 MSB)

Raises:

scapy.layers.ipsec.IPSecIntegrityError – if the integrity check fails

class scapy.layers.ipsec.CryptAlgo(name, cipher, mode, block_size=None, iv_size=None, key_size=None, icv_size=None, salt_size=None, format_mode_iv=None)[source]

Bases: object

IPsec encryption algorithm

check_key(key)[source]

Check that the key length is valid.

Parameters:

key – a byte string

decrypt(sa, esp, key, icv_size=None, esn_en=False, esn=0)[source]

Decrypt an ESP packet

Parameters:
  • sa – the SecurityAssociation associated with the ESP packet.

  • esp – an encrypted ESP packet

  • key – the secret key used for encryption

  • icv_size – the length of the icv used for integrity check

  • esn_en – extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit when using an AEAD algorithm

  • esn – extended sequence number (32 MSB)

Returns:

a valid ESP packet encrypted with this algorithm

Raises:

scapy.layers.ipsec.IPSecIntegrityError – if the integrity check fails with an AEAD algorithm

encrypt(sa, esp, key, icv_size=None, esn_en=False, esn=0)[source]

Encrypt an ESP packet

Parameters:
  • sa – the SecurityAssociation associated with the ESP packet.

  • esp – an unencrypted _ESPPlain packet with valid padding

  • key – the secret key used for encryption

  • icv_size – the length of the icv used for integrity check

Esn_en:

extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit when using an AEAD algorithm

Esn:

extended sequence number (32 MSB)

Returns:

a valid ESP packet encrypted with this algorithm

generate_iv()[source]

Generate a random initialization vector.

new_cipher(**kwargs: Any) Any[source]
pad(esp)[source]

Add the correct amount of padding so that the data to encrypt is exactly a multiple of the algorithm’s block size.

Also, make sure that the total ESP packet length is a multiple of 4 bytes.

Parameters:

esp – an unencrypted _ESPPlain packet

Returns:

an unencrypted _ESPPlain packet with valid padding

class scapy.layers.ipsec.ESP(_pkt, /, *, spi=1, seq=0, data=None)[source]

Bases: Packet

Encapsulated Security Payload

See https://tools.ietf.org/rfc/rfc4303.txt

aliastypes
classmethod dispatch_hook(_pkt=None, *args, **kargs)[source]
fields_desc
Display RFC-like schema
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                              SPI                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                              SEQ                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|              DATA             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                             Fig. ESP                             
ESP fields

spi

XIntField

1

seq

IntField

0

data

XStrField

None

exception scapy.layers.ipsec.IPSecIntegrityError[source]

Bases: Exception

Error risen when the integrity check fails.

class scapy.layers.ipsec.NAT_KEEPALIVE(_pkt, /, *, nat_keepalive=255)[source]

Bases: Packet

aliastypes
fields_desc
Display RFC-like schema
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NAT KEEPALIVE |
+-+-+-+-+-+-+-+-+

                        Fig. NAT_KEEPALIVE                        
NAT_KEEPALIVE fields

nat_keepalive

XByteField

255

class scapy.layers.ipsec.NON_ESP(_pkt, /, *, non_esp=0)[source]

Bases: Packet

aliastypes
fields_desc
Display RFC-like schema
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            NON ESP                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                           Fig. NON_ESP                           
NON_ESP fields

non_esp

XIntField

0

payload_guess

Possible sublayers: IKEv2

class scapy.layers.ipsec.SecurityAssociation(proto, spi, seq_num=1, crypt_algo=None, crypt_key=None, crypt_icv_size=None, auth_algo=None, auth_key=None, tunnel_header=None, nat_t_header=None, esn_en=False, esn=0)[source]

Bases: object

This class is responsible of “encryption” and “decryption” of IPsec packets. # noqa: E501

SUPPORTED_PROTOS = (<class 'scapy.layers.inet.IP'>, <class 'scapy.layers.inet6.IPv6'>)
check_spi(pkt)[source]
decrypt(pkt, verify=True, esn_en=None, esn=None)[source]

Decrypt (and decapsulate) an IP(v6) packet containing ESP or AH.

Parameters:
  • pkt – the packet to decrypt

  • verify – if False, do not perform the integrity check

  • esn_en – extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit when using an AEAD algorithm

  • esn – extended sequence number (32 MSB)

Returns:

the decrypted/decapsulated packet

Raises:

scapy.layers.ipsec.IPSecIntegrityError – if the integrity check fails

encrypt(pkt, seq_num=None, iv=None, esn_en=None, esn=None)[source]

Encrypt (and encapsulate) an IP(v6) packet with ESP or AH according to this SecurityAssociation.

Parameters:
  • pkt – the packet to encrypt

  • seq_num – if specified, use this sequence number instead of the generated one

  • esn_en – extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit when using an AEAD algorithm

  • esn – extended sequence number (32 MSB)

  • iv – if specified, use this initialization vector for encryption instead of a random one.

Returns:

the encrypted/encapsulated packet

scapy.layers.ipsec.split_for_transport(orig_pkt, transport_proto)[source]

Split an IP(v6) packet in the correct location to insert an ESP or AH header.

Parameters:
  • orig_pkt – the packet to split. Must be an IP or IPv6 packet

  • transport_proto – the IPsec protocol number that will be inserted at the split position.

Returns:

a tuple (header, nh, payload) where nh is the protocol number of payload.

scapy.layers.ipsec.zero_mutable_fields(pkt, sending=False)[source]

When using AH, all “mutable” fields must be “zeroed” before calculating the ICV. See RFC 4302, Section 3.3.3.1. Handling Mutable Fields.

Parameters:
  • pkt – an IP(v6) packet containing an AH layer. NOTE: The packet will be modified

  • sending – if true, ipv6 routing headers will not be reordered