[manage.py] Add setNftables() & sudoRun()
This commit is contained in:
parent
5ca129bcd5
commit
b0e440d652
3 changed files with 112 additions and 4 deletions
23
manage.py
23
manage.py
|
@ -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
90
nftables.conf.mako
Executable 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue