Прокладіть трафік через певний інтерфейс для процесу в Linux


20

Чи можливо маршрутизувати трафік, який використовується процесом, через певний інтерфейс?

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

Чи можливе таке правило в Linux?

Відповіді:


22

Це можна зробити за допомогою мережевих просторів імен Linux.

Ось стаття, яка пояснює, як. В основному ви створюєте мережевий простір імен з іншим маршрутом за замовчуванням і запускаєте там потрібні процеси. Ви підключаєте новостворений простір імен мережі до фізичного адаптера за допомогою моста (але, звичайно, можливі й інші рішення).

Оновлення: з ядра 3.14 ще простіше використовувати контрольні групи, як описано в цій статті . Ти мусиш:

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

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

3) використовувати маршрутизацію політики (ip правило add fwmark ....), щоб створити нову таблицю маршрутизації для позначених пакетів

Перевага полягає в тому, що нам не потрібно займатися мостовою справою, і все набагато динамічніше завдяки групам.


14

Я так боровся з цим, ось ось ЦІЛЬНЕ рішення. Це тестується на 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

Посібник HowTo

Спочатку встановіть підтримку та інструменти для cgroup:

sudo apt-get install cgroup-lite cgmanager cgroup-tools

Перезавантажте (можливо, не потрібно).

Вам потрібні iptables 1.6 .0+. Отримайте джерело випуску iptables 1.6.0 , витягніть його, а потім запустіть це ( --disable-nftablesпрапор дозволить уникнути помилок) з iptables source dir:

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

Тепер ми припустимо, що інтерфейс, який ви хочете використовувати для конкретної програми, має eth0IP шлюз 10.0.0.1. Замініть їх тим, що ви дійсно хочете (отримайте інформацію від ip route). Запустити ще як корінь:

# 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

Або якщо ви хочете перемістити вже запущений процес у групу, ну ... ви не можете! Це, мабуть, пов’язано з функцією NAT (маскарад): iptables -nvL -t natне відповідає при переключенні групи, але 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 відповісти evolware статті за процес маршрутизації беруть 2: з допомогою контрольних груп, IPTables і політики маршрутизації , Як зробити процес конкретного НЕ відбувається за допомогою бездротової технології OpenVPN? , Kill перемикач для OpenVPN на основі iptables


Дякую за чудову відповідь, як змусити його працювати з апачем? Я спробував cgexec -g net_cls:novpn apache2і подав мені весь список змінних невизначених помилок!
razzak

2
Ви отримаєте ті самі помилки, запустивши apache2безпосередньо з терміналу. Це тому apache2, що зазвичай запускається як послуга, з systemctl start apache2. Однак це не спрацює cgexec. apache2Викликана програма повинна бути батьком потрібного ( ) процесу для поширення групи net_cls. Тож вам потрібно знайти сценарій запуску. У цьому випадку це sudo cgexec -g net_cls:novpn /usr/sbin/apache2ctl start. Перевірте ./novpn.sh --list.
KrisWebDev

Він більше не працює в ubuntu 16.04!
razzak

2
Я використовую його на Ubuntu 16.04, і він працює чудово. Імена інтерфейсу змінилися в Ubuntu 16, можливо, вам потрібно замінити eth0щось на зразок enp7s0. Отримати інформацію з ifconfigкоманди.
KrisWebDev

Дякую. Але він не працює на Ubuntu 18.04, оскільки cpmanager був видалений через конфлікт із systemd
skonsoft


3

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

Я розмістив це як суть тут: https://gist.github.com/level323/54a921216f0baaa163127d960bfebbf0

Після цього він навіть може прибрати таблицю cgroup / iptables / маршрутизації!

Зворотній зв'язок Ласкаво просимо.

PS - Розроблено для Debian 8 (Jessie)


Привіт @allnatural, я хотів би використовувати ваш сценарій altnetworking.sh, але що я повинен вкласти у файл конфігурації?
Cris70

0

Ні за заявку, ні. Ви можете це робити за порт або за ip-адресою тощо, або сама програма може прив’язати до (та використовувати) певну мережеву карту.

Ви не можете налаштувати правило, щоб це зробити.


У мене програма Java, чи можливо прив'язати цю програму до інтерфейсу?
Суреш

Додаток Java, для якого ви маєте вихідний код і може перепрограмувати внутрішні програми?
Majenko

У мене є вихідний код програми Java, який використовує бібліотеку apache http.
Суреш

Тоді я би звернувся до stackoverflow.com і запитав там програмістів, як змінити вашу програму. Я ніколи не програмував на Java.
Majenko
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.