1.141. VPN (OpenBSD)
Das folgende HOWTO beschreibt einige wesentliche Elemente der Konfiguration eines VPN-Routers. Das Gerät ist lüfterlos und bootet von einer CF-Karte. Das System läuft im RAM-Drive. Die Anbindung an DAS INTERNET erfolgt unter Verwendung eines marktüblichen ADSL-Anschlusses (natürlich flat…). Die dynamisch zugeteilte Adresse wird per DYNDNS kanonisch auflösbar gemacht. Als VPN-Applikation wird ISAKMPD verwendet.
Ziel war es, viele kleine Standorte kostengünstig mittels ADSL an ein zentrales LAN via VPN anzubinden. Die VPN-Gateways an den Standorten sollten wartungsarm sein, d.h. über keine bewegten Teile verfügen. Weiterhin mussten sie schnell updatebar sein. Aus diesem Grund wurde eine zentrale Masterstation (baugleich mit den Stationen an den Standorten) aufgesetzt, die die CF-Karten bespielt, mit denen die VPN-Gateways an den Standorten bestückt werden.
1.141.1. DSL-Einwahl
1.141.1.1. /etc/rc.local
...other stuff
# PPPOE
/sbin/ifconfig re0 up && /usr/sbin/ppp -ddial pppoe
...other stuff
Kommentar:
re0 ist in diesem Fall das zu benutzende Interface.
Das Interface muss vor der Einwahl auf UP gesetzt werden.
1.141.1.2. /etc/ppp/ppp.conf
default:
set log Phase Chat LCP IPCP CCP tun command
set redial 10 0
set reconnect 10 10000
pppoe:
set device "!/usr/sbin/pppoe -i re0"
disable acfcomp protocomp
deny acfcomp
set mtu 1484
set mru 1484
set mtu maximum 1492
set mru maximum 1492
set speed sync
disable ipv6 ipv6cp
set authname "xxxxxxxxxxxxxxxxxxxxxxxxxxxx@t-online.de"
set authkey "yyyyyyyy"
enable mssfixup
enable lqr
add default HISADDR
Kommentar:
re0 ist in diesem Fall das zu benutzende Interface.
authname und authkey muessen natürlich die entsprechenden Werte enthalten.
1.141.1.3. /etc/ppp/ppp.linkup
pppoe:
! sh -c "/sbin/pfctl -F all -f /etc/ppp/pf.conf -D EXT0IF=INTERFACE"
!bg sh -c "/usr/local/sbin/ddclient -daemon=0 -syslog -quiet retry -mail root"
!bg /sbin/isakmpd
Kommentar:
Die Konfigurationen der Firewall,des dd-Klienten sowie des ISAKMPD werden später erklärt.
pfctl flushed die aktuellen und lädt die neuen Firewallregeln. Es unterstützt die Übergabe von Variablenwerten in der Kommandozeile, d.h. EXT0IF taucht später in der pf.conf wieder auf. Es wird hier auf den Wert des von PPP verwendeten Interfaces, meist tun0, gesetzt.
Der ddclient erledigt die Aktualisierung des bei
dyndns.org
registrierten kanonischen Names anhand der dynamisch vergebenen IP-Adresse.Der ISAKMPD stellt die VPN-Verbindung zum VPN-Gateway her.
1.141.1.4. /etc/ppp/ppp.linkdown
MYADDR:
!bg sh -c "/bin/kill -KILL `/bin/cat /var/run/isakmpd.pid`"
! sh -c "/sbin/pfctl -F all -f /etc/pf.conf"
Kommentar:
Der ISAKMPD wird gestoppt.
Die Standard-Firewallregeln werden geladen.
1.141.1.5. Tägliche Neuanmeldung
Die DTAG erzwingt alle >24h eine Abmeldung der bestehenden DSL-Verbindung. Um diesen Reset zu einem von uns bestimmten Zeitpunkt kontrolliert zu gestalten, melden wir uns einmal alle 24h ab und wieder an.
1.141.1.5.1. crontab
2 * * * /path/to/restart.sh
1.141.1.5.2. restart.sh
#!/bin/sh
PPPID=`ps wax | awk '{if ($5 ~ "ppp" && $6 == "-ddial") {print $1}}'`
if [ $PPPID -gt 0 ]; then
kill -INT $PPPID
else
echo "$(basename $0): $PPPID is not a number"
echo "$(basename $0): can not terminate ppp"
exit 1
fi
exit 0
1.141.2. Firewall
Die Firewall sollte beim Systemstart aktiviert werden. Dazu muss in der
/etc/rc.conf
PF=YES
gesetzt werden. Es existieren zwei
pf.conf
. Die eine, /etc/pf.conf
, wird im Zustand ohne
DSL-Anbindung, die andere /etc/ppp/pf.conf
wird nach dem Aufbau der
DSL-Verbindung geladen.
1.141.2.1. /etc/pf.conf
INT0IF="rl0"
set skip on lo0
scrub in
block in
pass out keep state
antispoof quick for { lo0 $INT0IF }
1.141.2.1.1. /etc/ppp/pf.conf
INT0IF="rl0"
EXT0IF="tun0"
VPNGATE="aaa.bbb.ccc.ddd/xx"
ADMINNET="aaa.bbb.ccc.ddd/xx"
SERVERNET="aaa.bbb.ccc.ddd/xx"
HOMENET="aaa.bbb.ccc.ddd/xx"
DNSSERVER="aaa.bbb.ccc.ddd"
HTTPPROXYSERVER="aaa.bbb.ccc.ddd"
FTPPROXYSERVER="aaa.bbb.ccc.ddd"
IMAPSERVER="aaa.bbb.ccc.ddd"
SMTPSERVER="aaa.bbb.ccc.ddd"
OFFICESERVER="aaa.bbb.ccc.ddd"
MYSQLSERVER="aaa.bbb.ccc.ddd"
INFORMIXSERVER="aaa.bbb.ccc.ddd"
WSUSSERVER="aaa.bbb.ccc.ddd"
AVGSERVER="aaa.bbb.ccc.ddd"
NTPSERVER="aaa.bbb.ccc.ddd"
table <VPN_T> \
{ $VPNGATE }
set skip on { lo0 enc0 }
scrub all
block in log all
pass out keep state
block out log on $EXT0IF from $HOMENET to any
# FROM HERE TO VPNGATE #################################################
# ICMP
pass in on $INT0IF inet proto icmp all icmp-type 8 code 0 keep state
# DNS
pass in on $INT0IF proto udp from $HOMENET to $DNSSERVER port 53 keep state
# HTTP ########################################################################
pass in on $INT0IF proto tcp from $HOMENET to $HTTPPROXYSERVER port 3128 keep state
pass in on $INT0IF proto udp from $HOMENET to $HTTPPROXYSERVER port 3128 keep state
# IMAP ########################################################################
pass in on $INT0IF proto tcp from $HOMENET to $IMAPSERVER port { 993 } keep state
pass in on $INT0IF proto udp from $HOMENET to $IMAPSERVER port { 993 } keep state
# SMTP ########################################################################
pass in on $INT0IF proto tcp from $HOMENET to $IMAPSERVER port 25 keep state
# OFFICE SAMBA ########################################################################
pass in on $INT0IF proto { tcp udp } from $HOMENET to $OFFICESERVER port { 137 138 139 445 } keep state
# MYSQL ################################################################
pass in on $INT0IF proto { tcp udp } from $HOMENET to $MYSQLSERVER port { 1433 } keep state
# INFORMIX ################################################################
pass in on $INT0IF proto { tcp udp } from $HOMENET to $INFORMIXSERVER port { 1526 } keep state
# WSUS ################################################################
pass in on $INT0IF proto { tcp udp } from $HOMENET to $WSUSSERVER port { 8530 } keep state
# AVG ################################################################
pass in on $INT0IF proto { tcp udp } from $HOMENET to $AVGSERVER port { 135 137 139 445 4156 } keep state
# NTP ################################################################
pass in on $INT0IF proto { tcp udp } from $HOMENET to $NTPSERVER port { 123 } keep state
# VNC ################################################################
pass in on $INT0IF proto { tcp udp } from $HOMENET to { $ADMINNET $SERVERNET } port { 5800 5900 } keep state
# PRINT ################################################################
pass in on $INT0IF proto { tcp udp } from $HOMENET to { $SERVERNET } port { 9100 } keep state
# FROM VPNGATE TO HERE #################################################
# ICMP ########################################################################
pass in on enc0 from { $ADMINNET $SERVERNET } to $HOMENET keep state
# SSH #########################################################################
pass in on $EXT0IF proto tcp from { $VPNGATE } to ($EXT0IF) port 22 keep state
# CRYPT #######################################################################
pass out quick proto esp from any to <VPN_T>
pass in quick proto esp from <VPN_T> to any
pass out quick on enc0 from any to <VPN_T>
pass in quick on enc0 from <VPN_T> to any
pass out quick on $EXT0IF proto udp from any to <VPN_T> port = 500
pass in quick on $EXT0IF proto udp from <VPN_T> to any port = 500
###############################################################################
Kommentar: Der CRYPT-Abschnitt sollte analog in der pf.conf des VPN-Gateways auftauchen.
1.141.3. ddclient
Der ddclient
aktualisiert einen zuvor unter
www.dyndns.org angelegten Dynamischen DNS Host mit
dem Namen myvpnrouter.homeunix.net
.
1.141.3.1. /etc/ddclient.conf
daemon=300 # check every 300 seconds
syslog=yes # log update msgs to syslog
mail=root # mail all msgs to root
mail-failure=root # mail failed update msgs to root
pid=/var/run/ddclient.pid # record PID in file.
use=web # via web
protocol=dyndns2 # default protocol
server=members.dyndns.org # default server
login=xxxxxxxxx # default login
password=yyyyyyyyy # default password
wildcard=yes # add wildcard CNAME?
server=members.dyndns.org, \
protocol=dyndns2 \
myvpnrouter.homeunix.net
1.141.4. ISAKMPD
Der ISAKMPD wird benutzt, um eine VPN-Verbindung zum Haupt-LAN herzustellen. Zur Authentifizierung werden x509-Zertifikate verwendet. Die Maschine die den Zugang zum Haupt-LAN verwaltet nennen wir myvpngate. Unseren VPN-Router nennen wir myvpnrouter00.
1.141.4.1. /etc/isakmpd/isakmpd.policy
Keynote-version:2
Authorizer: "POLICY"
Conditions: app_domain == "IPsec policy" &&
esp_present == "yes" &&
esp_enc_alg != "null" -> "true";
Kommentar:
Diese Datei ist auf beiden Maschinen gleich.
1.141.4.2. VPN-Gateway
Die Gegenstelle unseres VPN-Routers ist ein VPN-Gateway, der Zugang zum eigentlichen LAN. Dieses wird wie folgt konfiguriert um mit mehreren VPN-Routern mit dynamischen Adressen jeweils einen VPN-Tunnel aufbauen zu können:
1.141.4.2.1. /etc/isakmpd/isakmpd.conf
[Phase 1]
Default= myvpnrouters
[Phase 2]
Passive-Connections= VPN-myvpngate-myvpnrouter00,VPN-myvpngate-myvpnrouter01
[myvpnrouters]
Phase= 1
Transport= udp
Configuration= main-mode
ID= my-ID
[my-ID]
ID-type= FQDN
Name= myvpngate
[VPN-myvpngate-myvpnrouter00]
Phase= 2
ISAKMP-peer= myvpnrouter00
Configuration= quick-mode
Local-ID= myvpngate-internal-network
Remote-ID= myvpnrouter00-internal-network
[VPN-myvpngate-myvpnrouter01]
Phase= 2
ISAKMP-peer= myvpnrouter01
Configuration= quick-mode
Local-ID= myvpngate-internal-network
Remote-ID= myvpnrouter01-internal-network
[myvpngate-internal-network]
ID-type= IPV4_ADDR_SUBNET
Network= 192.168.0.0
Netmask= 255.255.0.0
[myvpnrouter00-internal-network]
ID-type= IPV4_ADDR_SUBNET
Network= 10.0.0.0
Netmask= 255.255.255.0
[myvpnrouter01-internal-network]
ID-type= IPV4_ADDR_SUBNET
Network= 10.0.1.0
Netmask= 255.255.255.0
[x509-certificates]
CA-directory= /etc/isakmpd/ca/
Cert-directory= /etc/isakmpd/certs/
Private-key= /etc/isakmpd/private/myvpngate.key
[main-mode]
DOI=IPSEC
EXCHANGE_TYPE=ID_PROT
Transforms=BLF-SHA-RSA_SIG
[quick-mode]
DOI=IPSEC
EXCHANGE_TYPE=QUICK_MODE
Suites=QM-ESP-AES-SHA-SUITE
[Default-main-mode]
DOI= IPSEC
EXCHANGE_TYPE= ID_PROT
Transforms= 3DES-SHA,BLF-SHA
[Default-quick-mode]
DOI= IPSEC
EXCHANGE_TYPE= QUICK_MODE
Suites= QM-ESP-3DES-SHA-SUITE
[PGP-main-mode]
DOI= IPSEC
EXCHANGE_TYPE= ID_PROT
Transforms= CAST-SHA,3DES-MD5
[PGP-quick-mode]
DOI= IPSEC
EXCHANGE_TYPE= QUICK_MODE
Suites= QM-ESP-CAST-SHA-SUITE,QM-ESP-CAST-MD5-SUITE,QM-ESP-3DES-MD5-SUITE
[3DES-MD5]
ENCRYPTION_ALGORITHM= 3DES_CBC
HASH_ALGORITHM= MD5
AUTHENTICATION_METHOD= PRE_SHARED
GROUP_DESCRIPTION= MODP_1024
Life= LIFE_1_DAY
[CAST-SHA]
ENCRYPTION_ALGORITHM= CAST_CBC
HASH_ALGORITHM= SHA
AUTHENTICATION_METHOD= PRE_SHARED
GROUP_DESCRIPTION= MODP_1536
Life= LIFE_1_DAY
[LIFE_1_DAY]
LIFE_TYPE= SECONDS
LIFE_DURATION= 86400,79200:93600
1.141.4.3. VPN-Router
Diese Sektion beschreibt die Konfiguration unseres VPN-Routers.
1.141.4.3.1. /etc/isakmpd/isakmpd.conf
[Phase 1]
# Statische IP des VPN-Gateways
aaa.bbb.ccc.ddd= myvpngate
[Phase 2]
Connections= VPN-myvpnrouter00-myvpngate
[myvpngate]
Phase= 1
Transport= udp
Address= aaa.bbb.ccc.ddd
Configuration= main-mode
ID= my-ID
[my-ID]
ID-type= FQDN
Name= myvpnrouter00
[VPN-myvpnrouter00-myvpngate]
Phase= 2
ISAKMP-peer= myvpngate
Configuration= quick-mode
Local-ID= myvpnrouter00-internal-network
Remote-ID= myvpngate-internal-network
[myvpnrouter00-internal-network]
ID-type= IPV4_ADDR_SUBNET
Network= 10.0.0.0
Netmask= 255.255.255.0
[myvpngate-internal-network]
ID-type= IPV4_ADDR_SUBNET
Network= 192.168.0.0
Netmask= 255.255.0.0
[x509-certificates]
CA-directory= /etc/isakmpd/ca/
Cert-directory= /etc/isakmpd/certs/
Private-key= /etc/isakmpd/private/myvpnrouter00.key
[main-mode]
DOI=IPSEC
EXCHANGE_TYPE=ID_PROT
Transforms=BLF-SHA-RSA_SIG
[quick-mode]
DOI=IPSEC
EXCHANGE_TYPE=QUICK_MODE
Suites=QM-ESP-AES-SHA-SUITE
[Default-main-mode]
DOI= IPSEC
EXCHANGE_TYPE= ID_PROT
Transforms= 3DES-SHA,BLF-SHA
[Default-quick-mode]
DOI= IPSEC
EXCHANGE_TYPE= QUICK_MODE
Suites= QM-ESP-3DES-SHA-SUITE
[PGP-main-mode]
DOI= IPSEC
EXCHANGE_TYPE= ID_PROT
Transforms= CAST-SHA,3DES-MD5
[PGP-quick-mode]
DOI= IPSEC
EXCHANGE_TYPE= QUICK_MODE
Suites= QM-ESP-CAST-SHA-SUITE,QM-ESP-CAST-MD5-SUITE,QM-ESP-3DES-MD5-SUITE
[3DES-MD5]
ENCRYPTION_ALGORITHM= 3DES_CBC
HASH_ALGORITHM= MD5
AUTHENTICATION_METHOD= PRE_SHARED
GROUP_DESCRIPTION= MODP_1024
Life= LIFE_1_DAY
[CAST-SHA]
ENCRYPTION_ALGORITHM= CAST_CBC
HASH_ALGORITHM= SHA
AUTHENTICATION_METHOD= PRE_SHARED
GROUP_DESCRIPTION= MODP_1536
Life= LIFE_1_DAY
[LIFE_1_DAY]
LIFE_TYPE= SECONDS
LIFE_DURATION= 86400,79200:93600
1.141.5. x509-Zertifikate
Auf die Funktionsweise von Zertifikaten wird an dieser Stelle nicht weiter eingegangen. Um unsere Zertifikate erstellen zu können, müssen wir uns von einer autorisierten Stelle zertifizieren lassen: Das kostet Geld. Als echte BSDler verabscheuen wir den Kommerz und zertifizieren uns selbst: Erst erzeugen wir uns für unsere eigene CA einen privaten Schlüssel,
# openssl genrsa -des3 -out $CA_PRIVATEKEY $KEYLENGTH
generieren eine Zertifikatsanfrage
# openssl req -new -key $CA_PRIVATEKEY -out $CA_CERT_REQ
und zertifizieren uns selbst:
# openssl x509 -req -days $(($VALIDYEARS * 365)) -in $CA_CERT_REQ -signkey $CA_PRIVATEKEY \
-extfile $SSLDIR/x509v3.cnf -extensions x509v3_CA -out $CA_CERT
Eine Kopie von $CA_CERT wird auf der jeweiligen Gegenseite in dem
Verzeichnis abgelegt, das in der gegnerischen isakmpd.conf
als
CA-directory eingetragen ist. In der Regel ist das /etc/isakmpd/ca
.
Jetzt können wir unseren privaten Schlüssel erzeugen,
# openssl genrsa -out $PRIVATEKEY $KEYLENGTH
eine Zertifikatsanforderung erstellen,
# openssl req -new -key $PRIVATEKEY -out $CERTREQ
ein Zertifikat erstellen,
# export CERTFQDN=$FQDN
# openssl x509 -req -days $VALIDDAYS -in $CERTREQ -CA $CA_CERT -CAkey $CA_PRIVATEKEY \
-CAcreateserial -extfile $SSLDIR/x509v3.cnf -extensions x509v3_FQDN -out $CERT
und zuletzt das Zertifikat verifizieren.
# openssl verify -CAfile $CA_CERT $CERT
Bemerkung
Der Name der Organisation sollte sich von dem der Zertifizierungsstelle unterscheiden!
Jetzt können wir das Zertifikat umbenennen
# mv $CERT $(dirname "$CERT")/$FQDN.crt
und die Rechte auf den privaten Schlüssel einschränken:
# chmod 600 $CFGDIR/private/*
$FQDN sollte sich mit den Einträgen in der isakmpd.conf
decken, also
hier myvpngate bzw. myvpnrouter00. $FQDN.crt muss sowohl auf der
eigenen, als auch auf der gegnerischen Maschine abgelegt werden und zwar
jeweils dort, wo in der jeweiligen isakmpd.conf
unter
Cert-directory angegeben. $PRIVATEKEY bleibt logischerweise auf der
eigenen Maschine und wird so platziert, wie in der lokalen
isakmpd.conf
unter Private-key eingetragen.
Zuletzt geändert: 2023-07-22