Я тут задался вопросом, надо ли пересобирать пакеты на маршрутизаторе, который фильтрует трафик ACL. Другими словами, использовать или не использовать ip virtual-reassembly.

RFC-1858 описывает различные атаки с использованием ip fragmentation. Нас интересует случай IP fragment overlap при котором последующий фрагмент перепишет L4 информацию предыдущего при сборке пакета на destination хосте. Если, например, удалось бы в первом фрагменте объявить, что это SYN пакет на порт tcp/80, а во втором переписать этот порт на tcp/3306, установив Fragment Offset в 0, то мы получили бы отличный способ ходить на закрытые ACL порты.

Я нашел вот этот документ, который рассказывает, что это невозможно сделать. Не поверив написанному, я решил проверить сам.

Взял ненужный 2600 маршрутизатор и сделал на нем

interface Ethernet0/0
ip address 10.50.200.200 255.255.0.0 secondary
ip address 10.1.200.200 255.255.0.0
ip access-group test in
 
ip access-list extended test
permit tcp any host 10.50.200.100 eq www
deny   ip any any

Использовал hping для генерации пакетов и tethereal, чтобы смотреть что проходит, а что нет.

# hping3  -S 10.50.200.100 -p 80
HPING 10.50.200.100 (ath0 10.50.200.100): S set, 40 headers + 0 data bytes
len=46 ip=10.50.200.100 ttl=64 DF id=0 sport=80 flags=SA seq=0 win=5840 rtt=54.7 ms
len=46 ip=10.50.200.100 ttl=64 DF id=0 sport=80 flags=SA seq=1 win=5840 rtt=1.8 ms
len=46 ip=10.50.200.100 ttl=64 DF id=0 sport=80 flags=SA seq=2 win=5840 rtt=1.9 ms
 
--- 10.50.200.100 hping statistic ---
3 packets tramitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 1.8/19.5/54.7 ms

Проходит. Ничего удивительного, мы разрешили порт 80 в ACL

А на порт 81

# hping3  -S 10.50.200.100 -p 81
HPING 10.50.200.100 (ath0 10.50.200.100): S set, 40 headers + 0 data bytes
ICMP Packet filtered from ip=10.1.200.200 name=UNKNOWN   
ICMP Packet filtered from ip=10.1.200.200 name=UNKNOWN   
ICMP Packet filtered from ip=10.1.200.200 name=UNKNOWN   
 
--- 10.50.200.100 hping statistic ---
4 packets tramitted, 3 packets received, 25% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

не проходит, маршрутизатор отвечает ICMP . Опять-таки, ничего удивительного.

Поставили флаг More Fragments, Fragment Offset = 0.

# hping3 -x -S 10.50.200.100 -p 80
HPING 10.50.200.100 (ath0 10.50.200.100): S set, 40 headers + 0 data bytes
 
--- 10.50.200.100 hping statistic ---
6 packets tramitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

Ответов не видно, потому-что на destination они не собираются из-за отсутствия last fragment.

Но если посмотреть в tethereal

  0.000000    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=0)
  1.000342    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=0)
  2.000619    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=0)
  3.004922    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=0)

То видно, что пакеты доходят до хоста.

Флаг More Fragments, Fragment Offset = 0, порт 81

# hping3 -x -S 10.50.200.100 -p 81
HPING 10.50.200.100 (ath0 10.50.200.100): S set, 40 headers + 0 data bytes
ICMP Packet filtered from ip=10.1.200.200 name=UNKNOWN   
ICMP Packet filtered from ip=10.1.200.200 name=UNKNOWN   
ICMP Packet filtered from ip=10.1.200.200 name=UNKNOWN   
 
--- 10.50.200.100 hping statistic ---
4 packets tramitted, 3 packets received, 25% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

На порт 81 уже не проходит.

Т.е. при Fragment Offset = 0 срабатывают ACL.

Интересно увеличить Fragment Offset и посмотреть, что будет. Тут надо обратить внимание, что в стандарте протокола IPv4 написано

Fragment Offset (bits 51 — 63)
The fragment offset field, measured in units of eight-byte blocks,
is 13 bits long and specifies the offset of a particular fragment
relative to the beginning of the original unfragmented IP datagram.
The first fragment has an offset of zero. This allows a maximum
offset of (213 – 1) × 8 = 65,528 which would exceed the maximum IP
packet length of 65,535 with the header length included.

Т.е. значение 0x01 будет соответствовать off=8, а значение 0x02 — off=16. Т.е. все значения offset можно указать только кратные 8ми.

Попробуем с Fragment Offset = 8.

# hping3 -x -g 8 -S 10.50.200.100 -p 80
HPING 10.50.200.100 (ath0 10.50.200.100): S set, 40 headers + 0 data bytes
 
--- 10.50.200.100 hping statistic ---
8 packets tramitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

Ответов нет, tethereal тоже ничего не показывает.

Порт 81

# hping3 -x -g 8 -S 10.50.200.100 -p 81
HPING 10.50.200.100 (ath0 10.50.200.100): S set, 40 headers + 0 data bytes
 
--- 10.50.200.100 hping statistic ---
5 packets tramitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

Результат аналогичный.

Т.е. маршрутизатор просто выкидывает пакеты с Fragment Offset = 8.

А вот уже с Fragment Offset = 16 и выше отлично пропускает, причем на любой порт.

# hping3 -x -g 16 -S 10.50.200.100 -p 81
HPING 10.50.200.100 (ath0 10.50.200.100): S set, 40 headers + 0 data bytes
 
--- 10.50.200.100 hping statistic ---
6 packets tramitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms
# hping3 -x -g 16 -S 10.50.200.100 -p 80
HPING 10.50.200.100 (ath0 10.50.200.100): S set, 40 headers + 0 data bytes
 
--- 10.50.200.100 hping statistic ---
4 packets tramitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms
[root@dyeldandi ~]#
  0.000000    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=16)
  1.000353    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=16)
  2.000815    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=16)
  4.305195    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=16)
  5.305509    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=16)
  6.305812    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=16)
  7.306096    10.1.3.78 -> 10.50.200.100 IP Fragmented IP protocol (proto=TCP 0x06, off=16)

Но Fragment Offset = 16 — это уже далеко за тем местом, где указываются tcp порты, а значит, ACL может со спокойной совестью пропускать, проверять там уже нечего.

Как резюме: Для проверки ACL собирать пакеты на CISCO маршрутизаторе не надо.

А когда надо? Только если используется Cisco IOS Firewall, как описано вот в этом документе.

Спасибо за внимание.