Traffic filtration using NIC capabilities on wire speed (10GE, 14Mpps)

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.