#!/usr/bin/nft -f

# https://github.com/trentbuck/nft-examples/blob/main/nftables-host.nft
# https://github.com/yoramvandevelde/nftables-example/blob/master/nftables-init.rules
# https://github.com/philippecrowdsec/iptables-nftables-multiroute-firewall/blob/main/nftables.conf
# https://www.firezone.dev/docs/reference/firewall-templates/nftables
# https://serverfault.com/questions/1149589/can-i-increase-readility-of-nftables-ruleset-syntax-and-does-it-affect-its-funct
# https://gbe0.com/pages/linux/nftables-configuration-templates/
# https://fishilico.github.io/generic-config/etc/nftables-server.conf.raw.html
# https://wiki.codeemo.com/secure/nftables.html
# https://github.com/chayleaf/notnft
# https://forum.qubes-os.org/t/qubes-os-4-2-nftables-nft-firewall-guide/20933/24
# https://k1024.org/posts/2023/2023-04-16-nftables-tcp-clamp-mss/

# https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks
# https://wiki.nftables.org/wiki-nftables/index.php/Classic_perimetral_firewall_example
# https://wiki.nftables.org/wiki-nftables/index.php/Ruleset_debug/tracing
# https://wiki.nftables.org/wiki-nftables/index.php/Logging_traffic

flush ruleset

table netdev filter {
  chain ingress {
    type filter hook ingress device wlp3s0 priority -500;

    # IP BOGONS
    # From <https://www.team-cymru.com/bogon-reference.html>.
    # https://team-cymru.org/Services/Bogons/bogon-bn-nonagg.txt
    ip saddr { \
      0.0.0.0/8, \
      10.0.0.0/8, \
      100.64.0.0/10, \
#      127.0.0.0/8, \
      169.254.0.0/16, \
#      172.16.0.0/12, \
      192.0.0.0/24, \
      192.0.2.0/24, \
#      192.168.0.0/16, \
      198.18.0.0/15, \
      198.51.100.0/24, \
      203.0.113.0/24, \
      224.0.0.0/4, \
      240.0.0.0/4 \
    } \
    counter drop

    # Drop all fragments.
    ip frag-off & 0x1fff != 0 counter comment "TODO: drop or not to drop?"

    # Drop XMAS packets.
    tcp flags & (fin|syn|rst|psh|ack|urg) == fin|syn|rst|psh|ack|urg counter drop

    # Drop NULL packets.
    tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 counter drop

    # Drop uncommon MSS values.
    tcp flags syn tcp option maxseg size 1-535 counter drop
  }
}

table filter {
  chain input {
    type filter hook input priority filter
    policy drop

    ct state invalid log group 1 prefix "Invalid packet:" counter drop
    ct state established, related accept

    iif != lo ip saddr 127.0.0.0/8 log group 1 prefix "Fake saddr localhost:" counter drop
    iif != lo ip daddr 127.0.0.0/8 log group 1 prefix "Fake daddr localhost:" counter comment "TODO"
    iif lo accept

    meta pkttype multicast udp dport 5353 drop comment "TODO: identify who is shitting"
    meta pkttype broadcast udp dport 21027 drop comment "TODO: syncthing"

    meta pkttype broadcast \
      log group 1 prefix "broadcast: " \
      counter drop comment "silently drop unsollicited broadcast"
    meta pkttype multicast \
      log group 1 prefix "multicast: " \
      counter drop comment "silently drop unsollicited multicast"
    ip daddr 255.255.255.255/32 counter drop comment "really drop unsollicited IPv4 broadcast"

    # Drop TCP traffic with invalid flags
    tcp flags != syn ct state new log group 1 prefix "New TCP without SYN: " \
      counter drop comment "Drop new connections that do not have the SYN TCP flag set"
    tcp flags & (fin|syn) == (fin|syn) log group 1 prefix "Port scan 1: " \
      counter drop comment "Drop common port scan traffic"
    tcp flags & (syn|rst) == (syn|rst) log group 1 prefix "Port scan 2: " \
      counter drop comment "Drop common port scan traffic"
    tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) log group 1 prefix "Port scan 3:" \
      counter drop comment "Drop common port scan traffic"
    tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) log group 1 prefix "Port scan 4:" \
      counter drop comment "Drop common port scan traffic"

    icmp type { echo-reply, destination-unreachable, source-quench, \
                router-advertisement, router-solicitation, time-exceeded, \
                parameter-problem } accept

    tcp dport 54321 ct state new accept comment "traefik vaultwarden"

    # log prefix "[nftables] Inbound Denied: " flags all counter drop
    counter
  }

#chain output {
#    type filter hook output priority 0; policy accept;
#    meta skuid t drop
#}

  chain forward {
    type filter hook forward priority filter
    policy drop

    # log prefix "[nftables] Forward Denied: " flags all counter drop
  }
}

table ip6 filter {
  chain i {
    type filter hook input priority filter
    policy drop
  }

  chain o {
    type filter hook output priority filter
    policy drop
  }

  chain f {
    type filter hook forward priority filter
    policy drop
  }
}
