Self-Hosted VPN Options
As a follow-up to my 2021 test, I wanted to compare various VPN options in regards to bandwidth speed performance. My requirements: self-hosted Linux-based server/exit node (Debian 12, amd64, 1 Xeon Gold CPU @ 3.0 GHz, 1 GB RAM, 10 Gbps bandwidth [real-world average 353 Mbps]) and an Android client (Pixel 8, Android 16, always-on VPN, block connections without VPN). The Android device was 775 miles away from the Linux exit node to stress test the latency. Note: all tests were performed as root with no firewall -- in production you would want to apply appropriate security and control measures.
________________________________________________________________________
apt install -y nano wget iptables wireguard qrencode
wget https://github.com/naggie/dsnet/releases/download/v0.8.1/dsnet-linux-amd64 -O /usr/local/bin/dsnet
chmod +x /usr/local/bin/dsnet
dsnet init
nano /etc/dsnetconfig.json
# Add "0.0.0.0/0" to the 'Networks' array and "8.8.8.8" as the 'DNS' setting
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
NETDEV=$(ip -o route get 8.8.8.8 | cut -f 5 -d " ")
iptables -t nat -A POSTROUTING -o $NETDEV -j MASQUERADE
iptables -A FORWARD -i dsnet -o $NETDEV -j ACCEPT
iptables -A FORWARD -i $NETDEV -o dsnet -m state --state RELATED,ESTABLISHED -j ACCEPT
dsnet up
dsnet add example | qrencode -t ansiutf8
# Android device: download WireGuard app from Play Store and scan QR code
VPN off: 580, 530, 560, 570, 550 = average 558 Mbps
VPN on: 87, 79, 98, 78, 62 = average 81 Mbps
________________________________________________________________________
Warning: if you use the commercial Tailscale platform always run with "--no-logs-no-support", otherwise they monitor your traffic.
apt install -y wireguard-tools networkd-dispatcher ethtool
curl -sLO https://github.com/juanfont/headscale/releases/download/v0.26.1/headscale_0.26.1_linux_amd64.deb
apt install ./headscale*.deb
echo '{"acls":[{"action":"accept","src":["*"],"dst":["*:*"]}]}' > /etc/headscale/acl.hujson
chmod 644 /etc/headscale/acl.hujson
umask 077
wg genkey > /etc/headscale/private.key
systemctl enable headscale
nano /etc/headscale/config.yaml
# make these edits:
- server_url: https://vpn.mydomain.com:443
- listen_addr: 0.0.0.0:443
- grpc_listen_addr: 0.0.0.0:50443
- allocation: random
- acme_email: "youremail@mydomain.com"
- tls_letsencrypt_hostname: "vpn.mydomain.com"
- policy > path: "/etc/headscale/acl.hujson"
- base_domain: mydomain.com
- magic_dns: false
systemctl restart headscale && sleep 10 && systemctl status headscale
headscale users create example
curl -fsSL https://tailscale.com/install.sh | sh
echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.d/99-tailscale.conf
sysctl -p /etc/sysctl.d/99-tailscale.conf
printf '#!/bin/sh\n\nethtool -K %s rx-udp-gro-forwarding on rx-gro-list off \n' "$(ip route show 0/0 | cut -f5 -d" " | head -n1)" | tee /etc/networkd-dispatcher/routable.d/50-tailscale
chmod 755 /etc/networkd-dispatcher/routable.d/50-tailscale
/etc/networkd-dispatcher/routable.d/50-tailscale
tailscale up --advertise-exit-node --accept-dns=false --login-server=https://vpn.mydomain.com:443
# It will provide a URL for you to open. Click on it and copy the command to authenticate the request. Paste the command into your Headscale server terminal (changing USERNAME to the user you created in the step above).
headscale nodes approve-routes --identifier 1 --routes 0.0.0.0/0
# Android device: install Tailscale from the Google Play Store, open it. Tap "Get Started". Tap "OK" at the VPN prompt. At the screen with the "Log in" button, quickly tap the gear icon in the top-right corner. (If you wait too long and it redirects you to a login page with various SSO options, tap the back button to go back to the prior screen). On the Settings page, tap Accounts. On the Accounts page, tap the three vertical button icon in the top-right corner and select 'Use an alternate server'. Type https://vpn.mydomain.com and then tap "Add account". Copy the resulting command shown to your Headscale server to authenticate. Once you get the Node yournode registered message, go back to the mobile app. In the EXIT NODE dropdown, select the exit node you created above. It should now appear in blue at the top of the Tailscale app screen and you should now be connected!
VPN off: 550, 600, 590, 620, 570 = average 586 Mbps
VPN on: 86, 90, 78, 110, 94 = average 92 Mbps
________________________________________________________________________
OpenConnect ocserv (or AnyLink) + Cisco Secure Client (AnyConnect)
apt install -y iptables-persistent certbot ocserv
tee -a /etc/sysctl.conf <<EOF
# Enable routing
net.ipv4.ip_forward = 1
# Protect from IP Spoofing
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Ignore ICMP broadcast requests
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Protect from bad icmp error messages
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Disable source packet routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
# Block SYN attacks
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5
# Log Martians
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Ignore send redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# Ignore ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
EOF
sysctl -p
iptables -t nat -A POSTROUTING -j MASQUERADE
iptables-save > /etc/iptables/rules.v4
Result: I couldn't get this to work with the Cisco Secure Client 5.1.9.115 in the Play Store
________________________________________________________________________
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
apt install -y jq
export ZITI_NETWORK="example"
export ZITI_CTRL_EDGE_ADVERTISED_ADDRESS=vpn.mydomain.com
export ZITI_CTRL_EDGE_ADVERTISED_PORT=8800
export ZITI_ROUTER_ADVERTISED_ADDRESS=vpn.mydomain.com
export ZITI_ROUTER_PORT=9090
source /dev/stdin <<< "$(wget -qO- https://get.openziti.io/ziti-cli-functions.sh)"; expressInstall
startController
startRouter
zitiLogin
mv /root/.ziti/quickstart/example/ziti-bin/ziti-v*/ziti /usr/local/bin/
ziti edge create identity "NewUser" -o NewUser.jwt
# Android device: copy the NewUser.jwt file to the device and then install the 'Ziti Mobile Edge' app from the Play Store and open. Tap the 'Add Identity' icon in the top-right corner and choose 'Select JWT File' and locate the NewUser.jwt file.
Result: Says connected but no Internet access on the Android device.
________________________________________________________________________
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
apt install -y jq
curl -fsSL https://get.docker.com | sh
export NETBIRD_DOMAIN=vpn.mydomain.com; curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started-with-zitadel.sh | bash
# Follow the instructions from the output of the prior command to login to the NetBird portal and change the default admin password
curl -fsSL https://pkgs.netbird.io/install.sh | sh
netbird up --management-url https://vpn.mydomain.com
# Click the three dots to the right of the newly added peer and choose 'Set Up Exit Node' then in the groups dropdown choose All.
# Android device: install the NetBird app from the Play Store and open. Tap the three-bar icon in the top-left corner and choose 'Change Server' (tap Yes when prompted for confirmation). In the Server textbox set https://vpn.mydomain.com:443 Once verified, you can tap the big grey circle in the middle of the app to connect. If you get an error, disable Always-On VPN and then try again and you should be prompted to login with your admin credentials. After you authenticate you can restore the Always-On VPN settings.
VPN off: 600, 550, 590, 630, 550 = average 584 Mbps
VPN on: 79, 89, 91, 35, 64 = average 72 Mbps
VPN off: 610, 580, 610, 600, 590 = average 598 Mbps
VPN on: 15, 12, 15, 31, 15 = average 18 Mbps
VPN off: 630, 600, 560, 630, 560 = average 596 Mbps
VPN on: 28, 35, 37, 18, 18 = average 27 Mbps
# Android device: install the WG Tunnel app from the Play Store and open. Tap the plus (+) button to load the configuration via QR code. You should then be able to connect.
VPN off: 560, 630, 550, 600, 550 = average 578 Mbps
VPN on: 79, 89, 91, 35, 64 = average 72 Mbps
Note: AmneziaWG has their own app on the Play Store but I found it to be slower than WG Tunnel.
________________________________________________________________________
wget https://git.io/vpn -O openvpn-install.sh && bash openvpn-install.sh
# select UDP mode
# transfer client ovpn file to Android device
# Android device: download OpenVPN Connect app from Play Store, open, and agree to terms. On the 'Upload File' tab, tap 'Browse' and select the ovpn file you downloaded in the prior step. Then tap 'Connect'.
VPN off: 610, 620, 590, 570, 580 = average 594 Mbps
VPN on: 58, 61, 69, 52, 62 = average 61 Mbps
VPN off: 580, 610, 580, 640, 570 = average 596 Mbps
VPN on: 67, 68, 57, 68, 31 = average 58 Mbps
________________________________________________________________________
su -c "bash <( wget -qO- https://github.com/vpnhood/VpnHood.App.Server/releases/latest/download/VpnHoodServer-linux-x64.sh)"
/opt/VpnHoodServer/vhserver gen
# copy the '--- AccessKey ---' string that starts with 'vh://' to a secure location
# Android device: download the 'VpnHood! Client' app from Play Store (not the 'VpnHood! Connect' app) and open. Tap on 'Server' at the bottom then tap 'Add server' and paste the 'vh://....' value from the previous step. If you get an error while initializing, temporarily disable Always-on VPN in the Android settings and retry.
VPN off: 590, 540, 630, 590, 590 = average 588 Mbps
VPN on: 75, 77, 80, 63, 73 = average 74 Mbps
________________________________________________________________________
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
bash <(curl https://bash.ooo/nami.sh)
nami install joker brook
joker brook server --listen :9999 --password hello
# Android device: download the Android APK file and install it. A free account via email is required (you can use an anonymous email service like TempMail). Once logged in, tap the plus (+) icon in the top-right corner. Enter the IP address of the server and the port the server is listening on (9999 in this example) as well as the password indicated in the server command above ('hello' in this example), then tap 'Add'. Tap 'Connect' and you should see an astronaut sitting on a rocket indicating the connection was successful.
VPN off: 560, 570, 460, 460, 590 = average 528 Mbps
VPN on: 300, 282, 252, 298, 321 = average 291 Mbps
Comments
Post a Comment
Keep it clean and professional...