(no commit message)
authorstephan48 <stephan48@web>
Sun, 14 Nov 2021 01:38:13 +0000 (02:38 +0100)
committerIkiWiki <ikiwiki.info>
Sun, 14 Nov 2021 01:38:13 +0000 (02:38 +0100)
posts/2021-11-14-home-vpn-downloader.mdwn [new file with mode: 0644]

diff --git a/posts/2021-11-14-home-vpn-downloader.mdwn b/posts/2021-11-14-home-vpn-downloader.mdwn
new file mode 100644 (file)
index 0000000..a06300a
--- /dev/null
@@ -0,0 +1,547 @@
+$ apt install jq bc openvpn
+
+Download netns-ctl from $SOURCE (not published yet)
+
+cd netns-ctl
+$ sudo make install
+
+$ sudo -i
+
+$ mkdir -p /etc/netns/{protonvpn-ch,vm-down}/{network/{if-down.d,if-post-down.d,if-pre-up.d,if-up.d,netns-scripts,interfaces.d},iptables}
+
+$ vim /etc/network/interfaces.d/pvpn-ch
+allow-hotplug pvpn-ch
+auto pvpn-ch
+iface pvpn-ch inet static
+ address 10.33.0.1
+ netmask 255.255.255.252
+
+$ vim /etc/network/interfaces.d/vm-down
+allow-hotplug vm-down
+auto vm-down
+iface vm-down inet static
+ address 10.33.0.9
+ netmask 255.255.255.252
+
+$ vim /etc/netns/protonvpn-ch/network/interfaces
+auto main
+iface main inet static
+ address 10.33.0.2
+ netmask 255.255.255.252
+ up ip route add 185.159.157.0/24 via 10.33.0.1 dev main
+ up ip route add 193.36.117.0/24 via 10.33.0.1 dev main
+
+allow-hotplug vm-down
+auto vm-down
+iface vm-down inet static
+ address 10.33.0.5
+ netmask 255.255.255.252
+
+auto lo
+iface lo inet loopback
+
+cat /etc/netns/vm-down/network/interfaces
+allow-hotplug main
+auto main
+iface main inet static
+ address 10.33.0.10
+ netmask 255.255.255.252
+
+allow-hotplug pvpn-ch
+auto pvpn-ch
+iface pvpn-ch inet static
+ address 10.33.0.6
+ netmask 255.255.255.252
+ up ip route add default via 10.33.0.5 dev pvpn-ch
+
+$ touch /etc/netns/protonvpn-ch/resolv.conf.vpn
+
+$ vim /etc/netns/protonvpn-ch/resolv.conf
+nameserver 127.0.0.1 
+
+$ vim /etc/netns/vm-down/resolv.conf
+nameserver 127.0.0.1
+
+$ vim /etc/netns/vm-down/resolv.conf.vpn
+nameserver 10.33.0.5
+
+$ vim /etc/netns/protonvpn-ch/iptables/rules.v4
+# Generated by xtables-save v1.8.2 on Tue Oct 20 19:35:40 2020
+*filter
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+COMMIT
+# Completed on Tue Oct 20 19:35:40 2020
+# Generated by xtables-save v1.8.2 on Tue Oct 20 19:35:40 2020
+*nat
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+-A POSTROUTING -o tun0 -j MASQUERADE
+COMMIT
+# Completed on Tue Oct 20 19:35:40 2020
+
+$ touch /etc/netns/protonvpn-ch/iptables/rules.v6
+
+$ touch /etc/netns/vm-down/iptables/rules.v4
+$ touch /etc/netns/vm-down/iptables/rules.v6
+
+$ vim /etc/netns/protonvpn-ch/network/netns-scripts/protonvpn-ch
+#!/bin/sh
+
+set -e;
+set -x;
+
+TASK="$1";
+NS="$2";
+
+case "$TASK" in
+        up-outer)
+                ifup pvpn-ch
+                ;;
+        down-outer)
+                ;;
+        up-inner)
+                echo "DUMMY"
+                iptables-restore < /etc/netns/protonvpn-ch/iptables/rules.v4
+                ip6tables-restore < /etc/netns/protonvpn-ch/iptables/rules.v6
+                ;;
+esac
+
+$ chmod +x /etc/netns/protonvpn-ch/network/netns-scripts/protonvpn-ch
+
+$ vim /etc/network/netns-ctl.conf
+netns main
+ pid 1
+ auto link main-protonvpn-ch
+ auto link main-vm-down
+ end
+
+netns protonvpn-ch
+ pid foreign
+ auto link main-protonvpn-ch
+ auto link protonvpn-ch-vm-down
+ end
+
+netns vm-down
+ pid foreign
+ auto link main-vm-down
+ auto link protonvpn-ch-vm-down
+ end
+
+link main-protonvpn-ch
+ iface main in protonvpn-ch
+ iface pvpn-ch in main
+ end
+
+link protonvpn-ch-vm-down
+ iface vm-down in protonvpn-ch
+ iface pvpn-ch in vm-down
+ end
+
+link main-vm-down
+ iface main in vm-down
+ iface vm-down in main
+
+TODO: Maybe have netns-ctl balk if there are auto links but no link tags?
+
+
+$ vim /etc/systemd/system/netns\@.service
+[Unit]
+Description=Network Namespace %i
+Wants=network-pre.target
+Before=network-pre.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=bash -c 'mkdir -p /run/netns &&  touch /run/netns/"%i" && mount --bind /proc/self/ns/net /run/netns/"%i"'
+ExecStop=/usr/bin/ip netns delete "%i"
+KillMode=none
+
+[Install]
+WantedBy=multi-user.target
+
+$ vim /etc/systemd/system/netns-ctl\@.service
+[Unit]
+Description=Network Namespace - CTL %i
+Wants=network-pre.target
+Before=network-pre.target
+After=netns@%i.service
+BindsTo=netns@%i.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/local/sbin/netns-ctl netnsup %i
+ExecStop=/usr/local/sbin/netns-ctl netnsdown %i
+KillMode=none
+
+[Install]
+WantedBy=multi-user.target
+
+
+$ mkdir -p /etc/systemd/system/netns@{protonvpn-ch,vm-down}.service.d/
+$ vim /etc/systemd/system/netns@protonvpn-ch.service.d/override.conf
+[Service]
+PrivateNetwork=yes
+[Unit]
+After=netns@protonvpn-ch.service
+BindsTo=netns@protonvpn-ch.service
+
+$ vim /etc/systemd/system/netns@vm-down.service.d/override.conf
+[Service]
+PrivateNetwork=yes
+
+[Unit]
+After=netns@protonvpn-ch.service
+
+$ mkdir /etc/systemd/system/openvpn@protonvpn-ch.service.d/
+
+$ vim /etc/systemd/system/openvpn@protonvpn-ch.service.d/override.conf
+[Unit]
+BindsTo = netns@protonvpn-ch.service
+JoinsNamespaceOf = netns@protonvpn-ch.service
+After = netns@protonvpn-ch.service
+
+[Service]
+PrivateNetwork = true
+BindPaths=/etc/netns/protonvpn-ch/resolv.conf:/etc/resolv.conf
+BindPaths=/etc/netns/protonvpn-ch/resolv.conf.vpn:/etc/resolv.conf.vpn
+
+$ mkdir /etc/openvpn/protonvpn/
+
+$ touch /etc/openvpn/protonvpn/login.conf
+$ chmod 600 /etc/openvpn/protonvpn/login.conf
+$ vim /etc/openvpn/protonvpn/login.conf
+username
+password
+
+$ mkdir /etc/openvpn/protonvpn/ch/
+$ vim /etc/openvpn/protonvpn/ch/ch.ovpn (modified ProtonVPN CH Config)
+#
+# The MIT License (MIT)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+# ==============================================================================
+
+client
+dev tun
+proto udp
+
+remote ch.protonvpn.com 80
+remote ch.protonvpn.com 443
+remote ch.protonvpn.com 4569
+remote ch.protonvpn.com 1194
+remote ch.protonvpn.com 5060
+
+remote-random
+resolv-retry infinite
+nobind
+cipher AES-256-CBC
+auth SHA512
+comp-lzo no
+verb 3
+
+tun-mtu 1500
+tun-mtu-extra 32
+mssfix 1450
+persist-key
+persist-tun
+
+reneg-sec 0
+
+remote-cert-tls server
+auth-user-pass
+pull
+fast-io
+
+
+<ca>
+...
+</ca>
+
+key-direction 1
+<tls-auth>
+...
+</tls-auth>
+
+cd /etc/openvpn/protonvpn/
+pull-filter ignore redirect-gateway
+redirect-gateway local
+auth-user-pass login.conf
+script-security 2
+up ch-test
+down ch-test
+ifconfig-noexec
+route-noexec
+route-up ch-test
+
+keepalive 10 120
+status /etc/openvpn/protonvpn/ch/openvpn-status.log
+#route-down ch-test
+#
+#
+auth-retry nointeract
+
+$ vim /etc/openvpn/protonvpn/ch/ch-test
+#!/bin/bash
+#
+# Parses DHCP options from openvpn to update resolv.conf
+# To use set as 'up' and 'down' script in your openvpn *.conf:
+# up /etc/openvpn/update-resolv-conf
+# down /etc/openvpn/update-resolv-conf
+#
+# Used snippets of resolvconf script by Thomas Hood and Chris Hanson.
+# Licensed under the GNU GPL.  See /usr/share/common-licenses/GPL.
+#
+# Example envs set from openvpn:
+#
+#     foreign_option_1='dhcp-option DNS 193.43.27.132'
+#     foreign_option_2='dhcp-option DNS 193.43.27.133'
+#     foreign_option_3='dhcp-option DOMAIN be.bnc.ch'
+#
+
+set -ex
+
+[ "$script_type" ] || exit 0
+[ "$dev" ] || exit 0
+
+split_into_parts()
+{
+        part1="$1"
+        part2="$2"
+        part3="$3"
+}
+
+ROUTING_TABLE=666
+
+echo "MODE START: $script_type"
+
+case "$script_type" in
+  up)
+        NMSRVRS=""
+        SRCHS=""
+        foreign_options=$(printf '%s\n' ${!foreign_option_*} | sort -t _ -k 3 -g)
+        for optionvarname in ${foreign_options} ; do
+                option="${!optionvarname}"
+                echo "$option"
+                split_into_parts $option
+                if [ "$part1" = "dhcp-option" ] ; then
+                        if [ "$part2" = "DNS" ] ; then
+                                NMSRVRS="${NMSRVRS:+$NMSRVRS }$part3"
+                        elif [ "$part2" = "DOMAIN" ] ; then
+                                SRCHS="${SRCHS:+$SRCHS }$part3"
+                        fi
+                fi
+        done
+        R=""
+        [ "$SRCHS" ] && R="search $SRCHS
+"
+        for NS in $NMSRVRS ; do
+                R="${R}nameserver $NS
+"
+        done
+        echo -n "$R" > /etc/resolv.conf.vpn # ip netns exec `ip netns identify` tee /etc/resolv.conf
+        cat /etc/resolv.conf.vpn
+
+        #ip link set  dev "$dev"  up  netns "vm-down"  mtu "$tun_mtu" 2>&1 | logger
+        #ip netns exec "vm-down" date 2>&1 | logger
+
+        ip link set dev "$dev" up mtu "$tun_mtu"
+
+        # set device address
+        netmask4="${ifconfig_netmask:-30}"
+        netbits6="${ifconfig_ipv6_netbits:-112}"
+
+        if [ -n "$ifconfig_local" ]; then
+            if [ -n "$ifconfig_remote" ]; then
+                   /sbin/ip -4 addr add \
+                       local "$ifconfig_local" \
+                       peer "$ifconfig_remote/$netmask4" \
+                       ${ifconfig_broadcast:+broadcast "$ifconfig_broadcast"} \
+                       dev "$dev"
+            else
+                   /sbin/ip -4 addr add \
+                       local "$ifconfig_local/$netmask4" \
+                       ${ifconfig_broadcast:+broadcast "$ifconfig_broadcast"} \
+                       dev "$dev"
+            fi
+            #ip -4 route
+            #ip -4 route | grep "src $ifconfig_local" || true
+            #ip -4 route | grep "src $ifconfig_local" | xargs -iIII -n 1 echo ip -4 route add III table $ROUTING_TABLE
+            #ip -4 route | grep "src $ifconfig_local" | xargs -iIII -n 1 ip -4 route add III table $ROUTING_TABLE
+            #10.0.1.4/30 dev vm-down proto kernel scope link src 10.0.1.6
+        fi
+        if [ -n "$IPV6" -a -n "$ifconfig_ipv6_local" ]; then
+            if [ -n "$ifconfig_ipv6_remote" ]; then
+                   /sbin/ip -6 addr add \
+                      local "$ifconfig_ipv6_local" \
+                      peer "$ifconfig_ipv6_remote/$netbits6" \
+                      dev "$dev"
+            else
+                   /sbin/ip -6 addr add \
+                      local "$ifconfig_ipv6_local/$netbits6" \
+                      dev "$dev"
+            fi
+        fi
+
+        ;;
+  route-up)
+        i=1
+
+        while
+            eval net=\"\$route_network_$i\"
+            eval mask=\"\$route_netmask_$i\"
+            eval gw=\"\$route_gateway_$i\"
+            eval mtr=\"\$route_metric_$i\"
+            [ -n "$net" ]
+        do
+            /sbin/ip -4 route add  "$net/$mask"  via "$gw"  ${mtr:+metric "$mtr"} table $ROUTING_TABLE
+            i=$(( i + 1 ))
+        done
+        if [ -n "$route_vpn_gateway" ]; then
+            /sbin/ip -4 route add  default  via "$route_vpn_gateway" table $ROUTING_TABLE
+        fi
+
+        if [ -n "$IPV6" ]; then
+            i=1
+            while
+                # There doesn't seem to be $route_ipv6_metric_<n>
+                # according to the manpage.
+                eval net=\"\$route_ipv6_network_$i\"
+                eval gw=\"\$route_ipv6_gateway_$i\"
+                [ -n "$net" ]
+            do
+                /sbin/ip -6 route add  "$net"  via "$gw"  metric 100 table $ROUTING_TABLE
+                i=$(( i + 1 ))
+            done
+            # There's no $route_vpn_gateway for IPv6. It's not
+            # documented if OpenVPN includes default route in
+            # $route_ipv6_*. Set default route to remote VPN
+            # endpoint address if there is one. Use higher metric
+            # than $route_ipv6_* routes to give preference to a
+            # possible default route in them.
+            if [ -n "$ifconfig_ipv6_remote" ]; then
+                /sbin/ip -6 route add  default \
+                    via "$ifconfig_ipv6_remote"  metric 200 table $ROUTING_TABLE
+            fi
+        fi
+
+        ip rule add iif vm-down lookup $ROUTING_TABLE
+        ;;
+  down)
+        ip rule del iif vm-down lookup $ROUTING_TABLE
+        echo > /etc/resolv.conf.vpn
+        ;;
+esac
+
+echo "MODE END: $script_type"
+
+$ chmod +x /etc/openvpn/protonvpn/ch-test
+
+$ ln -s /etc/openvpn/protonvpn/ch/ch.ovpn /etc/openvpn/protonvpn-ch.conf
+
+TODO: Upstream "foreign" mode for netns-ctl
+
+$  systemctl enable --now netns@main netns-ctl@main
+$  systemctl enable --now netns@protonvpn-ch netns-ctl@protonvpn-ch
+$  systemctl enable --now netns@vm-down netns-ctl@vm-down
+
+
+$ vim /etc/systemd/system/dnsmasq-netns\@.service
+[Unit]
+Description=dnsmasq - A lightweight DHCP and caching DNS server
+Requires=network.target
+Wants=netns-ctl@%i.service
+After=network.target netns-ctl@%i.service
+BindsTo = netns-ctl@%i.service
+JoinsNamespaceOf = netns@%i.service
+
+[Service]
+Type=forking
+PIDFile=/run/dnsmasq/dnsmasq-netns-%i.pid
+
+# Test the config file and refuse starting if it is not valid.
+ExecStartPre=/usr/sbin/dnsmasq --conf-dir /etc/dnsmasq/netns/%i/,*.conf --resolv=/etc/netns/%i/resolv.conf.vpn --test
+
+# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a
+# wrapper picking up extra configuration files and then execs dnsmasq
+# itself, when called with the "systemd-exec" function.
+ExecStart=/usr/sbin/dnsmasq --conf-dir /etc/dnsmasq/netns/%i/,*.conf --resolv=/etc/netns/%i/resolv.conf.vpn -x /run/dnsmasq/dnsmasq-netns-%i.pid
+
+# The systemd-*-resolvconf functions configure (and deconfigure)
+# resolvconf to work with the dnsmasq DNS server. They're called like
+# this to get correct error handling (ie don't start-resolvconf if the
+# dnsmasq daemon fails to start.
+#ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf
+#ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf
+
+
+ExecReload=/bin/kill -HUP $MAINPID
+
+PrivateNetwork = true
+BindPaths=/etc/netns/%i/resolv.conf:/etc/resolv.conf
+BindPaths=/etc/netns/%i/resolv.conf.vpn:/etc/resolv.conf.vpn
+
+[Install]
+WantedBy=multi-user.target
+
+$ mkdir /etc/dnsmasq/netns/{protonvpn-ch,vm-down}
+
+$ vim /etc/dnsmasq/netns/protonvpn-ch/dnsmasq.conf
+interface=main
+interface=vm-down
+interface=lo
+no-dhcp-interface=main
+no-dhcp-interface=tun0
+no-dhcp-interface=lo
+no-hosts
+
+$ vim /etc/dnsmasq/netns/vm-down/dnsmasq.conf
+interface=eth1-down
+interface=lo
+no-dhcp-interface=pvpn-ch
+no-hosts
+
+$ vim /etc/hosts
+#PVPN-CH START
+127.0.0.1 ch.protonvpn.com ch-12.protonvpn.com
+127.0.0.1 ch.protonvpn.com node-ch-03.protonvpn.net
+127.0.0.1 ch.protonvpn.com node-ch-02.protonvpn.net
+#PVPN-CH STOP
+
+$ vim /root/newpvpnch.sh
+#!/bin/bash
+
+SERVERS="`curl https://account.protonvpn.com/api/vpn/logicals | jq -r '[.LogicalServers[] | select( .ExitCountry == "CH" and .Tier >= 2 and .Load < 40 and .Features == 4 and .Status == 1) | { "entryIP": .Servers[0].EntryIP, "exitIP": .Servers[0].ExitIP,  "score": .Score, "load": .Load, obj: ., "domain": .Servers[0].Domain }] | sort_by(.score)[:3] | .[] | "\(.entryIP) ch.protonvpn.com \(.domain)"' | sort -R ` "
+echo -e "$SERVERS"
+perl -e '$/=undef; my $string = <STDIN>; $string =~ s/#PVPN-CH START.+#PVPN-CH STOP/#PVPN-CH START\n'"$SERVERS"'\n#PVPN-CH STOP/igs; print $string;' < /etc/hosts > /etc/hosts.tmp
+cat /etc/hosts.tmp
+cp /etc/hosts{,.bak}
+mv /etc/hosts.tmp /etc/hosts
+
+systemctl restart openvpn@protonvpn-ch
+journalctl --follow -u openvpn@protonvpn-ch
+
+$ chmod +x /root/newpvpnch.sh
+
+$ /root/new/pvpnch.sh