перенаправление портов на приложение в сетевом пространстве имен с помощью vpn

13

Я смог настроить сетевое пространство имен, установить туннель с openvpn и запустить приложение, которое использует этот туннель внутри пространства имен. Пока все хорошо, но к этому приложению можно получить доступ через веб-интерфейс, и я не могу понять, как перенаправлять запросы на веб-интерфейс внутри моей локальной сети.

Я следовал руководству от @schnouki, объясняющему, как настроить сетевое пространство имен и запустить в нем OpenVPN.

ip netns add myvpn
ip netns exec myvpn ip addr add 127.0.0.1/8 dev lo
ip netns exec myvpn ip link set lo up
ip link add vpn0 type veth peer name vpn1
ip link set vpn0 up
ip link set vpn1 netns myvpn up
ip addr add 10.200.200.1/24 dev vpn0
ip netns exec myvpn ip addr add 10.200.200.2/24 dev vpn1
ip netns exec myvpn ip route add default via 10.200.200.1 dev vpn1
iptables -A INPUT \! -i vpn0 -s 10.200.200.0/24 -j DROP
iptables -t nat -A POSTROUTING -s 10.200.200.0/24 -o en+ -j MASQUERADE
sysctl -q net.ipv4.ip_forward=1
mkdir -p /etc/netns/myvpn
echo 'nameserver 8.8.8.8' > /etc/netns/myvpn/resolv.conf

После этого я могу проверить свой внешний ip и получить разные результаты внутри и снаружи пространства имен, как и предполагалось:

curl -s ipv4.icanhazip.com
<my-isp-ip>
ip netns exec myvpn curl -s ipv4.icanhazip.com
<my-vpn-ip>

Приложение запущено, я использую потоп для этого примера. Я попробовал несколько приложений с веб-интерфейсом, чтобы убедиться, что это не проблема, связанная с потопом.

ip netns exec myvpn sudo -u <my-user> /usr/bin/deluged
ip netns exec myvpn sudo -u <my-user> /usr/bin/deluge-web -f
ps $(ip netns pids myvpn)
 PID TTY      STAT   TIME COMMAND
1468 ?        Ss     0:13 openvpn --config /etc/openvpn/myvpn/myvpn.conf
9302 ?        Sl    10:10 /usr/bin/python /usr/bin/deluged
9707 ?        S      0:37 /usr/bin/python /usr/bin/deluge-web -f

Я могу получить доступ к веб-интерфейсу через порт 8112 из пространства имен и извне, если я укажу ip veth vpn1.

ip netns exec myvpn curl -Is localhost:8112 | head -1
HTTP/1.1 200 OK
ip netns exec myvpn curl -Is 10.200.200.2:8112 | head -1
HTTP/1.1 200 OK
curl -Is 10.200.200.2:8112 | head -1
HTTP/1.1 200 OK

Но я хочу перенаправить порт 8112 с моего сервера на приложение в пространстве имен. Цель состоит в том, чтобы открыть браузер на компьютере в моей локальной сети и получить веб-интерфейс с http: // my-server-ip: 8112 (my-server-ip - это статический ip сервера, который создал сетевой интерфейс)

РЕДАКТИРОВАТЬ: я удалил свои попытки создать правила iptables. То, что я пытаюсь сделать, объяснено выше, и следующие команды должны вывести HTTP 200:

curl -I localhost:8112
curl: (7) Failed to connect to localhost port 8112: Connection refused
curl -I <my-server-ip>:8112
curl: (7) Failed to connect to <my-server-ip> port 8112: Connection refused

Я попробовал правила DNAT и SNAT и бросил MASQUERADE для хорошей меры, но так как я не знаю, что я делаю, мои попытки тщетны. Возможно, кто-то может помочь мне собрать эту конструкцию.

РЕДАКТИРОВАТЬ: выход tcpdump tcpdump -nn -q tcp port 8112. Неудивительно, что первая команда возвращает HTTP 200, а вторая команда завершается с отклоненным соединением.

curl -Is 10.200.200.2:8112 | head -1
listening on vpn0, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 10.200.200.1.36208 > 10.200.200.2.8112: tcp 82
IP 10.200.200.2.8112 > 10.200.200.1.36208: tcp 145

curl -Is <my-server-ip>:8112 | head -1
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
IP <my-server-ip>.58228 > <my-server-ip>.8112: tcp 0
IP <my-server-ip>.8112 > <my-server-ip>.58228: tcp 0

РЕДАКТИРОВАТЬ: @schnouki сам указал мне на статью администрации Debian, объясняющую универсальный TCP-прокси iptables . Применительно к рассматриваемой проблеме их сценарий будет выглядеть следующим образом:

YourIP=<my-server-ip>
YourPort=8112
TargetIP=10.200.200.2
TargetPort=8112

iptables -t nat -A PREROUTING --dst $YourIP -p tcp --dport $YourPort -j DNAT \
--to-destination $TargetIP:$TargetPort
iptables -t nat -A POSTROUTING -p tcp --dst $TargetIP --dport $TargetPort -j SNAT \
--to-source $YourIP
iptables -t nat -A OUTPUT --dst $YourIP -p tcp --dport $YourPort -j DNAT \
--to-destination $TargetIP:$TargetPort

К сожалению, трафик между интерфейсами veth конфискован и больше ничего не произошло. Тем не менее, @schnouki также предложил использовать socatв качестве TCP-прокси, и это работает отлично.

curl -Is <my-server-ip>:8112 | head -1
IP 10.200.200.1.43384 > 10.200.200.2.8112: tcp 913
IP 10.200.200.2.8112 > 10.200.200.1.43384: tcp 1495

Мне еще предстоит понять странную перестановку портов во время прохождения трафика через интерфейсы veth, но моя проблема решена сейчас.

pskiebe
источник
Отказ от ответственности: я не имею никакого опыта работы с vethустройствами (нахожу это очень интересным, хотя ... ;-)). Вы использовали tcpdumpдля проверки, как далеко зашли входящие пакеты? Если tcpdump -i veth0ничего не показывает, то tcpdumo -i loможет понадобиться.
Хауке Лагинг
Я добавил невербальный вывод tcpdump
pskiebe

Ответы:

9

У меня всегда были проблемы с перенаправлениями iptables (возможно, моя вина, я уверен, что это выполнимо). Но для случая, подобного вашему, IMO проще сделать это в пользовательской среде без iptables.

По сути, вам нужно, чтобы в вашей рабочей области «по умолчанию» был демон, прослушивающий TCP-порт 8112 и перенаправляющий весь трафик на порт 8112.10.2.2. Так что это простой TCP-прокси.

Вот как это сделать с помощью socat :

socat tcp-listen:8112,reuseaddr,fork tcp-connect:10.200.200.2:8112

( forkОпция необходима, чтобы избежать socatостановки после закрытия первого прокси-соединения).

РЕДАКТИРОВАТЬ : добавлено, reuseaddrкак предлагается в комментариях.

Если вы абсолютно хотите сделать это с помощью iptables, на сайте администрирования Debian есть руководство . Но я все еще предпочитаю socatболее сложные вещи, такие как проксирование IPv4 в IPv6 или удаление SSL, чтобы старые программы Java могли подключаться к защищенным сервисам ...

Однако помните, что все соединения в Deluge будут с IP вашего сервера, а не с реального IP-адреса клиента. Если вы хотите избежать этого, вам потребуется использовать реальный обратный прокси-сервер HTTP, который добавляет исходный IP-адрес клиента к прокси-запросу в заголовке HTTP.

Schnouki
источник
1
Вы только что сделали мой день! Я никогда не сталкивался, socatи это в точности соответствует тому, что я пытался сделать с iptables уже довольно давно. Я протестировал несколько приложений, и все они работают безупречно, подключаясь к внешнему миру через tun0, и в то же время предоставляя доступ к их веб-интерфейсу через veth1.
pskiebe
1
После некоторого тестирования я добавил reuseaddrфлаг. Это предотвращает port already in useошибки при запуске и остановке socat в быстрой последовательности:socat -4 TCP-LISTEN:8112,reuseaddr,fork TCP:10.200.200.2:8112
pskiebe
8

Соединение сетевого пространства имен с основным пространством имен меня всегда беспокоит. Причина, по которой я обычно создаю пространство имен, заключается в том, что я хочу, чтобы оно было изолированным. В зависимости от того, чего вы пытаетесь достичь с помощью пространств имен, создание межсоединений может победить эту цель.

Но даже в одиночестве я все еще хочу выложить его по сети, для удобства.

Это решение позволяет вам сохранять изоляцию и пересылать некоторые соединения к нему в любом случае. Вам не нужно создавать всю эту сеть между двумя сетевыми пространствами имен только для переадресации одного порта. Запустите это в пространстве имен, где вы хотите принимать соединения. Должен быть запущен как root для ip netns execработы.

socat tcp-listen:8112,fork,reuseaddr \
  exec:'ip netns exec myvpn socat STDIO tcp-connect\:127.0.0.1\:8112',nofork

Он прослушивает соединения в одном сетевом пространстве имен, где вы его запускаете, на порту 8112, затем подключенный клиент execзапускается ip netns exec myvpn ...для выполнения остальных внутри myvpnсетевого пространства имен, а затем, оказавшись внутри myvpnсетевого пространства имен, он снова создает второе соединение с другим socat.

AnyDev
источник
работать как очарование
примерное число
Так как я не слишком опытен в администрировании Linux, и мне потребовалось некоторое время, чтобы выяснить: убедитесь, что оба :символа заключены в одинарные кавычки, иначе вы можете столкнуться с ошибкой ... wrong number of parameters (2 instead of 1)(2 или 3). В противном случае: отлично работает! Огромное спасибо!
Игорь
2

Для потопа вот мое решение. Нет необходимости в iptables. Вот шаги:

  1. Начните свой openvpn туннель
  2. Создайте пространство имен и перенесите туда свой туннель openvpn:
ip netns добавляет $ NS
# Подождите, пока TUN появится
while [[$ (ip route | grep $ TUN | wc -l) == 0]]; спать 1; сделано
MY_IP = $ (ip addr show $ TUN | grep inet | cut -d '' -f6 | cut -d '/' -f1)
# Способ извлечения IP-адреса шлюза может отличаться для вашего соединения openvpn
GATEWAY_IP = $ MY_IP
# jail my $ TUN (интерфейс VPN) в пространство имен
ip link set $ TUN netns $ NS
# Создайте интерфейс с подсетью (эквивалентной той, которую мне дал VPN-сервер)
ip netns exec $ NS ifconfig $ TUN $ MY_IP / 24 up
# Подними петлю
ip netns exec $ NS ifconfig lo 127.0.0.1/8 up
# Настройте удаленный шлюз (ваш IP-адрес VPN-точки)
ip netns exec $ NS route add default gw $ GATEWAY_IP
  1. Установите veth соединение между вашим пространством имен по умолчанию и тем, которое вы создали:
# Настроить veth интерфейсы для связи между пространствами имен
ip-ссылка добавляет veth0 тип veth peer name veth1
# Переместите второй вет в ваше пространство имен
ip link set veth1 netns $ NS
# дать IP от неиспользованного диапазона IP до первого вет
ifconfig veth0 10.1.1.1/24 up
# И второй
ip netns exec $ NS ifconfig veth1 10.1.1.2/24 up
# TODO: установить мост между veth1 и интерфейсом eth, чтобы он мог взаимодействовать с локальной сетью
# Настройка DNS-клиента. ip netns будет эмулировать /etc/resolv.conf, используя этот файл:
mkdir -p / etc / netns / $ NS
echo "nameserver 8.8.4.4"> /etc/netns/$NS/resolv.conf
  1. Запустите ваш deluged в $ NS и ваш deluge-web в вашем пространстве имен по умолчанию. Укажите deluge-web на IP-адрес вета 10.1.1.2, где deluged будет прослушивать соединение.

Вуаля! Вы защищены deluge за VPN, а ваш deluge-web свободно доступен в вашей домашней сети.

Влад
источник
2

@ AndrDevEK ответ полезен. Чтобы расширить это, вы можете не захотеть устанавливать socat. В этом случае вы можете добиться того же с помощью немного запутанной настройки переадресации порта SSH. В частности, здесь полезна функция переадресации портов в / из сокета unix-домена, поскольку сокеты unix-домена работают независимо от пространств имен сети:

sudo ip netns exec myvpn su -c "ssh -N -L /tmp/myunixsock:localhost:8112 localhost" $USER &
ssh_pid1=$!
ssh -N -L localhost:8112:/tmp/myunixsock localhost &
ssh_pid2=$!

Очистка:

sudo kill $ssh_pid1
kill $ssh_pid2
rm /tmp/myunixsock

Первый ssh -N -Lзапускается в пространстве имен myvpn. Это создает сокет unix-домена /tmp/myunixsockи прослушивает его. Входящие соединения пересылаются на localhost: 8112 (внутри пространства имен myvpn). Второй ssh -N -Lзапускается в пространстве имен по умолчанию. Это создает прослушивающий TCP-порт и перенаправляет входящие соединения в сокет домена unix.

Следует отметить, что для того, чтобы это работало, sshвнутреннее пространство имен сети должно работать, если это еще не сделано (и операция pubkey без пароля полезна):

sudo ip netns exec myvpn ip link set up dev lo
sudo ip netns exec myvpn /usr/sbin/sshd -o PidFile=/run/sshd-myvpn.pid
ssh-copy-id localhost
Цифровая травма
источник