iptables - націлити на маршрутизацію пакету до певного інтерфейсу?


25

Мій домашній сервер має два основних інтерфейси eth1(стандартне підключення до Інтернету) та tun0(тунель OpenVPN). Я б хотів використати, iptablesщоб змусити всі пакети, згенеровані локальним процесом, що належить UID 1002, вийти через tun0, а всі інші пакети - вийти через eth1.

Я можу легко позначити збігаються пакети:

iptables -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11

Тепер я хотів би встановити якесь правило у ланцюжку POSTROUTING (ймовірно, таблиці mangle), щоб відповідати пакетам, позначеним 11, і відправити їх tun0, а потім правилом, яке відповідає всім пакетам та надсилати їх eth1.

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

Чи здатні на це iptables? Чи потрібно замість цього возитися із таблицею маршрутизації (через ip routeабо лише застарілі routeкоманди)?

Редагувати: Я думав, що, можливо, я повинен надати більше інформації. Інших правил iptables в даний час у мене немає (хоча я можу створити деякі правила для виконання незв'язаних завдань у майбутньому). Також вихід ip route:

default via 192.168.1.254 dev eth1  metric 203
10.32.0.49 dev tun0  proto kernel  scope link  src 10.32.0.50
85.17.27.71 via 192.168.1.254 dev eth1
192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.73  metric 203

Я не торкнувся таблиці маршрутизації - саме так вона є в даний час (хоча це виглядає досить брудно). Вибачте, але у мене не встановлена ​​застаріла routeкоманда на цій машині.

І вихід ip addr(звичайно, eth0 та eth2 можна ігнорувати - це NIC, які зараз не використовуються):

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 1c:6f:65:2a:73:3f brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast     state UP qlen 1000
    link/ether 00:1b:21:9d:4e:bb brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.73/24 brd 192.168.1.255 scope global eth1
    inet6 fe80::21b:21ff:fe9d:4ebb/64 scope link
       valid_lft forever preferred_lft forever
4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 00:1b:21:6a:c0:4b brd ff:ff:ff:ff:ff:ff
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc     pfifo_fast state UNKNOWN qlen 100
    link/none
    inet 10.32.0.50 peer 10.32.0.49/32 scope global tun0

Редагувати: я щось почав працювати, але відмічені пакети не пересилають до tun0. В основному я додав таблицю (11) і використав:

ip route add table 11 via 10.32.0.49 dev tun0
ip rule add priority 10000 fwmark 11 table 11

Коли я просто sudo -u user1000 wget -qO- whatismyip.orgотримую зовнішню IP-адресу свого будинку, але якщо це зробити sudo -u user1002 wget -qO- whatismyip.org, я також отримую IP-адресу свого будинку (але я повинен отримувати IP на іншому кінці тунелю OpenVPN).

Запуск iptables -vLпідтверджує, що пакети узгоджуються з правилом маркування, але, здається, вони не відповідають правилу маршрутизації.

EDIT: Я давно витрачав на це питання, і хоча це все ще не працює, я думаю, що я трохи ближче.

Правило iptables повинно знаходитись у mangleланцюзі вихідних даних таблиці. Я думаю, що мені також потрібне правило MASQUERADE у natланцюжку розсилки таблиці, щоб встановити адресу джерела. Однак перенаправлення, що виникає після виходу з ладу OUTPUT, працює неправильно.

Я витратив на це зараз 5 годин, тож я роблю перерву і, ймовірно, повернусь до неї пізніше сьогодні ввечері або десь завтра.

Відповіді:


26

Нещодавно я потрапив у подібну проблему, хоча і дещо іншу. Я хотів маршрутизувати тільки порт 25 TCP (SMTP) через інтерфейс OpenVPN tap0, одночасно перенаправляючи весь інший трафік (навіть для того ж хоста) через інтерфейс за замовчуванням.

Для цього мені довелося позначити пакети та встановити правила поводження з ним. Спочатку додайте правило, за допомогою якого пакети маршруту ядра позначаються 2через таблицю 3(пояснено далі):

ip rule add fwmark 2 table 3

Ви могли б додати символічне ім'я /etc/iproute2/rt_tables, але я цього не намагався зробити. Число 2і 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

Наведене вище правило застосовується лише в тому випадку, якщо пакети надходять з локальної машини. Дивіться http://inai.de/images/nf-packet-flow.png . Підлаштовуйте його під свої вимоги. Наприклад, якщо ви хочете лише маршрутизувати вихідний трафік HTTP через tap0інтерфейс, змініть 465 на 80.

Щоб запобігти передачі пакетів через tap0отримання вашої локальної адреси в якості вихідного IP, скористайтеся наступним правилом, щоб змінити його на адресу вашого інтерфейсу (припускаючи 10.0.0.2IP-адресу для інтерфейсу tap0):

iptables -t nat -A POSTROUTING -o tap0 -j SNAT --to-source 10.0.0.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

Чому ви використовуєте SNAT замість MASQUERADE? Хіба MASQUERADE не робить те ж саме, за винятком того, що IP-адреса збирається з інтерфейсу під час "виконання" та не жорстко кодується у конфігураційний файл?
Етан

6
@Ethan From man iptables: Він повинен використовуватися лише з динамічно призначеними IP (комутованими) з'єднаннями: якщо у вас статична IP-адреса, ви повинні використовувати ціль SNAT. Маскарадінг еквівалентний вказуванню відображення на IP-адресу інтерфейсу, що пакет виходить, але також має наслідком того, що підключення забуваються, коли інтерфейс виходить з ладу. Ви маєте рацію, але оскільки мій IP ніколи не зміниться, я вирішив використовувати SNAT за рекомендацією manpage.
Лекенштейн

Я думаю (хоча і не перевірено) останній крок (перевірка джерела зворотного шляху) не потрібен. Ви можете просто додати ще одне правило до PREROUTINGланцюга до DNATправильної адреси джерела (відповідно до шлюзу за замовчуванням).
Крістіан Вольф

7

Я це вирішив. Проблема була з маршрутизацією правил в таблиці 11. Таблиця 11 була отримати удар, але правила маршрутизації зробити його непрацездатним. Цей сценарій - це те, що я зараз використовую, і він, здається, працює добре (хоча він, очевидно, специфічний для моєї установки). Також я створив нову таблицю 21, присвячену основній висхідній лінії зв'язку (eth1).

# Add relevant iptables entries.
iptables -t mangle -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

# Flush ALL THE THINGS.
ip route flush table main
ip route flush table 11
ip route flush table 21
ip rule flush

# Restore the basic rules and add our own.
ip rule add lookup default priority 32767
ip rule add lookup main priority 32766
ip rule add fwmark 11 priority 1000 table 11
# This next rule basically sends all other traffic down eth1.
ip rule add priority 2000 table 21

# Restore the main table.  I flushed it because OpenVPN does weird things to it.
ip route add 127.0.0.0/8 via 127.0.0.1 dev lo
ip route add 192.168.1.0/24 dev eth1 src 192.168.1.73
ip route add default via 192.168.1.254

# Set up table 21.  This sends all traffic to eth1.
ip route add 192.168.1.0/24 dev eth1 table 21
ip route add default via 192.168.1.254 dev eth1 table 21

# Set up table 11.  I honestly don't know why 'default' won't work, or
# why the second line here is needed.  But it works this way.
ip route add 10.32.0.49/32 dev tun0 table 11
ip route add 10.32.0.1 via 10.32.0.50 dev tun0 table 11
ip route add 0.0.0.0/1 via 10.32.0.50 dev tun0 table 11

ip route flush cache

## MeanderingCode редагування (оскільки я поки не можу коментувати)

Дякую за цю відповідь! Схоже, це може заплутатися, оскільки вам доведеться тут підтримувати інформацію про маршрут (можливо, дублювання або порушення інших речей, які можуть захотіти встановити маршрути.

Можливо, у вашій таблиці маршрутизації з OpenVPN спостерігаються "дивні речі", оскільки сервер налаштований на "натискання" маршрутів, що дозволяє весь трафік проходити через мережевий інтерфейс VPN, а не "голий" Інтернет. Або ваш конфігурація OpenVPN, або будь-який сценарій / додаток, який він встановлює, це встановлення маршрутів.

У першому випадку, ви можете змінити конфігурацію OpenVPN і помістити в рядку , що містить «рут-nopull»
В останній, конфігурації перевірки для OpenVPN або будь-обгортки (мережі-менеджер-OpenVPN, наприклад , на багатьох сучасних настільну Linux дистрибутивів)
в системі в будь-якому випадку, усунення конфігурації маршрутизації, коли вона встановлюється, чистіша та безпечніша, ніж миття таблиці, залежно від того, коли ви запускаєте цей сценарій та що ще робить ваша система.

Ура!


2

Я думаю, ти хочеш:

/sbin/ip route add default via 10.32.0.49 dev tun0 table 11
/sbin/ip rule add priority 10000 fwmark 11 table 11

http://lartc.org/howto/lartc.netfilter.html

Але я не перевіряв вищесказане.


Перша команда повертає "Помилка: або" до "є дублікатом, або" 10.32.0.49 "є сміттям."
Етан

Вибачте, забув через проміжку за замовчуванням та IP.
mfarver

Я спробував це. Здається, це має такий же ефект, як і defaultвилучення ключового слова.
Етан

Для усунення параметрів ви можете спробувати зробити захоплення пакетів на tun0 і побачити, чи закінчуються пакети в цьому інтерфейсі. tcpdump -i tun0 .. або ж вам потрібно базувати його на ідентифікаторі користувача? Чи можете ви просто зробити це на основі IP-адреси призначення (простіше)? маршрут add <віддалений хост> через 10.32.0.49
mfarver

Я не можу базуватися, якщо вимкнути IP-адресу призначення - таких було б багато. Я також теоретично міг би базувати його на pid, але це ще складніше, тому що я не знаю pid до початку демона.
Етан

0

Це можна зробити без команди iptables Виконати просту команду ip

Для uid 1002:

ip rule add uidrange 1002-1002 table 502

Додайте маршрут за замовчуванням до таблиці 502 через інтерфейс, який ви хочете сказати

eth0 ip rule add default via a.b.c.d dev eth0

Я перевірив цю команду, і вона не спрацювала:Error: argument "uidrange" is wrong: Failed to parse rule type
kasperd

@kasperd Ви повинні бути, що він робив це неправильно, тому що це добре працює для мене.
horseyguy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.