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

table arp filter {
  limit lim_arp_local {
    rate over 50 mbytes/second burst 50 mbytes
  }
  limit lim_arp_dsl {
    rate over 1400 kbytes/second burst 1400 kbytes
  }

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

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

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

  chain input {
    type filter hook input priority filter
    policy accept

    iifname != dsl limit name lim_arp_local counter name arp-ratelimit-local-rx drop
    iifname dsl limit name lim_arp_dsl counter name arp-ratelimit-dsl-rx drop

    counter name arp-rx
  }

  chain output {
    type filter hook output priority filter
    policy accept

    oifname != dsl limit name lim_arp_local counter name arp-ratelimit-local-tx drop
    oifname dsl limit name lim_arp_dsl counter name arp-ratelimit-dsl-tx drop

    counter name arp-tx
  }
}

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

  limit lim_icmp_local {
    rate over 50 mbytes/second burst 50 mbytes
  }
  limit lim_icmp_dsl {
    rate over 1400 kbytes/second burst 1400 kbytes
  }

  counter icmp-ratelimit-dsl-fw {}
  counter icmp-ratelimit-local-fw {}

  counter icmp-fw {}

  counter invalid-fw {}
  counter fw-lo {}
  counter fw-lan {}
  counter fw-dsl {}

  counter fw-cups {}

  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-dsl-rx {}
  counter icmp-ratelimit-local-rx {}
  counter icmp-rx {}

  counter ssh-rx {}
  counter mosh-rx {}
  counter dns-rx {}
  counter nfs-rx {}
  counter wg-rx {}
  counter yggdrasil-gre-rx {}
  counter ipv6-pd-rx {}
  counter ntp-rx {}
  counter dhcp-rx {}
  counter samba-rx {}
  counter http-rx {}
  counter tftp-rx {}
  counter pgbackrest-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-dsl-tx {}
  counter icmp-ratelimit-local-tx {}
  counter icmp-tx {}

  counter ssh-tx {}
  counter mosh-tx {}
  counter dns-tx {}
  counter nfs-tx {}
  counter wg-tx {}
  counter yggdrasil-gre-tx {}
  counter ipv6-pd-tx {}
  counter ntp-tx {}
  counter dhcp-tx {}
  counter samba-tx {}
  counter http-tx {}
  counter tftp-tx {}
  counter pgbackrest-tx {}

  counter tx {}


  chain forward_icmp_accept {
    oifname { dsl, bifrost } limit name lim_icmp_dsl counter name icmp-ratelimit-dsl-fw drop
    iifname { dsl, bifrost } limit name lim_icmp_dsl counter name icmp-ratelimit-dsl-fw drop
    oifname != { dsl, bifrost } limit name lim_icmp_local counter name icmp-ratelimit-local-fw drop
    iifname != { dsl, bifrost } limit name lim_icmp_local counter name icmp-ratelimit-local-fw drop
    counter name icmp-fw accept
  }
  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

    oifname { lan, dsl, bifrost } meta l4proto $icmp_protos jump forward_icmp_accept
    iifname lan oifname { dsl, bifrost } counter name fw-lan accept

    iifname dsl oifname lan ct state { established, related } counter name fw-dsl 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 {
    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

    iifname { bifrost, dsl } meta l4proto $icmp_protos limit name lim_icmp_dsl counter name icmp-ratelimit-dsl-rx drop
    iifname != { bifrost, dsl } meta l4proto $icmp_protos limit name lim_icmp_local counter name icmp-ratelimit-local-rx drop
    meta l4proto $icmp_protos counter name icmp-rx accept

    iifname { lan, mgmt, dsl, yggdrasil, bifrost } tcp dport 22 counter name ssh-rx accept
    iifname { lan, mgmt, dsl, yggdrasil, bifrost } udp dport 60000-61000 counter name mosh-rx accept

    iifname { lan, mgmt, wifibh, yggdrasil } meta l4proto { tcp, udp } th dport 53 counter name dns-rx accept

    iifname { lan, yggdrasil } tcp dport 2049 counter name nfs-rx accept

    iifname { lan, mgmt, dsl } meta protocol ip udp dport 51820 counter name wg-rx accept
    iifname { lan, mgmt, dsl } meta protocol ip6 udp dport 51821 counter name wg-rx accept
    iifname "yggdrasil-wg-*" meta l4proto gre counter name yggdrasil-gre-rx accept

    iifname dsl meta protocol ip6 udp dport 546 udp sport 547 counter name ipv6-pd-rx accept

    iifname mgmt udp dport 123 counter name ntp-rx accept

    iifname { lan, mgmt, wifibh } udp dport 67 counter name dhcp-rx accept

    iifname lan meta l4proto . th dport { udp . 137, udp . 138, tcp . 139, tcp . 445, udp . 3702, tcp . 5357 } counter name samba-rx accept

    iifname yggdrasil tcp dport { 80, 443 } counter name http-rx accept
    iifname lan tcp dport 80 counter name http-rx accept

    iifname { lan, mgmt } udp dport 69 counter name tftp-rx accept

    tcp dport 8432 counter name pgbackrest-rx 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

    oifname { bifrost, dsl } meta l4proto $icmp_protos limit name lim_icmp_dsl counter name icmp-ratelimit-dsl-tx drop
    oifname != { bifrost, dsl } meta l4proto $icmp_protos limit name lim_icmp_local counter name icmp-ratelimit-local-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

    meta l4proto { tcp, udp } th sport 53 counter name dns-tx

    tcp sport 2049 counter name nfs-tx

    meta protocol ip udp sport 51820 counter name wg-tx
    meta protocol ip6 udp sport { 51821, 51822 } counter name wg-tx
    iifname "yggdrasil-wg-*" meta l4proto gre counter name yggdrasil-gre-tx

    meta protocol ip6 udp sport 546 udp dport 547 counter name ipv6-pd-tx

    udp sport 123 counter name ntp-tx accept

    udp sport 67 counter name dhcp-tx accept

    meta l4proto . th sport { udp . 137, udp . 138, tcp . 139, tcp . 445, udp . 3702, tcp . 5357 } counter name samba-tx accept

    tcp sport { 80, 443 } counter name http-tx accept

    udp sport 69 counter name tftp-tx accept
    udp dport 69 counter name tftp-tx accept

    tcp sport 8432 counter name pgbackrest-tx accept


    counter name tx
  }
}

table inet nat {
  counter dsl-nat {}
  # counter container-nat {}

  chain postrouting {
    type nat hook postrouting priority srcnat
    policy accept


    meta nfproto ipv4 oifname dsl counter name dsl-nat masquerade
    # iifname ve-* oifname dsl counter name container-nat masquerade
  }
}

table inet mss_clamp {
  counter dsl-mss-clamp {}

  chain postrouting {
    type filter hook postrouting priority mangle
    policy accept


    oifname dsl tcp flags & (syn|rst) == syn counter name dsl-mss-clamp tcp option maxseg size set rt mtu
  }
}

## Masks for extracting/storing data in the conntrack mark
# define ct_dscp = 0x0000003f
# define ct_dyn = 0x00000080
# define ct_dyn_static_dscp = 0x000000ff
define ct_static = 0x00000040
define ct_unused = 0xffffff80
# define ct_unused_dscp = 0xffffff3f
# define ct_unused_dyn = 0xffffff80

## DSCP classification values
define cs0 = 0
define lephb = 1
define cs1 = 8
define af11 = 10
define af12 = 12
define af13 = 14
define cs2 = 16
define af21 = 18
define af22 = 20
define af23 = 22
define cs3 = 24
define af31 = 26
define af32 = 28
define af33 = 30
define cs4 = 32
define af41 = 34
define af42 = 36
define af43 = 38
define cs5 = 40
define va = 44
define ef = 46
define cs6 = 48
define cs7 = 56

table inet dscpclassify {
    ## Set conntrack DSCP mark without modifying unused bits
    chain ct_set_cs0 {
        ct mark set ct mark and $ct_unused or $cs0
    }

    chain ct_set_lephb {
        ct mark set ct mark and $ct_unused or $lephb or $ct_static
    }

    chain ct_set_cs1 {
        ct mark set ct mark and $ct_unused or $cs1 or $ct_static
    }

    chain ct_set_af11 {
        ct mark set ct mark and $ct_unused or $af11 or $ct_static
    }

    chain ct_set_af12 {
        ct mark set ct mark and $ct_unused or $af12 or $ct_static
    }

    chain ct_set_af13 {
        ct mark set ct mark and $ct_unused or $af13 or $ct_static
    }

    chain ct_set_cs2 {
        ct mark set ct mark and $ct_unused or $cs2 or $ct_static
    }

    chain ct_set_af21 {
        ct mark set ct mark and $ct_unused or $af21 or $ct_static
    }

    chain ct_set_af22 {
        ct mark set ct mark and $ct_unused or $af22 or $ct_static
    }

    chain ct_set_af23 {
        ct mark set ct mark and $ct_unused or $af23 or $ct_static
    }

    chain ct_set_cs3 {
        ct mark set ct mark and $ct_unused or $cs3 or $ct_static
    }

    chain ct_set_af31 {
        ct mark set ct mark and $ct_unused or $af31 or $ct_static
    }

    chain ct_set_af32 {
        ct mark set ct mark and $ct_unused or $af32 or $ct_static
    }

    chain ct_set_af33 {
        ct mark set ct mark and $ct_unused or $af33 or $ct_static
    }

    chain ct_set_cs4 {
        ct mark set ct mark and $ct_unused or $cs4 or $ct_static
    }

    chain ct_set_af41 {
        ct mark set ct mark and $ct_unused or $af41 or $ct_static
    }

    chain ct_set_af42 {
        ct mark set ct mark and $ct_unused or $af42 or $ct_static
    }

    chain ct_set_af43 {
        ct mark set ct mark and $ct_unused or $af43 or $ct_static
    }

    chain ct_set_cs5 {
        ct mark set ct mark and $ct_unused or $cs5 or $ct_static
    }

    chain ct_set_va {
        ct mark set ct mark and $ct_unused or $va or $ct_static
    }

    chain ct_set_ef {
        ct mark set ct mark and $ct_unused or $ef or $ct_static
    }

    chain ct_set_cs6 {
        ct mark set ct mark and $ct_unused or $cs6 or $ct_static
    }

    chain ct_set_cs7 {
        ct mark set ct mark and $ct_unused or $cs7 or $ct_static
    }

    chain postrouting {
	type filter hook postrouting priority filter + 1; policy accept

	oifname != dsl return

	ip dscp cs0 goto ct_set_cs0
	ip dscp lephb goto ct_set_lephb
	ip dscp cs1 goto ct_set_cs1
	ip dscp af11 goto ct_set_af11
	ip dscp af12 goto ct_set_af12
	ip dscp af13 goto ct_set_af13
	ip dscp cs2 goto ct_set_cs2
	ip dscp af21 goto ct_set_af21
	ip dscp af22 goto ct_set_af22
	ip dscp af23 goto ct_set_af23
	ip dscp cs3 goto ct_set_cs3
	ip dscp af31 goto ct_set_af31
	ip dscp af32 goto ct_set_af32
	ip dscp af33 goto ct_set_af33
	ip dscp cs4 goto ct_set_cs4
	ip dscp af41 goto ct_set_af41
	ip dscp af42 goto ct_set_af42
	ip dscp af43 goto ct_set_af43
	ip dscp cs5 goto ct_set_cs5
	ip dscp va goto ct_set_va
	ip dscp ef goto ct_set_ef
	ip dscp cs6 goto ct_set_cs6
	ip dscp cs7 goto ct_set_cs7

	ip6 dscp cs0 goto ct_set_cs0
	ip6 dscp lephb goto ct_set_lephb
	ip6 dscp cs1 goto ct_set_cs1
	ip6 dscp af11 goto ct_set_af11
	ip6 dscp af12 goto ct_set_af12
	ip6 dscp af13 goto ct_set_af13
	ip6 dscp cs2 goto ct_set_cs2
	ip6 dscp af21 goto ct_set_af21
	ip6 dscp af22 goto ct_set_af22
	ip6 dscp af23 goto ct_set_af23
	ip6 dscp cs3 goto ct_set_cs3
	ip6 dscp af31 goto ct_set_af31
	ip6 dscp af32 goto ct_set_af32
	ip6 dscp af33 goto ct_set_af33
	ip6 dscp cs4 goto ct_set_cs4
	ip6 dscp af41 goto ct_set_af41
	ip6 dscp af42 goto ct_set_af42
	ip6 dscp af43 goto ct_set_af43
	ip6 dscp cs5 goto ct_set_cs5
	ip6 dscp va goto ct_set_va
	ip6 dscp ef goto ct_set_ef
	ip6 dscp cs6 goto ct_set_cs6
	ip6 dscp cs7 goto ct_set_cs7
    }
}