This topic about NIC hardware filtration is very rarely covered but it’s very useful.
Well, for this challenge you should buy modern 10GE NIC (for example, you could use Intel 520, Intel 540, Intel XL710 or any NIC on chipset Intel 82599). I will use NIC with Intel 82599 chipset with ixgbe driver.
First of all, you should use Intel drivers from SourceForge instead of drivers bundled with your Linux distribution. Because bundled driver is very little functional.
We will use ethtool for NIC capabilities management, please install it.
Let’s go!
We need to tune NIC driver and enable hardware filtration capability.
Open driver configuration file:
vim /etc/modprobe.d/ixgbe.conf
And put following text there:
FdirPballoc=3,3,3,3
After reconfiguration please unload and load driver again:
rmmod ixgbe modprobe ixgbe ifconfig 11.22.33.44. eth4
Why we set FdirPballoc to 3? That’s why we can select number of hardware filtering rules and we selected option with maximum number of rules:
1 = 8k hash filters or 2k perfect filters 2 = 16k hash filters or 4k perfect filters 3 = 32k hash filters or 8k perfect filters (array of int)
Look at dmesg and check number of rules in debug messages:
dmesg|grep 'Flow Director' [45847.024851] ixgbe: Flow Director packet buffer allocation set to 3 [45847.024874] ixgbe: 0000:0a:00.0: ixgbe_check_options: Flow Director will be allocated 256kB of packet buffer
Enable NIC hardware filtration support in runtime:
ethtool -K eth4 ntuple on
Because many distros has outdated ethtool man pages I provided most important for traffic filtration part here:
ethtool --help: ethtool -N|-U|--config-nfc|--config-ntuple DEVNAME Configure Rx network flow classification options or rules rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|tcp6|udp6|ah6|esp6|sctp6 m|v|t|s|d|f|n|r... | flow-type ether|ip4|tcp4|udp4|sctp4|ah4|esp4 [ src %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ] [ dst %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ] [ proto %d [m %x] ] [ src-ip %d.%d.%d.%d [m %d.%d.%d.%d] ] [ dst-ip %d.%d.%d.%d [m %d.%d.%d.%d] ] [ tos %d [m %x] ] [ l4proto %d [m %x] ] [ src-port %d [m %x] ] [ dst-port %d [m %x] ] [ spi %d [m %x] ] [ vlan-etype %x [m %x] ] [ vlan %x [m %x] ] [ user-def %x [m %x] ] [ action %d ] [ loc %d]] | delete %d
For testing purposes I started simulated DDoS attack with trafgen tool with power 8 Million packets per second (but this approach can mitigate attacks up to 14MPPS with a charm):
12:45:19.050037 IP 10.10.10.100.41356 > 10.10.10.200.61598: UDP, length 18 12:45:19.050045 IP 10.10.10.100.9967 > 10.10.10.200.24210: UDP, length 18 12:45:19.050052 IP 10.10.10.100.17254 > 10.10.10.200.44345: UDP, length 18 12:45:19.050061 IP 10.10.10.100.17516 > 10.10.10.200.41543: UDP, length 18 12:45:19.050069 IP 10.10.10.100.29307 > 10.10.10.200.60769: UDP, length 18 12:45:19.050078 IP 10.10.10.100.56313 > 10.10.10.200.49897: UDP, length 18 12:45:19.050085 IP 10.10.10.100.17761 > 10.10.10.200.6767: UDP, length 18 12:45:19.050093 IP 10.10.10.100.24303 > 10.10.10.200.12295: UDP, length 18 12:45:19.050101 IP 10.10.10.100.27105 > 10.10.10.200.52313: UDP, length 18 12:45:19.050109 IP 10.10.10.100.32141 > 10.10.10.200.55003: UDP, length 18 12:45:19.050119 IP 10.10.10.100.10274 > 10.10.10.200.11494: UDP, length 18
Look at server load. It’s very sad picture 🙁 Our server completely overloaded.
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 25.0 id, 0.0 wa, 0.0 hi, 75.0 si, 0.0 st
Let’s try to build traffic filter against this attack (action “-1” means traffic drop):
ethtool --config-ntuple eth4 flow-type udp4 src-ip 10.10.10.100 m 255.255.255.0 action -1
Check rules list:
ethtool --show-ntuple eth4 4 RX rings available Total 1 rules Filter: 8189 Rule Type: UDP over IPv4 Src IP addr: 0.0.0.100 mask: 255.255.255.0 Dest IP addr: 0.0.0.0 mask: 255.255.255.255 TOS: 0x0 mask: 0xff Src port: 0 mask: 0xffff Dest port: 0 mask: 0xffff VLAN EtherType: 0x0 mask: 0xffff VLAN: 0x0 mask: 0xffff User-defined: 0x0 mask: 0xffffffffffffffff Action: Drop
How to remove hardware filtering rule in case of mistake?
ethtool --config-ntuple eth4 delete 8189
Look at top and check server load:
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
Looks very nice! Isn’t it? How we can check how much packets rejected with this filter rule:
ethtool -S eth4 |grep fdir fdir_match: 916143392 fdir_miss: 139427055 fdir_overflow: 0
As you can see, it’s very fast and straightforward way to mitigate attacks directed on channel overflow.
You can block DNS/SNMP/CHARGEN traffic amplification attacks with this approach. But you should keep in mind restriction of this approach. We can filter traffic only by protocols, ports and specific IP’s. If you need filtration by TCP flags or by packet length you should implement complete firewall.