LINUX.ORG.RU
решено ФорумAdmin

Непонятки с iptables

 ,


0

2

Коллеги, разъясните пожалуйста, что может происходить?

Есть 2 устройства (условно, D63 и D64) - на каждом по одному 1G интерфейсу в общую сеть и по одному 10G интерфейсу, друг на друга. Схема примерно такая:



         D64                                   D63
<=1G=> | eth0 : 172.17.5.202/22    |         | eth1  : 172.17.0.2/16     | <=1G=>
       |                           |         |                           |
       | eth3 : 192.168.100.64/24  | <=10G=> | eth11 : 192.168.100.63/24 |
       |              /            |         |                           |
       |     (tun00e...tun07e)     |
       |              /            |
       |      ping 172.17.0.2      |
              

       # ip route show dev eth3
       172.17.0.0/16  scope link 
       192.168.100.0/24  proto kernel  scope link  src 192.168.100.64

На D64 запускается приложение, которое создаёт 8 (по числу процессоров) TUN-интерфейсов с именами (tun00e..tun07e) после чего происходит хитрая настройка фильтра пакетов так, чтобы локально генерируемый на D64 в сторону D63 (например, с использованием ping) трафик распределялся по tun-устройствам в соответствии с номером обрабатывающего пакет процессора. Пример настройки такой:

	ip link set dev tun00e up
	ip link ...
	ip link set dev tun07e up

	ip route add default dev tun00e table 100
	ip route ...
	ip route add default dev tun07e table 107

	ip rule add fwmark 100 table 100
	ip rule ...
	ip rule add fwmark 107 table 107

	iptables -t mangle -A OUTPUT -o eth3 -m cpu --cpu 0 -j MARK --set-mark 100
	iptables ...
	iptables -t mangle -A OUTPUT -o eth3 -m cpu --cpu 7 -j MARK --set-mark 107

На каждом из tun-устройств сидит поток приложения, который вычитывает оттуда IP-пакет и, далее, инкапсулирует его в UDP-датаграмму (sport:10000, dport=10000, checksum=0) с добавлением нового IP заголовка (saddr:192.168.100.64, daddr:192.168.100.63). После чего заталкивает полученный пакет обратно в стек через это же устройство.

Вот что далее запускается на D64:

	ip route add 172.17.0.2/16 dev eth3
	ping 172.17.0.2

ПРОБЛЕМА в том, что данные через eth3 НЕ ХОДЯТ.

С использованием tcpdump видно, что данные через tun-устройства идут. Более того, tcpdump подтверждает корректность построения новой IP-датаграммы.

Ниже приведу вывод статистики по iptables, из которой видно, что ICMP-пакеты проходят по цепочкам: OUTPUT и POSTROUTING, попадая, очевидно, на tun-устройство. Далее, видно также, что из tun-устройства выходят необходимые UDP-пакеты — цепочка PREROUTING. Но почему-то, далее эти пакеты не идут.

# iptables -t mangle -L -vn
Chain PREROUTING (policy ACCEPT 18685 packets, 1904K bytes)
 pkts bytes target     prot opt in     out     source               destination         
 4278  479K            udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp spt:10000
    0     0            icmp --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain INPUT (policy ACCEPT 14997 packets, 1480K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0            udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp spt:10000

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0            udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp spt:10000
    0     0            icmp --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 5644 packets, 772K bytes)
 pkts bytes target     prot opt in     out     source               destination         
  650 54600 MARK       all  --  *      eth3    0.0.0.0/0            0.0.0.0/0            cpu 0 MARK set 0x64
  ...
  615 51660 MARK       all  --  *      eth3    0.0.0.0/0            0.0.0.0/0            cpu 7 MARK set 0x6b
 3465  291K            icmp --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain POSTROUTING (policy ACCEPT 5644 packets, 772K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0            udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp spt:10000
 3449  290K            icmp --  *      *       0.0.0.0/0            0.0.0.0/0           

Что смотреть, куда копать? ;)

P.S.

net.ipv4.ip_forward = 1

★★

Ответ на: комментарий от i82

Вот что далее запускается на D64:....

Чтобы пошли пинги в сеть 172.17.0.2/16 через D63 надо сделать то, что я сказал выше. Что произойдет ты наверно догадываешься (вообще надо мыслить именно так для составления правил):

  • Пакет пришедший с адресом 192.168.100.64 изменит адрес отправителя на 172.17.0.2
  • В дело вступит маршутизация на D63 которая поймет, что адрес отправителя является он сам, а адрес получателя находится на интерфейсе eth1
gh0stwizard ★★★★★ ()
Последнее исправление: gh0stwizard (всего исправлений: 1)
Ответ на: комментарий от gh0stwizard

Объясни на пальцах, что происходит в этом случае.

В IP-стек на D64 через TUN-устройство запихивается IP-пакет с SRC=192.168.100.64 и DST=192.168.100.63. Далее, этот пакет виден в PREROUTING. То есть - стек его принял, он валидный и теперь система должна принять решение о маршрутизации. Маршрут к 192.168.100.0/24 есть и установлен через eth3.

Какого хрена пакет где-то протухает? :)

i82 ★★ ()
Ответ на: комментарий от i82

Трындец вы замудрили. Если вы делаете балансировку по интерфейсам, то ее можно делать через алиасы на ethX...

Далее, касательно D64 для каждой таблицы по идее надо прописывать везде:

ip route add 172.17.0.2/16 dev eth3 table 100..107
Но я не уверен. Вообще муторно. Но допустим, что и твой вариант работает. В любом случае пакет из tunX в сеть 172.17.0.2/16 должен прилетать на D63/eth11. Поток пакетов:

  • D64: 192.168.100.64 (eth3) -> 172.17.0.2 (eth11)
  • D63: 192.168.100.64 (eth11)/172.17.0.2 (MASQUERADE/SNAT) -> 172.17.0.2
gh0stwizard ★★★★★ ()
Последнее исправление: gh0stwizard (всего исправлений: 1)
Ответ на: комментарий от i82

Ты не указал еще про сеть на tunX интерфейсах. Если там такая же сеть как у eth3, тогда естественно ничего не будет работать. Потому что это физические интерфейсы и срабатывают правила по метрикам. И вообще что на другом конце этих tunX я тоже не понял.

gh0stwizard ★★★★★ ()
Ответ на: комментарий от gh0stwizard

Трындец вы замудрили. Если вы делаете балансировку по интерфейсам, то ее можно делать через алиасы на ethX...

Один tun не может прокачать 10G трафика, для этого в новых ядрах в него добавили поддержку очередей, но мы сейчас сидим на ядре 3.2, там этого нет. К слову сказать, наверное понятно, что tun нужен для шифрования. Боюсь, алиасами тут не помочь...

Что касается балансировки, то пытаемся достичь обработки (получения, прохождения IP-стека, шифрования в user-space) на одном ядре процессора, чтобы оптимально использовать его кеш. Других вариантов что-то в голову не приходит, как сие замутить :(

Про поток пакетов, то это должно быть так (D64):

ping -I eth0 172.17.0.2
1. [ IP (saddr=172.17.5.202, daddr=172.17.0.2) | ICMP (...) ] -> tun00e
2. [ IP (saddr=192.168.100.64, daddr=192.168.100.63) | UDP (sport=10000, dport=10000) | [IP...] ] -> eth3
i82 ★★ ()
Ответ на: комментарий от gh0stwizard

Так в том-то и дело, что НЕТ. Счётчики пакетов на eth3 не меняются...

i82 ★★ ()
Ответ на: комментарий от gh0stwizard

Сети там нет. На них только линк поднимается. IP-адрес не назначается, т.к. по-моему разумению не нужен.

i82 ★★ ()
Ответ на: комментарий от i82

Сети там нет. На них только линк поднимается. IP-адрес не назначается, т.к. по-моему разумению не нужен.

Ладно. Я не совсем всю идею понял. Кажись надо сделать следующее:

  • ip route add default dev tun00e table 100 - default надо прописывать с via, а не через dev: ip route add default via tun00e table 100
  • ip route add 172.17.0.2/16 dev eth3 table 100

Если итак не заработает (появление пакетов на eth3), тогда надо думать...

gh0stwizard ★★★★★ ()
Ответ на: комментарий от gh0stwizard

ip route add default dev tun00e table 100

Назначает ip-шнек 0.0.0.0/0, который перекрывает 172.17.0.2/16. Возможно проблема в этом. Надо метрику тогда проставить:

ip route add 172.17.0.2/16 dev eth3 weight 2 table 100

gh0stwizard ★★★★★ ()
Последнее исправление: gh0stwizard (всего исправлений: 1)
Ответ на: комментарий от gh0stwizard

Подозреваю, что что-то где-то не срастается, но что и где понять не могу пока. Не охота маршрутизацию в ядре смотреть, психологический барьер, так сказать :)

i82 ★★ ()
Ответ на: комментарий от gh0stwizard

Хрень какая-то. Что делаю, по пунктам, начиная с рабочей системы:

1) Проверка связи 192.168.100.64 <-> 192.168.100.63

# ping 192.168.100.63
PING 192.168.100.63 (192.168.100.63) 56(84) bytes of data.
64 bytes from 192.168.100.63: icmp_req=1 ttl=64 time=0.117 ms

2) Проверка связи 192.168.100.64 <-> 172.17.0.2

# ip route add 172.17.0.2 dev eth3
# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_req=1 ttl=64 time=0.094 ms

3) Запускаю приложение, поднимаю tun00e

# ip addr add 10.10.0.1 dev tun00e && ip link set dev tun00e up

4) Настраиваю policy-routing

# ip route add default via 10.10.0.1 dev tun00e table 100
# ip rule add fwmark 100 table 100

5) Проверяю - пинги до 172.17.0.2, пока всё OK...

6) Добавляю правило с установкой метки 100 на icmp-трафик в OUTPUT

# iptables -t mangle -A OUTPUT -p icmp -j MARK --set-mark 100

7) Проверяю - пинги до 172.17.0.2 и вижу, что трафиг заворачивается на tun00e, что логично:

~# tcpdump -nqv -i tun00e -X
tcpdump: listening on tun00e, link-type RAW (Raw IP), capture size 65535 bytes
13:38:40.714008 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.100.64 > 172.17.0.2: ICMP echo request, id 4497, seq 61, length 64
	0x0000:  4500 0054 0000 4000 4001 69ad c0a8 6440  E..T..@.@.i...d@
	0x0010:  ac11 0002 0800 6467 1191 003d a0c0 0b52  ......dg...=...R
	0x0020:  0000 0000 0ce5 0a00 0000 0000 1011 1213  ................
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
13:38:40.714056 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 112)
    192.168.100.64.10000 > 192.168.100.63.10000: UDP, length 84
	0x0000:  4500 0070 0000 4000 4011 f0ac c0a8 6440  E..p..@.@.....d@
	0x0010:  c0a8 643f 2710 2710 005c 0000 4500 0054  ..d?'.'..\..E..T
	0x0020:  0000 4000 4001 69ad c0a8 6440 ac11 0002  ..@.@.i...d@....
	0x0030:  0800 6467 1191 003d a0c0 0b52 0000 0000  ..dg...=...R....
	0x0040:  0ce5 0a00 0000 0000 1011 1213 1415 1617  ................
	0x0050:  1819 1a1b 1c1d 1e1f 2021 2223 2425 2627  .........!"#$%&'
	0x0060:  2829 2a2b 2c2d 2e2f 3031 3233 3435 3637  ()*+,-./01234567

То есть, на tun00e приходит ICMP пакет, генерируемый ping'ом (192.168.100.64 > 172.17.0.2). После чего, этот пакет оборачивается в IP+UDP и выходит в стек из этого же интерфейса с новыми адресами (192.168.100.64 > 192.168.100.63).

До этого места логика правильная.

8) На eth3 ничего нет.

9) Счётчики в iptables говорят, что ушедший с tun00e IP+UDP трафик попадает в PREROUTING, но дальше его нет. На eth3 он почему-то так и не доходит.

Хелп :)

i82 ★★ ()
Ответ на: комментарий от i82

5) Проверяю - пинги до 172.17.0.2, пока всё OK...

Как? Надо проверять указанием интерфейса:
ping -I tun00e 172.17.0.2
ping -I eth3 172.17.0.2

Счётчики в iptables говорят, что ушедший с tun00e IP+UDP трафик попадает в PREROUTING, но дальше его нет. На eth3 он почему-то так и не доходит.

Забей на счетчики. Смотреть надо все через tcpdump.

И я не увидел: ip route add 172.17.0.2/16 dev eth3 table 100

gh0stwizard ★★★★★ ()
Ответ на: комментарий от gh0stwizard

Как? Надо проверять указанием интерфейса:

ping -I eth3 172.17.0.2

# ping -I eth3 172.17.0.2 &
# tcpdump -nqv -i tun00e -X
tcpdump: listening on tun00e, link-type RAW (Raw IP), capture size 65535 bytes
14:05:55.460134 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.100.64 > 172.17.0.2: ICMP echo request, id 4606, seq 11, length 64
	0x0000:  4500 0054 0000 4000 4001 69ad c0a8 6440  E..T..@.@.i...d@
	0x0010:  ac11 0002 0800 c405 11fe 000b 03c7 0b52  ...............R
	0x0020:  0000 0000 4d05 0700 0000 0000 1011 1213  ....M...........
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
14:05:55.460180 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 112)
    192.168.100.64.10000 > 192.168.100.63.10000: UDP, length 84
	0x0000:  4500 0070 0000 4000 4011 f0ac c0a8 6440  E..p..@.@.....d@
	0x0010:  c0a8 643f 2710 2710 005c 0000 4500 0054  ..d?'.'..\..E..T
	0x0020:  0000 4000 4001 69ad c0a8 6440 ac11 0002  ..@.@.i...d@....
	0x0030:  0800 c405 11fe 000b 03c7 0b52 0000 0000  ...........R....
	0x0040:  4d05 0700 0000 0000 1011 1213 1415 1617  M...............
	0x0050:  1819 1a1b 1c1d 1e1f 2021 2223 2425 2627  .........!"#$%&'
	0x0060:  2829 2a2b 2c2d 2e2f 3031 3233 3435 3637  ()*+,-./01234567

На eth3 данных нет.

ping -I tun00e 172.17.0.2

# ping -I tun00e 172.17.0.2 &
# tcpdump -nqv -i tun00e -X
tcpdump: listening on tun00e, link-type RAW (Raw IP), capture size 65535 bytes
14:08:13.060110 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    10.10.0.1 > 172.17.0.2: ICMP echo request, id 4613, seq 46, length 64
	0x0000:  4500 0054 0000 4000 4001 848b 0a0a 0001  E..T..@.@.......
	0x0010:  ac11 0002 0800 d7f5 1205 002e 8dc7 0b52  ...............R
	0x0020:  0000 0000 b5ea 0000 0000 0000 1011 1213  ................
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
14:08:13.060156 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 112)
    192.168.100.64.10000 > 192.168.100.63.10000: UDP, length 84
	0x0000:  4500 0070 0000 4000 4011 f0ac c0a8 6440  E..p..@.@.....d@
	0x0010:  c0a8 643f 2710 2710 005c 0000 4500 0054  ..d?'.'..\..E..T
	0x0020:  0000 4000 4001 848b 0a0a 0001 ac11 0002  ..@.@...........
	0x0030:  0800 d7f5 1205 002e 8dc7 0b52 0000 0000  ...........R....
	0x0040:  b5ea 0000 0000 0000 1011 1213 1415 1617  ................
	0x0050:  1819 1a1b 1c1d 1e1f 2021 2223 2425 2627  .........!"#$%&'
	0x0060:  2829 2a2b 2c2d 2e2f 3031 3233 3435 3637  ()*+,-./01234567

На eth3 данных нет.

И я не увидел: ip route add 172.17.0.2/16 dev eth3 table 100

Не понимаю этого. По моей логике, в таблице 100 должно быть ТОЛЬКО одно правило - add default dev tun00e, дабы всё, что туда попадало улетало на tun00e.

Но я добавил то, что ты предложил. В итоге, ping'и стали улетать напрямую с eth3, не попадая на tun00e. Смысл?..

i82 ★★ ()
Ответ на: комментарий от i82

Смысл?..

А тебе что нужно? Как связан tunX с eth3 или D63/eth11? В твоей схеме никак. Я могу предложить правило для iptables, которое будет делать тоже самое: отправлять пакеты с eth3. Тебе это надо?

gh0stwizard ★★★★★ ()
Ответ на: комментарий от i82

В итоге, ping'и стали улетать напрямую с eth3, не попадая на tun00e

Если приложение сформирует пакет на tunX, то правило маршутизации все сделает за тебя: перенаправит пакет на другой интерфейс.

gh0stwizard ★★★★★ ()
Последнее исправление: gh0stwizard (всего исправлений: 1)
Ответ на: комментарий от gh0stwizard

Мне надо, чтобы пакет для 172.17.0.2, генерируемый локальными ping'ом уходя, залетал на tun00e, там оборачивался в IP+UDP и, далее, обернутый, уходил на eth3. Сейчас, почему-то он до eth3 не доходит...

Как связан tunX с eth3 или D63/eth11? В твоей схеме никак.

Я рассматриваю tunX как точку входа IP-трафика для обработки в user-space приложении. При этом, локальный трафик от ping посредством маркировки в цепочке OUTPUT удаётся завернуть на соответствующий tunX. Но выходя с tunX пакет куда-то пропадает, проходя, однако, через PREROUTING:

[57005.878297] (OUTPUT) IN= OUT=eth3 SRC=192.168.100.64 DST=172.17.0.2 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=2834 SEQ=133 
[57005.878400] (PREROUTING) IN=tun00e OUT= MAC= SRC=192.168.100.64 DST=192.168.100.63 LEN=112 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=UDP SPT=10000 DPT=10000 LEN=92
i82 ★★ ()
Последнее исправление: i82 (всего исправлений: 2)
Ответ на: комментарий от gh0stwizard

Если приложение сформирует пакет на tunX, то правило маршутизации все сделает за тебя: перенаправит пакет на другой интерфейс.

Да, но почему-то этого не происходит :(

i82 ★★ ()
Ответ на: комментарий от i82

Да, но почему-то этого не происходит :(

Cформирует если добавишь роут в нужную таблицу 100..107. Проверь сам. Проверять без приложения можно через ping -I tun00e 172.17.0.2, можно и так ping -I 10.0.0.1 172.17.0.2

gh0stwizard ★★★★★ ()
Ответ на: комментарий от gh0stwizard

Cформирует если добавишь роут в нужную таблицу 100..107. Проверь сам. Проверять без приложения можно через ping -I tun00e 172.17.0.2, можно и так ping -I 10.0.0.1 172.17.0.2

Объясни, может чего не понимаю. Таблица применяется только для маркированных пакетов, например с fwmark 100. Пакеты маркируются в цепочке OUTPUT, то есть это те пакеты, которые идут от локального процесса (т.е. ping'а). Далее, применяется policy-routing, пакет попадает на tunX, обрабатывается и возвращается в стек попадая при этом уже в PREROUTING, т.к. стек считает, что в систему с устройства пришёл новый пакет. Маркировка в PREROUTING отсутствует, т.к. считается, что система сама знает куда и что передавать (уж 92.168.100.64 > 192.168.100.63 точно). Но этого не происходит?

Добавил я маршрут в 100 таблицу и всё летит на eth3, не попадая в tun (ping -I tun00e 172.17.0.2).

i82 ★★ ()
Ответ на: комментарий от gh0stwizard

Вот это правило, применяемое к инкапсулированным пакетам в цепочке PREROUTING даёт результат. Действительно, через eth3 теперь идёт трафик, который видно на удалённой стороне, т.е. на D63.

iptables -t mangle -A PREROUTING -p udp --sport=10000 --dport=10000 -j TEE --gateway 192.168.100.63

Вопрос в том, почему это работает, а без этого правила - нет, ведь пакеты в PREROUTING и так имею адрес назначения 192.168.100.63???

i82 ★★ ()
Ответ на: комментарий от i82

Вопрос в том, почему это работает

TEE клонирует пакет, а дальше он улетает как обычно сразу через eth3. Можешь оставить так. Вообще, я не совсем понимаю задачу и не могу дать решение :) Вот на этапе прихода пакета в tunX тебе нужно чтобы он трансформировался и передался из eth3 не меняя адрес получателя/назначения. Следовательно, правило TEE это и делает - дублирует пакет и указывает через какой шлюз его надо отправить. В итоге из таблицы маршрутизации этот пакет и вылетит из нужного интерфейса (eth3). Тогда балансировка по процам грубо говоря вообще не нужна.

gh0stwizard ★★★★★ ()
Ответ на: комментарий от gh0stwizard

Бррр...

В PREROUTING попадает пакет (я его поймал tcpdump'ом на tun00e):

14:08:13.060156 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 112)
    192.168.100.64.10000 > 192.168.100.63.10000: UDP, length 84
	0x0000:  4500 0070 0000 4000 4011 f0ac c0a8 6440  E..p..@.@.....d@
	0x0010:  c0a8 643f 2710 2710 005c 0000 4500 0054  ..d?'.'..\..E..T
	0x0020:  0000 4000 4001 848b 0a0a 0001 ac11 0002  ..@.@...........
	0x0030:  0800 d7f5 1205 002e 8dc7 0b52 0000 0000  ...........R....
	0x0040:  b5ea 0000 0000 0000 1011 1213 1415 1617  ................
	0x0050:  1819 1a1b 1c1d 1e1f 2021 2223 2425 2627  .........!"#$%&'
	0x0060:  2829 2a2b 2c2d 2e2f 3031 3233 3435 3637  ()*+,-./01234567

В нём чёрным по белому :) написано, что это пакет от 192.168.100.64 к 192.168.100.63. Что ещё нужно для маршрутизации??? Всё же есть!

i82 ★★ ()
Ответ на: комментарий от gh0stwizard

Можешь оставить так.

Ну не хочется как-то 10G трафика клонировать :)

i82 ★★ ()
Ответ на: комментарий от i82

net.ipv4.conf.all.rp_filter = 1

Ну теперь нужно сходить в гугл, прочитать что это такое и подумать, как это будет работать относительно пакетов, приходящих с tunX-интерфейса.

mky ★★★★★ ()
Ответ на: комментарий от i82

Всё же есть!

Честно скажу, что идея с tunX где адресное пространство фактически в вакууме не даст никакого профита. Особенно в вопросе балансировки. Аналогично можно просто маркировать пакет и навешивать его на cpu и для обычного ethX. Поскольку интерфейс один, то все будет упираться в него, а не в cpu, как кажется. Только раскидаете равномерно пакеты.
Если нужно тупо нагрузить канал, то сойдут алиасы, как я говорил ранее.
Если нужно протестировать нагрузку на ваших tun'ах, то надо написать сначала серверную и клиентские части. И уже по ним гонять трафик.
В твоем случае, ядро через маршрутизацию само делает, то что необходимо. Пишет пакет из того интерфейса откуда оно должно вылететь.
Как решается вопрос в обход rp_filter и минуя маршутизацию через iptables:

iptables -t nat -I POSTROUTING -d 172.17.0.2/16 -o eth3 -j MASQUERADE
Предложу улучшенную его версию (для балансировки): создаете алиасы для eth3 и для каждого tunX делаете собственный SNAT (взамен грубого masquerade).

gh0stwizard ★★★★★ ()
Последнее исправление: gh0stwizard (всего исправлений: 1)
Ответ на: комментарий от gh0stwizard

При чём тут source-based routing? rp_filter рубит пакеты, приходящие из интерфейса, с «неправильным» (по главной таблице маршрутизации) src-адресом. Пакет рубится в стадии определения маршрута, то есть после прохождения mangle PREROUTING, но до остальных цепочек, именно как ТС и наблюдал и по поводу чего спрашивал.

А по поводу работоспособности этой схемы с восьмью тунелями ТС не спрашивал, ИМХО, лучше бы они наняли кернел-хакера, чтобы написали модуль ядра, осуществлящий шифрацию без user-space.

mky ★★★★★ ()
Ответ на: комментарий от mky

При чём тут source-based routing?

При том, что rp_filter косвенно этого вопроса касается.

gh0stwizard ★★★★★ ()
Ответ на: комментарий от mky

Сделал следующее:

for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo "0" > $i; done

Не помогло. Трафик на eth3 так и не заходит. Включил логи martians-пакетов:

for i in /proc/sys/net/ipv4/conf/*/log_martians; do echo "1" > $i; done

После чего в dmesg наблюдаю сообщения:

[139407.882561] martian source 192.168.100.63 from 192.168.100.64, on dev tun05e
[139408.881541] martian source 192.168.100.63 from 192.168.100.64, on dev tun05e
[139409.880623] martian source 192.168.100.63 from 192.168.100.64, on dev tun06e
[139410.879647] martian source 192.168.100.63 from 192.168.100.64, on dev tun06e
[139411.878648] martian source 192.168.100.63 from 192.168.100.64, on dev tun07e

То есть ядро не может найти маршрут, когда пакет поступает с tunX-интерфейса. Однако, маршрут же есть в целую подсеть (192.168.100.0/24):

# ip route show table main
default via 172.17.4.1 dev eth0  metric 100 
172.17.0.2 dev eth3  scope link 
172.17.4.0/22 dev eth0  proto kernel  scope link  src 172.17.5.202 
192.168.100.0/24 dev eth3  scope link 

Чувствую, что осталось немного. В чём здесь дело?

i82 ★★ ()
Ответ на: комментарий от i82

net/ipv4/route.c

/*
 *      NOTE. We drop all the packets that has local source
 *      addresses, because every properly looped back packet
 *      must have correct destination already attached by output routine.
 *
 *      Such approach solves two big problems:
 *      1. Not simplex devices are handled properly.
 *      2. IP spoofing attempts are filtered with 100% of guarantee.
 *      called with rcu_read_lock()
 */

внезапненько так..

i82 ★★ ()
Ответ на: комментарий от i82

Да, чем дальше, тем хреновее в Линуксе обстоит дело с маршрутизацие пакетов, ядро считает себя всё умнее и умнее. martian source . Вот здесь вот http://www.spinics.net/lists/netdev/msg195319.html в схожей ситуации советуют ставить src-адрес пакета из tun-интерфейса в 0.0.0.0 и тогда ядро само должно подправить адрес на нужный, попробуйте.

mky ★★★★★ ()
Ответ на: комментарий от mky

Угу, в последнем сообщении - оно. Только там вопрос с 0.0.0.0, а не утверждение. Проверил, ядро заместо 0.0.0.0 ничего не подставляет.

i82 ★★ ()
Ответ на: комментарий от mky

А по поводу работоспособности этой схемы с восьмью тунелями ТС не спрашивал, ИМХО, лучше бы они наняли кернел-хакера, чтобы написали модуль ядра, осуществлящий шифрацию без user-space.

Вопрос спорный с тем, где лучше шифровалку делать. Вообще, задача обрабатывать 10G трафик. Один TUN столько не прокачивает, к сожалению.

i82 ★★ ()
Ответ на: комментарий от i82

Да, но пакеты то пошли? Или вместо 0.0.0.0 можно взять другой ip-адрес, не назначенный на интерфейс. А на выходе их можно подправить с помощью SNAT.

mky ★★★★★ ()
Ответ на: комментарий от mky

Пакеты также дропаются как martians:

[11589.078309] martian source 192.168.100.63 from 0.0.0.0, on dev tun04e
[11590.077359] martian source 192.168.100.63 from 0.0.0.0, on dev tun05e

Но, если заместо адреса отправителя ставить, например, 192.168.100.65 (там, где на выходном интерфейсе адрес 192.168.100.64), то пакеты да, идут.

i82 ★★ ()
Ответ на: комментарий от i82

Вопрос спорный, но, ИМХО, в ядре для повышения производительности возможностей больше, пакеты можно ловить до цепочек iptables/conntrack. Да и восемь процессов, реализующих восемь тунелей, нужно мониторить и защищать от OMM-killer'а.

mky ★★★★★ ()
Ответ на: комментарий от mky

Да и восемь процессов, реализующих восемь тунелей, нужно мониторить и защищать от OMM-killer'а.

Это будет попроще, нежели защитить от #GP фолта ядро :) А в целом, согласен, в ядре возможностей побольше да и данные туда-сюда гонять не нужно. Однако, шифровалка, она же не обстрактна, туда ключи надо загружать etc. То есть в ней кроме логики шифрования есть ещё и инфраструктура, а вот как её в ядро затащить тогда - это уже вопрос. И будет ли в итоге решение надёжно и поддерживаемо, не знаю.

i82 ★★ ()
Ответ на: комментарий от i82

Ну ключи то в ядро передают, ipsec вполне работает, в user space только демон, занятый обменом ключами. Раньше ещё был cipe (шифрование в ядре, в userspace демон, который биндится на заданный udp-сокет и тем самым резервирует его для модуля в ядре).

А вот с поддержкой, да, будет тяжко. ЕМНИП, тот же cipe был одним патчем для всех 2.4.x ядер, а когда пошло 2.6.x, то, чуть ли ни для кажого ядра был свой патч и на 2.6.19 всё и загнулось.

p.s. Если у вас заработает это восьмитунельное решение, черкните сюда, какая скорость получилась.

mky ★★★★★ ()
Ответ на: комментарий от mky

OK, если что выйдет. Вопрос в догонку. В PREROUTING на пакет ставиться метка с использованием `-j MARK --set-mark=200` (через -j LOG видно, она есть). Далее, предполагается policy-based маршрутизации по метке 200 на таблицу 200 в которой одна запись `default dev tun00d`. То есть всё то же самое, что делали при отправке, но теперь на приём. Не работает маршрутизация почему-то входных пакетов по интерфейсам...... Что не так может быть здесь?

i82 ★★ ()
Ответ на: комментарий от i82

Адреса в пакетах какие? Если dst-адрес на локальный интерфейс, то он туда и пойдёт — ″ip route show table local″. И DNAT вам тут тоже не поможет, потому что conntrack. Получается, что вам нужно на отправляющей стороне формировать такие пакеты, чтобы они не попадали на приёмной в одну запись conntrack, тогда их можно будет развести каждый в свой тунель.

Либо делать транспортные пакеты тунеля с адресов, не принадлежащих этим D63 и D64, то есть формировать пакеты, допустим 192.168.100.60<->192.168.100.61, а на каждом из хостов прописывать соотв. маршрут:

ip route add 192.168.100.61 via 192.168.100.64

mky ★★★★★ ()
Ответ на: комментарий от mky

Всё, схему собрал. Тестирую, пока не айс. Почему-то на D63 входящие пакеты сыпятся в стек в один поток (в PREROUTING метка всегда соответствует CPU#5).. Это не понятно, т.к вроде бы прерывания от сетевухи по очередям TxRx-{0-7} распределены, RPS настроил как-то. Чего-то не хватает, очевидно.

i82 ★★ ()
Ответ на: комментарий от i82

Я думаю, что сначала нужно убедится, что RPS действительно работает, на обычном трафике, без шифрации и тунелей. Вроде как его включение/выключении должно быть заметно по результатам теста netperf. Потом посмотреть /proc/interrupts и /proc/softirqs.

Как я понял, при RPS аппаратные прерывания от сетёвки всё одно обрабатывает один процессор, а остальные загружаются потом через softirq. Возможно модуль iptables показывает то самый CPU, обрабатывающий аппаратные прерывания.

mky ★★★★★ ()
Ответ на: комментарий от mky

Как я понял, при RPS аппаратные прерывания от сетёвки всё одно обрабатывает один процессор, а остальные загружаются потом через softirq.

На сколько я понял, изучая код ядра, аппаратные прерывания должны обрабатывать разные ядра. Пакеты, выбранные из соответствующих очередей сетевой карты будут помещаться в backlog-очереди этих процессоров и, далее, планируется их softirq-обработка, которая, по идее, также должна быть осуществлена в рамках каждого из процессоров. Таким образом, по моим представлениям, один процессор может вести свой набор пакетов начиная от устройства и заканчивая приложением пользователя (сокетом, tun-устройством и т.д.)

Возможно модуль iptables показывает то самый CPU, обрабатывающий аппаратные прерывания.

Модуль проверят соответствие идентификатора процессора, указанного в правиле, идентификатору обрабатывающего пакет процессора. Если совпадают - ставит метку.

i82 ★★ ()
Последнее исправление: i82 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.