testing: Add scenarios that use XFRM interfaces

The network namespace scenario requires a kernel patch in 4.19 and 4.20
kernels (the fix is included in 5.0 kernels).
This commit is contained in:
Tobias Brunner
2019-04-04 09:31:38 +02:00
parent 801a5d3133
commit 760d7c9b4f
31 changed files with 547 additions and 0 deletions
@@ -0,0 +1,22 @@
This scenario demonstrates a property of <b>XFRM interfaces</b> that allows
moving them into network namespaces while retaining access to IPsec SAs and
policies in the original namespace. This enables an IKE daemon in one namespace
to provide IPsec tunnels for processes in other namespaces without having to
give them access to the keys and IKE credentials.
<p/>
The gateways use <b>route-based forwarding</b> with <b>XFRM interfaces</b>, with
firewall rules to allow traffic to pass. The IPsec traffic selector used is
0.0.0.0/0, however, specific routing is achieved with routes on the XFRM
interfaces. The IKE daemon does not install routes for CHILD_SAs with outbound
interface ID, so static routes are installed for the target subnets.
<p/>
The XFRM interface on gateway <b>moon</b> is moved into a new network namespace
from which a ping is sent to client <b>bob</b>. It is then moved back out and
<b>alice</b> sends another ping to <b>bob</b> to test if that works too.
<p/>
Gateway <b>sun</b> dynamically creates the XFRM interface via updown script
using the passed unique generated interface ID.
<p/>
Note that the dropped packet seen on the <b>XFRM interface</b> on <b>moon</b>
is an IPv6 Router Solicitation (NDP) sent from that namespace, which doesn't
match the IPsec policy.
@@ -0,0 +1,18 @@
moon::swanctl --list-sas --ike-id 1 --raw 2> /dev/null::gw.*version=2 state=ESTABLISHED local-host=PH_IP_MOON local-port=4500 local-id=moon.strongswan.org remote-host=PH_IP_SUN remote-port=4500 remote-id=sun.strongswan.org.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*local-ts=\[0.0.0.0/0] remote-ts=\[0.0.0.0/0]::YES
sun::swanctl --list-sas --ike-id 1 --raw 2> /dev/null::gw.*version=2 state=ESTABLISHED local-host=PH_IP_SUN local-port=4500 local-id=sun.strongswan.org remote-host=PH_IP_MOON remote-port=4500 remote-id=moon.strongswan.org.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*local-ts=\[0.0.0.0/0] remote-ts=\[0.0.0.0/0]::YES
alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::YES
moon::ip netns add xfrmi-test::.*::NO
moon::ip link set xfrm-moon netns xfrmi-test::.*::NO
moon::ip netns exec xfrmi-test ip addr add 10.1.0.42/32 dev xfrm-moon::.*::NO
moon::ip netns exec xfrmi-test ip link set dev xfrm-moon up::.*::NO
moon::ip netns exec xfrmi-test ip route add 10.2.0.0/16 dev xfrm-moon src 10.1.0.42::.*::NO
moon::ip netns exec xfrmi-test ip xfrm state::.*::NO
moon::ip netns exec xfrmi-test ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::YES
alice::ping -c 1 -W 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::NO
moon::ip netns exec xfrmi-test ip link set xfrm-moon netns 1::.*::NO
moon::ip netns del xfrmi-test::.*::NO
moon::ip link set dev xfrm-moon up::.*::NO
moon::ip route add 10.2.0.0/16 dev xfrm-moon::.*::NO
alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::YES
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
}
@@ -0,0 +1,30 @@
connections {
gw-gw {
local_addrs = PH_IP_MOON
remote_addrs = PH_IP_SUN
local {
auth = pubkey
certs = moonCert.pem
id = moon.strongswan.org
}
remote {
auth = pubkey
id = sun.strongswan.org
}
children {
net-net {
local_ts = 0.0.0.0/0
remote_ts = 0.0.0.0/0
if_id_out = 42
if_id_in = 42
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
}
@@ -0,0 +1,32 @@
connections {
gw-gw {
local_addrs = PH_IP_SUN
remote_addrs = PH_IP_MOON
local {
auth = pubkey
certs = sunCert.pem
id = sun.strongswan.org
}
remote {
auth = pubkey
id = moon.strongswan.org
}
children {
net-net {
local_ts = 0.0.0.0/0
remote_ts = 0.0.0.0/0
if_id_out = %unique
if_id_in = %unique
updown = /etc/updown
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
@@ -0,0 +1,18 @@
#!/bin/bash
IF_NAME="xfrmi-${PLUTO_IF_ID_IN}"
case "${PLUTO_VERB}" in
up-client)
/usr/local/libexec/ipsec/xfrmi -n "${IF_NAME}" -i "${PLUTO_IF_ID_IN}" -d eth0
ip link set "${IF_NAME}" up
ip route add 10.1.0.0/16 dev "${IF_NAME}"
iptables -A FORWARD -i "${IF_NAME}" -j ACCEPT
iptables -A FORWARD -o "${IF_NAME}" -j ACCEPT
;;
down-client)
iptables -D FORWARD -i "${IF_NAME}" -j ACCEPT
iptables -D FORWARD -o "${IF_NAME}" -j ACCEPT
ip link del "${IF_NAME}"
;;
esac
@@ -0,0 +1,8 @@
moon::swanctl --terminate --ike gw-gw
moon::systemctl stop strongswan-swanctl
sun::systemctl stop strongswan-swanctl
moon::iptables-restore < /etc/iptables.flush
sun::iptables-restore < /etc/iptables.flush
moon::ip -s link show xfrm-moon
moon::ip link del xfrm-moon
sun::rm /etc/updown
@@ -0,0 +1,12 @@
moon::iptables-restore < /etc/iptables.rules
sun::iptables-restore < /etc/iptables.rules
moon::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon -i 42 -d eth0
moon::ip link set xfrm-moon up
moon::ip route add 10.2.0.0/16 dev xfrm-moon
moon::iptables -A FORWARD -i xfrm-moon -j ACCEPT
moon::iptables -A FORWARD -o xfrm-moon -j ACCEPT
moon::systemctl start strongswan-swanctl
sun::systemctl start strongswan-swanctl
moon::expect-connection gw-gw
sun::expect-connection gw-gw
moon::swanctl --initiate --child net-net
@@ -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
@@ -0,0 +1,17 @@
A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b>
is set up using XFRM interfaces.
<p/>
The gateways use <b>route-based forwarding</b> with <b>XFRM interfaces</b>, with
firewall rules to allow traffic to pass. The IPsec traffic selector used is
0.0.0.0/0, however, specific routing is achieved with routes on the XFRM
interfaces. The IKE daemon does not install routes for CHILD_SAs with outbound
interface ID, so static routes are installed for the target subnets.
<p/>
Both gateways use separate interfaces for in- and outbound traffic (which is
completely optional and mainly for testing purposes, a single interface will
usually be enough). Gateway <b>moon</b> creates them before initiating the
connection, while gateway <b>sun</b> dynamically creates the interfaces via
updown script using the passed unique generated interface IDs.
<p/>
Client <b>alice</b> behind gateway <b>moon</b> pings client <b>bob</b> located
behind gateway <b>sun</b>.
@@ -0,0 +1,5 @@
moon::swanctl --list-sas --ike-id 1 --raw 2> /dev/null::gw.*version=2 state=ESTABLISHED local-host=PH_IP_MOON local-port=4500 local-id=moon.strongswan.org remote-host=PH_IP_SUN remote-port=4500 remote-id=sun.strongswan.org.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*local-ts=\[0.0.0.0/0] remote-ts=\[0.0.0.0/0]::YES
sun::swanctl --list-sas --ike-id 1 --raw 2> /dev/null::gw.*version=2 state=ESTABLISHED local-host=PH_IP_SUN local-port=4500 local-id=sun.strongswan.org remote-host=PH_IP_MOON remote-port=4500 remote-id=moon.strongswan.org.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*local-ts=\[0.0.0.0/0] remote-ts=\[0.0.0.0/0]::YES
alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::YES
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
}
@@ -0,0 +1,30 @@
connections {
gw-gw {
local_addrs = PH_IP_MOON
remote_addrs = PH_IP_SUN
local {
auth = pubkey
certs = moonCert.pem
id = moon.strongswan.org
}
remote {
auth = pubkey
id = sun.strongswan.org
}
children {
net-net {
local_ts = 0.0.0.0/0
remote_ts = 0.0.0.0/0
if_id_out = 1337
if_id_in = 42
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
}
@@ -0,0 +1,32 @@
connections {
gw-gw {
local_addrs = PH_IP_SUN
remote_addrs = PH_IP_MOON
local {
auth = pubkey
certs = sunCert.pem
id = sun.strongswan.org
}
remote {
auth = pubkey
id = moon.strongswan.org
}
children {
net-net {
local_ts = 0.0.0.0/0
remote_ts = 0.0.0.0/0
if_id_in = %unique-dir
if_id_out = %unique-dir
updown = /etc/updown
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
@@ -0,0 +1,23 @@
#!/bin/bash
IF_NAME="xfrm-"
IF_NAME_IN="${IF_NAME}${PLUTO_IF_ID_IN}-in"
IF_NAME_OUT="${IF_NAME}${PLUTO_IF_ID_OUT}-out"
case "${PLUTO_VERB}" in
up-client)
/usr/local/libexec/ipsec/xfrmi -n "${IF_NAME_OUT}" -i "${PLUTO_IF_ID_OUT}" -d eth0
/usr/local/libexec/ipsec/xfrmi -n "${IF_NAME_IN}" -i "${PLUTO_IF_ID_IN}" -d eth0
ip link set "${IF_NAME_OUT}" up
ip link set "${IF_NAME_IN}" up
ip route add 10.1.0.0/16 dev "${IF_NAME_OUT}"
iptables -A FORWARD -o "${IF_NAME_OUT}" -j ACCEPT
iptables -A FORWARD -i "${IF_NAME_IN}" -j ACCEPT
;;
down-client)
iptables -D FORWARD -o "${IF_NAME_OUT}" -j ACCEPT
iptables -D FORWARD -i "${IF_NAME_IN}" -j ACCEPT
ip link del "${IF_NAME_OUT}"
ip link del "${IF_NAME_IN}"
;;
esac
@@ -0,0 +1,10 @@
moon::swanctl --terminate --ike gw-gw
moon::systemctl stop strongswan-swanctl
sun::systemctl stop strongswan-swanctl
moon::iptables-restore < /etc/iptables.flush
sun::iptables-restore < /etc/iptables.flush
moon::ip -s link show xfrm-moon-out
moon::ip -s link show xfrm-moon-in
moon::ip link del xfrm-moon-out
moon::ip link del xfrm-moon-in
sun::rm /etc/updown
@@ -0,0 +1,14 @@
moon::iptables-restore < /etc/iptables.rules
sun::iptables-restore < /etc/iptables.rules
moon::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon-out -d eth0 -i 1337
moon::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon-in -d eth0 -i 42
moon::ip link set xfrm-moon-out up
moon::ip link set xfrm-moon-in up
moon::ip route add 10.2.0.0/16 dev xfrm-moon-out
moon::iptables -A FORWARD -o xfrm-moon-out -j ACCEPT
moon::iptables -A FORWARD -i xfrm-moon-in -j ACCEPT
moon::systemctl start strongswan-swanctl
sun::systemctl start strongswan-swanctl
moon::expect-connection gw-gw
sun::expect-connection gw-gw
moon::swanctl --initiate --child net-net
@@ -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
@@ -0,0 +1,12 @@
The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to
gateway <b>moon</b>. Both <b>carol</b> and <b>dave</b> request a <b>virtual
IP</b> via IKEv2 configuration payload.
<p/>
The gateway <b>moon</b> uses <b>route-based forwarding</b> with an <b>XFRM
interface</b>, with firewall rules to allow traffic to pass. The IKE daemon
does not install routes for CHILD_SAs with outbound interface ID, so a static
route is installed for the virtual IP subnet via XFRM interface.
<p/>
Both <b>carol</b> and <b>dave</b> ping the client <b>alice</b> behind the
gateway <b>moon</b>. The source IP addresses of the two pings will be the
virtual IPs <b>carol1</b> and <b>dave1</b>, respectively.
@@ -0,0 +1,10 @@
carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=PH_IP_CAROL local-port=4500 [email protected] remote-host=PH_IP_MOON remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*local-ts=\[10.3.0.1/32] remote-ts=\[10.1.0.0/16]::YES
dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=PH_IP_DAVE local-port=4500 [email protected] remote-host=PH_IP_MOON remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*local-ts=\[10.3.0.2/32] remote-ts=\[10.1.0.0/16]::YES
moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=PH_IP_MOON local-port=4500 local-id=moon.strongswan.org remote-host=PH_IP_CAROL remote-port=4500 [email protected].*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.1/32]::YES
moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=PH_IP_MOON local-port=4500 local-id=moon.strongswan.org remote-host=PH_IP_DAVE remote-port=4500 [email protected].*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.2/32]::YES
carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_.eq=1::YES
dave::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_.eq=1::YES
moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce aes sha1 sha2 hmac pem pkcs1 x509 revocation curve25519 gmp curl kernel-netlink socket-default updown vici
}
@@ -0,0 +1,28 @@
connections {
home {
local_addrs = PH_IP_CAROL
remote_addrs = PH_IP_MOON
vips = 0.0.0.0
local {
auth = pubkey
certs = carolCert.pem
id = [email protected]
}
remote {
auth = pubkey
id = moon.strongswan.org
}
children {
home {
remote_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce aes sha1 sha2 hmac pem pkcs1 x509 revocation curve25519 gmp curl kernel-netlink socket-default updown vici
}
@@ -0,0 +1,28 @@
connections {
home {
local_addrs = PH_IP_DAVE
remote_addrs = PH_IP_MOON
vips = 0.0.0.0
local {
auth = pubkey
certs = daveCert.pem
id = [email protected]
}
remote {
auth = pubkey
id = moon.strongswan.org
}
children {
home {
remote_ts = 10.1.0.0/16
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
@@ -0,0 +1,9 @@
# /etc/strongswan.conf - strongSwan configuration file
swanctl {
load = pem pkcs1 x509 revocation constraints pubkey openssl random
}
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
}
@@ -0,0 +1,34 @@
connections {
rw {
local_addrs = PH_IP_MOON
pools = rw_pool
local {
auth = pubkey
certs = moonCert.pem
id = moon.strongswan.org
}
remote {
auth = pubkey
}
children {
net {
local_ts = 10.1.0.0/16
if_id_out = 42
if_id_in = 42
esp_proposals = aes128gcm128-x25519
}
}
version = 2
proposals = aes128-sha256-x25519
}
}
pools {
rw_pool {
addrs = 10.3.0.0/28
}
}
@@ -0,0 +1,10 @@
carol::swanctl --terminate --ike home
dave::swanctl --terminate --ike home
moon::systemctl stop strongswan-swanctl
carol::systemctl stop strongswan-swanctl
dave::systemctl stop strongswan-swanctl
moon::iptables-restore < /etc/iptables.flush
carol::iptables-restore < /etc/iptables.flush
dave::iptables-restore < /etc/iptables.flush
moon::ip -s link show xfrm-moon
moon::ip link del xfrm-moon
@@ -0,0 +1,16 @@
moon::iptables-restore < /etc/iptables.rules
carol::iptables-restore < /etc/iptables.rules
dave::iptables-restore < /etc/iptables.rules
moon::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon -i 42 -d eth0
moon::ip link set xfrm-moon up
moon::ip route add 10.3.0.0/28 dev xfrm-moon
moon::iptables -A FORWARD -i xfrm-moon -j ACCEPT
moon::iptables -A FORWARD -o xfrm-moon -j ACCEPT
moon::systemctl start strongswan-swanctl
carol::systemctl start strongswan-swanctl
dave::systemctl start strongswan-swanctl
moon::expect-connection rw
carol::expect-connection home
carol::swanctl --initiate --child home
dave::expect-connection home
dave::swanctl --initiate --child home
@@ -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 carol winnetou dave"
# Corresponding block diagram
#
DIAGRAM="a-m-c-w-d.png"
# Guest instances on which tcpdump is to be started
#
TCPDUMPHOSTS="moon"
# Guest instances on which IPsec is started
# Used for IPsec logging purposes
#
IPSECHOSTS="moon carol dave"
# charon controlled by swanctl
#
SWANCTL=1