summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accounts/gkleen@sif/default.nix3
-rw-r--r--accounts/gkleen@sif/ssh-hosts.nix5
-rw-r--r--flake.lock3
-rw-r--r--flake.nix1
-rw-r--r--hosts/surtr/dns/zones/email.bouncy.soa10
-rw-r--r--hosts/surtr/email/ccert-policy-server/ccert_policy_server/__main__.py35
-rw-r--r--hosts/surtr/email/default.nix144
-rw-r--r--hosts/surtr/postgresql/default.nix14
-rw-r--r--hosts/surtr/ruleset.nft37
-rw-r--r--hosts/surtr/vpn/default.nix9
-rw-r--r--hosts/surtr/zfs.nix9
-rw-r--r--hosts/vidhar/dns/zones/yggdrasil.soa3
-rw-r--r--hosts/vidhar/network/default.nix2
-rw-r--r--hosts/vidhar/network/gpon.nix (renamed from hosts/vidhar/network/dsl.nix)14
-rw-r--r--hosts/vidhar/network/ruleset.nft72
-rw-r--r--hosts/vidhar/prometheus/default.nix60
-rw-r--r--hosts/vidhar/prometheus/zte_dsl01.mgmt.yggdrasil26
-rw-r--r--modules/postfwd.nix27
-rwxr-xr-xoverlays/worktime/worktime/__main__.py12
19 files changed, 309 insertions, 177 deletions
diff --git a/accounts/gkleen@sif/default.nix b/accounts/gkleen@sif/default.nix
index 2e7a25c9..87cd9e2f 100644
--- a/accounts/gkleen@sif/default.nix
+++ b/accounts/gkleen@sif/default.nix
@@ -143,7 +143,7 @@ in {
143 # ProxyCommand ${pkgs.socat}/bin/socat - SOCKS4A:127.0.0.1:%h:%p,socksport=8118 143 # ProxyCommand ${pkgs.socat}/bin/socat - SOCKS4A:127.0.0.1:%h:%p,socksport=8118
144 ProxyJump ssh.math.lmu.de 144 ProxyJump ssh.math.lmu.de
145 145
146 Match host *.cipmath.loc !host cip04.cipmath.loc !exec "nc -z -w 1 %h %p &>/dev/null" 146 Match host *.cipmath.loc !host cip04.cipmath.loc,mgmt-cls01.cipmath.loc !exec "nc -z -w 1 %h %p &>/dev/null"
147 ProxyJump cip04 147 ProxyJump cip04
148 148
149 Match host *.ifi.lmu.de,*.math.lmu.de 149 Match host *.ifi.lmu.de,*.math.lmu.de
@@ -225,6 +225,7 @@ in {
225 scrot = "$HOME/screenshots"; 225 scrot = "$HOME/screenshots";
226 flk = "$HOME/config/nixos-flakes"; 226 flk = "$HOME/config/nixos-flakes";
227 rz = "$HOME/projects/rz"; 227 rz = "$HOME/projects/rz";
228 pro = "$HOME/projects/pro";
228 }; 229 };
229 230
230 obs-studio = { 231 obs-studio = {
diff --git a/accounts/gkleen@sif/ssh-hosts.nix b/accounts/gkleen@sif/ssh-hosts.nix
index 8a34376a..ac930614 100644
--- a/accounts/gkleen@sif/ssh-hosts.nix
+++ b/accounts/gkleen@sif/ssh-hosts.nix
@@ -445,6 +445,11 @@
445 { hostname = "cip04.cipmath.loc"; 445 { hostname = "cip04.cipmath.loc";
446 proxyJump = "mathw0h"; 446 proxyJump = "mathw0h";
447 }; 447 };
448 "mgmt-cls01" =
449 { user = "root";
450 hostname = "mgmt-cls01.cipmath.loc";
451 proxyJump = "ssh.math.lmu.de";
452 };
448 "mgmt01" = 453 "mgmt01" =
449 { hostname = "mgmt01.mathinst.loc"; 454 { hostname = "mgmt01.mathinst.loc";
450 proxyJump = "mathw0h"; 455 proxyJump = "mathw0h";
diff --git a/flake.lock b/flake.lock
index 0c0a7ad1..09989a6a 100644
--- a/flake.lock
+++ b/flake.lock
@@ -815,6 +815,9 @@
815 "nixos-hardware": "nixos-hardware", 815 "nixos-hardware": "nixos-hardware",
816 "nixpkgs": "nixpkgs_2", 816 "nixpkgs": "nixpkgs_2",
817 "nixpkgs-eostre": "nixpkgs-eostre", 817 "nixpkgs-eostre": "nixpkgs-eostre",
818 "nixpkgs-installer": [
819 "nixpkgs-stable"
820 ],
818 "nixpkgs-pgbackrest": "nixpkgs-pgbackrest", 821 "nixpkgs-pgbackrest": "nixpkgs-pgbackrest",
819 "nixpkgs-stable": "nixpkgs-stable_2", 822 "nixpkgs-stable": "nixpkgs-stable_2",
820 "nvfetcher": "nvfetcher", 823 "nvfetcher": "nvfetcher",
diff --git a/flake.nix b/flake.nix
index 6f24a90c..dca04010 100644
--- a/flake.nix
+++ b/flake.nix
@@ -35,6 +35,7 @@
35 repo = "nixpkgs"; 35 repo = "nixpkgs";
36 ref = "23.11"; 36 ref = "23.11";
37 }; 37 };
38 nixpkgs-installer.follows = "nixpkgs-stable";
38 home-manager = { 39 home-manager = {
39 type = "github"; 40 type = "github";
40 # owner = "nix-community"; 41 # owner = "nix-community";
diff --git a/hosts/surtr/dns/zones/email.bouncy.soa b/hosts/surtr/dns/zones/email.bouncy.soa
index 40e4b78b..2b319a93 100644
--- a/hosts/surtr/dns/zones/email.bouncy.soa
+++ b/hosts/surtr/dns/zones/email.bouncy.soa
@@ -1,7 +1,7 @@
1$ORIGIN bouncy.email. 1$ORIGIN bouncy.email.
2$TTL 3600 2$TTL 3600
3@ IN SOA ns.yggdrasil.li. hostmaster.yggdrasil.li ( 3@ IN SOA ns.yggdrasil.li. hostmaster.yggdrasil.li (
4 2023020101 ; serial 4 2024070901 ; serial
5 10800 ; refresh 5 10800 ; refresh
6 3600 ; retry 6 3600 ; retry
7 604800 ; expire 7 604800 ; expire
@@ -41,10 +41,10 @@ mailin IN MX 0 mailin.bouncy.email.
41mailin IN TXT "v=spf1 redirect=bouncy.email" 41mailin IN TXT "v=spf1 redirect=bouncy.email"
42_acme-challenge.mailin IN NS ns.yggdrasil.li. 42_acme-challenge.mailin IN NS ns.yggdrasil.li.
43 43
44_25._tcp.mailin IN TLSA 2 1 1 276fe8a8c4ec7611565bf9fce6dcace9be320c1b5bea27596b2204071ed04f10 44; _25._tcp.mailin IN TLSA 2 1 1 276fe8a8c4ec7611565bf9fce6dcace9be320c1b5bea27596b2204071ed04f10
45_25._tcp.mailin IN TLSA 2 1 1 bd936e72b212ef6f773102c6b77d38f94297322efc25396bc3279422e0c89270 45; _25._tcp.mailin IN TLSA 2 1 1 bd936e72b212ef6f773102c6b77d38f94297322efc25396bc3279422e0c89270
46_25._tcp.mailin IN TLSA 2 1 1 8d02536c887482bc34ff54e41d2ba659bf85b341a0a20afadb5813dcfbcf286d 46; _25._tcp.mailin IN TLSA 2 1 1 8d02536c887482bc34ff54e41d2ba659bf85b341a0a20afadb5813dcfbcf286d
47_25._tcp.mailin IN TLSA 2 1 1 e5545e211347241891c554a03934cde9b749664a59d26d615fe58f77990f2d03 47; _25._tcp.mailin IN TLSA 2 1 1 e5545e211347241891c554a03934cde9b749664a59d26d615fe58f77990f2d03
48 48
49mailsub IN A 202.61.241.61 49mailsub IN A 202.61.241.61
50mailsub IN AAAA 2a03:4000:52:ada:: 50mailsub IN AAAA 2a03:4000:52:ada::
diff --git a/hosts/surtr/email/ccert-policy-server/ccert_policy_server/__main__.py b/hosts/surtr/email/ccert-policy-server/ccert_policy_server/__main__.py
index f481090c..00182523 100644
--- a/hosts/surtr/email/ccert-policy-server/ccert_policy_server/__main__.py
+++ b/hosts/surtr/email/ccert-policy-server/ccert_policy_server/__main__.py
@@ -27,20 +27,27 @@ class PolicyHandler(StreamRequestHandler):
27 logger.info('Connection parameters: %s', self.args) 27 logger.info('Connection parameters: %s', self.args)
28 28
29 allowed = False 29 allowed = False
30 with self.server.db_pool.connection() as conn: 30 user = None
31 local, domain = self.args['sender'].split(sep='@', maxsplit=1) 31 if self.args['sasl_username']:
32 extension = None 32 user = self.args['sasl_username']
33 if '+' in local: 33 if self.args['ccert_subject']:
34 local, extension = local.split(sep='+', maxsplit=1) 34 user = self.args['ccert_subject']
35 35
36 logger.debug('Parsed address: %s', {'local': local, 'extension': extension, 'domain': domain}) 36 if user:
37 37 with self.server.db_pool.connection() as conn:
38 with conn.cursor() as cur: 38 local, domain = self.args['sender'].split(sep='@', maxsplit=1)
39 cur.row_factory = namedtuple_row 39 extension = None
40 cur.execute('SELECT "mailbox"."mailbox" as "user", "local", "extension", "domain" FROM "mailbox" INNER JOIN "mailbox_mapping" ON "mailbox".id = "mailbox_mapping"."mailbox" WHERE "mailbox"."mailbox" = %(user)s AND ("local" = %(local)s OR "local" IS NULL) AND ("extension" = %(extension)s OR "extension" IS NULL) AND "domain" = %(domain)s', params = {'user': self.args['ccert_subject'], 'local': local, 'extension': extension if extension is not None else '', 'domain': domain}, prepare=True) 40 if '+' in local:
41 for record in cur: 41 local, extension = local.split(sep='+', maxsplit=1)
42 logger.debug('Received result: %s', record) 42
43 allowed = True 43 logger.debug('Parsed address: %s', {'local': local, 'extension': extension, 'domain': domain})
44
45 with conn.cursor() as cur:
46 cur.row_factory = namedtuple_row
47 cur.execute('SELECT "mailbox"."mailbox" as "user", "local", "extension", "domain" FROM "mailbox" INNER JOIN "mailbox_mapping" ON "mailbox".id = "mailbox_mapping"."mailbox" WHERE "mailbox"."mailbox" = %(user)s AND ("local" = %(local)s OR "local" IS NULL) AND ("extension" = %(extension)s OR "extension" IS NULL) AND "domain" = %(domain)s', params = {'user': user, 'local': local, 'extension': extension if extension is not None else '', 'domain': domain}, prepare=True)
48 for record in cur:
49 logger.debug('Received result: %s', record)
50 allowed = True
44 51
45 action = '550 5.7.0 Sender address not authorized for current user' 52 action = '550 5.7.0 Sender address not authorized for current user'
46 if allowed: 53 if allowed:
diff --git a/hosts/surtr/email/default.nix b/hosts/surtr/email/default.nix
index bb0f6e20..c10f611f 100644
--- a/hosts/surtr/email/default.nix
+++ b/hosts/surtr/email/default.nix
@@ -32,9 +32,63 @@ let
32 }); 32 });
33 }; 33 };
34 34
35 nftables-nologin-script = pkgs.writeScript "nftables-mail-nologin" ''
36 #!${pkgs.zsh}/bin/zsh
37
38 set -e
39 export PATH="${lib.makeBinPath (with pkgs; [inetutils nftables])}:$PATH"
40
41 typeset -a as_sets mnt_bys route route6
42 as_sets=(${lib.escapeShellArgs config.services.email.nologin.ASSets})
43 mnt_bys=(${lib.escapeShellArgs config.services.email.nologin.MNTBys})
44
45 for as_set in $as_sets; do
46 while IFS=$'\n' read line; do
47 if [[ "''${line}" =~ "^route:\s+(.+)$" ]]; then
48 route+=($match[1])
49 elif [[ "''${line}" =~ "^route6:\s+(.+)$" ]]; then
50 route6+=($match[1])
51 fi
52 done < <(whois -h whois.radb.net "!i''${as_set},1" | egrep -o 'AS[0-9]+' | xargs -- whois -h whois.radb.net -- -i origin)
53 done
54 for mnt_by in $mnt_bys; do
55 while IFS=$'\n' read line; do
56 if [[ "''${line}" =~ "^route:\s+(.+)$" ]]; then
57 route+=($match[1])
58 elif [[ "''${line}" =~ "^route6:\s+(.+)$" ]]; then
59 route6+=($match[1])
60 fi
61 done < <(whois -h whois.radb.net "!o''${mnt_by}")
62 done
63
64 printf -v elements4 '%s,' "''${route[@]}"
65 elements4=''${elements4%,}
66 printf -v elements6 '%s,' "''${route6[@]}"
67 elements6=''${elements6%,}
68 nft -f - <<EOF
69 flush set inet filter mail_nologin4
70 flush set inet filter mail_nologin6
71 add element inet filter mail_nologin4 {''${elements4}}
72 add element inet filter mail_nologin6 {''${elements6}}
73 EOF
74 '';
75
35 spmDomains = ["bouncy.email"]; 76 spmDomains = ["bouncy.email"];
36 emailDomains = spmDomains ++ ["kleen.consulting"]; 77 emailDomains = spmDomains ++ ["kleen.consulting"];
37in { 78in {
79 options = {
80 services.email.nologin = {
81 ASSets = mkOption {
82 type = types.listOf types.str;
83 default = [];
84 };
85 MNTBys = mkOption {
86 type = types.listOf types.str;
87 default = [];
88 };
89 };
90 };
91
38 config = { 92 config = {
39 nixpkgs.overlays = [ 93 nixpkgs.overlays = [
40 (final: prev: { 94 (final: prev: {
@@ -167,6 +221,7 @@ in {
167 maximal_backoff_time = "10m"; 221 maximal_backoff_time = "10m";
168 maximal_queue_lifetime = "100m"; 222 maximal_queue_lifetime = "100m";
169 bounce_queue_lifetime = "20m"; 223 bounce_queue_lifetime = "20m";
224 delay_warning_time = "10m";
170 225
171 smtpd_discard_ehlo_keyword_address_maps = "cidr:${pkgs.writeText "esmtp_access" '' 226 smtpd_discard_ehlo_keyword_address_maps = "cidr:${pkgs.writeText "esmtp_access" ''
172 # Allow DSN requests from local subnet only 227 # Allow DSN requests from local subnet only
@@ -204,17 +259,15 @@ in {
204 postscreen_greet_action = "enforce"; 259 postscreen_greet_action = "enforce";
205 }; 260 };
206 masterConfig = { 261 masterConfig = {
207 smtps = { 262 "465" = {
208 type = "inet"; 263 type = "inet";
209 private = false; 264 private = false;
210 command = "smtpd"; 265 command = "smtpd -v";
211 args = [ 266 args = [
212 "-o" "smtpd_tls_security_level=encrypt" 267 "-o" "smtpd_tls_security_level=encrypt"
213 "-o" "{smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1, !TLSv1.2}" 268 "-o" "{smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1, !TLSv1.2}"
214 "-o" "{smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1, !TLSv1.2}" 269 "-o" "{smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1, !TLSv1.2}"
215 "-o" "smtpd_tls_mandatory_ciphers=high" 270 "-o" "smtpd_tls_mandatory_ciphers=high"
216 "-o" "smtpd_tls_dh1024_param_file=${toString config.security.dhparams.params."postfix-smtps-1024".path}"
217 "-o" "smtpd_tls_dh512_param_file=${toString config.security.dhparams.params."postfix-smtps-512".path}"
218 "-o" "{tls_eecdh_auto_curves = X25519 X448}" 271 "-o" "{tls_eecdh_auto_curves = X25519 X448}"
219 272
220 "-o" "smtpd_tls_wrappermode=yes" 273 "-o" "smtpd_tls_wrappermode=yes"
@@ -223,22 +276,52 @@ in {
223 "-o" "smtpd_tls_received_header=no" 276 "-o" "smtpd_tls_received_header=no"
224 "-o" "cleanup_service_name=subcleanup" 277 "-o" "cleanup_service_name=subcleanup"
225 "-o" "smtpd_client_restrictions=permit_tls_all_clientcerts,reject" 278 "-o" "smtpd_client_restrictions=permit_tls_all_clientcerts,reject"
226 "-o" "{smtpd_data_restrictions = check_policy_service unix:/run/postfwd3/postfwd3.sock}"
227 "-o" "smtpd_relay_restrictions=permit_tls_all_clientcerts,reject"
228 "-o" "{smtpd_sender_restrictions = reject_unknown_sender_domain,reject_unverified_sender,check_policy_service unix:/run/postfix-ccert-sender-policy.sock}" 279 "-o" "{smtpd_sender_restrictions = reject_unknown_sender_domain,reject_unverified_sender,check_policy_service unix:/run/postfix-ccert-sender-policy.sock}"
280 "-o" ''{smtpd_recipient_restrictions=reject_unauth_pipelining,reject_non_fqdn_recipient,reject_unknown_recipient_domain,check_recipient_access pgsql:${pkgs.writeText "check_recipient_access.cf" ''
281 hosts = postgresql:///email
282 dbname = email
283 query = SELECT action FROM virtual_mailbox_access WHERE lookup = '%s' OR (lookup = regexp_replace('%s', '\+[^@]*@', '@') AND NOT EXISTS (SELECT 1 FROM virtual_mailbox_access WHERE lookup = '%s'))
284 ''},permit_tls_all_clientcerts,reject}''
285 "-o" "smtpd_relay_restrictions=permit_tls_all_clientcerts,reject"
286 "-o" "{smtpd_data_restrictions = check_policy_service unix:/run/postfwd3/postfwd3.sock}"
229 "-o" "unverified_sender_reject_code=550" 287 "-o" "unverified_sender_reject_code=550"
230 "-o" "unverified_sender_reject_reason={Sender address rejected: undeliverable address}" 288 "-o" "unverified_sender_reject_reason={Sender address rejected: undeliverable address}"
289 "-o" "milter_macro_daemon_name=surtr.yggdrasil.li"
290 "-o" ''smtpd_milters=${config.services.opendkim.socket}''
291 ];
292 };
293 "466" = {
294 type = "inet";
295 private = false;
296 command = "smtpd -v";
297 args = [
298 "-o" "smtpd_tls_security_level=encrypt"
299
300 "-o" "smtpd_tls_wrappermode=yes"
301 "-o" "smtpd_tls_ask_ccert=no"
302 "-o" "smtpd_tls_req_ccert=no"
303 "-o" "smtpd_sasl_type=dovecot"
304 "-o" "smtpd_sasl_path=/run/dovecot-sasl"
305 "-o" "smtpd_sasl_auth_enable=yes"
306 "-o" "smtpd_tls_received_header=no"
307 "-o" "cleanup_service_name=subcleanup"
308 "-o" "smtpd_client_restrictions=permit_sasl_authenticated,reject"
309 "-o" "{smtpd_sender_restrictions = reject_unknown_sender_domain,reject_unverified_sender,check_policy_service unix:/run/postfix-ccert-sender-policy.sock}"
231 "-o" ''{smtpd_recipient_restrictions=reject_unauth_pipelining,reject_non_fqdn_recipient,reject_unknown_recipient_domain,check_recipient_access pgsql:${pkgs.writeText "check_recipient_access.cf" '' 310 "-o" ''{smtpd_recipient_restrictions=reject_unauth_pipelining,reject_non_fqdn_recipient,reject_unknown_recipient_domain,check_recipient_access pgsql:${pkgs.writeText "check_recipient_access.cf" ''
232 hosts = postgresql:///email 311 hosts = postgresql:///email
233 dbname = email 312 dbname = email
234 query = SELECT action FROM virtual_mailbox_access WHERE lookup = '%s' OR (lookup = regexp_replace('%s', '\+[^@]*@', '@') AND NOT EXISTS (SELECT 1 FROM virtual_mailbox_access WHERE lookup = '%s')) 313 query = SELECT action FROM virtual_mailbox_access WHERE lookup = '%s' OR (lookup = regexp_replace('%s', '\+[^@]*@', '@') AND NOT EXISTS (SELECT 1 FROM virtual_mailbox_access WHERE lookup = '%s'))
235 ''},permit_tls_all_clientcerts,reject}'' 314 ''},permit_sasl_authenticated,reject}''
315 "-o" "smtpd_relay_restrictions=permit_sasl_authenticated,reject"
316 "-o" "{smtpd_data_restrictions = check_policy_service unix:/run/postfwd3/postfwd3.sock}"
317 "-o" "unverified_sender_reject_code=550"
318 "-o" "unverified_sender_reject_reason={Sender address rejected: undeliverable address}"
236 "-o" "milter_macro_daemon_name=surtr.yggdrasil.li" 319 "-o" "milter_macro_daemon_name=surtr.yggdrasil.li"
237 "-o" ''smtpd_milters=${config.services.opendkim.socket}'' 320 "-o" ''smtpd_milters=${config.services.opendkim.socket}''
238 ]; 321 ];
239 }; 322 };
240 subcleanup = { 323 subcleanup = {
241 command = "cleanup"; 324 command = "cleanup -v";
242 private = false; 325 private = false;
243 maxproc = 0; 326 maxproc = 0;
244 args = [ 327 args = [
@@ -256,13 +339,13 @@ in {
256 smtp_pass = { 339 smtp_pass = {
257 name = "smtpd"; 340 name = "smtpd";
258 type = "pass"; 341 type = "pass";
259 command = "smtpd"; 342 command = "smtpd -v";
260 }; 343 };
261 postscreen = { 344 postscreen = {
262 name = "smtp"; 345 name = "smtp";
263 type = "inet"; 346 type = "inet";
264 private = false; 347 private = false;
265 command = "postscreen"; 348 command = "postscreen -v";
266 maxproc = 1; 349 maxproc = 1;
267 }; 350 };
268 smtp = {}; 351 smtp = {};
@@ -417,7 +500,7 @@ in {
417 dovecotSqlConf = pkgs.writeText "dovecot-sql.conf" '' 500 dovecotSqlConf = pkgs.writeText "dovecot-sql.conf" ''
418 driver = pgsql 501 driver = pgsql
419 connect = dbname=email 502 connect = dbname=email
420 password_query = SELECT NULL as password, 'Y' as nopassword, "user", quota_rule, 'dovecot2' as uid, 'dovecot2' as gid FROM imap_user WHERE "user" = '%n' 503 password_query = SELECT (CASE WHEN '%k' = 'valid' AND '%m' = 'EXTERNAL' THEN NULL ELSE "password" END) as password, (CASE WHEN '%k' = 'valid' AND '%m' = 'EXTERNAL' THEN true WHEN password IS NULL THEN true ELSE NULL END) as nopassword, "user", quota_rule, 'dovecot2' as uid, 'dovecot2' as gid FROM imap_user WHERE "user" = '%n'
421 user_query = SELECT "user", quota_rule, 'dovecot2' as uid, 'dovecot2' as gid FROM imap_user WHERE "user" = '%n' 504 user_query = SELECT "user", quota_rule, 'dovecot2' as uid, 'dovecot2' as gid FROM imap_user WHERE "user" = '%n'
422 iterate_query = SELECT "user" FROM imap_user 505 iterate_query = SELECT "user" FROM imap_user
423 ''; 506 '';
@@ -449,7 +532,7 @@ in {
449 532
450 auth_ssl_username_from_cert = yes 533 auth_ssl_username_from_cert = yes
451 ssl_cert_username_field = commonName 534 ssl_cert_username_field = commonName
452 auth_mechanisms = external 535 auth_mechanisms = plain login external
453 536
454 auth_verbose = yes 537 auth_verbose = yes
455 verbose_ssl = yes 538 verbose_ssl = yes
@@ -505,6 +588,15 @@ in {
505 group = postfix 588 group = postfix
506 } 589 }
507 } 590 }
591 service auth {
592 vsz_limit = 2G
593
594 unix_listener /run/dovecot-sasl {
595 mode = 0600
596 user = postfix
597 group = postfix
598 }
599 }
508 600
509 namespace inbox { 601 namespace inbox {
510 separator = / 602 separator = /
@@ -869,9 +961,13 @@ in {
869 961
870 services.postfwd = { 962 services.postfwd = {
871 enable = true; 963 enable = true;
964 cache = false;
872 rules = '' 965 rules = ''
873 id=RCPT01; protocol_state=DATA; protocol_state=END-OF-MESSAGE; action=rcpt(ccert_subject/100/3600/set(HIT_RATELIMIT=1,HIT_RATECOUNT=$$ratecount,HIT_RATELIMIT_LIMIT=100,HIT_RATELIMIT_INTERVAL=3600)) 966 id=RCPT_SASL01; protocol_state=DATA; protocol_state=END-OF-MESSAGE; sasl_username!=; action=rcpt(sasl_username/100/3600/set(HIT_RATELIMIT=1,HIT_RATECOUNT=$$ratecount,HIT_RATELIMIT_LIMIT=100,HIT_RATELIMIT_INTERVAL=3600))
874 id=RCPT02; protocol_state=DATA; protocol_state=END-OF-MESSAGE; action=rcpt(ccert_subject/1000/86400/set(HIT_RATELIMIT=1,HIT_RATECOUNT=$$ratecount,HIT_RATELIMIT_LIMIT=1000,HIT_RATELIMIT_INTERVAL=86400)) 967 id=RCPT_SASL02; protocol_state=DATA; protocol_state=END-OF-MESSAGE; sasl_username!=; action=rcpt(sasl_username/1000/86400/set(HIT_RATELIMIT=1,HIT_RATECOUNT=$$ratecount,HIT_RATELIMIT_LIMIT=1000,HIT_RATELIMIT_INTERVAL=86400))
968
969 id=RCPT_CCERT01; protocol_state=DATA; protocol_state=END-OF-MESSAGE; ccert_subject!=; action=rcpt(ccert_subject/100/3600/set(HIT_RATELIMIT=1,HIT_RATECOUNT=$$ratecount,HIT_RATELIMIT_LIMIT=100,HIT_RATELIMIT_INTERVAL=3600))
970 id=RCPT_CCERT02; protocol_state=DATA; protocol_state=END-OF-MESSAGE; ccert_subject!=; action=rcpt(ccert_subject/1000/86400/set(HIT_RATELIMIT=1,HIT_RATECOUNT=$$ratecount,HIT_RATELIMIT_LIMIT=1000,HIT_RATELIMIT_INTERVAL=86400))
875 971
876 id=JUMP_REJECT_RL; HIT_RATELIMIT=="1"; action=jump(REJECT_RL) 972 id=JUMP_REJECT_RL; HIT_RATELIMIT=="1"; action=jump(REJECT_RL)
877 973
@@ -880,5 +976,25 @@ in {
880 id=REJECT_RL; action=450 4.7.1 Exceeding maximum of $$HIT_RATELIMIT_LIMIT recipients per $$HIT_RATELIMIT_INTERVAL seconds [$$HIT_RATECOUNT] 976 id=REJECT_RL; action=450 4.7.1 Exceeding maximum of $$HIT_RATELIMIT_LIMIT recipients per $$HIT_RATELIMIT_INTERVAL seconds [$$HIT_RATECOUNT]
881 ''; 977 '';
882 }; 978 };
979
980 services.email.nologin.MNTBys = ["MICROSOFT-MAINT"];
981 systemd.services.nftables.serviceConfig = {
982 ExecStart = lib.mkAfter [ nftables-nologin-script ];
983 ExecReload = lib.mkAfter [ nftables-nologin-script ];
984 };
985 systemd.services."nftables-mail-nologin" = {
986 serviceConfig = {
987 Type = "oneshot";
988 ExecStart = nftables-nologin-script;
989 };
990 };
991 systemd.timers."nftables-mail-nologin" = {
992 wantedBy = [ "nftables.service" ];
993
994 timerConfig = {
995 OnActiveSec = "20h";
996 RandomizedDelaySec = "8h";
997 };
998 };
883 }; 999 };
884} 1000}
diff --git a/hosts/surtr/postgresql/default.nix b/hosts/surtr/postgresql/default.nix
index f0e42ee8..583e4443 100644
--- a/hosts/surtr/postgresql/default.nix
+++ b/hosts/surtr/postgresql/default.nix
@@ -262,6 +262,20 @@ in {
262 262
263 GRANT DELETE ON "mailbox_mapping" TO "spm"; 263 GRANT DELETE ON "mailbox_mapping" TO "spm";
264 COMMIT; 264 COMMIT;
265
266 BEGIN;
267 SELECT _v.register_patch('011-password', ARRAY['000-base'], null);
268
269 ALTER TABLE mailbox ADD COLUMN password text CONSTRAINT password_non_empty CHECK (password IS DISTINCT FROM ''');
270 COMMIT;
271
272 BEGIN;
273 SELECT _v.register_patch('012-imap-password', ARRAY['000-base', '002-citext'], null);
274
275 DROP VIEW imap_user;
276 CREATE VIEW imap_user ("user", "password", quota_rule) AS SELECT mailbox.mailbox AS "user", "password", quota_rule FROM mailbox_quota_rule INNER JOIN mailbox ON mailbox_quota_rule.mailbox = mailbox.mailbox;
277
278 COMMIT;
265 ''} 279 ''}
266 280
267 psql etebase postgres -eXf ${pkgs.writeText "etebase.sql" '' 281 psql etebase postgres -eXf ${pkgs.writeText "etebase.sql" ''
diff --git a/hosts/surtr/ruleset.nft b/hosts/surtr/ruleset.nft
index ee72614f..5c2bba7c 100644
--- a/hosts/surtr/ruleset.nft
+++ b/hosts/surtr/ruleset.nft
@@ -86,6 +86,7 @@ table inet filter {
86 86
87 counter established-rx {} 87 counter established-rx {}
88 88
89 counter reject-mail-nologin {}
89 counter reject-ratelimit-rx {} 90 counter reject-ratelimit-rx {}
90 counter reject-rx {} 91 counter reject-rx {}
91 counter reject-tcp-rx {} 92 counter reject-tcp-rx {}
@@ -114,6 +115,17 @@ table inet filter {
114 115
115 counter tx {} 116 counter tx {}
116 117
118 set mail_nologin4 {
119 type ipv4_addr
120 flags interval
121 auto-merge
122 }
123 set mail_nologin6 {
124 type ipv6_addr
125 flags interval
126 auto-merge
127 }
128
117 chain forward { 129 chain forward {
118 type filter hook forward priority filter 130 type filter hook forward priority filter
119 policy drop 131 policy drop
@@ -145,6 +157,14 @@ table inet filter {
145 counter name drop-fw 157 counter name drop-fw
146 } 158 }
147 159
160 chain reject_input {
161 limit name lim_reject log level debug prefix "drop input: " counter name reject-ratelimit-rx drop
162 log level debug prefix "reject input: " counter name reject-rx
163 meta l4proto tcp ct state new counter name reject-tcp-rx reject with tcp reset
164 ct state new counter name reject-icmp-rx reject
165
166 counter name drop-rx
167 }
148 chain input { 168 chain input {
149 type filter hook input priority filter 169 type filter hook input priority filter
150 policy drop 170 policy drop
@@ -177,8 +197,11 @@ table inet filter {
177 udp dport {3478, 5349} counter name stun-rx accept 197 udp dport {3478, 5349} counter name stun-rx accept
178 udp dport 49000-50000 counter name turn-rx accept 198 udp dport 49000-50000 counter name turn-rx accept
179 199
200 tcp dport {465,466,993,4190} ip saddr @mail_nologin4 log prefix "mail nologin: " counter name reject-mail-nologin jump reject_input
201 tcp dport {465,466,993,4190} ip6 saddr @mail_nologin6 log prefix "mail nologin: " counter name reject-mail-nologin jump reject_input
202
180 tcp dport 25 counter name smtp-rx accept 203 tcp dport 25 counter name smtp-rx accept
181 tcp dport 465 counter name submissions-rx accept 204 tcp dport {465, 466} counter name submissions-rx accept
182 tcp dport 993 counter name imaps-rx accept 205 tcp dport 993 counter name imaps-rx accept
183 tcp dport 4190 counter name managesieve-rx accept 206 tcp dport 4190 counter name managesieve-rx accept
184 iifname yggdrasil tcp dport 8432 counter name pgbackrest-rx accept 207 iifname yggdrasil tcp dport 8432 counter name pgbackrest-rx accept
@@ -186,13 +209,7 @@ table inet filter {
186 ct state {established, related} counter name established-rx accept 209 ct state {established, related} counter name established-rx accept
187 210
188 211
189 limit name lim_reject log level debug prefix "drop input: " counter name reject-ratelimit-rx drop 212 jump reject_input
190 log level debug prefix "reject input: " counter name reject-rx
191 meta l4proto tcp ct state new counter name reject-tcp-rx reject with tcp reset
192 ct state new counter name reject-icmp-rx reject
193
194
195 counter name drop-rx
196 } 213 }
197 214
198 chain output { 215 chain output {
@@ -224,7 +241,7 @@ table inet filter {
224 udp sport 49000-50000 counter name turn-tx accept 241 udp sport 49000-50000 counter name turn-tx accept
225 242
226 tcp sport 25 counter name smtp-tx accept 243 tcp sport 25 counter name smtp-tx accept
227 tcp sport 465 counter name submissions-tx accept 244 tcp sport {465, 466} counter name submissions-tx accept
228 tcp sport 993 counter name imaps-tx accept 245 tcp sport 993 counter name imaps-tx accept
229 tcp sport 4190 counter name managesieve-tx accept 246 tcp sport 4190 counter name managesieve-tx accept
230 tcp sport 8432 counter name pgbackrest-tx accept 247 tcp sport 8432 counter name pgbackrest-tx accept
@@ -232,4 +249,4 @@ table inet filter {
232 249
233 counter name tx 250 counter name tx
234 } 251 }
235} \ No newline at end of file 252}
diff --git a/hosts/surtr/vpn/default.nix b/hosts/surtr/vpn/default.nix
index 1d31a6f2..3f7483bd 100644
--- a/hosts/surtr/vpn/default.nix
+++ b/hosts/surtr/vpn/default.nix
@@ -66,6 +66,15 @@ in {
66 66
67 systemd.network = { 67 systemd.network = {
68 netdevs = { 68 netdevs = {
69 upstream = {
70 netdevConfig = {
71 Name = "upstream";
72 Kind = "ipvlan";
73 };
74 ipvlanConfig = {
75 Mode = "L2";
76 };
77 };
69 vpn = { 78 vpn = {
70 netdevConfig = { 79 netdevConfig = {
71 Name = "vpn"; 80 Name = "vpn";
diff --git a/hosts/surtr/zfs.nix b/hosts/surtr/zfs.nix
index 583ab8e1..17c5cd32 100644
--- a/hosts/surtr/zfs.nix
+++ b/hosts/surtr/zfs.nix
@@ -17,7 +17,7 @@
17 fsType = "zfs"; 17 fsType = "zfs";
18 neededForBoot = true; 18 neededForBoot = true;
19 }; 19 };
20 20
21 "/var/lib/nixos" = 21 "/var/lib/nixos" =
22 { device = "surtr/local/var-lib-nixos"; 22 { device = "surtr/local/var-lib-nixos";
23 fsType = "zfs"; 23 fsType = "zfs";
@@ -62,10 +62,13 @@
62 }; 62 };
63 63
64 services.zfssnap.enable = true; 64 services.zfssnap.enable = true;
65 services.zfs.trim.enable = false; 65 services.zfs.trim = {
66 enable = true;
67 interval = "Sun 16:00:00 Europe/Berlin";
68 };
66 services.zfs.autoScrub = { 69 services.zfs.autoScrub = {
67 enable = true; 70 enable = true;
68 interval = "Sun *-*-1..7 04:00:00"; 71 interval = "Sun *-*-1..7 04:00:00 Europe/Berlin";
69 }; 72 };
70 services.zfs.zed.settings = { 73 services.zfs.zed.settings = {
71 ZED_SYSLOG_SUBCLASS_EXCLUDE = "history_event"; 74 ZED_SYSLOG_SUBCLASS_EXCLUDE = "history_event";
diff --git a/hosts/vidhar/dns/zones/yggdrasil.soa b/hosts/vidhar/dns/zones/yggdrasil.soa
index f679b741..dede06ac 100644
--- a/hosts/vidhar/dns/zones/yggdrasil.soa
+++ b/hosts/vidhar/dns/zones/yggdrasil.soa
@@ -1,7 +1,7 @@
1$ORIGIN yggdrasil. 1$ORIGIN yggdrasil.
2$TTL 300 2$TTL 300
3@ IN SOA vidhar.yggdrasil. hostmaster.yggdrasil.li ( 3@ IN SOA vidhar.yggdrasil. hostmaster.yggdrasil.li (
4 2023030501 ; serial 4 2024070901 ; serial
5 300 ; refresh 5 300 ; refresh
6 300 ; retry 6 300 ; retry
7 300 ; expire 7 300 ; expire
@@ -27,4 +27,5 @@ vidhar.lan IN A 10.141.0.1
27vidhar.mgmt IN A 10.141.1.1 27vidhar.mgmt IN A 10.141.1.1
28switch01.mgmt IN A 10.141.1.2 28switch01.mgmt IN A 10.141.1.2
29dsl01.mgmt IN A 10.141.1.3 29dsl01.mgmt IN A 10.141.1.3
30gpon01.mgmt IN A 10.10.1.1
30ap01.mgmt IN A 10.141.1.4 31ap01.mgmt IN A 10.141.1.4
diff --git a/hosts/vidhar/network/default.nix b/hosts/vidhar/network/default.nix
index 4a792851..0643f0bb 100644
--- a/hosts/vidhar/network/default.nix
+++ b/hosts/vidhar/network/default.nix
@@ -3,7 +3,7 @@
3with lib; 3with lib;
4 4
5{ 5{
6 imports = [ ./dsl.nix ./bifrost ./dhcp ]; 6 imports = [ ./gpon.nix ./bifrost ./dhcp ];
7 7
8 config = { 8 config = {
9 networking = { 9 networking = {
diff --git a/hosts/vidhar/network/dsl.nix b/hosts/vidhar/network/gpon.nix
index 1e8e9c73..1628159c 100644
--- a/hosts/vidhar/network/dsl.nix
+++ b/hosts/vidhar/network/gpon.nix
@@ -8,7 +8,7 @@ in {
8 options = { 8 options = {
9 networking.pppInterface = mkOption { 9 networking.pppInterface = mkOption {
10 type = types.str; 10 type = types.str;
11 default = "dsl"; 11 default = "gpon";
12 }; 12 };
13 }; 13 };
14 14
@@ -34,7 +34,7 @@ in {
34 plugin pppoe.so 34 plugin pppoe.so
35 name telekom 35 name telekom
36 user 002576900250551137425220#0001@t-online.de 36 user 002576900250551137425220#0001@t-online.de
37 telekom 37 nic-telekom
38 debug 38 debug
39 +ipv6 39 +ipv6
40 ''; 40 '';
@@ -45,6 +45,12 @@ in {
45 serviceConfig = { 45 serviceConfig = {
46 PIDFile = "/run/pppd/${pppInterface}.pid"; 46 PIDFile = "/run/pppd/${pppInterface}.pid";
47 }; 47 };
48 restartTriggers = with config; [
49 environment.etc."ppp/ip-pre-up".source
50 environment.etc."ppp/ip-up".source
51 environment.etc."ppp/ip-down".source
52 # sops.secrets."pap-secrets".sopsFile
53 ];
48 }; 54 };
49 sops.secrets."pap-secrets" = { 55 sops.secrets."pap-secrets" = {
50 format = "binary"; 56 format = "binary";
@@ -70,8 +76,8 @@ in {
70 76
71 tc qdisc add dev "${pppInterface}" handle ffff: ingress 77 tc qdisc add dev "${pppInterface}" handle ffff: ingress
72 tc filter add dev "${pppInterface}" parent ffff: basic action ctinfo dscp 0x0000003f 0x00000040 action mirred egress redirect dev "ifb4${pppInterface}" 78 tc filter add dev "${pppInterface}" parent ffff: basic action ctinfo dscp 0x0000003f 0x00000040 action mirred egress redirect dev "ifb4${pppInterface}"
73 tc qdisc replace dev "ifb4${pppInterface}" root cake memlimit 64Mb pppoe-ptm diffserv4 bandwidth 93mbit 79 tc qdisc replace dev "ifb4${pppInterface}" root cake memlimit 128Mb overhead 35 mpu 74 regional diffserv4 bandwidth 285mbit
74 tc qdisc replace dev "${pppInterface}" root cake memlimit 64Mb pppoe-ptm nat diffserv4 wash bandwidth 35mbit 80 tc qdisc replace dev "${pppInterface}" root cake memlimit 128Mb overhead 35 mpu 74 regional nat diffserv4 wash bandwidth 143mbit
75 ''; 81 '';
76 }; 82 };
77 in "${app}/bin/${app.meta.mainProgram}"; 83 in "${app}/bin/${app.meta.mainProgram}";
diff --git a/hosts/vidhar/network/ruleset.nft b/hosts/vidhar/network/ruleset.nft
index 6eb97f85..9f519302 100644
--- a/hosts/vidhar/network/ruleset.nft
+++ b/hosts/vidhar/network/ruleset.nft
@@ -4,15 +4,15 @@ table arp filter {
4 limit lim_arp_local { 4 limit lim_arp_local {
5 rate over 50 mbytes/second burst 50 mbytes 5 rate over 50 mbytes/second burst 50 mbytes
6 } 6 }
7 limit lim_arp_dsl { 7 limit lim_arp_gpon {
8 rate over 1400 kbytes/second burst 1400 kbytes 8 rate over 7500 kbytes/second burst 7500 kbytes
9 } 9 }
10 10
11 counter arp-rx {} 11 counter arp-rx {}
12 counter arp-tx {} 12 counter arp-tx {}
13 13
14 counter arp-ratelimit-dsl-rx {} 14 counter arp-ratelimit-gpon-rx {}
15 counter arp-ratelimit-dsl-tx {} 15 counter arp-ratelimit-gpon-tx {}
16 16
17 counter arp-ratelimit-local-rx {} 17 counter arp-ratelimit-local-rx {}
18 counter arp-ratelimit-local-tx {} 18 counter arp-ratelimit-local-tx {}
@@ -21,8 +21,8 @@ table arp filter {
21 type filter hook input priority filter 21 type filter hook input priority filter
22 policy accept 22 policy accept
23 23
24 iifname != dsl limit name lim_arp_local counter name arp-ratelimit-local-rx drop 24 iifname != gpon limit name lim_arp_local counter name arp-ratelimit-local-rx drop
25 iifname dsl limit name lim_arp_dsl counter name arp-ratelimit-dsl-rx drop 25 iifname gpon limit name lim_arp_gpon counter name arp-ratelimit-gpon-rx drop
26 26
27 counter name arp-rx 27 counter name arp-rx
28 } 28 }
@@ -31,8 +31,8 @@ table arp filter {
31 type filter hook output priority filter 31 type filter hook output priority filter
32 policy accept 32 policy accept
33 33
34 oifname != dsl limit name lim_arp_local counter name arp-ratelimit-local-tx drop 34 oifname != gpon limit name lim_arp_local counter name arp-ratelimit-local-tx drop
35 oifname dsl limit name lim_arp_dsl counter name arp-ratelimit-dsl-tx drop 35 oifname gpon limit name lim_arp_gpon counter name arp-ratelimit-gpon-tx drop
36 36
37 counter name arp-tx 37 counter name arp-tx
38 } 38 }
@@ -46,11 +46,11 @@ table inet filter {
46 limit lim_icmp_local { 46 limit lim_icmp_local {
47 rate over 50 mbytes/second burst 50 mbytes 47 rate over 50 mbytes/second burst 50 mbytes
48 } 48 }
49 limit lim_icmp_dsl { 49 limit lim_icmp_gpon {
50 rate over 1400 kbytes/second burst 1400 kbytes 50 rate over 7500 kbytes/second burst 7500 kbytes
51 } 51 }
52 52
53 counter icmp-ratelimit-dsl-fw {} 53 counter icmp-ratelimit-gpon-fw {}
54 counter icmp-ratelimit-local-fw {} 54 counter icmp-ratelimit-local-fw {}
55 55
56 counter icmp-fw {} 56 counter icmp-fw {}
@@ -58,7 +58,7 @@ table inet filter {
58 counter invalid-fw {} 58 counter invalid-fw {}
59 counter fw-lo {} 59 counter fw-lo {}
60 counter fw-lan {} 60 counter fw-lan {}
61 counter fw-dsl {} 61 counter fw-gpon {}
62 62
63 counter fw-cups {} 63 counter fw-cups {}
64 64
@@ -73,7 +73,7 @@ table inet filter {
73 counter invalid-local4-rx {} 73 counter invalid-local4-rx {}
74 counter invalid-local6-rx {} 74 counter invalid-local6-rx {}
75 75
76 counter icmp-ratelimit-dsl-rx {} 76 counter icmp-ratelimit-gpon-rx {}
77 counter icmp-ratelimit-local-rx {} 77 counter icmp-ratelimit-local-rx {}
78 counter icmp-rx {} 78 counter icmp-rx {}
79 79
@@ -101,7 +101,7 @@ table inet filter {
101 101
102 counter tx-lo {} 102 counter tx-lo {}
103 103
104 counter icmp-ratelimit-dsl-tx {} 104 counter icmp-ratelimit-gpon-tx {}
105 counter icmp-ratelimit-local-tx {} 105 counter icmp-ratelimit-local-tx {}
106 counter icmp-tx {} 106 counter icmp-tx {}
107 107
@@ -123,10 +123,10 @@ table inet filter {
123 123
124 124
125 chain forward_icmp_accept { 125 chain forward_icmp_accept {
126 oifname { dsl, bifrost } limit name lim_icmp_dsl counter name icmp-ratelimit-dsl-fw drop 126 oifname { gpon, bifrost } limit name lim_icmp_gpon counter name icmp-ratelimit-gpon-fw drop
127 iifname { dsl, bifrost } limit name lim_icmp_dsl counter name icmp-ratelimit-dsl-fw drop 127 iifname { gpon, bifrost } limit name lim_icmp_gpon counter name icmp-ratelimit-gpon-fw drop
128 oifname != { dsl, bifrost } limit name lim_icmp_local counter name icmp-ratelimit-local-fw drop 128 oifname != { gpon, bifrost } limit name lim_icmp_local counter name icmp-ratelimit-local-fw drop
129 iifname != { dsl, bifrost } limit name lim_icmp_local counter name icmp-ratelimit-local-fw drop 129 iifname != { gpon, bifrost } limit name lim_icmp_local counter name icmp-ratelimit-local-fw drop
130 counter name icmp-fw accept 130 counter name icmp-fw accept
131 } 131 }
132 chain forward { 132 chain forward {
@@ -139,10 +139,10 @@ table inet filter {
139 139
140 iifname lo counter name fw-lo accept 140 iifname lo counter name fw-lo accept
141 141
142 oifname { lan, dsl, bifrost } meta l4proto $icmp_protos jump forward_icmp_accept 142 oifname { lan, gpon, bifrost } meta l4proto $icmp_protos jump forward_icmp_accept
143 iifname lan oifname { dsl, bifrost } counter name fw-lan accept 143 iifname lan oifname { gpon, bifrost } counter name fw-lan accept
144 144
145 iifname dsl oifname lan ct state { established, related } counter name fw-dsl accept 145 iifname gpon oifname lan ct state { established, related } counter name fw-gpon accept
146 146
147 147
148 limit name lim_reject log level debug prefix "drop forward: " counter name reject-ratelimit-fw drop 148 limit name lim_reject log level debug prefix "drop forward: " counter name reject-ratelimit-fw drop
@@ -163,22 +163,22 @@ table inet filter {
163 iif != lo ip daddr 127.0.0.1/8 counter name invalid-local4-rx reject 163 iif != lo ip daddr 127.0.0.1/8 counter name invalid-local4-rx reject
164 iif != lo ip6 daddr ::1/128 counter name invalid-local6-rx reject 164 iif != lo ip6 daddr ::1/128 counter name invalid-local6-rx reject
165 165
166 iifname { bifrost, dsl } meta l4proto $icmp_protos limit name lim_icmp_dsl counter name icmp-ratelimit-dsl-rx drop 166 iifname { bifrost, gpon } meta l4proto $icmp_protos limit name lim_icmp_gpon counter name icmp-ratelimit-gpon-rx drop
167 iifname != { bifrost, dsl } meta l4proto $icmp_protos limit name lim_icmp_local counter name icmp-ratelimit-local-rx drop 167 iifname != { bifrost, gpon } meta l4proto $icmp_protos limit name lim_icmp_local counter name icmp-ratelimit-local-rx drop
168 meta l4proto $icmp_protos counter name icmp-rx accept 168 meta l4proto $icmp_protos counter name icmp-rx accept
169 169
170 iifname { lan, mgmt, dsl, yggdrasil, bifrost } tcp dport 22 counter name ssh-rx accept 170 iifname { lan, mgmt, gpon, yggdrasil, bifrost } tcp dport 22 counter name ssh-rx accept
171 iifname { lan, mgmt, dsl, yggdrasil, bifrost } udp dport 60000-61000 counter name mosh-rx accept 171 iifname { lan, mgmt, gpon, yggdrasil, bifrost } udp dport 60000-61000 counter name mosh-rx accept
172 172
173 iifname { lan, mgmt, wifibh, yggdrasil } meta l4proto { tcp, udp } th dport 53 counter name dns-rx accept 173 iifname { lan, mgmt, wifibh, yggdrasil } meta l4proto { tcp, udp } th dport 53 counter name dns-rx accept
174 174
175 iifname { lan, yggdrasil } tcp dport 2049 counter name nfs-rx accept 175 iifname { lan, yggdrasil } tcp dport 2049 counter name nfs-rx accept
176 176
177 iifname { lan, mgmt, dsl } meta protocol ip udp dport 51820 counter name wg-rx accept 177 iifname { lan, mgmt, gpon } meta protocol ip udp dport 51820 counter name wg-rx accept
178 iifname { lan, mgmt, dsl } meta protocol ip6 udp dport 51821 counter name wg-rx accept 178 iifname { lan, mgmt, gpon } meta protocol ip6 udp dport 51821 counter name wg-rx accept
179 iifname "yggdrasil-wg-*" meta l4proto gre counter name yggdrasil-gre-rx accept 179 iifname "yggdrasil-wg-*" meta l4proto gre counter name yggdrasil-gre-rx accept
180 180
181 iifname dsl meta protocol ip6 udp dport 546 udp sport 547 counter name ipv6-pd-rx accept 181 iifname gpon meta protocol ip6 udp dport 546 udp sport 547 counter name ipv6-pd-rx accept
182 182
183 iifname mgmt udp dport 123 counter name ntp-rx accept 183 iifname mgmt udp dport 123 counter name ntp-rx accept
184 184
@@ -209,8 +209,8 @@ table inet filter {
209 209
210 oifname lo counter name tx-lo accept 210 oifname lo counter name tx-lo accept
211 211
212 oifname { bifrost, dsl } meta l4proto $icmp_protos limit name lim_icmp_dsl counter name icmp-ratelimit-dsl-tx drop 212 oifname { bifrost, gpon } meta l4proto $icmp_protos limit name lim_icmp_gpon counter name icmp-ratelimit-gpon-tx drop
213 oifname != { bifrost, dsl } meta l4proto $icmp_protos limit name lim_icmp_local counter name icmp-ratelimit-local-tx drop 213 oifname != { bifrost, gpon } meta l4proto $icmp_protos limit name lim_icmp_local counter name icmp-ratelimit-local-tx drop
214 meta l4proto $icmp_protos counter name icmp-tx accept 214 meta l4proto $icmp_protos counter name icmp-tx accept
215 215
216 216
@@ -246,7 +246,7 @@ table inet filter {
246} 246}
247 247
248table inet nat { 248table inet nat {
249 counter dsl-nat {} 249 counter gpon-nat {}
250 # counter container-nat {} 250 # counter container-nat {}
251 251
252 chain postrouting { 252 chain postrouting {
@@ -254,20 +254,20 @@ table inet nat {
254 policy accept 254 policy accept
255 255
256 256
257 meta nfproto ipv4 oifname dsl counter name dsl-nat masquerade 257 meta nfproto ipv4 oifname gpon counter name gpon-nat masquerade
258 # iifname ve-* oifname dsl counter name container-nat masquerade 258 # iifname ve-* oifname gpon counter name container-nat masquerade
259 } 259 }
260} 260}
261 261
262table inet mss_clamp { 262table inet mss_clamp {
263 counter dsl-mss-clamp {} 263 counter gpon-mss-clamp {}
264 264
265 chain postrouting { 265 chain postrouting {
266 type filter hook postrouting priority mangle 266 type filter hook postrouting priority mangle
267 policy accept 267 policy accept
268 268
269 269
270 oifname dsl tcp flags & (syn|rst) == syn counter name dsl-mss-clamp tcp option maxseg size set rt mtu 270 oifname gpon tcp flags & (syn|rst) == syn counter name gpon-mss-clamp tcp option maxseg size set rt mtu
271 } 271 }
272} 272}
273 273
@@ -402,7 +402,7 @@ table inet dscpclassify {
402 chain postrouting { 402 chain postrouting {
403 type filter hook postrouting priority filter + 1; policy accept 403 type filter hook postrouting priority filter + 1; policy accept
404 404
405 oifname != dsl return 405 oifname != gpon return
406 406
407 ip dscp cs0 goto ct_set_cs0 407 ip dscp cs0 goto ct_set_cs0
408 ip dscp lephb goto ct_set_lephb 408 ip dscp lephb goto ct_set_lephb
diff --git a/hosts/vidhar/prometheus/default.nix b/hosts/vidhar/prometheus/default.nix
index 1e649824..3e938933 100644
--- a/hosts/vidhar/prometheus/default.nix
+++ b/hosts/vidhar/prometheus/default.nix
@@ -63,7 +63,7 @@ in {
63 systemd = { 63 systemd = {
64 enable = true; 64 enable = true;
65 extraFlags = [ 65 extraFlags = [
66 "--systemd.collector.unit-include=(dhcpcd-dsl|pppd-telekom|corerad|ndppd)\.service" 66 "--systemd.collector.unit-include=(dhcpcd-.*|pppd-telekom|corerad|ndppd)\.service"
67 "--systemd.collector.enable-restart-count" 67 "--systemd.collector.enable-restart-count"
68 "--systemd.collector.enable-ip-accounting" 68 "--systemd.collector.enable-ip-accounting"
69 ]; 69 ];
@@ -144,17 +144,6 @@ in {
144 ]; 144 ];
145 scrape_interval = "15s"; 145 scrape_interval = "15s";
146 } 146 }
147 { job_name = "zte";
148 static_configs = [
149 { targets = ["localhost:9900"]; }
150 ];
151 relabel_configs = [
152 { replacement = "dsl01";
153 target_label = "instance";
154 }
155 ];
156 scrape_interval = "15s";
157 }
158 { job_name = "unbound"; 147 { job_name = "unbound";
159 static_configs = [ 148 static_configs = [
160 { targets = ["localhost:${toString config.services.prometheus.exporters.unbound.port}"]; } 149 { targets = ["localhost:${toString config.services.prometheus.exporters.unbound.port}"]; }
@@ -274,6 +263,9 @@ in {
274 { record = "systemd_unit_runtime_seconds:resets_per_week"; 263 { record = "systemd_unit_runtime_seconds:resets_per_week";
275 expr = "resets(systemd_unit_runtime_seconds[1w])"; 264 expr = "resets(systemd_unit_runtime_seconds[1w])";
276 } 265 }
266 { record = "systemd_unit_runtime_seconds:avg_resets_per_day";
267 expr = "avg_over_time(systemd_unit_runtime_seconds:resets_per_day[1w])";
268 }
277 ]; 269 ];
278 } 270 }
279 { name = "apcupsd-transfers"; 271 { name = "apcupsd-transfers";
@@ -290,6 +282,9 @@ in {
290 { record = "apcupsd_last_transfer_on_battery_counter_seconds:resets_per_week"; 282 { record = "apcupsd_last_transfer_on_battery_counter_seconds:resets_per_week";
291 expr = "resets(apcupsd_last_transfer_on_battery_counter_seconds[1w])"; 283 expr = "resets(apcupsd_last_transfer_on_battery_counter_seconds[1w])";
292 } 284 }
285 { record = "apcupsd_last_transfer_on_battery_counter_seconds:avg_resets_per_day";
286 expr = "avg_over_time(apcupsd_last_transfer_on_battery_counter_seconds:resets_per_day[1w])";
287 }
293 ]; 288 ];
294 } 289 }
295 ]; 290 ];
@@ -315,47 +310,6 @@ in {
315 }; 310 };
316 }; 311 };
317 312
318 systemd.services."prometheus-zte-exporter@dsl01.mgmt.yggdrasil" = {
319 wantedBy = [ "multi-user.target" ];
320 after = [ "network.target" ];
321 serviceConfig = {
322 Restart = "always";
323 PrivateTmp = true;
324 WorkingDirectory = "/tmp";
325 DynamicUser = true;
326 CapabilityBoundingSet = [""];
327 DeviceAllow = [""];
328 LockPersonality = true;
329 MemoryDenyWriteExecute = true;
330 NoNewPrivileges = true;
331 PrivateDevices = true;
332 ProtectClock = true;
333 ProtectControlGroups = true;
334 ProtectHome = true;
335 ProtectHostname = true;
336 ProtectKernelLogs = true;
337 ProtectKernelModules = true;
338 ProtectKernelTunables = true;
339 ProtectSystem = "strict";
340 RemoveIPC = true;
341 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
342 RestrictNamespaces = true;
343 RestrictRealtime = true;
344 RestrictSUIDSGID = true;
345 SystemCallArchitectures = "native";
346 UMask = "0077";
347
348 Type = "simple";
349 ExecStart = "${pkgs.zte-prometheus-exporter}/bin/zte-prometheus-exporter";
350 Environment = "ZTE_BASEURL=http://%I ZTE_HOSTNAME=localhost ZTE_PORT=9900";
351 EnvironmentFile = config.sops.secrets."zte_dsl01.mgmt.yggdrasil".path;
352 };
353 };
354 sops.secrets."zte_dsl01.mgmt.yggdrasil" = {
355 format = "binary";
356 sopsFile = ./zte_dsl01.mgmt.yggdrasil;
357 };
358
359 systemd.services."prometheus-nftables-exporter" = { 313 systemd.services."prometheus-nftables-exporter" = {
360 wantedBy = [ "multi-user.target" ]; 314 wantedBy = [ "multi-user.target" ];
361 after = [ "network.target" ]; 315 after = [ "network.target" ];
diff --git a/hosts/vidhar/prometheus/zte_dsl01.mgmt.yggdrasil b/hosts/vidhar/prometheus/zte_dsl01.mgmt.yggdrasil
deleted file mode 100644
index 1c9c1fe0..00000000
--- a/hosts/vidhar/prometheus/zte_dsl01.mgmt.yggdrasil
+++ /dev/null
@@ -1,26 +0,0 @@
1{
2 "data": "ENC[AES256_GCM,data:nAsn7dhfDr0+V1cJjpqWn/kJQt2zGjlfQKi3n5speroJkL3IvMG/9fsTaXJQZSi2gPlrN8GbxKQ=,iv:9g0V3xRBC+sa/JPP2bUZMfg//VuKT5qI7ua9iU4QRCg=,tag:fzwih9OHUBLmx8dxL4BjGg==,type:str]",
3 "sops": {
4 "kms": null,
5 "gcp_kms": null,
6 "azure_kv": null,
7 "hc_vault": null,
8 "age": [
9 {
10 "recipient": "age1qffdqvy9arld9zd5a5cylt0n98xhcns5shxhrhwjq5g4qa844ejselaa4l",
11 "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIaEE3bUFBY0xKSDUrVnc2\nbFpjSkNOSm56amJTNjdXcTljdDNRREhITm1NCjZrOUEwNFpxN2FmTVV5T2xCbENk\nMEFmVzlPZ29CTlJ4dVNCRUsyRFFseXcKLS0tIEhscVZ4VUVsaG9OUnBIRFE4WXA2\ncGFnbWpNMlNIQzFLc1Ryc1Z3NUl1bVUKi9zYBlF2vslGKu4GP368ApbvuxjZnQpF\nuOujXSNoEps21wY6xUENm+CbYbgaJjSgmb5c1IjAmnubVI4JVY9OyQ==\n-----END AGE ENCRYPTED FILE-----\n"
12 }
13 ],
14 "lastmodified": "2021-12-31T15:00:33Z",
15 "mac": "ENC[AES256_GCM,data:sw2NVXHLibbuOChgScLhSTjGZBjSoHpzIuRqfCW0eL3DwhL5CekG6T/oYu06KjNmxVjxwb3OmqECSU0TUvPn9ySOWwMSoBfyJpDoTHnZ+YOjOH351IOAMBNcBDJse7aLGRWW5YXKLDfmp8Dhg2hlMhCmkVwAquQjPhfmAdJfj64=,iv:wgM/BlRU2XJSGj7KvAo1WRamecffUDnFvv2+4twtsQY=,tag:0mXblJtTGMTvxndedws94A==,type:str]",
16 "pgp": [
17 {
18 "created_at": "2023-01-30T10:58:49Z",
19 "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DXxoViZlp6dISAQdAcwl1Blp3J5wgpRJKbYI1G1yEZrRYeYuoDtYUh3ToMAQw\nd92/bIJJR5Ml91eDym9uBN0fFRRy72r6FOx4qZT7S4DhmuA84qCbASjF8bKSclc0\n0l4BBXvDS5Dz1Q7iYc+LxZjHASV1v73A+MaeCFvG/pjmHzF0z0EzBiAJD4ZWGcP0\nX2dDbjl+n9VFrvmeLRxQNh4XZW43iTXdRjwHDgm16zhd9X6VOVhr5UkC4Nyjq2Ar\n=4ZEa\n-----END PGP MESSAGE-----\n",
20 "fp": "30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51"
21 }
22 ],
23 "unencrypted_suffix": "_unencrypted",
24 "version": "3.7.1"
25 }
26} \ No newline at end of file
diff --git a/modules/postfwd.nix b/modules/postfwd.nix
index 3edff44d..93729978 100644
--- a/modules/postfwd.nix
+++ b/modules/postfwd.nix
@@ -9,6 +9,10 @@ in {
9 services.postfwd = with types; { 9 services.postfwd = with types; {
10 enable = mkEnableOption "postfwd3 - postfix firewall daemon"; 10 enable = mkEnableOption "postfwd3 - postfix firewall daemon";
11 11
12 cache = mkEnableOption "postfwd3 cache" // {
13 default = true;
14 };
15
12 rules = mkOption { 16 rules = mkOption {
13 type = lines; 17 type = lines;
14 default = ""; 18 default = "";
@@ -26,7 +30,7 @@ in {
26 serviceConfig = { 30 serviceConfig = {
27 Type = "forking"; 31 Type = "forking";
28 32
29 ExecStart = "${pkgs.postfwd}/bin/postfwd3 ${escapeShellArgs [ 33 ExecStart = "${pkgs.postfwd}/bin/postfwd3 ${escapeShellArgs ([
30 "-vv" 34 "-vv"
31 "--daemon" "--user" "postfwd" "--group" "postfwd" 35 "--daemon" "--user" "postfwd" "--group" "postfwd"
32 "--pidfile" "/run/postfwd3/postfwd3.pid" 36 "--pidfile" "/run/postfwd3/postfwd3.pid"
@@ -35,11 +39,14 @@ in {
35 "--save_rates" "/var/lib/postfwd/rates" 39 "--save_rates" "/var/lib/postfwd/rates"
36 "--save_groups" "/var/lib/postfwd/groups" 40 "--save_groups" "/var/lib/postfwd/groups"
37 "--summary" "3600" 41 "--summary" "3600"
42 "--file" (pkgs.writeText "postfwd3-rules" cfg.rules)
43 ] ++ lib.optionals cfg.cache [
38 "--cache" "600" 44 "--cache" "600"
39 "--cache_proto" "unix" 45 "--cache_proto" "unix"
40 "--cache_port" "/run/postfwd3/cache.sock" 46 "--cache_port" "/run/postfwd3/cache.sock"
41 "--file" (pkgs.writeText "postfwd3-rules" cfg.rules) 47 ] ++ lib.optionals (!cfg.cache) [
42 ]}"; 48 "--cache" "0"
49 ])}";
43 PIDFile = "/run/postfwd3/postfwd3.pid"; 50 PIDFile = "/run/postfwd3/postfwd3.pid";
44 51
45 Restart = "always"; 52 Restart = "always";
@@ -79,5 +86,19 @@ in {
79 IPAddressDeny = "any"; 86 IPAddressDeny = "any";
80 }; 87 };
81 }; 88 };
89
90 environment.systemPackages = [
91 (pkgs.postfwd.overrideAttrs (oldAttrs: {
92 nativeBuildInputs = (oldAttrs.nativeBuildInputs or []) ++ [ pkgs.makeWrapper pkgs.coreutils ];
93
94 postInstall = ''
95 ${oldAttrs.postInstall or ""}
96
97 wrapProgram $out/bin/postfwd3 \
98 --add-flags "--proto unix --port /run/postfwd3/postfwd3.sock"
99 ln -s postfwd3 $out/bin/postfwd
100 '';
101 }))
102 ];
82 }; 103 };
83} 104}
diff --git a/overlays/worktime/worktime/__main__.py b/overlays/worktime/worktime/__main__.py
index 0df226fa..21316182 100755
--- a/overlays/worktime/worktime/__main__.py
+++ b/overlays/worktime/worktime/__main__.py
@@ -2,9 +2,9 @@ import requests
2from requests.exceptions import HTTPError 2from requests.exceptions import HTTPError
3from requests.auth import HTTPBasicAuth 3from requests.auth import HTTPBasicAuth
4from datetime import * 4from datetime import *
5from xdg import (BaseDirectory) 5from xdg import BaseDirectory
6import toml 6import toml
7from uritools import uricompose 7from uritools import (uricompose)
8 8
9from dateutil.easter import * 9from dateutil.easter import *
10from dateutil.tz import * 10from dateutil.tz import *
@@ -80,7 +80,7 @@ class TogglAPI(object):
80 max_time=10, 80 max_time=10,
81 ) 81 )
82 def _raw_query(self, url, method): 82 def _raw_query(self, url, method):
83 headers = {'content-type': 'application/json'} 83 headers = {'content-type': 'application/json', 'accept': 'application/json'}
84 response = None 84 response = None
85 85
86 if method == 'GET': 86 if method == 'GET':
@@ -127,9 +127,9 @@ class TogglAPI(object):
127 pass 127 pass
128 128
129 entries = list() 129 entries = list()
130 params = { 'since': (req_start - timedelta(days=1)).astimezone(timezone.utc).isoformat(), 130 params = { 'since': (req_start - timedelta(days=1)).date().isoformat(),
131 'until': (req_end + timedelta(days=1)).astimezone(timezone.utc).isoformat(), 131 'until': (req_end + timedelta(days=1)).date().isoformat(),
132 'rounding': rounding, 132 'rounding': 'yes' if rounding else 'no',
133 'billable': 'yes' 133 'billable': 'yes'
134 } 134 }
135 if client_ids is not None: 135 if client_ids is not None: