2023-08-24
Configuration
The following instructions use the wonderful proxy.sh VPN provider: they are cheap, transparent, strongly privacy oriented, and they offer many servers, proxies and scriptable web APIs!
If you want to buy an account then click the following banner:
or just start installing and configuring the software:
1 | apt-get install openvpn netselect |
Create the proxysh.auth
text file containing your VPN credentials:
1 2 3 | mkdir -p /path/to/myvpn cd /path/to/myvpn echo -e "myusername\nmypassword" > proxysh.auth |
Setup an openvpn config updater script, say proxysh-update.sh
and substitute username
, password
with your VPN credentials:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | #!/bin/bash OVPND=/path/to/openvpn/config cat > $OVPND/proxysh.conf.tmp <<VPNCFG # https://openvpn.net/index.php/open-source/documentation/manuals/65-openvpn-20x-manpage.html client dev tun proto tcp port 443 auth SHA512 auth-user-pass $OVPND/proxysh.auth cipher AES-256-CBC remote-cert-tls server resolv-retry infinite verb 3 reneg-sec 0 route-method exe route-delay 2 mute 2 mute-replay-warnings nobind comp-lzo # https://community.openvpn.net/openvpn/wiki/IgnoreRedirectGateway #pull-filter ignore redirect-gateway # args: tun_dev tun_mtu link_mtu local_ip remote_ip [init|restart] up-restart script-security 2 up $OVPND/proxysh-cmd-up.sh #down $OVPND/proxysh-cmd-down.sh # ping every N seconds and restart after M without reply keepalive 30 90 <ca> -----BEGIN CERTIFICATE----- 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 TSMSym4Np+AmT7OX -----END CERTIFICATE----- </ca> #remote-random VPNCFG echo -n "`date +'%F %T'`: refresh config servers... " # get servers list with load < 80% post_auth=`cat $OVPND/proxysh.auth | tr "\n" "#" | sed -r 's/([^#]+)#([^#]+).*/u=\1\&p=\2/'` curl -s -X POST https://proxy.sh/api.php -d "$post_auth" | \ sed 's/^ *//' | tr -d "\n" | sed 's/<.server>/\0\n/g' | \ grep -Ev "Hub" | grep -Ev "load>(100|[5-9][0-9])" | \ sed -r 's/.*ress>(.+)<.add.*load>(.+)<.server_load.*/\1/' \ > $OVPND/proxysh.srv # check servers length if [ `cat $OVPND/proxysh.srv | wc -l` -eq 0 ]; then echo " DL ERROR!" exit fi # order servers by ping time (UDP) sudo netselect -s 64 `cat $OVPND/proxysh.srv | tr "\n" " "` 2> /dev/null | \ sed 's/.* /remote /' >> $OVPND/proxysh.conf.tmp # check servers length if [ `grep -E "remote [0-9]+" $OVPND/proxysh.conf.tmp | wc -l` -eq 0 ]; then echo " SORT ERROR!" exit fi # update the real config file chmod 600 $OVPND/proxysh.conf.tmp mv -f $OVPND/proxysh.conf.tmp $OVPND/proxysh.conf rm -f $OVPND/proxysh.srv echo "OK" |
Create an optional proxysh-cmd-up.sh
script that run after each openvpn start/restart:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/bash # script args: tun_dev tun_mtu link_mtu local_ip remote_ip [init|restart] # updating deluge listen_interface IP address if [ -d $HOME/.config/deluge ]; then cd $HOME/.config/deluge sed -i -r 's/("listen_interface": ")(.*)(")/\1'$4'\3/' ./core.conf if pgrep deluged > /dev/null ; then sudo -u cloud deluge-console "pause *" sudo -u cloud deluge-console "config -s listen_interface $4" ; sleep 3 sudo -u cloud deluge-console "resume *" fi cd - fi exit 0 |
Create a script to start and keep running the openvpn daemon say run.sh
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | #!/usr/bin/sudo /bin/bash [ `whoami` != "root" ] && { echo "you must be root!" && exit 1; } cd /path/to/myvpn || { echo "pwd not found!" && exit 2; } # read current config for later usage tbl=10 dev=`ip link | paste - - | grep -iE "state up.+ether" | head -n 1 | sed -r 's/[0-9]+: ([^:]+).+/\1/'` # device name met=`ip route | grep -E "^default via.+dev $dev.+metric" | sed -r 's/^.+metric ([0-9]+)[^0-9]*/\1/' ` # metric sub=`ip route | grep -E ".+\/.+dev $dev .+metric $met" | sed -r 's/^([0-9.]+\/[0-9]+).+/\1/' ` # subnet src=`ip route | grep -E ".+\/.+dev $dev .+metric $met" | sed -r 's/.+src ([0-9.]+) .+/\1/' ` # source gwy=`ip route | grep -E ".+via.+dev $dev.+metric $met" | sed -r 's/.+via ([0-9.]+) .+/\1/' ` # gateway # echo -e "dev: $dev\nmet: $met\nsub: $sub\nsrc: $src\ngwy: $gwy" if [ -z "$tbl" -o -z "$dev" -o -z "$met" -o -z "$sub" -o -z "$src" -o -z "$gwy" ]; then echo "configuration error" exit fi flg_restart="/tmp/openvpn.restart" flg_iproute="/tmp/openvpn.routes" del_ext_routes_rules () { echo " deleting old routes..." ip route del default via $gwy table $tbl dev $dev # local gateway ip ip route del to $sub table $tbl dev $dev # local subnet ip rule del from $src table $tbl # local ip } # del_ext_routes_rules add_ext_routes_rules () { echo " adding routes..." ip rule add from $src table $tbl # local ip ip route add to $sub table $tbl dev $dev # local subnet ip route add default via $gwy table $tbl dev $dev # local gateway ip } # add_ext_routes_rules # allow ssh via on non vpn address while vpn is open # https://forums.openvpn.net/viewtopic.php?f=15&t=7163&start=20 # https://serverfault.com/questions/659955/allowing-ssh-on-a-server-with-an-active-openvpn-client allow_outside_connections_to_eth () { echo "`date +'%F %T'`: updating routes..." # fix random lock out by deleting previous rules/routes del_ext_routes_rules ; sleep 1 del_ext_routes_rules 2> /dev/null # paranoia # re-add rules/routes add_ext_routes_rules } # allow_outside_connections_to_eth # another idea to check connection is up: try pinging vpn server ip (ping -c1 -w5 -q \`ip route|grep via.*eth0|sed ...\`) # here instead we check SSH connectivity: ensure_ssh_from_outside_via_eth () { tun_ip=`ip route | grep "tun.*src" | cut -f 9 -d ' '` cur_ip=`dig -b $src @208.67.222.222 +short myip.opendns.com` #[ -n "$tun_ip" -a -n "$cur_ip" ] && \ # { nc -w 5 -z -s $tun_ip $cur_ip 22 || allow_outside_connections_to_eth; } if ! [ -n "$tun_ip" -a -n "$cur_ip" ] ; then echo "`date +'%F %T'`: tun/eth IPs unavailable, stopping VPN..." quit_openvpn return fi if nc -w 5 -z -s $tun_ip $cur_ip 22 ; then rm -f $flg_iproute else if ! [ -f "$flg_routes" ]; then allow_outside_connections_to_eth touch $flg_iproute else echo "`date +'%F %T'`: no access from outside, stopping VPN..." quit_openvpn rm -f $flg_iproute fi fi } # ensure_ssh_from_outside_via_eth quit_openvpn () { # clean status rm -f $flg_iproute del_ext_routes_rules pkill openvpn ; sleep 2 pgrep openvpn > /dev/null && pkill -KILL openvpn } # quit_openvpn canary_failed () { echo "`date +'%F %T'`: CANARY FAILED ($1)! stopping VPN & exiting..." quit_openvpn exit } # canary_failed # exit if requested if [ "$1" = "stop" ]; then quit_openvpn exit fi # infinite loop run/check/restart openvpn while : ; do ts=`date +'%F %T'` # test proxy.sh warrant canary at 3AM psh_canary="/tmp/proxysh-${ts:0:10}.canary" if [ ! -f $psh_canary -a "03" = "${ts:11:2}" ]; then echo "$ts: testing warrant canary..." rm -f /tmp/proxysh-*.canary # purge previous file wget -q -O - https://proxy.sh/canary | gzip -9 -c > $psh_canary # test messages list cnd='The below "warrant canary" has been generated on: ' #`date +%F` cn1="To this date, there has been no warrants, searches or seizures that have not been reported in our Transparency Report, and that have actually taken place. The sky is blue :)" cn2="No warrants, searches or seizures of any kind, other than those reported via our Transparency Report, have ever been performed on proxy.sh assets, including in the following locations:" # test messages presence zgrep "$cnd" $psh_canary # print generation date zgrep "$cn1" $psh_canary > /dev/null || canary_failed "cn1" zgrep "$cn2" $psh_canary > /dev/null || canary_failed "cn2" fi if ! pgrep openvpn > /dev/null ; then ./proxysh-update.sh echo "$ts: restarting openvpn..." echo "${ts:0:10}" > $flg_restart # update restart flag allow_outside_connections_to_eth > /dev/null 2>&1 openvpn --config proxysh.conf --daemon sleep 20 fi # check SSH is reachable from outside via eth0 every 10 minutes [ "${ts:15:1}" = "0" ] && ensure_ssh_from_outside_via_eth # restart daily at 1AM if [ "$(<$flg_restart)" != "${ts:0:10}" -a "01" = "${ts:11:2}" ]; then echo echo "$ts: daily stopping..." quit_openvpn fi #echo -en "$ts\r" sleep 15 done |
the ip
commands are used to keep allowing incoming traffic from the previous default gateway 192.168.1.1
to the initial ip 192.168.1.110
in order to continue accessing your host services from the outside.
Note: Rarely you may lost connectivity via your physical interface (eg: dig -b 192.168.1.110 ...) for apparently no reason... just restart the networking service and vpn:
1 | sudo pkill openvpn && sudo systemctl restart networking && ./run.sh |
this should not happen anymore thanks to the ensure_ssh_from_outside_via_eth
function.
Extras
- To know your public IPs while openvpn is running type:
1 2 | dig @208.67.222.222 myip.opendns.com # get VPN server IP dig -b 192.168.1.110 @208.67.222.222 myip.opendns.com # get ISP public IP |
- If you want you can use the proxy.sh available proxies:
1 2 3 | socks.proxy.sh:1080 # useable inside the vpn (no auth required) ext-eu.proxy.sh:1080 # useable outside the vpn (same VPN credential) ext-us.proxy.sh:1080 # useable outside the vpn (same VPN credential) |
Here you can find more info for your precious privacy:
- Warrant canary (checked in
run.sh
) - Network alerts (outage, maintenance)
- Transparency report (abuse complaints)
- Warrant canary (checked in
For stronger security you can also nest your VPN connections, but make sure that the routes which are set by the second vpn client do not replace the direct access to the first vpn server:
1 2 3 | # Note: VPN servers must have different IPs ip route add IP_OF_1st_VPN_SERVER dev WAN_INTERFACE # eth0/wlan0 ip route add IP_OF_2nd_VPN_SERVER dev 1st_VPN_INTERFACE # tun0 |
- In order to retain connectivity to your default interface and just create a new virtual interface
tun0
for a separate use, you can override pushed routes from the server by adding these lines to the configuration file:
1 2 3 4 | route 0.0.0.0 192.0.0.0 net_gateway route 64.0.0.0 192.0.0.0 net_gateway route 128.0.0.0 192.0.0.0 net_gateway route 192.0.0.0 192.0.0.0 net_gateway |
Run the vpn inside a network namespace
Run openvpn
telling it to not configure the tunX
interface:
1 2 3 4 5 | openvpn --config proxysh.conf \ --ifconfig-noexec --route-noexec \ --up proxysh-cmd-netns.sh \ --route-up proxysh-cmd-netns.sh \ --down proxysh-cmd-netns.sh |
namespace creation and network configuration are then managed by the proxysh-cmd-netns.sh
script1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #!/bin/sh case $script_type in up) ( ip netns list | grep -qs proxysh ) || ip netns add proxysh ip netns exec proxysh ip link set dev lo up ip link set dev "$1" up netns proxysh mtu "$2" ip netns exec proxysh ip addr add dev "$1" \ "$4/${ifconfig_netmask:-30}" \ ${ifconfig_broadcast:+broadcast "$ifconfig_broadcast"} if [ -n "$ifconfig_ipv6_local" ]; then ip netns exec proxysh ip addr add dev "$1" \ "$ifconfig_ipv6_local"/112 fi ;; route-up) ip netns exec proxysh ip route add default via "$route_vpn_gateway" if [ -n "$ifconfig_ipv6_remote" ]; then ip netns exec proxysh ip route add default via \ "$ifconfig_ipv6_remote" fi ;; down) # do not delete the namespace: keep it in case of server disconnection #ip netns delete proxysh ;; esac |
Once the VPN is up and running you can launch programs in the proxysh
network namespace as root
like this:
1 | ip netns exec proxysh su username -l -c "command arguments" |
or you can conveniently use this script:
1 2 3 4 5 6 7 8 9 10 11 12 | #!/usr/bin/sudo /bin/bash function die() { echo "USAGE: netns-exec namespace cmd [arguments...]" exit } ([ -z "$1" ] && die) || NS_NAME="$1" ; shift # check namespace ([ -z "$1" ] && die) || NS_CMD="$1" ; shift # check command RUN_CMD="$NS_CMD $@" ip netns exec $NS_NAME su $SUDO_USER -l -c "${RUN_CMD}" |
Source: OpenVPN manpage, Proxy.sh raspi howto, allow SSH via eth0, up/down scripts, UFW limit traffic on eth0 & paste.bin script, Deluge vpn/proxy guide, Proxy.sh SOCKS, Deluge VPN 1 and 2, Getting started with Proxy.sh VPN, Ignore pushed routes on Superuser and OpenVPN docs
Tips: test reachable port on server with NC, get SSH server key fingerprint, VPN services comparison