Следующая новость
Предыдущая новость

VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces

15.01.2018 13:25
VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces

Содержание статьи

  • Немного о Linux namespaces
  • Введение в курс
  • База netns
  • Выполнение команд и запуск процессов внутри netns
  • Разбираемся с OpenVPN
  • Изменение клиентского конфига
  • Управление клиентом
  • Заключение

VPN — это замечательная штука, которая повышает твою анонимность и безопасность. Но постоянно сидеть под VPN может быть неудобно: хочешь, например, зайти в интернет-банк со своего реального IP, но на закачке стоит пара новых эпизодов любимого сериала. В Linux можно решить эту проблему при помощи механизма network namespaces и туннелировать трафик отдельных приложений. Сейчас я покажу, как это сделать.

Немного о Linux namespaces

В Linux реализована функция пространства имен (namespace), которая отвечает за изоляцию разных ресурсов системы. Она вовсю применяется в проектах контейнеризации, например таких как Docker. Существует несколько типов пространств имен: pid, net, mnt, user, uts, ipc.

Нас интересует пространство имен для сетей (netns), которое изолирует сетевые ресурсы. Для каждого netns можно назначать: свои интерфейсы, наборы IP-адресов и портов (сокеты), таблицы маршрутизации, правила файрвола и так далее. Есть возможность перемещать интерфейсы из одного netns в другой. Физический интерфейс (например, eth0) может находиться одновременно только в одном netns.

Изначально все интерфейсы и процессы содержатся в исходном (initial) netns, у него нет конкретного имени, и он не отображается в списке. После освобождения какого-либо netns все физические интерфейсы, которые были в нем, возвращаются в initial netns. Освобождение происходит после завершения последнего процесса в этом netns. Например, даже если удалить конкретный netns, но процесс, запущенный в нем, будет активным, физический интерфейс не перенесется обратно в исходный netns до тех пор, пока процесс не будет завершен. Рассмотрим этот вариант позже.

Введение в курс

Именно netns поможет нам в туннелировании трафика отдельных приложений. Для начала нужно немного разобраться в командах управления.

База netns

За контроль netns отвечает утилита ip из пакета iproute2. Для соединения netns между собой можно использовать пару виртуальных интерфейсов veth. Рассмотрим пример создания нескольких netns и их соединения. Для этого выполним

$ sudo ip netns add ns_1 $ sudo ip netns add ns_2 

Наличие этих netns смотри командой ip netns list или просто ip netns, так как list — действие по умолчанию. Добавим виртуальную пару при помощи команды

$ sudo ip link add dev virt01 type veth peer name virt02 
Управление netns и veth с помощью ip

Интерфейсы добавились, теперь переместим virt01 в netns ns_1, а virt02 — в ns_2.

$ sudo ip link set virt01 netns ns_1 $ sudo ip link set virt02 netns ns_2 

Если не появилось сообщений об ошибках, значит, все прошло успешно. Для выполнения команды внутри netns используется команда

$ sudo ip netns exec <имя netns> <команда для выполнения> 

Например, посмотреть список доступных интерфейсов внутри netns ns_1 можно при помощи

$ sudo ip netns exec ns_1 ip link 

Почитав man, узнаем, что выполнять команды ip внутри netns можно при помощи $ sudo ip -n <имя netns>, а значит, $ sudo ip netns exec ns_1 ip link заменяем на $ sudo ip -n ns_1 link.

VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces
Удостоверимся, что интерфейсы перенеслись в нужные netns

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

Добавим нашим интерфейсам virt01 и virt02 по IP-адресу и переведем их в состояние UP. Для этого воспользуемся «прокачанной» командой, подсмотренной в man:

$ sudo ip -n ns_1 addr add 10.0.0.1/24 dev virt01 $ sudo ip -n ns_2 addr add 10.0.0.2/24 dev virt02 $ sudo ip -n ns_1 link set dev virt01 up $ sudo ip -n ns_2 link set dev virt02 up $ sudo ip -n ns_1 addr show $ sudo ip -n ns_2 addr show 
VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces
Соединяем вместе нашу виртуальную пару

Как я уже говорил, у каждой netns своя таблица маршрутизации, проверим это.

VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces
Действительно, таблицы отличаются

Для проверки связи между ns_1 и ns_2 воспользуемся командой ping.

$ sudo ip netns exec ns_1 ping -c 4 10.0.0.2 
VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces
Соединение установлено успешно

Как ты помнишь, адрес 10.0.0.2 принадлежит интерфейсу virt02, который находится в ns_2. Похожим способом netns соединяют с физическим eth0.

Выполнение команд и запуск процессов внутри netns

Как ты помнишь, команды внутри netns выполняются при помощи

$ sudo ip netns exec <имя netns> <команда> 

Чтобы не писать все это каждый раз, запустим bash!

$ sudo ip netns exec ns_1 bash 

После этого все команды будут исполняться внутри netns — заодно и проверим ситуацию с файрволом. Чтобы вернуться, пиши exit или CTRL + D.

VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces
Список правил пуст

У меня всегда присутствуют правила в файрволе, так что это точно отдельный набор. ????

Перейдем к примеру с возвращением физического интерфейса в initial netns. Для этого проверим текущее расположение enp0s3 и перенесем его в ns_2.

$ sudo ip link set dev enp0s3 netns ns_2 
VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces
Как видно, enp0s3 больше нет в init netns

Поднимем его в netns ns_2 и запустим WireShark от имени пользователя (eakj) там же.

$ sudo ip -n ns_2 link set dev enp0s3 up $ sudo ip -n ns_2 link $ sudo ip netns exec ns_2 sudo -u eakj wireshark 2>/dev/null & 
VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces
WireShark запущен в netns ns_2

Теперь удалим netns ns_2 и посмотрим, вернется ли enp0s3 в initial netns:

$ sudo ip netns del ns_2 
VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces
enp0s3 не освободится, пока процесс WireShark не будет завершен, даже несмотря на удаление ns_2

Закроем WireShark и посмотрим, даст ли это результат.

VPN не для всех. Туннелируем трафик отдельных приложений с помощью Linux network namespaces
После завершения процесса enp0s3 вернулся в initial netns

Этого должно быть достаточно, чтобы понять, как работают netns и как ими управлять. Перейдем к OpenVPN.

Разбираемся с OpenVPN

Не так давно я писал о том, как поднять собственный OpenVPN на арендованном сервере. Если ты следовал гайду, то у тебя уже настроен клиентский файл, который можно использовать. Конфигурационные файлы других VPN-провайдеров тоже подойдут, так как никаких изменений на сервере делать не придется.

Изменение клиентского конфига

Познакомимся с новыми директивами OpenVPN.

  1. ifconfig-noexec — запрещает клиенту автоматическое выполнение ifconfig для добавления IP-адреса интерфейсу tun. Вместо этого передаст нужные параметры в качестве переменных окружения.
  2. route-noexec — та же ситуация, что и с ifconfig-noexec, только вместо IP он не будет добавлять маршруты. Необходимые параметры передадутся.
  3. route-up /полный/путь/к/скрипту отправит на скрипт переменной окружения $script_type строку route-up.
  4. up /полный/путь/к/скрипту — то же, что и route-up, только передаст строку up после поднятия интерфейса tun/tap. Выполняется до директивы user, которая должна понизить наши привилегии.
  5. down /полный/путь/к/скрипту — то же, что и route-up, только строку down, после удаления интерфейса tun/tap. Выполняется после директивы user!
  6. script-security 2 позволит исполнять кастомные скрипты.

Полный список передаваемых переменных окружения можно посмотреть в man openvpn, секция Environmental Variables.

Надеюсь, ты обратил внимание на жирный шрифт. Директива up добавит наш netns, down — удалит. Для добавления и удаления netns нужны права рута. Это не проблема в случае с up, поскольку она исполняется перед user, а та, в свою очередь, понижает права до nobody. А вот с down явно будут проблемы, так как пользователь nobody не сможет удалить netns. Поэтому первым делом в клиентском конфиге закомментируй или удали строчки

user nobody group nobody 

и добавь новые директивы. Пример немного измененного скрипта из прошлой статьи:

Продолжение статьи доступно только подписчикам

Cтатьи из последних выпусков журнала можно покупать отдельно только через два месяца после публикации. Чтобы читать эту статью, необходимо купить подписку.

Подпишись на журнал «Хакер» по выгодной цене!

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

1 год

5690 р.

Экономия 1400 рублей!

1 месяц

720 р.

25-30 статей в месяц

Уже подписан?

Источник

Последние новости