215 lignes
6.7 KiB
Django/Jinja
215 lignes
6.7 KiB
Django/Jinja
#!/usr/bin/env nft -f
|
|
# The home-server project produces a multi-purpose setup using Ansible.
|
|
# Copyright © 2018 Y. Gablin, under the GPL-3.0-or-later license.
|
|
# Full licensing information in the LICENSE file, or gnu.org/licences/gpl-3.0.txt if the file is missing.
|
|
|
|
flush ruleset
|
|
|
|
{% for V in ['4', '6'] %}
|
|
{% set v = V | replace('4', '') %}
|
|
{% macro trust(list) %}
|
|
{% for net in list.split(' ') %}
|
|
{% if not net is match('127(?:\.\d{1,3}){3}(?:/\d+)?|::1|^$') %}
|
|
{% if (net is match('\d{1,3}(?:\.\d{1,3}){3}(?:/\d+)?')
|
|
and V == '4') or (net is search(':') and V == '6') %}
|
|
{{caller(net)}}
|
|
{% endif %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endmacro %}
|
|
|
|
table ip{{v}} Inet{{V}} {
|
|
set https_ban {
|
|
type ipv{{V}}_addr
|
|
flags timeout
|
|
}
|
|
set mail_ban {
|
|
type ipv{{V}}_addr
|
|
flags timeout
|
|
}
|
|
set sshd_ban {
|
|
type ipv{{V}}_addr
|
|
flags timeout
|
|
}
|
|
|
|
{% set seq = fw_portknock_seq.split(' ') %}
|
|
{% for port in seq %}
|
|
set Knocked_{{loop.index}} {
|
|
type ipv{{V}}_addr
|
|
flags timeout
|
|
{% if loop.last %}
|
|
timeout {{fw_knock_timeout_min}}m
|
|
{% else %}
|
|
timeout 10s
|
|
{% endif %}
|
|
gc-interval 4s
|
|
}
|
|
{% endfor %}
|
|
|
|
chain doBan {
|
|
type filter hook prerouting priority -200; policy accept;
|
|
|
|
ip{{v}} saddr @https_ban tcp dport {80, 443} drop
|
|
ip{{v}} saddr @mail_ban tcp dport {25, 465, 587, 993} drop
|
|
ip{{v}} saddr @sshd_ban tcp dport {22, 2222, 22000} drop
|
|
}
|
|
|
|
chain NAT_in {
|
|
type nat hook prerouting priority -100
|
|
{% call(net) trust(SafeZone_IP) %}
|
|
|
|
# Git SSH
|
|
tcp dport 2222 log prefix "DNAT/git: " dnat to {{net}}
|
|
{% endcall %}
|
|
|
|
# Trusted hosts
|
|
tcp dport 443 ip{{v}} saddr @Knocked_{{seq | length}} log prefix "DNAT/HTTPS after Port-Knock: " redirect to 444
|
|
{% call(net) trust(net_trusted_ranges) %}
|
|
tcp dport 443 ip{{v}} saddr {{net}} redirect to 444
|
|
{% endcall %}
|
|
tcp dport 22 ip{{v}} saddr @Knocked_{{seq | length}} log prefix "DNAT/SSH after Port-Knock: " redirect to 23
|
|
{% call(net) trust(net_trusted_ranges) %}
|
|
tcp dport 22 ip{{v}} saddr {{net}} redirect to 23
|
|
{% endcall %}
|
|
}
|
|
chain NAT_out {
|
|
type nat hook postrouting priority 100
|
|
ct status dnat masquerade
|
|
}
|
|
|
|
{% for port in seq %}
|
|
chain Knock_{{loop.index}} {
|
|
{% if not loop.first %}
|
|
set update ip{{v}} saddr timeout 0s @Knocked_{{loop.index-1}}
|
|
{% endif %}
|
|
set add ip{{v}} saddr @Knocked_{{loop.index}}{% if loop.last %} log prefix "Port-Knock accepted: "{% endif %}
|
|
|
|
}
|
|
{% if not loop.last %}
|
|
chain Unknock_{{loop.index}} {
|
|
set update ip{{v}} saddr timeout 0s @Knocked_{{loop.index}}
|
|
}
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
chain RefreshKnock {
|
|
set update ip{{v}} saddr timeout {{fw_knock_timeout_min}}m @Knocked_{{seq | length}}
|
|
}
|
|
|
|
chain PortKnock {
|
|
{% for port in seq | reverse %}
|
|
{% if loop.first %}
|
|
ct state new ip{{v}} saddr @Knocked_{{loop.revindex}} goto RefreshKnock
|
|
{% else %}
|
|
tcp dport {{seq[loop.revindex]}} ct state new ip{{v}} saddr @Knocked_{{loop.revindex}} goto Knock_{{loop.revindex+1}}
|
|
tcp dport {{port}} ct state new ip{{v}} saddr @Knocked_{{loop.revindex}} return
|
|
ip{{v}} saddr @Knocked_{{loop.revindex}} ct state new goto Unknock_{{loop.revindex}}
|
|
{% endif %}
|
|
{% if loop.last %}
|
|
tcp dport {{port}} ct state new goto Knock_{{loop.revindex}}
|
|
{% endif %}
|
|
{% endfor %}
|
|
}
|
|
|
|
chain FilterIn {
|
|
type filter hook input priority 0
|
|
policy drop
|
|
|
|
# allow established/related connections
|
|
ct state {established, related} accept
|
|
|
|
# early drop of invalid connections
|
|
ct state invalid drop
|
|
|
|
# allow from loopback
|
|
meta iif lo accept
|
|
|
|
# allow icmp
|
|
{% if V == '4' %}
|
|
ip protocol icmp accept
|
|
{% else %}
|
|
ip6 nexthdr icmpv6 accept
|
|
{% endif %}
|
|
|
|
# allow iodine
|
|
meta iifname dns0 accept
|
|
|
|
# port-knocking
|
|
jump PortKnock
|
|
|
|
# trusted ssh and https
|
|
ct status dnat accept
|
|
|
|
# smtp
|
|
tcp dport 25 accept
|
|
|
|
# iodine
|
|
tcp dport 53 accept
|
|
udp dport 53 accept
|
|
|
|
# http
|
|
tcp dport 80 accept
|
|
|
|
# https
|
|
tcp dport 443 accept
|
|
|
|
# smtps
|
|
tcp dport 465 accept
|
|
|
|
# submission (smtp)
|
|
tcp dport 587 accept
|
|
|
|
# ipp
|
|
{% call(net) trust(net_trusted_ranges) %}
|
|
tcp dport 631 ip{{v}} saddr {{net}} accept
|
|
udp dport 631 ip{{v}} saddr {{net}} accept
|
|
{% endcall %}
|
|
|
|
# imaps
|
|
tcp dport 993 accept
|
|
|
|
# xmpp client
|
|
tcp dport 5222 accept
|
|
|
|
# xmpp server
|
|
tcp dport 5269 accept
|
|
|
|
# xmpp components
|
|
tcp dport 5347 accept
|
|
|
|
# zeroconf
|
|
{% call(net) trust(net_trusted_ranges) %}
|
|
udp dport 5353 ip{{v}} saddr {{net}} accept
|
|
{% endcall %}
|
|
|
|
# remote-help ssh
|
|
tcp dport 22000 accept
|
|
{% call(net) trust(net_trusted_ranges) %}
|
|
tcp dport 22001-22009 ip{{v}} saddr {{net}} accept
|
|
{% endcall %}
|
|
|
|
# transmission
|
|
tcp dport {{transmission_bt_port}} accept
|
|
udp dport {{transmission_bt_port}} accept
|
|
}
|
|
|
|
chain FilterOut {
|
|
type filter hook output priority 0
|
|
policy drop
|
|
ct state {established, related} accept
|
|
meta oif lo accept
|
|
{% call(net) trust(SafeZone_IP + ' ' + dns_hosts + ' ' + allowed_domains_ip + ' ' + ntp_hosts) %}
|
|
ip{{v}} daddr {{net}} accept
|
|
{% endcall %}
|
|
meta skuid {{aur_user}} accept
|
|
meta skuid exim tcp dport 25 accept
|
|
meta skuid prosody accept
|
|
meta skgid spamd accept
|
|
meta skuid transmission tcp dport 443 accept
|
|
meta skuid transmission udp dport 443 accept
|
|
meta skuid transmission tcp dport > 1024 accept
|
|
meta skuid transmission udp dport > 1024 accept
|
|
}
|
|
}
|
|
{% endfor %}
|