Scan inbound and outbound via the smarthost only, harden rspamd and Valkey
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful

- tag inbound instead of rejecting, keep virus reject and tempfail when ClamAV fails
- score inbound against the first hop before the edge relays
- sign and skip GPT only for smarthost mynetworks sources
- elect the highest-offset Valkey on full restart, cap memory at 384mb
- read a hashed controller password
This commit is contained in:
2026-10-12 22:14:55 +11:00
parent f627902dd6
commit ecede40f7f
14 changed files with 146 additions and 49 deletions
+1 -2
View File
@@ -1,5 +1,4 @@
# Sign outbound only: authenticated or local_addrs senders, never inbound.
sign_authenticated = true;
sign_authenticated = false;
sign_local = true;
sign_inbound = false;
use_domain = "header";
@@ -0,0 +1,8 @@
# Edge gateway public IPs (smarthost gateways.cidr): score the first hop before them.
enabled = true;
rules {
EDGE_RELAY {
strategy = "ip_map";
ip_map = ["192.0.2.1/32", "192.0.2.2/32"];
}
}
+7
View File
@@ -0,0 +1,7 @@
rules {
CLAMAV_UNAVAILABLE {
action = "soft reject";
expression = "CLAM_VIRUS_FAIL";
message = "Virus scanner unavailable, try again later";
}
}
+1 -4
View File
@@ -10,12 +10,9 @@ model_parameters = {
}
};
timeout = 10s;
# Only ask the model about inbound mail whose score is uncertain (2 <= score < 12).
# Inbound only (settings.conf disables it outbound); only uncertain scores (2 <= score < 12).
condition = <<EOD
return function(task)
if task:get_user() then return false, 'authenticated' end
local ip = task:get_from_ip()
if ip and ip:is_local() then return false, 'local sender' end
local res = task:get_metric_result()
if not res then return false, 'no result' end
if res.passthrough then return false, 'passthrough' end
+30
View File
@@ -0,0 +1,30 @@
# Outbound sources (smarthost mynetworks): DKIM-signed, scored with reject, no GPT.
127.0.0.0/8
::1
10.42.0.0/16
10.10.12.200/32
198.18.1.10/32
198.18.2.160/27
198.18.2.192/27
198.18.13.0/24
198.18.14.0/24
198.18.15.0/24
198.18.16.0/24
198.18.17.0/24
198.18.18.0/24
198.18.19.0/24
198.18.20.0/24
198.18.21.0/24
198.18.22.0/24
198.18.23.0/24
198.18.25.0/24
198.18.26.0/24
198.18.27.0/24
198.18.28.0/24
198.18.29.0/24
198.18.64.0/24
198.18.65.0/24
198.18.66.0/24
198.18.67.0/24
198.18.68.0/24
198.18.69.0/24
@@ -0,0 +1,2 @@
use = ["x-spamd-result", "x-spam-status", "x-spam-level", "authentication-results"];
skip_local = true;
+1 -2
View File
@@ -1,3 +1,2 @@
# Pod network (Stalwart via the smarthost) and lab networks: local, so outbound mail from them is DKIM-signed.
local_addrs = ["127.0.0.0/8", "::1", "10.42.0.0/16", "198.18.0.0/16"];
local_addrs = "/etc/rspamd/local.d/local_networks.map";
task_timeout = 20s;
+19
View File
@@ -0,0 +1,19 @@
outbound {
priority = high;
ip_map = "/etc/rspamd/local.d/local_networks.map";
apply {
symbols_disabled = ["GPT_CHECK"];
}
}
inbound {
priority = high;
ip_map = "/etc/rspamd/local.d/local_networks.map";
inverse = true;
apply {
symbols_disabled = ["DKIM_SIGNED"];
# Tag only; reject stays defined (unreachable by score) so ClamAV's virus reject still applies.
actions {
reject = 1000;
}
}
}
+2 -2
View File
@@ -1,3 +1,3 @@
password = "{= env.CONTROLLER_PASSWORD =}";
enable_password = "{= env.CONTROLLER_PASSWORD =}";
password = "{= env.CONTROLLER_PASSWORD_HASH =}";
enable_password = "{= env.CONTROLLER_PASSWORD_HASH =}";
allow_file_and_shm_inputs = false;