[manage.py] Add setNftables() & sudoRun()

This commit is contained in:
Viyurz 2024-10-01 13:44:53 +02:00
parent 5ca129bcd5
commit b0e440d652
Signed by: Viyurz
SSH key fingerprint: SHA256:IskOHTmhHSJIvAt04N6aaxd5SZCVWW1Guf9tEcxIMj8
3 changed files with 112 additions and 4 deletions

View file

@ -1,6 +1,7 @@
#!/usr/bin/python3 #!/usr/bin/python3
import os, sys, re import os, sys, re
import filecmp
from glob import glob from glob import glob
from mako.template import Template from mako.template import Template
import subprocess import subprocess
@ -74,6 +75,16 @@ def setCertPerms(service):
setPerms(pkeyFile, 640) setPerms(pkeyFile, 640)
def setNftables():
renderFile("nftables.conf.mako")
if not filecmp.cmp("nftables.conf.rendered", "/etc/nftables.conf"):
print("nftables.conf changed, copying new version.")
sudoRun(["cp", "nftables.conf.rendered", "/etc/nftables.conf"])
sudoRun(["systemctl", "restart", "nftables"])
else:
print("nftables.conf unchanged.")
def setOwner(path, uid=None, gid=None): def setOwner(path, uid=None, gid=None):
stat = os.stat(path) stat = os.stat(path)
if not uid: if not uid:
@ -83,9 +94,7 @@ def setOwner(path, uid=None, gid=None):
if stat.st_uid != uid or stat.st_gid != gid: if stat.st_uid != uid or stat.st_gid != gid:
print(f"Changing ownership of {path} to {uid}:{gid} from {stat.st_uid}:{stat.st_gid}.") print(f"Changing ownership of {path} to {uid}:{gid} from {stat.st_uid}:{stat.st_gid}.")
child = subprocess.Popen(["sudo", "chown", f"{uid}:{gid}", path], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) sudoRun(["chown", f"{uid}:{gid}", path])
if re.search('^\\[sudo\\] password for .+', child.stdout.read().strip()):
child.communicate(input=input().encode())[0]
else: else:
print(f"Ownership of {path} already set to {uid}:{gid}.") print(f"Ownership of {path} already set to {uid}:{gid}.")
@ -119,6 +128,12 @@ def setupProj(project):
upProj(project) upProj(project)
def sudoRun(args):
child = subprocess.Popen(["sudo"] + args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if re.search('^\\[sudo\\] password for .+', child.stdout.read().strip()):
child.communicate(input=input().encode())[0]
def upProj(project): def upProj(project):
print(f"Creating & starting stack for project {project}.") print(f"Creating & starting stack for project {project}.")
if subprocess.run(["podman", "container", "exists", project]).returncode == 0: if subprocess.run(["podman", "container", "exists", project]).returncode == 0:
@ -172,6 +187,8 @@ def main():
target_projects = target_projects.split(' ') target_projects = target_projects.split(' ')
print(f"Target projects: {target_projects}") print(f"Target projects: {target_projects}")
setNftables()
match action: match action:
case '1' | 'S': case '1' | 'S':
for project in target_projects: for project in target_projects:

90
nftables.conf.mako Executable file
View file

@ -0,0 +1,90 @@
#!/usr/sbin/nft -f
flush ruleset
table inet nat {
chain prerouting {
type nat hook prerouting priority dstnat;
iif eth0 tcp dport ${env['ports']['syncthing_relaysrv']} redirect to :22067
iif eth0 tcp dport 25 redirect to :${env['ports']['mailserver_smtp']}
iif eth0 tcp dport 465 redirect to :${env['ports']['mailserver_smtps']}
iif eth0 tcp dport 993 redirect to :${env['ports']['mailserver_imaps']}
}
}
table inet filter {
set blackhole_ipv4 {
type ipv4_addr
timeout 30s
flags dynamic
}
set blackhole_ipv6 {
type ipv6_addr
timeout 30s
flags dynamic
}
chain input {
type filter hook input priority 0; policy drop;
iif lo accept
# Block all IPs in blackhole
ip saddr @blackhole_ipv4 set update ip saddr @blackhole_ipv4 drop
ip6 saddr @blackhole_ipv6 set update ip6 saddr @blackhole_ipv6 drop
ct state invalid drop
ct state { established, related } accept
<%text>
# Prevent DDoS
# Rate limiting
meta nfproto ipv4 meter ratelimit4 \
{ ip saddr limit rate over 75/second burst 15 packets } \
add @blackhole_ipv4 { ip saddr } counter
meta nfproto ipv6 meter ratelimit6 \
{ ip6 saddr limit rate over 75/second burst 15 packets } \
add @blackhole_ipv6 { ip6 saddr } counter
# Max concurrent connections
meta nfproto ipv4 meter connlimit4 \
{ ip saddr ct count over 100 } add @blackhole_ipv4 { ip saddr } counter
meta nfproto ipv6 meter connlimit6 \
{ ip6 saddr ct count over 100 } add @blackhole_ipv6 { ip6 saddr } counter
</%text>
# Allow ICMP
meta l4proto icmp accept
meta l4proto ipv6-icmp accept
# HTTP/S
tcp dport { http, https } accept
# SSH
tcp dport ssh accept
# SMTP/IMAP
tcp dport { ${env['ports']['mailserver_smtp']}, ${env['ports']['mailserver_smtps']}, ${env['ports']['mailserver_imaps']} } accept
# Syncthing
tcp dport { ${env['ports']['syncthing_tcp']}, 22067 } accept
udp dport ${env['ports']['syncthing_udp']} accept
# Coturn
tcp dport { ${env['ports']['coturn_listening']}, ${env['ports']['coturn_tls_listening']} } accept
udp dport { ${env['ports']['coturn_listening']}, ${env['ports']['coturn_tls_listening']}, ${env['ports']['coturn_relay_min']}-${env['ports']['coturn_relay_max']} } accept
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
# Don't waste resources responding to blocked IPs
ip daddr @blackhole_ipv4 reject
ip6 daddr @blackhole_ipv6 reject
}
}

View file

@ -6,7 +6,7 @@ if [[ $(whoami) == "root" ]]; then
fi fi
sudo apt install -y aardvark-dns dbus-user-session passt podman podman-compose python3-mako uidmap sudo apt install -y aardvark-dns dbus-user-session nftables passt podman podman-compose python3-mako uidmap
for unit in podman.service podman.socket podman-auto-update.service podman-auto-update.timer podman-clean-transient.service podman-restart.service; do for unit in podman.service podman.socket podman-auto-update.service podman-auto-update.timer podman-clean-transient.service podman-restart.service; do
@ -36,5 +36,6 @@ for key in "${!sysctl_vars[@]}"; do
done done
systemctl enable --now nftables
systemctl --user daemon-reload systemctl --user daemon-reload
systemctl --user restart podman systemctl --user restart podman