Site-to-site IPsec on VMM

This guide is designed to help you simulate an IPsec gateway using the IPsec site-to-site guide. If you lack real hardware to test with, you can simulate the setup inside vmm.

This guide assumes you have read the IPsec site-to-site guide. It only covers parts that are specific to the setup on VMM.

                192.0.2.1             198.51.100.1
                        <--IPsec veb12--> 
initlan <-veb11-> init                    resp <-veb22-> resplan
10.0.1.2         10.0.1.1              10.0.2.1          10.0.2.2

Configuring the host

First, we set up the host's interfaces:

host# cat /etc/hostname.veb11
up
host# cat /etc/hostname.veb12
add vport11
up
host# cat /etc/hostname.veb22
up
host# cat /etc/hostname.vport11
inet 192.0.0.1 0xffffff00
!route add -inet 192.0.2.1 -cloning -link -iface vport11
!route add -inet 192.0.2/24 192.0.2.1
!route add -inet 198.51.100.1 -cloning -link -iface vport11
!route add -inet 198.51.100/24 198.51.100.1
up

Next we configure vm.conf:

socket owner :vmdusers

switch "switch11" {
    locked lladdr
    interface veb11
}
switch "switch12" {
    locked lladdr
    interface veb12
}
switch "switch22" {
    locked lladdr
    interface veb22
}

bsdiso="/home/iso/install75.iso"

vm "initlan" {
        owner $USER
        memory 1G
        cdrom $bsdiso
        disk /home/$USER/initlan.qcow2 format qcow2
        interface tap10 {
                locked lladdr e8:8b:10:00:01:02
                switch "switch11"
        }
}

vm "init" {
        owner $USER
        memory 1G
        cdrom $bsdiso
        disk /home/$USER/init.qcow2 format qcow2
        interface tap11 {
                locked lladdr e8:8b:11:11:11:11
                switch "switch12"
        }
        interface tap12 {
                locked lladdr e8:8b:10:00:01:01
                switch "switch11"
        }
}

vm "resplan" {
        owner $USER
        memory 1G
        cdrom $bsdiso
        disk /home/$USER/resplan.qcow2 format qcow2
        interface tap20 {
                locked lladdr e8:8b:10:00:02:02
                switch "switch22"
        }
}

vm "resp" {
        owner $USER
        memory 1G
        cdrom $bsdiso
        disk /home/$USER/resp.qcow2 format qcow2
        interface tap21 {
                locked lladdr e8:8b:22:22:22:22
                switch "switch12"
        }
        interface tap22 {
                locked lladdr e8:8b:10:00:02:01
                switch "switch22"
        }
}

Make sure to create each of the qcow2 images and install OpenBSD.

Next, configure the interfaces in each of the virtual machines:

initlan# cat /etc/hostname.vio0
inet 10.0.1.2 0xffffff00
initlan# cat /etc/mygate
10.0.1.1

init# cat /etc/hostname.vio0
inet 192.0.2.1 0xffffff00
up
!route add -inet 192.0.0.1 -cloning -link -iface vio0
!route add -inet default 192.0.0.1
init# cat /etc/hostname.vio1
inet 10.0.1.1 0xffffff00
up
!route add -inet 10/8 10.0.1.1

resplan# cat /etc/hostname.vio0
inet 10.0.2.2 0xffffff00
resplan# cat /etc/mygate
10.0.2.1

resp# cat /etc/hostname.vio0
inet 198.51.100.1 0xffffff00
up
!route add -inet 192.0.0.1 -cloning -link -iface vio0
!route add -inet default 192.0.0.1
resp# cat /etc/hostname.vio1
inet 10.0.2.1 0xffffff00
up
!route add -inet 10/8 10.0.2.1

Make sure to configure iked(8) as mentioned in the site-to-site IPsec guide.

Exchange public keys. From init to resp:

init$ cat /etc/iked/local.pub | ssh 198.51.100.1 'doas tee /etc/iked/pubkeys/fqdn/init.example.com'

From resp to init:

resp$ cat /etc/iked/local.pub | ssh 192.0.2.1 'doas tee /etc/iked/pubkeys/fqdn/resp.example.com'

Configure iked.conf(5) for both resp and init:

init# cat /etc/iked.conf
init="192.0.2.1"
resp="198.51.100.1"
initlan="10.0.1.0/24"
resplan="10.0.2.0/24"

ikev2 'init' active esp \
	from $initlan to $resplan \
	from $initlan to $resp \
	local $init peer $resp \
	srcid init.example.com

resp# cat /etc/iked.conf
init="192.0.2.1"
resp="198.51.100.1"
initlan="10.0.1.0/24"
resplan="10.0.2.0/24"

ikev2 'resp' passive esp \
        from $resplan to $initlan \
        from $resplan to $init \
        local $resp peer $init \
        srcid resp.example.com

Tighten permissions for iked(8):

init# chmod 0600 /etc/iked.conf

resp# chmod 0600 /etc/iked.conf

Appropriate sysctls should be enabled:

init# cat /etc/sysctl.conf
net.inet.ip.forwarding=1
net.inet.esp.enable=1
net.inet.ah.enable=1

resp# cat /etc/sysctl.conf
net.inet.ip.forwarding=1
net.inet.esp.enable=1
net.inet.ah.enable=1

Adjust /etc/pf.conf? for resp:

init="192.0.2.1"
resp="198.51.100.1"
pass in log on $ext_if proto udp from $init to $resp port {isakmp, ipsec-nat-t} tag IKED
pass in log on $ext_if proto esp from $init to $resp tag IKED

Reload packet filter:

resp# pfctl -f /etc/pf.conf

Start iked:

init# rcctl enable iked
init# rcctl start iked
iked(ok)

resp# rcctl enable iked
resp# rcctl start iked
iked(ok)

Confirm IPsec flows with ipsecctl and verify security associations with ikectl:

init# ipsecctl -sa
...
resp# ikectl show sa
...

Testing

Test the tunnel works by pinging resplan (10.0.2.2) from initlan (10.0.1.2):

initlan$ ping -I 10.0.1.2 10.0.2.2
PING 10.0.2.2 (10.0.2.2): 56 data bytes
64 bytes from 10.0.2.2: icmp_seq=0 ttl=108 time=45.523 ms
64 bytes from 10.0.2.2: icmp_seq=1 ttl=108 time=45.304 ms

Run tcpdump? on an enc(4) interface to see packets prior to encapsulation and after decapsulation:

init# tcpdump -ne -i enc0
tcpdump: listening on enc0, link-type ENC
23:05:45.520270 (authentic,confidential): SPI 0xf997b9a0: 10.0.2.2 > 10.0.1.2: icmp: echo request (encap)
23:05:45.520825 (authentic,confidential): SPI 0xa484d765: 10.0.1.2 > 10.0.2.2: icmp: echo reply (encap)

IPsec Statistics

init# netstat -s -p esp
esp:
        144 input ESP packets
        150 output ESP packets
        0 packets from unsupported protocol families
....
        0 raw ESP packets for encapsulating TDB received
        19976 input bytes
        20406 output bytes
init# netstat -s -p ah
ah:
        0 input AH packets
        0 output AH packets
        0 packets from unsupported protocol families
...
        0 output packets could not be sent
        0 input bytes
        0 output bytes

As expected, there are no AH packets being sent because the IPsec gateways are using ESP for confidentiality. For more information, see ipsec(4).