Linux: не работает advanced routing
Версия для печати

Конференция: Конференция iXBT.com (http://forum.ixbt.com/)
Форум: Программы: Unix-like системы (http://forum.ixbt.com/?id=76)
URL: http://forum.ixbt.com/topic.cgi?id=76:9522



KB, 02.06.2010 13:53
Есть на сервере два канала - основной и резервный, через GPRS.
Хочется мне чтобы через резервный канал висел всегда проброшеный openvpn-туннель до другого сервера, на случай ядерной войны Но весь остальной траффик до этого сервера шёл через основной канал. Т.е. зарулить только определнный порт через GPRS.

Делал так:
код:

# iptables -t mangle -A OUTPUT -d 1.1.1.1 -p tcp --dport 1196 -j MARK --set-mark 1196

Пакеты маркируются:
# iptables -t mangle -L -nv | grep 1196
8 444 MARK tcp -- * * 0.0.0.0/0 1.1.1.1 tcp dpt:1196 MARK set 0x4ac

# ip route add default dev ppp64 table GPRS
# ip rule add fwmark 1196 table GPRS

Но при этом соединение на 1196 порт идет один фиг через основной канал.
Или такой механизм реализовать можно только если пакеты маркировать в PREROUTING? Но проблема в том, что пакеты от самого хоста, а не те, которые он форвардит, туда вообще не попадают.

1. SuSt, 02.06.2010 16:01
KB
код:
ip rule add fwmark 1196 table GPRS

Посмотри, по умолчанию твое новое правило "встанет" после таблицы main, а в таблице main наверняка есть default gw, вот на него все и пойдет.

Сделай
код:
ip rule ls

посмотри какой приоритет будет у таблицы main, и модифицируй команду добавления правила
код:
ip rule add fwmark 1196 table GPRS prio бла-бла-бла

где "бла-бла-бла" должно быть меньше чем приоритет таблицы main.

2. KB, 03.06.2010 17:52
Да не, оно по умолчанию фигачилось с меньшим приоритетом, так что всё ОК. Но дело в том, что пакеты нужно маркировать в PREROUTING, чтобы они обрабатывались в ip rule fwmark, а пакеты, отправленные с самого сервера (а не пропущенные через НАТ) в PREROUTING не попадают. Вот такая петрушка. Так что пришлось заюзать через-пень-колодный метод, запуская openvpn из /etc/ppp/ip-up и скармливая ему в качестве айпишника для исходящих коннектов, тот, что получил pppd. Плюс там же добавляем правило ip rule from IP table GPRS... Криво, но работает.

3. SuSt, 04.06.2010 15:14
Забавно-с. Даже и не ожидал, что в Linux в-принципе могут быть такие досадные неприятности. Какие-то уж слишком странные на мой взгляд грабли на ровном месте.

Теоретически OpenVPN можно "повесить" на dummy-интерфейс со своим "статичным" ip-шником и прописАть жестко маршрутизацию через GPRS с этого IP. Тогда не нужно будет "дергать" ppp/ip-up.

4. -Sorcerer-, 04.06.2010 20:19
SuSt
Даже и не ожидал, что в Linux в-принципе могут быть такие досадные неприятности.

Ессно никаких неприятностей нет, есть непонимание работы netfilter топикстартером.
Routing decision принимается до выхода пакета если его origin - localhost.
Так работает любой раутер.

5. KB, 04.06.2010 20:55
-Sorcerer-
Ну так как реализовать правильно данный механизм, о всезнающий
До выхода пакета откуда-куда? До цепочки OUTPUT имеется в виду?

6. borispr, 04.06.2010 21:01
Я чета не понял, к чему такие сложности? OpenVPN же поднимает коннект не хрен знает куда по 1196, а на вполне конкретный IP. Так чем статик рут на этот IP не устраивает?

7. -Sorcerer-, 04.06.2010 22:03
KB
Ну так как реализовать правильно данный механизм, о всезнающий

Правильно - никак.
Ибо ничего правильного в попытке вмешательства в локальную таблицу быть не может, по-определению.

Добавление от 04.06.2010 22:11:

KB
До цепочки OUTPUT имеется в виду?

Да, решение о локальности пакета наступает раньше, чем он поступает в любое правило/цепочку нетфильтра.
Возвратить его обратно - никак нельзя.
Если же хочется "во что бы ты не стало" то можно через patch-o-matic-ng поставить таргет ROUTE и направить через него.

8. SuSt, 04.06.2010 22:48
borispr
Так чем статик рут на этот IP не устраивает?
Дык хочется зарутить только один порт, а не все подряд на этот IP.

KB
Кстати, насчет "-j ROUTE" - тоже мысль. Хотя лично я не проверял как оно работает. Сам тоже все метками, метками...

9. KB, 04.06.2010 23:20
-Sorcerer-
Ну вот как бы казалось простая задача, а решения нет. Пакеты все локальные, делай что хочу, ан нет. Эдакий design flaw

borispr
Да, нужен только один TCP порт, остальное на этот айпи - через основной канал, т.к. там еще много чего

SuSt
Да как-то не хочется от ванильного ядра отходить, пущай работает как есть, а там, если в mainline добавят - будем пробовать.

На лоре еще советовали NATить локальные пакеты, тоже пока не проверял, ибо выглядит как-то дико и per rectum

10. -Sorcerer-, 05.06.2010 00:34
KB
Пакеты все локальные, делай что хочу, ан нет. Эдакий design flaw

Ну да, правда такой "design flaw" присутствует во всех видах раутеров, что мне известны.
И, в принципе, оно называется: inherent behavior.

Добавление от 05.06.2010 00:39:

Хотя, че-то я не подумал, это design flaw стека TCP/IP вообще! Они не придумали обратную инкапсуляцию!

Добавление от 05.06.2010 00:56:

Хммм....судя по комментариям, таки: "-t nat -A OUTPUT -j DNAT" могут спасти отца русской демократии, т.к. nat_output - это единственный чейн, который проходится до routing decision.

11. SuSt, 05.06.2010 10:57
KB
На лоре еще советовали NATить локальные пакеты, тоже пока не проверял
Кстати, да. Очень может быть. Например, для OpenVZ-шных контейнеров, использующих venet - это самый простой способ зарутить исходящие пакеты через нужный реальный интерфейс (в случае, если их несколько).

Да как-то не хочется от ванильного ядра отходить
При желании можно скомпилировать отдельный модуль к ядру, не пересобирая ядро целиком. И, по-моему, этот модуль даже не придется потом трогать после обновлений ядра, насколько я помню.

-Sorcerer-
могут спасти отца русской демократии
Дык, на лоре советовали делать SNAT, а не DNAT. И что-то мне подсказывает, что они правы.

12. -Sorcerer-, 05.06.2010 11:02
SuSt
Дык, на лоре советовали делать SNAT, а не DNAT. И что-то мне подсказывает, что они правы.

Таргет SNAT поддерживается только в POSTROUTING, по понятным причинам.
Ожидаемый уровень знаний на ЛОРе.

13. arvidjaar, 11.06.2010 22:26
-Sorcerer-
Routing decision принимается до выхода пакета если его origin - localhost
Вот только OUTPUT отрабатывает до routing decision

KB
Маркировка и маршрутизация по ней в случае локального трафика точно работают:
код:
{pts/0}% sudo ip route add default dev eth0 table 23
{pts/0}% sudo ip rule add fwmark 23 table 23
{pts/0}% ping 69.61.106.93
PING 69.61.106.93 (69.61.106.93) 56(84) bytes of data.
64 bytes from 69.61.106.93: icmp_seq=1 ttl=48 time=662 ms
^C
--- 69.61.106.93 ping statistics ---
2 packets transmitted, 1 received, 50% packet loss, time 999ms
rtt min/avg/max/mdev = 662.201/662.201/662.201/0.000 ms
{pts/0}% sudo iptables -t mangle -A OUTPUT -p icmp -d 69.61.106.93 -j MARK --set-mark 23
{pts/0}% ping 69.61.106.93
PING 69.61.106.93 (69.61.106.93) 56(84) bytes of data.
From 192.168.10.103 icmp_seq=2 Destination Host Unreachable
From 192.168.10.103 icmp_seq=3 Destination Host Unreachable
From 192.168.10.103 icmp_seq=4 Destination Host Unreachable
^C
--- 69.61.106.93 ping statistics ---
4 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2999ms

Так что проблема в чем то другом.

14. SuSt, 12.06.2010 13:07
arvidjaar
KB
Ну, коллеги, вы меня, черт возьми, заинтриговали! Причем настолько сильно, что я не поленился разобраться и проверить все своими руками.
Если совсем кратко: на ЛОР-е ответили верно, нужно было сделать еще и SNAT. Метки в "mangle, OUTPUT" работают. Только ядро при этом не может "понять", какой src ip назначить исходящему пакету. Собственно, в этом ему и может помочь добавление правила в nat, POSTROUTING.

Теперь по порядку. Решил воспроизвести у себя на стенде эксперимент, описанный тов. arvidjaar.
Исходные данные:
код:
root@shelf:~# ifconfig
eth0 Link encap:Ethernet HWaddr 08:00:27:24:1c:85
inet addr:192.168.17.1 Bcast:192.168.17.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:968 errors:0 dropped:0 overruns:0 frame:0
TX packets:601 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:93537 (91.3 KiB) TX bytes:71037 (69.3 KiB)

eth1 Link encap:Ethernet HWaddr 08:00:27:68:18:43
inet addr:192.168.56.2 Bcast:192.168.56.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:42 errors:0 dropped:0 overruns:0 frame:0
TX packets:38 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:6550 (6.3 KiB) TX bytes:3236 (3.1 KiB)
Interrupt:9 Base address:0xd040

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:300 (300.0 B) TX bytes:300 (300.0 B)


root@shelf:~root@shelf:~# ip route show table main
192.168.17.0/24 dev eth0 proto kernel scope link src 192.168.17.1
192.168.56.0/24 dev eth1 proto kernel scope link src 192.168.56.2
default via 192.168.17.5 dev eth0

root@shelf:~# traceroute -I 77.88.21.3
traceroute to 77.88.21.3 (77.88.21.3), 30 hops max, 40 byte packets
1 noisy.home.staser.ru (192.168.17.5) 0.548 ms 0.421 ms 0.590 ms
2 * * *
3 * * *
4 msk-ix-m10.yandex.net (193.232.246.93) 2.624 ms 3.351 ms *
5 www.yandex.ru (77.88.21.3) 2.816 ms 2.942 ms *


Начинаем эксперимент, повторяем действия arvidjaar-а:
код:
root@shelf:~# iptables -t mangle -A OUTPUT -d 77.88.21.3 -p icmp -j MARK --set-mark 1196
root@shelf:~# echo "1196 yandex" >> /etc/iproute2/rt_tables
root@shelf:~# ip route add default via 192.168.56.1 table yandex
root@shelf:~# ip rule add fwmark 1196 table yandex


На всякий случай проверяем, что маршрутизация выставлена именно так, как нам хочется:
код:
root@shelf:~# ip rule ls
0: from all lookup local
32765: from all fwmark 0x4ac lookup yandex
32766: from all lookup main
32767: from all lookup default

root@shelf:~# ip route show table yandex
default via 192.168.56.1 dev eth1


Пробуем пинговать. Не пингуется. Пытаемся разобраться где же "застрял" пакет, и с удивлением обнаруживаем icmp-ответ ... на интерфейсе обратной петли ("lo")!
код:
root@shelf:~# ping 77.88.21.3 -c1
PING 77.88.21.3 (77.88.21.3) 56(84) bytes of data.
From 192.168.17.1 icmp_seq=1 Destination Host Unreachable

--- 77.88.21.3 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

root@shelf:~# tcpdump -nn -t -v -p -i lo icmp
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 96 bytes
IP (tos 0xc0, ttl 64, id 44971, offset 0, flags [none], proto ICMP (1), length 112) 192.168.17.1 > 192.168.17.1: ICMP host 77.88.21.3 unreachable, length 92
IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.17.1 > 77.88.21.3: ICMP echo request, id 35847, seq 1, length 64


Фигня какая-то... Ладно, продолжаем эксперимент. Уберем вообще из таблицы main шлюз по умолчанию, а таблицу "yandex" передвинем таким образом, чтобы она шла после таблицы main:
код:
root@shelf:~# ip rule ls
0: from all lookup local
32764: from all lookup main
32765: from all fwmark 0x4ac lookup yandex
32767: from all lookup default

root@shelf:~# ip route flush cache
root@shelf:~# route del default

root@shelf:~# ping 77.88.21.3 -c1
connect: Network is unreachable


Вот оно как, Михалыч... казалось бы, метки действительно не работают. При отсутсвии default gw система вообще не смогла никуда направить этот пакет. Но мы не сдаемся! Вернем на место default gw, уберем правило "yandex" (то есть вернем все к исходному состоянию, как было до начала эксперимента) и пропишем правило SNAT-а:
код:
root@shelf:~# iptables -t nat -A POSTROUTING -p icmp -d 77.88.21.3 -j SNAT --to-source 192.168.56.2
oot@shelf:~# tcpdump -nn -t -v -p -i eth1 icmp
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
IP (tos 0x0, ttl 59, id 3193, offset 0, flags [none], proto ICMP (1), length 84) 77.88.21.3 > 192.168.56.2: ICMP echo reply, id 46343, seq 1, length 64


Что мы видим? Пакет приходит на правильный интерфейс, но уходит с "неправильного". Ну да, логично. Ведь src ip мы ему подменили, а маршрут ядро выбрало в соответствии с default gw.

Теперь вернем на место правило для маршрута на основе метки и повторим пинг:
код:
root@shelf:~# ip rule add fwmark 1196 lookup yandex
root@shelf:~# tcpdump -nn -t -v -p -i eth1 icmp
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.56.2 > 77.88.21.3: ICMP echo request, id 49159, seq 1, length 64
IP (tos 0x0, ttl 59, id 3195, offset 0, flags [none], proto ICMP (1), length 84) 77.88.21.3 > 192.168.56.2: ICMP echo reply, id 49159, seq 1, length 64


Ура! Победа! Пакет и ушел с правильно интерфейса, и вернулся на правильный интерфейс!

Для бОльшей убедительности проверим трассировки:
код:
root@shelf:~# traceroute -I 77.88.21.3
traceroute to 77.88.21.3 (77.88.21.3), 30 hops max, 40 byte packets
1 192.168.56.1 (192.168.56.1) 0.242 ms 0.191 ms 0.234 ms
2 * * *
3 * * *
4 * * *
5 * * *
6 www.yandex.ru (77.88.21.3) 2.564 ms * *

root@shelf:~# traceroute -I 87.250.251.3
traceroute to 87.250.251.3 (87.250.251.3), 30 hops max, 40 byte packets
1 noisy.home.staser.ru (192.168.17.5) 0.579 ms 0.476 ms 0.606 ms
2 * * *
3 * * *
4 msk-ix-m10.yandex.net (193.232.246.93) 2.672 ms * *
5 * * *
6 l3-eto1-eto2.yandex.net (213.180.213.44) 2.575 ms 2.981 ms *
7 l3-iva2-eto1.yandex.net (213.180.213.21) 3.855 ms * 3.630 ms
8 www.yandex.ru (87.250.251.3) 3.538 ms * *


Пакеты идут разными маршрутами, что и требовалось доказать.


P.S. Даааа... Все-таки ядро Linux для меня - загадка.
За это сообщение сказали спасибо: arvidjaar

15. arvidjaar, 12.06.2010 19:03
SuSt
Метки в "mangle, OUTPUT" работают. Только ядро при этом не может "понять", какой src ip назначить исходящему пакету.

Да, я это предполагал, но смоделировать не на чем было.

Все-таки ядро Linux для меня - загадка.
Ядро Linux здесь на самом деле не при чем - те же самые проблемы возникают на любой multihome системе. При отправке пакета система должна решить две задачи - выбрать адрес отправителя и интерфейс, через который уйдет пакет. Эти две задачи достаточно независимы. И, к сожалению, их взаимодействие достаточно плохо документировано в тех системах, с которыми я сталкивался (Solaris, Windows). Есть статьи, но их еще надо найти ...

В любом случае спасибо за исчерпывающий разбор полетов

16. kononets, 12.06.2010 20:55
<<На всякий случай проверяем, что маршрутизация выставлена именно так, как нам хочется:

код:


root@shelf:~# ip rule ls
0: from all lookup local
32765: from all fwmark 0x4ac lookup yandex
32766: from all lookup main
32767: from all lookup default

root@shelf:~# ip route show table yandex
default via 192.168.56.1 dev eth1


Пробуем пинговать. Не пингуется.>>

имхо можно добавить кроме маршрута по умолчанию ещё и маршрут в подсеть, указав предпочтительный src address (для меня очевидным решением представляется продублировать таблицу main, заменив только маршрут по умолчанию):
код:
192.168.56.0/24 dev eth1  scope link  src 192.168.56.2


имхо не помешает после каждой модификации таблиц маршрутов также сбрасывать кэш маршрутов, ip route flush cache

17. SuSt, 13.06.2010 17:36
kononets
Уже после того, как я написал свой предыдущий пост, я подумал о том же самом. И попробовал сделать так, как Вы говорите. Результат от этого не меняется. То есть все остается точно так же, как я уже описал. Даже если явно указывать "proto kernel src 192.168.56.2".

Насчет "ip route flush cache" - я это тоже делал. На самом деле я повторял все перечисленные эксперименты ДВА раза, по второму разу после каждой операции на всякий случай давал команду "flush cache". Конечный результат от этого, опять же, не изменился. Поэтому я не стал об этом писАть, чтобы не загромождать итак немаленькие выкладки.

И да, если кому интересно. Упражнялся я на последнем стабильном Debian-е (который 5.0.4), запущенном внутри VirtualBox-а (+KVM).

18. SuSt, 14.06.2010 15:15
arvidjaar
Поразмышляв немного на досуге, я понял почему так происходит.

Приложение может заbind-иться либо на конкретный интерфейс/адрес, либо на "0.0.0.0" (все интерфейсы). Во втором случае при отправке пакета ядро может выбрать src ip только в том случае, если маршрут до destination присутствует в таблице "main", и баста. Все прочие таблицы "не канают". Вот и ответ.

А "изврат" с SNAT это только подтверждает. То есть, приложение отправляет пакет с того интерфейса, для которого найдет маршрут в таблице main (и ни в какой другой). В данном случае это будет default gw. А потом уже начинается все это шаманство с метками. И после того как iproute1 "отпустит" пакет, за него берется iproute2. И тут его "обманным путем" выкинут через другой интерфейс, да еще и замаскарадят. Поэтому, в общем, KB применил самый правильный способ решения задачи, на самом деле.

Осталось только ради интереса выяснить что будет, если в таблице main будут присутствовать два разных default gw.

19. kononets, 14.06.2010 22:32
непонятно, почему traceroute разными путями пошёл, ведь особый маршрут задан только для конечного IP.

20. arvidjaar, 15.06.2010 07:13
SuSt
Приложение может заbind-иться либо на конкретный интерфейс/адрес, либо на "0.0.0.0" (все интерфейсы). Во втором случае при отправке пакета ядро может выбрать src ip только в том случае, если маршрут до destination присутствует в таблице "main", и баста.
??? А что, если выбрана другая таблица, пакет уходит вообще без обратного адреса? Вообще-то раньше я был уверен, что по умолчанию выбирается IP адрес того интерфейса, через который отсылается пакет. Похоже, играют роль какие-то другие факторы - вот их и было бы интересно понять.

Кстати, а если вместо SNAT просто указать в таблице src
код:
ip route add default via 192.168.56.1 src 192.168.56.2 table yandex

? Результат должен быть тот же. Если нет - это повод задуматься

21. SuSt, 15.06.2010 09:03
kononets
непонятно, почему traceroute разными путями пошёл, ведь особый маршрут задан только для конечного IP.
Ну "здравствуйте, я Ваша тётя!". kononets, Вы меня пугаете такими вопросами! Там же только TTL разный при трассировке, а src ip и dst ip одни и те же.

arvidjaar
А что, если выбрана другая таблица, пакет уходит вообще без обратного адреса?
Он просто не уходит. Да и что значит "выбрана другая таблица"? Кем выбрана-то?

Результат должен быть тот же.
Я же уже написал, что этот вариант тоже попробовал. Посмотрите пожалуйста повнимательнее.

22. kononets, 15.06.2010 12:16
SuSt
у меня есть маленький шлюз, на нем поднят vpn канал посредством cisco vpn клиента. маршрут по умолчанию направлен в vpn канал. есть отдельная таблица маршрутов, чтобы шлюз принимал соединения и мог общаться с локальной подсетью, в которой все маршруты точно такие, какие присутствуют в main до того как клиент поднимает vpn и впишет туда свои маршруты (lo, локальный интерфейс и подсеть, и локальный маршрут по умолчанию).

если я заверну в ту самую отдельную таблицу трафик для 77.88.21.3, то TTL в пинге на 77.88.21.3 меняется, а traceroute -I все равно как шел, так и идет через vpn канал.

UPD
повторные тесты показали, что при выполнении traceroute -I трафик появляется на локальном интерфейсе, но с src address vpn-канала. видимо, cisco vpn клиент как-то манипулирует трафиком.

23. SuSt, 15.06.2010 12:38
kononets
в которой все маршруты точно такие, какие присутствуют в main до того как клиент поднимает vpn и впишет туда свои маршруты
Хм... интересно, а зачем? Нельзя было просто дописать статические маршруты до локальной сети прямо в main? Ну Вам, конечно, виднее. Но я не очень понимаю постановки Вашей задачи.

а traceroute -I все равно как шел, так и идет через vpn канал.
Да потому что src ip трассировочного пакета остался прежним. А промежуточные узлы кидают сообщение "TTL exceeded in-transit" на тот адрес, с которого пришел пакет с "протухшим" TTL-ем.

24. kononets, 15.06.2010 12:43
SuSt
Да потому что src ip трассировочного пакета остался прежним. А промежуточные узлы кидают сообщение "TTL exceeded in-transit" на тот адрес, с которого пришел пакет с "протухшим" TTL-ем.

разумеется. но если я пингую, src address устанавливается "правильный". а для traceroute "неправильный"

Добавление от 15.06.2010 12:46:

SuSt
Хм... интересно, а зачем? Нельзя было просто дописать статические маршруты до локальной сети прямо в main? Ну Вам, конечно, виднее. Но я не очень понимаю постановки Вашей задачи.

мне нужна не только локальная подсеть. нужно также, чтобы локальный интерфейс принимал соединия с интернета.

25. SuSt, 15.06.2010 12:46
разумеется. но если я пингую, src address устанавливается "правильный". а для traceroute "неправильный"
А это нужно еще проверить. Вы tcpdump-ом смотрели?

Ну и плюс к тому, можно запустить traceroute с параметром "-s адрес_источника", и ping с параметром "-I адрес_источника", чтобы явно указать с какого интерфейса отправлять пакет. Тогда все должно стать предельно прозрачно.

26. kononets, 15.06.2010 12:57
tcpdump-ом смотрел, как иначе узнать-то.

если запускаю
код:
traceroute -i ra0 -I 77.88.21.3

, то source address и интерфейс выбирается "правильный" и трассировка показывает "правильный" маршрут. если без -i ra0, то назначается "неправильный" адрес, но трафик traceroute появляется на "правильном" интерфейсе, и на выводе traceroute маршрут проходит "неправильно", то есть через vpn-канал.
код:

# ip ru l
0: from all lookup local
32763: from all to 77.88.21.3 lookup T1
32764: from all to 192.168.254.224/28 lookup T1
32765: from 192.168.254.227 lookup T1
32766: from all lookup main
32767: from all lookup default
~# ip r l table T1
192.168.254.224/28 dev ra0 scope link src 192.168.254.227
127.0.0.0/8 dev lo scope link
default via 192.168.254.238 dev ra0

27. SuSt, 15.06.2010 14:00
kononets
Я окончательно запутался. "Правильный" - "неправильный"... Нельзя ли целиком выложить сюда таблицы все маршрутизации и ifconfig, или они секретные?

Как я сейчас это себе представляю. Возьмем ситуацию, когда не задаем параметр "-i ra0" у traceroute. Тогда он (traceroute) будет искать в таблице main маршрут до 77.88.21.3. И он его найдет, поскольку в таблице main есть default gw, который "смотрит" в тоннель. Поэтому согласно моим представлениям, он должен присвоить пакету src ip того интерфейса, который фигурирует в таблице main в одной строчке с "0.0.0.0". Я прав?

28. kononets, 15.06.2010 20:30
шлюз за NATом.

интерфейсы:
код:

# ifconfig
cipsec0 Link encap:Ethernet HWaddr 00:0b:fc:f8:01:8f
inet addr:129.16.143.20 Mask:255.255.255.0
UP RUNNING NOARP MTU:1356 Metric:1
RX packets:1652682 errors:0 dropped:0 overruns:0 frame:0
TX packets:1361458 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:975309723 (930.1 MiB) TX bytes:199505053 (190.2 MiB)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:19537 errors:0 dropped:0 overruns:0 frame:0
TX packets:19537 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:4244861 (4.0 MiB) TX bytes:4244861 (4.0 MiB)

ra0 Link encap:Ethernet HWaddr 00:22:43:00:10:14
inet addr:192.168.254.227 Bcast:192.168.254.239 Mask:255.255.255.240
UP BROADCAST NOTRAILERS RUNNING MULTICAST MTU:1500 Metric:1
RX packets:111634792 errors:0 dropped:0 overruns:0 frame:0
TX packets:5437074 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:3109656810 (2.8 GiB) TX bytes:1600024838 (1.4 GiB)
Interrupt:19


маршруты и политики:
код:

# ip ru l
0: from all lookup local
32763: from all to 129.16.100.74 lookup T1
32764: from all to 192.168.254.224/28 lookup T1
32765: from 192.168.254.227 lookup T1
32766: from all lookup main
32767: from all lookup default
# ip r l table T1
192.168.254.224/28 dev ra0 scope link src 192.168.254.227
127.0.0.0/8 dev lo scope link
default via 192.168.254.238 dev ra0
# ip r l
129.16.144.11 via 192.168.254.238 dev ra0
129.16.143.0/24 dev cipsec0 proto kernel scope link src 129.16.143.20
127.0.0.0/8 dev lo scope link
default via 129.16.143.20 dev cipsec0 scope link
# cat /etc/iproute2/rt_tables | grep -v ^#
255 local
254 main
253 default
0 unspec
10 T1


запускаем ping
код:
# ping -c 2 77.88.21.3
PING 77.88.21.3 (77.88.21.3) 56(84) bytes of data.
64 bytes from 77.88.21.3: icmp_seq=1 ttl=53 time=52.9 ms
64 bytes from 77.88.21.3: icmp_seq=2 ttl=53 time=52.2 ms

при этом на выводе tcpdump ничего нет. TTL равен 53.

запускаем traceroute:
код:

# traceroute -I 77.88.21.3
traceroute to 77.88.21.3 (77.88.21.3), 30 hops max, 38 byte packets
1 vpn1-tunnel.vpn.chalmers.se (129.16.144.11) 20.485 ms 19.852 ms 19.369 ms
2 cth143a-itss-gw.chalmers.se (129.16.143.3) 19.611 ms 20.015 ms 20.040 ms
3 core1-itss-gw.chalmers.se (129.16.2.178) 19.634 ms 19.648 ms 20.140 ms
4 optosunet-lr1-core1-gw.chalmers.se (129.16.2.193) 27.315 ms 27.288 ms 27.266 ms
5 c1sth-ae0-1002.sunet.se (193.11.0.1) 27.727 ms 27.745 ms 27.817 ms
6 netnod-a.stk.retn.net (194.68.123.157) 27.816 ms 28.038 ms 27.820 ms
7 ae2-9.RT.V10.MSK.RU.retn.net (87.245.233.13) 51.937 ms 51.840 ms 51.929 ms
8 GW-Yandex.retn.net (87.245.253.26) 52.059 ms 52.032 ms 52.013 ms
9 gallium-vlan901.yandex.net (77.88.56.126) 52.064 ms 52.180 ms 52.141 ms
10 l3-ugr2-ugr1.yandex.net (213.180.213.55) 52.441 ms 52.184 ms 52.219 ms
11 toyota-vlan4.yandex.net (213.180.210.181) 52.382 ms 52.464 ms 52.401 ms
12 www.yandex.ru (77.88.21.3) 52.294 ms 52.313 ms 52.320 ms


делаем
код:
# ip ru a to 77.88.21.3 table T1
# ip ru l
0: from all lookup local
32762: from all to 77.88.21.3 lookup T1
32763: from all to 129.16.100.74 lookup T1
32764: from all to 192.168.254.224/28 lookup T1
32765: from 192.168.254.227 lookup T1
32766: from all lookup main
32767: from all lookup default

запускаем ping
код:
# ping -c 2 77.88.21.3
PING 77.88.21.3 (77.88.21.3) 56(84) bytes of data.
64 bytes from 77.88.21.3: icmp_seq=1 ttl=51 time=37.0 ms
64 bytes from 77.88.21.3: icmp_seq=2 ttl=51 time=36.3 ms

TTL теперь равен 51. на выводе tcpdump видим:
код:

# tcpdump -nn -t -v -p -i ra0 -p icmp
tcpdump: listening on ra0, link-type EN10MB (Ethernet), capture size 96 bytes
IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.254.227 > 77.88.21.3: ICMP echo request, id 6961, seq 1, length 64
IP (tos 0x0, ttl 51, id 51625, offset 0, flags [none], proto ICMP (1), length 84)
77.88.21.3 > 192.168.254.227: ICMP echo reply, id 6961, seq 1, length 64
IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.254.227 > 77.88.21.3: ICMP echo request, id 6961, seq 2, length 64
IP (tos 0x0, ttl 51, id 51626, offset 0, flags [none], proto ICMP (1), length 84)
77.88.21.3 > 192.168.254.227: ICMP echo reply, id 6961, seq 2, length 64


запускаем traceroute
код:
# traceroute -I 77.88.21.3
traceroute to 77.88.21.3 (77.88.21.3), 30 hops max, 38 byte packets
1 vpn1-tunnel.vpn.chalmers.se (129.16.144.11) 20.294 ms 20.315 ms 19.726 ms
2 cth143a-itss-gw.chalmers.se (129.16.143.3) 19.978 ms 20.394 ms 20.435 ms
3 core1-itss-gw.chalmers.se (129.16.2.178) 20.795 ms 20.407 ms 20.448 ms
4 optosunet-lr1-core1-gw.chalmers.se (129.16.2.193) 27.642 ms 27.667 ms 120.936 ms
5 c2sth-ae0-1002.sunet.se (193.11.0.5) 28.249 ms 28.039 ms 28.011 ms
6 netnod-b.stk.retn.net (194.68.128.157) 28.224 ms 28.099 ms 28.175 ms
7 ae2-9.RT.V10.MSK.RU.retn.net (87.245.233.13) 115.324 ms 52.236 ms 52.227 ms
8 GW-Yandex.retn.net (87.245.253.26) 52.328 ms 52.410 ms 52.346 ms
9 gallium-vlan901.yandex.net (77.88.56.126) 52.563 ms 52.576 ms 52.494 ms
10 l3-ugr2-ugr1.yandex.net (213.180.213.55) 52.576 ms 52.531 ms 52.498 ms
11 toyota-vlan4.yandex.net (213.180.210.181) 52.774 ms 52.790 ms 52.851 ms
12 www.yandex.ru (77.88.21.3) 52.802 ms 52.775 ms 52.972 ms

как говорится, найдите 10 отличий от предыдущего результата.

на выводе tcpdump имеем:
код:
    129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 1, length 18
IP (tos 0x0, ttl 1, id 45712, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 2, length 18
IP (tos 0x0, ttl 1, id 45713, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 3, length 18
IP (tos 0x0, ttl 2, id 45714, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 4, length 18
IP (tos 0x0, ttl 2, id 45715, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 5, length 18
IP (tos 0x0, ttl 2, id 45716, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 6, length 18
IP (tos 0x0, ttl 3, id 45717, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 7, length 18
IP (tos 0x0, ttl 3, id 45718, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 8, length 18
IP (tos 0x0, ttl 3, id 45719, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 9, length 18
IP (tos 0x0, ttl 4, id 45720, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 10, length 18
IP (tos 0x0, ttl 4, id 45721, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 11, length 18
IP (tos 0x0, ttl 4, id 45722, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 12, length 18
IP (tos 0x0, ttl 5, id 45723, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 13, length 18
IP (tos 0x0, ttl 5, id 45724, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 14, length 18
IP (tos 0x0, ttl 5, id 45725, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 15, length 18
IP (tos 0x0, ttl 6, id 45726, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 16, length 18
IP (tos 0x0, ttl 6, id 45727, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 17, length 18
IP (tos 0x0, ttl 6, id 45728, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 18, length 18
IP (tos 0x0, ttl 7, id 45729, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 19, length 18
IP (tos 0x0, ttl 7, id 45730, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 20, length 18
IP (tos 0x0, ttl 7, id 45731, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 21, length 18
IP (tos 0x0, ttl 8, id 45732, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 22, length 18
IP (tos 0x0, ttl 8, id 45733, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 23, length 18
IP (tos 0x0, ttl 8, id 45734, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 24, length 18
IP (tos 0x0, ttl 9, id 45735, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 25, length 18
IP (tos 0x0, ttl 9, id 45736, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 26, length 18
IP (tos 0x0, ttl 9, id 45737, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 27, length 18
IP (tos 0x0, ttl 10, id 45738, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 28, length 18
IP (tos 0x0, ttl 10, id 45739, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 29, length 18
IP (tos 0x0, ttl 10, id 45740, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 30, length 18
IP (tos 0x0, ttl 11, id 45741, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 31, length 18
IP (tos 0x0, ttl 11, id 45742, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 32, length 18
IP (tos 0x0, ttl 11, id 45743, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 33, length 18
IP (tos 0x0, ttl 12, id 45744, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 34, length 18
IP (tos 0x0, ttl 12, id 45745, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 35, length 18
IP (tos 0x0, ttl 12, id 45746, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 36, length 18

и это на интерфейсе ra0, которому присвоен адрес 192.168.254.227

29. SuSt, 16.06.2010 13:08
kononets

Интересно. Во всей этой истории лично мне больше всего непонятно, куда делись "лишние" два хопа, если пинговать напрямую (не через тоннель). Я могу сделать только одно предположение. Вполне возможно, что маршрутизатор "с той стороны" (который у провайдера) сам искусственно увеличивает TTL для пакетов, которые заворачиваются внутрь тоннеля. Циски вообще иногда любят мудрить с TTL-ями сами по себе, я замечал такое.

Если уж попытаться вообще-внатуре-конкретно разобраться, что называется, "на интерес", я бы еще попробовал запустить tcpdump с параметрами "-e -vv" (в дополнение к уже имеющимся) и посмотрел бы MAC-адреса кадров, соответствующих приходящим от провайдера пакетов. Я не очень хорошо понимаю, как работают цисковские тоннели. Но если MAC-адреса "через тоннель" и "напрямую" будут разными, то tcpdump это покажет.

Еще можно попробовать сделать что-нибудь вроде "ping -t 1 129.16.144.11" как через тоннель, так и напрямую. И посмотреть будет ли разница в ответах.

Ну и Вы все-таки утаили таблицу main.

30. kononets, 16.06.2010 14:06
не утаил, она там. пожалуйста, вот она отдельно:
код:
# ip r l
129.16.144.11 via 192.168.254.238 dev ra0
129.16.143.0/24 dev cipsec0 proto kernel scope link src 129.16.143.20
127.0.0.0/8 dev lo scope link
default via 129.16.143.20 dev cipsec0 scope link

31. SuSt, 16.06.2010 15:21
kononets
Да-да, я проглядел. Виноват.

Ну дык, Вы только подтвердили мои предположения. То есть все происходит как раз так, как я и говорил уже ранее. Ваш последний пример:

на выводе tcpdump имеем:
код:
IP (tos 0x0, ttl 3, id 45718, offset 0, flags [none], proto ICMP (1), length 38)
129.16.143.20 > 77.88.21.3: ICMP echo request, id 45710, seq 8, length 18

и это на интерфейсе ra0, которому присвоен адрес 192.168.254.227

Все логично. Несмотря на то, что Вы при помощи iproute2 "завернули" трафик на 77.88.21.3 через 192.168.254.238, default gw в таблице main все равно как был 129.16.143.20, так и остался. Поэтому traceroute без параметра "-s" по-прежнему привязывается к тому адресу, для которого определен default gw в таблице main. Вот трассировка и не изменилась. Если Вы в дополнение к "ip ru a to 77.88.21.3 table T1", например, сделаете "iptables -t nat -A POSTROUTING -d 77.88.21.3 -j SNAT --to-source 192.168.254.227", то увидите, что трассировка изменилась. Тот же самый эффект произойдет, если вы запустите "traceroute -s 192.168.254.227 -I 77.88.21.3".

32. kononets, 16.06.2010 18:29
а почему ping на два переходе длинее через vpn-канал? я не думаю, что где-то по пути задается увеличенный TTL, скорее всего маршрут действительно длиннее. но точно не знаю.

33. -Sorcerer-, 17.06.2010 02:05
arvidjaar
Вот только OUTPUT отрабатывает до routing decision

С фига? Как ядро знает, что пакет локальный-то?
Только таблица nat отрабатывает до.
Иначе на бриджах все пакеты будут локальными.

Ну и по фактеге есть проблемы. Например: раутинг решает только про интерфейс. Сорс адрес пакета берется из байнда на уровне аппликации, вмешаться в сорс можно только через nat.

34. SuSt, 17.06.2010 08:40
kononets
а почему ping на два переходе длинее через vpn-канал?
Не длиннее, а, наоборот, короче. Коль скоро у входящего пакета TTL больше, значит хопов он прошел как раз таки меньше. И эти два хопа - 192.168.254.238 и какой-нибудь промежуточный между 192.168.254.238 и 129.16.144.11. Когда пакет идет в тоннеле, он по этим хопам не проходит.

35. kononets, 17.06.2010 10:55
SuSt
да, я неправильно сформулировал.
да, один хоп прибавляется за счет NAT шлюза. в остальном маршруты просто разные. меня удивляет, что для ping и для traceroute выбираются разные src address

-Sorcerer-
Вот только OUTPUT отрабатывает до routing decision

С фига?

http://www.netfilter.org/documentation/HOWTO//netfil…OWTO-3.html#ss3.2

36. SuSt, 17.06.2010 11:08
kononets
меня удивляет, что для ping и для traceroute выбираются разные src address

Хороший вопрос! Я не знаю на него ответа. Попробую в выходные еще поковыряться на своем домашнем десктопе с виртуалками. Действительно, очень загадочно.

37. SuSt, 18.06.2010 10:39
kononets
что для ping и для traceroute выбираются разные src address

Видимо, ответ на этот вопрос сможет дать только анализ исходных кодов (ака "сырцов") утилит ping и traceroute. Другого способа я не вижу. И вот почему.

Исходные данные. У меня на работе есть Linux-маршрутизатор на основе последнего стабильного Debian (ядро 2.6.26). Это обычный PC, но на борту у него 12 интерфейсов, из которых 4 - это аплинки до провайдеров. Таблицы маршрутизации там сложные, но никакой динамики (как то OSPF, BGP и т.п.) там нет. То есть маршрутизация на 100% статическая, но с использованием iproute2 и кучей разных хитропопых критериев выбора маршрута, в том числе и по меткам.

Далее. В таблице main этого роутера начисто отсутствует default gateway. Вообще. Он там просто не нужен. Захожу на эту машину, начинаю свои бесчеловечные эксперименты. Но сперва выдержки из мануалов по ping и traceroute.

цитата (man ping):
-I interface address
Set source address to specified interface address. Argument may be numeric IP address or name of
device.

цитата (man traceroute):
-i interface
Specifies the interface through which traceroute should send packets. By default, the interface
is selected according to the routing table.

-s source_addr
Chooses an alternative source address. Note that you must select the address of one of the inter‐
faces. By default, the address of the outgoing interface is used.

Пока понятно? То бишь, у traceroute предусмотрены два разных параметра: имя интерфейса и src ip задаются по отдельности разными ключами командной строки. А у ping все свалено "в одну кучу". Ключом "-I" можно задать как src ip, так и имя интерфейса. По крайней мере, так заявлено в документации.

Итак, самое интересное. Повторяю, записи "default gateway" в таблице main НЕТ! Вместо него используются правила типа "from x.x.x.x lookup провайдер1", "from y.y.y.y lookup провайдер2", и так далее. Что же мы имеем (в целях конспирации третий октет я "засекретил")?

код:
gw1:~# ifconfig eth8
eth8 Link encap:Ethernet HWaddr 00:15:17:a9:f4:14
inet addr:87.118.xxx.213 Bcast:87.118.xxx.215 Mask:255.255.255.252
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:26580364 errors:0 dropped:0 overruns:0 frame:0
TX packets:23502357 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:14898126016 (13.8 GiB) TX bytes:4965197172 (4.6 GiB)
Memory:fe680000-fe6a0000

gw1:~# traceroute 77.88.21.3 -ns 87.118.xxx.213
traceroute to 77.88.21.3 (77.88.21.3), 30 hops max, 40 byte packets
1 87.118.xxx.214 0.649 ms 0.642 ms 0.636 ms
2 195.128.64.76 1.358 ms 1.371 ms 1.588 ms
3 193.232.244.93 1.332 ms 1.328 ms 1.320 ms
4 77.88.56.126 1.551 ms 1.546 ms 1.766 ms
5 213.180.213.39 1.528 ms 1.740 ms 1.733 ms
6 213.180.210.181 96.659 ms 96.004 ms 96.234 ms
7 77.88.21.3 1.782 ms 1.834 ms 1.831 ms

gw1:~# traceroute 77.88.21.3 -ni eth8
traceroute to 77.88.21.3 (77.88.21.3), 30 hops max, 40 byte packets
1 87.118.xxx.214 0.750 ms 0.729 ms 0.721 ms
2 195.128.64.76 1.947 ms 1.948 ms 1.942 ms
3 193.232.244.93 1.656 ms 1.654 ms 1.648 ms
4 77.88.56.126 1.642 ms 1.635 ms 1.860 ms
5 213.180.213.39 88.285 ms 88.283 ms 88.278 ms
6 213.180.210.181 1.827 ms 1.834 ms 1.816 ms
7 77.88.21.3 1.796 ms 2.186 ms 2.177 ms

gw1:~# ping 77.88.21.3 -c4 -nI 87.118.xxx.213
PING 77.88.21.3 (77.88.21.3) from 87.118.xxx.213 : 56(84) bytes of data.
64 bytes from 77.88.21.3: icmp_seq=1 ttl=58 time=1.89 ms
64 bytes from 77.88.21.3: icmp_seq=2 ttl=58 time=1.76 ms
64 bytes from 77.88.21.3: icmp_seq=3 ttl=58 time=1.64 ms
64 bytes from 77.88.21.3: icmp_seq=4 ttl=58 time=2.03 ms

--- 77.88.21.3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3013ms
rtt min/avg/max/mdev = 1.648/1.835/2.035/0.145 ms

gw1:~# ping 77.88.21.3 -c4 -nI eth8
PING 77.88.21.3 (77.88.21.3) from 87.118.xxx.213 eth8: 56(84) bytes of data.
From 87.118.xxx.213 icmp_seq=1 Destination Host Unreachable
From 87.118.xxx.213 icmp_seq=2 Destination Host Unreachable
From 87.118.xxx.213 icmp_seq=3 Destination Host Unreachable
From 87.118.xxx.213 icmp_seq=4 Destination Host Unreachable

--- 77.88.21.3 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3016ms
, pipe 3


Если все еще не совсем ясно, в чем прикол, поясню. Для traceroute пофигу, то ли мы задали src ip, то ли интерфейс: он и в том, и в другом случае отработал успешно. А вот ping справился с задачей только в том случае, если мы указываем src ip. Обратите внимание, что если мы указываем для ping интерфейс, то он корректно ресолвит его (интерфейса) адрес. Только вот пакеты все равно никуда не уходят. А tcpdump показывает "host unreachable" не где-нибудь, а на "lo"-интерфейсе.

Ну чо, кому не слабО разобраться в исходниках? У меня, боюсь, квалификации не хватит.
За это сообщение сказали спасибо: compro

38. -Sorcerer-, 20.06.2010 00:56
kononets

Ну и расскажите мне, коллега как отработает правило:
iptables -A OUTPUT -o eth1 -j DROP
Если output interface еще неизвестен?

39. SuSt, 20.06.2010 10:42
-Sorcerer-
Если output interface еще неизвестен?
В таблице "filter" OUTPUT-интерфейс уже известен. А kononets говорил про таблицу "mangle". Учите матчасть (http://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#TRAVERSINGOFTABLES) по iptables.

40. arvidjaar, 20.06.2010 10:45
-Sorcerer-
Ну и расскажите мне, коллега как отработает правило:
iptables -A OUTPUT -o eth1 -j DROP
Если output interface еще неизвестен?

По правилам

Таблица mangle выполняется до, таблица filter (куда ваша команда правило и добавляет) - после routing.

В самом начале речь шла именно о маркировке пакетов. Это выполняется в mangle.

41. SuSt, 20.06.2010 10:55
Вот еще одна очень красивая схема. Мне понравилась. Всё очень наглядно представлено.
http://upload.wikimedia.org/wikipedia/commons/3/37/N…r-packet-flow.svg

42. arvidjaar, 20.06.2010 11:46
kononets
меня удивляет, что для ping и для traceroute выбираются разные src address
У меня - одинаковые
код:
{pts/0}% ip rule list
0: from all lookup local
32765: from all to 69.61.106.93 lookup 23
32766: from all lookup main
32767: from all lookup default
{pts/0}% ip route list
192.168.35.0/24 dev vmnet1 proto kernel scope link src 192.168.35.1
172.16.95.0/24 dev vmnet8 proto kernel scope link src 172.16.95.1
192.168.10.0/24 dev wlan0 proto kernel scope link src 192.168.10.103 metric 2
1.0.0.0/8 dev eth0 proto kernel scope link src 1.1.1.1
127.0.0.0/8 dev lo scope link
default via 192.168.10.1 dev wlan0 proto static
{pts/0}% ip route list table 23
default via 192.168.35.130 dev vmnet1
{pts/0}% ping -c 1 69.61.106.93
{pts/1}% sudo tshark -i vmnet1
Running as user "root" and group "root". This could be dangerous.
Capturing on vmnet1
0.000000 Vmware_c0:00:01 -> Broadcast ARP Who has 192.168.35.130? Tell 192.168.35.1
0.000264 Vmware_89:7f:73 -> Vmware_c0:00:01 ARP 192.168.35.130 is at 00:0c:29:89:7f:73
0.000273 192.168.35.1 -> 69.61.106.93 ICMP Echo (ping) request
^C3 packets captured
{pts/0}% sudo traceroute -I 69.61.106.93
{pts/1}% sudo tshark -i vmnet1
Running as user "root" and group "root". This could be dangerous.
Capturing on vmnet1
0.000000 192.168.35.1 -> 69.61.106.93 ICMP Echo (ping) request
0.000213 192.168.35.1 -> 69.61.106.93 ICMP Echo (ping) request
0.000235 192.168.35.1 -> 69.61.106.93 ICMP Echo (ping) request


Никаких игр с iptables нет.

Так что есть какие-то отличия в конфигурации.

Кстати, заодно стало понятно, почему использование fwmark не (всегда) работает для локальных исходящих соединений. Решение о выборе локального адреса - по крайней мере, для ICMP - принимается до генерации каких-либо пакетов (при выполнении connect()). Соотвественно, привесить mark в этот момент не к чему и используются таблицы по умолчанию.

43. -Sorcerer-, 20.06.2010 13:16
SuSt
В таблице "filter" OUTPUT-интерфейс уже известен.

Как он "известен" если routing decision еще не было?

В таблице "filter" OUTPUT-интерфейс уже известен. А kononets говорил про таблицу "mangle".

Если че, это говорил я, еще на первой странице.

Но смех конечно не в этом, а в том, что для output делают route два раза, как тут выяснилось. Т.е. первый пост вообще - пальцем в небо.

Добавление от 20.06.2010 13:18:

arvidjaar
Решение о выборе локального адреса - по крайней мере, для ICMP - принимается до генерации каких-либо пакетов (при выполнении connect()).

Это верно для любой аппликации которая не делает bind() как я уже говорил.

Добавление от 20.06.2010 14:00:

arvidjaar

Кстати, интересный вопрос: какой kernel? Скомпилен ли tun.ko как модуль или внутри ядра?
Есть у меня тут одна веселая догадка про то как накосячили в 2.6.30+

44. kononets, 20.06.2010 14:46
arvidjaar
У меня - одинаковые

...

Никаких игр с iptables нет.

Так что есть какие-то отличия в конфигурации.


у меня стоит vpn-канал, который поднимается патченным cisco vpn клиентом. непатченный клиент блокирует трафик с хоста в локальную подсеть, если этого требует vpn-сервер (который требует, а мне так не надо). мне кажется, что именно в этом кроется причина, но у меня не хватит знаний разобраться в исходном коде.

45. arvidjaar, 20.06.2010 15:27
kononets
vpn-канал, который поднимается патченным cisco vpn клиентом ... мне кажется, что именно в этом кроется причина
Там есть модуль ядра или это целиком пользовательское приложение?

46. -Sorcerer-, 20.06.2010 15:29
kononets
у меня стоит vpn-канал, который поднимается патченным cisco vpn клиентом. непатченный клиент блокирует трафик с хоста в локальную подсеть, если этого требует vpn-сервер

А? vpnc ничего нигде не блокирует.

Добавление от 20.06.2010 15:29:

arvidjaar
Там есть модуль ядра или это целиком пользовательское приложение?

vpnc юзает tun, как и openvpn

47. kononets, 20.06.2010 15:30
arvidjaar
Там есть модуль ядра или это целиком пользовательское приложение?

совершенно верно, есть модуль ядра. это проприетарный клиент для cisco 3000 series vpn concentrator

Добавление от 20.06.2010 15:43:

-Sorcerer-
vpnc

спасибо, про vpnc раньше не слышал, но пробовать, скорее всего, не буду. этот сервис у нас скоро выведут из эксплуатации, в качестве замены предлагается использовать pptp или l2tp/ipsec.

48. -Sorcerer-, 20.06.2010 15:52
kononets
есть модуль ядра

У меня есть подозрения, что сорс раутинг работает "неправильно" только для встроенных в ядро функций, а если модулем - все ок.



URL: http://forum.ixbt.com/topic.cgi?id=76:9522