Jump to content
Калькуляторы

iptables -j ROUTE в каком дистрибутиве linux это есть?

Нужен дистрибутив linux, в котором у iptables есть -j ROUTE.

 

Дело в том, что начиная с какого-то момента -j ROUTE признали идеалогически неверным и связка (iptables -j MARK+ip rule+несколько таблиц маршрутизации(iproute2)) считается якобы универсальна, но я никак не могу понять как обойти правило "0: from all lookup local" (ip rule list).

 

В кратце задача такова: если приложение запущено от пользователя xxx, то ВЕСЬ трафик выпускать через шлюз xx.xx.xx.xx через сабинтерфейс eth0.xxx. Вроде бы всё хорошо, метим трафик через iptables, в ip rule создаём правило, что использовать такую-то таблицу маршрутизации и всё отлично, НО(!), если попингать ip, который висит на любом из сабов этого же сервера, то всегда срабатывает правило "0: from all lookup local" и трафик замыкается локально, а не идёт на нужный мне шлюз xx.xx.xx.xx. На вопрос зачем это надо - сразу отвечу, что есть много пересекающихся адресных пространств(vrf'ов), до хостов этих vrf'ов нужно получить доступ по ip из одной точки(с linux-сервера), вот и получается, что в каком-то(или даже нескольких) vrf'е(ах) есть ip 10.1.1.1 и такой же ip навешан на одном из сабов сервера.

Share this post


Link to post
Share on other sites
В кратце задача такова: если приложение запущено от пользователя xxx, то ВЕСЬ трафик выпускать через шлюз xx.xx.xx.xx через сабинтерфейс eth0.xxx.

...

НО(!), если попингать ip

пинг не идёт от пользователя ххх, проверяйте телнетом может.
Edited by voron

Share this post


Link to post
Share on other sites
А в чём проблема собрать из сырцов-то ?

В том, что этот патч выпилен из последних patch-o-matic, а старый на новый netfilter не накладывается

 

пинг не идёт от пользователя ххх, проверяйте телнетом может.

да, сейчас чаще всего встречается суидный бит на /bin/ping, но можно его снять и установить capability CAP_NET_RAW (утилита setcap), после чего пинг будет работать не от рута, а от обычного пользователя

 

Share this post


Link to post
Share on other sites
Дело в том, что начиная с какого-то момента -j ROUTE признали идеалогически неверным и связка (iptables -j MARK+ip rule+несколько таблиц маршрутизации(iproute2)) считается якобы универсальна, но я никак не могу понять как обойти правило "0: from all lookup local" (ip rule list).

А почему нельзя перенести это правило с 0 на 10000 и вставить нужные правила перед этим, а нулевое удалить ? Сам не пробовал, но этопервое, что приходит в голову при условии, что в принципе подход "iptables -j MARK+ip rule+несколько таблиц маршрутизации(iproute2)" устраивает - надо лишь обойти правило номер ноль :-).

 

А если получится, то можно развить идею: найти роут демон, который умеет заносить маршруты в разные таблицы. bird вроде умеет, но чё-то это ИМХО глючное создание. Можно поискать патчи для quagga - фактически самый адекватный роутер из опенсорс, т.е. реальной альтернативы не существует. Но если bird устроит, то почему бы и нет ?

 

А если и это получится - здравствуй true vrf :-).

Edited by wtyd

Share this post


Link to post
Share on other sites

>А почему нельзя перенести это правило с 0 на 10000 и вставить нужные правила перед этим, а нулевое удалить ?

 

Вот уж не знаю почему, видимо кто-то когда посчитал, что их правило номер 0 не подлежит какой-либо критике. В мане пишут как-то так:

 

At startup time the kernel configures the default RPDB consisting of three rules:

 

1.

Priority: 0, Selector: match anything, Action: lookup routing table local (ID 255). The local table is a special routing table containing high priority control routes for local and broadcast addresses.

Rule 0 is special. It cannot be deleted or overridden.

 

 

Была идея править таблицу 255(local), но если из неё что-либо удалять и/или перемещать в другие таблицы, то просто сеть перестаёт работать и спасает только перезагрузка

Share this post


Link to post
Share on other sites
>А почему нельзя перенести это правило с 0 на 10000 и вставить нужные правила перед этим, а нулевое удалить ?

 

Вот уж не знаю почему, видимо кто-то когда посчитал, что их правило номер 0 не подлежит какой-либо критике. В мане пишут как-то так:

 

At startup time the kernel configures the default RPDB consisting of three rules:

 

1.

Priority: 0, Selector: match anything, Action: lookup routing table local (ID 255). The local table is a special routing table containing high priority control routes for local and broadcast addresses.

Rule 0 is special. It cannot be deleted or overridden.

# ip ru

200: from all lookup local

220: from all lookup 220

32766: from all lookup main

32767: from all lookup default

 

Это я сделал ip ru a from all table local pref 200 ; ip ru del pref 0. Вроде пока ничего не сломалось - интырнет работает. 220 это описекас у меня так сделал :-). По-скольку, таблиц всего 255 то имеет смысл столько же первых правиил (минус три) выделить под наши vrf и сделать соотетствие номера vrf номеру правила и номеру таблицы. Ну это я теоретизировать взялся снова :-).

 

Пожалуйста, всё-таки попробуйте так сделать. Я так понял, у вас есть работающая инсталляция софта, которая уже почти vrf, у меня такой нет, так бы я сам попробовал. Ну и хотелось бы от вас потом результат узнать.

 

Share this post


Link to post
Share on other sites

Очень интересно. Попробую - отпишусь что получилось. Кстати, таблиц не 255, по крайней мере у меня есть таблица с номером 2010.

Share this post


Link to post
Share on other sites
Очень интересно. Попробую - отпишусь что получилось. Кстати, таблиц не 255, по крайней мере у меня есть таблица с номером 2010.

Это точно не номер правила ? Если так, то тоже очень интересная информация :-).

Share this post


Link to post
Share on other sites

Не удаляется правило номер 0:

 

# ip ru del pref 0

RTNETLINK answers: Operation not permitted

 

 

У Вас какое ядро?

 

>Это точно не номер правила ? Если так, то тоже очень интересная информация :-).

 

Точно не номер правила:

# ip route list table 2010

default via 10.12.10.49 dev eth1.3

Share this post


Link to post
Share on other sites
Не удаляется правило номер 0:

 

# ip ru del pref 0

RTNETLINK answers: Operation not permitted

 

 

У Вас какое ядро?

 

>Это точно не номер правила ? Если так, то тоже очень интересная информация :-).

 

Точно не номер правила:

# ip route list table 2010

default via 10.12.10.49 dev eth1.3

# uname -a

Linux warm2 2.6.33-ARCH #1 SMP PREEMPT Mon Apr 26 19:31:00 CEST 2010 x86_64 AMD Athlon 64 Processor 3000+ AuthenticAMD GNU/Linux

 

# pacman -Ss kernel26

core/kernel26 2.6.33.3-1 (base)

The Linux Kernel and modules

 

 

Дистрибутивное ядро.

 

Share this post


Link to post
Share on other sites

wtyd, спасибо большое! Обновил на своей десктопной машине ядро с 2.6.31 до 2.6.33, предварительно всё работает. Скоро соберу тестовый стенд и всё проверю, нет ли ещё каких нюансов по "созданию" полноценных vrf.

Share this post


Link to post
Share on other sites
wtyd, спасибо большое! Обновил на своей десктопной машине ядро с 2.6.31 до 2.6.33, предварительно всё работает. Скоро соберу тестовый стенд и всё проверю, нет ли ещё каких нюансов по "созданию" полноценных vrf.

Это плохой признак, что в 2.6.31 это не работает, а в 2.6.33 работает - как бы обратно не исправили. Я надеялся, что у вас версия ядра значительно старше :). Изучать гору ченджлогов нет никакого настроения ...

Share this post


Link to post
Share on other sites

В итоге всё получилось. Ядро должно быть обязательно 2.6.33(возможно, на старших будет работать), т.к. можно удалить правило номер 0(ip rule del pref 0) и ещё добавили нужную фичу accept_local(см. http://git.kernel.org/?p=linux/kernel/git/...32002e46d3f504a )

 

Тестовая схема: test7200 Fa1/0 <-> server eth1

на сервере eth0 ip 1.1.1.2/30, default gw 1.1.1.1(таблица main)

Если в глобальной таблице не будет маршрута по умолчанию, то почти ничего работать не будет, т.к. source ip выбирается на основе главной таблицы и если не будет хоть какого-нибудь маршрута в таблице main к нужной сети, то получим network unreachable.

 

Конфиг cisco:

hostname test7200
ip vrf test2
  rd 100:2
ip vrf test3
  rd 100:3
ip vrf test4
  rd 100:4
interface Loopback2
  ip vrf forwarding test2
  ip address 192.168.3.2 255.255.255.255
interface Loopback3
  ip vrf forwarding test3
  ip address 192.168.2.2 255.255.255.255
interface Loopback4
  ip vrf forwarding test4
  ip address 192.168.2.4 255.255.255.255
interface FastEthernet1/0
  no ip address
  duplex auto
  speed auto
interface FastEthernet1/0.2
  encapsulation dot1Q 2
  ip vrf forwarding test2
  ip address 192.168.2.1 255.255.255.252
interface FastEthernet1/0.3
  encapsulation dot1Q 3
  ip vrf forwarding test3
  ip address 192.168.3.1 255.255.255.252
interface FastEthernet1/0.4
  encapsulation dot1Q 4
  ip vrf forwarding test4
  ip address 192.168.2.1 255.255.255.252

 

На сервере:

Задача в том, чтобы запереть пользователя test2(uid 2002 gid 2002) в vrf test2, test3(2003/2003) в vrf 2003 и т.д., а также, чтобы все входящие соединения с vlan2 выходили через vlan2 и т.д.

 

0. Таблицы маршрутизации

# cat /etc/iproute2/rt_tables

255    local
254    main
253    default
0    unspec
2    test2
3    test3
4    test4

 

1. Сабинтерфейсы на сервере(такое именование для совместимости со SLES):

modprobe 8021q
vconfig set_name_type VLAN_PLUS_VID_NO_PAD
ifconfig eth1 0.0.0.0
vconfig add eth1 2
vconfig add eth1 3
vconfig add eth1 4
ifconfig vlan2 192.168.2.2 netmask 255.255.255.252
ifconfig vlan3 192.168.3.2 netmask 255.255.255.252
ifconfig vlan4 192.168.2.2 netmask 255.255.255.252

 

Таблица main(на сервере) теперь выглядет так:

# ip route sh

192.168.3.0/30 dev vlan3 proto kernel scope link src 192.168.3.2

192.168.2.0/30 dev vlan2 proto kernel scope link src 192.168.2.2

192.168.2.0/30 dev vlan4 proto kernel scope link src 192.168.2.2

1.1.1.0/30 dev eth0 proto kernel scope link src 1.1.1.2

default via 1.1.1.1 dev eth0

 

2. Политики маршрутизации:

ip rule add from all lookup local pref 30000
#зачем удалять политику номер 0 - см. выше в теме
ip rule del pref 0
ip rule add fwmark 2002 lookup test2 pref 2002
ip rule add fwmark 2003 lookup test3 pref 2003
ip rule add fwmark 2004 lookup test4 pref 2004

 

3. Маршруты:

#!/bin/bash
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do
  echo 0 > $i 
done
for i in /proc/sys/net/ipv4/conf/*/accept_local; do
  echo 1 > $i 
done
ip route flush table test2
ip route flush table test3
ip route flush table test4
ip route add 0.0.0.0/0 via 192.168.2.1 dev vlan2 table test2
ip route add 0.0.0.0/0 via 192.168.3.1 dev vlan3 table test3
ip route add 0.0.0.0/0 via 192.168.2.1 dev vlan4 table test4
ip route flush cache
ip route flush cache table test2
ip route flush cache table test3
ip route flush cache table test4

4. фаервол:

iptables -t mangle -F
iptables -F
iptables -t nat -F

#помечаем трафик от пользователя test номером 2002, чтобы решение о маршрутизации принималось по таблице test2
iptables -t mangle -A OUTPUT -m owner --gid-owner test2 -j MARK --set-mark 2002
iptables -t mangle -A OUTPUT -m owner --gid-owner test2 -j ACCEPT
#замена source ip(см. комментарий выше)
iptables -t nat -A POSTROUTING -m mark --mark 2002 ! -s 192.168.2.2 -o vlan2 -j SNAT --to-source 192.168.2.2
#запоминаем трафик, пришедший с vlan2 и даём ему номер 2002
iptables -t mangle -A INPUT -i vlan2 -j CONNMARK --set-mark 2002
#трафик, порождённый трафиком с номером 2002 передаём через vlan2(restore-mark маркирует обычным mark'ом и срабатывает политика маршрутизации "ip rule add fwmark 2002 lookup test2 pref 2002")
iptables -t mangle -A OUTPUT -m connmark --mark 2002 -j CONNMARK --restore-mark

iptables -t mangle -A OUTPUT -m owner --gid-owner test3 -j MARK --set-mark 2003
iptables -t mangle -A OUTPUT -m owner --gid-owner test3 -j ACCEPT
iptables -t nat -A POSTROUTING -m mark --mark 2003 ! -s 192.168.3.2 -o vlan3 -j SNAT --to-source 192.168.3.2
iptables -t mangle -A INPUT -i vlan3 -j CONNMARK --set-mark 2003
iptables -t mangle -A OUTPUT -m connmark --mark 2003 -j CONNMARK --restore-mark

iptables -t mangle -A OUTPUT -m owner --gid-owner test4 -j MARK --set-mark 2004
iptables -t mangle -A OUTPUT -m owner --gid-owner test4 -j ACCEPT
iptables -t nat -A POSTROUTING -m mark --mark 2004 ! -s 192.168.2.2 -o vlan4 -j SNAT --to-source 192.168.2.2
iptables -t mangle -A INPUT -i vlan4 -j CONNMARK --set-mark 2004
iptables -t mangle -A OUTPUT -m connmark --mark 2004 -j CONNMARK --restore-mark

Можно насоздавать своих цепочек для красоты и т.д.(правила iptables -t mangle -A OUTPUT -m owner --gid-owner testX -j ACCEPT не обязательны(используется для корректного подсчёта пакетов))

 

Тестирование:

icmp:

test7200#ping vrf test2 192.168.2.2 source 192.168.2.1 - 100%
test7200#ping vrf test2 192.168.2.2 source 192.168.3.2 - 100%
test7200#ping vrf test3 192.168.3.2 source 192.168.3.1 - 100%
test7200#ping vrf test3 192.168.3.2 source 192.168.2.2 - 100%
test7200#ping vrf test4 192.168.2.2 source 192.168.2.1 - 100%
test7200#ping vrf test4 192.168.2.2 source 192.168.2.4 - 100%

 

tcp:

root@serv:~# echo hello > 1
root@serv:~# nc -l 23 < 1
test7200#telnet 192.168.2.2 /vrf test2 /source-interface loopback 2
Trying 192.168.2.2 ... Open
hello

[Connection to 192.168.2.2 closed by foreign host]

 

другие комбинации telnet ipX /vrf Y /source-interface Z - тоже всё ок

 

Трафик, исходящий от сервера:

root@serv:~# chmod u-s /bin/ping
root@serv:~# setcap cap_net_raw+ep /bin/ping
root@serv:~# su - test2
test2@serv:~$ ping 192.168.3.2 - 100%, ttl=255=cisco(если бы пингался локальный интерфейс, то было бы 64)
test2@serv:~$ telnet 192.168.3.2
Trying 192.168.3.2...
Connected to 192.168.3.2.
Escape character is '^]'.


Password required, but none set
Connection closed by foreign host.

 

От других пользователей тоже всё как ожидалось: и пинги и tcp.

 

Может кто покритикует?(особенно в плане SNAT и CONNMARK - чем это может обернуться?)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this