Зачем нужен VPN-туннель? Ясное дело — связать две приватные подсети друг с другом через интернет. А если подсетей, допустим не две, а пять? Что делать в этом случае? Как можно, как лучше? Мои размышления на эту тему с конкретным примером реализации. Пример основан на программных средствах, с минимумом вложений.
Предисловие
Статья была написана почти 3 года назад. Спец по сетям из меня тогда был аховый, больше "сервачник" и "виндусятник". Сейчас, в 2019 сказал бы, давайте мне цисок, DMVPN вам замучу. Но тогда я просто этого не умел. Никах средств и никакого оборудования мне никто выделять не собирался. Да и никто не воспринял мою затею всерьёз. Всё что мне было позволено — создать несколько виртуальных машин на имеющихся серверах, да ещё в моём распоряжении была неиспользуемая мини рабочая станция HP. Но я попробовал, результат получился на удивление изящный и дешёвый, сам удивляюсь:
- Абонентка 500 рублей в месяц за VPS-сервер;
- Потом уже, когда система заработала и была обкатана, купили 2 Raspberry Pi 3;
- Стабильная работа и keep alive
Чуть теории
На данный момент соединение сетей с помощью VPN туннелей является самым популярным способом в первую очередь потому, что требует минимум начальных вложений в создание инфраструктуры и никаких ежемесячных платежей за аренду (500 рублей в месяц для организации это просто ничто, поэтому не считаем), за трафик или ещё что-то — носителем выступает условно-бесплатная среда интернета. Минус в этом же — маршрут движения пакетов непостоянен во времени и как следствие непостоянна задержка между шлюзами туннеля. Чем дальше территориально разнесены сети, тем более возрастает нестабильность фактора задержки в течение рабочего дня.
Не буду скрывать, да это и очевидно — всё, что будет описано в данной записи, 100% материала — придумано всё это не мной, как сказал один мой знакомый — всё украдено до нас. Моя задача смотреть, анализировать, собирать информацию и доводить проект до конечной реализации сперва на бумаге, а потом в продакшене.
Выбор топологии
Итак, несколько подсетей. Для начала нужно проверить, что они не перекрываются. При всей очевидности проверить все-таки надо. Вот скажите сходу перекрываются ли сети?
192.168.0.0/20 192.168.17.0/24
А сети?
192.168.0.0/20 192.168.15.0/24
Далее, вариантов соединения сетей может быть несколько, но все они сводятся к двум основным — полносвязное соединение и звезда.
Полносвязное соединение
Все элементы равнозначны.
Плюсы:
- Простота настройки. Все туннели настраиваются на роутерах, которые смотрят в интернет и поддерживают функцию создания туннеля. На момент даже относительно дешевые роутеры это умеют;
- Нет единой точки отказа, если отваливается один туннель, то остальные продолжают работать;
- Оптимальное решение при небольшом количестве сетей - две, три - максимум, без последующего расширения.
Минусы:
- При большом количестве сетей избыточная, громоздкая структура;
- Добавление новой сети требует настройки еще стольких новых туннелей, сколько подсетей уже имеется (либо DMVPN);
- Если одна сеть (филиал организации) переезжает по новому адресу, то это требует полной перенастройки всех связанных с ней туннелей.
Звезда
Ядро системы настраивается как VPN сервер, остальные элементы как VPN клиенты.
Плюсы:
- VPN клиент может находиться за NAT. IP адрес он может получать по DHCP. Это делает такого клиента непривязанным к конкретной сети провайдера. Включаем его на новом месте, он подсоединяется к серверу и работает. Всё что нужно сделать, это кинуть на него маршрут;
- Простота добавления нового клиента — минимальная настройка на сервере, а сам клиент настраивается из типового шаблона;
- Если клиент реализован на виртуальной машине, то это бесплатно. Вычислительная мощность такого клиента настраивается за минуту в любую сторону;
- Неочевидный плюс безопасности: маршрут на клиент, выступающий в роли шлюза в туннель, можно прописать как для всей локальной сети, так и для отдельных узлов;
- Второй неочевидный плюс безопасности: анонимность — с клиентов остальные подсети видятся только по своим приватным адресам, а если вдобавок на vpn-сервере выключен лог, то даже получив доступ к нему невозможно собрать информацию кто и откуда подключался;
- Третий неочевидный плюс безопасности: если локальная подсеть клиента маленькая, либо же малое число клиентов в сети использует туннель, то в этом случае клиент можно реализовать на микрокомпьютере Raspberry Pi. При необходимости такой микрокомпьютер можно здорово запрятать, а при настройке соединения через Wi-Fi и вовсе его не найдешь;
- Четвертый неочевидный плюс безопасности: всю структуру можно выключить, выключив VPN сервер. Если при этом VPN сервер реализован как VPS в интернете, то сделать это можно, находясь где угодно, одним нажатием на смартфоне. Если хостер разумно-жадный, что в данном случае хорошо и не делает бесплатных бекапов, то и полностью удалить VPN сервер без всяких следов можно также легко.
Минусы:
- Единая точка отказа, если VPN сервер недоступен по каким-либо причинам, то вся сеть лежит;
- Для каждого клиента нужны либо виртуальная машина, либо машина физическая;
- Размещенный в интернете VPN сервер требует ежемесячной оплаты;
- VPN сервер должен обладать необходимой вычислительной мощностью чтобы покрывать обсчет трафика от клиентов. Теоретически при достаточно большом количестве клиентов и больших подсетях за клиентами этой мощности может не хватить. На практике такого никогда не случится.
Реализация
Сначала хотел сделать что-то, взяв готовые решения типа IpCop, но потом понял, что из этого ничего не получится. Заставить тестового Ubuntu-клиента приконнектиться к серверу не удалось. Несмотря на стандарт, реализация Openvpn видимо везде разная, например openvpn-сервер на роутере Mikrotik RB2011U почему-то использует TCP.. ( //voxlink.ru/kb/voip-devices-configuration/Conf_openVPN_windows_after_openVPN_Mikrotik/ ). Это видно из строки proto tcp-client. Роутер Mikrotik в режиме клиента непонятно что использует, но к готовой реализации проекта он также не подключился. Может что-то не разобрал, не спорю, тем не менее в конце-концов, ещё задолго до заказа VPS, пришел к выводу, что придется всё настраивать с нуля на одной ОС для всех машин туннеля.
По многим причинам выбрал вариант с выделенным VPS в интернете. Для начала нужно определиться где, в каком дата-центре разместить VPN сервер. Для этого нужно попросить в поддержке интересующего дата-центра тестовый IP, попинговать его и сделать трассировку из всех предполагаемых к соединению сетей, посмотреть число хопов. Полезная программа WinMTR:
Это занимает определенное время и вот наконец дата-центр выбран, VPS оплачен и готов к настройке.
Настройка VPN-сервера
Используем Ubuntu 16.04 LTS как дружелюбную, хорошо отлаженную систему. Установить систему на VPS можно из предварительно настроенных образов хостера, либо же отписать в поддержку и попросить загрузить для установки свой дистрибутив - А у вас нет такого же, но с перламутровыми пуговицами? Не стал заморачиваться и взял то, что дают. Установил, установка занимает пару минут: root включен, ssh доступ root включен, swap раздела нет. Последнее не очень хорошо, поэтому первое:
apt-get install swapspace vi /etc/swapspace.conf swappath="/var/lib/swapspace" - директория, где создаются swap-файлы lower_freelimit=20 - нижний лимит незанятого пространства ОЗУ upper_freelimit=60 - верхний лимит незанятого пространства ОЗУ freetarget=30 - уровень до которого будет освобождено, должен находиться между двумя предыдущими min_swapsize=512m - минимальный размер swap-файла max_swapsize=1g - максимальный размер swap-файла cooldown=600 - какая-то задержка (сек.) max=10 min
Меняем hostname, когда сидишь через ssh сразу на нескольких машинах, то можно легко запутаться и набумбасить лишнего там, где не надо, потом будет обидно, а если отвалится связь с машиной, то очень обидно, поэтому:
vi /etc/hosts вместо "hostname" - имя вашего компьютера vi /etc/hostname
Своих клиентов обозвал по порядку V1, V2, V3 и так далее.
Убираем автообновление, вредная штука:
apt-get update apt-get dist-upgrade dpkg-reconfigure unattended-upgrades
Меняем root пароль:
passwd root
Также полезно пользоваться командой history для просмотра истории команд.
Настройка Openvpn и сертификатов
apt-get install openvpn easy-rsa
Копируем дефолтный конфиг Openvpn для правки:
gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf
Правим:
vi /etc/openvpn/server.conf
Конфиг
################################################# # Sample OpenVPN 2.0 config file for # # multi-client server. # # # # This file is for the server side # # of a many-clients <-> one-server # # OpenVPN configuration. # # # # OpenVPN also supports # # single-machine <-> single-machine # # configurations (See the Examples page # # on the web site for more info). # # # # This config should work on Windows # # or Linux/BSD systems. Remember on # # Windows to quote pathnames and use # # double backslashes, e.g.: # # "C:\\Program Files\\OpenVPN\\config\\foo.key" # # # # Comments are preceded with '#' or ';' # ################################################# # Which local IP address should OpenVPN # listen on? (optional) ;local a.b.c.d # Which TCP/UDP port should OpenVPN listen on? # If you want to run multiple OpenVPN instances # on the same machine, use a different port # number for each one. You will need to # open up this port on your firewall. port 1194 # TCP or UDP server? ;proto tcp proto udp # "dev tun" will create a routed IP tunnel, # "dev tap" will create an ethernet tunnel. # Use "dev tap0" if you are ethernet bridging # and have precreated a tap0 virtual interface # and bridged it with your ethernet interface. # If you want to control access policies # over the VPN, you must create firewall # rules for the the TUN/TAP interface. # On non-Windows systems, you can give # an explicit unit number, such as tun0. # On Windows, use "dev-node" for this. # On most systems, the VPN will not function # unless you partially or fully disable # the firewall for the TUN/TAP interface. ;dev tap dev tun # Windows needs the TAP-Win32 adapter name # from the Network Connections panel if you # have more than one. On XP SP2 or higher, # you may need to selectively disable the # Windows firewall for the TAP adapter. # Non-Windows systems usually don't need this. ;dev-node MyTap # SSL/TLS root certificate (ca), certificate # (cert), and private key (key). Each client # and the server must have their own cert and # key file. The server and all clients will # use the same ca file. # # See the "easy-rsa" directory for a series # of scripts for generating RSA certificates # and private keys. Remember to use # a unique Common Name for the server # and each of the client certificates. # # Any X509 key management system can be used. # OpenVPN can also use a PKCS #12 formatted key file # (see "pkcs12" directive in man page). ca ca.crt cert server.crt key server.key # This file should be kept secret # Diffie hellman parameters. # Generate your own with: # openssl dhparam -out dh2048.pem 2048 dh dh2048.pem # Network topology # Should be subnet (addressing via IP) # unless Windows clients v2.0.9 and lower have to # be supported (then net30, i.e. a /30 per client) # Defaults to net30 (not recommended) ;topology subnet # Configure server mode and supply a VPN subnet # for OpenVPN to draw client addresses from. # The server will take 10.8.0.1 for itself, # the rest will be made available to clients. # Each client will be able to reach the server # on 10.8.0.1. Comment this line out if you are # ethernet bridging. See the man page for more info. server 10.8.0.0 255.255.255.0 # Maintain a record of client <-> virtual IP address # associations in this file. If OpenVPN goes down or # is restarted, reconnecting clients can be assigned # the same virtual IP address from the pool that was # previously assigned. ifconfig-pool-persist ipp.txt # Configure server mode for ethernet bridging. # You must first use your OS's bridging capability # to bridge the TAP interface with the ethernet # NIC interface. Then you must manually set the # IP/netmask on the bridge interface, here we # assume 10.8.0.4/255.255.255.0. Finally we # must set aside an IP range in this subnet # (start=10.8.0.50 end=10.8.0.100) to allocate # to connecting clients. Leave this line commented # out unless you are ethernet bridging. ;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100 # Configure server mode for ethernet bridging # using a DHCP-proxy, where clients talk # to the OpenVPN server-side DHCP server # to receive their IP address allocation # and DNS server addresses. You must first use # your OS's bridging capability to bridge the TAP # interface with the ethernet NIC interface. # Note: this mode only works on clients (such as # Windows), where the client-side TAP adapter is # bound to a DHCP client. ;server-bridge # Push routes to the client to allow it # to reach other private subnets behind # the server. Remember that these # private subnets will also need # to know to route the OpenVPN client # address pool (10.8.0.0/255.255.255.0) # back to the OpenVPN server. ;push "route 192.168.10.0 255.255.255.0" ;push "route 192.168.20.0 255.255.255.0" # To assign specific IP addresses to specific # clients or if a connecting client has a private # subnet behind it that should also have VPN access, # use the subdirectory "ccd" for client-specific # configuration files (see man page for more info). # EXAMPLE: Suppose the client # having the certificate common name "Thelonious" # also has a small subnet behind his connecting # machine, such as 192.168.40.128/255.255.255.248. # First, uncomment out these lines: ;client-config-dir ccd ;route 192.168.40.128 255.255.255.248 client-config-dir ccd ccd-exclusive route 192.168.190.0 255.255.255.0 route 192.168.192.0 255.255.255.0 route 192.168.0.0 255.255.240.0 # Then create a file ccd/Thelonious with this line: # iroute 192.168.40.128 255.255.255.248 # This will allow Thelonious' private subnet to # access the VPN. This example will only work # if you are routing, not bridging, i.e. you are # using "dev tun" and "server" directives. # EXAMPLE: Suppose you want to give # Thelonious a fixed VPN IP address of 10.9.0.1. # First uncomment out these lines: ;client-config-dir ccd ;route 10.9.0.0 255.255.255.252 # Then add this line to ccd/Thelonious: # ifconfig-push 10.9.0.1 10.9.0.2 # Suppose that you want to enable different # firewall access policies for different groups # of clients. There are two methods: # (1) Run multiple OpenVPN daemons, one for each # group, and firewall the TUN/TAP interface # for each group/daemon appropriately. # (2) (Advanced) Create a script to dynamically # modify the firewall in response to access # from different clients. See man # page for more info on learn-address script. ;learn-address ./script # If enabled, this directive will configure # all clients to redirect their default # network gateway through the VPN, causing # all IP traffic such as web browsing and # and DNS lookups to go through the VPN # (The OpenVPN server machine may need to NAT # or bridge the TUN/TAP interface to the internet # in order for this to work properly). push "redirect-gateway def1 bypass-dhcp" # Certain Windows-specific network settings # can be pushed to clients, such as DNS # or WINS server addresses. CAVEAT: # http://openvpn.net/faq.html#dhcpcaveats # The addresses below refer to the public # DNS servers provided by opendns.com. push "dhcp-option DNS 208.67.222.222" push "dhcp-option DNS 208.67.220.220" # Uncomment this directive to allow different # clients to be able to "see" each other. # By default, clients will only see the server. # To force clients to only see the server, you # will also need to appropriately firewall the # server's TUN/TAP interface. client-to-client # Uncomment this directive if multiple clients # might connect with the same certificate/key # files or common names. This is recommended # only for testing purposes. For production use, # each client should have its own certificate/key # pair. # # IF YOU HAVE NOT GENERATED INDIVIDUAL # CERTIFICATE/KEY PAIRS FOR EACH CLIENT, # EACH HAVING ITS OWN UNIQUE "COMMON NAME", # UNCOMMENT THIS LINE OUT. ;duplicate-cn # The keepalive directive causes ping-like # messages to be sent back and forth over # the link so that each side knows when # the other side has gone down. # Ping every 10 seconds, assume that remote # peer is down if no ping received during # a 120 second time period. keepalive 20 120 # For extra security beyond that provided # by SSL/TLS, create an "HMAC firewall" # to help block DoS attacks and UDP port flooding. # # Generate with: # openvpn --genkey --secret ta.key # # The server and each client must have # a copy of this key. # The second parameter should be '0' # on the server and '1' on the clients. ;tls-auth ta.key 0 # This file is secret # Select a cryptographic cipher. # This config item must be copied to # the client config file as well. ;cipher BF-CBC # Blowfish (default) cipher AES-128-CBC # AES ;cipher DES-EDE3-CBC # Triple-DES # Enable compression on the VPN link. # If you enable it here, you must also # enable it in the client config file. comp-lzo # The maximum number of concurrently connected # clients we want to allow. ;max-clients 100 # It's a good idea to reduce the OpenVPN # daemon's privileges after initialization. # # You can uncomment this out on # non-Windows systems. user nobody group nogroup # The persist options will try to avoid # accessing certain resources on restart # that may no longer be accessible because # of the privilege downgrade. persist-key persist-tun # Output a short status file showing # current connections, truncated # and rewritten every minute. ;status openvpn-status.log # By default, log messages will go to the syslog (or # on Windows, if running as a service, they will go to # the "\Program Files\OpenVPN\log" directory). # Use log or log-append to override this default. # "log" will truncate the log file on OpenVPN startup, # while "log-append" will append to it. Use one # or the other (but not both). ;log openvpn.log ;log-append openvpn.log # Set the appropriate level of log # file verbosity. # # 0 is silent, except for fatal errors # 4 is reasonable for general usage # 5 and 6 can help to debug connection problems # 9 is extremely verbose verb 0 # Silence repeating messages. At most 20 # sequential messages of the same message # category will be output to the log. ;mute 20
Все понятно, наиболее важные параметры:
push "redirect-gateway def1 bypass-dhcp" - клиенты будут пихать весь траффик в туннель по умолчанию client-to-client - разрешить пакеты из подсети одного клиента в подсеть другого cipher AES-128-CBC - алгоритм шифрования, точно такой же должен быть прописан в конфиге клиента comp-lzo - включить сжатие user nobody group nogroup - две команды запускать openvpn не от root'а ;log openvpn.log ;log-append openvpn.log verb 0 - это чтобы сервер "не шумел" и ничего не писал в лог
Разрешаем форвардинг пакетов, полученных с других машин. Вот тут я долго не мог понять почему с клиента пакеты через туннель ходят, а пакеты отправленные с хостов на клиент лезут в интернет, вместо того чтобы лезть в туннель:
echo 1 > /proc/sys/net/ipv4/ip_forward vi /etc/sysctl.conf net.ipv4.ip_forward=1
Файрвол
Файрвол по умолчанию выключен. Настраиваем:
ufw allow ssh ufw allow 1194/udp vi /etc/default/ufw DEFAULT_FORWARD_POLICY="ACCEPT" vi /etc/ufw/before.rules # rules.before # # Rules that should be run before the ufw command line added rules. Custom # rules should be added to one of these chains: # ufw-before-input # ufw-before-output # ufw-before-forward # START OPENVPN RULES # NAT table rules *nat :POSTROUTING ACCEPT [0:0] # Allow traffic from OpenVPN client to eth0 -A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE COMMIT # END OPENVPN RULES
И включаем:
ufw enable
Генерация сертификатов сервера
cp -r /usr/share/easy-rsa/ /etc/openvpn mkdir /etc/openvpn/easy-rsa/keys vi /etc/openvpn/easy-rsa/vars export KEY_COUNTRY="US" export KEY_PROVINCE="TX" export KEY_CITY="Dallas" export KEY_ORG="My Company Name" export KEY_EMAIL="sammy@example.com" export KEY_OU="MYOrganizationalUnit" - тут меняем данные на что-то близкое к реальности export KEY_NAME="server" - эта строчка важна, потому что серверный ключ должен называться server
Алгоритм Диффи-Хеллмана (DH) не является механизмом шифрования и обычно не используется для шифрования данных. Он позволяет обеспечивать безопасный обмен ключами, которые используются для шифрования данных. Алгоритмы DH позволяют двум сторонам установить общий секретный ключ, который используется алгоритмами шифрования и хеширования. openssl dhparam -out /etc/openvpn/dh2048.pem 2048
Данное действо происходит довольно долго и зависит от мощности сервера.
Переходим непосредственно к генерации ключей сервера:
cd /etc/openvpn/easy-rsa . ./vars ./clean-all - это действо нужно производить аккуратно, очищает все старые ключи ./build-ca - на все вопросы жмем Enter, все параметры мы уже поправили выше и где вопрос [y/n] - там y. ./build-key-server server - тож самое
Будут сгенерированы сертификат удостоверяющего центра и сертификат и ключ сервера - ca.crt, server.crt, server.key, все их нужно скопировать в папку /etc/openvpn:
cp /etc/openvpn/easy-rsa/keys/ca.crt /etc/openvpn cp /etc/openvpn/easy-rsa/keys/server.crt /etc/openvpn cp /etc/openvpn/easy-rsa/keys/server.key /etc/openvpn
Проверим, что все на месте:
ls -la /etc/openvpn
Запускаем сервис и проверяем его статус:
service openvpn start service openvpn status
Если само не возвращается в привилегированный режим, то жмем Ctrl-C.
Генерация сертификатов клиентов
./build-key client1 ./build-key client2 ................... ./build-key clientX - по количеству клиентов
Совет - генерируйте сразу на пару клиентских сертификатов больше, чем нужно, с запасом.
Для заливки/скачивания с машины файлов есть очень удобная программа WinSCP.exe
Копируем ключи с сервера с помощью WinSCP.exe на свою локальную машину. Для каждого клиента X должен быть наборчик - ca.crt, clientX.crt, clientX.key.
Параметры сервера для каждого клиента
В конфиге сервера есть строчки:
client-config-dir ccd ccd-exclusive
Они говорят что дополнительные параметры клиентов хранятся в директории ccd и для каждого клиента доступны свои эксклюзивные параметры. Создаем указанную директорию и файлы параметров:
cd /etc/openvpn mkdir ccd cd ccd touch client1 touch client2 ............. touch clientX
Редактируем каждый файл параметров:
vi client1 ifconfig-push 10.8.0.6 10.8.0.5 iroute 192.168.190.0 255.255.255.0
Первая строчка говорит, что шлюз туннеля на клиенте один получит адрес 10.8.0.6, вторая обратный маршрут - маршрут с VPN сервера в подсеть клиента один. После настройки всех файлов параметров:
service openvpn restart service openvpn status
Немного о подсетях для туннеля
Каждый туннель это соединение point-to-point, в котором используется подсеть на 4 адреса. Такая подсесть имеет маску /30, то есть 255.255.255.252, а количество адресов вычисляется по формуле 2^n , где n = 32 - количество бит маски, поэтому адресов для маски /30:
2^(32-30) = 2^2 = 4
Но первый адрес - это адрес всей подсети, последний - широковещательный адрес этой подсети, поэтому для назначения узлам доступно только два адреса - второй и третий по счету. Формула тут уже 2^n-2 и для наших подсетей это равно двум. Считать очень легко, группами по четыре ( 0,1,2,3 - 4,5,6,7 - 8,9,10,11 - 12,13,14,15 - 16,17,18,19 - ... - 252,253,254,255 ):
10.8.0.0 - 10.8.0.3 - первая подсесть (используется для vpn-сервера - из конфига: # The server will take 10.8.0.1 for itself.. ), доступные адреса узлов - 10.8.0.1 и 10.8.0.2 10.8.0.4 - 10.8.0.7 - вторая подсесть (используется для клиента один), доступные адреса узлов - 10.8.0.5 и 10.8.0.6 10.8.0.8 - 10.8.0.11 - третья подсесть (используется для клиента два), доступные адреса узлов - 10.8.0.9 и 10.8.0.10
Легко можно посчитать, что максимум клиентов при такой конфигурации 256/4 - 1 = 63, то есть больше, чем когда-либо понадобится (минус 1, потому что 1 подсеть использована для сервера).
На этом, чтобы не усложнять, с сервером пока всё.
Настройка клиента
Для клиентов официальный дистрибутив Ubuntu-Server x64 со страницы проекта, в качестве носителя — виртуальная машина, получение настроек сети — по умолчанию (от DHCP). Виртуальная машина идеально подходит для экспериментов, создаем контрольную точку и по необходимости откатываемся на неё столько раз, сколько надо. Создание нового клиента также идеально на виртуальной машине — предварительно настроенная болванка машины выкладывается куда-нибудь на Яндекс Диск и люди с той стороны её забирают, включают на своем Hyper-V и всё работает.
После установки включаем root'а:
sudo passwd root
Включаем вход root по ssh:
sudo vi /etc/ssh/sshd_config PermitRootLogin yes
Переключаемся на root и убиваем текущего пользователя, созданного при установке:
userdel user11 - или какой там у вас
Далее кратенько, так как почти все уже делалось на сервере:
apt-get update apt-get upgrade sudo dpkg-reconfigure unattended-upgrades
apt-get install openvpn
echo 1 > /proc/sys/net/ipv4/ip_forward vi /etc/sysctl.conf net.ipv4.ip_forward=1
Файрвол не включаем, клиент за NAT, нет необходимости.
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/server.conf vi /etc/openvpn/server.conf
Конфиг
############################################## # Sample client-side OpenVPN 2.0 config file # # for connecting to multi-client server. # # # # This configuration can be used by multiple # # clients, however each client should have # # its own cert and key files. # # # # On Windows, you might want to rename this # # file so it has a .ovpn extension # ############################################## # Specify that we are a client and that we # will be pulling certain config file directives # from the server. client # Use the same setting as you are using on # the server. # On most systems, the VPN will not function # unless you partially or fully disable # the firewall for the TUN/TAP interface. ;dev tap dev tun # Windows needs the TAP-Win32 adapter name # from the Network Connections panel # if you have more than one. On XP SP2, # you may need to disable the firewall # for the TAP adapter. ;dev-node MyTap # Are we connecting to a TCP or # UDP server? Use the same setting as # on the server. ;proto tcp proto udp # The hostname/IP and port of the server. # You can have multiple remote entries # to load balance between the servers. remote X.X.X.X 1194 ;remote my-server-2 1194 # Choose a random host from the remote # list for load-balancing. Otherwise # try hosts in the order specified. ;remote-random # Keep trying indefinitely to resolve the # host name of the OpenVPN server. Very useful # on machines which are not permanently connected # to the internet such as laptops. resolv-retry infinite # Most clients don't need to bind to # a specific local port number. nobind # Downgrade privileges after initialization (non-Windows only) user nobody group nogroup # Try to preserve some state across restarts. persist-key persist-tun # If you are connecting through an # HTTP proxy to reach the actual OpenVPN # server, put the proxy server/IP and # port number here. See the man page # if your proxy server requires # authentication. ;http-proxy-retry # retry on connection failures ;http-proxy [proxy server] [proxy port #] # Wireless networks often produce a lot # of duplicate packets. Set this flag # to silence duplicate packet warnings. ;mute-replay-warnings # SSL/TLS parms. # See the server config file for more # description. It's best to use # a separate .crt/.key file pair # for each client. A single ca # file can be used for all clients. ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/client1.crt key /etc/openvpn/keys/client1.key # Verify server certificate by checking that the # certicate has the correct key usage set. # This is an important precaution to protect against # a potential attack discussed here: # http://openvpn.net/howto.html#mitm # # To use this feature, you will need to generate # your server certificates with the keyUsage set to # digitalSignature, keyEncipherment # and the extendedKeyUsage to # serverAuth # EasyRSA can do this for you. remote-cert-tls server # If a tls-auth key is used on the server # then every client must also have the key. ;tls-auth ta.key 1 # Select a cryptographic cipher. # If the cipher option is used on the server # then you must also specify it here. ;cipher x cipher AES-128-CBC # Enable compression on the VPN link. # Don't enable this unless it is also # enabled in the server config file. comp-lzo # Set log file verbosity. verb 0 # Silence repeating messages ;mute 20
Тут важного:
cipher AES-128-CBC remote X.X.X.X 1194 - вместо X.X.X.X должен быть публичный ip-адрес vpn-сервера
Ключи
mkdir /etc/openvpn/keys cd /etc/openvpn/keys
Копируем ключи, проверяем что все на месте, стартуем Openvpn, проверяем статус туннеля:
ifconfig tun0
Если все нормально, то будет так:
Доступность openvpn-сервера:
ping 10.8.0.1
На этом с основной настройкой всё.
Скрип авто-поднятия туннеля на клиентах
Дело в том, что если туннель на работающем клиенте по каким-то причинам упадёт, то сам он не поднимется до перезапуска сервиса или до перезагрузки клиента, поэтому лепим скрипт, делаем его исполняемым и ставим его в Cron:
cd /etc mkdir scripts vi /etc/scripts/openvpn.sh # test openvpn-tun if [ -z "`ifconfig tun0`" ]; then service openvpn restart echo "`date`" >> /etc/scripts/openvpn.bug fi
Если туннель не найден среди активных интерфейсов, то время пишется в файл openvpn.bug.
chmod +x /etc/scripts/openvpn.sh
vi /etc/crontab # restart openvpn-service if drop */3 * * * * root /etc/scripts/openvpn.sh
Проверка идет каждые 3 минуты, этого достаточно, так как перезапуск службы и подъём туннеля происходит мгновенно.
Синхронизация времени
Решил что будет правильным, если время синхронизировано. И на клиентах, и на сервере:
apt-get install ntpdate apt-get install -y ntp /etc/init.d/ntp stop ntpdate pool.ntp.org /etc/init.d/ntp start
Установить временную зону:
dpkg-reconfigure tzdata
Проверить время можно так:
date
Сервер
vi /etc/ntp.conf
# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help driftfile /var/lib/ntp/ntp.drift # Enable this if you want statistics to be logged. #statsdir /var/log/ntpstats/ statistics loopstats peerstats clockstats filegen loopstats file loopstats type day enable filegen peerstats file peerstats type day enable filegen clockstats file clockstats type day enable # Specify one or more NTP servers. # Use servers from the NTP Pool Project. Approved by Ubuntu Technical Board # on 2011-02-08 (LP: #104525). See http://www.pool.ntp.org/join.html for # more information. pool 0.ubuntu.pool.ntp.org iburst pool 1.ubuntu.pool.ntp.org iburst pool 2.ubuntu.pool.ntp.org iburst pool 3.ubuntu.pool.ntp.org iburst # Use Ubuntu's ntp server as a fallback. pool ntp.ubuntu.com # Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for # details. The web page <http://support.ntp.org/bin/view/Support/AccessRestrictions> # might also be helpful. # # Note that "restrict" applies to both servers and clients, so a configuration # that might be intended to block requests from certain clients could also end # up blocking replies from your own upstream servers. # By default, exchange time with everybody, but don't allow configuration. restrict -4 default kod notrap nomodify nopeer noquery limited restrict -6 default kod notrap nomodify nopeer noquery limited # Local users may interrogate the ntp server more closely. restrict 127.0.0.1 restrict ::1 # Needed for adding pool entries restrict source notrap nomodify noquery # Clients from this (example!) subnet have unlimited access, but only if # cryptographically authenticated. #restrict 10.8.0.0 mask 255.255.255.0 notrust restrict 10.8.0.0 mask 255.255.255.0 nomodify notrap # If you want to provide time to your local subnet, change the next line. # (Again, the address is an example only.) broadcast 10.8.0.1 # If you want to listen to time broadcasts on your local subnet, de-comment the # next lines. Please do this only if you trust everybody on the network! #disable auth #broadcastclient #Changes recquired to use pps synchonisation as explained in documentation: #http://www.ntp.org/ntpfaq/NTP-s-config-adv.htm#AEN3918 #server 127.127.8.1 mode 135 prefer # Meinberg GPS167 with PPS #fudge 127.127.8.1 time1 0.0042 # relative to PPS for my hardware #server 127.127.22.1 # ATOM(PPS) #fudge 127.127.22.1 flag3 1 # enable PPS API
Чтобы с NTP-сервером могли синхронизироваться машины из локальной сети:
restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
Служба синхронизации времени использует порт 123 для соединения с сервером, поэтому необходимо разрешить доступ:
ufw allow from 10.8.0.0/24 to any port ntp
Окончательный вид файрвола сервера:
ufw status
Клиенты
# Use servers from the NTP Pool Project. Approved by Ubuntu Technical Board # on 2011-02-08 (LP: #104525). See http://www.pool.ntp.org/join.html for # more information. server 10.8.0.1 iburst prefer pool 0.ubuntu.pool.ntp.org pool 1.ubuntu.pool.ntp.org pool 2.ubuntu.pool.ntp.org pool 3.ubuntu.pool.ntp.org
Узнаем насколько время на клиенте отстает от сервера:
ntpdate -q 10.8.0.1
Основные маршруты
Чтобы все машины подсети клиента, речь идёт о Windows машинах, могли ходить в туннель и видеть подсети за туннелем накидываем маршруты для этих подсетей на местный офисный роутер. Если же это нужно только для отдельных машин, то прописываем маршруты на каждой из них, пример для 1 маршрута и соответственно для 1 удалённой подсети:
route add -p 192.168.0.0 mask 255.255.240.0 192.168.190.162 - опция -p нужна чтобы маршрут остался после перезагрузки
Остальные машины данной подсети не смогут видеть другие подсети через туннель и сами будут недоступны из других подсетей — пакет-то они получат, но вот оправить обратно не смогут.
Как добавить постоянный маршрут на Ubuntu машину рассказано в отдельной записи.
Дополнительные маршруты
А что если на одном или нескольких клиентах есть больше чем одна подсеть? К примеру у меня в центральном офисе за напрямую подключенной к клиенту сетью 192.168.0.0/20, есть еще 10.50.0.0/20. Эта сеть находится за роутером и маршрута в эту сеть на клиенте центрального офиса нет, он ничего про неё не знает. Нужно прописать 4 маршрута - 3 прямых и 1 обратный. То есть сеть 10.50.0.0/20 прописывается:
- На клиенте центрального офиса V3;
- В файле sever.conf на vpn-сервере:
# EXAMPLE: Suppose the client # having the certificate common name "Thelonious" # also has a small subnet behind his connecting # machine, such as 192.168.40.128/255.255.255.248. # First, uncomment out these lines: ;client-config-dir ccd ;route 192.168.40.128 255.255.255.248 client-config-dir ccd ccd-exclusive route 192.168.190.0 255.255.255.0 route 192.168.192.0 255.255.255.0 route 192.168.0.0 255.255.240.0 route 10.50.0.0 255.255.240.0
- В файле параметров клиента на vpn-сервере:
cd /etc/openvpn/ccd/ vi client3 ifconfig-push 10.8.0.14 10.8.0.13 iroute 192.168.0.0 255.255.240.0 iroute 10.50.0.0 255.255.240.0
- И в подсети другого клиента, где сеть 10.50.0.0/24 должна быть доступна, на роутере или на хостах.
Клиент - физическая машина
Админов можно классифицировать по разным признакам, один из признаков - админы, как и коты, бывают ленивые и очень ленивые. Умные дядьки с хорошими зарплатами из центрального офиса сказали, что поднять Hyper-V сервер - это невозможная задача и времени надо как минимум до середины ноября, поэтому готовую виртуальную машину пришлось заливать на физическую и передавать уже в таком виде. Процесс описан в отдельной записи. Ещё надо не забыть включить в BIOS машины опцию Power On After Power Fail.
Клиент - Raspberry Pi 3
Начиная с третьей версии Малинка поддерживает Ubuntu. Два дистрибутива, что я нашел - не заработали. Дистрибутив с официальной страницы после обновления стал вываливаться в дамп. Второй дистрибутив с "raspberry2" в названии вообще не стартовал. Поставил Raspbian. Это моё первое знакомство с данной ОС. Логин/пароль по умолчанию pi/raspberry. Практически все команды работают, Debian он и есть.. - установить vim и команды задавать как vim ... Не нашел как отключить автоматическое обновление (а включено ли оно вообще?). Всё остальное также как и для других клиентов - включить root, убить пользователя pi и так далее. Рассмотрение настройки Малинки не входит в задачи этой статьи. Очень-очень кратко:
raspi-config rm -rf /opt - удалим каталог с образцом видео df -h - проверяем свободное место update-rc.d -f bluetooth remove update-rc.d -f dhcpcd remove
vim /etc/network/interfaces - закомментировать всё, что не по делу
Добавление нового клиента
Через некоторое время потребуется добавить нового клиента. Генерим новые сертификаты на сервере:
. ./vars ./build-key client5
Другой хороший вариант - сгенерировать сразу клиентских сертификатов с запасом, штук десять.
Прописываем новую сеть в конфигурацию сервера server.conf, создаем файл параметров клиента в папке ccd. Берем болванку виртуальной машины и заливаем сертификаты, а старые удаляем. В начале этого процесса лучше изолировать машину от выхода в интернет, иначе она полезет к серверу и нарушит работу машины, с которой была снята эта болванка.
Подключение к клиентам
После прописывания основных маршрутов все клиенты доступны по SSH через туннель по своим адресам в туннеле - 10.8.0.X.
Заключение
Чего-то много опять получилось, реально статья - 5300+ слов. Наверное половину слов дают конфиги 🙂 А на написание и правку так вообще целый день ушел, больше даже, но написание подобных статей хорошо систематизирует знания. Openvpn сеть работает и чем дольше пользуюсь, тем больше мне нравится. Приятно, что открытое ПО стало уже таким зрелым и вкусным.
Единственный момент, который был упущен из виду MTU на сервере и на клиентах. Хотя при настройках по умолчанию всё работало нормально. Кто хочет поразбираться с данным моментом, можно почитать на OpenVPN Wiki, поиск по ключу "mssfix".
/etc/default/ufw
DEFAULT_FORWARD_POLICY="ACCEPT"
слишком координально...
лучше добавить правило, например:
ufw route allow from 10.8.0.0/24 to 192.168.0.0/24
хотя и это многовато.. 🙂
Андрей, спасибо за комментарий. Учту.
Так, ещё раз всё проверил, что-то вы путаете. http://help.ubuntu.ru/wiki/руководство_по_ubuntu_server/безопасность/firewall
Цитирую: 1. Во-первых, в ufw должно быть активировано перенаправление. Для этого нужно изменить конфигурацию двух файлов, в /etc/default/ufw измените DEFAULT_FORWARD_POLICY на “ACCEPT”
И посмотрите в статье "Окончательный вид файрвола сервера:". Там мы видим, что разрешён трафик ssh отовсюду - он защищён паролем и сертификатом, разрешён трафик openvpn отовсюду - подключатся лишь клиенты с верным сертификатом и разрешен трафик NTP из внутренней сети. Никаких проблем в безопасности нет, DEFAULT_FORWARD_POLICY “ACCEPT” всего лишь правило по-умолчанию, без которого вообще никакой форвардинг пакетов через сервер невозможен.
Возможно что то путаю, но у меня работает с DROP по умолчанию и правилом ufw route. Я это понимают так. Если openvpn сервер находится в локалке то да можно так
/etc/default/ufw
DEFAULT_FORWARD_POLICY="ACCEPT"
Правило по умолчанию: Если не запрещено то куда угодно.
В такой ситуации даже ufw disable не слишком опасно, но если на интернет шлюзе то лучше всетаки "DROP" и правило
ufw route allow from 10.8.0.0/24 to 192.168.0.0/24
(хотя и там лучше ограничить порты и протоколы до необходимых) - разрешает маршрутизацию только между подсетями 10.8.0 и 192.168.0
На help.ubuntu.ru хорший мануал, но там эту проблему решают както непосредсвенно через iptable.. для меня слишком умно ))), а ufw route почемуто забыли.. см. man ufw
Сама маршрутизация включается действительно в /etc/ufw/sysctl.conf :
net/ipv4/ip_forward=1
в Windows c помощью regedit кажется так:
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters для параметра IPEnableRouter на “1” и перезагрузить...
Насколько понимаю в силу своего разумения - ufw закрывает не только трафик снаружи, но и внутри машины, а именно между сетевыми интерфейсами, если их несколько.
DEFAULT_INPUT_POLICY="DROP"
DEFAULT_OUTPUT_POLICY="ACCEPT"
DEFAULT_FORWARD_POLICY="DROP"
DEFAULT_APPLICATION_POLICY="SKIP"
Вот чтобы интерфейсы имели возможность пересылать между собой трафик и нужно правило DEFAULT_FORWARD_POLICY="ACCEPT" и больше ни для чего, и больше ни на что оно не влияет. Можно его сделать DROP и точно указать с какого интерфейса на какой разрешено пересылать трафик? Да можно конечно. А зачем? Ведь это внутри машины всё. Зачем трафик внутри машины нагружать обсчётом? На это тратятся ресурсы. Считаю неоптимальным решением.
Полнстью согласен. Оптимальное решение должно быть основано на конкретной ситуации и личных предпочтениях. Я только предложил еще один вариант конфигурации.
Спасибо за комментарии, пришлось посидеть, поразбираться с устройством файрвола в Linux. Уже хорошо 🙂 Также чётче обозначилась необходимость закончить LPIC-1, потому что знаний курса Essentials, который пройдён на момент, явно недостаточно и довольно несложная вещь (как вопрос, который мы обсуждали) сначала превращается в гадание на кофейной гуще, а потом в высиживание интернета в поисках ответов - это про себя говорю. Надеюсь, вы тоже получили какую-то пользу от нашего обсуждения.
Да точно в linux для включения маршрутизации нужно еще echo 1 > /proc/sys/net/ipv4/ip_forward