Welcome to ike’s documentation!¶
Contents:
About ike¶
The goal of this project is to be a minimalistic IKEv2 (RFC 5996) implementation in Python.
Status¶
This project is in early stages. Use at own risk.
It will make your IP stack talk ESP to the remote peer.
What it can do:
- Act as an initiator
- Authenticate itself and peer using raw RSA keys.
- Install ESP SAs and SPD entries to use the key material via
setkey
command from ipsec-tools.
Limitations (hardcoded values):
- Cipher algorithm is Camellia in CBC mode with 256 bit keys.
- HMAC / Hash / PRF algorithm is SHA2/256.
- IKE group is Diffie-Hellman modp 14.
- Authentication (both own private and peer public) key file paths are hardcoded.
- ‘setkey’ syntax is of whatever the ipsec-tools on Debian 7.1 accept.
- Traffic selectors are myip:any:0-65535 <-> peerip:any:0-65535
Design principles¶
- Minimal amount of code.
- Support MUST features of draft-kivinen-ipsecme-ikev2-rfc5996bis-02 (RFC 5996 successor)
- Use strongest algorithms possible.
Documentation¶
You can read the Documentation at https://pythonhosted.org/ike
What this project is NOT going to be¶
- ISAKMP (IKEv1) RFC 2409 compliant
- IPSec data plane / ESP protocol
License¶
- MIT License
ike package¶
Subpackages¶
ike.util package¶
Submodules¶
ike.util.cipher module¶
-
class
ike.util.cipher.
Camellia
(key, iv=None)¶ Bases:
ike.util.cipher._Cipher
-
ike.util.cipher.
pad
(data, blocksize=16)¶ Pads data to blocksize according to RFC 4303. Pad length field is included in output.
ike.util.dh module¶
ike.util.dump module¶
-
ike.util.dump.
dump
(src)¶ Returns data in hex format in groups of 4 octets delimited by spaces for debugging purposes.
ike.util.external module¶
-
ike.util.external.
run_setkey
(input)¶ Runs a script through the ‘setkey’ command that is a user space insterface for PFKEY. :param input: setkey configuration file contents.
ike.util.prf module¶
-
ike.util.prf.
prf
(key, data, hash_algorithm='sha256')¶
-
ike.util.prf.
prfplus
(key, data, n)¶
ike.util.pubkey module¶
-
ike.util.pubkey.
sign
(data, filename, hash_alg='SHA-256')¶
-
ike.util.pubkey.
verify
(data, signature, filename)¶
Module contents¶
Submodules¶
ike.const module¶
-
class
ike.const.
ExchangeType
¶ Bases:
enum.IntEnum
An enumeration.
-
CREATE_CHILD_SA
= 36¶
-
IKE_AUTH
= 35¶
-
IKE_SA_INIT
= 34¶
-
INFORMATIONAL
= 37¶
-
-
class
ike.const.
MessageType
¶ Bases:
enum.IntEnum
An enumeration.
-
ADDITIONAL_IP4_ADDRESS
= 16397¶
-
ADDITIONAL_IP6_ADDRESS
= 16398¶
-
ADDITIONAL_TS_POSSIBLE
= 16386¶
-
ANOTHER_AUTH_FOLLOWS
= 16405¶
-
AUTHENTICATION_FAILED
= 24¶
-
AUTHORIZATION_FAILED
= 46¶
-
AUTH_LIFETIME
= 16403¶
-
CHILDLESS_IKEV2_SUPPORTED
= 16418¶
-
CHILD_SA_NOT_FOUND
= 44¶
-
COOKIE
= 16390¶
-
COOKIE2
= 16401¶
-
EAP_ONLY_AUTHENTICATION
= 16417¶
-
ERX_SUPPORTED
= 16427¶
-
ESP_TFC_PADDING_NOT_SUPPORTED
= 16394¶
-
FAILED_CP_REQUIRED
= 37¶
-
HTTP_CERT_LOOKUP_SUPPORTED
= 16392¶
-
IFOM_CAPABILITY
= 16428¶
-
IKEV2_MESSAGE_ID_SYNC
= 16422¶
-
IKEV2_MESSAGE_ID_SYNC_SUPPORTED
= 16420¶
-
INITIAL_CONTACT
= 16384¶
-
INTERNAL_ADDRESS_FAILURE
= 36¶
-
INVALID_GROUP_ID
= 45¶
-
INVALID_IKE_SPI
= 4¶
-
INVALID_KE_PAYLOAD
= 17¶
-
INVALID_MAJOR_VERSION
= 5¶
-
INVALID_MESSAGE_ID
= 9¶
-
INVALID_SELECTORS
= 39¶
-
INVALID_SPI
= 11¶
-
INVALID_SYNTAX
= 7¶
-
IPCOMP_SUPPORTED
= 16387¶
-
IPSEC_REPLAY_COUNTER_SYNC
= 16423¶
-
IPSEC_REPLAY_COUNTER_SYNC_SUPPORTED
= 16421¶
-
LINK_ID
= 16414¶
-
MOBIKE_SUPPORTED
= 16396¶
-
MULTIPLE_AUTH_SUPPORTED
= 16404¶
-
NAT_DETECTION_DESTINATION_IP
= 16389¶
-
NAT_DETECTION_SOURCE_IP
= 16388¶
-
NON_FIRST_FRAGMENTS_ALSO
= 16395¶
-
NO_ADDITIONAL_ADDRESSES
= 16399¶
-
NO_ADDITIONAL_SAS
= 35¶
-
NO_NATS_ALLOWED
= 16402¶
-
NO_PROPOSAL_CHOSEN
= 14¶
-
PSK_CONFIRM
= 16426¶
-
PSK_PERSIST
= 16425¶
-
QUICK_CRASH_DETECTION
= 16419¶
-
REDIRECT
= 16407¶
-
REDIRECTED_FROM
= 16408¶
-
REDIRECT_SUPPORTED
= 16406¶
-
REKEY_SA
= 16393¶
-
ROHC_SUPPORTED
= 16416¶
-
Reserved
= 0¶
-
SECURE_PASSWORD_METHODS
= 16424¶
-
SENDER_REQUEST_ID
= 16429¶
-
SET_WINDOW_SIZE
= 16385¶
-
SINGLE_PAIR_REQUIRED
= 34¶
-
TEMPORARY_FAILURE
= 43¶
-
TICKET_ACK
= 16411¶
-
TICKET_LT_OPAQUE
= 16409¶
-
TICKET_NACK
= 16412¶
-
TICKET_OPAQUE
= 16413¶
-
TICKET_REQUEST
= 16410¶
-
TS_UNACCEPTABLE
= 38¶
-
UNACCEPTABLE_ADDRESSES
= 40¶
-
UNEXPECTED_NAT_DETECTED
= 41¶
-
UNSUPPORTED_CRITICAL_PAYLOAD
= 1¶
-
UPDATE_SA_ADDRESSES
= 16400¶
-
USE_ASSIGNED_HoA
= 42¶
-
USE_TRANSPORT_MODE
= 16391¶
-
USE_WESP_MODE
= 16415¶
-
ike.initiator module¶
IKE v2 (RFC 5996) initiator implementation
- Usage:
- initiator.py <remote_peer>
To clean up afterwards,
setkey -FP && setkey -F
-
class
ike.initiator.
IKEInitiator
¶ Bases:
asyncio.protocols.DatagramProtocol
Implements an IKE initiator that attempt to negotiate a single child SA to remote peer.
-
connectionRefused
()¶
-
connection_made
(transport)¶
-
datagram_received
(data, address)¶
-
-
ike.initiator.
main
(peer)¶
ike.payloads module¶
IKEv2 Payloads as specified in RFC 5996 sections 3.2 - 3.16
-
class
ike.payloads.
AUTH
(signed_octets=None, data=None, next_payload=<no_next_payload: 0>, critical=False)¶ Bases:
ike.payloads._IkePayload
-
class
ike.payloads.
Fragment
(data=None, next_payload=<no_next_payload: 0>, critical=False, fragment=None)¶ Bases:
ike.payloads._IkePayload
Fragment Payload
-
parse
(data)¶
-
-
class
ike.payloads.
IDi
(data=None, next_payload=<no_next_payload: 0>, critical=False)¶ Bases:
ike.payloads._IkePayload
Identification Payload for initiator
-
class
ike.payloads.
IDr
(data=None, next_payload=<no_next_payload: 0>, critical=False)¶ Bases:
ike.payloads._IkePayload
Identification Payload for responder
-
class
ike.payloads.
KE
(data=None, next_payload=<no_next_payload: 0>, critical=False, group=14, diffie_hellman=None)¶ Bases:
ike.payloads._IkePayload
-
parse
(data)¶
-
-
class
ike.payloads.
Nonce
(data=None, next_payload=<no_next_payload: 0>, critical=False, nonce=None)¶ Bases:
ike.payloads._IkePayload
-
parse
(data)¶
-
-
class
ike.payloads.
Notify
(notify_type=None, data=None, next_payload=<no_next_payload: 0>, critical=False)¶ Bases:
ike.payloads._IkePayload
-
parse
(data)¶
-
-
class
ike.payloads.
SA
(data=None, proposals=None, next_payload=<no_next_payload: 0>, critical=False)¶ Bases:
ike.payloads._IkePayload
-
parse
(data)¶
-
-
class
ike.payloads.
SK
(data=None, next_payload=<no_next_payload: 0>, critical=False, iv=None, ciphertext=None)¶ Bases:
ike.payloads._IkePayload
-
mac
(hmac)¶
-
-
class
ike.payloads.
TSi
(addr=None, data=None, next_payload=<no_next_payload: 0>, critical=False)¶ Bases:
ike.payloads._TS
Traffic Selector Payload for initiator
-
class
ike.payloads.
TSr
(addr=None, data=None, next_payload=<no_next_payload: 0>, critical=False)¶ Bases:
ike.payloads._TS
Traffic Selector Payload for responder
-
class
ike.payloads.
Type
¶ Bases:
enum.IntEnum
Payload types from IANA
-
AUTH
= 39¶
-
CERT
= 37¶
-
CERTREQ
= 38¶
-
CP
= 47¶
-
Delete
= 42¶
-
EAP
= 48¶
-
Fragment
= 132¶
-
GSA
= 51¶
-
GSPM
= 49¶
-
IDg
= 50¶
-
IDi
= 35¶
-
IDr
= 36¶
-
KD
= 52¶
-
KE
= 34¶
-
Ni
= 40¶
-
Nonce
= 40¶
-
Notify
= 41¶
-
Nr
= 40¶
-
SA
= 33¶
-
SK
= 46¶
-
TSi
= 44¶
-
TSr
= 45¶
-
Vendor
= 43¶
-
no_next_payload
= 0¶
-
-
class
ike.payloads.
Vendor
(data=None, next_payload=<no_next_payload: 0>, critical=False, vendor=None)¶ Bases:
ike.payloads._IkePayload
-
parse
(data)¶
-
-
ike.payloads.
get_by_type
(payload_type)¶ Returns an IkePayload (sub)class based on the RFC5996 payload_type :param payload_type: int() Ike Payload type
ike.proposal module¶
Implements Proposal and Transform substructures for Security association (SA) payloads.
Conforms to RFC5996 section 3.3
ike.protocol module¶
High level interface to IKEv2 protocol
-
class
ike.protocol.
IKE
(address, peer, dh_group=14, nonce_len=32)¶ Bases:
object
A single IKE negotiation / SA.
Currently implements only Initiator side of the negotiation.
-
auth_recv
()¶ Handle peer’s IKE_AUTH response.
-
auth_send
()¶ Generates the second (IKE_AUTH) packet for Initiator
Returns: bytes() containing a valid IKE_INIT packet
-
authenticate_peer
(auth_data, peer_id, message)¶ Verifies the peers authentication.
-
decrypt
(data)¶ Decrypts an encrypted (SK, 46) IKE payload using self.SK_er
Parameters: data – Encrypted IKE payload including headers (payloads.SK()) Returns: next_payload, data_containing_payloads Raises: IkeError – If packet is corrupted.
-
encrypt_and_hmac
(packet)¶ Encrypts and signs a Packet() using self.SK_ei and self.SK_ai
Parameters: packet – Unecrypted Packet() with one or more payloads. Returns: Encrypted and signed Packet() with a single payloads.SK
-
init_recv
()¶ Parses the IKE_INIT response packet received from Responder.
Assigns the correct values of rSPI and Nr Calculates Diffie-Hellman exchange and assigns all keys to self.
-
init_send
()¶ Generates the first (IKE_INIT) packet for Initiator
Returns: bytes() containing a valid IKE_INIT packet
-
install_ipsec_sas
()¶
-
-
exception
ike.protocol.
IkeError
¶ Bases:
Exception
-
class
ike.protocol.
Packet
(data=None, exchange_type=None, message_id=0, iSPI=0, rSPI=0)¶ Bases:
object
An IKE packet.
To generate packets:
- instantiate an Packet()
- add payloads by Packet.add_payload(<payloads.IkePayload instance>)
- send bytes(Packet) to other peer.
Received packets should be generated by IKE.parse_packet().
-
add_payload
(payload)¶ Adds a payload to packet, updating last payload’s next_payload field