Skip to content

Example IPv4 IPv6

wirefalls edited this page Aug 31, 2021 · 3 revisions
Geolocation for nftables

Example IPv4 - IPv6 nftables Firewall Ruleset

This is a basic firewall for testing purposes only and not a complete firewall to protect your system.

This ruleset supports both IPv4 and IPv6 simultaneously (dual stack). The default input and forward policy is set to drop. The default output policy is set to accept, which allows necessary outgoing traffic during testing.

After backing up your current nftables.conf file, copy and paste the following code to a new file /etc/nftables.conf (Ubuntu/Debian) or /etc/sysconfig/nftables.conf (Fedora/Red Hat):

nftables.conf

#!/usr/bin/nft -f

flush ruleset

# Add a netdev table to allow early geolocation filtering before incoming
# packets are routed.
table netdev filter {

  # Define empty set to store IPv4 country code specific address ranges.
  set geo-netdev4 {
    type ipv4_addr
    flags interval
    # Elements for this set are defined in /etc/nftables/geo-nft/refill-sets.conf
  }

  # Define empty set to store IPv6 country code specific address ranges.
  set geo-netdev6 {
    type ipv6_addr
    flags interval
    # Elements for this set are defined in /etc/nftables/geo-nft/refill-sets.conf
  }

  chain ingress {
    # Replace 'device_name' below with the name of your WAN network interface
    # from running "ip a" or "ifconfig" in a terminal.
    type filter hook ingress device device_name priority 0; policy accept;

    # Count and drop IPv4 traffic from source address ranges (elements) in the geo-netdev4
    # set defined above.
    ip saddr @geo-netdev4 counter drop comment "Drop source addresses in set geo-netdev4"

    # Count and drop IPv6 traffic from source address ranges (elements) in the geo-netdev6
    # set defined above.
    ip6 saddr @geo-netdev6 counter drop comment "Drop source addresses in set geo-netdev6"
  }
}

# Add an inet table to allow both IPv4 and IPv6 traffic.
table inet filter {

  # We can do geolocation packet filtering in this table too.
  # Define empty set to store IPv4 country code specific address ranges.
  set geo-inet4 {
    type ipv4_addr
    flags interval
    # Elements for this set are defined in /etc/nftables/geo-nft/refill-sets.conf
  }

  # Define empty set to store IPv6 country code specific address ranges.
  set geo-inet6 {
    type ipv6_addr
    flags interval
    # Elements for this set are defined in /etc/nftables/geo-nft/refill-sets.conf
  }

  chain input {
    type filter hook input priority 0; policy drop;

    # Accept incoming traffic from connections we originated.
    ct state established,related counter accept comment "Accept established and related traffic"

    # Accept localhost traffic.
    iif lo counter accept comment "Accept localhost traffic"

    # Drop invalid state packets.
    ct state invalid counter drop comment "Drop invalid state packets"

    # Accept SSH on port 22.
    tcp dport 22 counter accept comment "Accept SSH on port 22"

    # Accept ICMP traffic.
    ip protocol icmp limit rate 5/second counter accept comment "Accept ICMP traffic"

    # Accept IGMP traffic.
    ip protocol igmp limit rate 5/second counter accept comment "Accept IGMP traffic"

    # Accept IPv6 neighbor discovery traffic, otherwise connectivity will break.
    ip6 nexthdr icmpv6 icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert, echo-request } \
      limit rate 5/second counter accept comment "Accept IPv6 neighbor discovery traffic"

    # Drop all other incoming traffic.
    counter drop comment "Drop all other incoming traffic"
  }

  chain forward {
    type filter hook forward priority 0; policy drop;
    counter drop comment "Drop forwarded packets since this isn't a router"
  }

  chain output {
    type filter hook output priority 0; policy accept;

    # Accept outgoing traffic to connections we originated.
    ct state established,related counter accept comment "Accept established and related traffic"

    # Accept localhost traffic.
    oif lo counter accept comment "Accept localhost traffic"

    # Drop invalid state packets.
    ct state invalid counter drop comment "Drop invalid state packets"

    # Allow new outgoing UDP and TCP packets to port 53 for DNS resolution during
    # testing. Enables URL's to resolve if you block traffic to your own country.
    meta l4proto { udp, tcp } @th,16,16 53 ct state new counter accept comment "Allow new DNS out"

    # Reject outgoing IPv4 packets to destination address ranges (elements) in the
    # geo-inet4 set. Outgoing packets are rejected rather than dropped to prevent
    # local apps and clients from having to wait for the connection to time out.
    ip daddr @geo-inet4 counter reject comment "Reject destination addresses in set geo-inet4"

    # Reject outgoing IPv6 packets to destination address ranges (elements) in the
    # geo-inet6 set. Outgoing packets are rejected rather than dropped to prevent
    # local apps and clients from having to wait for the connection to time out.
    ip6 daddr @geo-inet6 counter reject comment "Reject destination addresses in set geo-inet6"

    # Allow outgoing HTTP/HTTPS packets.
    meta l4proto { tcp, udp } @th,16,16 { 80, 443 } counter accept comment "Allow outgoing HTTP/HTTPS packets"

    # Accept all other outgoing traffic.
    counter accept comment "Accept all other outgoing traffic"
  }
}

# Include the refill-sets.nft script at the end of your nftables.conf file to
# fill empty geolocation sets during system startup. The filename includes an
# asterisk to allow nftables to load in case the file isn't found. Uncomment the
# next line after your refill-sets.nft script is manually tested and working.
#include "/etc/nftables/geo-nft/*refill-sets.nft"

Remember to change the device_name in the ingress chain above to match the name of your WAN network interface reported by running ip a or ifconfig in a terminal. The interface name is typically something like enp16s0f0 or eth0. If the name happens to be eth0 then the line would look like this:

type filter hook ingress device eth0 priority 0; policy accept;

 


Geolocation for nftables documentation is licensed under the GNU GPLv2 (or at your option, any later version).