
Это, вероятно, вопрос новичка, но...
Я использую Ubuntu 18.04.3 LTS и у меня естьVPNкоторый я хочу использовать для нескольких приложений. Я проверилnamespaced-openvpn
и это работает! Проблема в том, что я не могу подключиться к этому приложению локально (в целях управления).
Есть ли способ перенаправить определенный порт внутри VPN-туннеля на локальный хост?без использования VPN-туннеля в других целях и, таким образом, утечки слишком большого количества информации?
Что я уже умею:
- бегать
namespaced-openvpn
-скрипт:sudo ./namespaced-openvpn --namespace vpn --config /etc/openvpn/vpn-xxxxx.ovpn
- выполнить приложение внутри сетевого пространства имен:
sudo ip netns exec vpn application
Чего я хочу добиться:
- подключиться к приложению, запущенному внутри VPN-туннеля (например, на порту
1234
), с реального локального хоста (enp3s0
адаптера Ethernet) - перенаправить этот порт таким образом, чтобы я мог получить к нему доступ с других компьютеров в моей локальной сети
решение1
С опозданием на много лет, но на случай, если кто-то наткнется на это, как я хотел бы сделать в последние пару дней или около того.
Надеюсь, это кому-то поможет.
Во-первых, вот namespaced-vpn, который делает 90% работы по запуску всего этого.
https://github.com/slingamn/namespaced-openvpn
И вот ответ на вопрос, почти такой же, как этот, который мне очень помог, хотя я и не понимал, что и зачем делается. https://unix.stackexchange.com/questions/391193/how-to-forward-traffic-between-linux-network-namespaces
Я попытаюсь объяснить, что я понял после многих проб и ошибок, используя крупицы информации, которые я нашел в своих поисках.
Наиболее важной частью для перенаправления соединений к вашей службе (не с ПК, на котором запущена служба), я считаю, является эта (обратите внимание на восклицательный знак после PREROUTING):
iptables -t nat -A PREROUTING ! -s 10.0.0.0/24 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
Где, 10.0.0.0/24
представляет собой диапазоны IP-адресов, которые НЕ ХОТИТЕ пересылать.
Это в основном необходимо для предотвращения петли маршрутизации, когда любые службы, доступные с использованием 10.0.0.0/24
подсети, направляются обратно к себе.
--dport 80 — только для пересылки пакетов, ищущих порт 80, т. е. подключение к веб-серверу
10.0.0.2
. — это интерфейс veth, который был перемещен ВНУТРИ пространства имен, на котором работает ваш сервер.
Это позволяет пакетам, поступающим НЕ из 10.0.0.0/24
подсети, которые ищут службу порта 80, получать IP-адрес назначения, преобразованный в 10.0.0.2
. Пример: 192.168.1.200:80
становится 10.0.0.2:80
, который предположительно является интерфейсом внутри пространства имен, в котором находится ваш сервер.
У меня есть несколько vpn-туннелей, работающих в нескольких пространствах имен. Если я не добавлю правило PREROUTING в свои iptables, я не смогу получить доступ к ресурсу из-за пределов моего ПК в моей локальной сети.
Если вы хотите, чтобы он был доступен с вашего ПК, вам нужно добавить правило, например:
iptables --table nat --append OUTPUT --destination 192.168.1.2 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
Таким образом, если вы вводите в браузере на ПК, на котором установлен сервер, 192.168.1.2
чтобы получить доступ к своему серверу, он будет перенаправлен на 10.0.0.2
.
Я попытаюсь объяснить часть моей установки...
Пример пространства имен:ip netns add ns_example
Создайте пару veth. Одна сторона останется в пространстве имен root/normal (я называю это host
), другая сторона перейдет в пространство имен с VPN.
ip link add dev ihost type veth peer name ivpn
Переместите сторону vpn пары veth в целевое пространство имен:
ip link set dev ivpn netns ns_example
Назначьте IP-адреса созданной вами паре veth.
Я использую /32, потому что я хочу назначить только этот точный IP, а не диапазон. В противном случае, когда я поднимаю устройства, некоторые маршруты автоматически вставляются в мою ip route
таблицу, и это портит мою маршрутизацию для моих других пространств имен.
Для назначения принимающей стороне.
ip addr add 10.0.0.1/32 dev ihost
Чтобы назначить сторону vpn, которая была перемещена в пространство имен, необходимо добавить к команде префикс ..
ip netns exec TARGET_NAMESPACE
Итак, чтобы назначить IP для VPN-стороны:
ip netns exec ns_example ip addr add 10.0.0.2/32 dev ivpn
Теперь поднимите интерфейсы.
ip link set dev ihost up
ip netns exec ns_example ip link set dev ivpn up
Здесь я добавляю маршруты и iptables, чтобы трафик шел между ними.
Из корневого пространства имен, чтобы попасть на сторону VPN( 10.0.0.2
), используйте интерфейс ihost и перепишите исходный адрес на сторону корневого пространства имен( 10.0.0.1
).
ip route add 10.0.0.2/32 dev ihost src 10.0.0.1
Сделайте то же самое, но с противоположной точки зрения внутри пространства имен VPN.
ip netns exec ns_example ip route add 10.0.0.1/32 dev ivpn src 10.0.0.2
Теперь я добавляю те же операции, iptables
которые являются отдельными, ip route
но выполняют схожие задачи.
Любой пакет, отправляемый на 10.0.0.2
адрес источника, переписывается на10.0.0.1
iptables --table nat --append POSTROUTING --destination 10.0.0.2/32 --jump SNAT --to-source 10.0.0.1
То же самое, но с противоположной точки зрения и внутри пространства имен.
ip netns exec ns_example iptables --table nat --append POSTROUTING --destination 10.0.0.1/32 --jump SNAT --to-source 10.0.0.2
Если я правильно понимаю, перезапись исходного адреса нужна только для того, чтобы пакет знал, как выйти из пространства имен и наоборот.
Теперь, например: чтобы получить доступ к torrent webui в пространстве имен на порту 8080, я делаю это.
Любой пакет, идущий на мой LAN IP (пример: я ввожу 192.168.1.2:8080
в браузере). Он перепишет пункт назначения на пространство имен, на котором работает мой torrent-клиент (пример: 10.0.0.2
).
iptables --table nat --append OUTPUT --destination 192.168.1.2/32 --protocol tcp --match tcp --dport 8080 --jump DNAT --to-destination 10.0.0.2
Это правило специально перенаправляет только порт 8080, и это правило предназначено для вас, чтобы получить доступ к службе НА ПК, на котором она работает. Любому другому ПК в сети, получающему доступ, 192.168.1.2:8080
нужно правило PREROUTING, которое я упомянул в начале ответа (просто измените --dport 80 на --dport 8080 или любой другой нужный вам порт/протокол).
Для тех, кто использует этот метод и скрипт namespaced-vpn.py. У вас могут возникнуть проблемы, если вам когда-либо придется сбросить vpn. Namespaced vpn выдает исключение, когда обнаруживает интерфейсы внутри вашего целевого пространства имен, отличные от lo
интерфейса loopback.
Вот часть, которая выдает исключения для меня, когда я использую namespaced-vpn.py, когда мое целевое пространство имен уже существует и в нем есть мои пары veth.
if os.path.exists(os.path.join('/var/run/netns', namespace)):
adapters = _adapter_names(namespace)
if adapters != [b'lo']:
LOG.error('Namespace %s already has adapters %s, exiting.' % (namespace, adapters))
raise Exception
Вот пример модификации, которую я использовал.
allowed_adapters = [b'lo', b'ivpn']
if os.path.exists(os.path.join('/var/run/netns', namespace)):
adapters = _adapter_names(namespace)
# Iterate and ensure all are in allowed list
for a in adapters:
if not a.split(b'@')[0] in allowed_adapters:
LOG.error('Namespace %s has non-whitelisted adapters %s, exiting.' % (namespace, adapters))
raise Exception
Просто не забудьте добавить такой вызов для каждого интерфейса, который, как вы ожидаете, уже существует в нижней части функции `def setup_namespace(namespace)`. Замените LO на имя устройства.
subprocess.check_call(_enter_namespace_cmd(namespace) + [IP_CMD, 'link', 'set', 'LO', 'up'])
Пример:
subprocess.check_call(_enter_namespace_cmd(namespace) + [IP_CMD, 'link', 'set', 'ivpn', 'up'])
Для тех, кто использует клиент BitTorrent, подключенный к интерфейсу VPN, вы можете столкнуться с проблемой случайного прерывания соединения вашего клиента по любой причине. Например, вы просыпаетесь утром и видите, что все ваши прекрасные загрузки заморожены через 10 минут после того, как вы ушли.
Я считаю, что эта проблема возникает из-за программного обеспечения VPN IE OpenVPN, которое повторно подключается к провайдеру VPN по какой-либо причине (ошибка, перезапуск ping и т. д.) и получает новый IP-адрес. Интерфейс VPN может быть переведен в автономный режим на долю секунды, чтобы сбросить конфигурацию, и это приводит к сбоям в работе клиента (qBittorrent точно это делает). «Исправление», которое я начал изучать, заключается в написании скрипта, который определяет, когда интерфейс VPN получает новый IP-адрес или отключается по какой-либо причине. Скрипт должен корректно (важно: корректно, чтобы избежать повреждения чего-либо/ошибки файловой системы) выходить из клиента Torrent, а затем перезапускать его. У меня пока нет рабочего скрипта, но, похоже, это неплохой вектор для решения этой проблемы.
решение2
Ладно. Кажется, этот вопрос слишком сложен для того, чтобы на него кто-то мог ответить, или, возможно, на него уже отвечали, но никто не удосужился ответить.
В любом случае: я работал над этим еще один день и решил, что поскольку я заинтересован только в предоставлении доступа к одному порту для веб-интерфейса приложения, я могу также использоватьsocat
. Так я и сделал.
После создания соединения namespaced-openvpn и запуска приложения внутри этого сетевого пространства имен я выполнил следующую команду в выделенном терминале:
sudo socat tcp-listen:PORT-TO-FORWARD-TO,fork,reuseaddr exec:'ip netns exec vpn socat STDIO tcp-connect\:127.0.0.1\:PORT-TO-LISTEN-TO',nofork
Примечания:
PORT-TO-FORWARD-TO
это порт, на который я хочу перенаправить порт (в корневом сетевом пространстве имен)PORT-TO-LISTEN-TO
это порт приложения, который я хочу выставить в корневом пространстве имен127.0.0.1
Мне пришлось использовать настоящий локальный IP-адрес (а неlocalhost
имя, потому что он, похоже, не разрешается должным образом)- обязательно экранируйте символ двойной точки (
:
) внутри одинарных кавычек - Я не уверен, приводит ли это к утечкам DNS; судя по тому, что я проверил, это не так, но я не могу быть в этом уверен, так как не знаю, как это проверить.
Что осталось сделать:
- автоматизировать все команды для запуска приложения и переадресации порта при запуске: в данный момент мне это не нужно, но если/когда я узнаю, как это сделать, я добавлю это сюда