Как использовать namespaced-openvpn для VPN для каждого приложения?
Это, наверное, вопрос для новичков, но...
Я использую 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
) с реального localhost (enp3s0
адаптер Ethernet) - перенаправить этот порт таким образом, чтобы я мог получить к нему доступ с других моих компьютеров в моей локальной сети
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
Мне пришлось использовать фактический localhost-IP (неlocalhost
или имя, потому что оно, кажется, не решается должным образом)- убедитесь, что вы экранировали двойной знак (
:
) внутри одинарных кавычек - Я не уверен, вызывает ли это утечку DNS; из того, что я проверил, это не так, но я не могу быть уверен, так как не знаю, как это проверить
Что осталось делать:
- автоматизировать все команды, чтобы запустить приложение и перенаправить порт при запуске: в настоящее время мне это не нужно, но если / когда я узнаю, как это сделать, я добавлю его сюда
С опозданием на много лет, но на случай, если кто-то столкнется с этим, как мне хотелось бы, чтобы я сделал это в последние пару дней или около того.
Надеюсь, это кому-то поможет.
Во-первых, вот namespace-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
Где обозначает назначенные диапазоны IP-адресов, которые вы НЕ ХОТИТЕ пересылать.
В основном это делается для предотвращения образования петли маршрутизации, при которой любые службы, доступные через подсеть, перенаправляются обратно к себе.
--dport 80 предназначен для пересылки только пакетов, ищущих порт 80 IE, для подключения к веб-серверу.
— это интерфейс veth, который был перемещен ВНУТРИ пространства имен, в котором работает ваш сервер.
Это делает так, что пакеты, поступающие, НЕ от10.0.0.0/24
подсеть, которая ищет службу порта 80, преобразует свой IP-адрес назначения в . Пример: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
для доступа к вашему серверу вместо этого он перенаправляется.
Попробую объяснить часть моей установки...
Пример пространства имен:ip netns add ns_example
Создайте вет-пару. Одна сторона останется в корневом/обычном пространстве имен (я называю это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 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(), используйте интерфейс ihost и перезапишите исходный адрес на сторону корневого пространства имен().
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.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
Если я правильно понимаю, перезапись исходного адреса нужна только для того, чтобы убедиться, что пакет знает, как вернуться из пространства имен, и наоборот.
Теперь например: чтобы получить доступ к торрент вебуи в пространстве имён по порту 8080, я делаю так.
Любой пакет, идущий на мой IP-адрес в локальной сети (пример: я печатаю в браузере). Он перезапишет место назначения в пространство имен, в котором работает мой торрент-клиент (Пример: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. VPN с пространством имен выдает исключение, когда обнаруживает интерфейсы внутри вашего целевого пространства имен, отличные отlo
петлевой интерфейс.
Вот та часть, которая выдает мне исключения, когда я использую 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, которое по какой-либо причине (ошибка, перезапуск ping и т. д.) повторно подключается к провайдеру VPN и получает новый IP-адрес. Интерфейс VPN, возможно, придется отключить на долю секунды, чтобы сбросить конфигурацию, и это приведет к сбою клиента (qBittorrent наверняка делает это). «Исправление», над которым я начал работать, — это написать сценарий, который определяет, когда интерфейс VPN получает новый IP-адрес или по какой-либо причине отключается от сети. Скрипт должен корректно (важно: корректно, чтобы избежать повреждения чего-либо/ошибки файловой системы) выйти из торрент-клиента, а затем перезапустить его. У меня пока нет рабочего скрипта, но это кажется достойным вектором решения данной проблемы.