Netzwerksicherheit Linuxhotel April 2019 (Debian)

1 Informationen zum Kurs

3 Forwarding und Routing unter Linux

  • Debian 9 VMs
  • Benutzer: nutzer, Password: villa
  • Root-Shell per su - und dem Passwort vogelsang
  • IP Adressen der Router
    • 01: 192.168.1.168 (Christian)
    • 02: 192.168.1.179 (Tom)
    • 03: 192.168.1.131 (Christoph)
    • 04: 192.168.1.128 (Holger)
    • 05: 192.168.1.109 (Carsten)
+--------+	       	  +--------+
| Client |	   	  | Server |
|        |	   	  |        |
| enp0s3 | 	   	  | enp0s3 |
+---+----+		  +----+---+
    |        Router	       |
    |       +------+       |
    | enp0s8|      | enp0s9|
    +-------+      +-------+
	    +---+--+
		|enp0s3 (externe Netze/Laptops)
  • MAC Adresse des Client: 08:00:00:00:0C:XX
  • MAC Adresse des Servers: 08:00:00:00:0F:XX
ssh nutzer@<ip-adresse>
su -
ip address show

3.1 Editoren auf den virtuellen Maschinen

  • emacs
  • vi (vim)
  • mg (Micro Emacs)
  • jove
  • nano
  • joe
  • weitere Editoren können/dürfen nachinstalliert werden

4 TMUX - terminal multiplexer

  • Auf dem Router
tmux
Aktion Tastaturkombination
Neues Terminal CTRL+B C
nächstes Terminal CTRL+B N
voheriges Terminal CTRL+B P
Terminal horizontal teilen CTRL+B "
Terminal vertikal teilen CTRL+B %
zwischen geteilten Terminals wechseln CTRL+B <cursor>
zwischen geteilten Terminals wechseln CTRL+B O
Terminal schliessen CTRL+B x
Tmux abhängen (detach) CTRL+B d
Tmux anhängen tmux attach
TMUX Kommandozeile CTRL+B :
Tastenkommandos in alle Fenster (Kommandozeile) set synchronize-panes

4.1 Zugang zum Server und zum Client

  • von einer MAC-Adresse zu einer IPv6 Adresse
08:00:27:ff:e8:ae
  • von 48bit auf 64bit erweitern per "FFFE"
08:00:27:FF:FE:ff:e8:ae
  • Bit 7 invertieren
0A:00:27:FF:FE:ff:e8:ae
  • Link-Lokaler IPv6 Prefix anfuegen und als IPv6 Adresse schreiben
fe80::a27:ff:feff:e8ae
  • vollständige IPv6 Adresse
fe80:0000:0000:0000:0a27:00ff:feff:e8ae
  • ausprobieren: im tmux je eine neue Pane für Server und Client erstellen, und dort an die beiden anderen VMs verbinden
  • Client:
ip link set up dev enp0s8
ping6 fe80::a00:ff:fe00:c0x%enp0s8
ssh nutzer@fe80::a00:ff:fe00:c0x%enp0s8
  • Server
ip link set up dev enp0s9
ping6 fe80::a00:ff:fe00:f0x%enp0s9
ssh nutzer@fe80::a00:ff:fe00:f0x%snp0s9
  • Hostnamen der Server VM ändern
hostnamectl set-hostname server0x
bash
  • Hostnamen der Client VM ändern
hostnamectl set-hostname client0x
bash

5 Quagga Router

  • wir arbeiten auf dem Router-VM Rechner
  • Empfehlung: tmux starten und in tmux arbeiten
  • auf dem Router Server den Hostnamen aendern (als root)
hostnamectl set-hostname router0X
  • um den neuen Hostnamen zu sehen, die Root-Shell beenden und per sudo -s eine neuen Root-Shell öffnen (oder mit bash eine neue Shell starten)
  • die Routing-Software quagga installieren (auf dem Router)
apt install quagga
  • Rechte auf dem Konfigurationsverzeichnis anpassen und den Quagga-Dienst starten
touch /etc/quagga/zebra.conf
touch /etc/quagga/vtysh.conf
systemctl enable zebra
systemctl start zebra
systemctl status zebra
ps aux | grep quagga
quagga    3214  0.0  0.0  24712   732 ?        Ss   21:58   0:00 /usr/lib/quagga/zebra --daemon -A 127.0.0.1
root      3232  0.0  0.1  14228   976 pts/1    S+   21:58   0:00 grep --color=auto quagga
  • IPv6 und IPv4 Konfiguration der Netzwerkschnittstellen enp0s8 (Client-Netz) und enp0s9 (Server-Netz) von der Quagga Kommanozeile (auf dem Router)
vtysh
router0X#
router0x# conf terminal
router0x(config)# interface enp0s8
router0x(config-if)# ipv6 address fd0x::1/64
router0x(config-if)# ipv6 nd prefix fd0x::/64 900 300
router0x(config-if)# no ipv6 nd suppress-ra
router0x(config-if)# no shutdown
router0x(config-if)# exit
router0x(config)# interface enp0s9
router0x(config-if)# ipv6 address 2001:db8:x::1/64
router0x(config-if)# ipv6 nd prefix 2001:db8:x::/64 900 300
router0x(config-if)# no ipv6 nd suppress-ra
router0x(config-if)# no shutdown
router0x(config-if)# exit
router0x(config)# exit
router0x# write
router0x# conf terminal
router0x(config)# interface enp0s8
router0x(config-if)# ip address 172.16.x.1/24
router0x(config-if)# exit
router0x(config)# interface enp0s9
router0x(config-if)# ip address 100.64.x.1/24
router0x(config-if)# exit
router0x(config)# exit
router0x# write
  • vom Router SSH auf den Server (neues TMUX Fenster oeffnen)
ssh nutzer@2001:db8:x::a00:ff:fe00:f0x
  • manuelle IPv4 Konfiguration auf dem Server
su -
hostnamectl set-hostname server0X
ip addr add 100.64.x.2/24 dev enp0s3
ip route add default via 100.64.x.1
  • IP Konfiguration fest einstellen in der Datei /etc/network/interfaces
iface enp0s3 inet static
        address 100.64.x.2
        netmask 255.255.255.0
        gateway 100.64.x.1
  • vom Router per SSH auf den Client (neues TMUX Fenster oeffnen)
ssh nutzer@fd0x::a00:ff:fe00:c0x
  • manuelle IPv4 Konfiguration auf dem Client
hostnamectl set-hostname client0X
ip addr add 172.16.x.2/24 dev enp0s3
ip route add default via 172.16.x.1
  • IP Konfiguration fest einstellen in der Datei /etc/network/interfaces
iface enp0s3 inet static
        address 172.16.x.2
        netmask 255.255.255.0
        gateway 172.16.x.1
  • Testen der Verbindungen
    • vom Server zum Router (auf dem Server):
ping 100.64.x.1
ping 172.16.x.1
ping6 2001:db8:x::1
ping6 fd0x::1
  • vom Client zum Router (auf dem Client):
ping 172.16.x.1
ping 100.64.x.1
ping6 fd0x::1
ping6 2001:db8:x::1
  • Geht ein 'ping' vom Server zum Client?

5.1 Routing (Forwarding)

  • Geht ein 'ping' vom Server zum Client?
  • Antwort: ohne IP-Forwarding - nein
  • Forwarding anschalten (in der Quagga Shell auf dem Router)
vtysh
router0x# conf terminal
router0x(config)# ip forwarding
router0x(config)# ipv6 forwarding
router0x(config)# exit
route0x# write

5.2 Verbindung in das Internet

  • Geht ein 'ping' von Router ins Internet (1.0.0.1)? (auf dem Router ausführen)
ping 1.1
  • geht ein 'ping' vom Server oder Client ins Internet (1.0.0.1)? (auf dem Server oder dem Client ausführen)
ping 1.1
  • Lösung: iptables Masquerading NAT (auch Cone-NAT oder NATPT oder NAT44 genannt)
  • auf dem Router in einer BASH-Shell (nicht im Quagga)
iptables -A POSTROUTING -t nat -o enp0s3 -j MASQUERADE
  • nach dem Eintragen des NAT nochmals Testen, ob ein 'ping' vom Client und Server in das Internet funktioniert

6 iptables/nftables Firewall

6.1 iptables

6.1.1 Chains

  • prerouting
  • input
  • output
  • forward
  • postrouting

6.1.2 Tables

  • filter (default)
  • nat
  • mangle
  • raw

6.1.3 Befehle

  1. Regeln auflisten
    iptables -L <chain> [-t <table>]
    iptables -L <chain> [-t <table>] -v -n
    
  2. Regeln einer Chain/Tabelle loeschen
    iptables -F <chain> [-t <table>]
    
  3. Default Policy setzen
    iptables -P <chain> [DROP|ACCEPT]
    
  4. Chain anlegen/loeschen
    iptables -N <chainname>
    iptables -X <chainname>
    
  5. Regeln anlegen/einfuegen/loeschen
    iptables -A <chain> <Regel>
    iptables -I <chain> <pos> <Regel>
    iptables -R <chain> <pos> <Regel>
    iptables -D <chain> <pos>/<Regel>
    

6.1.4 Regeln

ein "!" vor einem Regelelement negiert das Regelelement

-i <interface> # Eingangs-Interface
-o <interface> # Ausgangs-Interface
-s <ipaddr>    # Quelladresse
-d <ipaddr>    # Zieladresse
-p <protocol>  # tcp, udp, icmp ...
-dport <port>  # Zielport
-sport <port>  # Quellport
-m <modul> <modulparameter> # Modul laden und benutzen
-j <target>    # Ziel der Regel (ACCEPT, DROP, REJECT ...)

6.1.5 Targets

-j RETURN # back to calling chain
-j LOG # syslog
-j REJECT [--reject-with <icmp-error-type>]
-j SNAT --to-source <addr>[-addr][:port-port] # nur POSTROUTING, Table "nat"
-j DNAT --to-destination <addr>[-addr][:port-port] # nur PREROUTING und OUTPUT, Table "nat"
-j REDIRECT --to-ports port[-port]
-j MASQUERADE --to-ports port[-port]
-j chain-name

6.1.6 Protokoll "tcp"

--syn # Verbindungsaufbau
--tcp-flags <mask> <active> # SYN,ACK,FIN,RST,URG,PSH,ALL,NONE
--tcp-flags SYN,RST,ACK SYN

6.1.7 Protokoll "icmp"

--icmp-type <icmp-type>
iptables -p icmp -h  # lists icmp types

6.1.8 Modul "state"

  • NEW
  • ESTABLISHED
  • RELATED
  • INVALID
-m state --state <state1[,state2,...]>

6.1.9 Modul 'recent'

  • Nur 3 SSH Anmeldeversuche per 15 Minuten
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 900 --hitcount 3 -j DROP

6.1.10 Logging

-j LOG --log-level <num>
-j LOG --log-prefix <prefix> # 14 chars
-j LOG --log-tcp-options
-j LOG --log-ip-options

6.1.11 Masqerading

// masquerading auf dem Router anschalten, server und client kommen nun ins Internet
iptables -A POSTROUTING -t nat -o enp0s3 -j MASQUERADE
iptables -L -t nat

6.1.12 Beispiel einer 'iptables' Script Preamble

#!/bin/sh

# default policy
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

# bestehene Regeln löschen (Firewall Reset)
iptables -F
iptables -F -t nat

# Loopback Interface erlauben
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

6.1.13 Beispiel eines Firewall-Stopp-Script

#!/bin/sh

iptables -P INPUT   ACCEPT
iptables -P OUTPUT  ACCEPT
iptables -P FORWARD ACCEPT

# bestehene Regeln löschen (Firewall Reset)
iptables -F
iptables -F -t nat

6.1.14 Firewall Regeln testen mit "Sicherheitsnetz"

  • Firewall-Regeln nach 1 Minute zurücksetzen
(sleep 60 && ./firewall-stopp.sh) &
./firewall.sh

6.2 Aufgabe Host-Firewall mit iptables

  • BIND 9 auf dem Router installieren, um eine Server Anwendung auf dem Router zu haben
apt install bind9 dnsutils
systemctl start bind9
  • Erstelle eine Host-Firewall-Regeln für den Router
    • ausgehend alle Verbindungen erlauben
    • eingehend auf enp0s3, enp0s8 und enp0s9 nur SSH (Port 22) und ICMPv4 erlauben
    • Verworfene Pakete in das syslog (Journal) schreiben
    • wer möchte kopiert seine Lösung in das Etherpad
  • Log-Ausgaben anschauen
journalctl -e  # an das Ende des Journal-Log springen
journalctl -f  # an das Ende des Journals springen und neue Einträge sofort anzeigen (wie tail -f)

6.2.1 Tests

  • Diese Tests sollen funktionieren
    • SSH vom Laptop zum Router
    • "ping" vom Router zum Internet-GW 192.168.1.5
    • "ping" vom Laptop zum Router
  • dieser Test sollten nicht funktionieren
    • DNS Anfrage von Laptop zum Router (auf dem Router läuft ein BIND 9 DNS Server) dig @<ip-des-routers> chaos txt authors.bind. Diese Anfrage sollte ein Timeout ergeben, das Paket an Port 53 der Firewall sollte verworfen werden (im Journal nachschauen)

6.2.2 eine mögliche Lösung

#!/bin/sh

# default policy
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

# bestehene Regeln loeschen (Firewall Reset)
iptables -F
iptables -F -t nat

# Loopback Interface erlauben
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# bestehende eingehende Verbindungen aus dem Internet erlauben
iptables -A INPUT  -i enp0s3 -m state --state RELATED,ESTABLISHED -j ACCEPT
# bestehende eingehende Verbindungen aus dem Client/Server-Netz erlauben
iptables -A INPUT  -i enp0s8 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT  -i enp0s9 -m state --state RELATED,ESTABLISHED -j ACCEPT

# bestehende ausgehende Verbindungen erlauben
iptables -A OUTPUT  -m state --state RELATED,ESTABLISHED -j ACCEPT

# neue ausgehende Verbindungen erlauben
iptables -A OUTPUT  -m state --state NEW -j ACCEPT

# NATPT fuer ausgehende Verbindungen
iptables -A POSTROUTING -t nat -o enp0s3 -j MASQUERADE

# SSH eingehend erlauben
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

# icmp eingehend erlauben
iptables -A INPUT -p icmp -j ACCEPT

# Pakete verwerfen und ins Syslog schreiben
iptables -A INPUT -j LOG --log-prefix "FW Drop:"
iptables -A INPUT -j DROP
  • aktives (Filter-Tabelle-) Regelwerk mit Regel-Nummern, Zählern und Interface-Abhängigkeiten anzeigen
iptables -L -v --line-numbers

6.3 Aufgabe: DNS Anfragen zum BIND 9 DNS-Server erlauben

  • Erweitere die Firewall, so das DNS-Anfragen (Port 53) vom Laptop zum Router möglich sind
  • Firewall-Regeln neu laden und dann die Firewall testen (vom Laptop aus)
dig @<ip-des-routers> txt chaos authors.bind
dig +tcp @<ip-des-routers> txt chaos version.bind

6.3.1 Lösung

[...]
# DNS eingehend erlauben
iptables -A INPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT
iptables -A INPUT -p udp --dport 53 -m state --state NEW -j ACCEPT
[...]

6.4 Firewall testen mit "nmap"

  • Test der Firewall vom Laptop aus (d.h. diese Befehle direkt auf dem Laptop ausführen)
apt install nmap
nmap -sT -v -A 192.168.1.yyy # <ip-der-firewall>
ip route add 172.16.x.0/24 via <ip-des-Firewall-Routers>
nmap -sT -v -A 172.16.x.0/24 # <ip-netz-hinter-der-firewall>

6.5 iptables Regeln sichern

router0x$ iptables-save > /etc/iptables.rules

6.6 iptables systemd unit

  • Datei /usr/local/sbin/iptables-flush
#!/bin/sh

iptables -P INPUT   ACCEPT
iptables -P OUTPUT  ACCEPT
iptables -P FORWARD ACCEPT

# bestehene Regeln löschen (Firewall Reset)
iptables -F
iptables -F -t nat
  • Datei ausführbar machen
chmod +x /usr/local/sbin/iptables-flush
  • Datei /etc/systemd/system/iptables.service
[Unit]
Description=IPTables Packet Filtering Framework
DefaultDependencies=no
After=systemd-sysctl.service
Before=sysinit.target
[Service]
Type=oneshot
ExecStart=/sbin/iptables-restore /etc/iptables.rules
ExecReload=/sbin/iptables-restore /etc/iptables.rules
ExecStop=/usr/local/sbin/iptables-flush
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
  • Systemd-Unit-Dateien neu laden
systemctl daemon-reload
  • iptables Unit ausprobieren
systemctl start iptables
iptables -L
systemctl stop iptables
iptables -L
  • Firewall beim Neustart anschalten
systemctl enable iptables

6.7 Anpassung des Firewall-Flush-Skripts

  • Firewall-Regeln aus dem Speicher sichern. Hiermit werden manuelle Änderungen an den Firewall-Regeln permanent gespeichert. Dies ist optional und nicht in allen Fällen erwünscht!
  • Datei /usr/local/sbin/iptables-flush
#!/bin/sh
# Firewall-Regeln sichern
iptables-save > /etc/iptables.rules

# Default-Policy öffnen
iptables -P INPUT   ACCEPT
iptables -P OUTPUT  ACCEPT
iptables -P FORWARD ACCEPT

# bestehene Regeln löschen (Firewall Reset)
iptables -F
iptables -F -t nat

6.8 Anpassung: vom Client zum Linuxhotel DNS-Resolver

  • SSH vom Router auf Client/Server erlauben, dafür die Zeilen
# bestehende eingehende Verbindungen aus dem Internet erlauben
iptables -A INPUT  -i enp0s3 -m state --state RELATED,ESTABLISHED -j ACCEPT
  • ersetzen durch
# bestehende eingehende Verbindungen erlauben
iptables -A INPUT  -m state --state RELATED,ESTABLISHED -j ACCEPT
  • Erstelle Regeln, welche dem Client erlauben, per DNS Port 53 (UDP/TCP) auf den DNS-Resolver im Linuxhotel (192.168.1.5) zuzugreifen
[...]
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s 172.16.x.0/24 -d 192.168.1.5 -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -s 172.16.x.0/24 -d 192.168.1.5 -p tcp --dport 53 -j ACCEPT
[...]
  • DNS-Resolver in der /etc/resolv.conf auf der Client VM eintragen
client0x$ echo "nameserver 192.168.1.5" > /etc/resolv.conf
  • Test der Namensauflösung
ping one.one.one.one
  • eine Regel in der Chain FORWARD für icmp (IPv4) hinzufügen, damit der ping auch das Internet erreicht
iptables -A FORWARD -s 172.16.x.0/24 -d 192.168.1.5 -p icmp -j ACCEPT

6.9 Aufgabe - Regeln für Paket-Installation:

  • welche weiteren Regeln müssen in der Firewall eingetragen werden, um Paketinstallationen auf dem Client per apt install zu erlauben?
  • erstelle die Regeln und teste die Pakete dnsutils und links zu installieren (ein Text-Webbrowser) (apt install links dnsutils)
  • Testen, das der Client (VM) DNS-Namensauflösung über den DNS-Resolver im Linuxhotel-Netzwerk machen kann
ssh nutzer@172.16.x.2

client0x$ dig @192.168.1.5 linuxhotel.de A
; <<>> DiG 9.9.6-P1 <<>> @192.168.1.5 linuxhotel.de
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12224
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;linuxhotel.de.                 IN      A

;; ANSWER SECTION:
linuxhotel.de.          3599    IN      A       217.69.87.63

;; Query time: 47 msec
;; SERVER: 192.168.1.5#53(192.168.1.17)
;; WHEN: Tue Jan 19 04:38:16 CET 2016
;; MSG SIZE  rcvd: 58

6.10 Lösung - Regeln für Paket-Installation:

[...]
iptables -A FORWARD -s 172.16.x.0/24  -p tcp --dport 80  -j ACCEPT
[...]

6.11 Verbindungen auf dem Router anschauen per iftop

router0x$ apt install iftop
router0x$ iftop -i enp0s3
  • Taste p schaltet die Anzeige der UDP/TCP Ports an
  • Taste n schaltet DNS-Rückwärtsauflösung für IP-Adressen aus

6.12 Aufgabe: Routing-Firewall

  • Erstelle erweiterte Regeln für das Routing des Router
    • SSH von Client/Firewall zum Server erlauben
    • HTTP (Port 80) vom Client zum Server erlauben
    • DNS von Client und vom Server ins Internet erlauben
    • HTTP (80) vom Client/Server ins Internet zulassen (fuer Software Updates)
    • Masquerading NAT für Verbindungen ins 'Internet'
    • vom Router DHCP ins Linuxhotel-Netz erlauben (Port 67/68 UDP)
    • keine anderen ausgehenden Verbindungen erlauben

6.12.1 Tests

  • SSH vom Client zum Server
client0x# ssh root@100.64.x.2
  • HTTP vom Client zum Server testen
    • auf dem Server einen Webserver-Prozess starten
server0x# python -m SimpleHTTPServer 80
  • auf dem Client einen Text-Modus Browser starten
    • die Dateien im Heimverzeichnis des Benutzers "root" auf dem Server sollten angezeigt werden (wenn keine Datei "index.html" vorliegt)
client0x# links 100.64.x.2
  • DNS vom Server ins Internet testen
server0x# dig @192.168.1.5 kernel.org a
  • http/https vom Server/Client ins Internet testen
echo "nameserver 192.168.1.5" > /etc/resolv.conf
links www.linuxhotel.de
links https://notes.defaultroutes.de
  • auf dem Server/Client "nmap" installieren und von dort den Router und das Linuxhotel GW scannen (was laesst die Firewall von innen nach aussen durch)
apt install nmap
nmap -sT 172.16.x.1
nmap -sT 172.16.x.2
nmap -sT 100.64.x.1
nmap -sT 100.64.x.2
nmap -sT 192.168.1.5
  • bei einem Scan vom Server/Client oder von der Firewall in das Linuxhotel Netz oder ins Internet dürfen nur die Ports 53, 80 und 443 als offen angezeigt werden. Rechner in den Client und Server Netzen dürfen nur über diese Ports mit der Aussenwelt kommunizieren. Ein SSH vom Server ins Internet darf nicht möglich sein.

6.12.2 Eine mögliche Lösung

#!/bin/sh

iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

# bestehene Regeln löschen (Firewall Reset)
iptables -F
iptables -F -t nat

# Loopback Interface erlauben
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# bestehende ausgehende Verbindungen erlauben
iptables -A OUTPUT  -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

# bestehende eingehende Verbindungen erlauben
iptables -A INPUT  -m state --state RELATED,ESTABLISHED -j ACCEPT

# NATPT fuer ausgehende Verbindungen
iptables -A POSTROUTING -t nat -o enp0s3 -j MASQUERADE

# DHCPv4 ausgehen erlauben
iptables -A OUTPUT -p udp --dport 68 -m state --state NEW -j ACCEPT

# SSH eingehend erlauben
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

# SSH vom Router zum Server erlauben
iptables -A OUTPUT -o enp0s9 -p tcp --dport 22 -j ACCEPT

# SSH vom Router zum Client erlauben
iptables -A OUTPUT -o enp0s8 -p tcp --dport 22 -j ACCEPT

# SSH vom Client-Netz zum Server erlauben
iptables -A FORWARD -i enp0s9 -p tcp --dport 22 -j ACCEPT

# HTTP vom Client zum Server
iptables -A FORWARD -s 172.16.x.2 -d 100.64.x.2 -p tcp --dport 80 -j ACCEPT

# DNS ausgehend zulassen
iptables -A OUTPUT -o enp0s3 -m state --state NEW -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -o enp0s3 -m state --state NEW -p tcp --dport 53 -j ACCEPT

# DNS vom Client/Server zulassen
iptables -A FORWARD -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -p tcp --dport 53 -j ACCEPT

# HTTP/HTTPS vom Router/Client/Server zulassen
iptables -A FORWARD -o enp0s3 -m state --state new -p tcp --dport 80  -j ACCEPT
iptables -A FORWARD -o enp0s3 -m state --state new -p tcp --dport 443 -j ACCEPT
iptables -A OUTPUT  -o enp0s3 -m state --state new -p tcp --dport 80  -j ACCEPT
iptables -A OUTPUT  -o enp0s3 -m state --state new -p tcp --dport 443 -j ACCEPT

# icmp erlauben
iptables -A INPUT -p icmp -j ACCEPT

# Pakete verwerfen
iptables -A INPUT   -j LOG --log-prefix "FW INP Drop:"
iptables -A FORWARD -j LOG --log-prefix "FW FRW Drop:"
iptables -A OUTPUT  -j LOG --log-prefix "FW OUT Drop:"
iptables -A INPUT -j DROP
iptables -A FORWARD -j DROP
iptables -A OUTPUT -j DROP

6.13 Beispiel Destination-NAT (DNAT)

  • Zugriff vom Laptop zum Webserver auf der Server VM (in das Firewall-Skript an passender Stelle einbauen)
# HTTP vom Internet auf Server zulassen
iptables -A FORWARD -i enp0s3 -m state --state new -p tcp --dport 80 -j ACCEPT
  • Auf dem Server eine kleine Webseite erzeugen und den Webserver starten
echo "dies ist der Server" > ~/index.html
cd ~
python -m SimpleHTTPServer 80
  • Auf dem Laptop eine Route auf den Server setzen und dann per Firefox auf die URL http://100.64.x.2 gehen
ip route add 100.64.x.0/24 via 192.168.1.xxx
  • Auf dem Client (der hier die Rolle eines Backup-Webserver einnimmt) eine kleine Webseite erzeugen und den Webserver starten
echo "dies ist der Client" > ~/index.html
cd ~
python -m SimpleHTTPServer 80
  • Backup DNAT um Anfragen an den Webserver 100.64.x.2 auf den Client "umzuleiten"
# HTTP per DNAT von Server auf den Client "umbiegen"
iptables -A PREROUTING -t nat -i enp0s3 -p tcp --dport 80 \
    -j DNAT --to-destination 172.16.x.2
  • Alternative, wenn das Ziel eine Anwendung auf der Firewall-Maschine ist
iptables -A PREROUTING -t nat -i enp0s3 -p tcp --dport 80 \
    -j REDIRECT --to-port 3128

6.14 Firewall Monitoring/Log-Auswertung

6.14.1 Templater installieren

  • auf dem Router als Benutzer root
apt install git automake autoconf gcc make
mkdir ~/src
cd ~/src
git clone https://github.com/rondilley/tmpltr.git
cd tmpltr
./bootstrap
autoreconf -i
./configure
make
make install

6.14.2 iptables Log mit "tmpltr" auswerten

  • iptables Log mit tmpltr auswerten
journalctl |  grep "kernel: FW" | tmpltr - | sort -n |  sed -e 's/%s.*||//'
  • Templates abspeichern, dann "ignore" Datei bearbeiten. z.B. Log-Ausgaben zu Multicast-DNS oder OSPF (Multicast-IP 224.0.0.5) ausfiltern.
journalctl |  grep "kernel: FW" | tmpltr -w fw.ignore -
  • Log mit "ignore" Datei auswerten
journalctl |  grep "kernel: FW" | tmpltr -t fw.ignore - | sort -n |  sed -e 's/%s.*||//'

6.15 Shorewall

systemctl stop iptables
systemctl disable iptables
  • Installation unter Debian
apt install shorewall
  • /etc/shorewall/zones - firewall "zonen" (5 Zeichen)
#ZONE   TYPE    OPTIONS                 IN                      OUT
#                                       OPTIONS                 OPTIONS
fw      firewall
net     ipv4
loc     ipv4
dmz     ipv4
  • /etc/shorewall/interfaces - Interface zu Host Zuordnung
?FORMAT 2
###############################################################################
#ZONE           INTERFACE               OPTIONS
net             enp0s3                    dhcp
loc             enp0s8
dmz             enp0s9
  • /etc/shorewall/masq - Masquerading und SNAT
#INTERFACE:DEST         SOURCE          ADDRESS         PROTO   PORT(S) IPSEC   MARK    USER/   SWITCH  ORIGINAL
#                                                                                       GROUP           DEST
enp0s3:                 100.64.x.0/24,172.16.x.0/24
  • /etc/shorewall/policy - generische Policy zwischen Zonen
#SOURCE         DEST            POLICY          LOG LEVEL       LIMIT:BURST
loc             net             ACCEPT
net             all             DROP            info
# THE FOLLOWING POLICY MUST BE LAST
all             all             REJECT          info
  • /etc/shorewall/rules - Ausnahmen zu der Policy zwischen Zonen (Firewallregeln)
#ACTION         SOURCE          DEST            PROTO   DEST    SOURCE          ORIGINAL        RATE          USER/   MARK    CONNLIMIT       TIME            HEADERS         SWITCH          HELPER
#                                                       PORT    PORT(S)         DEST            LIMIT           GROUP
?SECTION ALL
?SECTION ESTABLISHED
?SECTION RELATED
?SECTION INVALID
?SECTION UNTRACKED
?SECTION NEW
# Kaputte Pakete stoppen
#
Invalid(DROP)   net             all             tcp

# DNS Firewall -> Internet
#
DNS(ACCEPT)     $FW             net
#
#
# SSH von Lokal zu DMZ, Firewall
#
SSH(ACCEPT)     loc             $FW
SSH(ACCEPT)     loc             dmz
#
# SSH von der Firewall zum Client, Server
##
SSH(ACCEPT)     $FW             loc
SSH(ACCEPT)     $FW             dmz
#
#
# SSH von Internet zu Firewall
#
SSH(ACCEPT)     net             $FW
#
# DNS aus der DMZ ins Internet
#
DNS(ACCEPT)     dmz             net
# Kein "ping" auf die Firewall
#
Ping(DROP)      net             $FW
#
# ping zwischen loc, firewall, dmz
#
Ping(ACCEPT)    loc             $FW
Ping(ACCEPT)    dmz             $FW
Ping(ACCEPT)    loc             dmz
Ping(ACCEPT)    dmz             loc
Ping(ACCEPT)    dmz             net
ACCEPT          $FW             net             icmp
ACCEPT          $FW             loc             icmp
ACCEPT          $FW             dmz             icmp
  • /etc/shorewall/stoppedrules - Regeln aktiv wenn die Firewall gestoppt wird/ist
ACCEPT          enp0s3            -
ACCEPT          -               enp0s3
ACCEPT          enp0s8            -
ACCEPT          -               enp0s8
ACCEPT          enp0s9            -
ACCEPT          -               enp0s9
  • /etc/shorewall/shorewall.conf - Globale Konfiguration des Shorewall Programms
[...]
STARTUP_ENABLED=yes

LOGFILE=/var/log/shorewall
[...]
  • Shorewall starten
touch /var/log/shorewall
shorewall start
  • die von Shorewall erzeugten iptables Regeln anzeigen
iptables -L
iptables -L -t nat 
  • Shorewall stoppen (ACHTUNG! Stoprules sind aktiv)
shorewall stop
  • Shorewall Regeln löschen (Firewall wird ausgeschaltet)
shorewall clear
  • Shorewall Regeln/Verbindungen anzeigen
shorewall ls
shorewall ls connections
shorewall ls policies
shorewall ls routing
  • Shorewall über Systemd starten/anschalten/stoppen
systemctl enable shorewall
systemctl start shorewall
systemctl stop shorewall

6.16 Firewall Unittest und Dokumentation mit Emacs-Org-Mode und Babel

apt install emacs-nox ruby
  • Org-Babel-Dokument (, am Anfang der Zeilen entfernen, sind notwendig um Org-Mode innerhalb von einem Org-Mode Dokument einzubetten)
#+Title: Firewall-Dokumentation
#+Language: de

* Babel anschalten                                                 :noexport:
#+BEGIN_EXAMPLE                                                                                          
(org-babel-do-load-languages 'org-babel-load-languages                                                   
  '((ruby . t)                                                                                           
))                                                                                                       
#+END_EXAMPLE                                                                                            

#+BEGIN_SRC ruby :exports results
require 'time'
"Dieser Firewalltest wurde am #{Time.now}
 auf Rechner #{`hostname`} erstellt"
#+END_SRC

#+RESULTS:
: Dieser Firewalltest wurde am 2016-11-30 09:10:09 +0100
:  auf Rechner csmobile4.home.strotmann.de
:  erstellt

* Firewall Regeln

Dies sind unsere aktuellen Firewall Regeln

** INPUT Chain

*** Filter Tabelle

#+BEGIN_SRC ruby :exports results
`sudo iptables -L INPUT -t filter -v -n --line-numbers`
#+END_SRC

#+RESULTS:
#+begin_example
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:53
2        0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:53
3        0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:67
4        0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:67
5    63268   28M ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
6      591 41163 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
7     2655  631K INPUT_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0
8     2655  631K INPUT_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0
9     2655  631K INPUT_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0
10       0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
11     516 84169 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited
#+end_example

* Firewall Tests

 * Können wir das Internet über Port 80 erreichen?

#+BEGIN_SRC ruby :exports both
`nmap -sT linuxhotel.de -p 80`
#+END_SRC

#+RESULTS:
:
: Starting Nmap 7.12 ( https://nmap.org ) at 2016-11-30 09:16 CET
: Nmap scan report for linuxhotel.de (217.69.87.63)
: Host is up (0.030s latency).
: rDNS record for 217.69.87.63: namebased-hostings.villa-vogelsang.de
: PORT   STATE SERVICE
: 80/tcp open  http
:
: Nmap done: 1 IP address (1 host up) scanned in 0.53 seconds

6.16.1 ICMP Filter

  • Firewall-Regeln für ICMPv6 werden in RFC 4820: "Recommendations for Filtering ICMPv6 Messages in Firewalls" beschrieben
  • Unbedingt benötigte ICMPv6 Kommunikation
    • Destination Unreachable (Type 1) - All codes
    • Packet Too Big (Type 2)
    • Time Exceeded (Type 3) - Code 0 only
    • Parameter Problem (Type 4) - Codes 1 and 2 only
    • Echo request / Echo reply (needed for Teredo)
  • oft benötigte ICMPv6 Meldungen
    • Time Exceeded (Type 3) - Code 1
    • Parameter Problem (Type 4) - Code 0
    • Mobile IPv6 (nur wenn eingesetzt)
      • Home Agent Address Discovery Request (Type 144)
      • Home Agent Address Discovery Reply (Type 145)
      • Mobile Prefix Solicitation (Type 146)
      • Mobile Prefix Advertisement (Type 147)
  • selektiv Filtern (nur erlauben wenn diese Funktionen benutzt werden)
    • Node Information Query (Type 139)
    • Node Information Response (Type 140)
    • Router Renumbering (Type 138)
    • ICMPv6 mit experimentellen Nachrichten-Typen (100, 101, 200, and 201)
    • Erweiterungs-Nachrichten-Typen (Types 127 and 255)
  • alles andere Blocken, insbesondere
    • Seamoby Experimental (Type 150)
    • Unallocated Error messages (Types 5-99 inclusive and 102-126 inclusive)
    • Unallocated Informational messages (Types 154-199 inclusive and 202-254 inclusive)
  • Liste der ip6tables ICMPv6 Codes
ip6tables -p ipv6-icmp -h

6.16.2 Beispiel IPv6 Firewall

#!/bin/sh

# default policy
ip6tables -P INPUT DROP
ip6tables -P OUTPUT DROP
ip6tables -P FORWARD DROP

# bestehene Regeln löschen (Firewall Reset)
ip6tables -F
ip6tables -F -t nat

# Loopback Interface erlauben
ip6tables -A INPUT  -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

# Pakete mit RH0 (Routing Header 0, Source Routing) blocken
ip6tables -A INPUT -m rt --rt-type 0 -j DROP
ip6tables -A FORWARD -m rt --rt-type 0 -j DROP
ip6tables -A OUTPUT -m rt --rt-type 0 -j DROP

# bestehende eingehende Verbindungen aus dem Internet erlauben
ip6tables -A INPUT  -i enp0s3 -m state --state RELATED,ESTABLISHED -j ACCEPT

# bestehende eingehende Verbindungen aus dem Client-Netz erlauben
ip6tables -A INPUT  -i enp0s8 -m state --state RELATED,ESTABLISHED -j ACCEPT

# bestehende ausgehende Verbindungen erlauben
ip6tables -A OUTPUT  -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

# neue ausgehende Verbindungen erlauben
ip6tables -A OUTPUT  -m state --state NEW -j ACCEPT

# Link-Lokaler Multicast eingehend erlauben
ip6tables -A INPUT -s ff02::/16 -j ACCEPT

# Link-Lokale Kommunikation im Subnet erlauben
ip6tables -A INPUT -s fe80::/10 -j ACCEPT

# ICMPv6
ip6tables -A INPUT -p icmpv6 --icmpv6-type 1 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type 2 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type 3/0 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type 4/1 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type 4/2 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -m limit --limit 900/minute -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-reply   -m limit --limit 900/minute -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT
# ICMPv6 redirect erlauben (notwendig fuer Router-Fallback)
ip6tables -A INPUT -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j LOG --log-prefix "ICMPv6:"

6.17 nftables Firewall

systemctl stop shorewall
shorewall clear
iptables -L
iptables -L -t nat
  • "nftables" auf dem Router installieren
apt install nftables
  • root-Shell öffnen, ntf Version abfragen
nft -v
  • das nftables Ruleset auflisten (sollte am Anfang leer sein)
nft list ruleset
  • ein nft Ruleset für eine Host-Firewall, per Editor in die Datei /etc/nftables.conf schreiben
# Regelsatz löschen
flush ruleset

# Variable "any" definieren
define any = 0::0/0

table inet filter {
        chain input {
                type filter hook input priority 0;

                # accept any localhost traffic
                iif lo accept

                # accept traffic originated from us
                ct state established,related accept

                # activate the following line to accept common local services
                tcp dport { 22, 80, 443 } ct state new accept

                # NTP multicast
                ip6 daddr ff02::1010 udp dport 123 accept

                # mDNS (avahi)
                ip6 daddr ff02::fb udp dport 5353 accept
                ip  daddr 224.0.0.251 udp dport 5353 accept

                # DHCPv6
                ip6 saddr $any udp dport 546 accept

                # IPP (CUPS)
                tcp dport 631 accept

                # Accept neighbour discovery otherwise IPv6 connectivity breaks.
                ip6 saddr $any icmpv6 type { nd-neighbor-solicit,  
                                             nd-router-advert, 
                                             nd-neighbor-advert }  accept

                # Accept essential icmpv6
                ip6 saddr $any icmpv6 type { echo-reply, 
                                             echo-request, 
                                             packet-too-big, 
                                             destination-unreachable, 
                                             time-exceeded, 
                                             parameter-problem } accept

                # count and drop any other traffic
                counter log prefix "nftables drop: " drop
        }
}
  • nftables Firewall laden
systemctl start nftables
  • Regelwerk anzeigen
nft list ruleset
  • Log-Ausgaben anzeigen
journalctl -f | grep nftables
  • eigenen Router vom Laptop aus mit nmap scannen (einmal mit nftables Firewall eingeschaltet, danach mit der nftables Firewall ausgeschaltet. Gibt es einen Unterschied?)
nmap -sT 192.168.1.xxx # <--- IP Adresse des Routers

7 OSPF Routing mit Quagga

  • für die initiale Konfiguration des OSPF bitte die Firewall abschalten. Wir erstellen später Regeln für OSPF in unserer Firewall
  • OSPF Quagga Daemon starten
touch /etc/quagga/ospfd.conf
systemctl enable ospfd
systemctl start ospfd
systemctl status ospfd
  • Ordner für das Quagga Log anlegen
mkdir /var/log/quagga
chown quagga /var/log/quagga
  • OSPF Konfiguration
router0x$ vtysh
router0x# conf terminal
router0x(config)# log file /var/log/quagga/quagga.log
router0x(config)# router ospf
router0x(config-router)# network 192.168.1.0/24 area 0
router0x(config-router)# network 172.16.x.0/24 area 0
router0x(config-router)# network 100.64.x.0/24 area 0
router0x(config-router)# redistribute connected
router0x(config-router)# redistribute static
router0x(config-router)# router-id 192.168.1.yyy <-- IP Adresse auf enp0s3 des Routers
router0x(config-router)# end
router0x# write
Building Configuration...
Configuration saved to /etc/quagga/zebra.conf
Configuration saved to /etc/quagga/ospfd.conf
[OK]
router0x# show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, A - Babel,
       > - selected route, * - FIB route

K>* 0.0.0.0/0 via 192.168.1.5, enp0s3
C>* 100.64.x.0/24 is directly connected, enp0s9
C>* 127.0.0.0/8 is directly connected, lo
C>* 172.16.x.0/24 is directly connected, enp0s8
O   192.168.1.0/24 [110/10] is directly connected, enp0s3, 00:04:32
C>* 192.168.1.0/24 is directly connected, enp0s3
  • OSPF 'neighbors' anzeigen
router0x# show ip ospf neighbor
  • Traceroute vom eigenen Client auf einen Server eines andern Teilnehmers
traceroute 172.16.x.2
apt install mtr
mtr 172.16.x.2

7.1 OSPF mit Authentisierung

  • HMAC-MD5 Authentisierung der OSPF-Kommunikation einschalten. Es wird ein "Shared-Secret" verwendet, hier das Wort "VILLA". Aus dem Wort und den Daten wird eine Signatur für die OSPF Pakete erzeugt. Auf allen OSPF-Routern (einer Area) muss das gleiche Secret konfiguriert werden.
router0x$ vtysh
router0x# conf terminal
router0x(config)# interface enp0s3
router0x(config-if)# ip ospf authentication message-digest
router0x(config-if)# ip ospf message-digest-key 1 md5 VILLA
router0x(config-if)# exit
router0x# router ospf
router0x(config-router)# area 0 authentication message-digest
router0x(config-router)# exit
router0x(config)# exit
router0x# write
router0x# debug ospf packet all
  • Test: einen Server oder Router eines der anderen Teilnehmer per 'ping' erreichen (oder SSH).

7.2 OSPF in der Firewall

  • OSPF ist ein eigenes IP Protokoll (wie UDP oder TCP). Die Protokollnummer ist 89, der Protokoll-Name kann in der Datei /etc/protcols gefunden werden
grep ospf /etc/protocols
  • Beispiel OSPF Regel
iptables -A INPUT  -p ospf -s <Quell-Netzwerk> -j ACCEPT
iptables -A OUTPUT -p ospf -d 224.0.0.0/24     -j ACCEPT
  • Erweitere das IPTables Firewall Regelwerk für OSPF, starte danach den OSPFd Dienst auf dem Router neu un prüfe, ob der Routing-Dienst weiterhin die anderen Router "sehen" kann. Prüfe die Firewall-Logs auf neue Block-Meldungen.

9 WireGuard

  • Wir haben 5 virtuelle Maschinen im Internet (vm01-vm05.defaultroutes.de),
  • Benutzer root, Passwort netsec05!
  • Plan: VPN vom Laptop zur VM im Internet, alle Pakete vom Laptop sollen über das VPN und die VM im Internet gesendet werden

9.1 Wireguard Debian Installation (VPN-Client/VPN-Server)

  • Installationsinformationen für Wireguard https://www.wireguard.com/install/
  • Derzeit ist Wireguard noch nicht in den Linux-Kernel eingezogen, soll aber in Version ~5.2 in den Kernel kommen
  • der Laptop ist unser Wireguard-Client
  • auf dem Laptop und auf dem VPS Server im Internet das Wireguard Repository hinzufügen, Paketlisten updaten und Wireguard-Pakete installieren
echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list
printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable
apt update
apt install wireguard

9.2 Konfiguration Wireguard auf dem VPN-Server (Gateway)

  • User-Mask für neue Dateien und Verzeichnisse setzen, ein Verzeichnis für die Wireguard-Dateien erstellen
umask 077
mkdir /etc/wireguard
cd /etc/wireguard
  • einen privaten Schlüssel für den Wireguard-Dienst erstellen
wg genkey > private.key
  • Wireguard-Interface erstellen
ip link add dev wg0 type wireguard
  • IP-Adresse auf dem neuen Wireguard-Interface wg0 setzen
ip addr add 10.0.0.2/24 dev wg0
  • Privaten Schlüssel in das wg0 Interface laden
wg set wg0 private-key ./private.key
  • Interface wg0 aktivieren
ip link set wg0 up
  • Konfiguration der Schnittstelle anzeigen
wg show wg0

9.3 Konfiguration Wireguard auf dem VPN-Client

  • der Laptop ist unser VPN-Client
  • Wireguard installieren. Wurde ein neuer Linux-Kernel installiert, dann nach der Installation von Wireguard den Rechner neu starten, denn die Wireguard-Kernel-Module wurden schon für die neue Kernel-Version gebaut
echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list
printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable
apt update
apt install wireguard
  • Verzeichnis für die Wireguard-Dateien erstellen
umask 077
mkdir /etc/wireguard
cd /etc/wireguard
  • einen privaten Schlüssel für den Wireguard-Dienst erstellen
wg genkey > private.key
  • Wireguard-Interface erstellen
ip link add dev wg0 type wireguard
  • IP-Adresse auf dem neuen Wireguard-Interface wg0 setzen
ip addr add 10.0.0.1/24 dev wg0
  • Privaten Schlüssel in das wg0 Interface laden
wg set wg0 private-key ./private.key
  • Interface wg0 aktivieren
ip link set wg0 up
  • öffentlicher Schlüssel, erlaubte IP-Adressen und IP/Port des VPN-Servers eintragen
wg set wg0 peer <schlüssel> allowed-ips 0.0.0.0/0 endpoint <vpn-server>:<port>
  • Konfiguration der Schnittstelle anzeigen
wg show wg0
  • Konfiguration in die Konfigurationsdatei speichern
wg showconf wg0 > /etc/wireguard/wg0.conf
chmod 0600 /etc/wireguard/wg0.conf
  • Konfigurationsdatei anpassen, Address einfügen und Abschnitt Peer
[Interface]
ListenPort = <port>
PrivateKey = <private-key>
Address = 10.0.0.1/24

[Peer]
PublicKey = <public-key>
AllowedIPs = 0.0.0.0/0
Endpoint = <ip-of-vpn-server>:<port>

9.4 Client auf dem Server erlauben

  • auf dem VPN-Server, die Wireguard-Configuration speichern
wg showconf wg0 > /etc/wireguard/wg0.conf
chmod 0600 /etc/wireguard/wg0.conf
  • Konfigurationsdatei anpassen (Address und Abschnitt Peer)
[Interface]
ListenPort = <port>
PrivateKey = <private-key>
Address = 10.0.0.2/24

[Peer]
PublicKey = <public-key-of-client>
AllowedIPs = 10.0.0.1/32

9.5 IP-NATPT auf dem Server und IPv4-Forwarding anschalten

iptables -A POSTROUTING -t nat -o eth0 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf

9.6 Wireguard manuell aktivieren

  • auf dem VPN-Gateway
oot@debian-s-1vcpu-1gb-ams3-01:/etc/wireguard# wg-quick down wg0
[#] ip link delete dev wg0
root@debian-s-1vcpu-1gb-ams3-01:/etc/wireguard# wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip link set mtu 1420 up dev wg0
[#] ip route add 10.0.0.1/32 dev wg0
  • auf dem VPN-Client
root@router05:/etc/wireguard# wg-quick down wg0
[#] ip link delete dev wg0
root@router05:/etc/wireguard# wg-quick up wg0                                                                   
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip link set mtu 1420 up dev wg0
[#] wg set wg0 fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0

9.7 VPN Test

  • Ping vom VPN-Client Wireguard-IP zum VPN-Server
ping 10.0.0.2

9.8 DNS Resolver auf einen Resolver im Internet setzen

  • der DNS-Resolver des Linuxhotels ist über den Tunnel nicht erreichbar, daher müssen wir einen DNS-Resolver im Internet benuzten (oder, besser, einen eigenen DNS-Resolver auf dem VPN-Gateway-Server).
echo "nameserver 1.1.1.1" > /etc/resolv.conf

9.9 Tests der Wireguard-Verbindung

  • Sichtbare IP-Adresse des Client mit und ohne Wireguard prüfen, z.B. per Firefox auf der Seite https://ripe.net
  • Route zu einem Host im Internet per mtr testen, mit und ohne Wireguard
  • Wireguard aktivieren, mtr auf einen Server im Internet laufen lassen. Dann von Ethernet (Kabel) auf WLAN umschalten, der mtr Trace darf nicht abbrechen, der Wireguard Tunnel überlebt das umschalten
apt install mtr
mtr -t google.com

9.10 Wireguard per systemd

  • die folgenden Schritte sowohl auf dem VPN-Gateway, als auch auf dem Client ausführen
  • manuell gestartetes Wireguard beenden
wg-quick down wg0
  • Wireguard per Systemd aktivieren
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
systemctl status wg-quick@wg0
● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
   Loaded: loaded (/lib/systemd/system/wg-quick@.service; enabled; vendor preset: enabled)
   Active: active (exited) since Mon 2019-05-06 16:18:02 EDT; 1s ago
     Docs: man:wg-quick(8)
	   man:wg(8)
	   https://www.wireguard.com/
	   https://www.wireguard.com/quickstart/
	   https://git.zx2c4.com/WireGuard/about/src/tools/man/wg-quick.8
	   https://git.zx2c4.com/WireGuard/about/src/tools/man/wg.8
  Process: 13492 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
 Main PID: 13492 (code=exited, status=0/SUCCESS)

May 06 16:18:02 router05 systemd[1]: Starting WireGuard via wg-quick(8) for wg0...
May 06 16:18:02 router05 wg-quick[13492]: [#] ip link add wg0 type wireguard
May 06 16:18:02 router05 wg-quick[13492]: [#] wg setconf wg0 /dev/fd/63
May 06 16:18:02 router05 wg-quick[13492]: [#] ip address add 10.0.0.1/24 dev wg0
May 06 16:18:02 router05 wg-quick[13492]: [#] ip link set mtu 1420 up dev wg0
May 06 16:18:02 router05 wg-quick[13492]: [#] wg set wg0 fwmark 51820
May 06 16:18:02 router05 wg-quick[13492]: [#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
May 06 16:18:02 router05 wg-quick[13492]: [#] ip -4 rule add not fwmark 51820 table 51820
May 06 16:18:02 router05 wg-quick[13492]: [#] ip -4 rule add table main suppress_prefixlength 0
May 06 16:18:02 router05 systemd[1]: Started WireGuard via wg-quick(8) for wg0.

9.11 Optional: Alternatives Routing auf dem Client ohne wg-quick

  • Alle Pakete (mit Aussnahme der Wireguard Pakete) sollen durch den VPN-Tunnel gesendet werden. Eine Split-Default-Route sorgt dafür, das wir die original Default-Route nicht verlieren
ip route add <ip-des-VPN-servers>/32 via 192.168.1.5 dev eth0
ip route add  0.0.0.0/1 via 10.0.0.2 dev wg0
ip route add  128.0.0.0/1 via 10.0.0.2 dev wg0
  • Test
# tracepath google.com
 1?: [LOCALHOST]                                         pmtu 1420
 1:  10.0.0.2                                             15.453ms 
 1:  10.0.0.2                                             15.446ms 
 2:  no reply
 3:  45.63.118.33                                         18.164ms 
 4:  no reply
 5:  ffm-b12-link.telia.net                               20.718ms 
 6:  ffm-bb4-link.telia.net                               15.889ms 
 7:  ffm-b1-link.telia.net                                16.062ms 
 8:  google-ic-319727-ffm-b1.c.telia.net                  15.997ms asymm 10
[...]

9.12 Optional: Wireguard mit alternativen Routing auf dem Client ausschalten

  • Routen löschen
ip r del 0.0.0.0/1 via 10.0.0.2 dev wg0
ip r del 128.0.0.0/1 via 10.0.0.2 dev wg0
ip r del <ip-des-vpn-servers> via 192.168.1.5 dev eth0
  • Wireguard Interface ausschalten
ip link set dev wg0 down

10 OpenVPN

  • OpenVPN auf dem Client und auf dem Server installieren
apt install openvpn
  • Schlüssel erzeugen und per gesicherten Kanal auf beide Endpunkte des VPN-Tunnels bringen (z.B. per Secure Copy "scp")
client0x# cd /etc/openvpn
client0x# openvpn --genkey --secret static.key
client0x# scp static.key root@100.64.x.2:/etc/openvpn/
  • Server-Konfiguration /etc/openvpn/server.conf (auf dem Server-Rechner)
dev tun
ifconfig 10.0.x.1 10.0.x.2
secret /etc/openvpn/static.key
  • Client-Konfiguration /etc/openvpn/client.conf (auf dem Client-Rechner)
remote 100.64.x.2
dev tun
ifconfig 10.0.x.2 10.0.x.1
secret /etc/openvpn/static.key
  • Treiber für Tunnel-Interface laden und OpenVPN start (Server)
modprobe tun
openvpn /etc/openvpn/server.conf &
  • Auf dem Server einen Webserver (Port 8000) starten
python -m SimpleHTTPServer 8000
  • OpenVPN start (Client)
modprobe tun
openvpn /etc/openvpn/client.conf &
  • Tunnel-Interfaces anzeigen
ip a
  • OpenVPN testen (mit tcpdump auf dem Router die Pakete anschauen tcpdump -i enp0s8 port 80 und tcpdump -i enp0s8 icmp )
client0x# ping 10.0.x.1
client0x# links http://10.0.x.1:8000

11 SSL/TLS

11.1 TLS-Einführung

11.2 x509 Zertifikate mit OpenSSL

  • RSA-Privaten Schluessel erstellen (2048 bit)
mkdir ~/tls
cd ~/tls
openssl genrsa -aes128 -out mykey.private 2048
less mykey.private
openssl rsa -text -in mykey.private | less
  • öffentlichen RSA-Schlüssel erzeugen
openssl rsa -in mykey.private -pubout -out mykey.public
less mykey.public
openssl rsa -text -pubin -in mykey.public | less
  • Certificate signing request (CSR) erstellen
openssl req -new -key mykey.private -out mycert.csr
less mycert.csr
openssl req -text -in mycert.csr -noout | less
  • CSR mit Konfigurationsdatei / mehrere Domain-Namen. Hier im Beispiel eine Datei mit dem Namen mycert.conf erstellen:
[req]
prompt = no
distinguished_name = dn
req_extensions = ext

[dn]
CN = ubu01do.strotmann.de
emailAddress = carsten@strotmann.de
O = Linuxhotel
L = Essen
C = DE

[ext]
subjectAltName = DNS:www.ubu01do.strotmann.de,DNS:ubu01do.strotmann.de
  • Certificate Signing Request mittels der Konfigurationsdatei erstellen
openssl req -new -config mycert.conf -key mykey.private -out mycert.csr
  • Self-Signed-Certificate erstellen (selbst signieren, ohne CA)
openssl x509 -req -days 365 -in mycert.csr -signkey mykey.private -out mycert.crt
  • x.509 Cert per OpenSSL anzeigen
openssl x509 -text -in mycert.crt -noout
  • Alternatives Kommando zum Erstellen eines Self-Signed Certificate: Self-Signed-Cert ohne CSR (Signing Reuqest Zwischenschritt)
openssl req -new -x509 -config mycert.conf -days 365 -key mykey.private -out mycert.crt

11.3 OpenSSL als TLS-Client um Zertifikate zu exportieren

  • per OpenSSL eine Verbindung zu einem Server erstellen (https und starttls für smtp, pop3, imap, ftp und xmpp)
openssl s_client -connect www.linuxhotel.de:443
openssl s_client -connect mx.openit.de:25 -starttls smtp
echo "quit" | openssl s_client -connect mx.openit.de:25 -starttls smtp > mx.openit.de.pem
openssl x509 -text -noout -in mx.openit.de.pem | less
  • TLS Server mit SNI (Server Name Indication)
openssl s_client -connect www.linuxhotel.de:443 -servername www.linuxhotel.de

11.4 TLS mit Caddy

  • Webseite des Caddy Webserver https://caddyserver.com
  • wir arbeiten auf dem Debian VPS im Internet
  • NGINX (und andere Server auf Port 80/443) stoppen
systemctl stop nginx
  • Vorbereitetes Caddy-Paket vom Schulungsserver laden
sudo -s
cd /srv
wget https://notes.defaultroutes.de/caddy.tgz
  • Caddy auspacken (Caddy ist in Go geschrieben, ist ein statisches Programm und muss nicht "installiert" werden)
tar xvfz caddy.tgz
rm caddy.tgz
mv caddy /usr/local/bin
  • Caddy Konfigurationsdatei vi Caddyfile
vm0x.defaultroutes.de {
        gzip
        tls nutzerXX@linuxhotel.de
        root /srv/website
}
  • Webseite erstellen
mkdir /srv/website
echo "Meine erste Caddy-Webseite" > /srv/website/index.html
  • Caddy starten
caddy -conf /srv/Caddyfile
  • Webseite im Firefox testen https://vm0x.defaultroutes.de/ Zertifikat anschauen

11.5 Let's Encrypt und das ACME Protokoll

11.5.1 Let's Encrypt Zertifikate mit acme.sh

  • Wir arbeiten auf der Debian VPS im Internet
  • Abhängigkeiten git und socat installieren. socat wird nur für die standalone Web-Challenge, nicht aber für die DNS-Challenge benötigt
apt install git socat
  • acme.sh per git aus dem Repository laden
git clone https://github.com/Neilpang/acme.sh
  • acme.sh installieren
cd acme.sh
./acme.sh --install --cert-home /etc/tls --home /etc/acme
  • Caddy stoppen (da wir acme.sh hier im standalone Modus betreiben und acme.sh einen eigenen Server auf Port 80 startet)
pkill caddy
  • Test: ein Zertifikat für den Namen vmXX.defaultroutes.de per standalone Webservice anfordern (Port 80 auf dem Server muss frei sein)
cd ~
source ~/.bashrc
acme.sh  --issue  -d vmXX.defaultroutes.de  --standalone --cert-home /etc/tls
[Tue Mar 20 11:27:00 UTC 2018] Standalone mode.
[Tue Mar 20 11:27:01 UTC 2018] Registering account
[Tue Mar 20 11:27:01 UTC 2018] Registered
[Tue Mar 20 11:27:02 UTC 2018] ACCOUNT_THUMBPRINT='B4YKRQUJv42qkv9SH_2JP-FD_JsEyKkmgt7wRVsug3c'
[Tue Mar 20 11:27:02 UTC 2018] Creating domain key
[Tue Mar 20 11:27:02 UTC 2018] The domain key is here: /etc/acme/.acme.sh/vmXX.defaultroutes.de/vmXX.defaultroutes.de.key
[Tue Mar 20 11:27:02 UTC 2018] Single domain='vmXX.defaultroutes.de'
[Tue Mar 20 11:27:02 UTC 2018] Getting domain auth token for each domain
[Tue Mar 20 11:27:02 UTC 2018] Getting webroot for domain='vmXX.defaultroutes.de'
[Tue Mar 20 11:27:02 UTC 2018] Getting new-authz for domain='vmXX.defaultroutes.de'
[Tue Mar 20 11:27:02 UTC 2018] The new-authz request is ok.
[Tue Mar 20 11:27:03 UTC 2018] Verifying:vmXX.defaultroutes.de
[Tue Mar 20 11:27:03 UTC 2018] Standalone mode server
[Tue Mar 20 11:27:06 UTC 2018] Success
[Tue Mar 20 11:27:06 UTC 2018] Verify finished, start to sign.
[Tue Mar 20 11:27:07 UTC 2018] Cert success.
-----BEGIN CERTIFICATE-----
MIIFDTCCA/WgAwIBAgISBGvqztwcY0p9jGrx/psiyxfLMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODAzMjAxMDI3MDdaFw0x
[...]
qIOIRUmRSuTLXDWjih7kTKSLzDr8NEsvIm9qh8EmUsPEYDqye0lU2hV1evaHZXkQ
pQOxfr9yf0eGvS5jj2kW1AVi2Dz3880c0M0jUJH7JyMOs3KrVk2VorGfVTctlx8c
4g==
-----END CERTIFICATE-----
[Tue Mar 20 11:27:07 UTC 2018] Your cert is in  /etc/tls/vmXX.defaultroutes.de/vmXX.defaultroutes.de.cer
[Tue Mar 20 11:27:07 UTC 2018] Your cert key is in  /etc/tls/vmXX.defaultroutes.de/vmXX.defaultroutes.de.key
[Tue Mar 20 11:27:08 UTC 2018] The intermediate CA cert is in  /etc/tls/vmXX.defaultroutes.de/ca.cer
[Tue Mar 20 11:27:08 UTC 2018] And the full chain certs is there:  /etc/tls/vmXX.defaultroutes.de/fullchain.cer
  • die Pfade zu den ACME-Zertifikaten in der NGINX-Configuration /etc/nginx/nginx.conf anpassen und NGINX neu starten
$EDITOR /etc/nginx/nginx.conf
systemctl start nginx
  • Webseite vm0X.defaultroutes.de testen. Dort sollte nun keine Zertifikatswarnung mehr erscheinen und das Schloss-Symbol in der URL-Leiste des Browsers sollte grün werden

11.6 Qualität der SSL/TLS Konfiguration eines Webservers testen

12 IPSec mit StrongSWAN

12.1 Installation

  • für die Übung die IPTables Firewall auf dem router ausschalten, Masquerading NAT für die Paketinstallation aber angeschaltet lassen
  • in einem separaten Terminal-Fenster auf dem Router ein tcpdump für icmp laufen lassen, um die Kommunikation zwischen Client und Server zu beobachten
router# tcpdump -i enp0s8 icmp
  • auf dem Client und auf dem Server
apt install strongswan

12.2 Konfiguration auf dem Client

  • Host-to-Host Tunnel Mode (Client) /etc/ipsec.conf
config setup

conn %default
     ikelifetime=60m
     keylife=20m
     rekeymargin=3m
     keyingtries=1
     keyexchange=ikev2
     authby=secret

conn host-host
     left=172.16.x.2
     right=100.64.x.2
     auto=add
  • Passwort (PSK) Client /etc/ipsec.secrets
: PSK 'sharedsecret'

12.3 Konfiguration auf dem Server

  • Host-to-Host Tunnel Mode (Server) /etc/ipsec.conf
config setup

conn %default
     ikelifetime=60m
     keylife=20m
     rekeymargin=3m
     keyingtries=1
     keyexchange=ikev2
     authby=secret

conn host-host
     left=100.64.x.2  # Konfig auf dem Server
     right=172.16.x.2 # Konfig auf dem Server
     auto=add
  • Passwort (PSK) Server /etc/ipsec.secrets
: PSK 'sharedsecret'

12.4 IPSec starten

  • IPSec Daemon starten (auf beiden Rechnern Server/Client)
ipsec restart
  • Status der Verbindungen abfragen (derzeit ist noch keine Verbindung aktiv)
ipsec status
ipsec statusall
  • IPSec Verbindung starten
ipsec up host-host
ipsec status
ipsec statusall
  • ein ping zwischen Client und Server VM sollte weiterhin möglich sein, jetzt aber auf dem Router mit tcpdump nicht mehr sichtbar sein
  • IPSec Status aus dem Linux-Kernel anzeigen
ip xfrm state

12.5 IPSec mit Wireshark prüfen

  • vom Laptop per SSH X11 Tunnel auf den Router verbinden
ssh -Y nutzer@192.168.1.xxx <-- IP des Routers
  • Wireshark installieren und den Benutzer nutzer der Gruppe wireshark hinzufügen, so das der Benutzer das Recht hat, per Sniffing Netzwerkpakete abzuhören
su -
apt install wireshark
usermod -a -G wireshark nutzer
exit

SSH Verbindung beenden, neu einloggen (damit die neue Gruppenzugehörigkeit aktiv wird) und Wireshark starten

router0x$ wireshark
  • Im Wireshark auf Interface enp0s8/enp0s9 sniffen
  • auf dem Server einen Webserver starten
server0$ python -m SimpleHTTPServer
  • auf dem Client die Webseite aufrufen
client0x$ links http://100.64.x.2:8000
  • Im Wireshark sollten wir zwischen der Client-IP und Server-IP nur ESP-, aber keine HTTP-Pakete
  • IPSec stoppen (ipsec down host-host), dann das Experiment ohne IPSec wiederholen. Es sollten nun die HTTP-Pakete im Wireshark sichtbar sein

12.6 IPSec Daten im Wireshark entschlüsseln

  • um per IPSec geschützte Daten im Wireshark entschlüsseln zu können, werden für jede Richtung (Security Association) benötigt: Quell-Adresse, Ziel-Adresse, SPI, Verschlüsselungs-Algorithmus, Verschlüsselungs-Schlüssel, Authentisierungs-Algorithmus und Schlüssel für die Authentisierung. Diese Daten werden auf einem Linux-Rechner mit aktiver IPSec Verbindung mit dem Befehl ip xfrm state angezeigt:
root@client05:~# ip xfr state
src 172.16.5.2 dst 100.64.5.2
        proto esp spi 0xc3d57e0e reqid 3 mode tunnel
        replay-window 0 flag af-unspec
        auth-trunc hmac(sha256) 0xebd9e051b05a07c89e51d4840ab2df87d8ca107385cee1bc291d0dd442293dd3 128
        enc cbc(aes) 0xd5719f2b10cd766bb7562099c0ee4bb5
        anti-replay context: seq 0x0, oseq 0x5, bitmap 0x00000000
src 100.64.5.2 dst 172.16.5.2
        proto esp spi 0xcf12dd2b reqid 3 mode tunnel
        replay-window 32 flag af-unspec
        auth-trunc hmac(sha256) 0xc82360181bc299d6931cc8061508740d5d25216f6b31ca93c436b65d27072c2e 128
        enc cbc(aes) 0x4e8a18060003b6727d8f8509e98310c5
        anti-replay context: seq 0x5, oseq 0x0, bitmap 0x0000001f
  • Diese Daten im Wireshark unter Edit -> Preferences -> Protocols -> ESP -> ESP SAs -> Edit eintragen. Alle Felder müssen gefüllt werden. Die Schlüssel werden in der Hexadezimalen Schreibweise mit vorangestelltem 0x (wie vom ip xfrm state Befehl ausgegeben) eingetragen.
  • Der Packet Trace im Wireshark wird nun dekodiert, die verschlüsselten Protokolle (z.B. HTTP) können analysiert werden.

13 TOR - The Onion Router

13.0.1 TOR Installieren

  • auf dem Laptop arbeiten
apt install tor
systemctl enable tor
systemctl start tor

13.0.2 TOR-Browser

  • den Tor-Browser von Tor-Projekt installieren ( http://www.torproject.org ) oder den Socksv5-Proxy im Browser auf Port 9050 einstellen

13.0.3 TOR-Onion-Services

  • Onion Hidden-Service auf Localhost Port 8000
$EDITOR /etc/tor/torrc
[...]
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:8000
[...]
  • Tor neu starten
systemctl restart tor
systemctl status tor
  • Webserver Service starten (einfacher Python Webserver auf Port 8000)
python -m SimpleHTTPServer
  • den Onion-Namen herausfinden (Datei /var/lib/tor/hidden_service/hostname) und an einen der Teilnehmer weitergeben
  • einen Onion-Dienst ansprechen, per Socks-Proxy aus dem Firefox oder mit dem Tor-Browser

13.1 Sicherheit

  • Einige Server-Dienste schalten spezielle Admin-Funktionen frei, wenn der Server über eine Loopback-Adresse (127.0.0.1) angesprochen wird (z.B. der Apache Webserver –> https://www.heise.de/security/meldung/Apache-verpetzt-moeglicherweise-Tor-Hidden-Services-3090218.html). Bei Bennutzung als Tor-Dienst auf einer Loopback-Adresse sind diese Admin-Funktionen von aussen über das Tor-Netzwerk erreichbar. Lösung: den Dienst auf einer nicht-Loopback Adresse konfigurieren, oder die speziellen Admin-Funktionen in der Server-Konfiguration ausschalten.

13.2 Onion-Dienst mit Client-Authentifizierung

Der Onion-Dienst, wie oben beschrieben, ist erreichbar für jeden Benutzer der den Onion-Namen kennt. Ein Onion-Name besteht derzeit aus 16 Zeichen (80 bit) und kann u.U. erraten werden. Um die Sicherheit des Onion-Dienstes noch weiter zu erhöhen, kann der Dienst mit einer Authentisierung versehen werden. Bei der Authentisierung bekommt jeder Client einen eigenen kryptografischen Schlüssel zugewiesen, und nur wenn dieser Schlüssel beim Verbindungsaufbau mit angegeben wird, ist der Onion-Dienst erreichbar (und sichtbar). Der Schlüssel ist ein Authentisierungs-Cookie aus 16 Bytes (Base64 kodiert) welcher zusätzlich zum Onion-Namen bekannt sein muss.

13.2.1 Authentisierung auf der Seite des Onion-Dienstes (Server)

Die Dienste-Authentisierung wird auf der Server-Seite mit der Konfigurationsdirektive HiddenServiceAuthorizeClient angeschaltet. Diese Direktive nimmt als Parameter den Authentisierungs-Modus (basic oder stealth) und eine per Komma getrennte Liste an Client-Namen. Diese Client-Namen sind nur beschreibener Natur und müssen nicht mit Hostnamen oder Domain-Namen übereinstimmen. Die Direktive gilt für den jeweils voher definierten Onion-Dienst:

HiddenServiceDir /var/lib/tor/ssh/
HiddenServicePort 22 127.0.0.1:22
HiddenServiceAuthorizeClient stealth client1,client2,client3

Nach einem Neustart des Tor-Dienstes findet sich im Verzeichnis des Onion-Dienstes eine neue Datei mit dem Dateinamen client_keys. Diese Datei enthält die Authentisierungs-Cookies und privaten Schlüssel für jeden angegebenen Client-Rechner:

client-name client1
descriptor-cookie QJVF38CnraTrg8FaAHuvFw==
client-key
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDTcZOJO3Eh4GWva8L9I4MlabqAvujx6oCL3xso00NTX6zWNWZn
[...]
6rEwyC92BYs2rShFsGadG0ET6N6+j7uWNf18Ya+qikCl
-----END RSA PRIVATE KEY-----
client-name client2
descriptor-cookie m6Isl8df2gPV+MBDoYFNLw==
client-key
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQC/OSyIWcTGD9oZK3vUqeTpSIJkpkJc670/c57iXo6a6L94VW/0
[...]
NFd2QdCnL87ay3gxjTx9APvGdDRf6VaMNaSurciq2Q==
-----END RSA PRIVATE KEY-----

In der Datei hostname im Verzeichnis des Onion-Dienstes befinden sich nun unterschiedliche Onion-Namen für die jeweiligen Clients, zusammen mit den Authentisierungs-Cookies:

iaopwbjmex2splr2.onion QJVF38CnraTrg8FaAHuvFx # client: client1
bdc5ujizach44dwm.onion m6Isl8df2gPV+MBDoYFNLx # client: client2
kura5sy7vsmi6ws6.onion wyThiRFLyqtsppBS0TDoHB # client: client3

Aus dieser Datei muss nun für jeden Client der Onion-Namen und der dazugehörige Cookie in die Konfiguration der Tor-Software auf den jeweiligen Clients kopiert werden.

13.2.2 Authentisierung auf der Client-Seite

Onion-Namen und Cookie werden auf Client-Seite mit der Direktive HidServAuth in die Konfigurationsdatei /etc/tor/torrc eingetragen:

HidServAuth  kura5sy7vsmi6ws6.onion wyThiRFLyqtsppBS0TDoHB # client: client3

Nach einem Neustart der Tor-Software auf dem Client sollte nun der Onion-Dienst von diesem Client aus sichtbar und benutzbar sein.

Ein Verbindungsaufbau zum Dienst ohne den Authentisierungs-Cookie bedingt einen Timeout:

# torify ssh -v kura5sy7vsmi6ws6.onion
OpenSSH_7.5p1, OpenSSL 1.1.0f-fips  25 May 2017
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Reading configuration data /etc/ssh/ssh_config.d/05-redhat.conf
debug1: Reading configuration data /etc/crypto-policies/back-ends/openssh.config
debug1: /etc/ssh/ssh_config.d/05-redhat.conf line 8: Applying options for *
debug1: Connecting to kura5sy7vsmi6ws6.onion [127.42.42.0] port 22.
[Aug 03 22:26:45] ERROR torsocks[9052]: Connection timed out (in socks5_recv_connect_reply() at socks5.c:536)
debug1: connect to address 127.42.42.0 port 22: Connection timed out
ssh: connect to host kura5sy7vsmi6ws6.onion port 22: Connection timed out

Mit dem korrektem Cookie funktioniert der Verbindungsaufbau:

# torify ssh -v kura5sy7vsmi6ws6.onion
OpenSSH_7.5p1, OpenSSL 1.1.0f-fips  25 May 2017
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Reading configuration data /etc/ssh/ssh_config.d/05-redhat.conf
debug1: Reading configuration data /etc/crypto-policies/back-ends/openssh.config
debug1: /etc/ssh/ssh_config.d/05-redhat.conf line 8: Applying options for *
debug1: Connecting to kura5sy7vsmi6ws6.onion [127.42.42.0] port 22.
debug1: Connection established.
[...]
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256@libssh.org
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: aes256-gcm@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: aes256-gcm@openssh.com MAC: <implicit> compression: none
debug1: kex: curve25519-sha256@libssh.org need=32 dh_need=32
debug1: kex: curve25519-sha256@libssh.org need=32 dh_need=32
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:UDnhiUeJdxYVlYJHM/cOmP4gh+a6jKO+dfYwH0J8fDc
The authenticity of host 'kura5sy7vsmi6ws6.onion (127.42.42.0)' can't be established.
ECDSA key fingerprint is SHA256:UDnhiUeJdxYVlYJHM/cOmP4gh+a6jKO+dfYwH0J8fDc.
ECDSA key fingerprint is MD5:8e:cc:bf:07:ee:bb:a7:9e:5f:77:f7:10:12:01:01:fa.
Are you sure you want to continue connecting (yes/no)? 

13.3 Vor- und Nachteile von Tor-Onion-Diensten

13.3.1 Vorteile

  • keine Änderungen an der (Heim-)Firewall notwendig. Keine Port-Forwardings etc.
  • kein DynDNS notwendig, um eine wechselne IP-Adresse mit einen Namen zu verbinden. Der Onion-Name wird immer im Tor-Netz gefunden
  • Datenverkehr ist (einfach) verschlüsselt (1024bit RSA)
  • Datenverkehr ist anonymisiert

13.3.2 Nachteile

  • Client muss die Tor-Software als Proxy benutzen
  • nur IPv4, kein IPv6 (daran wird gearbeitet)
  • hohe Latenz (Verzögerung) bei den Paketlaufzeiten
  • Tor-Verschlüsselung von 1024bit RSA nicht mehr zeitgemäß (auch daran wird im Tor-Projekt gearbeitet)

14 I2P - Invisible Internet Project

$ apt install java-1_8_0-openjdk
$ sudo useradd i2p
$ sudo passwd i2p
$ sudo mkdir /home/i2p
$ sudo chown -R i2p /home/i2p
$ su - i2p
# mkdir ~/i2p
# cd ~/i2p
# wget https://download.i2p2.de/releases/<version>/i2pinstall_<version>.jar
# java -jar i2pinstall_<version>.jar
#  ./i2p/i2prouter start
Starting I2P Service...
Waiting for I2P Service.....
running: PID:7087

15 stunnel

15.1 Tunnel, wenn sowohl Client als auch Server kein TLS sprechen

  • Installation (auf Client und Server)
apt install stunnel
  • Client stunnel Konfiguration in /etc/stunnel/stunnel.conf
client  = yes
debug   = info
output  = /var/log/stunnel.log

; These options provide additional security at some performance degradation
options = SINGLE_ECDH_USE
options = SINGLE_DH_USE

[http-to-https]
accept  = 80
connect = 100.64.x.2:8000
cert    = /etc/stunnel/stunnel.pem
  • Server stunnel Konfiguration in /etc/stunnel/stunnel.conf
debug = info
output = /var/log/stunnel.log

; These options provide additional security at some performance degradation
options = SINGLE_ECDH_USE
options = SINGLE_DH_USE
[https-8000]
accept  = 8000
connect = localhost:8001
cert = /etc/stunnel/stunnel.pem
  • systemd unit in /etc/systemd/system/stunnel.service on the server
### stunnel.service

[Unit]
Description=Stunnel service
After=network.target

[Service]
Type=forking
ExecStart=/usr/bin/stunnel /etc/stunnel/stunnel.conf
Restart=always

[Install]
WantedBy=Default.target
  • x509 Zertifikat erstellen
$ openssl req -new -nodes -x509 -out /etc/stunnel/stunnel.pem \
  -keyout /etc/stunnel/stunnel.pem
$ chmod 400 /etc/stunnel/stunnel.pem
  • Systemd Unit auf dem Server starten
$ systemctl daemon-reload
$ systemctl enable --now stunnel
  • Webserver auf dem Server auf Port 8001 starten
server0x$ python -m SimpleHTTPServer 8001
  • Start des stunnel auf dem Client
$ stunnel
$ tail /var/log/stunnel.log
$ lsof -i | grep stunnel
  • Test der Verbindung, links verbindet sich per HTTP unverschlüsselt, stunnel bietet die TLS Verschlüsselung (per tcpdump auf dem Router schauen das die Pakete SSL/TLS verschluesselt sind)
$ links http://localhost
  • per tcpdump auf dem Router testen, das kein HTTP oder HTTPS Verkehr zu sehen ist
tcpdump -nn -i eth1 port 80 or 443 or 8000

16 DNSSEC

17 DNSSEC Einführung

17.1 PGP Schlüssel im DNS ablegen (mit DNSSEC gesichert)

#!/bin/bash
# fetches an OPENPGPKEY and pipes the key into gpg based on a
# Twitter msg by Paul Wouters
# (https://twitter.com/letoams/status/560834359981539329) updated for
# draft-ietf-dane-openpgpkey-03 2015-05-14

maildomain=$(echo $1 | cut -d "@" -f 2)
localmail=$(echo $1 | cut -d "@" -f 1)
openpgpkeydomain=$(echo -n $localmail | openssl dgst -sha256 | cut -d "=" -f 2 | cut -c 1-57)._openpgpkey.$maildomain
echo "fetching ${openpgpkeydomain} ..."
dig +short +vc type61 $openpgpkeydomain | sed "s/ [^ ]*//;s/\W//g" | xxd -r -p | gpg
  • OPENPGPKEY manuell abfragen (ab BIND 9.10.0)
dig 3b8b91c75627bee566dcb88f4805901b20a3eab2520bcff8d26c8715._openpgpkey.sys4.de OPENPGPKEY
  • OPENPGPKEY manuell abfragen (vor BIND 9.10.0)
dig 3b8b91c75627bee566dcb88f4805901b20a3eab2520bcff8d26c8715._openpgpkey.sys4.de TYPE61
  • S/MIME Zertifikate aus dem DNS Abfragen
#!/bin/bash
# fetches an SMIMECERT
# 2016-01-20

maildomain=$(echo $1 | cut -d "@" -f 2)
localmail=$(echo $1 | cut -d "@" -f 1)
smimecertdomain=$(echo -n $localmail | openssl dgst -sha256 | cut -d "=" -f 2 | cut -c 1-57)._smimecert.$maildomain
echo "fetching ${smimecertdomain} ..."
dig +short +vc type53 $smimecertdomain

17.2 Unbound DNS-Resolver mit DNSSEC

  • wir arbeiten auf der Debian VPS
  • Unbound und die DNS-Tools installieren
apt install unbound dnsutils
  • DNS-Abfrage manuell testen, bei einer bekannt DNSSEC geschützten Domain muss im Header das AD-Flag (Authentic Data) angezeigt werden. Das AD-Flag ist das Signal, das die DNS-Daten DNSSEC abgesichert sind und korrekt überprüft (validiert) wurden:
dig @127.0.0.1 linuxhotel.de a
  • die Linux-Resolver Konfiguration anpassen, damit alle Anwendungen des Servers über den Unbound DNS-Resolver gehen
echo "nameserver 127.0.0.1" > /etc/resolv.conf
  • DNSSEC Vertrauenskette mit dem Tool drill aus dem Paket ldnsutils anzeigen
apt install ldnsutils
  • den Root-KSK Schlüssel besorgen und lokal abspeichern
dig @a.root-servers.net dnskey . | grep 257 > root.key
  • DNSSEC Vertrauenskette prüfen
drill -SD -k root.key www.linuxhotel.de a

18 Host-to-Host IPSec VPN mit LibreSWAN (CentOS Version)

  • Installation von StrongSWAN auf Client und Server, Befehle je auf Client und Server ausführen
yum install libreswan

18.1 IPSec auf dem Client (Client-VM) einrichten

  • NSS-Datenbank initialisieren
ipsec initnss --nssdir /etc/ipsec.d
  • IPSEC Schlüssel auf dem Client erstellen
ipsec newhostkey --output /etc/ipsec.secrets
Generated RSA key pair with CKAID <ckaid> was stored in the NSS database
  • Schlüssel anzeigen (wird in der Konfiguration benötigt)
ipsec showhostkey --left --ckaid <ckaid>
        # rsakey AwEAAei9b
        leftrsasigkey=0sAwEA[...]sadas==

18.2 IPSec auf dem Server (Server-VM) einrichten

  • NSS-Datenbank initialisieren
ipsec initnss --nssdir /etc/ipsec.d
  • IPSEC Schlüssel auf dem Client erstellen
ipsec newhostkey --output /etc/ipsec.secrets
Generated RSA key pair with CKAID <ckaid> was stored in the NSS database
  • Schlüssel anzeigen (wird in der Konfiguration benötigt)
ipsec showhostkey --right --ckaid <ckaid>
        # rsakey AwEAAei9b
        rightrsasigkey=0sAwEA[...]sadas==

18.3 IPSec Konfigurationsdatei beider IPSec-Recher

  • Konfigurationsdatei für diese IPSec-Verbindung auf beiden Rechnern in der Datei /etc/ipsec.d/host-to-host.conf erstellen:
conn host-to-host
 left=172.16.x.2
 leftrsasigkey=0sAwEAAe[...]
 right=100.64.x.2
 authby=rsasig
 rightrsasigkey=0sAwEAA[...]
 #auto=start, ondemand, add
 auto=add
 ikev2=insist

18.4 IPSec starten

  • auf beiden Rechner IPSec starten und Tunnel host-to-host starten
ipsec start
ipsec auto --add host-to-host
ipsec auto --up host-to-host

18.5 IPSec testen

  • tcpdump auf dem Router darf nur ESP Pakete sehen, keine ICMP Pakete
tcpdump -v -i eth1 icmp   # <-- keine Pakete zu sehen
tcpdump -v -i eth1 esp    # <-- IPSec Pakete sehen
  • Ping vom Server zum Client
ping -c4 172.16.x.2
  • Ping von Client zum Server
ping -c4 100.64.x.2

18.6 IPSec Fehlersuche

  • IPSec Status
ipsec status
  • Verbindungsstatus anschauen
ipsec whack --trafficstatus
  • IPSec Verbindungsinformationen im Kernel
ip xfrm state
  • IPSec Verschlüsselungs-Policy im Kernel anzeigen (welche Verbindungen sind durch IPSec geschützt)
ip xfrm policy
  • ESP, IKEv1 und IKEv2 im tcpdump sehen
tcpdump -n esp or port 500 or port 4500 -i eth0 

18.7 Resourcen

19 SSH VPN

  • ein SSH VPN eignet sich als Ad-Hoc VPN zwischen Systemen, bei denen nur der SSH Port offen ist
  • wir erstellen ein SSH-VPN zwischen der Client-VM und der Server-VM
  • Auf dem Client/Server OpenVPN stoppen
pkill openvpn
  • SSH-VPN Tunnel auf dem Server erlauben
server0x# $EDITOR /etc/ssh/sshd_config
---
PermitTunnel yes
---
systemctl restart sshd
  • auf dem Server Anmeldung per Passwort für Root freischalten
$EDITOR /etc/ssh/sshd_config
---
[...]
PermitRootLogin yes
[...]
---
systemctl restart sshd
  • auf dem Client ein SSH-VPN Tunnel zum Server (-N kein Befehl am Ziel ausführen, -T kein Terminal auf dem Ziel öffnen, -C Komprimierung einschalten (optional), -f- sende SSH in den Hintergrund, -w 0:0 Nummer des lokalen TUN Netzwerkinterface und des entfernten Netzwerkinterface)
client0x$ sudo ssh -NTCf -w 0:0 100.64.x.2
  • auf dem Server geben wir dem Tunnel eine IP-Adresse aus dem Server-Segment
sudo ip link set tun0 up
sudo ip addr add 100.64.1x.100/32 peer 100.64.1x.200 dev tun0
  • auf dem Client auch (IP Adressen vertauscht)
sudo ip link set tun0 up
sudo ip addr add 100.64.1x.200/32 peer 100.64.1x.100 dev tun0
  • nun sollten wir die jeweilige Gegenseite per ping erreichen
  • über Routing kann nun, ähnlich wie in der Wireguard-Übung, die IP-Kommunikation eines der Rechner (oder eines Netzes) über den SSH-VPN-Tunnel gesendet werden.
  • Alternative für ein SSH-VPN: sshuttle https://github.com/apenwarr/sshuttle

20 Anhang

20.1 Literaturliste

20.2 Referenzen:

20.2.1 Linux Zufallszahlen

20.2.2 SSL/TLS

20.2.3 Webserver Sicherheit

20.2.4 Wireguard