Poor mans VPN over SSH
Shell JavaScript
Switch branches/tags
Nothing to show
Clone or download



pvpn is a tool to set up layer 3 VPNs over SSH. It is mostly a wrapper around OpenSSH and pppd(8), but provides a helpful interface. Given that you fulfil the requirements (root access to local machine and SSH server, IP forwarding enabled; see REQUIREMENTS for details), you can, for example, reroute all your IP traffic through myserver with

$ pvpn root@myserver default

pvpn can use several different ways of tunneling, using the -t option: ppp over ssh (-t ppp) or the OpenSSH built-in Layer 3 tunnel (-t ssh-3). The different ways have slightly different requirements. See below for details.

pvpn is useful to protect your network communication when on a public, unencrypted network, or when you need access to a private network without any regular VPN infrastructure available.

See pvpn(8) for a complete reference.


pvpn [OPTION] …​ SSH-HOST [ROUTE] …​


-h, --help

Show help and exit.

-v, --version

Show version and exit.

-d, --debug

Trace code execution.


-t TYPE, --type TYPE

Type of tunnel. Valid options are:

  • ppp (ppp over ssh)

  • ssh-3 (OpenSSH Layer 3)

-i IP1:IP2, --ip IP1:IP2

Use IP1 for local and IP2 for remote tunnel device IPs. Default any:any, which becomes 10.b.c.1:10.b.c.2 where b and c are random.

-s SSH-IP, --first-ssh-hop SSH-IP

Tell IP address or hostname of first SSH server. Needed when you connect through reverse tunnels or intermediate servers with ProxyCommand.

-D, --inherit-dns

Inherit DNS settings from SSH-HOST. When disconnecting, the current DNS settings will be restored.


-S [DEVICE], --stop [DEVICE]

Stop tunnel with client device DEVICE, or all if no DEVICE is given, then exit.


Gain access to the 192.168.xxx.yyy network at work

$ pvpn -i root@work

Encrypt all IP traffic, e.g. when on a public wifi using OpenSSH Layer 3

$ pvpn -t ssh-3 root@secureproxy default

Disconnect tunnel with device ppp0

$ pvpn -S ppp0

Adding additional arguments to SSH:

$ SSH_ARGS="-i ~/.ssh/id_rsa" root@work

Test that traffic is routed through your tunnel with e.g. traceroute(8).


  • GNU/Linux

  • OpenSSH

  • pppd

  • bash

  • iproute2

  • dnsutils (dig(1))

  • asciidoc



Edit config.mk if you need to customize your installation.


Directory under which pvpn will be installed as bin/pvpn


Directory under which the manpage will be installed


$ make install


$ make uninstall


To establish a VPN connection through an SSH server, the following is required:

  • root access on both client and server. To enable root SSH access on the server via authentication keys, set below in /etc/ssh/sshd_config.

PermitRootLogin without-password
  • Authentication through SSH authentication keys. On the client, as root, run

$ ssh-keygen

$ ssh-copy-id root@<server>
  • IP forwarding enabled on server. It can be enabled by something like below, depending on your software stack.

$ sysctl net.ipv4.ip_forward = 1

$ iptables -P FORWARD ACCEPT

$ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
  • iproute2 installed on client and server (ip(8)).

  • dnsutils installed on client (dig(1)).

Table 1. Tunnel type specific requirements
ppp ssh-3

sshd_config PermitTunnel

point-to-point or yes


pppd(8) on both sides

OpenSSH 4.3+


Works-for-me™. Developed and tested on Arch Linux. I have not tested this on other systems but would like to hear from you if you have, successfully or not. Let me know at henrik@k2h.se.


Released under the New BSD License; see LICENSE.