From: stephan48 Date: Sun, 14 Nov 2021 01:38:13 +0000 (+0100) Subject: (no commit message) X-Git-Url: https://blog.stejau.de/gitweb/gitweb.cgi?a=commitdiff_plain;h=e24ff9c007a5c44d70cb2fc95988767e53886bb8;p=stejau-blog.git --- diff --git a/posts/2021-11-14-home-vpn-downloader.mdwn b/posts/2021-11-14-home-vpn-downloader.mdwn new file mode 100644 index 0000000..a06300a --- /dev/null +++ b/posts/2021-11-14-home-vpn-downloader.mdwn @@ -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 + + + +... + + +key-direction 1 + +... + + +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_ + # 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 = ; $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