Маршрутизация трафика через определенный интерфейс для процесса в Linux
Можно ли направить трафик, используемый процессом, через определенный интерфейс?
Например, сетевой трафик при загрузке приложения всегда должен использовать интерфейс wlan0
тогда как все другие приложения на машине должны использовать eth0
,
Возможно ли иметь такое правило в Linux?
5 ответов
Я ооочень боролся с этим, так что вот ПОЛНОЕ решение. Он протестирован на Ubuntu 15 и 16. Вы можете особенно использовать его с OpenVPN для маршрутизации определенных приложений вне интерфейса VPN-туннеля.
Полное решение "cgroup"
Как это работает?
- Ядро Linux поместит приложение в контрольную группу. Сетевой трафик от приложений в этой группе будет идентифицирован по их идентификатору класса на уровне сетевого контроллера.
- iptables отметит этот трафик и заставит его выйти с правильным IP
- ip route будет обрабатывать помеченный трафик в другой таблице маршрутизации с маршрутом по умолчанию к любому IP-адресу шлюза, который вы хотите.
Автоматический скрипт
Я сделал скрипт novpn.sh для автоматизации установки и запуска зависимостей. Проверено на Ubuntu.
Сначала запустите свой VPN.
wget https://gist.githubusercontent.com/kriswebdev/a8d291936fe4299fb17d3744497b1170/raw/cf8b37fbe6c3f50a0be825eb77cafa3e0134946f/novpn.sh
# If you don't use eth0, edit the script setting.
sudo chmod +x novpn.sh
./novpn.sh traceroute www.google.com
./novpn.sh --help
Ручная инструкция
Сначала установите поддержку cgroup и инструменты:
sudo apt-get install cgroup-lite cgmanager cgroup-tools
Перезагрузка (может и не понадобиться).
Вам нужен iptables 1.6.0+. Получите исходный код iptables 1.6.0, распакуйте его и запустите --disable-nftables
флаг позволит избежать ошибок) из каталога iptables:
sudo apt-get install dh-autoreconf bison flex
./configure --prefix=/usr \
--sbindir=/sbin \
--disable-nftables \
--enable-libipq \
--with-xtlibdir=/lib/xtables
make
sudo make install
iptables --version
Теперь настоящий конфиг. Определите контрольную группу с именем novpn
, Процессы в этой группе будут иметь класс 0x00110011
(11:11).
sudo su
mkdir /sys/fs/cgroup/net_cls/novpn
cd /sys/fs/cgroup/net_cls/novpn
echo 0x00110011 > net_cls.classid
Теперь предположим, что интерфейс, который вы хотите использовать для конкретного приложения, eth0
со шлюзом IP 10.0.0.1
, Замените их тем, что вы действительно хотите (получить информацию от ip route
). Запустите еще как root:
# Add mark 11 on packets of classid 0x00110011
iptables -t mangle -A OUTPUT -m cgroup --cgroup 0x00110011 -j MARK --set-mark 11
# Force the packets to exit through eth0 with NAT
iptables -t nat -A POSTROUTING -m cgroup --cgroup 0x00110011 -o eth0 -j MASQUERADE
# Define a new "novpn" routing table
# DO THIS JUST ONCE !
echo 11 novpn >> /etc/iproute2/rt_tables
# Packets with mark 11 will use novpn
ip rule add fwmark 11 table novpn
# Novpn has a default gateway to the interface you want to use
ip route add default via 10.0.0.1 table novpn
# Unset reverse path filtering for all interfaces, or at least for "eth0" and "all"
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $i; done
Наконец, запустите ваше приложение на определенном интерфейсе:
exit
sudo cgcreate -t $USER:$USER -a $USER:$USER -g net_cls:novpn
cgexec -g net_cls:novpn traceroute www.google.com
# Close all Firefox windows first
cgexec -g net_cls:novpn firefox
Или если вы хотите перенести уже запущенный процесс в cgroup, ну... вы не можете! Похоже, это связано с функцией NAT (маскарад): iptables -nvL -t nat
не совпадает при переключении cgroup, но iptables -nvL -t mangle
совпадает
# Get PID of the process (we'll then suppose it's 1234)
pidof firefox
# Add to cgroup - THIS DOESN'T WORK! Silently fails to produce the final result.
sudo echo 1234 > /sys/fs/cgroup/net_cls/novpn/tasks
# Remove - but this works...
sudo echo 1234 > /sys/fs/cgroup/net_cls
Кредиты: ни один ответ не работал, как ожидалось, но смесь из них сработала: chripell answer статья evolware Маршрутизация процесса занимает 2: использование cgroups, iptables и маршрутизация политики. Как сделать так, чтобы конкретный процесс НЕ проходил через соединение OpenVPN? Убей свитч для OpenVPN на основе iptables
Это можно сделать с помощью сетевых имен Linux.
Вот статья, которая объясняет как. По сути, вы создаете сетевое пространство имен с другим маршрутом по умолчанию и запускаете там процессы, которые в нем нуждаются. Вы подключаете только что созданное сетевое пространство имен к физическому адаптеру с помощью моста (но, конечно, возможны и другие решения).
Обновление: из ядра 3.14 использование групп управления еще проще, как описано в этой статье. Ты должен:
1) определить контрольную группу net_cls для аннотирования пакетов из данного процесса с помощью classid (или группы процессов, обратите внимание, что между ними не должно быть никаких отношений родитель-потомок)
2) использовать модуль iptables cgroup (добавлен в Linux 3.14), чтобы пометить пакеты
3) использовать политику маршрутизации (ip rule add fwmark ....) для создания новой таблицы маршрутизации для помеченных пакетов
Преимущество состоит в том, что нам не нужно заниматься связующим звеном, и все намного динамичнее благодаря cgroups.
Несколько человек написали прокладки, которые используют функцию LD_PRELOAD в Linux для достижения этой цели:
Комбинируя превосходные ответы mariusmatutiae и KrisWebDev, я создал чрезвычайно модифицированную версию KrisWebDev. novpn.sh
скрипт. В то время как сценарий KrisWebDev предназначен для устранения более специфического зуда (запуск и перемещение процессов внутри / вне VPN), моя версия позволяет вам выполнять практически любую команду в сетевой среде, которую вы укажете. Вы можете указать интерфейс для привязки, маршрут по умолчанию, указать свои собственные правила iptables, статические маршруты, указать "тест", чтобы подтвердить, что все работает, как вы хотите, перед запуском команды... и т. Д.). Он позволяет вам использовать несколько конфигурационных файлов, чтобы вы могли определить любое количество конкретных сетевых сред, в которых вы можете запускать команды / процессы.
Я разместил это как суть здесь: https://gist.github.com/level323/54a921216f0baaa163127d960bfebbf0
Впоследствии он может даже очистить таблицы cgroup/iptables/routing!
Обратная связь приветствуется.
PS - Он предназначен для Debian 8 (Джесси)
Не за приложение, нет. Вы можете сделать это для каждого порта или для каждого IP-адреса и т. Д., Или само приложение может привязать (и использовать) определенную сетевую карту.
Вы не можете установить правило, чтобы сделать это, хотя.