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

Флаг DF с ip_no_pmtu_disc в LXC

 , , , ,


0

1

Есть вредная железка X, которую нужно мониторить по SNMP и которая в упор не отвечает на IP-пакеты с флагом DF (баг в прошивке, который неизвестно как, когда и кто пофиксит).

Есть софт, живущий в контейнере (systemd-nspawn), который опрашивает snmpget'ом разные железки, в том числе и железку X.

Проблема в том, что все пакеты от софта в контейнере шлются с установленным флагом DF. Если на гипервизоре выставить ip_no_pmtu_disc=1 и запустить софт прямо на том же гипервизоре, а не в контейнере, то всё работает. Однако ip_no_pmtu_disc=1 не влияет на софт в контейнере — пакеты всё равно шлются с флагом DF.

Как быть?

Проверялось на Arch'е, CentOS'е 7, Ubuntu в systemd-nspawn и docker'е — везде одно и то же.

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

NFQUEUE — это хорошая идея, спасибо.

Нашёл ещё такое:

tc filter add dev eth0 parent ffff: u32 match u32 0 0 action pedit munge ip df clear

Правда, в CentOS команда невалидна, видимо, юзерспейс старый. А в Арче почему-то эффекта не имеет. Может, я неправильно выстроил иерархию. А документации внятной на munge нет.

post-factum ★★★★★
() автор топика

так в контейнере свой NET_NS

В контейнере не пробовал сделать ip_no_pmtu_disc=1 ?

vel ★★★★★
()
Ответ на: комментарий от post-factum

на 4.4.14 в контейнере нормально работает ip_no_pmtu_disc

root@wfctl:~# sysctl net.ipv4.ip_no_pmtu_disc=1
net.ipv4.ip_no_pmtu_disc = 1
root@wfctl:~# tcpdump -ni vlan0004 -s0 -v  udp and host 10.252.24.37
tcpdump: listening on vlan0004, link-type EN10MB (Ethernet), capture size 65535 bytes
00:04:07.543224 IP (tos 0x0, ttl 64, id 44507, offset 0, flags [none], proto UDP (17), length 71)
    10.252.24.1.33831 > 10.252.24.37.161:  { SNMPv2c { GetRequest(28) R=794529125  .1.3.6.1.2.1.1.1.0 } } 
00:04:07.543893 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 86)
    10.252.24.37.161 > 10.252.24.1.33831:  { SNMPv2c { GetResponse(43) R=794529125  .1.3.6.1.2.1.1.1.0="D-Link DAP-2690" } } 

root@wfctl:~# sysctl net.ipv4.ip_no_pmtu_disc=0
net.ipv4.ip_no_pmtu_disc = 0
root@wfctl:~# tcpdump -ni vlan0004 -s0 -v  udp and host 10.252.24.37
tcpdump: listening on vlan0004, link-type EN10MB (Ethernet), capture size 65535 bytes
00:04:47.935795 IP (tos 0x0, ttl 64, id 63365, offset 0, flags [DF], proto UDP (17), length 71)
    10.252.24.1.46952 > 10.252.24.37.161:  { SNMPv2c { GetRequest(28) R=505027713  .1.3.6.1.2.1.1.1.0 } } 
00:04:47.936520 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 86)
    10.252.24.37.161 > 10.252.24.1.46952:  { SNMPv2c { GetResponse(43) R=505027713  .1.3.6.1.2.1.1.1.0="D-Link DAP-2690" } } 

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

Наверное, systemd-nspawn чудит что-то с неймспейсами. Нужно будет покурить детальнее, а то сходу инфы мало. Спасибо за наводку.

post-factum ★★★★★
() автор топика
Ответ на: комментарий от post-factum

Да, похоже раньше munge не умел всяких df и прочих флагов, но в CentOS 6, вроде, munge есть, там как-то должно выглядеть:

... action pedit munge offset 6 u8 set 0x00 retain 0xbf \
pipe action csum ip
А почему это не работает нужно изучать отдельно, у этого фильтра есть срабатотки в ″tc -s″?

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

Я тут ещё на всякий случай нашёл старый ipt_DF и даже заставил его компилиться. Если будут вопросы с портированием, поможешь?

post-factum ★★★★★
() автор топика
Ответ на: комментарий от post-factum

зачем нужны костыли, если работает ip_no_pmtu_disc?

IMHO намного полезнее будет разобраться как в systemd-nspawn изменить sysctl до запуска процесса.

В худшем случае процесс можно запустить через shell-обертку

#!/bin/sh
sysctl net.ipv4.ip_no_pmtu_disc=1
exec process

а ipt_DF ты как собирался использовать? на хосте или в контейнере ?

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

Я просто хочу рассмотреть доступные варианты. С nspawn буду разбираться отдельно из принципа, т.к. он тоже должен работать.

Использовать ipt_DF в контейнере хочу, очевидно.

post-factum ★★★★★
() автор топика
Ответ на: комментарий от post-factum

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

А где исходники можно взять ? В гугле есть только патч для iptables, а ядерный модуль что-то не найти.

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

Для 3.2 было. Я днём push сделаю, дам ссылку.

post-factum ★★★★★
() автор топика
Ответ на: комментарий от post-factum

на 3.18 ядерный модуль собрался без проблем и даже работает.

на 4.4.14 собирается, работоспособность не проверял.

А нафига это в виде патчей ? imho проще в виде отдельного проекта http://devel.aanet.ru/ndpi/DF/ipt_DF.tar.gz

vel ★★★★★
()
Ответ на: комментарий от post-factum

imho "-j DF --clean" - избыточно. Т.к. DF умеет только сбрасывать флаг было бы логично иметь просто "-j DF"

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

Я думаю, это изначально была заготовка к тому, чтобы флаг можно было принудительно и выставлять тоже.

Можно попробовать дописать, хотя хз, кому это может понадобиться.

post-factum ★★★★★
() автор топика
Ответ на: комментарий от post-factum

В продакшне трюк с NFQUEUE работает, кстати.

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

Пооветовали тут ещё один способ — добавить специфик через ip route с параметром mtu lock:

              mtu lock MTU
                     the MTU along the path to the destination. If the modifier lock is not used, the MTU may be updated by the
                     kernel due to Path MTU Discovery. If the modifier lock is used, no path MTU discovery will be tried, all
                     packets will be sent without the DF bit in IPv4 case or fragmented to MTU for IPv6.

Таки тоже работает.

post-factum ★★★★★
() автор топика
Ответ на: комментарий от post-factum

Сделал снятие DF-флага на SL 6 (RHEL 6) с ядром 2.6.32, правда, получилось извращение, но зато получилось без всяких патчей, компиляции и т.д. Оставлю это здесь, чтобы не забыть.

# tc qdisc add dev vlan2 root handle 1: prio

tc filter add                            \
dev vlan2                                 \
parent 1:                                \
pref 10                                  \
protocol ip                              \
handle ::1                               \
u32                                      \
match ip protocol 1 0xff                 \
match ip src 192.168.2.220/32            \
match ip df                              \
action pedit munge offset 6 u8 set 0x00 retain 0xbf \
pipe action pedit munge offset 14 u8 set 66 \
pipe action nat egress 192.168.66.220 192.168.2.220

Вывод/удаления фильтра командой:

# tc -s f ls dev vlan2

# tc filter del dev vlan2 parent 1: pref 1

Начало фильтра обычное, указывается с какого хоста брать пакеты и что пакеты должны быть с флагом DF, можно указать какой dst адрес/порт должны быть у пакетов. Далее идёт ″action pedit″, меняющий флаг DF. Флаг сбрасывается, но в результате получается пакет с неправильной контрольной суммой ip-заголовка. А ″action csum″ в RHEL 6 нет и единственно, что изменяет контрольную сумму это ″action nat″, но nat её не пересчитывает, а изменяет, в соответствии с изменяемым ip адресом.

Поэтому сначала с помощью ″action pedit″ меняется ip-адрес, чтобы контрольня сумма стала верной, а потом этот ip-адрес снова меняется с помощью ″action nat″. 2 = 00000010, 66 = 01000010, инвертируем в байте с чётным смещением 6-ой бит (смещение как у флага DF).

mky ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.