Anleitung: OpenVPN Script fuer automatische Kaskadierung und Verbindungsueberwachung

@Morbis55
Vielen Dank für den Zuspruch und deine verbale Unzterstützung. :)
Es freut mich immer zu hören, wenn meine Arbeit wertgeschätzt wird.

Der von Dir genannte "Auto Reconnect" ist ja schon in meinem Script implementiert. Hier arbeite ich letztendlich mit dem, was die openVPN-Logs ausgeben.
Der Schwenk auf einen anderen Server wäre bestimmt, seitens PP, möglich - jedoch für mich schwer zu realisieren, da ich keine Referenzwerte zur Auslastung der Server beziehen kann. Lediglich die Serverauflistung auf der PP Website - jedoch weiß ich nicht, wie 'aktuell' diese Daten immer sind.
 
UPDATE

Changelog
- Bug im Array zur Serverlistung behoben -> fehlende Funktion zur 'Freigabe' sämtlicher Server, wenn die letzte Sitzung abgelaufen ist --> nun werden bei jedem neuen Verbindungsaufbau wieder sämtliche Server herangezogen
- leichte Geschwindigkeitsoptimierung -> zum Startzeitpunkt des Script wurde eine 'doppelte' Bereinigung eventuell vorhandener Sessions durchgeführt --> nun auf 1x begrnzt (spart knapp 3 Sekunden)
 

nonono

Member
@PrivateMember: Hast du nicht mal Lust ein Script zu schreiben, das einfach per Aufruf verschiende Interfaces für Traffic außerhalb von tun0 blockt? So als "Schutz" vor einem Verbindungsabbruch? Optional könnte man das persistent oder temporär aktivieren? Das wäre praktisch.
 
@PrivateMember: Hast du nicht mal Lust ein Script zu schreiben, das einfach per Aufruf verschiende Interfaces für Traffic außerhalb von tun0 blockt? So als "Schutz" vor einem Verbindungsabbruch? Optional könnte man das persistent oder temporär aktivieren? Das wäre praktisch.
Und wie soll der Traffic dann das System verlassen?
 
Und wie soll der Traffic dann das System verlassen?
Man muss schon die entsprechenden ports für den Aufbau der VPN-Verbindung offen lassen. Sobald dann die Verbindung steht kann geprüft werden, ob interfaces mit dem Namen tun* vorhandene sind. Dann einfach deny all in und out auf den anderen interfaces. Natürlich muss vorher noch definiert werden, welche ports noch benötigt werden (z.B. wenn das System per SSH bedient wird und nicht direkt mit Tastatur und Maus)
 
Man muss schon die entsprechenden ports für den Aufbau der VPN-Verbindung offen lassen. Sobald dann die Verbindung steht kann geprüft werden, ob interfaces mit dem Namen tun* vorhandene sind. Dann einfach deny all in und out auf den anderen interfaces. Natürlich muss vorher noch definiert werden, welche ports noch benötigt werden (z.B. wenn das System per SSH bedient wird und nicht direkt mit Tastatur und Maus)
Ich glaube ihr beide müsst euch nochmal anschauen wie OpenVPN/Tun Interfaces funktionieren
 
Ok bin gespannt wie du ohne eth interface ins internet kommst :--)
Hier mal ein Überblick bei aktiver Verbindung und aktiver Firewall (achte bitte auf die DENY ALL-Regeln meiner Firewall):
Code:
user@host4711:/var/log/ovpn_reconnect$ sudo ufw status numbered

[sudo] Passwort für user:

Status: active


     To                         Action      From

     --                         ------      ----

[ 1] 22/tcp                     ALLOW IN    192.168.10.0/24

[ 2] 6000/tcp                   ALLOW IN    192.168.20.5

[ 3] 22/tcp                     ALLOW IN    192.168.20.0/24

[ 4] 44/udp                     ALLOW OUT   Anywhere on eno1           (out)

[ 5] 443/udp                    ALLOW OUT   Anywhere on eno1           (out)

[ 6] 4433/udp                   ALLOW OUT   Anywhere on eno1           (out)

[ 7] 9091/tcp                   ALLOW IN    192.168.20.5

[ 8] Anywhere                   DENY OUT    Anywhere on eno1           (out)

[ 9] Anywhere on eno1           DENY IN     Anywhere

[10] Anywhere on tun            DENY IN     Anywhere




user@host4711:/var/log/ovpn_reconnect$ ip r

0.0.0.0/2 via 10.4.0.1 dev tun1

0.0.0.0/1 via 10.1.147.1 dev tun0

default via 192.168.20.1 dev eno1 onlink

10.1.147.0/24 dev tun0 proto kernel scope link src 10.1.147.33

10.4.0.0/24 dev tun1 proto kernel scope link src 10.4.0.33

64.0.0.0/2 via 10.4.0.1 dev tun1

128.0.0.0/2 via 10.4.0.1 dev tun1

128.0.0.0/1 via 10.1.147.1 dev tun0

185.152.32.66 via 10.1.147.1 dev tun0

192.0.0.0/2 via 10.4.0.1 dev tun1

192.168.20.0/24 dev eno1 proto kernel scope link src 192.168.20.6

195.138.249.2 via 192.168.20.1 dev eno1



user@host4711:/var/log/ovpn_reconnect$ ip addr

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: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

    link/ether 70:f3:95:ff:ff:ff brd ff:ff:ff:ff:ff:ff

    inet 192.168.20.6/24 brd 192.168.20.255 scope global eno1

       valid_lft forever preferred_lft forever

    inet6 fe80::72f3:95ff:ffff:ffff/64 scope link

       valid_lft forever preferred_lft forever

54: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100

    link/none

    inet 10.1.147.33/24 brd 10.1.147.255 scope global tun0

       valid_lft forever preferred_lft forever

    inet6 fdbf:1d37:bbe0:0:25:3:0:21/112 scope global

       valid_lft forever preferred_lft forever

    inet6 fe80::845c:c475:3142:5b6c/64 scope link stable-privacy

       valid_lft forever preferred_lft forever

55: tun1: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100

    link/none

    inet 10.4.0.33/24 brd 10.4.0.255 scope global tun1

       valid_lft forever preferred_lft forever

    inet6 fdbf:1d37:bbe0:0:64::21/112 scope global

       valid_lft forever preferred_lft forever

    inet6 fe80::47fc:86df:9722:a3ff/64 scope link stable-privacy

       valid_lft forever preferred_lft forever

     

     

user@host4711:/var/log/ovpn_reconnect$ ping google.de

PING google.de (172.217.169.3) 56(84) bytes of data.

64 bytes from lhr25s26-in-f3.1e100.net (172.217.169.3): icmp_seq=1 ttl=54 time=105 ms

64 bytes from lhr25s26-in-f3.1e100.net (172.217.169.3): icmp_seq=2 ttl=54 time=105 ms

64 bytes from lhr25s26-in-f3.1e100.net (172.217.169.3): icmp_seq=3 ttl=54 time=105 ms

64 bytes from lhr25s26-in-f3.1e100.net (172.217.169.3): icmp_seq=4 ttl=54 time=105 ms

^C

--- google.de ping statistics ---

4 packets transmitted, 4 received, 0% packet loss, time 7ms

rtt min/avg/max/mdev = 104.839/105.212/105.471/0.411 ms


user@host4711:/var/log/ovpn_reconnect$

Nun kappe ich die Verbindung, wodurch ich nicht mehr über das eno1-Interface (physikalischer Adapter) in externe Netze komme:
Bash:
user@host4711:/var/log/ovpn_reconnect$ sudo systemctl stop openvpn-restart-cascading-watchdog.service

user@host4711:/var/log/ovpn_reconnect$ sudo systemctl stop openvpn-restart-cascading.service

user@host4711:/var/log/ovpn_reconnect$ sudo killall openvpn


user@host4711:/var/log/ovpn_reconnect$ ip addr

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: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

    link/ether 70:f3:95:ff:ff:ff brd ff:ff:ff:ff:ff:ff

    inet 192.168.20.6/24 brd 192.168.20.255 scope global eno1

       valid_lft forever preferred_lft forever

    inet6 fe80::72f3:95ff:ffff:ffff/64 scope link

       valid_lft forever preferred_lft forever

     

user@host4711:/var/log/ovpn_reconnect$ ip r

default via 192.168.20.1 dev eno1 onlink

192.168.20.0/24 dev eno1 proto kernel scope link src 192.168.20.6

user@host4711:/var/log/ovpn_reconnect$ sudo ufw status numbered

Status: active


     To                         Action      From

     --                         ------      ----

[ 1] 22/tcp                     ALLOW IN    192.168.10.0/24

[ 2] 6000/tcp                   ALLOW IN    192.168.20.5

[ 3] 22/tcp                     ALLOW IN    192.168.20.0/24

[ 4] 44/udp                     ALLOW OUT   Anywhere on eno1           (out)

[ 5] 443/udp                    ALLOW OUT   Anywhere on eno1           (out)

[ 6] 4433/udp                   ALLOW OUT   Anywhere on eno1           (out)

[ 7] 9091/tcp                   ALLOW IN    192.168.20.5

[ 8] Anywhere                   DENY OUT    Anywhere on eno1           (out)

[ 9] Anywhere on eno1           DENY IN     Anywhere

[10] Anywhere on tun            DENY IN     Anywhere


user@host4711:/var/log/ovpn_reconnect$ ping google.de

ping: google.de: Temporärer Fehler bei der Namensauflösung

user@host4711:/var/log/ovpn_reconnect$

Ich verstehe wirklich nicht, was das Problem sein soll. :(


BTW: Ich habe lediglich meine MAC-Adresse 'geschwärzt'.
 
---BETA---

Killswitch-Script zum abriegeln der physischen Netzwerkadapter


Bash:
#!/bin/bash
#
function fw_rules_iptables {
    # loeschen der vorhandenen Regeln
    iptables -F

    # Freigabe der openVPN-Ports der Standardkonfiguration von Perfect-Privacy
    iptables -t filter -A OUTPUT -o "$1" -p udp -m multiport --dports 1148,148,1149,149,1150,150,1151,151,44,443,4433 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    iptables -t filter -A OUTPUT -o "$1" -p tcp -m multiport --dports 300,301,1142,142,1152,152,22 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    iptables -t filter -A INPUT -i "$1" -p udp -m multiport --sports 1148,148,1149,149,1150,150,1151,151,44,443,4433 -m state --state ESTABLISHED,RELATED -j ACCEPT
    iptables -t filter -A INPUT -i "$1" -p tcp -m multiport --sports 300,301,1142,142,1152,152,22 -m state --state ESTABLISHED,RELATED -j ACCEPT

    # Freigabe der Standard-IP-Ranges fuer lokale Netzwerke
    iptables -t filter -A OUTPUT --dst 192.168.0.0/16 -j ACCEPT
    iptables -t filter -A INPUT --src 192.168.0.0/16 -j ACCEPT
    iptables -t filter -A OUTPUT --dst 10.0.0.0/8 -j ACCEPT
    iptables -t filter -A INPUT --src 10.0.0.0/8 -j ACCEPT
    iptables -t filter -A OUTPUT --dst 172.16.0.0/12 -j ACCEPT
    iptables -t filter -A INPUT --src 172.16.0.0/12 -j ACCEPT

    # Blockieren saemtlicher, nicht zuvor definierter, Netzwerkanfragen
    iptables -t filter -A OUTPUT -o "$1" -j DROP
    iptables -t filter -A INPUT -i "$1" -j DROP
}
function fw_rules_nftables {
    # Hinzufuegen einer neuen Table
    nft add table block_without_tun

    # loeschen der vorhandenen Regeln
    nft flush table block_without_tun

    # Chains anlegen
    nft add chain block_without_tun input { type filter hook input priority 0 \; }
    nft add chain block_without_tun output { type filter hook input priority 0 \; }

    # Freigabe der openVPN-Ports der Standardkonfiguration von Perfect-Privacy
    nft add rule block_without_tun output oifname '"'"$1"'"' ip protocol udp udp dport { 1148,148,1149,149,1150,150,1151,151,44,443,4433} ct state new,related,established counter accept
    nft add rule block_without_tun output oifname '"'"$1"'"' ip protocol tcp tcp dport { 300,301,1142,142,1152,152,22} ct state new,related,established counter accept
    nft add rule block_without_tun input iifname '"'"$1"'"' ip protocol udp udp sport { 1148,148,1149,149,1150,150,1151,151,44,443,4433} ct state related,established counter accept
    nft add rule block_without_tun input iifname '"'"$1"'"' ip protocol tcp tcp sport { 300,301,1142,142,1152,152,22} ct state related,established counter accept

    # Freigabe der Standard-IP-Ranges fuer lokale Netzwerke
    nft add rule block_without_tun output ip daddr 192.168.0.0/16 counter accept
    nft add rule block_without_tun input ip saddr 192.168.0.0/16 counter accept
    nft add rule block_without_tun output ip daddr 10.0.0.0/8 counter accept
    nft add rule block_without_tun input ip saddr 10.0.0.0/8 counter accept
    nft add rule block_without_tun output ip daddr 172.16.0.0/12 counter accept
    nft add rule block_without_tun input ip saddr 172.16.0.0/12 counter accept

    # Blockieren saemtlicher -nicht zuvor definierter- Netzwerkanfragen
    nft add rule block_without_tun output oifname '"'"$1"'"' counter drop
    nft add rule block_without_tun input iifname '"'"$1"'"' counter drop
}

echo -e "\n\nKillswitch-Script zum Abriegeln der physischen Netzwerkadapter"
echo -e "--------------------------------------------------------------\n"

# ermitteln der genutzten Firewall
dpkg -l | grep ^ii | awk '{print $2}' | grep -w "iptables" >> /dev/null
inst_ipt="$?"

dpkg -l | grep ^ii | awk '{print $2}' | grep -w "nftables" >> /dev/null
inst_nft="$?"

if [ "$inst_ipt" -eq "1" ] && [ "$inst_nft" -eq "1" ];
then
    echo -e "'iptables' oder 'nftables' nicht installiert!"
    echo -e "Bitte erst die gewuenschte Firewall mit folgendem Befehl installieren und anschliessend das Script erneut ausfuehren:"
    echo -e "\niptables:\tsudo apt-get install iptables\n"
    echo -e "\nnftables:\tsudo apt-get install nftables\n"
    exit
elif [ "$inst_ipt" -eq "$inst_nft" ];
then

    if systemctl status nftables | grep -w "inactive" >> /dev/null
    then
        use_fw=iptables
    else
        use_fw=nftables
    fi
elif [ "$inst_ipt" -eq "0" ] && [ "$inst_nft" -eq "1" ];
then
    use_fw=iptables
elif [ "$inst_ipt" -eq "1" ] && [ "$inst_nft" -eq "0" ];
then
    use_fw=nftables
else
    echo -e "\n--------------------------------"
    echo -e "unbekannter Status - beenden!"
    echo -e "--------------------------------\n\n"
    exit
fi

# ermitteln vorhandener physischer Netzwerkadapter
mapfile -t phy_net < <(grep -E -v 'tun|lo' /proc/net/dev | cut -d ':' -f 1 | tr -d '[:blank:]' | grep -E '*[0-9]')

# ermitteln vorhandener VPN-TUN
mapfile -t tun_net < <(grep 'tun' /proc/net/dev | cut -d ':' -f 1 | tr -d '[:blank:]')

if [ "${#tun_net[*]}" -gt "0" ];
then
    START=0
    count="$((${#phy_net[*]}-"1"))"
    echo -e "Es wurden folgende physischen Apdater erkannt"
    echo -e "---------------------------------------------"
    for (( i=START; i<=count; i++ ))
    do
        echo -e "==> ${phy_net[i]}"
    done
    echo -e "\n\nErkannte, aktive Firewall"
    echo -e "-------------------------"

    if [ "$use_fw" == "iptables" ];
    then
        echo -e "==> 'iptables' scheint aktiv zu sein!\n"
    elif [ "$use_fw" == "nftables" ];
    then
        echo -e "==> 'nftables' scheint aktiv zu sein!\n"
    fi
    echo -e "Firewall-Konfiguration von $use_fw wird somit angepasst!"

    echo -e "\nHINWEIS: Nach einem Neustart werden die Anpassungen automatisch zurueckgesetzt!"
    echo -e "Welche Aktion soll ausgefuehrt werden?\n"
    echo -e "(i)mport der Regeln\n(l)oeschen saemtlicher Regeln\n(a)bbruch des Scripts"
    read -r answer

    case "$answer" in
        i)
            START=0
            count="$((${#phy_net[*]}-"1"))"
            echo -e "\nAntwort: 'import'\n"
            for (( i=START; i<=count; i++ ))
            do
                if [ "$use_fw" == "iptables" ];
                then
                    fw_rules_iptables "${phy_net[i]}"
                elif [ "$use_fw" == "nftables" ];
                then
                    fw_rules_nftables "${phy_net[i]}"
                fi
            done
            echo -e "\n-------------------------------------------"
            echo -e "Hinzufuegen der Firewall-Regeln erfolgreich"
            echo -e "-------------------------------------------\n\n"
            ;;

        l)
            echo -e "\nAntwort: 'loeschen'\n"
            if [ "$use_fw" == "iptables" ];
            then
                iptables -F
            elif [ "$use_fw" == "nftables" ];
            then
                nft flush table block_without_tun
            fi
            echo -e "\n----------------------------------------"
            echo -e "Loeschen der Firewall-Regeln erfolgreich"
            echo -e "----------------------------------------\n\n"
            ;;

        a)
            echo -e "\nAntwort: 'abbruch'\n"
            echo -e "\n-------------"
            echo -e "Scriptabbruch"
            echo -e "-------------\n\n"
            ;;

        *)
            echo -e "\nAntwort: 'undefiniert'\n"
            echo -e "\n-------------"
            echo -e "Scriptabbruch"
            echo -e "-------------\n\n"
            ;;
    esac

else
    echo -e "Es konnten KEINE TUN-Adapter ermittelt werden"
    echo -e "Bitte die VPN-Verbindungen aufbauen und das Script im Anschluss erneut starten!\n"

    echo -e "Soll versucht werden, saemtliche temporaere 'iptables' und 'nftables' Regeln zu entfernen?\n"
    echo -e "(j)a / (n)ein"
    read -r answer

    case "$answer" in
        j)
            echo -e "\nAntwort: 'ja'\n"
            iptables -F
            nft flush table block_without_tun
            echo -e "\n---------------"
            echo -e "Regeln entfernt"
            echo -e "---------------\n\n"
            ;;

        n)
            echo -e "\nAntwort: 'nein'\n"
            echo -e "\n-------------"
            echo -e "Scriptabbruch"
            echo -e "-------------\n\n"
            ;;

        *)
            echo -e "\nAntwort: 'undefiniert'\n"
            echo -e "\n-------------"
            echo -e "Scriptabbruch"
            echo -e "-------------\n\n"
            ;;
    esac
fi
- bitte mal bisschen spielen und testen
- Script überprüft auf vorhandensein von iptables ODER nftables
- je nach aktiver Firewall werden die Regeln editiert
- Script prüft vorab, ob VPN-Tunnel vorhanden sind -> keine Ausführung, wenn KEIN Tunnel aufgebaut ist
- Nach einem Neustart werden die Regeln automatisch entfernt
- Auswahlmöglichkeiten bei Ausführung: import der Regeln, löschen der Regeln, Scriptabbruch
- Zugriff auf das lokale Netzwerk bleibt bestehen, wenn es dem Standard eines IP Klasse A, B oder C Netzes für interne Netzwerke entspricht
- Standardports für den Connect zu PP-Servern (TCP und UDP) sind freigegeben + SSH auf Port 22
- es werden die Regeln für SÄMTLICHE physische Adapter angewandt
- ACHTUNG: wenn die Verbindung zu dem System AUSSERHALB des lokalen Netzes erfolgt (z.B. per SSH) kann es sein, dass das System nicht mehr erreichbar ist! Bitte unbedingt beachten!

Um das Script ausführbar zu machen, muss auf dem System eine Datei erstellt werden, z.B. 'firewall_pp.sh', den o.g. Inhalt einfügen, diese Datei ausführbar machen (z.B. 'sudo chmod +x firewall_pp.sh') und ausführen ('sudo ./firewall_pp.sh).

Teilt mir mit, falls es Schwierigkeiten oder Komplikationen gibt.

@nonono
 
Last edited:

nonono

Member
Das ist der Output, die Netzwerkadapter wurden korrekt erkannt, dann:

Code:
Antwort: 'import'

./fw.sh: line 7: iptables: command not found
./fw.sh: line 10: iptables: command not found
./fw.sh: line 11: iptables: command not found
./fw.sh: line 12: iptables: command not found
./fw.sh: line 13: iptables: command not found
./fw.sh: line 16: iptables: command not found
./fw.sh: line 17: iptables: command not found
./fw.sh: line 18: iptables: command not found
./fw.sh: line 19: iptables: command not found
./fw.sh: line 20: iptables: command not found
./fw.sh: line 21: iptables: command not found
./fw.sh: line 24: iptables: command not found
./fw.sh: line 25: iptables: command not found
./fw.sh: line 7: iptables: command not found
./fw.sh: line 10: iptables: command not found
./fw.sh: line 11: iptables: command not found
./fw.sh: line 12: iptables: command not found
./fw.sh: line 13: iptables: command not found
./fw.sh: line 16: iptables: command not found
./fw.sh: line 17: iptables: command not found
./fw.sh: line 18: iptables: command not found
./fw.sh: line 19: iptables: command not found
./fw.sh: line 20: iptables: command not found
./fw.sh: line 21: iptables: command not found
./fw.sh: line 24: iptables: command not found
./fw.sh: line 25: iptables: command not found

--------------------------------
Firewall-Anpassungen erfolgreich
--------------------------------
Das wird aber daran liegen, dass iptables ab Debian Buster durch nftables ersetzt wurde.
 
Hast du das Script als 'sudo' ausgeführt?
Falls iptables fehlen sollte, hättest du eine Meldung erhalten und das Script wäre sofort beendet.

iptables kann lediglich mit sudo-rechten ausgeführt werden.
 
Last edited:

BruceWayne

Member
Hello PrivateMember, I am working on Qubes OS version of your script. The interesting point is etc/ directory is not preserved, so better to use /rw/config
 
Hello PrivateMember, I am working on Qubes OS version of your script. The interesting point is etc/ directory is not preserved, so better to use /rw/config
Hello BruceWayne,

I don't have any informations about Qubes OS.
Isn't there any '/etc' directory?
In other distributions I do not know the '/rw' directory.

Are you able to run the script with the default configuration?


HINT: If you want to change the default directorys, simply edit the script after installation.
As default you can find it here:
Bash:
/etc/systemd/system/openvpn_service_restart_cascading.sh
=> hopefully in qubes OS, too

look at the variables in 'Variablen deklarieren'-Section, for example:
Bash:
path_ovpn_conf=/etc/openvpn/connections/
 
Top