VPN-ы

10.10.07
Последнее изменение: 24.12.09
Аркадий Иванов

 

    Основной принцип всех VPN(Virtual Privacy Network) - это TCP/IP соединение поверх уже существующего физического соединения между компьютерами. Каким бы механизмом создания VPN вы не пользовались, обычно в результате успешной инициализации VPN у вас появляются новые сетевые интерфейсы, имеющие IP-адреса, отличающиеся от IP-адресов физически существующих сетевых устройств в вашем компьютере.
Создаваемые при инициализации VPN сетевые устройства физически не существуют, отсюда и название Virtual.

    Данный документ - это просто сборник рецептов по созданию VPN в Linux-е. Я совершенно не претендую на академическое преподавание основ VPN. Надеюсь, что если вы читаете эту страницу, вы немного представляете зачем вы сюда попали. :-)

    Основная задача, для которых я применял VPNы - это соединить свои сети через небезопасный Интернет, дать пользователям разных сетей привычный доступ к ресурсам - файлам, каталогам, принтерам, программам и при этом избежать мучительной настройки всяческих защит от хакеров из Интернета. VPN - это как раз то, что надо в таких случаях. После установки VPN вы сразу имеете возможность подключать в получившейся общей сети каталоги компьютеров через NFS,  Samba, сделать общую сеть принтеров через CUPS, общие сканеры через SANE и т.п.

    Реализации VPN есть самые разные. VPNы разные нужны, VPNы разные важны. Некоторые просто нельзя использовать в ситуациях, когда ваш провайдер Интернета даёт вам внутренний IP и больше ничего.
Варианты настроек я почерпнул из самых разных источников. Спасибо всем авторам, которые описали действительно работающие VPNы. :-) И конечно, большое спасибо разработчикам, которые дали нам в руки эти технологии.

Ключевой идеей VPN-а является то, что пакеты между вашими сетями упаковываются внутрь пакетов, которыми уже соединены маршрутизаторы через Интернет.

Итак, здесь приводятся конфигурации для простых туннелей, для PPP-туннелей, для IPSEC, для VTUND.  Позволю высказать своё мнение, что лучше, надёжнее и понятнее VTUND в этой компании ничего нет.

 

Простейший VPN без криптования.

 

Дано 2 сети. Каждая имеет по шлюзу в Интернет и по несколько компьютеров внутри. Надо соединить компьютеры внутренних сетей.
На шлюзах установлен Linux.

Сеть A B
Внешний (в Internet-е) адрес шлюза: 195.1.1.1 195.2.2.2
Внутренний адрес шлюза: 192.168.1.1 192.168.2.2
Внутренняя сеть: 192.168.1.0, маска 255.255.255.0 192.168.2.0, маска 255.255.255.0
Режим инкапсуляции: GRE GRE
Скрипт на шлюзе для создания vpn

#!/bin/bash
modprobe ip_gre
ip tunnel del tun0
ip tunnel add tun0 mode gre local 195.1.1.1 \
    remote 195.2.2.2 ttl 255
ip addr add 192.168.3.1 tun0 netmask 255.255.255.0
ip link set tun0 up
ip route add 192.168.2.0/24 dev tun0

#!/bin/bash
modprobe ip_gre
ip tunnel del tun0
ip tunnel add tun0 mode gre local 195.2.2.2  \
      remote 195.1.1.1 ttl 255
ip addr add 192.168.3.2 tun0 netmask 255.255.255.0
ip link set tun0 up
ip route add 192.168.1.0/24 dev tun0

Конечно, ядро должно поддерживать GRE (Generic Routing Encapsulation).

В результате выполнения скриптов компьютеры сети A получат доступ к сети 192.168.2, а компьютеры сети B к сети 192.168.1.
Если у вас настроен firewall на шлюзе, стоит внести в него разрешения на общение между хостами этих сетей.
Маршрутизация между внутренними сетями настроена статически (ip route add).
Ничто не мешает промасштабировать это решение на несколько сетей.

Механизм инкапсуляции может быть GRE.
Модуль ядра должен быть загружен (ip_gre).
В команде создания туннеля вы указываете "... mode gre ...".

 

Механизм инкапсуляции может быть IP поверх IP.
Модуль ядра должен быть загружен (ipip).
В команде создания туннеля вы указываете "... mode ipip ...".

 

  VPN посредством PPTP (Point-to-Point Tunneling Protocol).

Этот вид VPN хорош тем, что его виртуальное соединение обычно можно установить и у провайдера, который даёт вам только адрес из своей внутренней сети и маскирует ваш IP. Ну конечно, вам всё равно нужен сервер где-то в Инете, к которому вы присоединяетесь и который имеет нормальный IP-адрес и который и будет PPTP-сервером. Всяких опций PPTP содержит множество. Да и конфигурационными файлами не обделён. Ведь внутри работает PPP, у коего своих опций от души.
Маленькие замечания:
- провайдер должен пропускать пакеты GRE-протокола.
- на своём сервере откройте TCP-порт 1723.

Последний раз я тренировался в AltLinux Server 4.0.0.

Понадобятся пакеты: ppp ppp-common pptp-client pptpd

 

В предлагаемой конфигурации предполагается, что:
Сервер имеет внешний IP=195.1.1.1
IP виртуального соединения со стороны сервера: 192.168.222.1
IP виртуального соединения со стороны клиента: 192.168.222.2


Конфигурация на стороне сервера:

/etc/pptpd.conf:

# Откуда PPP будет брать опции:
option /etc/ppp/options.pptpd

logwtmp
debug
#
#Чтобы использовать chap-secrets при назначении IP клиенту, нужна опция:
delegate

#Какой адрес будет у серверного конца:
localip 192.168.222.1

 

/etc/ppp/options.pptpd:

# Имя локального конца PPP.
# Именно его будет искать "pppd" во второй колонке в /etc/ppp/chap-secrets
# при подключении удалённой машины
name myserver
192.168.222.1:

require-chap
debug
lock
nobsdcomp
nodeflate
nomppe
mtu 576

mru 576

Параметры mtu, mru,nodeflate,nobsdcomp весьма ощутимо влияют на качество передачи
на спутниковых каналах. Поскольку у меня все каналы спутниковые, для меня это важно.
 

/etc/ppp/chap-secrets (файл с паролями подключающихся клиентов): 

# Клиент   сервер   пароль   IP-клиенту
clnt   myserver   secret   192.168.222.2

 

Естественно надо бы запустить PPTP-сервер:

 

chkconfig pptpd on
service pptpd start

 

 

 

Конфигурация на стороне клиента:

 

/etc/ppp/options.pptp (это будут опции для "ppp"):

# Получаем IP от сервера
ipcp-accept-remote
ipcp-accept-local 

nobsdcomp
nodeflate
mtu 576
mru 576

 

/etc/ppp/chap-secrets (файл с паролями для PPP-подключения к серверу): 

# Клиент   сервер   пароль   IP-клиенту
clnt   myserver   secret   192.168.222.2

Строка для подключения на сервере и на клиенте совпадают.
IP всё равно будет получен с сервера.

 

/etc/ppp/peers/mycall: (Конфиг для запуска PPTP+PPPD)

debug
pty "/usr/sbin/pptp 195.1.1.1 --nolaunchpppd"
name clnt
remotename myserver
file /etc/ppp/options.pptp

 

Здесь предполагаем, что сервер имеет внешний IP=195.1.1.1

Ну а теперь можно и подключиться:

pppd call mycall

 

Отладочные сообщения смотрите в /var/log/messages и /var/log/pppd.

 

 

 

VPN с криптованием - IPSEC.


Дано 2 сети. Каждая имеет по шлюзу в Интернет и по несколько компьютеров внутри. Надо дать свободный доступ между копьютерами 2-х сетей.
На шлюзах установлен Linux.

Сеть A B
Внешний (в Internet-е) адрес шлюза: 195.1.1.1 195.2.2.2
  Имя шлюза в Интернете: a.mynet.org b.mynet.org
Внутренний адрес шлюза: 192.168.1.1 192.168.2.2
Внутренняя сеть: 192.168.1.0, маска 255.255.255.0 192.168.2.0, маска 255.255.255.0

В дистрибутивах Linux-а не всегда есть готовые пакеты для создания IPSEC-соединения. Поэтому здесь надо брать дистрибутив пакета, обеспечивающего IPSEC и компилировать. Я предпочитаю проект OpenSwan - www.openswan.org. С этого сайта скачиваете openswan-2.4.9.tar.gz, раскрываете архив,  и делаете следующее:

apt-get gmp-devel #этот пакет нужен для компиляции.
make programs
make install

В установке вы можете также собрать ядерный модуль ipsec. Для работы OpenSwan с ядрами 2.6 он не требуется. На момент написания этого описания у меня стоит ядро 2.6.19. То, что можно обойтись без сборки модуля, экономит время. Но если вам нравится иметь в системе устройства "ipsec", то вперёд... :-)  (Сразу предупреждаю, при отладке ipsec я несколько раз попался на останов системы и быстренько  отказался от этой затеи).

Сразу после установки пакете сделайте:

chkconfig ipsec off

поскольку процедура установки прописывает автозапуск ipsec сервиса.

 

Файлов конфигурации 2: /etc/ipsec.conf и /etc/ipsec.secrets
В /etc/ipsec.conf есть обычно директива "include", которая включает в этот файл строки из других файлов. Обычно конфигурацию отдельного VPN удобно вынести в отдельный файл. Итак для нашего случая содержимое  ipsec.conf на машине A:

version 2.0
config setup
        nat_traversal=yes
        nhelpers=0

include /etc/ipsec.d/examples/a.conf
include /etc/ipsec.d/examples/no_oe.conf

Само описаниее соединения находится в /etc/ipsec.d/examples/a.conf. Его содержимое:

conn my
        type=tunnel
        pfs=no
        esp=3des-md5
        keyexchange=ike
        authby=secret
        keylife=1d
        compress=no
        #
        left=195.1.1.1
        leftsubnet=192.168.1.0/24
        leftid=@a.mynet.org
        leftnexthop=%defaultroute
       #
        right=195.2.2.2
        rightid=@b.mynet.org
        rightnexthop=%defaultroute
        rightsubnet=192.168.2.0/24
        auto=add

 

Содержое /etc/ipsec.secrets:

195.1.1.1 195.2.2.2: PSK "secretik"
@a.mynet.com  @b.mynet.org: PSK "secretik"

 

В этих настройках указано, что аутентификация будет по секретной фразе,  алгоритм криптования - 3DES, для хэша используется MD5.
Секретная фраза указывается в /etc/ipsec.secrets.

Скопируйте файлы на машину B и переверните описание для left и right.

Если у вас стоит firewall (как же сегодня без него!) и маскируются внутренние сети, то в правилах маскирования для машины A надо прописать:

iptable -t nat -A POSTROUTING -o eth_dsl -d ! 192.168.2.0/24  -j SNAT --to-source 195.1.1.1

,где предполагается, что ваш внешний сетевой интерфейс называется eth_dsl.
Таким образом траффик на сеть 192.168.2 не будет маскарадиться.
Аналогичную настройку надо провести на машине B.

Ну вот теперь финал:

На обеих машинах запустите ipsec:

service ipsec start

И на машине A инициируйте соединение:

ipsec auto -up my

Если нигде нет орфографической ошибки, вы должны увидеть что нибудь подобное:

104 "my" #1: STATE_MAIN_I1: initiate
003 "my" #1: received Vendor ID payload [Openswan (this version) 2.4.9  PLUTO_SENDS_VENDORID PLUTO_USES_KE.....
003 "my" #1: received Vendor ID payload [Dead Peer Detection]
003 "my" #1: received Vendor ID payload [RFC 3947] method set to=110
106 "my" #1: STATE_MAIN_I2: sent MI2, expecting MR2
003 "my" #1: NAT-Traversal: Result using RFC 3947 (NAT-Traversal): no NAT detected
108 "my" #1: STATE_MAIN_I3: sent MI3, expecting MR3
004 "my" #1: STATE_MAIN_I4: ISAKMP SA established {auth=OAKLEY_PRESHARED_KEY cipher=oakley_3des_cbc_192 pr......
117 "my" #2: STATE_QUICK_I1: initiate
004 "my" #2: STATE_QUICK_I2: sent QI2, IPsec SA established {ESP=>0xeca3d298 <0x66ca60ed xfrm=3DES_0-HMAC_......


Последний раз развлекался в AltLinux Server 4.0. Ядро 2.6.19, OpenSwan 2.4.9.

 

 

 

VTUND

 

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

 

Мне пришлось его применять вместо PPTP по причине того, что DSL-модем, через который к рабочему серверу коннектились несколько домашних компов, мог пропустить только одно PPTP-соединение. Пришлось искать замену PPTP.

 

В документации есть прекрасный пример конфигурирования vtund в качестве сервера и клиента.

Я приведу только небольшой готовый рецепт поднятия туннеля.

 

  1. modprobe tun
    В ядрах 2.6 это уже штатный драйвер. Для работы vtund он необходим.
     
  2. Устанавливаем на сервере и на клиенте пакет: "apt-get install vtund"
     
  3. Конфиг на сервере для подключения 2-х компов (/etc/vtund.conf):
    default {
            type tun;
            proto tcp;
            comp lzo:1;
            keepalive yes;
    }

    # Туннель между сервером и моим домашним компьютером
    # IP со стороны сервера: 192.168.100.1
    # IP со стороны моего компа:192.168.200.1
    # Подключение к серверу:
    mycomp {
        pass mypassword;
        up {
           ifconfig "%% 192.168.100.1 pointopoint 192.168.200.1";
           program /sbin/arp "-sD 192.168.200.1 eth0 pub";
        };
    }

    # IP компа жены:192.168.200.2
    # Ещё одно подключение к серверу
    wifecomp {
        pass wifepassword;
        up {
           ifconfig "%% 192.168.100.1 pointopoint 192.168.200.2";
           program /sbin/arp "-sD 192.168.200.2 eth0 pub";
        };
    }
     
  4. Запускаем vtund на сервере:
    vtund -s
     
  5. По умолчанию vtund ждёт соединений на 5000-м порту. Если на сервере запущена firewall, коннект к данному порту следует разрешить (пример для IPTABLES:)
    iptables -I INPUT -p tcp --dport 5000 -j ACCEPT

     
  6. Конфиг на моём домашнем компьютере (клиент) (/etc/vtund.conf):
    default {
            type tun;
            proto tcp;
            comp lzo:1;
            keepalive yes;
    }

    mycomp {
        pass mypassword;
        up {
           ifconfig "%% 192.168.200.1 pointopoint 192.168.100.1";
           program /sbin/arp "-sD 192.168.100.1 eth0 pub";
           route "delete default";
           route "add default gw 192.168.100.1";
        };
    }
  7. Запуск vtund на моём компьютере как клиента:
    vtund mycomp server_ip_address
     
  8. На втором клиентском компьютере настройки и запуск vtund аналогичны первому.
  9. Дополнительными командами после соединения устанавливаю на клиентских компьютерах маршрут по умолчанию (default) через 192.168.100.1.

 

Примечание: Легко ограничить скорость виртуального канала. Для этого в описание соединения введите параметр:

      

mycomp {
    ...
    speed 512;
    ...

}

Это ограничит общую пропускную способность канала 512 килобитами секунду на передачу и 512 на скачивание. Можно указывать скорости отдельно.

 

 

 

 


  PPPOE - PPP over Ethernet.

Сегодня это очень популярная технология среди Internet-провайдеров.

Провайдер выдаёт вам имя и пароль для подключения. Обычно IP и адрес DNS вы получаете автоматически в момент подключения

Важным моментом является то, что вам не надо присваивать изначально хосту какой-либо IP-адрес (в отличие от PPTP, L2TP,...).

Опишу где настроить клиентское подключение в Linux и как его инициировать:

1. В AltLinux у меня установлены пакеты: rp-pppoe-client  rp-pppoe-base  ppp-pppoe

2. Правлю файл /etc/pppoe.conf:

  # Указываю Ethernet-устройство, к которому подключён модем:

  ETH=eth1

  # Указываю login, который сообщил мне провайдер

  USER=userlogin

  # Указываю постоянное соединение с провайдером, а не дозвонку по требованию.

  DEMAND=no

  # Указываю, что у меня уже настроен DNS в /etc/resolv.conf и мне не надо его менять при подключении.

   DNSTYPE=NOCHANGE

  # Для старых версий PPPD указываю, что не надо использовать DNS от провайдера

   PEERDNS=no

  # Не менять настроенный в моей системе шлюз. У меня несколько подключений к провайдерам и мне это не надо.

   DEFAULTROUTE=no

  # Укажу дополнительную опцию PPPD - номер PPP интерфейса.

  # Люблю, чтобы интерфейс с провайдером у меня был строго определённый

  # Так проще firewall настраивать.

  PPPD_EXTRA="unit 200"

 

3. Провайдер мне выдал login ("userlogin") и пароль ("mysecret"). Добавляю запись о login/password в /etc/ppp/chap-secret:

   userlogin      *    mysecret

 

4. Стартую pppoe:

    pppoe-start

 

5. Это всё.