Я создал контейнер Ubuntu 16.04 lxd и установил в нем Stunnel, Tinyproxy и клиент OpenVPN.
Цель — подключиться к Tinyproxy через Stunnel и заставить Tinyproxy использовать интерфейс OpenVPN для исходящих подключений.
Stunnel -> Tinyproxy работает нормально — страницы в браузере загружаются как положено, однако, как только я запускаю службу OpenVPN, Stunnel на стороне клиента дает сбой из-за тайм-аута, и браузер продолжает ждать ответа.
Поскольку Tinyproxy 1.8.3 (новейшая версия для Ubuntu 16.04) не поддерживает возможность привязки исходящих подключений к определенному интерфейсу, мне пришлось разрешить OpenVPN добавлять маршруты по умолчанию через его tun0
интерфейс.
OpenVPN-клиент работает как и ожидалось - все пакеты из контейнера проходят через VPN. Хост с контейнером - удаленный хост с публичным IP. DNAT настроен на контейнер.
Я не очень хорошо знаком с внутренним устройством маршрутизации, смог настроить только SNAT/DNAT и фильтрацию с помощью iptables. Поэтому я не могу понять корень проблемы.
Вот наиболее важные параметры окружающей среды:
ifconfig
$ ifconfig -a
eth0 Link encap:Ethernet HWaddr 00:16:3e:5f:46:ba
inet addr:10.227.60.197 Bcast:10.227.60.255 Mask:255.255.255.0
inet6 addr: fe80::216:3eff:fe5f:46ba/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:16291 errors:0 dropped:0 overruns:0 frame:0
TX packets:15632 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:5044056 (5.0 MB) TX bytes:4171187 (4.1 MB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:2446 errors:0 dropped:0 overruns:0 frame:0
TX packets:2446 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:2483699 (2.4 MB) TX bytes:2483699 (2.4 MB)
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.8.0.3 P-t-P:10.8.0.3 Mask:255.255.255.0
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:3 errors:0 dropped:0 overruns:0 frame:0
TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:252 (252.0 B) TX bytes:252 (252.0 B)
маршрут
$ route -v -e
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
default 10.8.0.1 128.0.0.0 UG 0 0 0 tun0
default 10.227.60.1 0.0.0.0 UG 0 0 0 eth0
10.8.0.0 * 255.255.255.0 U 0 0 0 tun0
10.227.60.0 * 255.255.255.0 U 0 0 0 eth0
128.0.0.0 10.8.0.1 128.0.0.0 UG 0 0 0 tun0
<vpn server IP> 10.227.60.1 255.255.255.255 UGH 0 0 0 eth0
stunnel.конг
...
accept = 10.227.60.197:8081
connect = 127.0.0.1:8080
...
tinyproxy.conf
...
Port 8080
Listen 127.0.0.1
...
vpnclient.conf
dev tun
proto udp
remote <vpn server ip> 1195
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA512
cipher AES-256-CBC
key-direction 1
verb 3
#route-nopull
...
iptablesпусты.
решение1
Проблема была в конфигурации таблицы маршрутизации.
Я заметил, что при удалении маршрутов, добавленных OpenVPN:
Destination Gateway Genmask Flags MSS Window irtt Iface
default 10.8.0.1 128.0.0.0 UG 0 0 0 tun0
и пытаясь выполнить ping 8.8.8.8 -I tun0
и одновременно контролировать пакеты с tcpdump -nn icmp
, ответные icmp-запросы на самом деле попадают, eth0
но не продолжаются. После некоторого расследования я обнаружил, что также должна быть отдельная таблица маршрутизации для tun0
и правила для нее, поскольку у сервера 2 интерфейса.
В конце концов я обновил tinyproxy до последней версии, чтобы иметь возможность указывать исходящий интерфейс, и отключил OpenVPN для передачи маршрутов по умолчанию, подобных тому, который я удалил выше.
Затем я добавил таблицу /etc/iproute2/rt_tables
:
...
12 vpn
добавлены маршруты в эту таблицу и правила:
ip route add 10.8.0.0/24 dev tun0 src 10.8.0.3 table vpn
ip route add default via 10.8.0.1 dev tun0 table vpn
ip rule add from 10.8.0.3/32 table vpn
ip rule add to 10.8.0.3/32 table vpn
После этого все стало работать так, как и ожидалось.