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
Ну а теперь можно и подключиться:
Отладочные сообщения смотрите в /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 я несколько раз попался на останов системы и быстренько отказался от этой затеи).
Сразу после установки пакете сделайте:
поскольку процедура установки прописывает автозапуск 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:
И на машине A инициируйте соединение:
Если нигде нет орфографической ошибки, вы должны увидеть что нибудь подобное:
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 в качестве сервера и клиента.
Я приведу только небольшой готовый рецепт поднятия туннеля.
- modprobe tun
В ядрах 2.6 это уже штатный драйвер. Для работы vtund он необходим.
- Устанавливаем на сервере и на клиенте пакет: "apt-get install vtund"
- Конфиг на сервере для подключения 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";
};
}
- Запускаем vtund на сервере:
vtund -s
- По умолчанию vtund ждёт соединений на 5000-м порту. Если на сервере запущена firewall, коннект к данному порту следует разрешить (пример для IPTABLES:)
iptables -I INPUT -p tcp --dport 5000 -j ACCEPT
- Конфиг на моём домашнем компьютере (клиент) (/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";
};
} - Запуск vtund на моём компьютере как клиента:
vtund mycomp server_ip_address
- На втором клиентском компьютере настройки и запуск vtund аналогичны первому.
- Дополнительными командами после соединения устанавливаю на клиентских компьютерах маршрут по умолчанию (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. Это всё.