Vpn over ssh tunnel

VPN over SSH

There are several ways to set up a Virtual Private Network through SSH. Note that, while this may be useful from time to time, it may not be a full replacement for a regular VPN. See for example [1].


Using badvpn’s tun2socks

badvpn is a collection of utilities for various VPN-related use cases.

Start SSH dynamic SOCKS proxy

First, we will set up a normal SSH dynamic socks proxy like usual:

Set up badvpn and tunnel interface

Afterwards, we can go ahead with setting up the TUN.

Now you have a working local tun0 interface which routes all traffic going into it through the SOCKS proxy you set up earlier.

Get traffic into the tunnel

All that’s left to do now is to set up a local route to get some traffic into it. Let us set up a route that routes all traffic into it. We will need three routes:

  1. Route that goes to the SSH server that we use for the tunnel with a low metric.
  2. Route for DNS server (because tun2socks does not do UDP which is necessary for DNS) with a low metric.
  3. Default route for all other traffic with a higher metric than the other routes.

The idea behind setting the metrics specifically is because we need to ensure that the route picked to the SSH server is always direct because otherwise it would go back into the SSH tunnel which would cause a loop and we would lose the SSH connection as a result. Apart from that, we need to set an explicit DNS route because tun2socks does not tunnel UDP (required for DNS). We also need a new default route with a lower metric than your old default route so that traffic goes into the tunnel at all. With all of that said, let us get to work:

Now all traffic (except for DNS and the SSH server itself) should go through tun0 .

OpenSSH’s built in tunneling

OpenSSH has built-in TUN/TAP support using -w : . Here, a layer 3/point-to-point/ TUN tunnel is described. It is also possible to create a layer 2/ethernet/TAP tunnel.

Enable forwarding for the TUN device

To enable forwarding for the TUN device, edit /etc/ssh/sshd_config and set PermitTunnel to yes , point-to-point or ethernet . Setting yes enables forwarding for both point-to-point and ethernet tunnels. See sshd_config(5) for details.

Create tun interfaces using systemd-networkd

Once these files are created, enable them by restarting systemd-networkd.service .

Also, you may manage tun interfaces with ip tunnel command.

Creating interfaces in SSH command

SSH creates both interfaces automatically, but IP and routing should be configured after the connection is established.

Start SSH

or you may add keep-alive options if you are behind a NAT.


  • ssh should have access rights to tun interface or permissions to create it. Check owner of tun interface and/or /dev/net/tun.
  • Obviously if you want to access a network rather than a single machine you should properly set up IP packet forwarding, routing and maybe a netfilter on both sides.
  • If you do not enable tunneling, you may get the following error when you want to create an SSH tunnel using -w :

Using PPP over SSH

pppd can easily be used to create a tunnel through an SSH server:

When the VPN is established, you can route traffic through it. To get access to an internal network:

To route all Internet traffic through the tunnel, for example, to protect your communication on an unencrypted network, first add a route to the SSH server through your regular gateway:

Next, replace the default route with the tunnel

Helper script

pvpn (package pvpn AUR ) is a wrapper script around pppd over SSH.


Ubuntu Documentation

Needs Updating
This article needs updating to include the latest versions of Ubuntu. More info.

This page details how to set up an SSH VPN.

NB: You must be using OpenSSH version 4.3 or later to do this— this means that this will not work with Ubuntu 6.06 or earlier’s default packages — it will only work with Ubuntu 6.10 or later, or with a locally compiled SSH version 4.3 or later.

This page discusses using SSH to set up SSH-based point to point connections, which can then be used to create routes that create virtual private networks.

Note that using SSH in this fashion is not the «best» way to create a permanent, stable VPN. Notably, SSH uses TCP, and TCP over TCP can provide abysmal performance under pathological conditions. See also OpenVPN, etc.

Читайте также:  Картридж 719h для каких принтеров

You also need to have installed uml-utilities on the «calling» machine (the one that will ask for the tunnel). You can check by trying:


OpenSSH version 4.3 introduced a new feature: the ability to create on-the-fly «Virtual Private Networks» via the tunnel driver, or «tun» driver. This feature allows you to create a network interface that bridges two physically disparate network segments. A quick diagram:

What does this diagram represent? In this case, we have two machines, machine A and machine B. Machine A is connected to network A via ethernet, and machine B is connected to network B via ethernet. Machine A’s IP address on Network A is, and Machine B’s IP address on Network B is Each network has an internet NAT gateway to allow for internet connectivity.

In this example, we are connecting machine B to network A via an ssh tunnel interface. Machine A already has an IP addresses on network A: its ethernet interface address ( Machine B must also be allocated one IP address on network A: its tunnel interface address (

Also, Machine B must have some access to the ssh server on Machine A; the most direct way for this to happen is that Machine A must have either a globally routable address itself; or (as is diagramed), port 22 (or whatever port ssh is running on) must be forwarded to Machine A by the NAT system. There are other ways to allow Machine B access to Machine A’s ssh server, but this is left as an exercise for the reader.

Once the tunnel is set up, Machine B will be able to directly access Network A. In other words, Machine B would be «plugged in» to Network A via its tunnel with Machine A. Of couse, the devil’s in the details: how do you set all this up?

IP forwarding

Of course the first and most obvious thing is that you’d better have IP forwarding enabled.

on Machine A (and it wouldn’t hurt on B), execute:

The SSH command

The actual SSH command that gets the ball rolling is quite simple:

on Machine B, execute:

Tip : Additional ssh options.

  • -N Do not execute a remote command. This is useful for just forwarding ports (or in this case tunnels).
  • -T Disable pseudo-tty allocation.
  • -C Requests compression of all data (including stdin, stdout, stderr, and data for forwarded X11 and TCP connections). Compress can speed up or potentially slow down your speed, so try with and without.
  • -f Requests ssh to go to background just before command execution.

This command creates a tunnel interface named tun0 on both the client and server systems. In keeping with our diagram above, the server is Machine A (with a globally routable IP address of, and the client is Machine B.

Note that you will need to have root access on both systems in order for ssh to be able to create these interfaces (see the security section below for security considerations and options to increase security). Additionally, you will need the following settings in your sshd_config on Machine A (the server):

Security considerations

To increase security, use ssh keys — see AdvancedOpenSSH for information on keys — and change Permit Root Login yes to :

Do not let that command fool you, without-password means root can not log in with a password (see man sshd).

Also, on the server, if you use a key, you do NOT need to set a root password and your can restrict what commands can be run with the key (to ssh tunnels only).

See the «Single-purpose keys» section of this link .

On the client side, again if you do not wish to give your user complete root access , configure sudo. See RootSudo or sudoers man page.

If no errors occur, then you should be able to see a tun0 interface on both systems as existing, but unconfigured: Machine A:

($ represents the shell prompt and not a character to type)

Configuring the interfaces

At this point, we have got interfaces, but they are unconfigured. All we need to do to configure them is give them each an IP address (do this as root):

Once each interface is configured, we have essentially got the VPN set up; it is just minor details from here. In fact, we can now ping from Machine B to Machine A:

And of course we can also ping from Machine A back to Machine B:

Plugging into the network

At this point, we’ve created the actual link that allows Machine B to be plugged into Network A, but we haven’t set up any routing information to actually get packets back and forth between Machine B and Network A. The first thing we need to do is to tell Machine B about Network A:

This allows us to send packets from Machine B to any IP address on Network A, via Machine A. However, to ensure that packets have a route back to Machine B, we need to set some things up on Machine A.

Читайте также:  Postgresql drop all constraint

This ensures that other machines plugged into Network A will know to send packets destined for to Machine A (so that it can forward them back to Machine B).

At this point, we do have two way communication betweek Network A and Machine B. Therefore, we can ping another machine on Network A from Machine B:

Expanding the scope of the VPN

At this point, we have successfully plugged Machine B into Network A, and Machine B can access Network A’s resources and vice versa. However, what if we want to expand the scope of this VPN— what if we want to pretend that Machine B’s only network connection is through network A?

If we did this, then all packets coming from or going to Machine B would route through Network A; this would complete Machine B’s integration into the private network. So, how do we do this?

Simple: we just switch Machine B’s default gateway.

However, first, we must create a host-based route to Machine A’s globally routable IP address; all packets except for the packets that actually create the link must go through the tunnel, but of course the packets that create the tunnel cannot go through the tunnel.

In this case, is Machine B’s current default gateway; it is the gateway on Network B that provides internet connectivity. Before we switch Machine B’s default gateway away from Network B, we must set up this explicit route so that tunnel packets will continue to flow.

After that route is in place, we can switch Machine B’s default gateway:

In this case, again, is Network B’s default gateway, and is Network A’s default gateway. Since Machine B is now connected to Network A, we are telling it to use Network A’s default gateway instead of its usual default gateway on Network B. At this point, the conversion is complete, and Machine B is now completely on Network A and has all the resources available to Network A, through the SSH tunnel. We can verify this by looking at the output of a tracepath:

Automating it all with ifup/down

At this point, we have successfully created a virtual private network using SSH 4.3’s tunnels. Can we automate this process with ifup/down? The answer is: yes!

These example /etc/network/interface snippets show how you would, on Machine B, simply have to execute:

And the system would automatically make the ssh connection, set up the tunnel, and turn on the VPN. Additionally, the ifdown command can be used to put the routes back to normal, or turn off the VPN.

Note that the sleep commands in the snippet are there to allow ssh time to set the tunnel interface up, as it will not be instantaneous.

Where do I go from here?

There are many other possible ways to use SSH 4.3’s tunnels besides creating a VPN to connect machine B to network A. For example, you could connect machine B to network A, and then route back on machine A to network B, creating a sort-of reverse VPN. Or you could connect machine B to network A, and then redirect traffic from network A to machine B to another system on network B. The possibilities are only limited by the amount of root access you have.

SSH_VPN (последним исправлял пользователь ki7mt 2014-01-10 06:35:28)

The material on this wiki is available under a free license, see Copyright / License for details
You can contribute to this wiki, see Wiki Guide for details


Кунг-фу стиля Linux: бесплатный VPN по SSH

Если вы видите на некоторых сайтах множество рекламных баннеров, то вы знаете, что, если не будете пользоваться VPN (Virtual Private Network, виртуальной частной сетью), хакеры очень скоро захватят и разорят ваш компьютер и сожгут ваше жилище. Ну, они, по крайней мере, точно что-то такое задумывают. На самом же деле существует две основных причины, по которым кому-то может понадобиться VPN-подключение. Можно, конечно, купить подписку на соответствующий сервис, но если у вас есть SSH-доступ к какому-нибудь компьютеру, имеющему выход в интернет, это значит, что вы можете создать собственный VPN-сервис, не потратив на это ни копейки.

Основная идея тут заключается в том, чтобы подключиться к удалённому компьютеру, находящемуся в некоей сети, и сделать так, чтобы весь ваш сетевой трафик выглядел бы для той сети как локальный.

Первая причина, по которой это может кому-то понадобиться, заключается в повышении уровня безопасности и в заблаговременном устранении возможных угроз. Например, может понадобиться печатать на сетевом принтере, не «выставляя» этот принтер в обычный интернет. В результате, например, некто может сидеть в кафе и, подключившись к сети по VPN, распечатывать документы на принтере, чувствуя себя так, будто он находится за своим рабочим столом, а принтер стоит в паре метров от него. Использование VPN, кроме того, будет означать, что данные, передаваемые по WiFi-сети кафе, будут зашифрованы.

Вторая причина — это скрытие реального местоположения пользователя от любопытных глаз. Предположим, кому-то нравится смотреть видеоматериалы BBC, но живёт он в Эквадоре. Это значит, что для того чтобы видео не были бы для него заблокированы, ему нужно будет подключиться по VPN к сети, находящейся в Великобритании. Если власти некоей страны мониторят и цензурируют интернет, то жителям этой страны тоже может пригодиться возможность замаскировать свой трафик.

Читайте также:  Canon mf3200 принтер не видит

Использование SSH для организации VPN-подключения подойдёт для решения обеих вышеописанных задач. Правда, если вам, преимущественно, интересна первая из них, то вам, возможно, лучше подойдёт использование выделенного маршрутизатора или маленького компьютера, вроде Raspberry Pi, нацеленного на решение вашей задачи. Надо сказать, что если вы где-то арендуете сервер, то «VPN по SSH» — это не для вас.

Предварительная подготовка

Вам понадобится лишь root-доступ к обеим машинам. На удалённом компьютере должен быть установлен SSH-сервер. Понадобится вам, конечно, и SSH-клиент. И на локальной, и на удалённой машинах нужно будет выполнить некоторые настройки. Я использую KDE, поэтому для выполнения необходимых настроек применяю NetworkManager, но можно пойти и другим путём. Применение NetworkManager всего лишь упрощает задачу.

На сервере должны быть выполнены некоторые особые настройки, но вполне возможно то, что они уже на нём сделаны. Так, в файле /etc/ssh/sshd_config должна присутствовать строка PermitTunnel=yes . Кроме того, может понадобиться установить в значение yes параметр AllowTCPForwarding . В некоторых настройках может нуждаться и файрвол. При этом инструкции по конфигурированию плагина NetworkManager могут оказаться полезными даже тем, кто этой программой не пользуется.

Настройки на стороне клиента

Если вы пользуетесь NetworkManager, то вам понадобится соответствующий плагин. Для Neon и других дистрибутивов, основанных на Debian, подойдёт пакет network-manager-ssh . Это — всё, что вам потребуется. Если вы не хотите пользоваться NetworkManager, то можете применить следующие команды из материала автора плагина:

Тут нужен root-доступ к обеим системам, так как мы создаём туннель. Это, даже при использовании плагина, ведёт к нескольким проблемам. Очевидно, нам не хотелось бы, чтобы у нас постоянно запрашивали бы пароль для SSH-подключения и проводили бы проверку ключа. Но если настраивать VPN вручную, с этими проблемами можно справиться.


Большинство современных систем не позволяют входить в систему с root-правами, используя пароль, а иногда и вовсе не позволяют подключаться к системе в таком режиме. Поэтому нам, в первую очередь, нужно решить эту проблему. Кроме того, когда NetworkManager запускает SSH, он ищет ключи, причём, для root-пользователя, а не для обычного пользователя. Если он чего-то не может найти, он просто останавливается. Поэтому нам нужно обеспечить возможность беспрепятственного root-входа в систему.

Для того чтобы обеспечить возможность root-входа на сервер, нужно отредактировать файл /etc/ssh/sshd_config и установить параметр PermitRootLogin в значение yes . Рекомендую работать в этом режиме ровно столько времени, сколько нужно на выполнение следующих шагов настройки сервера. Далее, нужно будет перезапустить sshd-сервер, например, такой командой:

Ещё можно воспользоваться такой командой:

Затем, войдя в локальную машину с использованием обычной учётной записи, нужно воспользоваться ssh-copy-id для установки сертификата на хост-машину. После того, как это будет сделано, нужно вернуться на сервер и поменять в /etc/ssh/sshd_config значение PermitRootLogin на prohibit-password . Благодаря этому входить на сервер как root-пользователь можно будет с использованием сертификата, но не с использованием пароля.

Если вы уже выполняли вход с root-аккаунта, то вам, возможно, уже задавали вопрос о том, хотите ли вы принять ключ сервера. Если это не так — значит — у нас проблема. Если можете, осуществите вход и ответьте утвердительно на соответствующий вопрос, после чего система перестанет его задавать. Но, если сделать этого нельзя, мы можем решить проблему, отключив StrictHostKeyChecking .

В теории, можно передавать плагину NetworkManager дополнительные опции ssh, но по каким-то причинам этот подход не работает с версией плагина из репозиториев. Если же вы плагином не пользуетесь, делая всё вручную, то вы можете сами выполнить необходимые настройки. Настройки SSH для root-пользователя можно задать в /root/.ssh/config . Можно, кроме того, задать глобальные настройки в /etc/ssh/ssh_config .

Если вы меняете глобальные настройки, то, если система это поддерживает, рассмотрите возможность использования /etc/ssh/ssh_config.d . Благодаря этому у вас будет возможность задавать параметры для конкретного хоста, которые не будут переписаны при обновлении системы. Например, можно создать в соответствующей директории файл с именем hackaday.conf :

Опять же, если вам не нравится идея проверки ключа хоста, просто один раз войдите в систему из root-аккаунта и вручную примите удалённый ключ. Или, если храбрости вам не занимать, вручную отредактируйте /root/.ssh/known_hosts .


Теперь всё должно быть готово к работе. Если вы используете плагин для NetworkManager, вам понадобится просто установить новое соединение. А именно, нужно перейти в раздел VPN-соединений и выбрать SSH.

Выбор типа соединения

Теперь нужно настроить несколько параметров нового соединения. В том числе — нужно указать сертификат, который планируется использовать для входа в удалённую систему.

После сохранения настроек соединения это соединение можно активировать — как и любой другой сетевой интерфейс. Если вы хотите проверить ваш новый VPN — сначала, в обычном режиме, поинтересуйтесь своим IP-адресом на специальном сайте. А после этого включите VPN и снова узнайте свой адрес. Если VPN-соединение вам установить не удастся — поищите в системном журнале сведения об ошибках, выдаваемых SSH.


Конечно, есть и другие VPN-решения. Но практически гарантированно то, что на удалённом компьютере, с которым вы работаете, есть SSH-сервер. Поэтому предлагаемый метод установления VPN-соединения через SSH — это простое и удобное решение, которым можно воспользоваться без какой-либо предварительной подготовки.


Поделиться с друзьями