s.lobanov Posted May 6, 2010 · Report post Нужен дистрибутив 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 навешан на одном из сабов сервера. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
1GE Posted May 6, 2010 · Report post Врядли он где-то есть в составе дистра, так как это часть path-o-matic-а iptables. http://www.iptables.org/projects/patch-o-m...-external-ROUTE А в чём проблема собрать из сырцов-то ? Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
voron Posted May 6, 2010 (edited) · Report post В кратце задача такова: если приложение запущено от пользователя xxx, то ВЕСЬ трафик выпускать через шлюз xx.xx.xx.xx через сабинтерфейс eth0.xxx. ... НО(!), если попингать ip пинг не идёт от пользователя ххх, проверяйте телнетом может. Edited May 6, 2010 by voron Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
s.lobanov Posted May 7, 2010 · Report post А в чём проблема собрать из сырцов-то ? В том, что этот патч выпилен из последних patch-o-matic, а старый на новый netfilter не накладывается пинг не идёт от пользователя ххх, проверяйте телнетом может. да, сейчас чаще всего встречается суидный бит на /bin/ping, но можно его снять и установить capability CAP_NET_RAW (утилита setcap), после чего пинг будет работать не от рута, а от обычного пользователя Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
wtyd Posted May 7, 2010 (edited) · Report post Дело в том, что начиная с какого-то момента -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 May 7, 2010 by wtyd Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
s.lobanov Posted May 7, 2010 · Report post >А почему нельзя перенести это правило с 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), но если из неё что-либо удалять и/или перемещать в другие таблицы, то просто сеть перестаёт работать и спасает только перезагрузка Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
wtyd Posted May 8, 2010 · Report post >А почему нельзя перенести это правило с 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, у меня такой нет, так бы я сам попробовал. Ну и хотелось бы от вас потом результат узнать. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
s.lobanov Posted May 8, 2010 · Report post Очень интересно. Попробую - отпишусь что получилось. Кстати, таблиц не 255, по крайней мере у меня есть таблица с номером 2010. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
wtyd Posted May 8, 2010 · Report post Очень интересно. Попробую - отпишусь что получилось. Кстати, таблиц не 255, по крайней мере у меня есть таблица с номером 2010. Это точно не номер правила ? Если так, то тоже очень интересная информация :-). Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
s.lobanov Posted May 8, 2010 · Report post Не удаляется правило номер 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 Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
wtyd Posted May 8, 2010 · Report post Не удаляется правило номер 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 Дистрибутивное ядро. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
s.lobanov Posted May 8, 2010 · Report post wtyd, спасибо большое! Обновил на своей десктопной машине ядро с 2.6.31 до 2.6.33, предварительно всё работает. Скоро соберу тестовый стенд и всё проверю, нет ли ещё каких нюансов по "созданию" полноценных vrf. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
wtyd Posted May 9, 2010 · Report post wtyd, спасибо большое! Обновил на своей десктопной машине ядро с 2.6.31 до 2.6.33, предварительно всё работает. Скоро соберу тестовый стенд и всё проверю, нет ли ещё каких нюансов по "созданию" полноценных vrf. Это плохой признак, что в 2.6.31 это не работает, а в 2.6.33 работает - как бы обратно не исправили. Я надеялся, что у вас версия ядра значительно старше :). Изучать гору ченджлогов нет никакого настроения ... Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
s.lobanov Posted May 10, 2010 · Report post В итоге всё получилось. Ядро должно быть обязательно 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 - чем это может обернуться?) Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...