Маршрутизация IP-трафика на основе процесса к различным маршрутам / интерфейсам по умолчанию
Я пытаюсь определить, возможно ли выборочно направлять IP-пакеты от процесса или группы процессов через определенный интерфейс, в то время как все другие пакеты маршрутизируются через другой интерфейс. То есть я хочу весь трафик с /usr/bin/testapp
проложить через eth1
в то время как все другие пакеты проходят eth0
, Пакеты в этом случае могут быть TCP, UDP, ICMP и т. Д. И могут быть настроены конечными пользователями для использования различных портов.
Поскольку я не могу легко заставить рассматриваемый процесс привязываться к определенному интерфейсу, я пытаюсь достичь того же результата с помощью маршрутизации. Это возможно?
--- редактировать ---
Благодаря полезному предложению здесь и во многих других местах стоит пометить пакеты на основе UID; это не совсем цель. Цель состоит в том, чтобы пометить / отфильтровать / проложить маршрут на основе процесса независимо от пользователя. То есть если alice
, bob
а также charlie
все запустить свой собственный экземпляр /usr/bin/testapp
; все пакеты из всех трех экземпляров должны пройти eth1
в то время как все другие пакеты из системы должны пройти eth0
,
Обратите внимание, что маркировка по порту источника / назначения, имени пользователя /UID и т. Д. Недостаточна, так как могут работать разные пользователи testapp
и они могут настроить разные порты в своих ~/.config/testapp.conf
или что угодно. Вопрос о фильтрации по процессу.
Один вариант, который доступен, хотя я не знаю, насколько он полезен, это использовать /bin/(ba|z)?sh
обертка вокруг родного двоичного файла.
--- редактировать ---
Я имею в виду маршрутизацию в системе с современным ядром Linux, скажем, 4.0 или выше. Если есть программные зависимости за пределами iproute2
, nftables
, conntrack
и подобные инструменты, я готов исследовать решения с открытым исходным кодом, хотя основные инструменты предпочтительнее.
5 ответов
Ваша маршрутизация пакетов через eth1 или eth0. Таблицы Мангл должны решить эту проблему. Для этого мне пришлось пометить пакеты и установить правила для их обработки. Сначала добавьте правило, в котором пакеты маршрутизации ядра помечаются как 2 через таблицу
ip rule add fwmark 2 table 3
Добавьте маршрут для перенаправления трафика через другой интерфейс, предполагая, что шлюз 10.0.0.1:
ip route add default via 10.0.0.1 table 3
Очистите ваш кэш маршрутизации.
ip route flush cache
Теперь установите правило брандмауэра для маркировки назначенных пакетов:
iptables -t mangle -A OUTPUT -p tcp --dport 465 -j MARK --set-mark 2
Наконец, ослабьте проверку источника обратного пути. Некоторые предлагают вам установить его на 0, но 2 кажется лучшим выбором в соответствии с https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
, Если вы пропустите это, вы получите пакеты (это можно подтвердить, используя tcpdump -i tap0 -n
), но пакеты не принимаются. Команда для изменения настройки, чтобы пакеты были приняты:
sysctl -w net.ipv4.conf.tap0.rp_filter=2
Ссылка: http://faultserver.ru/questions/345111/iptables-target-to-route-packet-to-specific-interface
Вы можете запустить процесс с определенным пользователем и сопоставить пакеты с iptables owner
расширение. После сопоставления вы можете пометить его и использовать с другой таблицей маршрутизации, используйте POSTROUTING
или любое другое решение, которое вам может понравиться.
Этот пост лучше объясняет соответствие пакетов с owner
,
Это возможно с использованием сетевых пространств имен для изоляции процесса и виртуального Ethernet-соединения для подключения этого сетевого пространства имен к вашему основному пространству имен. Затем вы можете использовать iptables для маршрутизации на основе этого источника.
Итак, вот пример. Я использую сетевой менеджер для некоторых команд, но вы можете сделать это в сыром виде.
# Create a namespace
ip netns add ns1
# create a bridge between them
nmcli connection add type veth ifname virt0 peer virt1
ip link set virt1 netns ns1
ip addr add 192.168.69.1/24 dev virt0
ip netns exec ns1 ip addr add 192.168.69.2/24 dev virt1
ip netns exec ns1 ip link up virt1
echo 1 > sudo tee /proc/sys/net/ipv4/ip_forward
# At this point traffic from ns1 will appear in your main network namespace as coming from ip 192.168.69.2 dev virt0, so you can handle it from there. You will need NAT to make it go somewhere useful.
# In this case I want the traffic to go out through interface vpn1, which is not a default route on my system.
# Add your process-specific routing rules in a non-default table (12345 in this case)
ip route add default dev vpn1 table 12345 proto static scope link metric 50
# Set up a rule to use that table for the traffic coming from that IP, with lower priority than the default table's rule.
ip rule add priority 30000 from 192.168.69.0/24 lookup 12345
# Add the nat, so that the traffic can actually exist on your outbound interface
iptables -t nat -A POSTROUTING -o vpn1 -j MASQUERADE
# At this point traffic from ns1 will go out through interface vpn1. Now you can run command sin that netns to utilize this.
nsenter --net=/var/run/netns/ns1 your_program
К сожалению, на man-странице расширений iptables ( http://ipset.netfilter.org/iptables-extensions.man.html) не указано ни одного модуля для полного удовлетворения ваших требований.
Я бы предложил то же самое, что и Mauricio López.
Вы могли бы setuid
или же setgid
целевое приложение для конкретного пользователя или группы, чтобы независимо от того, кто изначально запустил приложение, оно всегда выполнялось как определенный пользователь или группа):
adduser specialrouteuser
chown specialrouteuser: /usr/bin/testapp
chmod +s /usr/bin/testapp
а затем использовать Iptables owner
расширение, чтобы соответствовать этому конкретному UID или GID.
Это, конечно, может добавить другие проблемы или проблемы безопасности.
Ну, учитывая, что вы сказали нам:
Поскольку я не могу легко заставить рассматриваемый процесс привязываться к определенному интерфейсу, я пытаюсь достичь того же результата с помощью маршрутизации. Это возможно?
мы можем начать помогать вам с этого момента. Однажды во FreeBSD jail
Системный вызов появился с целью ограничить процесс или группу процессов каким-либо подразделом системных ресурсов. В частности, можно указать IP-адрес, который эти "изолированные" процессы будут использовать для своей сетевой активности. Это было так удобно, что я очень скучал по этой функции в Linux. Но у Linux также есть несколько способов добиться подобных результатов:
или, самое легкое, будет просто возиться с пространствами имен вручную: https://unix.stackexchange.com/questions/155446/linux-is-there-handy-way-to-exec-a-program-binding-it-to-ip-address-of-choice