define icmp_protos = { ipv6-icmp, icmp, igmp }

table arp filter {
  limit lim_arp {
    rate over 50 mbytes/second burst 50 mbytes
  }

  counter arp-rx {}
  counter arp-tx {}

  counter arp-ratelimit-rx {}
  counter arp-ratelimit-tx {}

  chain input {
    type filter hook input priority filter
    policy accept

    limit name lim_arp counter name arp-ratelimit-rx drop

    counter name arp-rx
  }

  chain output {
    type filter hook output priority filter
    policy accept

    limit name lim_arp counter name arp-ratelimit-tx drop

    counter name arp-tx
  }
}

table inet filter {
  limit lim_reject {
    rate over 1000/second burst 1000 packets
  }

  limit lim_icmp {
    rate over 50 mbytes/second burst 50 mbytes
  }

  counter invalid-fw {}

  counter fw-lo {}

  counter reject-ratelimit-fw {}
  counter reject-fw {}
  counter reject-tcp-fw {}
  counter reject-icmp-fw {}


  counter invalid-rx {}
  counter rx-lo {}
  counter invalid-local4-rx {}
  counter invalid-local6-rx {}

  counter icmp-ratelimit-rx {}
  counter icmp-rx {}

  counter ssh-rx {}
  counter mosh-rx {}
  counter wg-rx {}
  counter yggdrasil-gre-rx {}
  counter quickserve-rx {}
  counter ausweisapp2-rx {}

  counter established-rx {}

  counter reject-ratelimit-rx {}
  counter reject-rx {}
  counter reject-tcp-rx {}
  counter reject-icmp-rx {}


  counter tx-lo {}

  counter icmp-ratelimit-tx {}
  counter icmp-tx {}

  counter ssh-tx {}
  counter mosh-tx {}
  counter wg-tx {}
  counter yggdrasil-gre-tx {}
  counter quickserve-tx {}

  counter tx {}

  counter fw-libvirt {}
  counter libvirt-dhcp {}
  counter libvirt-dns {}


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


    ct state invalid log level debug prefix "drop invalid forward: " counter name invalid-fw drop


    iifname lo counter name fw-lo accept

    jump forward_tmp

    iifname virbr0 oifname != {lo, wgrz, yggdrasil-wg-4, yggdrasil-wg-6, yggdrasil, ip6tnl, ip6gre, yggre-surtr-6, yggre-surtr-4, yggre-vidhar-4} counter name fw-libvirt accept
    oifname virbr0 ct state {established, related} counter name fw-libvirt accept


    limit name lim_reject log level debug prefix "drop forward: " counter name reject-ratelimit-fw drop
    log level debug prefix "reject forward: " counter name reject-fw
    meta l4proto tcp ct state new counter name reject-tcp-fw reject with tcp reset
    ct state new counter name reject-icmp-fw reject
  }

  chain input_tmp {}
  chain input {
    type filter hook input priority filter
    policy drop


    ct state invalid log level debug prefix "drop invalid input: " counter name invalid-rx drop


    iifname lo counter name rx-lo accept
    iif != lo ip daddr 127.0.0.1/8 counter name invalid-local4-rx reject
    iif != lo ip6 daddr ::1/128 counter name invalid-local6-rx reject

    meta l4proto $icmp_protos limit name lim_icmp counter name icmp-ratelimit-rx drop
    meta l4proto $icmp_protos counter name icmp-rx accept

    jump input_tmp

    tcp dport 22 counter name ssh-rx accept
    udp dport 60000-61000 counter name mosh-rx accept

    tcp dport 8000 counter name quickserve-rx accept
    udp dport 24727 counter name ausweisapp2-rx accept

    udp dport 51820-51822 counter name wg-rx accept
    iifname "yggdrasil-wg-*" meta l4proto gre counter name yggdrasil-gre-rx accept

    iifname virbr0 udp dport 67 counter name libvirt-dhcp accept
    iifname virbr0 udp dport 547 counter name libvirt-dhcp accept
    iifname virbr0 udp dport 53 counter name libvirt-dns accept
    iifname virbr0 tcp dport 53 counter name libvirt-dns accept

    iifname wgrz ip saddr 10.200.116.1 meta l4proto gre counter accept

    ct state {established, related} counter name established-rx accept


    limit name lim_reject log level debug prefix "drop input: " counter name reject-ratelimit-rx drop
    log level debug prefix "reject input: " counter name reject-rx
    meta l4proto tcp ct state new counter name reject-tcp-rx reject with tcp reset
    ct state new counter name reject-icmp-rx reject
  }

  chain output {
    type filter hook output priority filter
    policy accept


    oifname lo counter name tx-lo accept

    meta l4proto $icmp_protos limit name lim_icmp counter name icmp-ratelimit-tx drop
    meta l4proto $icmp_protos counter name icmp-tx accept


    tcp sport 22 counter name ssh-tx
    udp sport 60000-61000 counter name mosh-tx

    udp sport 51820-51822 counter name wg-tx
    iifname "yggdrasil-wg-*" meta l4proto gre counter name yggdrasil-gre-tx

    tcp sport 8000 counter name quickserve-tx accept

    oifname virbr0 udp sport 67 counter name libvirt-dhcp accept
    oifname virbr0 udp sport 547 counter name libvirt-dhcp accept
    oifname virbr0 udp sport 53 counter name libvirt-dns accept
    oifname virbr0 tcp sport 53 counter name libvirt-dns accept


    counter name tx
  }
}

table ip nat {
  counter libvirt-nat {}

  chain postrouting_tmp {}
  chain postrouting {
    type nat hook postrouting priority srcnat
    policy accept

    iifname virbr0 oifname != virbr0 counter name libvirt-nat masquerade
    jump postrouting_tmp
  }
}

table ip6 nat {
  counter libvirt-nat {}

  chain postrouting {
    type nat hook postrouting priority srcnat
    policy accept

    iifname virbr0 oifname != virbr0 counter name libvirt-nat masquerade
  }
}

table ip mss_clamp {
  counter libvirt-mss-clamp {}

  chain postrouting_tmp {}
  chain postrouting {
    type filter hook postrouting priority mangle
    policy accept

    iifname virbr0 oifname != virbr0 tcp flags & (syn|rst) == syn counter name libvirt-mss-clamp tcp option maxseg size set rt mtu
    jump postrouting_tmp
  }
}