19

Можно ли направить трафик, используемый процессом, через определенный интерфейс?

Например, сетевой трафик приложения загрузки всегда должен использовать интерфейс wlan0 тогда как все другие приложения на машине должны использовать eth0 .

Возможно ли иметь такое правило в Linux?

5 ответов5

21

Это можно сделать с помощью сетевых имен Linux.

Вот статья, которая объясняет как. По сути, вы создаете сетевое пространство имен с другим маршрутом по умолчанию и запускаете там процессы, которые в нем нуждаются. Вы подключаете только что созданное сетевое пространство имен к физическому адаптеру с помощью моста (но, конечно, возможны и другие решения).

Обновление: из ядра 3.14 использование групп управления еще проще, как описано в этой статье. Ты должен:

1) определить контрольную группу net_cls для аннотирования пакетов из данного процесса с помощью classid (или группы процессов, обратите внимание, что между ними не должно быть никаких отношений родитель-потомок)

2) использовать модуль iptables cgroup (добавлен в Linux 3.14), чтобы пометить пакеты

3) использовать политику маршрутизации (ip rule add fwmark ....) для создания новой таблицы маршрутизации для помеченных пакетов

Преимущество состоит в том, что нам не нужно заниматься связующим звеном, и все намного динамичнее благодаря cgroups.

13

Я ооочень боролся с этим, так что вот ПОЛНОЕ решение. Это проверено на 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

3

Комбинируя превосходные ответы mariusmatutiae и KrisWebDev, я создал чрезвычайно измененную версию превосходного сценария KrisWebDev для novpn.sh . В то время как сценарий KrisWebDev предназначен для устранения более специфического зуда (запуск и перемещение процессов внутри / вне VPN), моя версия позволяет вам выполнять практически любую команду в сетевой среде, которую вы укажете. Вы можете указать интерфейс для привязки, маршрут по умолчанию, указать свои собственные правила iptables, статические маршруты, указать "тест", чтобы подтвердить, что все работает, как вы хотите, перед выполнением команды ... и т.д.). Он позволяет вам использовать несколько файлов конфигурации, чтобы вы могли определить любое количество конкретных сетевых сред, в которых вы можете запускать команды / процессы.

Я разместил это как суть здесь:https://gist.github.com/level323/54a921216f0baaa163127d960bfebbf0

Впоследствии он может даже очистить таблицы cgroup/iptables/routing!

Обратная связь приветствуется.

PS - Он предназначен для Debian 8 (Джесси)

2

Несколько человек написали прокладки, которые используют функцию LD_PRELOAD в Linux для достижения этой цели:

0

Не за приложение, нет. Вы можете сделать это для каждого порта или для каждого IP-адреса и т.д., Или само приложение может привязать (и использовать) определенную сетевую карту.

Вы не можете установить правило, чтобы сделать это, хотя.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .