FreeBSD 10: IPv4 IPsec Net-to-Net VPN in der Jail

Gewünscht ist die Anbindung von zwei unterschiedlichen Broadcast-Domains mit Hilfe von IPsec als VPN Lösung.
Das VPN Routing selbst soll jeweils in einer Jail stattfinden.
Da eine Direktkommunikation zwischen den FreeBSD Gateways möglich ist, kann unmittelbar mit AH (für Authentizität/Integrität und Echtheit der Daten) die erste Ebene abgesichert werden ohne auf NAT Probleme zu stoßen.

– die Außenhülle des Tunnels verwendet AH mit hmac-sha1 (transport mode)
– der Kern des Tunnels besteht aus ESP mit aes-cbc Verschlüsselung
– die Zwiebel innerhalb des Kernes bedient sich erneut einer AH Verbindung zur Validierung, diesmal mit hmac-ripemd160

plitc_freebsd_ipsec_ipv4_n2n

#
<<< ======== (ipip-proto-4) ======== >>>

10003 ------------- AH ---------- >>> 20003 (transport)
10002 <<< --------- ESP ------------- 20002 (tunnel)
10001 ------------- AH ---------- >>> 20001 (tunnel)*
#

*(nicht im Jail HOST tcpdump sichtbar)

statische Keys, KEIN Perfect Forward Secrecy

Ausgegangen wird von einem „Bridge Zones“ Setup
siehe: FreeBSD 10: komplexe Bridge Zones (mit lacp uplink)

Da es bei einigen Servern Probleme mit „options IPSEC_FILTERTUNNEL“ (Abstürze/keine funktionierende Filterung mit ipfw unter FreeBSD 10) gab, rate ich zum Zeitpunkt dieses HowTo davon ab.

INFO: 28.02.2014 – Patch in FreeBSD 10.1, siehe:

FreeBSD 10: IPv4 VPN Relay (IPsec entry/OpenVPN middle/OpenVPN exit node) mit Jails für Roadwarrior

Als Einführung sind recht hilfreich:
– FreeBSD VPN over IPsec
– FreeBSD IPsec
Network Configuration—Tunneling with Free BSD
Understanding VPN IPsec Tunnel Mode and IPsec Transport Mode – What’s the Difference?
An Illustrated Guide to IPsec

Security: IPsec ohne integrity check
A DoS Attack Against the Integrity-Less ESP (IPsec)

VPN Jail1 (Maschine A) hat eine Public Adresse beginnend mit 80.xxx.xxx.xxx
VPN Jail2 (Maschine B) hat eine Public Adresse beginnend mit 212.xxx.xxx.xxx

geroutet werden soll 192.168.1.0 nach 192.168.2.0 und umgekehrt

FreeBSD Beastie IPv4 IPsec Net-to-Net VPN in der Jail

Punkt 1 Kernel mit IPsec kompilieren

$
options   IPSEC        #IP security
device    crypto
$

Die Jails benötigen ein GIF Interface, Auszug aus einer ezjail config:

Punkt 2 ezjail/jail1

$
### VIMAGE // ###
export jail_vpnjail1_exec_poststart0="ifconfig epair89a vnet vpnjail1"
export jail_vpnjail1_exec_poststart1="ifconfig epair90a vnet vpnjail1"
export jail_vpnjail1_exec_poststart2="ifconfig epair92a vnet vpnjail1"
export jail_vpnjail1_exec_poststart3="ifconfig epair93a vnet vpnjail1"
export jail_vpnjail1_exec_poststart4="ifconfig gif26 vnet vpnjail1"
export jail_vpnjail1_exec_poststart5="ifconfig gif27 vnet vpnjail1"
export jail_vpnjail1_exec_poststart6="jexec vpnjail1 /sbin/ifconfig epair89a 80.xxx.xxx.xxx/27"
export jail_vpnjail1_exec_poststart7="jexec vpnjail1 /sbin/route add default 80.xxx.xxx.xxx"
export jail_vpnjail1_exec_poststart8="jexec vpnjail1 /sbin/ifconfig epair89a inet6 2a01:xxxx:xxxx:xxxx::xxxx:1 prefixlen 64"
export jail_vpnjail1_exec_poststart9="jexec vpnjail1 /sbin/route add -inet6 default fe80::1%epair89a"
export jail_vpnjail1_exec_poststart10="jexec vpnjail1 /sbin/ifconfig epair90a 192.168.254.254/24"
export jail_vpnjail1_exec_poststart11="jexec vpnjail1 /sbin/ifconfig epair93a 192.168.253.254/24"
### // VIMAGE ###

## IPSEC /
#
export jail_vpnjail1_exec_poststart12="jexec vpnjail1 /sbin/ifconfig epair92a 192.168.1.254/24"
export jail_vpnjail1_exec_poststart13="jexec vpnjail1 /sbin/ifconfig epair92a 192.168.5.254/24 alias"
#
# --- route 1 to 2
export jail_vpnjail1_exec_poststart14="jexec vpnjail1 /sbin/ifconfig gif26 192.168.101.254 192.168.102.254"
export jail_vpnjail1_exec_poststart15="jexec vpnjail1 /sbin/ifconfig gif26 tunnel 80.xxx.xxx.xxx 212.xxx.xxx.xxx"
export jail_vpnjail1_exec_poststart16="jexec vpnjail1 /sbin/ifconfig gif26 up"
export jail_vpnjail1_exec_poststart17="jexec vpnjail1 /sbin/route add 192.168.2.0 192.168.102.254 255.255.255.0"
#
## / IPSEC
$

Punkt 3 HOST !!! IPsec in den Bridge Zones erlauben

$
vi /etc/firewall.rules

add 00040 allow esp from any to any
add 00041 allow ah from any to any
add 00042 allow ipencap from any to any
add 00043 allow udp from any 500 to any
$

Punkt 4 Jail1: sofern die Firewall alles erlaubt -> kann man zumindest die Pakete zählen lassen und routing aktivieren

$
vi /etc/jail_firewall.rules

### ### ### ### ### ### ### ### ###
add 00040 count esp from any to any
add 00041 count ah from any to any
add 00042 count ipencap from any to any
add 00043 count udp from any 500 to any
### ### ### ### ### ### ### ### ###

vi /etc/sysctl.conf

### ### ### ### ### ### ### ### ###
net.inet.ip.forwarding=1
net.inet.ip.fastforwarding=0
net.inet6.ip6.forwarding=1
net.inet.ip.fw.one_pass=1
### ### ### ### ### ### ### ### ###
$

Punkt 5 Jail1: ipsec-tools installieren

$
cd /usr/ports/security/ipsec-tools/ && make install clean
$

Punkt 6 Jail1: racoon.conf erstellen

$
vi /usr/local/etc/racoon/racoon.conf

### ### ### ### ### ### ### ### ###
path    pre_shared_key  "/usr/local/etc/racoon/psk.txt"; #location of pre-shared key file
log     debug;  #log verbosity setting: set to 'notify' when testing and debugging is complete

padding # options are not to be changed
{
        maximum_length  20;
        randomize       off;
        strict_check    off;
        exclusive_tail  off;
}

timer   # timing options. change as needed
{
        counter         5;
        interval        20 sec;
        persend         1;
#       natt_keepalive  15 sec;
        phase1          30 sec;
        phase2          15 sec;
}

listen  # address [port] that racoon will listening on
{
        isakmp          80.xxx.xxx.xxx [500];
        isakmp_natt     80.xxx.xxx.xxx [4500];
}

remote  212.xxx.xxx.xxx [500]
{
        exchange_mode   main;
        doi             ipsec_doi;
        situation       identity_only;
        my_identifier   address 80.xxx.xxx.xxx;
        peers_identifier        address 212.xxx.xxx.xxx;
        lifetime        time 8 hour;
        passive         off;
        proposal_check  strict;
#       nat_traversal   off;
        generate_policy off;

                        proposal {
                                encryption_algorithm    aes 256;
                                hash_algorithm          sha512;
                                authentication_method   pre_shared_key;
                                lifetime time           7200 sec;
                                dh_group                16;
                        }
}

sainfo  (address 192.168.1.0/24 any address 192.168.2.0/24 any)
{
        pfs_group       16;
        lifetime        time       3600 sec;
        encryption_algorithm       aes 256;
        authentication_algorithm   hmac_sha512;
        compression_algorithm      deflate;
}
### ### ### ### ### ### ### ### ###
$

Punkt 7 Jail1: pre-shared key file erzeugen

$
vi /usr/local/etc/racoon/psk.txt

212.xxx.xxx.xxx my_fancy_psk
$

Punkt 8 Jail1: setkey.conf erstellen

Beispiel mit statischen Keys, ohne PFS und ohne racoon !!!

$
vi /usr/local/etc/racoon/setkey.conf

### ### ### ### ### ### ### ### ###
flush;

# route 1 to 2
# / INFO: -A key length 20
# / INFO: -E key length 16
#
add 80.xxx.xxx.xxx 212.xxx.xxx.xxx ah 0x10001  -m tunnel -u 1 -A hmac-ripemd160 "B884DA4799BE4A4F5D57";
add 80.xxx.xxx.xxx 212.xxx.xxx.xxx esp 0x10002 -m tunnel -u 2 -E aes-cbc "36DE843AFA42554F";
add 80.xxx.xxx.xxx 212.xxx.xxx.xxx ah 0x10003  -m transport -u 3 -A hmac-sha1 "B884DA4799BE4A4F5D58";
#
add 212.xxx.xxx.xxx 80.xxx.xxx.xxx ah 0x20001  -m tunnel -u 4 -A hmac-ripemd160 "A884DA4799BE4A4F5D57";
add 212.xxx.xxx.xxx 80.xxx.xxx.xxx esp 0x20002 -m tunnel -u 5 -E aes-cbc "38DE843AFA42554A";
add 212.xxx.xxx.xxx 80.xxx.xxx.xxx ah 0x20003  -m transport -u 6 -A hmac-sha1 "C884DA4799BE4A4F5D50";

spdflush;

# route 1 to 2
#
spdadd 192.168.1.0/24 192.168.2.0/24 any -P out ipsec
ah/tunnel/80.xxx.xxx.xxx-212.xxx.xxx.xxx/unique:1
esp/tunnel/80.xxx.xxx.xxx-212.xxx.xxx.xxx/unique:2
ah/transport/80.xxx.xxx.xxx-212.xxx.xxx.xxx/unique:3;
#
spdadd 192.168.2.0/24 192.168.1.0/24 any -P in ipsec
ah/tunnel/212.xxx.xxx.xxx-80.xxx.xxx.xxx/unique:4
esp/tunnel/212.xxx.xxx.xxx-80.xxx.xxx.xxx/unique:5
ah/transport/212.xxx.xxx.xxx-80.xxx.xxx.xxx/unique:6;
### ### ### ### ### ### ### ### ###
# EOF

chmod 0600 /usr/local/etc/racoon/*
$

plitc_freebsd_ipsec_ipv4_n2n1_pfs

Racoon wird benötigt, PFS wird verwendet !!!

$
vi /usr/local/etc/racoon/setkey.conf

### ### ### ### ### ### ### ### ###
flush;

spdflush;

# route 1 to 2
#
spdadd 192.168.1.0/24 192.168.2.0/24 any -P out ipsec
esp/tunnel/80.xxx.xxx.xxx-212.xxx.xxx.xxx/require
ah/transport/80.xxx.xxx.xxx-212.xxx.xxx.xxx/require;
#
spdadd 192.168.2.0/24 192.168.1.0/24 any -P in ipsec
esp/tunnel/212.xxx.xxx.xxx-80.xxx.xxx.xxx/require
ah/transport/212.xxx.xxx.xxx-80.xxx.xxx.xxx/require;
### ### ### ### ### ### ### ### ###
# EOF

chmod 0600 /usr/local/etc/racoon/*
$

Punkt 9 Jail1: psk generieren

$
# für 20 Zeichen lange AH Keys
#
openssl enc -aes-256-xts -k secret -P -md sha1 | grep "key" | sed 's/key=//g' | cut -c-20
#
# für 16 Zeichen lange ESP Keys
openssl enc -aes-256-xts -k secret -P -md sha1 | grep "key" | sed 's/key=//g' | cut -c-16
$

Punkt 10 Jail1: bei Jailstart IPsec mit laden lassen

$
vi /etc/rc.conf

### ### ### ### ### ### ### ### ###
gateway_enable="YES"

ipv6_gateway_enable="YES"
rtadvd_enable="NO"
rtadvd_interfaces="epair89a"

firewall_enable="YES"
#firewall_type="open"
firewall_logging="YES"
firewall_type="/etc/firewall.rules"
firewall_script="/etc/rc.firewall.local"

ipsec_enable="YES"
ipsec_program="/usr/local/sbin/setkey"
ipsec_file="/usr/local/etc/racoon/setkey.conf" # allows setting up spd policies on boot
racoon_enable="yes"
### ### ### ### ### ### ### ### ###
$

Punkt 11 Jail1: IPsec Policy manuell setzen und Racoon starten

$
clear; service racoon stop; service ipsec stop; sleep 1; service ipsec start; service racoon start
$

In Jail2 erfolgt das ganze noch einmal nur mit umgedrehter Reihenfolge in der setkey.conf (spdadd die in und out Einträge)

Bei erfolgreicher Verbindung kann man folgendes im TCPDump beobachten:

Punkt 12 Verbindungstest

$
# ipfw counter in der jail
#
00040     0       0 count esp from any to any
00041 28660 6649120 count ah from any to any
00042     0       0 count ipencap from any to any
00043     0       0 count udp from any 500 to any
$
$
# tcpdump im Jail HOST
#
# tcpdump -e -n -i vswitch26 'not ip6 and not arp and not icmp'
#
tcpdump: WARNING: vswitch26: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vswitch26, link-type EN10MB (Ethernet), capture size 65535 bytes
capability mode sandbox enabled
15:07:53.785236 MAC > MAC, ethertype IPv4 (0x0800), length 246: 212.xxx.xxx.xxx > 80.xxx.xxx.xxx: AH(spi=0x00020003,seq=0x3d17): 212.xxx.xxx.xxx > 80.xxx.xxx.xxx: ESP(spi=0x00020002,seq=0x3d17), length 168
15:07:53.787686 MAC > MAC, ethertype IPv4 (0x0800), length 246: 80.xxx.xxx.xxx > 212.xxx.xxx.xxx: AH(spi=0x00010003,seq=0x38b2): 80.xxx.xxx.xxx > 212.xxx.xxx.xxx: ESP(spi=0x00010002,seq=0x38b2), length 168
15:07:54.791368 MAC > MAC, ethertype IPv4 (0x0800), length 246: 212.xxx.xxx.xxx > 80.xxx.xxx.xxx: AH(spi=0x00020003,seq=0x3d18): 212.xxx.xxx.xxx > 80.xxx.xxx.xxx: ESP(spi=0x00020002,seq=0x3d18), length 168
15:07:54.793567 MAC > MAC, ethertype IPv4 (0x0800), length 246: 80.xxx.xxx.xxx > 212.xxx.xxx.xxx: AH(spi=0x00010003,seq=0x38b3): 80.xxx.xxx.xxx > 212.xxx.xxx.xxx: ESP(spi=0x00010002,seq=0x38b3), length 168
15:07:55.796186 MAC > MAC, ethertype IPv4 (0x0800), length 246: 212.xxx.xxx.xxx > 80.xxx.xxx.xxx: AH(spi=0x00020003,seq=0x3d19): 212.xxx.xxx.xxx > 80.xxx.xxx.xxx: ESP(spi=0x00020002,seq=0x3d19), length 168
15:07:55.797195 MAC > MAC, ethertype IPv4 (0x0800), length 246: 80.xxx.xxx.xxx > 212.xxx.xxx.xxx: AH(spi=0x00010003,seq=0x38b4): 80.xxx.xxx.xxx > 212.xxx.xxx.xxx: ESP(spi=0x00010002,seq=0x38b4), length 168
15:07:56.805821 MAC > MAC, ethertype IPv4 (0x0800), length 246: 212.xxx.xxx.xxx > 80.xxx.xxx.xxx: AH(spi=0x00020003,seq=0x3d1a): 212.xxx.xxx.xxx > 80.xxx.xxx.xxx: ESP(spi=0x00020002,seq=0x3d1a), length 168
15:07:56.806448 MAC > MAC, ethertype IPv4 (0x0800), length 246: 80.xxx.xxx.xxx > 212.xxx.xxx.xxx: AH(spi=0x00010003,seq=0x38b5): 80.xxx.xxx.xxx > 212.xxx.xxx.xxx: ESP(spi=0x00010002,seq=0x38b5), length 168
^C
9 packets captured
11 packets received by filter
0 packets dropped by kernel
$

eine gute Übersicht liefert auch: setkey -D

in einem laufenden BHYE Linux, mit tap Device Anbindung, muss noch zusätzlich die Route (über die VPN Jail) gesetzt werden:

$
route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.1.254
$

Ergänzungen

24.11.2014 Im BHYVE (Debian) Linux funktioniert eine MTU von 1350

$
# tap26: bhyve vm1 <-> ipsec jail1 <---> ipsec jail2 <-> vm2
ifconfig eth1 mtu 1350 up
$

That’s FreeBSD

Ein Gedanke zu „FreeBSD 10: IPv4 IPsec Net-to-Net VPN in der Jail

Schreibe einen Kommentar