переадресація порту до програми в просторі мереж імен за допомогою 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>

Додаток запущено, я використовую deluge для цього прикладу. Я спробував кілька додатків з веб-інтерфейсом, щоб переконатися, що це не проблема специфічного потоку.

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 сервера, який інстанціював мережевий інтерфейс)

EDIT: Я видалив свої спроби створити правила 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 і на добру міру кинув МАСКВЕРАДУ, але оскільки я не знаю, що роблю, мої спроби марні. Можливо, хтось може допомогти мені зібрати цю конструкцію.

EDIT: вихід 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

EDIT: Сам @schnouki вказав на статтю в адміністрації Debian, що пояснює загальний проксі-сервер iptables TCP . Як застосовано до проблеми, їх сценарій виглядатиме так:

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, але зараз моя проблема вирішена.


Відмова: Я взагалі не маю досвіду роботи з vethпристроями (вважаю це дуже цікавим, хоча ... ;-)). Ви використовували tcpdumpдля перевірки, наскільки далеко потрапляють вхідні пакети? Якщо tcpdump -i veth0нічого не показує, то tcpdumo -i loможе знадобитися.
Hauke ​​Laging

Я додав невербальний вихід tcpdump
pskiebe

Відповіді:


9

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

По суті, вам потрібно мати демон у прослуховуванні робочого простору за замовчуванням на порту TCP 8112 і перенаправляти весь трафік на порт 10.200.200.2 8112. Отже, це простий проксі-сервер TCP.

Ось як це зробити з socat :

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

( forkОпція потрібна, щоб уникнути socatзупинки після закриття першого проксі-зв'язку).

EDIT : додано, reuseaddrяк було запропоновано в коментарях.

Якщо ви абсолютно хочете зробити це за допомогою iptables, на сайті адміністрації Debian є посібник . Але я все-таки віддаю перевагу socatбільш досконалим речам - наприклад, наближення IPv4 до IPv6 або позбавлення SSL, щоб дозволити старі програми Java підключатися до захищених служб ...

Однак остерігайтеся, що всі з'єднання в Deluge будуть здійснюватися з IP вашого сервера замість реального IP-адреси клієнта. Якщо ви хочете цього уникнути, вам потрібно буде використовувати справжній зворотний проксі HTTP, який додає вихідний IP-код клієнта до проксі-запиту в заголовку HTTP.


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.


працює як шарм
приблизно в

Оскільки я не надто досвідчений в управлінні 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
# в'яжіть мій $ TUN (інтерфейс VPN) у простір імен
ip набір $ TUN мереж $ 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 додати gw $ GATEWAY_IP за замовчуванням
  1. Встановіть veth зв’язок між вашим простором імен за замовчуванням та тим, що ви створили:
# Налаштування veth-інтерфейсів для зв'язку між просторами імен
ip посилання додати veth0 тип veth одноліткове ім'я veth1
# Перемістіть другий вентилятор до простору імен
ip встановити посилання veth1 netns $ NS
# дайте IP з невикористаного діапазону IP першим клієнтам
ifconfig veth0 10.1.1.1/24 вгору
# І другий
ip netns exec $ NS ifconfig veth1 10.1.1.2/24 вгору
# TODO: встановіть міст між інтерфейсом veth1 та et, щоб він міг спілкуватися з локальною мережею
# Налаштування DNS-клієнта. ip netns буде імітувати /etc/resolv.conf, використовуючи цей файл:
mkdir -p / etc / netns / $ NS
echo "nameserver 8.8.4.4"> /etc/netns/$NS/resolv.conf
  1. Запустіть потоплене в $ NS і ваше потокове мережу в просторі імен за замовчуванням. Вкажіть deluge-web на 10.1.1.2 veth IP-адресу, де потоплений буде слухати його з'єднання.

Вуаля! Ви занурилися захищені за VPN, поки ваша мережа потопу вільно доступна у вашій домашній мережі


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всередині вашого мережевого простору імен потрібно буде працювати, якщо його ще немає (і корисна операція віртуального пароля):

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.