Skip to content

Instantly share code, notes, and snippets.

Last active October 28, 2022 19:32
What would you like to do?
Access to a remote private IPv4 network, using SSH as a VPN
# Goal to reach:
# +--------------------------------+ +-----------------------------+
# | tun1 | <=(ter)=> | tun1 |
# | Private IPv4 of the remote net | net | Remote IPv4 private network |
# +--------------------------------+ +-----------------------------+
# Good doc:
# Notes:
# - If you just need to access to a webpage located on a remote non-reachable web
# server, just configure your browser to use a SOCKS5 created with ssh -D, and
# you don't need a root access or any specific configuration on the remote server
# - If you just need to access to various TCP connections from your laptop, just use
# sshuttle, and you don't need a root access or any specific configuration on the
# remote server (it uses iptable to redirect TCP flows and uses directly SSH to
# transmit data, which is more efficient than using SOCKS5)
# - But with this solution (ssh -w), you get a real VPN and you can do everything \o/
# On your local laptop:
# - Be sure all host key verifications on the SSH path are already done
# - Be sure your SSH agent is already running and will not ask any input
# On the remote server:
# - apt install uml-utilites
# - PermitRootLogin yes in sshd_config
# - PermitTunnel yes in sshd_config
remote_prefix=10.10.0 # /24
# This script has to be runned with your standard user
if [ $EUID -eq 0 ]; then
echo '[ERR] You should not be root.' 1>&2
exit 1
set -x
# SSH has to be used as root on your laptop to be able to open the tunnel
# ... but we would like to keep all SSH configs in ~user/.ssh/config
# (with a ProxyCommand, remind to use -F /root/.ssh/config.vpn)
sudo cp "/home/$USER/.ssh/config" /root/.ssh/config.vpn
sudo chown root: /root/.ssh/config.vpn
# ... and to use the SSH agent of the standard user
ssh -A "${local_rootssh}" "\
ssh -F /root/.ssh/config.vpn -TC -w 1:1 ${remote_ssh} '\
ip link set tun1 up;\
ip address add ${remote_prefix}.${remote_peer_ip}/32 peer ${remote_prefix}.${local_peer_ip} dev tun1;\
arp -sD ${remote_prefix}.${local_peer_ip} ${remote_netdev} pub;\
echo 1 > /proc/sys/net/ipv4/ip_forward\
" > /dev/null &
# Wait for the creation of the tunnel
false || while [ $? -ne 0 ]; do
sleep 1
ip link show dev tun1 &> /dev/null
sudo ip link set tun1 up
sudo ip address add "${remote_prefix}.${local_peer_ip}/32" peer "${remote_prefix}.${remote_peer_ip}" dev tun1
sudo ip route add "${remote_prefix}.0/24" via "${remote_prefix}.${remote_peer_ip}"
vpn_pid=$(ps aux | grep ssh | grep -v "${local_rootssh}" | awk "/[1] ${remote_ssh}/ { print \$2 }")
set +x
echo -e "\nStop VPN connection?"
sudo kill "${vpn_pid}"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment