Jump to content
 Share

Roy

[C] XDP Firewall - Exciting Project :D

Recommended Posts

Hey everyone,

 

I just wanted to share another side, but big project I've been working hard on recently. I decided to make an XDP firewall that reads filtering rules based off of a config file. For those that do not know, XDP is a hook in the NIC's driver. If the host's NIC driver supports XDP-native (support list), you can attach XDP programs to the hook directly inside the NIC driver. When blocking packets on this hook, XDP can drop packets over 10 times faster than IPTables! If your NIC doesn't support XDP-native, it will still attempt to use XDP Generic which isn't as fast, but should be the same speed as IPTables assuming your NIC's driver has enough headroom so it doesn't need to do double copies. XDP is pretty good to use when blocking (D)DoS attacks :)

 

Anyways, I will now copy the contents of the GitHub README to this thread.

 

XDP Firewall
Description
An XDP firewall designed to read filtering rules based off of a config file. This software only supports IPv4 and protocols TCP, UDP, and ICMP at the moment. With that said, the program comes with accepted and blocked packet statistics which can be disabled if need to be.

Additionally, if the host's NIC doesn't support XDP-native, the program will attempt to attach via XDP generic. The program firstly tries XDP-native, though.

 

Command Line Usage
The following command line arguments are supported:

  • --config -c => Location to config file. Default => /etc/xdpfw/xdpfw.conf.
  • --list -l => List all filtering rules scanned from config file.
  • --help -h => Print help menu for command line options.

 

Configuration File Options
Main

  • interface => The interface for the XDP program to attach to.
  • updatetime => How often to update the config and filtering rules. Leaving this at 0 disables auto-updating.
  • nostats => If true, no accepted/blocked packet statistics will be displayed in stdout.

 

Filters
Config option filters is an array. Each filter includes the following options:

  • enabled => If true, this rule is enabled.
  • action => What action to perform against the packet if matched. 0 = Block. 1 = Allow.
  • srcip => The source IP to match (e.g. 10.50.0.3).
  • dstip => The destination IP to match (e.g. 10.50.0.4).
  • min_ttl => The minimum TTL (time to live) the packet has to match.
  • max_ttl => The maximum TTL (time to live) the packet has to match.
  • max_len => The maximum packet length the packet has to match. This includes the entire frame (ethernet header, IP header, L4 header, and data).
  • min_len => The minimum packet length the packet has to match. This includes the entire frame (ethernet header, IP header, L4 header, and data).
  • tos => The TOS (type of service) the packet has to match.
  • payloadmatch => The payload (L4 data) the packet has to match. The format is in hexadecimal and each byte is separated by a space. An example includes: FF FF FF FF 59.

 

TCP Options
The config option tcpopts within a filter is an array including TCP options. This should only be one array per filter. Options include:

  • enabled => If true, check for TCP-specific matches.
  • sport => The source port the packet must match.
  • dport => The destination port the packet must match.
  • urg => If true, the packet must have the URG flag set to match.
  • ack => If true, the packet must have the ACK flag set to match.
  • rst => If true, the packet must have the RST flag set to match.
  • psh => If true, the packet must have the PSH flag set to match.
  • syn => If true, the packet must have the SYN flag set to match.
  • fin => If true, the packet must have the FIN flag set to match.

 

UDP Options
The config option udpopts within a filter is an array including UDP options. This should only be one array per filter. Options include:

  • enabled => If true, check for UDP-specific matches.
  • sport => The source port the packet must match.
  • dport => The destination port the packet must match.

 

ICMP Options
The config option icmpopts within a filter is an array including ICMP options. This should only be one array per filter. Options include:

  • enabled => If true, check for ICMP-specific matches.
  • code => The ICMP code the packet must match.
  • type => The ICMP type the packet must match.

 

Note - Everything besides the main enabled and action options within a filter are not required. This means you do not have to define them within your config.

 

Note - As of right now, the payloadmatch option does not work. I am planning to implement functionality for this soon. Unfortunately, BPF hasn't liked the matching methods I've used so far.

 

Configuration Example
Here's an example of a config:

 

interface = "ens18";
updatetime = 15;

filters = (
    {
        enabled = true,
        action = 0,

        udpopts = (
            {
                enabled = true,
                dport = 27015
            }
        )
    },
    {
        enabled = true,
        action = 1,

        tcpopts = (
            {
                enabled = true,
                syn = true,
                dport = 27015
            }
        )
    },
    {
        enabled = true,
        action = 0,

        icmpopts = (
            {
                enabled = true,
                code = 0
            }
        )
    },
    {
        enabled = true,
        action = 0,
        srcip = "10.50.0.4"
    }
);


Credits
@Roy - Creator.

 

GitHub Project

 

Thanks!

Share this post


Link to post
Share on other sites


Just an update on this, I've implemented rate-limiting filter options (packets per second/PPS and bytes per second/BPS) along with a blocktime filter option. The blocktime filter option blocks the source IP for x amount of seconds if the packet matches that specific filter. This is useful if you have PPS and BPS filter options set very high, you'd want to set the blocktime value high as well since this is obviously an attack from that source IP. It also technically blocks matched packets faster since it doesn't have to check each packet against the filters after the first match and instead, checks if the source IP is a part of the blacklist BPF map and if it is and the block time hasn't exceeded, it drops the packet immediately.

 

If you set the blocktime low on these specific filtering rules, packets will come through every x seconds depending on the blocktime value. You may also set blocktime to 0 if you want to block specific packet types, but not the source IP itself.

 

I'm still working to implement payload matching. However, BPF hasn't liked any of the methods I've used to do this. I'm going to post a thread on the XDP mailing list requesting for assistance regarding this. If I'm able to implement this feature, I believe the software is golden at that point.

 

Thanks!

Share this post


Link to post
Share on other sites


Just an update on this, BPF really doesn't like the payload matching functionality I'm trying to implement into for loops. No matter what I do, I cannot get it working and I've tried asking experienced developers such as @Dreae along with making a thread on the XDP Newbies mailing list. Even some of the experienced kernel devs from the mailing list aren't sure. They've stated the BPF compiler isn't convinced the code is safe (even though it is from our prospective).

 

Toke from the XDP Newbies mailing list suggested this:

 

Quote

Use a matching algorithm that doesn't require looping through the packet byte-by-byte as you're doing now. For instance, you could have a hash map that uses the payload you're trying to match as the key with an appropriate chunk size.

 

I've asked for clarification this morning. I searched the BPF Helper functions list here, but wasn't able to find any hashing function that supported XDP programs. There were some for BPF programs that support the sk_buff structure. However, this is typically used for TC programs. With that said, the hashing functions supported the entire packet, not the payload, unfortunately.

 

Hopefully I can find some sort of workaround because having dynamic payload matching in an XDP program would be amazing and I feel it's a necessity for making a firewall that blocks (D)DoS attacks either automatically (based off of patterns) or manually inputted filtering rules.

 

Thanks.

Share this post


Link to post
Share on other sites


I just received another email from Toke:

 

2693-05-13-2020-EWccYkcb.png

 

It looks like the XDP Maintainer (Jesper) was also having similar issues and made these pull requests just as of last week (very recent):

 

https://github.com/xdp-project/xdp-tutorial/pull/123
https://github.com/xdp-project/xdp-tutorial/pull/124

 

Interesting in my opinion, but glad I'm not the only person having these issues and this seems to be an issue with BPF itself. It shouldn't be this difficult to match payload data in my opinion, lol.

 

Thanks!

Share this post


Link to post
Share on other sites


Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


×
×
  • Create New...