Как заблокировать входящие фрагменты IPv6?

У меня проблема с настройкой брандмауэра. Я хотел бы заблокировать все фрагментированные пакеты IPv6 в конкретном интерфейсе. Итак, я попробовал:

# ip6tables -A INPUT -d <ipv6_address> -i eth0 -m ipv6header --header ipv6-frag --soft -j DROP

Но фрагментированный трафик IPv6 продолжает поступать.

Я также нашел эту ссылку: https://www.secfu.net/2015/03/25/how-to-block-incoming-ipv6-fragments-in-latest-red-hat-releases/ которая объясняет, что ipv6- frag или frag не блокируют фрагментированный трафик ipv6 в последней версии CentOS, поскольку после идентификатора ошибки 1011214 (kernel-2.6.32-437.el6) netfilter начал обрабатывать повторно собранный пакет вместо фрагментов, как это делает IPv4. В той же статье предлагается использовать nftables, которые будут выглядеть следующим образом:

table ip6 filter {
   chain preroute500 {
      type filter hook prerouting priority -500; policy accept;
      ip6 nexthdr ipv6-frag counter packets 2 bytes 2104
   }
 } 

Как я могу сделать что-то подобное, используя ip6tables?

# cat /etc/system-release
CentOS Linux release 7.5.1804 (Core)

# uname -r
5.0.8-1.el7.elrepo.x86_64

1 ответ

Решение

Как уже было сказано, вы должны быть уверены, что блокирование фрагментов - это действительно ваша цель, а не метод, который, по вашему мнению, лучше всего подходит для вашей цели, в то время как существуют лучшие методы. Во всяком случае, для чего это стоит, вы должны:

  • используйте достаточно свежее ядро. Функция была добавлена ​​в ядро ​​4.16. CentOS использует 3.10. Хотя многие функции перенесены в бэкпорт (начиная с nftables, который недоступен в ядре vanilla 3.10, но есть в RHEL/CentOS 3.10), эта функция не была перенесена в последнюю версию ядра CentOS 7.6. Поскольку вы используете ядро ​​"elrepo" 5.0.8, эта функция присутствует. Вот описание функции и почему она существует (в основном для маршрутизации или, по крайней мере, для ситуаций с брандмауэрами без сохранения состояния / без NAT):

    Сетевой фильтр: nf_defrag:

    Пропустить дефрагментацию, если установлено NOTRACK. Контрарагивание дефрагментации необходимо, только если какой-либо модуль, такой как CONNTRACK или NAT, явно запрашивает его. Для простых сценариев пересылки дефрагментация не требуется и может быть пропущена, если в правиле установлен NOTRACK.

    Поскольку дефрагментация conntrack в настоящее время имеет более высокий приоритет, чем необработанная таблица, настройка NOTRACK не является достаточной. Нам нужно перейти на более высокий приоритет только для iptables.

    Это достигается введением параметра модуля raw_before_defrag, который позволяет изменить приоритет необработанной таблицы для ее размещения перед дефрагментацией. По умолчанию параметр отключен, и приоритет необработанной таблицы - NF_IP_PRI_RAW для поддержки устаревшего поведения. Если параметр модуля включен, то приоритет необработанной таблицы устанавливается на NF_IP_PRI_RAW_BEFORE_DEFRAG.

  • (при необходимости удалите существующие необработанные правила ip6tables, выгрузите и) загрузите ip6table_raw модуль с параметром raw_before_defrag=1 Таким образом, хук необработанного кода (в PREROUTING) переключается с prio -300 на -450, до дефрагментации -400.

    modprobe ip6table_raw raw_before_defrag=1
    

    который должен получить сообщение ядра, как ip6table_raw: Enabling raw table before defrag

Сейчас в raw таблица, и, вероятно, имеет смысл только в PREROUTING, ip6tables сможет видеть фрагменты. Он может отфильтровать их там, или выбрать пропустить conntrack (iptables -t raw -A PREROUTING ... -j CT --notrack), который, как объясняется в патче, также будет пропускать дефрагментацию, позволяя другим цепочкам обрабатывать их (конечно, не включая nat цепочки таблиц или любые другие функции, связанные с conntrack).


Обратите внимание, что для того, чтобы увидеть проблему, описанную в тестовом сетевом пространстве имен, необходимо сначала искусственно включить операции conntrack для зависимости conntrack от defrag, которая не активируется до первой необходимости. Вот пример сетевого пространства имен:

ip netns add sender
ip netns add receiver
ip -n sender   link add veth0 address 02:00:00:00:00:01 type veth peer netns receiver name veth0 address 02:00:00:00:00:02
ip -n sender   link set veth0 up
ip -n receiver link set veth0 up

Это работает:

# ip netns exec sender ping6 -s 4000 fe80::ff:fe00:2%veth0
PING fe80::ff:fe00:2%veth0(fe80::ff:fe00:2%veth0) 4000 data bytes
4008 bytes from fe80::ff:fe00:2%veth0: icmp_seq=1 ttl=64 time=0.069 ms
^C

После этого он больше не будет работать:

ip netns exec receiver ip6tables -A INPUT -m ipv6header --header ipv6-frag --soft -j DROP

Как только conntrack активирован в пространстве имен сети с этими командами, по-видимому, приводящими к неработоспособности:

ip netns exec receiver ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED
ip netns exec receiver ip6tables -D INPUT -m conntrack --ctstate ESTABLISHED

дефрагментация ipv6 также активирована. Теперь предыдущий пинг будет работать всегда, потому что правило в INPUT видит только дефрагментированные пакеты.

С ранее (повторно) загруженным ip6table_raw модуль с параметром raw_before_defrag=1, это восстановит блокировку фрагментированного пинга:

ip netns exec receiver ip6tables -t raw -A PREROUTING -m ipv6header --header ipv6-frag --soft -j DROP

В качестве альтернативы, интересные пакеты могут быть помечены как notrack, таким образом освобождая их от conntrack, таким образом не получая обработки дефрагментации, что позволяет их снова фильтровать с помощью правила в filter/INPUT цепь. Так что вместо предыдущего raw Правило, это также будет блокировать пинг-пакеты (3 из них на пинг), но на этот раз снова в filter/INPUT цепь:

ip netns exec receiver ip6tables -t raw -A PREROUTING -m ipv6header --header ipv6-frag --soft -j CT --notrack

Это только пример, который не имеет особого смысла.

Другие вопросы по тегам