#!/usr/bin/nft -f
# WARNING: This file is automatically managed by ansible, any changes in it will be discarded on configuration reload

flush ruleset

table inet filter {
  chain input {
    type filter hook input priority 0;

    # allow established/related connections
    ct state { established, related } accept

    # early drop of invalid connections
    ct state invalid drop

    # allow from loopback
    iifname lo accept

    iifname { {{ eth_external | join(", ") }} } jump input-ext
    iifname { {{ eth_internal | join(", ") }} } jump input-int

    drop
  }

  chain input-ext {
    # allow icmp
    ip protocol icmp limit rate 10/second accept
    ip protocol icmp log prefix "icmp rate " drop
    ip6 nexthdr icmpv6 limit rate 10/second accept
    ip6 nexthdr icmpv6 log prefix "icmpv6 rate " drop

    ip saddr { 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 127.0.0.0/8 } \
        drop;

    tcp dport {
      64697, # znc irc only
      ssh
    } limit rate 15/minute accept
    tcp dport {
      http,
      https
    } accept
    tcp dport { domain } limit rate 20/second accept
    udp dport { domain } limit rate 20/second accept
    udp dport { 64194 } accept # OpenVPN
  }

  chain input-int {
    ip protocol icmp accept
    ip6 nexthdr icmpv6 accept

    tcp dport {
      smtp,
      ssh,
      http,
      https,
      53, # dns
      64697, # znc irc only
      64698 # znc admin internal
    } accept
    
    udp dport {
      53, # dns
      67, 68, # DHCPv4
      547, # DHCPv6
      64194 # OpenVPN
    } accept

    drop # without log
  }

  chain forward {
    type filter hook forward priority 0;

    iifname { {{ eth_external | join(", ") }} } \
        oifname { {{ eth_internal | join(", ") }} } \
        ct state { established, related } \
        accept

    iifname { {{ eth_internal | join(", ") }} } \
        oifname { {{ eth_external | join(", " ) }} } \
        accept

    drop
  }

  chain output {
    type filter hook output priority 0;
  }

}

table nat {

  chain prerouting {
    type nat hook prerouting priority -100;
    
    {% if nat is defined %}
      {% for host in nat.ports %}
        {% if host.tcp is defined %}
          iifname { {{ eth_external | join(", ") }} } \
              tcp dport { {{ host.tcp | join(", ") }} } \
              log prefix "dnat tcp to {{ host.name }} " \
              dnat {{ host.dst }} # {{ host.name }}
        {% endif %}
        {% if host.udp is defined %}
          iifname { {{ eth_external | join(", ") }} } \
              udp dport { {{ host.udp | join(", ") }} } \
              log prefix "dnat tcp to {{ host.name }} " \
              dnat {{ host.dst }} # {{ host.name }}
        {% endif %}
      {% endfor %}
    {% endif %}
  }

  chain postrouting {
    type nat hook postrouting priority 100;

    oifname { {{ eth_external | join(", ") }} } \
        masquerade
  }
}

# vim:set ts=2 sw=2 et:
