feat: add outbound firewall to server & add helix and zellij
This commit is contained in:
parent
d273765b99
commit
7fcf26263a
23 changed files with 769 additions and 145 deletions
|
|
@ -15,6 +15,29 @@ in
|
|||
inherit hostname username;
|
||||
domain = "net.dn";
|
||||
hyprland.enable = false;
|
||||
security = {
|
||||
allowedDomains = [
|
||||
"github.com"
|
||||
"cache.nixos.org"
|
||||
"hyprland.cachix.org"
|
||||
"maps.rspamd.com"
|
||||
"cdn-hub.crowdsec.net"
|
||||
"api.crowdsec.net"
|
||||
];
|
||||
allowedIPs = [
|
||||
"10.0.0.0/24"
|
||||
"127.0.0.1"
|
||||
];
|
||||
allowedIPv6 = [
|
||||
"ff02::/16"
|
||||
"fe80::/10"
|
||||
"::1"
|
||||
];
|
||||
sourceIPs = [
|
||||
"10.0.0.1"
|
||||
"192.168.100.0/24"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
imports = [
|
||||
|
|
@ -25,6 +48,7 @@ in
|
|||
./security
|
||||
./services
|
||||
./sops
|
||||
./options
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
helper,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (config.systemConf) username;
|
||||
inherit (config.systemConf) username security;
|
||||
inherit (lib) concatStringsSep;
|
||||
inherit (helper.nftables) mkElementsStatement;
|
||||
|
||||
ethInterface = "enp0s31f6";
|
||||
sshPorts = [ 30072 ];
|
||||
sshPortsString = builtins.concatStringsSep ", " (builtins.map (p: builtins.toString p) sshPorts);
|
||||
sshPortsString = concatStringsSep ", " (map (p: toString p) sshPorts);
|
||||
|
||||
personal = {
|
||||
inherit (config.networking) domain;
|
||||
|
|
@ -30,7 +33,7 @@ let
|
|||
masterAPIServerPort = 6443;
|
||||
};
|
||||
|
||||
allowedSSHIPs = builtins.concatStringsSep ", " [
|
||||
allowedSSHIPs = concatStringsSep ", " [
|
||||
"122.117.215.55"
|
||||
"192.168.100.1/24"
|
||||
personal.range
|
||||
|
|
@ -189,63 +192,104 @@ in
|
|||
|
||||
nftables = {
|
||||
enable = true;
|
||||
ruleset = ''
|
||||
table inet wg-filter {
|
||||
chain input {
|
||||
type filter hook input priority 0; policy drop;
|
||||
tables = {
|
||||
filter = {
|
||||
family = "inet";
|
||||
content = ''
|
||||
set restrict_source_ips {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
${mkElementsStatement security.sourceIPs}
|
||||
}
|
||||
|
||||
iif lo accept
|
||||
set ${security.rules.setName} {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
${mkElementsStatement security.allowedIPs}
|
||||
}
|
||||
|
||||
meta nftrace set 1
|
||||
meta l4proto { icmp, ipv6-icmp } accept
|
||||
set ${security.rules.setNameV6} {
|
||||
type ipv6_addr
|
||||
flags interval
|
||||
${mkElementsStatement security.allowedIPv6}
|
||||
}
|
||||
|
||||
ct state vmap { invalid : drop, established : accept, related : accept }
|
||||
chain input {
|
||||
type filter hook input priority 0; policy drop;
|
||||
|
||||
udp dport 53 accept
|
||||
tcp dport 53 accept
|
||||
iif lo accept
|
||||
|
||||
tcp dport { ${sshPortsString} } jump ssh-filter
|
||||
meta nftrace set 1
|
||||
meta l4proto { icmp, ipv6-icmp } accept
|
||||
|
||||
iifname { ${ethInterface}, ${personal.interface}, ${kube.interface} } udp dport { ${builtins.toString personal.port}, ${builtins.toString kube.port} } accept
|
||||
iifname ${personal.interface} ip saddr ${personal.ip} jump wg-subnet
|
||||
iifname ${kube.interface} ip saddr ${kube.ip} jump kube-filter
|
||||
ct state vmap { invalid : drop, established : accept, related : accept }
|
||||
|
||||
counter reject
|
||||
}
|
||||
udp dport 53 accept
|
||||
tcp dport 53 accept
|
||||
|
||||
chain ssh-filter {
|
||||
ip saddr { ${allowedSSHIPs} } accept
|
||||
counter reject
|
||||
}
|
||||
tcp dport { ${sshPortsString} } jump ssh-filter
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy drop;
|
||||
iifname { ${ethInterface}, ${personal.interface}, ${kube.interface} } udp dport { ${toString personal.port}, ${toString kube.port} } accept
|
||||
iifname ${personal.interface} ip saddr ${personal.ip} jump wg-subnet
|
||||
iifname ${kube.interface} ip saddr ${kube.ip} jump kube-filter
|
||||
|
||||
meta l4proto { icmp, ipv6-icmp } accept
|
||||
drop
|
||||
}
|
||||
|
||||
iifname ${personal.interface} ip saddr ${personal.ip} jump wg-subnet
|
||||
iifname ${kube.interface} ip saddr ${kube.ip} jump kube-filter
|
||||
chain output {
|
||||
type filter hook output priority 0; policy drop;
|
||||
|
||||
counter
|
||||
}
|
||||
iif lo accept
|
||||
|
||||
chain kube-filter {
|
||||
ip saddr ${kube.ip} ip daddr ${kube.ip} accept
|
||||
counter drop
|
||||
}
|
||||
# Allow DNS qeury
|
||||
udp dport 53 accept
|
||||
tcp dport 53 accept
|
||||
|
||||
chain wg-subnet {
|
||||
ip saddr ${personal.full} accept
|
||||
ip saddr ${personal.restrict} ip daddr ${personal.range} accept
|
||||
counter drop
|
||||
}
|
||||
meta skuid ${toString config.users.users.systemd-timesync.uid} accept
|
||||
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority 100; policy accept;
|
||||
oifname ${ethInterface} masquerade
|
||||
}
|
||||
}
|
||||
'';
|
||||
ct state vmap { invalid : drop, established : accept, related : accept }
|
||||
ip saddr != @restrict_source_ips accept
|
||||
|
||||
ip daddr @${security.rules.setName} accept
|
||||
ip6 daddr @${security.rules.setNameV6} accept
|
||||
|
||||
counter log prefix "OUTPUT-DROP: " flags all drop
|
||||
}
|
||||
|
||||
chain ssh-filter {
|
||||
ip saddr { ${allowedSSHIPs} } accept
|
||||
counter reject
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy drop;
|
||||
|
||||
meta l4proto { icmp, ipv6-icmp } accept
|
||||
|
||||
iifname ${personal.interface} ip saddr ${personal.ip} jump wg-subnet
|
||||
iifname ${kube.interface} ip saddr ${kube.ip} jump kube-filter
|
||||
|
||||
counter
|
||||
}
|
||||
|
||||
chain kube-filter {
|
||||
ip saddr ${kube.ip} ip daddr ${kube.ip} accept
|
||||
counter drop
|
||||
}
|
||||
|
||||
chain wg-subnet {
|
||||
ip saddr ${personal.full} accept
|
||||
ip saddr ${personal.restrict} ip daddr ${personal.range} accept
|
||||
counter drop
|
||||
}
|
||||
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority 100; policy accept;
|
||||
oifname ${ethInterface} masquerade
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
wireguard = {
|
||||
|
|
@ -323,7 +367,11 @@ in
|
|||
webserver-port=8081
|
||||
local-port=5359
|
||||
dnsupdate=yes
|
||||
primary=yes
|
||||
secondary=no
|
||||
allow-dnsupdate-from=10.0.0.0/24
|
||||
allow-axfr-ips=10.0.0.0/24
|
||||
also-notify=10.0.0.148:53
|
||||
'';
|
||||
secretFile = config.sops.secrets.powerdns.path;
|
||||
};
|
||||
|
|
@ -333,6 +381,7 @@ in
|
|||
forwardZones = {
|
||||
"${config.networking.domain}." = "127.0.0.1:5359";
|
||||
"pre7780.dn." = "127.0.0.1:5359";
|
||||
"test.local." = "127.0.0.1:5359";
|
||||
};
|
||||
forwardZonesRecurse = {
|
||||
"." = "8.8.8.8";
|
||||
|
|
@ -342,9 +391,6 @@ in
|
|||
"127.0.0.0/8"
|
||||
"10.0.0.0/24"
|
||||
"192.168.100.0/24"
|
||||
"::1/128"
|
||||
"fc00::/7"
|
||||
"fe80::/10"
|
||||
];
|
||||
yaml-settings = {
|
||||
webservice.webserver = true;
|
||||
|
|
|
|||
5
system/dev/dn-server/options/default.nix
Normal file
5
system/dev/dn-server/options/default.nix
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./network.nix
|
||||
];
|
||||
}
|
||||
91
system/dev/dn-server/options/network.nix
Normal file
91
system/dev/dn-server/options/network.nix
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkOption types concatStringsSep;
|
||||
cfg = config.systemConf.security;
|
||||
in
|
||||
{
|
||||
options.systemConf.security = {
|
||||
allowedDomains = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "Domains that allowed to query dns.";
|
||||
default = [ ];
|
||||
};
|
||||
rules = {
|
||||
setName = mkOption {
|
||||
type = with types; str;
|
||||
default = "allowed_output_ips";
|
||||
readOnly = true;
|
||||
};
|
||||
setNameV6 = mkOption {
|
||||
type = with types; str;
|
||||
default = "allowed_output_ipv6";
|
||||
readOnly = true;
|
||||
};
|
||||
};
|
||||
dnsIPs = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "External DNS server to use";
|
||||
default = [ "8.8.8.8" ];
|
||||
};
|
||||
allowedIPs = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "IPv4 that allowed to request.";
|
||||
default = [ ];
|
||||
};
|
||||
allowedIPv6 = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "IPv6 that allowed to request.";
|
||||
default = [ ];
|
||||
};
|
||||
sourceIPs = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "Source IPs to restrict.";
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
environment.systemPackages = with pkgs; [
|
||||
ipset
|
||||
];
|
||||
|
||||
systemd.timers.fetch-allowed-domains = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnBootSec = 10;
|
||||
OnUnitActiveSec = 60;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.fetch-allowed-domains = {
|
||||
path = with pkgs; [
|
||||
nftables
|
||||
dig.dnsutils
|
||||
];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.writeShellScript "fetch-allowed-domains" ''
|
||||
DOMAINS=(${toString (map (x: ''"${x}"'') cfg.allowedDomains)})
|
||||
SETNAME="inet filter ${cfg.rules.setName}"
|
||||
|
||||
nft flush set $SETNAME
|
||||
nft add element $SETNAME { ${concatStringsSep "," cfg.allowedIPs} }
|
||||
|
||||
for domain in "''${DOMAINS[@]}"; do
|
||||
ips=$(dig +short A $domain | grep -E '^[0-9.]+$')
|
||||
for ip in $ips; do
|
||||
nft add element $SETNAME { $ip }
|
||||
echo "Added $ip for $domain"
|
||||
done
|
||||
done
|
||||
''}";
|
||||
Type = "oneshot";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ in
|
|||
adminAccountFile = config.sops.secrets."oauth/adminEnv".path;
|
||||
};
|
||||
ldap = {
|
||||
filter = "(&(objectClass=inetOrgPerson)(objectClass=mailRoutingObject)(uid=%{user | username}))";
|
||||
filter = "(&(objectClass=inetOrgPerson)(objectClass=inetMailRoutingObject)(uid=%{user | username}))";
|
||||
extraAuthConf = ''
|
||||
auth_username_format = %{user | lower}
|
||||
fields {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue