From ec503ade58d3c84169f0517e79e9d2ecd6bd1949 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 20 Sep 2013 08:43:46 +0200 Subject: [PATCH 1/5] libipsec: Add possibility to relay acquire events Keeping it simple and just forwarding the reqid. --- src/libipsec/ipsec_event_listener.h | 10 +++- src/libipsec/ipsec_event_relay.c | 73 ++++++++++++++++++++--------- src/libipsec/ipsec_event_relay.h | 8 ++++ 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/src/libipsec/ipsec_event_listener.h b/src/libipsec/ipsec_event_listener.h index c8b6db80e..5d53109df 100644 --- a/src/libipsec/ipsec_event_listener.h +++ b/src/libipsec/ipsec_event_listener.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2013 Tobias Brunner * * Copyright (C) secunet Security Networks AG * @@ -25,6 +25,7 @@ typedef struct ipsec_event_listener_t ipsec_event_listener_t; #include +#include /** * Listener interface for IPsec events @@ -42,6 +43,13 @@ struct ipsec_event_listener_t { * @param hard TRUE if this is a hard expire, FALSE otherwise */ void (*expire)(uint8_t protocol, uint32_t spi, host_t *dst, bool hard); + + /** + * Called when no IPsec SA is found for an outbound policy + * + * @param reqid reqid of the policy for which to acquire an SA + */ + void (*acquire)(uint32_t reqid); }; #endif /** IPSEC_EVENT_LISTENER_H_ @}*/ diff --git a/src/libipsec/ipsec_event_relay.c b/src/libipsec/ipsec_event_relay.c index 6317089e1..0f10795d1 100644 --- a/src/libipsec/ipsec_event_relay.c +++ b/src/libipsec/ipsec_event_relay.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2013 Tobias Brunner * Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Ralf Sager * @@ -63,33 +63,30 @@ typedef struct { */ enum { IPSEC_EVENT_EXPIRE, + IPSEC_EVENT_ACQUIRE, } type; /** - * Protocol of the SA - */ - uint8_t protocol; - - /** - * SPI of the SA, if any - */ - uint32_t spi; - - /** - * SA destination address - */ - host_t *dst; - - /** - * Additional data for specific event types + * Data for specific event types */ union { struct { + /** Protocol of the SA */ + uint8_t protocol; + /** SPI of the SA */ + uint32_t spi; + /** SA destination address */ + host_t *dst; /** TRUE in case of a hard expire */ bool hard; } expire; + struct { + /** Reqid of the SA */ + uint32_t reqid; + } acquire; + } data; } ipsec_event_t; @@ -99,7 +96,14 @@ typedef struct { */ static void ipsec_event_destroy(ipsec_event_t *event) { - event->dst->destroy(event->dst); + switch (event->type) + { + case IPSEC_EVENT_EXPIRE: + event->data.expire.dst->destroy(event->data.expire.dst); + break; + case IPSEC_EVENT_ACQUIRE: + break; + } free(event); } @@ -123,10 +127,18 @@ static job_requeue_t handle_events(private_ipsec_event_relay_t *this) case IPSEC_EVENT_EXPIRE: if (current->expire) { - current->expire(event->protocol, event->spi, event->dst, + current->expire(event->data.expire.protocol, + event->data.expire.spi, + event->data.expire.dst, event->data.expire.hard); } break; + case IPSEC_EVENT_ACQUIRE: + if (current->acquire) + { + current->acquire(event->data.acquire.reqid); + } + break; } } enumerator->destroy(enumerator); @@ -143,11 +155,11 @@ METHOD(ipsec_event_relay_t, expire, void, INIT(event, .type = IPSEC_EVENT_EXPIRE, - .protocol = protocol, - .spi = spi, - .dst = dst->clone(dst), .data = { .expire = { + .protocol = protocol, + .spi = spi, + .dst = dst->clone(dst), .hard = hard, }, }, @@ -155,6 +167,22 @@ METHOD(ipsec_event_relay_t, expire, void, this->queue->enqueue(this->queue, event); } +METHOD(ipsec_event_relay_t, acquire, void, + private_ipsec_event_relay_t *this, uint32_t reqid) +{ + ipsec_event_t *event; + + INIT(event, + .type = IPSEC_EVENT_ACQUIRE, + .data = { + .acquire = { + .reqid = reqid, + }, + }, + ); + this->queue->enqueue(this->queue, event); +} + METHOD(ipsec_event_relay_t, register_listener, void, private_ipsec_event_relay_t *this, ipsec_event_listener_t *listener) { @@ -190,6 +218,7 @@ ipsec_event_relay_t *ipsec_event_relay_create() INIT(this, .public = { .expire = _expire, + .acquire = _acquire, .register_listener = _register_listener, .unregister_listener = _unregister_listener, .destroy = _destroy, diff --git a/src/libipsec/ipsec_event_relay.h b/src/libipsec/ipsec_event_relay.h index 16bf3d95a..ee484f879 100644 --- a/src/libipsec/ipsec_event_relay.h +++ b/src/libipsec/ipsec_event_relay.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Ralf Sager * @@ -47,6 +48,13 @@ struct ipsec_event_relay_t { void (*expire)(ipsec_event_relay_t *this, uint8_t protocol, uint32_t spi, host_t *dst, bool hard); + /** + * Raise an acquire event. + * + * @param reqid reqid of the policy for which to acquire an SA + */ + void (*acquire)(ipsec_event_relay_t *this, uint32_t reqid); + /** * Register a listener to events raised by this manager * From 4e9acf98d0e2e256e8994b94361d653c1c019f31 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 4 May 2023 14:20:09 +0200 Subject: [PATCH 2/5] ipsec-sa-mgr: Optionally keep track of acquires for outbound SAs Currently just based on the reqid. An acquire for the same reqid is triggered at most every 10 seconds (gets ignored in trap_manager_t if the SA is still getting established). Entries are only cleaned up if an SA is eventually installed (similar to the allocated SPIs). Should that ever be a problem, we could probably schedule a job that regularly flushes old entries. --- src/libipsec/ipsec_processor.c | 2 +- src/libipsec/ipsec_sa_mgr.c | 103 ++++++++++++++++++++++++++++++--- src/libipsec/ipsec_sa_mgr.h | 9 ++- 3 files changed, 102 insertions(+), 12 deletions(-) diff --git a/src/libipsec/ipsec_processor.c b/src/libipsec/ipsec_processor.c index bf13fb885..80b25e01a 100644 --- a/src/libipsec/ipsec_processor.c +++ b/src/libipsec/ipsec_processor.c @@ -208,7 +208,7 @@ static job_requeue_t process_outbound(private_ipsec_processor_t *this) } sa = ipsec->sas->checkout_by_reqid(ipsec->sas, policy->get_reqid(policy), - FALSE); + FALSE, NULL); if (!sa) { /* TODO-IPSEC: send an acquire to upper layer */ DBG1(DBG_ESP, "could not find an outbound IPsec SA for reqid {%u}, " diff --git a/src/libipsec/ipsec_sa_mgr.c b/src/libipsec/ipsec_sa_mgr.c index ab6a2f079..12f5fc141 100644 --- a/src/libipsec/ipsec_sa_mgr.c +++ b/src/libipsec/ipsec_sa_mgr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2017 Tobias Brunner + * Copyright (C) 2012-2023 Tobias Brunner * Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Ralf Sager * @@ -27,6 +27,12 @@ #include #include +/** + * Timeout in seconds for acquries for the same reqid (i.e. the interval used + * to trigger acquires while no SA is established). + */ +#define ACQUIRE_TIMEOUT 10 + typedef struct private_ipsec_sa_mgr_t private_ipsec_sa_mgr_t; /** @@ -49,6 +55,11 @@ struct private_ipsec_sa_mgr_t { */ hashtable_t *allocated_spis; + /** + * Pending acquires (uint32_t => acquire_entry_t) + */ + hashtable_t *acquires; + /** * Mutex used to synchronize access to the SA manager */ @@ -90,7 +101,7 @@ typedef struct { */ bool awaits_deletion; -} ipsec_sa_entry_t; +} ipsec_sa_entry_t; /** * Helper struct for expiration events @@ -119,15 +130,32 @@ typedef struct { } ipsec_sa_expired_t; -/* - * Used for the hash table of allocated SPIs +/** + * Struct to keep track of acquires */ -static bool spi_equals(uint32_t *spi, uint32_t *other_spi) +typedef struct { + + /** + * Reqid of this acquire + */ + uint32_t reqid; + + /** + * Time the entry was created or updated + */ + time_t triggered; + +} acquire_entry_t; + +/** + * Used for the hash table of allocated SPIs and pending acquires + */ +static bool uint32_equals(const uint32_t *spi, const uint32_t *other_spi) { return *spi == *other_spi; } -static u_int spi_hash(uint32_t *spi) +static u_int uint32_hash(const uint32_t *spi) { return chunk_hash(chunk_from_thing(*spi)); } @@ -508,6 +536,10 @@ METHOD(ipsec_sa_mgr_t, add_sa, status_t, spi_alloc = this->allocated_spis->remove(this->allocated_spis, &spi); free(spi_alloc); } + if (!inbound) + { /* remove any acquires for outbound SAs */ + free(this->acquires->remove(this->acquires, &reqid)); + } if (this->sas->find_first(this->sas, match_entry_by_spi_src_dst_cb, NULL, spi, src, dst)) @@ -620,8 +652,53 @@ METHOD(ipsec_sa_mgr_t, del_sa, status_t, return FAILED; } +/** + * Remove all acquires + */ +static void flush_acquires(private_ipsec_sa_mgr_t *this) +{ + enumerator_t *enumerator; + acquire_entry_t *entry; + + DBG2(DBG_ESP, "flushing acquires"); + enumerator = this->acquires->create_enumerator(this->acquires); + while (enumerator->enumerate(enumerator, NULL, (void**)&entry)) + { + this->acquires->remove_at(this->acquires, enumerator); + DBG2(DBG_ESP, " removed acquire for reqid {%u}", entry->reqid); + free(entry); + } + enumerator->destroy(enumerator); +} + +/** + * Check whether an acquire should be sent for the given reqid. + */ +static bool check_acquire(private_ipsec_sa_mgr_t *this, uint32_t reqid) +{ + acquire_entry_t *entry; + time_t now; + + now = time_monotonic(NULL); + + entry = this->acquires->get(this->acquires, &reqid); + if (!entry) + { + INIT(entry, + .reqid = reqid, + ); + this->acquires->put(this->acquires, &entry->reqid, entry); + } + else if (now - entry->triggered <= ACQUIRE_TIMEOUT) + { + return FALSE; + } + entry->triggered = now; + return TRUE; +} + METHOD(ipsec_sa_mgr_t, checkout_by_reqid, ipsec_sa_t*, - private_ipsec_sa_mgr_t *this, uint32_t reqid, bool inbound) + private_ipsec_sa_mgr_t *this, uint32_t reqid, bool inbound, bool *acquire) { ipsec_sa_entry_t *entry; ipsec_sa_t *sa = NULL; @@ -633,6 +710,10 @@ METHOD(ipsec_sa_mgr_t, checkout_by_reqid, ipsec_sa_t*, { sa = entry->sa; } + if (!sa && acquire) + { + *acquire = !inbound && check_acquire(this, reqid); + } this->mutex->unlock(this->mutex); return sa; } @@ -687,9 +768,11 @@ METHOD(ipsec_sa_mgr_t, destroy, void, this->mutex->lock(this->mutex); flush_entries(this); flush_allocated_spis(this); + flush_acquires(this); this->mutex->unlock(this->mutex); this->allocated_spis->destroy(this->allocated_spis); + this->acquires->destroy(this->acquires); this->sas->destroy(this->sas); this->mutex->destroy(this->mutex); @@ -719,8 +802,10 @@ ipsec_sa_mgr_t *ipsec_sa_mgr_create() }, .sas = linked_list_create(), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), - .allocated_spis = hashtable_create((hashtable_hash_t)spi_hash, - (hashtable_equals_t)spi_equals, 16), + .allocated_spis = hashtable_create((hashtable_hash_t)uint32_hash, + (hashtable_equals_t)uint32_equals, 16), + .acquires = hashtable_create((hashtable_hash_t)uint32_hash, + (hashtable_equals_t)uint32_equals, 16), ); return &this->public; diff --git a/src/libipsec/ipsec_sa_mgr.h b/src/libipsec/ipsec_sa_mgr.h index 549b9f22b..957de5f46 100644 --- a/src/libipsec/ipsec_sa_mgr.h +++ b/src/libipsec/ipsec_sa_mgr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2023 Tobias Brunner * Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Ralf Sager * @@ -174,12 +174,17 @@ struct ipsec_sa_mgr_t { * Since other threads may be waiting for a checked out SA, it should be * checked in as soon as possible after use. * + * If no matching outbound SA is found, acquire indicates if an acquire + * should be sent for the given reqid. + * * @param reqid reqid of the SA * @param inbound TRUE for an inbound SA, FALSE for an outbound SA + * @param[out] acquire TRUE if an acquire should be triggered, FALSE if one + * is already pending or an SA was found * @return the matching IPsec SA, or NULL if none is found */ ipsec_sa_t *(*checkout_by_reqid)(ipsec_sa_mgr_t *this, uint32_t reqid, - bool inbound); + bool inbound, bool *acquire); /** * Checkin an SA after use. From 9192ef16209a6f65fd348218e4565c40411e6f3a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 4 May 2023 14:32:49 +0200 Subject: [PATCH 3/5] ipsec-processor: Trigger acquire if no matching outbound SA is found --- src/libipsec/ipsec_processor.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/libipsec/ipsec_processor.c b/src/libipsec/ipsec_processor.c index 80b25e01a..11c587c93 100644 --- a/src/libipsec/ipsec_processor.c +++ b/src/libipsec/ipsec_processor.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2023 Tobias Brunner * * Copyright (C) secunet Security Networks AG * @@ -194,6 +194,7 @@ static job_requeue_t process_outbound(private_ipsec_processor_t *this) ip_packet_t *packet; ipsec_sa_t *sa; host_t *src, *dst; + bool acquire = FALSE; packet = (ip_packet_t*)this->outbound_queue->dequeue(this->outbound_queue); @@ -208,11 +209,22 @@ static job_requeue_t process_outbound(private_ipsec_processor_t *this) } sa = ipsec->sas->checkout_by_reqid(ipsec->sas, policy->get_reqid(policy), - FALSE, NULL); + FALSE, &acquire); if (!sa) - { /* TODO-IPSEC: send an acquire to upper layer */ - DBG1(DBG_ESP, "could not find an outbound IPsec SA for reqid {%u}, " - "dropping packet", policy->get_reqid(policy)); + { + if (acquire) + { + DBG1(DBG_ESP, "could not find an outbound IPsec SA for reqid {%u}, " + "dropping packet and triggering acquire", + policy->get_reqid(policy)); + ipsec->events->acquire(ipsec->events, policy->get_reqid(policy)); + } + else + { + DBG2(DBG_ESP, "could not find an outbound IPsec SA for reqid {%u}, " + "dropping packet while acquire is pending", + policy->get_reqid(policy)); + } packet->destroy(packet); policy->destroy(policy); return JOB_REQUEUE_DIRECT; From b0eb88f7032e6655ffaea7e6f4a72e0f9e50e2a0 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 4 May 2023 14:42:53 +0200 Subject: [PATCH 4/5] kernel-libipsec: Forward acquires from libipsec to the daemon --- .../plugins/kernel_libipsec/kernel_libipsec_ipsec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c index d067ed58e..8df2e3dbc 100644 --- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c +++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c @@ -228,6 +228,16 @@ static void expire(uint8_t protocol, uint32_t spi, host_t *dst, bool hard) charon->kernel->expire(charon->kernel, protocol, spi, dst, hard); } +/** + * Acquire callback + */ +static void acquire(uint32_t reqid) +{ + kernel_acquire_data_t data = {}; + + charon->kernel->acquire(charon->kernel, reqid, &data); +} + METHOD(kernel_ipsec_t, get_features, kernel_feature_t, private_kernel_libipsec_ipsec_t *this) { @@ -681,6 +691,7 @@ kernel_libipsec_ipsec_t *kernel_libipsec_ipsec_create() }, .ipsec_listener = { .expire = expire, + .acquire = acquire, }, .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .policies = linked_list_create(), From cb049e14c8e59c2a366440f66040879ffcbd0950 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 4 May 2023 16:00:37 +0200 Subject: [PATCH 5/5] testing: Add libipsec/net2net-trap scenario --- .../libipsec/net2net-trap/description.txt | 11 ++++ .../tests/libipsec/net2net-trap/evaltest.dat | 8 +++ .../hosts/moon/etc/strongswan.conf | 10 ++++ .../hosts/moon/etc/swanctl/swanctl.conf | 30 ++++++++++ .../net2net-trap/hosts/moon/etc/updown | 59 +++++++++++++++++++ .../hosts/sun/etc/strongswan.conf | 10 ++++ .../hosts/sun/etc/swanctl/swanctl.conf | 30 ++++++++++ .../net2net-trap/hosts/sun/etc/updown | 59 +++++++++++++++++++ .../tests/libipsec/net2net-trap/posttest.dat | 5 ++ .../tests/libipsec/net2net-trap/pretest.dat | 9 +++ testing/tests/libipsec/net2net-trap/test.conf | 25 ++++++++ 11 files changed, 256 insertions(+) create mode 100644 testing/tests/libipsec/net2net-trap/description.txt create mode 100644 testing/tests/libipsec/net2net-trap/evaltest.dat create mode 100644 testing/tests/libipsec/net2net-trap/hosts/moon/etc/strongswan.conf create mode 100755 testing/tests/libipsec/net2net-trap/hosts/moon/etc/swanctl/swanctl.conf create mode 100755 testing/tests/libipsec/net2net-trap/hosts/moon/etc/updown create mode 100644 testing/tests/libipsec/net2net-trap/hosts/sun/etc/strongswan.conf create mode 100755 testing/tests/libipsec/net2net-trap/hosts/sun/etc/swanctl/swanctl.conf create mode 100755 testing/tests/libipsec/net2net-trap/hosts/sun/etc/updown create mode 100644 testing/tests/libipsec/net2net-trap/posttest.dat create mode 100644 testing/tests/libipsec/net2net-trap/pretest.dat create mode 100644 testing/tests/libipsec/net2net-trap/test.conf diff --git a/testing/tests/libipsec/net2net-trap/description.txt b/testing/tests/libipsec/net2net-trap/description.txt new file mode 100644 index 000000000..bf128d1b2 --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/description.txt @@ -0,0 +1,11 @@ +A tunnel that will connect the subnets behind the gateways moon +and sun, respectively, is preconfigured by installing a trap policy +on gateway moon by means of the setting start_action = trap in swanctl.conf. +A subsequent ping issued by client alice behind gateway moon to +bob located behind gateway sun triggers an acquire and +leads to the automatic establishment of the subnet-to-subnet tunnel. +

+Upon the successful establishment of the IPsec tunnel, an updown script automatically +inserts iptables-based firewall rules that let pass the traffic tunneled via the +ipsec0 tun interface. In order to test both tunnel and firewall, client alice +behind gateway moon pings client bob located behind gateway sun. diff --git a/testing/tests/libipsec/net2net-trap/evaltest.dat b/testing/tests/libipsec/net2net-trap/evaltest.dat new file mode 100644 index 000000000..71d9fdc5a --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/evaltest.dat @@ -0,0 +1,8 @@ +moon::swanctl --list-pols --raw 2> /dev/null::net-net.*mode=TUNNEL local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES +moon::cat /var/log/daemon.log::could not find an outbound IPsec SA for reqid {1}, dropping packet and triggering acquire::YES +moon::cat /var/log/daemon.log::creating acquire job for policy with reqid {1}::YES +alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::YES +moon:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=4500 remote-id=sun.strongswan.org initiator=yes.*nat-remote=yes nat-any=yes encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net-net.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES +sun::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=4500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org.*nat-remote=yes nat-any=yes encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net-net.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES +sun::tcpdump::IP moon.strongswan.org.\(4500\|ipsec-nat-t\) > sun.strongswan.org.\(4500\|ipsec-nat-t\): UDP-encap: ESP::YES +sun::tcpdump::IP sun.strongswan.org.\(4500\|ipsec-nat-t\) > moon.strongswan.org.\(4500\|ipsec-nat-t\): UDP-encap: ESP::YES diff --git a/testing/tests/libipsec/net2net-trap/hosts/moon/etc/strongswan.conf b/testing/tests/libipsec/net2net-trap/hosts/moon/etc/strongswan.conf new file mode 100644 index 000000000..8ce7c2a78 --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/hosts/moon/etc/strongswan.conf @@ -0,0 +1,10 @@ +# /etc/strongswan.conf - strongSwan configuration file + +swanctl { + load = pem pkcs1 x509 revocation constraints pubkey openssl random +} + +charon-systemd { + load = random nonce aes sha1 sha2 gcm pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-libipsec kernel-netlink socket-default updown + multiple_authentication = no +} diff --git a/testing/tests/libipsec/net2net-trap/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/libipsec/net2net-trap/hosts/moon/etc/swanctl/swanctl.conf new file mode 100755 index 000000000..8c9121b93 --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/hosts/moon/etc/swanctl/swanctl.conf @@ -0,0 +1,30 @@ +connections { + + gw-gw { + local_addrs = 192.168.0.1 + remote_addrs = 192.168.0.2 + + local { + auth = pubkey + certs = moonCert.pem + id = moon.strongswan.org + } + remote { + auth = pubkey + id = sun.strongswan.org + } + children { + net-net { + local_ts = 10.1.0.0/16 + remote_ts = 10.2.0.0/16 + + start_action = trap + updown = /etc/updown + esp_proposals = aes128gcm128-x25519 + } + } + version = 2 + mobike = no + proposals = aes128-sha256-x25519 + } +} diff --git a/testing/tests/libipsec/net2net-trap/hosts/moon/etc/updown b/testing/tests/libipsec/net2net-trap/hosts/moon/etc/updown new file mode 100755 index 000000000..682ccc701 --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/hosts/moon/etc/updown @@ -0,0 +1,59 @@ +#!/bin/sh + +TUN_NAME=ipsec0 + +# use protocol specific options to set ports +case "$PLUTO_MY_PROTOCOL" in +1) # ICMP + ICMP_TYPE_OPTION="--icmp-type" + ;; +58) # ICMPv6 + ICMP_TYPE_OPTION="--icmpv6-type" + ;; +*) + ;; +esac + +# are there port numbers? +if [ "$PLUTO_MY_PORT" != 0 ] +then + if [ -n "$ICMP_TYPE_OPTION" ] + then + S_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT" + D_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT" + else + S_MY_PORT="--sport $PLUTO_MY_PORT" + D_MY_PORT="--dport $PLUTO_MY_PORT" + fi +fi +if [ "$PLUTO_PEER_PORT" != 0 ] +then + if [ -n "$ICMP_TYPE_OPTION" ] + then + # the syntax is --icmp[v6]-type type[/code], so add it to the existing option + S_MY_PORT="$S_MY_PORT/$PLUTO_PEER_PORT" + D_MY_PORT="$D_MY_PORT/$PLUTO_PEER_PORT" + else + S_PEER_PORT="--sport $PLUTO_PEER_PORT" + D_PEER_PORT="--dport $PLUTO_PEER_PORT" + fi +fi + +case "$PLUTO_VERB" in +up-client) + iptables -I FORWARD 1 -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \ + -s $PLUTO_MY_CLIENT $S_MY_PORT \ + -d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT + iptables -I FORWARD 1 -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \ + -s $PLUTO_PEER_CLIENT $S_PEER_PORT \ + -d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT + ;; +down-client) + iptables -D FORWARD -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \ + -s $PLUTO_MY_CLIENT $S_MY_PORT \ + -d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT + iptables -D FORWARD -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \ + -s $PLUTO_PEER_CLIENT $S_PEER_PORT \ + -d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT + ;; +esac diff --git a/testing/tests/libipsec/net2net-trap/hosts/sun/etc/strongswan.conf b/testing/tests/libipsec/net2net-trap/hosts/sun/etc/strongswan.conf new file mode 100644 index 000000000..8ce7c2a78 --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/hosts/sun/etc/strongswan.conf @@ -0,0 +1,10 @@ +# /etc/strongswan.conf - strongSwan configuration file + +swanctl { + load = pem pkcs1 x509 revocation constraints pubkey openssl random +} + +charon-systemd { + load = random nonce aes sha1 sha2 gcm pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-libipsec kernel-netlink socket-default updown + multiple_authentication = no +} diff --git a/testing/tests/libipsec/net2net-trap/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/libipsec/net2net-trap/hosts/sun/etc/swanctl/swanctl.conf new file mode 100755 index 000000000..60aca1d02 --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/hosts/sun/etc/swanctl/swanctl.conf @@ -0,0 +1,30 @@ +connections { + + gw-gw { + local_addrs = 192.168.0.2 + remote_addrs = 192.168.0.1 + + local { + auth = pubkey + certs = sunCert.pem + id = sun.strongswan.org + } + remote { + auth = pubkey + id = moon.strongswan.org + } + children { + net-net { + local_ts = 10.2.0.0/16 + remote_ts = 10.1.0.0/16 + + start_action = none + updown = /etc/updown + esp_proposals = aes128gcm128-x25519 + } + } + version = 2 + mobike = no + proposals = aes128-sha256-x25519 + } +} diff --git a/testing/tests/libipsec/net2net-trap/hosts/sun/etc/updown b/testing/tests/libipsec/net2net-trap/hosts/sun/etc/updown new file mode 100755 index 000000000..682ccc701 --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/hosts/sun/etc/updown @@ -0,0 +1,59 @@ +#!/bin/sh + +TUN_NAME=ipsec0 + +# use protocol specific options to set ports +case "$PLUTO_MY_PROTOCOL" in +1) # ICMP + ICMP_TYPE_OPTION="--icmp-type" + ;; +58) # ICMPv6 + ICMP_TYPE_OPTION="--icmpv6-type" + ;; +*) + ;; +esac + +# are there port numbers? +if [ "$PLUTO_MY_PORT" != 0 ] +then + if [ -n "$ICMP_TYPE_OPTION" ] + then + S_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT" + D_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT" + else + S_MY_PORT="--sport $PLUTO_MY_PORT" + D_MY_PORT="--dport $PLUTO_MY_PORT" + fi +fi +if [ "$PLUTO_PEER_PORT" != 0 ] +then + if [ -n "$ICMP_TYPE_OPTION" ] + then + # the syntax is --icmp[v6]-type type[/code], so add it to the existing option + S_MY_PORT="$S_MY_PORT/$PLUTO_PEER_PORT" + D_MY_PORT="$D_MY_PORT/$PLUTO_PEER_PORT" + else + S_PEER_PORT="--sport $PLUTO_PEER_PORT" + D_PEER_PORT="--dport $PLUTO_PEER_PORT" + fi +fi + +case "$PLUTO_VERB" in +up-client) + iptables -I FORWARD 1 -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \ + -s $PLUTO_MY_CLIENT $S_MY_PORT \ + -d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT + iptables -I FORWARD 1 -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \ + -s $PLUTO_PEER_CLIENT $S_PEER_PORT \ + -d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT + ;; +down-client) + iptables -D FORWARD -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \ + -s $PLUTO_MY_CLIENT $S_MY_PORT \ + -d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT + iptables -D FORWARD -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \ + -s $PLUTO_PEER_CLIENT $S_PEER_PORT \ + -d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT + ;; +esac diff --git a/testing/tests/libipsec/net2net-trap/posttest.dat b/testing/tests/libipsec/net2net-trap/posttest.dat new file mode 100644 index 000000000..cc6a5bff7 --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/posttest.dat @@ -0,0 +1,5 @@ +moon::swanctl --terminate --ike gw-gw 2> /dev/null +moon::systemctl stop strongswan +sun::systemctl stop strongswan +moon::iptables-restore < /etc/iptables.flush +sun::iptables-restore < /etc/iptables.flush diff --git a/testing/tests/libipsec/net2net-trap/pretest.dat b/testing/tests/libipsec/net2net-trap/pretest.dat new file mode 100644 index 000000000..14336d93d --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/pretest.dat @@ -0,0 +1,9 @@ +moon::iptables-restore < /etc/iptables.rules +# allow traffic from local subnet via TUN device before SA is up +moon::iptables -I FORWARD -o ipsec0 -s 10.1.0.0/16 -d 10.2.0.0/16 -j ACCEPT +sun::iptables-restore < /etc/iptables.rules +moon::systemctl start strongswan +sun::systemctl start strongswan +moon::expect-connection gw-gw +sun::expect-connection gw-gw +alice::ping -c 3 -W 1 -i 0.2 PH_IP_BOB diff --git a/testing/tests/libipsec/net2net-trap/test.conf b/testing/tests/libipsec/net2net-trap/test.conf new file mode 100644 index 000000000..87abc763b --- /dev/null +++ b/testing/tests/libipsec/net2net-trap/test.conf @@ -0,0 +1,25 @@ +#!/bin/bash +# +# This configuration file provides information on the +# guest instances used for this test + +# All guest instances that are required for this test +# +VIRTHOSTS="alice moon winnetou sun bob" + +# Corresponding block diagram +# +DIAGRAM="a-m-w-s-b.png" + +# Guest instances on which tcpdump is to be started +# +TCPDUMPHOSTS="sun" + +# Guest instances on which IPsec is started +# Used for IPsec logging purposes +# +IPSECHOSTS="moon sun" + +# charon controlled by swanctl +# +SWANCTL=1