SSH VPN over Internet (SSH tun туннелирование)

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

    Для решения этой задачи, лучше всего подходит технология Vitual Private Network (VPN). Но с помощью чего реализовать эту технологию?
    — Я выбрал SSH.
    Дело в том, что OpenSSH начиная с версии 4.3, поддерживает tun туннелирование. Этим я и воспользовался…



    Схематически это будет выглядеть следующим образом:



    Для начала необходимо установить OpenSSH на сервере. У меня Ubuntu Server, и я это делаю так:

    sudo aptitude install openssh-server

    Хотя, скорее всего, он уже установлен. У меня — точно установлен ;)

    Взглянем на более подробную схему, и обсудим её.



    Как видно из рисунка, рабочий компьютер имеет IP 172.16.0.1 с маской 255.255.255.0 и шлюзом по умолчанию 172.16.0.254, а в качестве DNS указан IP 8.8.8.8

    Компьютер Work:
    IP address: 172.16.0.1
    Netmask: 255.255.255.0
    Default Gateway: 172.16.0.254
    DNS: 8.8.8.8

    Таблица маршрутизации клиента (Work):

      172.16.0.0    0.0.0.0       255.255.255.0   U  1    0 0 eth0
      169.254.0.0   0.0.0.0       255.255.0.0     U  1000 0 0 eth0
      0.0.0.0       172.16.0.254  0.0.0.0         UG 0    0 0 eth0

    169.254.0.0 — это zeroconf маршрут.

    Для организации туннеля, в конфигурационном файле OpenSSH необходимо разрешить туннелирование. В /etc/ssh/sshd_config нужно добавить строку PermitTunnel point-to-point и перезагрузить OpenSSH сервер service ssh restart
    Нюансы:
    Дело в том, что для того что-бы организовать туннель, на сервер необходимо авторизироваться под учётной записью root, что не есть хорошо! Поэтому есть два варианта решения проблемы:
    1. Ставим на root сложный пароль вида md5 хэша.
    2. Настраиваем авторизацию по ключам.
    Какой из методов выбрать — решать Вам. Для описываемого мной примера, это не имеет никакого значения.
    Если вы хотите использовать парольную авторизацию, разрешите в конфиге PermitRootLogin yes для того, что-бы можно было авторизироваться под root.

    Подключение к серверу и создание туннеля делается при помощи команды sudo ssh root@74.125.87.104 -w 0:0
    Обязательно делать через sudo или root-а. Будут создаваться tun устройства, что требует привилегий.

    Ключ -w создаст tun0 устройства на сервере и клиенте, объединив их между собой.
    Вот описание из man-а.
    -w local_tun[:remote_tun]
    Requests tunnel device forwarding with the specified tun(4) devices between the client (local_tun) and the server(remote_tun)

    Настройка tun устройств.
    На сервере ifconfig tun0 10.0.0.1/30 pointopoint 10.0.0.2
    На клиенте ifconfig tun0 10.0.0.2/30 pointopoint 10.0.0.1

    Можно протестировать при помощи ping (с компьютера клиента):
        user@host:~$ ping 10.0.0.1 -c 2
        PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
        64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=5.80 ms
        64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=8.61 ms
    
        --- 10.0.0.1 ping statistics ---
        2 packets transmitted, 2 received, 0% packet loss, time 1001ms
        rtt min/avg/max/mdev = 5.800/7.209/8.618/1.409 ms
    

    Сейчас необходимо весь трафик пустить через tun0, для этого требуется просто указать tun0 шлюзом по умолчанию, но при этом потеряется связь с сервером (Home Server) и DNS сервером. Поэтому прежде чем удалить текущий шлюз по умолчанию (172.16.0.254) обязательно нужно добавить маршруты к серверу и DNS серверу в таблицу маршрутизации. Что можно сделать следующим образом:

    route add -host 74.125.87.104 gw 172.16.0.254
    route add -host 8.8.8.8 gw 172.16.0.254

    После чего удаляем текущий шлюз по умолчанию (172.16.0.254) и указываем в качестве шлюза IP адрес, который мы назначили на интерфейсе tun0 сервера (10.0.0.1)

    route del default
    route add default gw 10.0.0.1

    Выполнив вышеуказанные действия таблица маршрутизации клиента (Work) принимает следующий вид:
        74.125.87.104  172.16.0.254 255.255.255.255  UGH 0     0 0 eth0
        8.8.8.8        172.16.0.254 255.255.255.255  UGH 0     0 0 eth0
        10.0.0.0       0.0.0.0      255.255.255.252  U   0     0 0 tun0
        172.16.0.0     0.0.0.0      255.255.255.0    U   1     0 0 eth0
        169.254.0.0    0.0.0.0      255.255.0.0      U   1000  0 0 eth0
        0.0.0.0        10.0.0.1     0.0.0.0          UG  0     0 0 tun0
    

    Теперь весь трафик, который направляется в неизвестные подсети, а неизвестные все, кроме адресов 8.8.8.8 и 74.125.87.104, направляется через 10.0.0.1, то есть через ШИФРОВАННЫЙ SSH туннель. Но сервер ничего с ним, трафиком, не делает. Потому что необходимо настроить NAT для клиента. Для этого добавляем правило в iptables

    iptables -t nat -A POSTROUTING -s 10.0.0.2 -j MASQUERADE

    Включаем в ядре ip forward-инг

    sysctl -w net.ipv4.ip_forward=1

    Не забываем сделать так, что бы он включался при загрузке системы…

    mcedit /etc/sysctl.conf

    P.S> mcedit — текстовый редактор. Можно использовать любой другой.

    Находим закомментированную строку net.ipv4.ip_forward=1 и раскомментируем её.

    Всё, mission complete, теперь весь трафик направляется через ssh туннель и NATится в Internet. Туннель шифрованный, трафик до сервера защищён!
    Поделиться публикацией

    Комментарии 40

      0
        +3
        Спасибо за ссылку, очень занимательная информация.

        Будьте любезны сравнить посты по ссылке с моим топиком, и Вы мгновенно увидите разницу.
          0
          Действительно. Признаю, погорячился.
        +1
        А почему именно SSH-туннель? Я вижу только одно преимущество — не надо ничего устанавливать лишнего, как в случае с ipsec или openvpn.
        Но и теряем кроссплатформенность.
        Сам использую OpenVPN
          +2
          Но и теряем кроссплатформенность.

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

          В любом случае, думаю данная информация будет кому-нибудь полезна.
          0
          А как быть с не штатным ребутом? постоянно руками править таблицу маршрутизации? :))
          А так, да хороший пример.
            0
            Ну, пример описывает локальное, а не продакшн, использование.

            Думаю, в любом случае можно написать скрипт.
              0
              pastebin.com/rq7A9291

              Я лично использую такой скрипт, проверка кроном каждые 5 минут.
                0
                можно сделать проще: просто добавив команду создания туннеля в /etc/inittab c respawn
                0
                Пардон, не правильно суть вопроса понял.

                Мой пример написан относительно этого скрипта, который и таблицу прописывает.
                +2
                Собралась карма — перенес в «Системное администрирование».
                  +1
                  В свое время тоже изобретал что-то похожее, даже в песочницу отправил… Да НЛО не признало :)

                  Может кому будет полезно, готовый скрипт: pastebin.com/aY8tgajy
                    0
                    А что быть с Windows? Там это как нибидуь организовать можно, с плане клиента?
                      +1
                      Под windows в cygwin ssh (нейкий portable version of OpenSSH) работает судя по www.openssh.com/windows.html. То есть в теории должно работать.
                        0
                        А на винде я получу еще одно соединение? или как там это все будет работать?
                          0
                          Ну в моём понимании — туннель всегда является сетевым интерфейсом.
                          Попробуйте, если под windows заработает то будет отлично.
                        +1
                        Лично я использую для ssh-туннеля к удаленному серверу putty и перенаправляю трафик приложений в локальный сокс-прокси.
                        +1
                        То есть можно делать шифрованные туннели практически стандартным линуксовым софтом. Замечательно. Надо было бы только написать скрипты для автоматизации этого всего дела. Пускаешь на клиенте скрипт всё что надо делает и коннектится к серверу. Сервер замечает коннект и тоже что надо делает.
                          0
                          Вы, наверное, не обратили внимание на то, что на сервере ничего настраивать не надо.
                          P.S> За исключением того случая — когда используется аутентификация по ключам.

                          Я хотел показать КАК сделать туннель, а скрипты — наверное это тема для другого поста.
                          0
                          Под Windows через putty можно
                            0
                            Не думаю…
                              0
                              ну в данном случае все упирается в создание tun под windows
                              навскидку
                              у openvpn есть скомпилленный драйвер под окна.

                              осталось только попробовать :)

                              +можно SOCKS proxy сделать без всего этого например
                                0
                                создание tun под windows

                                Не знал, что такое возможно, но как потом этот tun завязать на ssh???
                                  +1
                                  хабр съел ссылки :(

                                  первая — www.varsanofiev.com/inside/using_tuntap_under_windows.htm
                                  вторая — sanmai.livejournal.com/361790.html
                                    0
                                    SOCKS Proxy — это нам давно знакомо, не используем с тех пор как на Linux-е. P.S>Всё равно спасибо.
                                    А вот tun/tap Windows, это мы почитаем, в жизни пригодится. thanks
                              0
                              Самое большое зло во всем этом — логин под рутом. Я как-то пытался сделать это через обычного пользователя — не получилось.
                              А оставлять PermitRootLogin из-за неспособности/нежелания настроить vtun — ИМХО, не круто.
                                0
                                Аутентификацию по ключам ещё никто не отменял. И PermitRootLogin NO можете оставить неизменным.
                                  0
                                  Я уж думал, что что-то упустил. Нет, PermitRootLogin=no запрещает вход под рутом при любом способе аутентификации. Хоть pubkey, хоть password-based, хоть hostbased.
                                  Как вариант, forced-commands-only, но если бы Вы представили способ проброса туннелей под обычным пользователем (еще желательно и без sudo), информация была бы ценной.
                                    0
                                    Да Вы правы, ошибся…
                                    Помню себе, что у меня всё работает, и совершенно забыл, что в Ubuntu, а у меня ubuntu, root — по умолчанию отключён. При настроенной авторизации по ключам, root остаётся отключённым, но я всё равно захожу под рутом.
                                      0
                                      Вероятно потому, что по умолчанию включен
                                      PermitRootLogin without-password
                                      Если не указано другое, то будет работать ;)
                                        0
                                        Конфиг OpenSSH по умолчанию в Ubuntu содержит PermitRootLogin Yes — поэтому и работает, поэтому и ошибся…
                                          0
                                          Если без # в начале, то как-бы и не правильно…
                                          Я бы порекомендовал without-password…
                                          Если там еще и root без пароля сразу после установки, то я сильно огорчусь :)
                                            0
                                            В Ubuntu по умолчанию пароля root нет, в /etc/shadow имеем следующее root:!:, что запрещает вход под рутом, но при настроенной «ключной» аутентификации — работает.
                                              0
                                              Не будем сейчас вникать в дебри реализации Ubuntu.
                                              Я давно туда не заглядывал, а привычки и пристрастия свои навязывать не буду…

                                              Ценности статьи это ни как не изменит.
                                    0
                                    PermitRootLogin without-password
                                    позволяет авторизацию по ключам root…
                                    При этом, по паролю — нет…
                                    При этом, вызов sudo ssh root@ доработать на предмет использования ключа…

                                    Маршрутизацию же, если настраивать средствами /etc/net/tun0, то можно прописать все, что нужно…

                                    И вместо
                                    # route del default
                                    # route add default gw 10.0.0.1

                                    пора использовать
                                    # ip route *
                                    Кошернее…

                                    Спасибо за статью.
                                    0
                                    Я для этого использую авторизацию пользователя, который на сервере через судо выполняет нужные команды. Таким образом, можно оставить PermitRootLogin NO.
                                    0
                                    А на Маке это будет нормально работать? Честно говоря, на таком уровне я заклинаниями OpenSSH не владею…
                                      0
                                      Мне, если честно, вообще неясен смысл использования SSH Tunnel. При встроенном в тот же SSH Socks-proxy, работать с которым можно учить любые приложения (те, которые нужно, а не все подряд) полная L3-маршрутизация через SSH может понадобиться ну совсем уж в редких случаях.
                                        0

                                        Автор жив?
                                        Хочу реализовать описанное на роутера с openwrt или ddwrt, сейчас работает openvpn, но очень садит скорость.
                                        Если автор ещё тут, прошу помощи в личке.

                                          0
                                          Я не автор, но всё-же. В openwrt ssh клиент не умеет интерфейсы создавать, по крайней мере тот, который у меня в тестовом роутере из коробки. Порты только если пробрасывть. Но думаю можно что-нибудь собрать руками. Как раз сам загорелся этой идеей.

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

                                        Самое читаемое