VPN — это замечательная штука, которая повышает твою анонимность и безопасность. Но постоянно сидеть под VPN может быть неудобно: хочешь, например, зайти в интернет-банк со своего реального IP, но на закачке стоит пара новых эпизодов любимого сериала. В Linux можно решить эту проблему при помощи механизма network 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 отвечает утилита 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
Интерфейсы добавились, теперь переместим 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
.
По умолчанию интерфейсы, созданные или перемещенные в 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
Как я уже говорил, у каждой netns своя таблица маршрутизации, проверим это.
Для проверки связи между ns_1
и ns_2
воспользуемся командой ping
.
$ sudo ip netns exec ns_1 ping -c 4 10.0.0.2
Как ты помнишь, адрес 10.0.0.2 принадлежит интерфейсу virt02
, который находится в ns_2
. Похожим способом netns соединяют с физическим eth0
.
Как ты помнишь, команды внутри netns выполняются при помощи
$ sudo ip netns exec <имя netns> <команда>
Чтобы не писать все это каждый раз, запустим bash
!
$ sudo ip netns exec ns_1 bash
После этого все команды будут исполняться внутри netns — заодно и проверим ситуацию с файрволом. Чтобы вернуться, пиши exit
или CTRL + D
.
У меня всегда присутствуют правила в файрволе, так что это точно отдельный набор. ????
Перейдем к примеру с возвращением физического интерфейса в initial netns. Для этого проверим текущее расположение enp0s3
и перенесем его в ns_2
.
$ sudo ip link set dev enp0s3 netns ns_2
Поднимем его в 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 &
Теперь удалим netns ns_2
и посмотрим, вернется ли enp0s3
в initial netns:
$ sudo ip netns del ns_2
Закроем WireShark и посмотрим, даст ли это результат.
Этого должно быть достаточно, чтобы понять, как работают netns и как ими управлять. Перейдем к OpenVPN.
Не так давно я писал о том, как поднять собственный OpenVPN на арендованном сервере. Если ты следовал гайду, то у тебя уже настроен клиентский файл, который можно использовать. Конфигурационные файлы других VPN-провайдеров тоже подойдут, так как никаких изменений на сервере делать не придется.
Познакомимся с новыми директивами OpenVPN.
ifconfig-noexec
— запрещает клиенту автоматическое выполнение ifconfig
для добавления IP-адреса интерфейсу tun
. Вместо этого передаст нужные параметры в качестве переменных окружения.route-noexec
— та же ситуация, что и с ifconfig-noexec
, только вместо IP он не будет добавлять маршруты. Необходимые параметры передадутся.route-up /полный/путь/к/скрипту
отправит на скрипт переменной окружения $script_type
строку route-up
.up /полный/путь/к/скрипту
— то же, что и route-up
, только передаст строку up
после поднятия интерфейса tun/tap. Выполняется до директивы user
, которая должна понизить наши привилегии.down /полный/путь/к/скрипту
— то же, что и route-up
, только строку down
, после удаления интерфейса tun/tap. Выполняется после директивы user
!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 статей в месяц |
Уже подписан?
Читайте также
Последние новости