Ziel dieses Lab soll es sein, 2 Endgeräte (debian-black und debian-blue) über 2 GENUscreens so miteinander zu verbinden, das die Verbindung zwischen den beiden GENUscreens mittels IPsec verschlüsselt erfolgt. Dabei tasten wir uns Schritt für Schritt an eine funktionierende Konfiguration heran.
Aber kommen wir erst einmal zum Laboraufbau:
Konfigurieren wir zuerst unsere Endgeräte, dabei handelt es sich in meinem Fall um 2 Debian11-Clients. Beiden verpassen wir in den jeweiligen Subnetzen eine passende IP (endet auf .100 sowie ein Default Gateway).
black# nano /etc/network/interfaces
allow-hotplug enp0s3
iface enp0s3 inet static
address 192.168.0.100
gateway 192.168.0.1
black# ifdown enp0s3
black# ifup enp0s3
black# ip a enp0s3
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:19:f7:74 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.100/24 brd 192.168.0.255 scope global enp0s3
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe19:f774/64 scope link
valid_lft forever preferred_lft forever
black# ip r
default via 192.168.0.1 dev enp0s3 onlink
169.254.0.0/16 dev enp0s3 scope link metric 1000
192.168.0.0/24 dev enp0s3 proto kernel scope link src 192.168.0.100
blue# nano /etc/network/interfaces
allow-hotplug enp0s3
iface enp0s3 inet static
address 172.16.0.100
gateway 172.16.0.1
Das reicht auch schon. Am Ende werden wir unsere Konfiguration testen, indem wir erfolgreich sowohl Ping als auch SSH zum gegenüberliegenden Client durchführen können (ein SSH-Server sollte natürlich auf deinem debian-blue bereits funktional sein).
Als nächstes kümmern wir uns um die beiden GENUscreens. Fangen wir mit der Grundkonfiguration beider Firewalls an. Wichtig ist bei allen Konfigurationsänderungen, das diese zwar bei „Änderung speichern“ immer übernommen, aber erst aktiviert werden, wenn oben rechts auf „Konfiguration übernehmen“ geklickt wird.
Zuerst prüfen wir die einzelnen Schnittstellen (RED, BLACK und BLUE) und erlauben grundsätzlich auf all diesen einen allgemeinen PING. Ansonsten empfehle ich dir eine passende Beschreibung der Schnittstelle, notwendig ist dies aber nicht.
Viel wichtiger ist die Zuordnung der IP-Adressen zu den einzelnen Schnittstellen:
Der Rechnername (Hostname) muss in beiden Fällen eindeutig sein, den benötigen wir später noch.
Wenn du dies hast, kannst du erste Pings vom debian-blue zur den nachfolgenden Schnittstellen testen:
black# ping 192.168.0.100
PING 192.168.0.100 (192.168.0.100) 56(84) bytes of data.
64 bytes from 192.168.0.100: icmp_seq=1 ttl=64 time=0.023 ms
black# ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=255 time=0.747 ms
black# ping 10.12.12.2
PING 10.12.12.2 (10.12.12.2) 56(84) bytes of data.
64 bytes from 10.12.12.2: icmp_seq=1 ttl=255 time=0.684 ms
black# ping 10.12.12.1
PING 10.12.12.1 (10.12.12.1) 56(84) bytes of data.
17 packets transmitted, 0 received, 100% packet loss, time 16383ms
Okay, wir können uns also selbst pingen, die LAN-Seite der eigenen Firewall, die WAN-Seite der eigenen Firewall, aber nicht die fremde Firewall. Die Erklärung ist ganz einfach, es ist nun mal eine Firewall! Und so verlassen die einzelnen Datenpakete unsere eigene Firewall nicht einmal. Das kannst du auch mit mit tcpdump -i em0 auf der Firewall testen (auf der ssh-Konsole). Es existieren unter Filter/Filterregeln schlicht noch keine Regeln, die überhaupt irgendetwas erlauben würden und die Standardregel lautet deny any any – also verbiete alles, was nicht erlaubt ist.
Also brauchen wir als nächstes eine Regel auf der eigenen Firewall (die fremde erlaubt ja ohnehin eingehende ICMP-Pakete (denke an deine Schnittstellenkonfiguration), die Datenpakete, die auf der LAN-Seite der eigenen Firewall eingehen, auch zur WAN-Seite weitergeleitet werden. Und da fangen wir mit ICMP ganz klein an. Unter Firewall/Dienste legen wir ganz unten durch einen Klick auf „anlegen“ einen neuen Dienst an, hier ICMP. Es existieren zwar bereits eine Menge vordefinierter Dienste, aber ICMP ist leider nicht dabei.
Als nächstes erstellen wir auf beiden Firewalls unter Filter/Filterregeln eine neue Regel, die ICMP auf allen Schnittstellen erlaubt. ICMP ist nicht böse, das geht schon so in Ordnung!
Und jetzt kannst du erneut den Ping versuchen (Konfigruation speichern und aktivieren nicht vergessen):
black# ping 10.12.12.1
PING 10.12.12.1 (10.12.12.1) 56(84) bytes of data.
64 bytes from 10.12.12.1: icmp_seq=109 ttl=254 time=0.819 ms
black# ping 172.16.0.100
PING 172.16.0.100 (172.16.0.100) 56(84) bytes of data.
64 bytes from 172.16.0.100: icmp_seq=1 ttl=62 time=1.79 ms
Prima, jetzt kommen wir mit unserem Ping bis zur Gegenseite.
Konfiguration IPsec
Jetzt machen wir uns ein „wenig“ mehr Sicherheit. Wir aktivieren auf allen Schnittstellen RED (also em0 auf beiden Firewalls) die Option „nur verschlüsselten Traffic erlauben“ (Konfiguration speichern und übernehmen nicht vergessen).
Anschließend pingen wir von debian-black unser Ziel debian-blue erneut an:
black# ping 172.16.0.100
PING 172.16.0.100 (172.16.0.100) 56(84) bytes of data.
4 packets transmitted, 0 received, 100% packet loss, time 3055ms
Was ist passiert? Da die Firewall auf den roten Schnittstellen nur noch verschlüsselten Datenverkehr zulässt, kommt ein ICMP hier nicht mehr durch. Es braucht also zwingend verschlüsselten Datenverkehr. Dazu erstellen wir uns als nächstes einen IPsec-Tunnel. IPSec arbeitet grundsätzlich auf den Ports 500 und wenn NAT im Spiel ist, auch 4500. Aber darum brauchst du dich bei der GENUscreen nicht kümmern, die notwendigen Filteregeln erstellt die GENUscreen für dich im Hintergrund.
Doch zuerst müssen wir die VPN-Basis-Einstellungen bei beiden GENUscreen konfigurieren:
Die externe Adresse ist die eigene WAN-Adresse, bei unserem Lab also die eigene IP-Adresse aus dem Subnetz 10.12.12.0/30. Im Produktivbetrieb kannst du an einem WAN-Interface, welches die IP-Adresse durch den Provider dynamisch zugewiesen bekommt, hier einfach die Schnittstelle anstatt der IP-Adresse auswählen.
Die interne(n) Adresse(n) sind das oder die Netzwerke deines LAN, welche für die andere Seite erreichbar sein sollen. Wenn du hier nichts angbibst, kann zwar der Tunnel trotzdem aufgebaut werden, aber die Gegenseite erreicht die Geräte in dem dahinterliegenden Netzwerk nicht (da das notwendige Routing nicht automatisch eingerichtet wird). Mehr Einstellungen sind nicht notwendig. Aber stopp! Nach einem Klick auf „Änderungen übertragen“ siehst du spätestens dann, wie im Beispiel oben, den Link zu „Anzeigen es aktuellen öffentlichen Schlüssels“. Klick darauf und kopiere den angezeigten Inhalt (RSA-Key) in die Zwischenablage oder ein Notepad, denn den brauchst du im nächsten Schritt, wenn wir den Partner konfigurieren:
Hier ist jetzt der Name ganz oben sehr wichtig, dabei handelt es sich um den Hostnamen (Rechnername) der fremden Firewall und muss mit der Realität übereinstimmen.
Die externe Adresse ist die IP der gegnerischen Firewall. Wenn die Gegenseite eine dynamische IP vom Provider zugewiesen bekommt, dann lass das Feld einfach leer (wie im Beispiel oben). Dann muss jedoch der Tunnelaufbau durch die andere Seite initiert werden (also im o.a. Beispiel muss black die Verbindung initieren).
Bei den internen Netzen handelt es sich um die Subnetze, aus denen du IP-Pakete der anderen Seite erlauben willst – du musst hier Eintragungen machen, sonst hast du zwar einen funktionierenden Tunnel, aber ansonsten keinen Datenverkehr.
Bei IKE-Schlüssel kommt der jeweilige Schlüssel der Gegenseite hinein, den du im letzten Schritt kopiert hast.
Wenn du alles richtig konfiguriert und die Änderungen aktiviert hast, sollte unter Überwachung/VPN folgendes Bild zu sehen sein (ist die Zeile rot und bei Tunnel steht „fehlt“ überprüfe deine Konfig):
Ein Ping zur Gegenseite klappt jetzt auch wieder:
black# ping 172.16.0.100
PING 172.16.0.100 (172.16.0.100) 56(84) bytes of data.
64 bytes from 172.16.0.100: icmp_seq=1 ttl=62 time=1.19 ms
Und so schaut der Verbindungsaufbau durch die Brille von tcpdump aus:
blue.local# tcpdump -i em0
tcpdump: listening on em0, link-type EN10MB
10:06:28.592448 10.12.12.2.isakmp > 10.12.12.1.isakmp: isakmp v1.0 exchange ID_PROT
cookie: 1b72016319d8f753->0000000000000000 msgid: 00000000 len: 204
10:06:28.593333 10.12.12.1.isakmp > 10.12.12.2.isakmp: isakmp v1.0 exchange ID_PROT
cookie: 1b72016319d8f753->1cac2a867eacc749 msgid: 00000000 len: 204
10:06:28.598579 10.12.12.2.isakmp > 10.12.12.1.isakmp: isakmp v1.0 exchange ID_PROT
cookie: 1b72016319d8f753->1cac2a867eacc749 msgid: 00000000 len: 380
10:06:28.602760 10.12.12.1.isakmp > 10.12.12.2.isakmp: isakmp v1.0 exchange ID_PROT
cookie: 1b72016319d8f753->1cac2a867eacc749 msgid: 00000000 len: 380
10:06:28.609201 10.12.12.2.isakmp > 10.12.12.1.isakmp: isakmp v1.0 exchange ID_PROT encrypted
cookie: 1b72016319d8f753->1cac2a867eacc749 msgid: 00000000 len: 348
10:06:28.612072 10.12.12.1.isakmp > 10.12.12.2.isakmp: isakmp v1.0 exchange ID_PROT encrypted
cookie: 1b72016319d8f753->1cac2a867eacc749 msgid: 00000000 len: 348
10:06:28.613516 10.12.12.2.isakmp > 10.12.12.1.isakmp: isakmp v1.0 exchange QUICK_MODE encrypted
cookie: 1b72016319d8f753->1cac2a867eacc749 msgid: d6a1b47a len: 172
10:06:28.613931 10.12.12.1.isakmp > 10.12.12.2.isakmp: isakmp v1.0 exchange QUICK_MODE encrypted
cookie: 1b72016319d8f753->1cac2a867eacc749 msgid: d6a1b47a len: 172
10:06:28.614550 10.12.12.2.isakmp > 10.12.12.1.isakmp: isakmp v1.0 exchange QUICK_MODE encrypted
cookie: 1b72016319d8f753->1cac2a867eacc749 msgid: d6a1b47a len: 76
10:06:58.624219 10.12.12.2.isakmp > 10.12.12.1.isakmp: isakmp v1.0 exchange INFO encrypted
cookie: 1b72016319d8f753->1cac2a867eacc749 msgid: 491dbd63 len: 108
10:06:58.624457 10.12.12.1.isakmp > 10.12.12.2.isakmp: isakmp v1.0 exchange INFO encrypted
cookie: 1b72016319d8f753->1cac2a867eacc749 msgid: 5fdf43bc len: 108
10:07:19.590443 10.12.12.2 > 10.12.12.1: esp spi 0x4b427af9 seq 2 len 136 (DF)
10:07:19.590862 10.12.12.1 > 10.12.12.2: esp spi 0x00dedbf8 seq 2 len 136
10:07:20.592167 10.12.12.2 > 10.12.12.1: esp spi 0x4b427af9 seq 3 len 136 (DF)
10:07:20.592688 10.12.12.1 > 10.12.12.2: esp spi 0x00dedbf8 seq 3 len 136
Die letzten 4 Zeilen zeigen einen ICMP innerhalb des Tunnels, das weiß ich aber auch nur, weil ich in den Moment gepingt habe – es sind schließlich nur ESP-Pakete zu sehen..
So, als nächstes wollen wir SSH von der schwarzen zur blauen Seite einrichten:
black# ssh 172.16.0.100
The authenticity of host '172.16.0.100 (172.16.0.100)' can't be established.
ECDSA key fingerprint is SHA256:UnW1lehNyvRR+umy5uW83o/xQX08sKbWTGJ6STQDkRY.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '172.16.0.100' (ECDSA) to the list of known hosts.
root@172.16.0.100's password:
Debian GNU/Linux 11 (bullseye) (kernel 5.10.0-9-amd64)
Linux blue 5.10.0-9-amd64 #1 SMP Debian 5.10.70-1 (2021-09-30) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
blue~#
Wie du siehst, brauchst du keinerlei neuen Filterregeln, da die GENUscreen deinen IPsec-Tunnel fix und fertig konfiguiert, so das sämtlicher Datenverkehr den Tunnel passieren kann (mittels tcpdump siehst du nur noch ESP-Pakete).
In den Paketfiltereglen schaut das nämlich wie folgt aus:
blue.local# pfctl -s rules
...
pass on em0 proto esp all keep state (if-bound) tag PERMIT
pass on em0 proto udp from any to (self) port = 500 keep state (if-bound) tag PERMIT
pass on em0 proto udp from any to (self) port = 4500 keep state (if-bound) tag PERMIT
pass on em0 proto udp from (self) port = 500 to any keep state (if-bound) tag PERMIT
pass on em0 proto udp from (self) port = 4500 to any keep state (if-bound) tag PERMIT
...
pass in on em0 inet proto udp from any port = 500 to 10.12.12.1 port = 500 keep state (if-bound) label "ipsec0"
pass in on em0 inet proto udp from any port = 500 to 10.12.12.1 port = 4500 keep state (if-bound) label "ipsec0"
pass in on em0 inet proto udp from any port = 4500 to 10.12.12.1 port = 500 keep state (if-bound) label "ipsec0"
pass in on em0 inet proto udp from any port = 4500 to 10.12.12.1 port = 4500 keep state (if-bound) label "ipsec0"
pass out on em0 inet proto udp from 10.12.12.1 port = 500 to any port = 500 keep state (if-bound) label "ipsec0"
pass out on em0 inet proto udp from 10.12.12.1 port = 500 to any port = 4500 keep state (if-bound) label "ipsec0"
pass out on em0 inet proto udp from 10.12.12.1 port = 4500 to any port = 500 keep state (if-bound) label "ipsec0"
pass out on em0 inet proto udp from 10.12.12.1 port = 4500 to any port = 4500 keep state (if-bound) label "ipsec0"
pass in on em0 inet proto esp from any to 10.12.12.1 keep state (if-bound) label "ipsec0"
pass out on em0 inet proto esp from 10.12.12.1 to any keep state (if-bound) label "ipsec0"
pass in quick on enc0 inet proto ipencap from any to 10.12.12.1 keep state (if-bound) label "ipsec0.ipip" tagged ipsec0
IPsec über NAT
Im letzten Schritt möchte ich dir noch zeigen, wie du den Tunnel über NAT aufbauen kannst, doch zuvor ein tcpdump-Auszug beim Debian-blue wenn ein Ping ankommt (du siehst also die realen IP-Adressen der Endgeräte, also kein NAT).
black# ping 172.16.0.100
PING 172.16.0.100 (172.16.0.100) 56(84) bytes of data.
64 bytes from 172.16.0.100: icmp_seq=1 ttl=62 time=1.08 ms
64 bytes from 172.16.0.100: icmp_seq=2 ttl=62 time=1.21 ms
blue# tcpdump -i enp0s3
11:39:45.083290 192.168.0.100 > 172.16.0.100: icmp: echo request (DF)
11:39:45.083933 172.16.0.100 > 192.168.0.100: icmp: echo reply
11:39:46.084690 192.168.0.100 > 172.16.0.100: icmp: echo request (DF)
11:39:46.085094 172.16.0.100 > 192.168.0.100: icmp: echo reply
Wir gehen in unserem Lab davon aus, das die schwarze Seite an der WAN-Seite der Firewall geNATtet werden soll. Dazu sind jetzt Änderungen unter Filter/Adressumsetzung (NAT) auf der scharzen GENUscreen als auch Änderungen in der VPN-Partner-Konfig auf der blauen Genuscreen notwendig.
Auf den ersten Blick wirst du keinerlei Änderungen im Verhalten feststellen, da dein Ping ohnehin durch den Tunnel rauscht und es für das IP-Paket selbst keinen Unterschied macht, ob da jetzt NAT ist oder nicht.
Und auch auf den zweiten Blick nicht, den ich wiederhole es nochmal ganz deutlich. Dadurch, das dein ICMP-Paket in den IPsec-Tunnel geroutet wird und erst auf der anderen Seite wieder herauskommt, merkt es nicht, bekommt es von den Schnittstellen unterwegs nichts mit und wird auch vom NAT-Prozess nicht beeinflusst.
bypass IPsec
Und hier ist es auch ganz wichtig zu erwähnen, das du auf gar keinen Fall jetzt Filterregeln schreiben solltest, die dir deine IP-Pakete ggf. NATten, da alle IP-Pakete für die Gegenseite in den Tunnel „geworfen“ werden. Nur wenn es Filteregeln geben soll, die Verbindungen außerhalb des Tunnels zulassen sollen (z.B. HTTP(s)-Zugriff auf einen externen Webserver wie z.B. unter https://203.0.113.1 (also außerhalb unseres Site-to-Site-Netzwerkes)), muss auf diesen Filteregeln auch die NAT-Konfiguration auf em0 gebunden werden.
Und jetzt viel Erfolg bei der Umsetzung 😉