Senior Linux Administrator
1,2
рейтинг
18 марта 2014 в 14:51

Администрирование → Поднимаем VPN-туннель из мира домой в обход NAT tutorial

.

Хочу рассказать вам про то как имея в интернете свой VPS-сервер можно поднять туннель в домашнюю сеть. И не платить при этом за статический IP провайдеру, и даже находясь за NAT, все равно сделать доступными в интернете свои домашние сервисы.

Исходные данные


  • VPS сервер на debian со статическим реальным IP
  • роутер с прошивкой OpenWRT, который находится за провайдерским NAT
  • домашняя сеть с компьютерами и виртуальными машинами в 192.168.1.0/24


Настройка туннеля


Первым делом установим и настроим OpenVPN сервер на нашем VPS:
apt-get update
apt-get install openvpn

Отредактируем файл конфигурации:
vi /etc/openvpn/tun0.conf
dev tun0
ifconfig 10.9.8.1 10.9.8.2
secret /etc/openvpn/static.key
route 192.168.1.0 255.255.255.0

Здесь 10.9.8.x будет наша VPN-сеть, в которой адрес 10.9.8.1 мы назначем VPN-серверу, а адрес 10.9.8.2 VPN-клиенту.
Последняя строчка являет ссобой статисческий маршрут, который нужен для того, что бы наш VPS знал что путь в нашу домашнюю сеть лежит через роутер

Еще нам нужно сгенерировать ключ с которым будет подключаться к серверу наш роутер:
openvpn --genkey --secret static.key

И можно запускать демона:
service openvpn start


Теперь установим OpenVPN на наш роутер с которого мы будем инициализировать VPN-соединение:
opkg update
opkg install openvpn

Скопируем ключ на наш рутер, исполюзуя scp:
scp root@your-server.org:/etc/openvpn/static.key /etc/openvpn/static.key 

Отредактируем конфигурацию интерфейса:
vi /etc/openvpn/tun0.conf
remote your-server.org
dev tun0
ifconfig 10.9.8.2 10.9.8.1
secret /etc/openvpn/static.key
keepalive 60 120

как сказал alexdob:
keepalive 60 180
Означает следующее: каждые 60 секунд посылать ping на удаленный хост, и, если за 180 секунд не было получено ни одного пакета — то перезапускать туннель.

И проверим, все ли у нас заработает:
openvpn --config /etc/openvpn/tun0.conf 

Если все ок, то запустим и добавим OpenVPN демона в автозапуск:
/etc/init.d/openvpn start
/etc/init.d/openvpn enable


Маршрутизация


Теперь настроим маршрутизацию.

Что бы наш роутер пропускал наш сервер в домашнюю сеть, а машины из домашней сети пропускал к серверу, нужно добавить следующие правила на роутер.

Создадим файлик и запишем в него эти правила:
vi /etc/iptables.up.rules
#!/bin/sh

#Allow forwarding via tunnel
iptables -I INPUT -i tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -j ACCEPT
iptables -I OUTPUT -o tun0 -j ACCEPT
iptables -I FORWARD -o tun0 -j ACCEPT

Cделаем его исполняемым:
chmod +x /etc/iptables.up.rules

И добавим его в /etc/rc.local для автозапуска:
/etc/iptables.up.rules

Добавлять нужно перед exit 0

В принципе все готово.
Наши сети соединены, все машины прекрасно друг-друга видят и обмениваются пакетами.
Теперь, при желании, можно настроить проброс портов с внешнего на внутренний адрес.

Вот так, к примеру, выглядит проброс ssh порта на одну из машин у меня в домашней сети:
# Forward SSH port to server
iptables -t nat -A PREROUTING -d XX.XX.XX.XXX -p tcp --dport 666 -j DNAT --to-dest 192.168.1.200:22
iptables -t nat -A POSTROUTING -d 192.168.1.200 -p tcp --dport 22 -j SNAT --to-source 10.9.8.1

Где XX.XX.XX.XXX — внешний IP сервера, 192.168.1.200 — IP моей машины внутри домашней сети, 666 — порт при обращении к которому я попадаю на эту машину

PS: Если у вас что-то не получается убедитесь что на вашем VPS есть и подключены все необходимые для этого модули ядра

Источники


При написании статьи, я использовал информацию из следующих источников:
kvaps @kvaps
карма
46,0
рейтинг 1,2
Senior Linux Administrator
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Администрирование

Комментарии (27)

  • +1
    это все довольно стандартно, я вот недавно уперся в следующую задачу и за 5 минут она не решилась: допустим есть примерно так оргинизованный проброс, на vps указывают dns записи ряда ресурсов. как часть из них отправить на домашний сервер (т.е. по сути, чтобы часть сайтов жила на vps, а часть на домашнем сервере, тогда как обращение ко всем было исключительно по именам (без портов и пр.))
    • 0
      т.е. грубо говоря что бы сайт vasya.pepkin.com открывался с VPS, а petya.pupkin.com — с домашней сети и при этом DNS записи для «мира» указывали на внешний адрес VPS?
      как вариант — используйте http-proxy. Модуль есть как у apache, так и у nginx, lighttpd и т.д
      • 0
        да, теоретически все так, но практически не задалось — надо будет еще попилить. если есть ссылки на success story — было бы полезно
        • +1
          ничего сложного нет.
          Рабочий пример для nginx
          server {
                  listen 80;
                  listen [::]:80;
                  server_name vasya.pupkin.com;
                  root /www/pupkin.com/vasya/public;
          
                  charset utf-8;
                  client_max_body_size 1m;
          
                  location / {
                          index index.php;
                          try_files $uri $uri/ /index.php?$args;
                  }
                  ...
                  ...
          }
          
          server {
                  listen 80;
                  listen [::]:80;
                  server_name petya.pupkin.com;
          
                  charset utf-8;
                  client_header_timeout  10m;
                  client_body_timeout    10m;
                  client_max_body_size   10m;
                  send_timeout           10m;
          
                  location / {
                          proxy_set_header X-Forwarded-Host $host;
                          proxy_set_header X-Forwarded-Server $host;
                          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                          proxy_pass http://192.168.16.44:7990;
                          port_in_redirect off;
                          proxy_redirect http://192.168.16.44:7990/ http://petya.pupkin.com/;
                  }
          }
          


          там, где указан ip: порт при использовании порта 80 можно порт опустить, указав лишь ip. В прокси указывается именно IP, а не FQDN
          DNS записи для обоих хостов vasya.pupkin.com и petya.pupkin.com должны указывать на внешний IP вашего VPS
          • 0
            спасибо. попробую допилить апач, если нет, то перекину на nginx
            • +2
              для апача будет как-то так:
              apache config proxy
              <VirtualHost *:80>
                  DocumentRoot "/www/pupkin.com/vasya/public"
                  ServerName vasya.pupkin.com
              
                  # Other directives here
              </VirtualHost>
              
              <VirtualHost *:80>
                  #DocumentRoot apache требует хоть какой-то обязательно
                  DocumentRoot "/www/pupkin.com/petya/public"
                  ServerName petya.pupkin.com
              
                  ProxyRequests On
                  ProxyPreserveHost On
                  ProxyVia full
              
              
                  <proxy *>
                  Order deny,allow
                  Allow from all
                  </proxy>
              
                  ProxyPass        /  http://192.168.16.44/
                  ProxyPassReverse /  http://192.168.16.44/
              </VirtualHost>
              


              после чего

              sudo a2enmod proxy_connect
              sudo a2enmod proxy_html
              sudo a2ensite /etc/apache2/sites-available/petya.pupkin.com.conf
              sudo /etc/init.d/apache2 reload
              

              справедливо для Debian-based систем

              проверить не могу, написал на скорую руку читая документацию по apache
              • 0
                спасибо, попробую как дома буду
    • 0
      Мне тоже был интересен данный вопрос.
      Ничего лучше кроме реверс-прокси я пока не придумал.
      Еще была идея с форвардингом запросов на определенный домен (или субдомен) с использованием модуля string в netfilter,
      но пока это все так никуда и не вылилось.
  • 0
    а чем стандартный pptp\l2tp не устроил?
    кстати, маршруты openvpn умеет поднимать сам. ну и конечно же о «tun+» — данные правила разрешат вам хождение трафика с любого TUN интерфейса. У вас же в конфиге четко указано использовать tun0 интерфейс.
    В общем статья об очередное HOW-TO openvpn…
    habrahabr.ru/post/78101/
    habrahabr.ru/post/188474/
    habrahabr.ru/post/56652/
    и т.д.
    ну а DNAT с внешнего сервера внутрь — это совсем грустно, я бы лучше выбрал static-IP от провайдера, а не экономить копейки увеличивая latency
    • +1
      а чем стандартный pptp\l2tp не устроил?
      OpenVPN вроде бы и безопаснее и привычнее
      «tun+»
      Да, спасибо, поправил, изначально использовал только 1 tun, потому и не заострил на этом внимания
      ну а DNAT с внешнего сервера внутрь — это совсем грустно, я бы лучше выбрал static-IP от провайдера, а не экономить копейки увеличивая latency
      Первоначально делал это все для того, что бы сервера внутри моей домашней сети смогли обмениваться с VPS'кой пакетами так, как будто, они были бы в одной сети. DNAT с внешнего сервера внутрь — скорее приятное дополнение, чем моя основная задача
      • 0
        что бы сервера внутри моей домашней сети смогли обмениваться с VPS'кой пакетами так, как будто, они были бы в одной сети

        тогда, как по-мне, лучше использовать tap, чем tun, т.к. первый работает на канальном уровне, соотв. можно было выдать IP из домашней сети и не думать о маршрутизации
        • 0
          И можно использовать vtun вместо OpenVPN…
  • 0
    Но Вы ведь фактически просто удлинили цепочку подключения и заменили:
    И не платить при этом за статический IP провайдеру

    На оплату выделенного:
    VPS сервер на debian со статическим реальным IP

    Если VPS стоит дешевле, чем выделенный IP у провайдера, то такая схема имеет смысл. В противном случае проще и дешевле купить IP у провайдера и настроить на роутере маршрутизацию (или поднять OpenVPN-сервер на самом роутере, если производительность позволяет)
    • 0
      Все верно, ответил выше :)
    • 0
      Вообще, если сделать TAP и NAT у провайдера не симметричный, сервер будет использоваться только в момент подключения. Потом пакеты будут ходить напрямую :)
    • 0
      VPS сам по себе имеет позитивную ценность. У меня статический IP за 150 рублей в месяц, но подумываю о переходе на такую же схему, чтобы платить рублей 300 в месяц за VPS только.
      • 0
        К сожалению сильно потеряете в скорости/времени отклика, причем порядком: немного времени назад проводил эксперименты — соединял две сети, через интернет разными технологиями, железки routerboard 951
        EoIP — 100Мбит (без шифрования)
        OpenVPN -2.5 Мбит (aes128/blowfish128)
        EoIP+IPsec — 2 мбит (aes128)
        l2tp — 5 Мбит (MPPE128)
        pptp — 0.5-1 Мбит (MPPE128)

        Как и ожидалось — шифрование, без соответствующего аппаратного модуля потребляет очень много ресурсов
        • 0
          А в сильном шифовании не сильно заинтересован.

          Потом, дома стоит сервер с Windows Server 2012, можно на нём поднять VPN софтово. Должно быть ОК.
  • +2
    кстати, насчет пинга… в конфиге сервера не заметил директивы keepalive
    keepalive — является совмещением сразу двух команд — ping и ping-restart. Использует сразу два параметра в секундах, перечисленных через пробел. Пример:
    keepalive 10 180
    Означает следующее: каждые 10 секунд посылать ping на удаленный хост, и, если за 180 секунд не было получено ни одного пакета — то перезапускать туннель.

    возможно в этом причина затыка и не нужен будет костыль с бесконечным циклом?
    • +3
      Да. Причем, как правило, на UDP таймауты меньше делают. На TCP смело можете делать таймаут в 1 минуту, практически гарантировано ниже 1 минуты не опустится ни одной провайдерский NAT.

      Это, конечно, похвально, что kvaps разбирается с ранее незнакомыми вещами, но статья плохая. Тут и костыли⁴ (ping.sh, добавление в /etc/rc.local, статические ключи, route add), и неудачная конфигурация. Было бы лучше, если бы kvaps потратил немного больше времени, почитал бы man openvpn, и затем написал бы хорошую статью про OpenVPN.
      • +1
        ValdikSS и alexdob,
        Большое вам спасибо за конструктивную критику, я уверен, что напишу еще много хороших статей. Но и этой не стоит пропадать, исправил ее, включая ваши замечания.

        Объясните мне, чем так плохи статические ключи?
        • 0
          Не то, чтобы они плохи, у них есть преимущества, и для конфигураций компьютер-компьютер они подходят, но:
          1. Нет Diffie Hellman обмена ключей, это значит, что если ваш ключ скомпрометирован, то все ваши данные, переданные ранее, могут быть расшифрованы.
          2. К OpenVPN-серверу может быть подключен только один клиент.

          Преимущество одно:
          Легко генерировать. Не нужно держать инфраструктуру ключей.
          • 0
            2. К OpenVPN-серверу может быть подключен только один клиент.

            Не совсем понял — почему? возможно вы имели ввиду один клиент = один набор ключей? тогда да, и то, есть опция в конфигурации, что бы отключить данное поведение.
            В HOWTO Openvpn приведены примеры конфигов для one server = multi-client
            Небольшой оффтоп
            Когда-то давно был опыт по настройке связки OpenVPN server + Radius + MySQL для multi-client конфигурации. В том числе удобный установщик Openvpn клиента для win пользователей (основной контингент) с самописным GUI на Qt… но это было достаточно давно и в настоящее время уже не актуально, т.к. аналогичных поделок пруд пруди… но если кому интересно — основной компонент системы radius_plugin для openvpn (на сколько я понял проект больше не развивается), ну а связка freeradius и MySQL — тривиальна.
            • 0
              Не совсем понял — почему? возможно вы имели ввиду один клиент = один набор ключей?

              Потому, что ключ вообще один. Общий для сервера и для клиента. Для работы OpenVPN в режиме один сервер-несколько клиентов нужен x509 (т.е. сертификаты), и по вашей ссылке как раз они и используются, а не статические ключи.
              • +1
                Прошу прощения, сутра не понял, что речь идет именно о конфигурации, приведенной в статье… Тогда конечно правильно.
  • 0
    промазал… комментарий чуть выше
  • 0
    Использую VPS DigitalOcean. Недорого относительно. Поднят OpenVPN для выхода в мир и NeoRouter для соединения своих компов и Андрюши.

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