# nftables filtering (dshield, wizcrafts, bogons), perl6

## mimosinnet

After playing with nftables, I must say I am quite impressed. I have been using ipset and iptables since 2012 thanks to a post of Bones McCracker in the forums. I have tried to recreate the same configuration with nftables (blacklist known attackers) using nftables sets.

This is my nftables script:

```
#!/sbin/nft

flush ruleset;

define INTERFACE = enp5s0

# Load chain input, forward and output

include "/etc/nftables/ipv4-filter"

# Load @trusted_hosts @trusted_networks

include "/home/mimosinnet/.config/nftables/trusted.nft"

# Load @countries, @dshield, @wizcrafts, @fullbogons

include "/home/mimosinnet/.config/nftables/sets.nft"

add rule filter input meta iifname $INTERFACE ct state new ip saddr @trusted_hosts accept comment "accept from trusted hosts"

add rule filter input ct state {established, related} counter accept comment "accept all connections related to connections made by us"

add rule filter input meta iifname $INTERFACE ct state new ip saddr @dshield ip saddr @wizcrafts ip saddr @fullbogons drop comment "drop from blacklists" 

add rule filter input meta iifname $INTERFACE ip protocol tcp ct state new ip saddr @trusted_networks tcp dport 22 counter accept comment "accept SSH from trusted networks"

add rule filter input ct state invalid counter drop comment "drop invalid packets" 

add rule filter input iifname lo accept comment "accept loopback";

add rule filter input iifname != lo ip daddr 127.0.0.1/8 counter drop comment "drop connections to loopback not coming from loopback"

add rule filter input ip protocol icmp counter accept comment "accept all icmp types"

add rule filter input drop

# Policies

add rule filter forward drop;

add rule filter output accept;

```

The script loads the following sets: @trusted_hosts @trusted_networks, @countries, @dshield, @wizcrafts, @fullbogons. As suggested in the nftables wiki, shells scripts are problematic and native nftables scripting should be used instead. I have used perl6 (and any other language would do) to create the nftables scripts that define the sets. 

This is the perl6 code that defines @countries, @dshield, @wizcrafts

```
#!/usr/bin/env perl6

# Definition of sets (countries, dshield, wizcrafts, bogons) to be used in nftables stored in 'sets.nft'

use v6;

# Definition of countries according to http://www.ipdeny.com/ipblocks/

my @countries = <es>;

my %webs =

fullbogons => 'http://www.team-cymru.org/Services/Bogons/fullbogons-ipv4.txt',

wizcrafts    => 'http://www.wizcrafts.net/exploited-servers-iptables-blocklist.html',

dshield       => 'http://feeds.dshield.org/block.txt';

# Add to %webs the url of each country

for @countries -> $country {

   %webs{"country$country"} = "http://www.ipdeny.com/ipblocks/data/countries/$country.zone";

}

my token ip_number { \d ** 1..3  }

my token ip             { [<ip_number>\.] ** 3 <ip_number> }

my token cidr        { <ip> \/ <ip_number> };

# Add sets: fullbogons, wizcrafts, dshield, countries

my $nft_file = open 'sets.nft', :w;

$nft_file.say('#!/sbin/nft

add set filter fullbogons { type ipv4_addr; flags interval; }

add set filter wizcrafts  { type ipv4_addr; flags interval; }

add set filter dshield       { type ipv4_addr; flags interval; }

add set filter countries    { type ipv4_addr; flags interval; }

');

# Check Internet Connection and Web Availability

die 'Error: no connection to internet' unless qx{ping -c 3 google.es}.match('0% packet loss');

for %webs.keys -> $list {

   %webs{$list} = qqx{wget -O - %webs{$list}};

   die "Unavailable data in $list" if %webs{$list}.chars < 9;

}

# Dshield has a different format than the other pages

for %webs<dshield>.lines -> $line {

   # Capture ip and netmask

   if $line ~~ /(<ip>) \s+ <ip> \s+ (<ip_number>) / {

      $nft_file.say('add element filter dshield {' ~ $/.list[0].Str ~ '/' ~ $/.list[1].Str ~ '}');

   }

}

%webs<dshield>:delete;

# http://www.team-cymru.org (fullbogons), http://www.wizcrafts.net, http://www.ipdeny.com (countries)

for %webs.keys -> $key {

      my $set = $key;

      $set = 'countries' if $key.match(/country.*/);

   for %webs{$key}.lines -> $line {

      if $line ~~ /^(<cidr>)/ {

         $nft_file.say("add element filter $set \{" ~ $/.Str ~ '}');

      }

   }

}

$nft_file.close;
```

After executing the perl6 script and the nftables script, the firewall blocks known attackers   :Wink: 

Let me know if this is useful (so I can write it on the gentoo wiki) or there are better ways of doing this. 

Cheers!   :Very Happy: 

----------

