Translate

пʼятницю, 3 лютого 2017 р.

OpenVPN Part II: Connect Two Local Networks (Tun Interface)

Декілька тижнів тому я опублікував першу статтю про програму OpenVPN, де описав декілька способів її практичного використання. Цього разу я розповім про те, як об’єднати дві різні локальні мережі, в результаті чого кожен із вузлів буде мати доступ до всіх інших вузлів обох підмереж. Звісно дуже раджу спочатку ознайомитись із першою статтею, яка надасть необхідний теоретичний мінімум.

Для експериментів будемо використовувати наступні вузли:

 Short name  Public IP  Private IP  Network  Role
 ams1 37.139.10.10 10.129.18.182  10.129.0.0/16 SERVER
 ams2  - 10.129.20.80 10.129.0.0/16   -
 local1  - 192.168.1.10 192.168.1.0/24 CLIENT
 local2 -  192.168.1.20 192.168.1.0/24  -

Отже ми маємо два хости у підмережі 10.129.0.0/16 та два в іншій підмережі 192.168.1.0/24. ams1 (10.129.18.182) буде працювати у ролі сервера і для зовнішніх з’єднань володітиме публічною адресою 37.139.10.10 (це обов’язкова умова, якщо не враховувати можливість перебросу порта на OpenVPN-сервер). А local1 (192.168.1.10) буде підключатись до сервера у якості клієнта OpenVPN.

Установимо OpenVPN на ams1 та local1 вузлах:

# apt install openvpn

Запустимо OpenVPN у якості сервера на ams1, використовуючи конфігураційний файл, приведений нижче:

# vim /etc/openvpn/server.conf

# Port and protocol
port 1194
proto udp

# Emulated network interface
dev tun

# Server's certificates/key
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret

# Diffie-Hellman key
dh dh2048.pem

# OpenVPN client's address pool
server 10.8.0.0 255.255.255.0

# configuration files for each client
client-config-dir ccd

route 192.168.1.0 255.255.255.0

# Timeouts
keepalive 10 120

# TLS authentication secret
tls-auth ta.key 0 # This file is secret
key-direction 0

# Minimal TLS version for connection
tls-version-min 1.2

# TLS cipheres. We are using only most secure ones.
tls-cipher TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256

# Encryption algorithm for traffic
cipher AES-256-CBC

# HMAC auth
auth SHA256

# Traffic commpression
comp-lzo

# Redusing daemon's privileges after initialization.
user nobody
group nogroup

# Persistence of client's interface/key
# after server restarting
persist-key
persist-tun

# Logging parameters
status openvpn-status.log
log-append /var/log/openvpn.log
verb 4
# No more than 20 the same messages
mute 20

Як згенерувати ключі для сервера та що значить кожна опція можна прочитати в першій статті про OpenVPN.

Описуємо маршрути на сервері, котрі необхідно буде додати на клієнті 192.168.1.10:

# cat /etc/openvpn/ccd/client1

iroute 192.168.1.0 255.255.255.0
push "route 10.129.0.0 255.255.0.0"

client1 - ім'я файлу, який має зівпадати зі значенням CN під час генерації сертифіката і ключа для клієнта.

Маршрути на сервері після старту OpenVPN:

# route -n

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         37.139.10.1     0.0.0.0         UG    0      0        0 eth0
10.8.0.0        10.8.0.2        255.255.255.0   UG    0      0        0 tun0
10.8.0.2        0.0.0.0         255.255.255.255 UH    0      0        0 tun0
10.129.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth1
37.139.10.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.1.0     10.8.0.2        255.255.255.0   UG    0      0        0 tun0

Виходячи з конфігураційного файлу сервера, створимо профіль для клієнта. Деталі його створення, знову ж, можна знайти в першій статті. Головне не забути виставити CN сертифікату, що відповідає назві файлу ccd на сервері. Загалом він має виглядати приблизно так:

# cat client1.ovpn

client
dev tun

proto udp
remote 37.139.10.10 1194

resolv-retry infinite

nobind

user nobody
group nogroup

persist-key
persist-tun

tls-version-min 1.2

tls-cipher TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256

remote-cert-tls server

cipher AES-256-CBC
auth SHA256
# 0 is on server and 1 on client
key-direction 1

comp-lzo

verb 4
mute 20

# script-security 2
# up /etc/openvpn/update-resolv-conf
# down /etc/openvpn/update-resolv-conf
<ca>
-----BEGIN CERTIFICATE-----
MIIFDzCCA/egAwIBAgIJAMX81RffWnqkMA0GCSqGSIb3DQEBCwUAMIG1MQswCQYD
...
6qk0ZJH2Zj+iMPkl10QuJeXXzR1Q8/UJxvZKjwUbax0q4GWs4DwBjHuN3gY4YEqA
C+q1
-----END CERTIFICATE-----
</ca>
<cert>
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 2 (0x2)
...
        Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=MyOrganizationalUnit, CN=client1/name=server/emailAddress=me@myhost.mydomain
...
         2b:7e:67:28:1c:ae:d3:89:27:a1:15:42:7c:45:be:d7:9b:c8:
         7e:f1:af:20
-----BEGIN CERTIFICATE-----
MIIFYTCCBEmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBtTELMAkGA1UEBhMCVVMx
...
txT8lhfRBxdZ8ntCAAdGK35nKByu04knoRVCfEW+15vIfvGvIA==
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwoxoskak9uP93
...
Ii5fit+0Qo31nJc1NMbgOL0=
-----END PRIVATE KEY-----
</key>
<tls-auth>
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
9d8d206cf67f30575c65d29ab43ecaac
...
79853b78b8c1dfd097de022a6d725c58
-----END OpenVPN Static key V1-----
</tls-auth>

Скопіюємо профіль на клієнт (192.168.1.10) та підключимось до сервера:

# openvpn --config client1.ovpn

Вигляд маршрутів на клієнті стане наступним:

# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth1
10.8.0.1        10.8.0.9        255.255.255.255 UGH   0      0        0 tun0
10.8.0.9        0.0.0.0         255.255.255.255 UH    0      0        0 tun0
10.129.0.0      10.8.0.9        255.255.0.0     UG    0      0        0 tun0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1

Варто не забувати, що як клієнт, так і сервер потребують установки значення ip_forward в 1:

# vim /etc/sysctl.conf
...
net.ipv4.ip_forward=1
...

# sysctl -p

На даному етапі вузол 10.129.18.182 буде бачити хости своєї підмережі та лише OpenVPN-клієнт 192.168.1.10:

root@ams1:~# for i in 10.129.18.182 10.129.20.80 192.168.1.10 192.168.1.20; do ping -c 2 $i; printf '=%.0s' {1..30} && echo -e "\n"; done

PING 10.129.18.182 (10.129.18.182) 56(84) bytes of data.
64 bytes from 10.129.18.182: icmp_seq=1 ttl=64 time=0.111 ms
64 bytes from 10.129.18.182: icmp_seq=2 ttl=64 time=0.104 ms

--- 10.129.18.182 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.104/0.107/0.111/0.010 ms
==============================

PING 10.129.20.80 (10.129.20.80) 56(84) bytes of data.
64 bytes from 10.129.20.80: icmp_seq=1 ttl=64 time=1.27 ms
64 bytes from 10.129.20.80: icmp_seq=2 ttl=64 time=0.594 ms

--- 10.129.20.80 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.594/0.936/1.279/0.343 ms
==============================

PING 192.168.1.10 (192.168.1.10) 56(84) bytes of data.
64 bytes from 192.168.1.10: icmp_seq=1 ttl=64 time=44.8 ms
64 bytes from 192.168.1.10: icmp_seq=2 ttl=64 time=44.7 ms

--- 192.168.1.10 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 44.703/44.771/44.840/0.222 ms
==============================

PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.

--- 192.168.1.20 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 999ms

І відповідно 192.168.1.10 також буде бачити свою мережу та лише OpenVPN-сервер 10.129.18.182 без доступу до інших вузлів мережі:

root@local1:~# for i in 10.129.18.182 10.129.20.80 192.168.1.10 192.168.1.20; do ping -c 2 $i; printf '=%.0s' {1..30}; echo -e "\n"; done

PING 10.129.18.182 (10.129.18.182) 56(84) bytes of data.
64 bytes from 10.129.18.182: icmp_seq=1 ttl=64 time=45.0 ms
64 bytes from 10.129.18.182: icmp_seq=2 ttl=64 time=44.5 ms

--- 10.129.18.182 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 44.597/44.838/45.080/0.321 ms
==============================

PING 10.129.20.80 (10.129.20.80) 56(84) bytes of data.

--- 10.129.20.80 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1009ms

==============================

PING 192.168.1.10 (192.168.1.10) 56(84) bytes of data.
64 bytes from 192.168.1.10: icmp_seq=1 ttl=64 time=0.059 ms
64 bytes from 192.168.1.10: icmp_seq=2 ttl=64 time=0.082 ms

--- 192.168.1.10 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.059/0.070/0.082/0.014 ms
==============================

PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.
64 bytes from 192.168.1.20: icmp_seq=1 ttl=64 time=0.788 ms
64 bytes from 192.168.1.20: icmp_seq=2 ttl=64 time=0.950 ms

--- 192.168.1.20 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
rtt min/avg/max/mdev = 0.788/0.869/0.950/0.081 ms
==============================

Тож першу проблему, котру необхідно вирішити - це дозволити трансляцію адрес з клієнта у підмережу сервера і з сервера в підмережу клієнта. Це нескладно і правило трансляції адрес на клієнті (192.168.1.10) та сервері (10.129.18.182) буде виглядати наступним чином:

# iptables -t nat -s 10.8.0.0/24 -A POSTROUTING -o eth1 -j MASQUERADE

eth1 - це інтерфейс, якому призначена локальна адреса.

У той же час, якщо дефолтна політика ланцюжка FORWARD не ACCEPT, необхідно виконати на сервері та клієнті:

# iptables -P FORWARD ACCEPT

Після цього, як OpenVPN-клієнт, так і сервер матимуть доступ до всіх вузлів обох підмереж.

Проте це ще не все. На даному етапі 192.168.1.20 та 10.129.20.80, тобто вузли підмереж за OpenVPN-клієнтом та сервером, бачитимуть лише свою підмережу. Для виправлення цієї ситуації на 192.168.1.20 варто додати наступний маршрут:

# route add -net 10.129.0.0 netmask 255.255.0.0 gw 192.168.1.10

Тобто всі запити до адрес підмережі 10.129.0.0/16 з сервера 192.168.1.20 будуть надсилатись через OpenVPN-клієнт 192.168.1.10. Цього правила буде достатньо для того, щоб пакети дійшли до OpenVPN-сервера 10.129.18.182, а далі вони не будуть знати, що роботи. Для подолання цієї проблеми необхідно на OpenVPN-сервері 10.129.18.182 додати нове правило трансляції адрес:

# iptables -t nat -s 192.168.1.0/24 -A POSTROUTING -o eth1 -j MASQUERADE

І, як результат, всі пакети з 192.168.1.20 будуть доходити до адресатів обох підмереж.

Для того, щоб і вузол 10.129.20.80 бачив усі хости за OpenVPN-клієнтом необхідно додати схоже правило трансляції на OpenVPN-клієнт 192.168.1.10:

# iptables -t nat -s 10.129.0.0/16 -A POSTROUTING -o eth1 -j MASQUERADE

У цьому випадку, як і у попередньому, eth1 - інтерфейс, що обслуговує локальну мережу. Також 10.129.20.80 потребує додатковий роут на 10.129.18.182, для маршрутизації запитів до підмережі 192.168.1.0/24:

# route add -net 192.168.1.0 netmask 255.255.255.0 gw 10.129.18.182

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

Звісно це не найелегантніше рішення і ліпше за все ці маршрути описувати на основних шлюзах кожної мережі.

За необхідністю пересвідчитись в тому, що пакети справді потрапляють на певний хост можна за допомогою tcpdump. Наприклад так він може відслідковувати всі icmp-пакети на інтерфейсі eth1:

# tcpdump -i eth1 -n -nn -ttt 'ip proto \icmp'

P.S. Якщо було введене невірне правило iptables, видалити його можна наступним чином. На прикладі таблиці nat виведемо номер кожного правила:

# iptables -t nat --line-numbers -L

Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    MASQUERADE  all  --  10.8.0.0/24          anywhere
2    MASQUERADE  all  --  10.9.0.0/24          anywhere

Видалимо лише друге правило з ланцюжка POSTROUTING:

# iptables -t nat -D POSTROUTING 2

Очистити усю таблицю nat можна так:

# iptables -t nat -F

А очистити всі ланцюжки зі всіма таблицями так https://www.cyberciti.biz/tips/linux-iptables-how-to-flush-all-rules.html

P.P.S. Можна також почитати та спробувати, за необхідності чи з цікавості, роботу OpenVPN в bridged режимі. Про деталі можна, наприклад, прочитати тут http://yakim.org.ua/articles/servers/170-openvpn-esxi.html

Посилання:

Iptables
http://www.k-max.name/linux/netfilter-iptables-v-linux/
http://www.k-max.name/linux/iptables-v-primerax/
https://www.digitalocean.com/community/tutorials/how-to-list-and-delete-iptables-firewall-rules
http://lubos.rendek.org/remove-all-iptables-prerouting-nat-rules/

OpenVPN
https://debian-administration.org/article/489/Connecting_to_office_network_using_OpenVPN_tunnel
http://www.area536.com/projects/securely-link-two-offices-using-openvpn/
http://sysadm.pp.ua/linux/shifrovanie/openvpn-point-to-point.html
https://www.bestvpnz.com/openvpn-guide-and-best-providers-offering-the-protocol/
https://www.clearos.com/resources/documentation/clearos/content:en_us:kb_o_connecting_networks_with_openvpn
http://robert.penz.name/312/howto-connect-multiple-networks-over-the-internet-the-cheap-way/
https://community.openvpn.net/openvpn/wiki/RoutedLans

Немає коментарів:

Дописати коментар