stockholm/krebs/3modules/iptables.nix

195 lines
5.6 KiB
Nix
Raw Normal View History

2016-06-28 15:24:36 +00:00
{ config, lib, pkgs, ... }:
2015-07-16 13:48:56 +00:00
with import <stockholm/lib>;
2015-07-16 13:48:56 +00:00
let
2016-06-13 00:04:22 +00:00
inherit (pkgs) writeText;
2015-07-18 11:29:07 +00:00
2015-10-01 20:10:21 +00:00
inherit (builtins)
elem
;
cfg = config.krebs.iptables;
2015-07-16 13:48:56 +00:00
out = {
2015-10-01 20:10:21 +00:00
options.krebs.iptables = api;
2015-07-16 13:48:56 +00:00
config = mkIf cfg.enable imp;
};
api = {
enable = mkEnableOption "iptables";
#tables.filter.INPUT = {
# policy = "DROP";
# rules = [
# { predicate = "-i retiolum"; target = "ACCEPT"; priority = -10; }
# ];
#};
#new api
tables = mkOption {
type = with types; attrsOf (attrsOf (submodule ({
options = {
2016-11-28 12:06:00 +00:00
#TODO: find out good defaults.
2015-07-16 13:48:56 +00:00
policy = mkOption {
type = str;
2016-11-28 12:06:00 +00:00
default = "ACCEPT";
2015-07-16 13:48:56 +00:00
};
rules = mkOption {
type = nullOr (listOf (submodule ({
options = {
predicate = mkOption {
type = str;
};
target = mkOption {
type = str;
};
precedence = mkOption {
type = int;
default = 0;
};
v4 = mkOption {
type = bool;
default = true;
};
v6 = mkOption {
type = bool;
default = true;
};
2015-07-16 13:48:56 +00:00
};
})));
default = null;
};
};
})));
2018-01-02 17:24:40 +00:00
default = {
filter.INPUT.policy = "ACCEPT";
filter.FORWARD.policy = "ACCEPT";
filter.OUTPUT.policy = "ACCEPT";
nat.PREROUTING.policy = "ACCEPT";
nat.INPUT.policy = "ACCEPT";
nat.OUTPUT.policy = "ACCEPT";
nat.POSTROUTING.policy = "ACCEPT";
};
2015-07-16 13:48:56 +00:00
};
};
imp = mkMerge ([{
2015-07-16 13:48:56 +00:00
networking.firewall.enable = false;
2015-10-01 20:10:21 +00:00
systemd.services.krebs-iptables = {
wantedBy = [ "sysinit.target" ];
wants = [ "network-pre.target" ];
2015-07-16 13:48:56 +00:00
before = [ "network-pre.target" ];
after = [ "systemd-modules-load.service" ];
path = with pkgs; [
iptables
];
restartIfChanged = true;
serviceConfig = {
Type = "simple";
RemainAfterExit = true;
Restart = "always";
ExecStart = startScript;
2015-07-16 13:48:56 +00:00
};
unitConfig.DefaultDependencies = false;
2015-07-16 13:48:56 +00:00
};
}] ++ compat);
compat = [
({
krebs.iptables.tables.filter.INPUT.rules = map
(port: { predicate = "-p tcp --dport ${toString port}"; target = "ACCEPT"; })
config.networking.firewall.allowedTCPPorts;
})
({
krebs.iptables.tables.filter.INPUT.rules = map
(port: { predicate = "-p udp --dport ${toString port}"; target = "ACCEPT"; })
config.networking.firewall.allowedUDPPorts;
})
({
krebs.iptables.tables.filter.INPUT.rules = map
(portRange: { predicate = "-p tcp --dport ${toString port.from}:${toString port.to}"; target = "ACCEPT"; })
config.networking.firewall.allowedTCPPortRanges;
})
({
krebs.iptables.tables.filter.INPUT.rules = map
(portRange: { predicate = "-p udp --dport ${toString port.from}:${toString port.to}"; target = "ACCEPT"; })
config.networking.firewall.allowedUDPPortRanges;
})
({
krebs.iptables.tables.filter.INPUT.rules = flatten (mapAttrsToList
(interface: interfaceConfig: [
(map (port: { predicate = "-i ${interface} -p tcp --dport ${toString port}"; target = "ACCEPT"; }) interfaceConfig.allowedTCPPorts)
(map (port: { predicate = "-i ${interface} -p udp --dport ${toString port}"; target = "ACCEPT"; }) interfaceConfig.allowedUDPPorts)
(map (portRange: { predicate = "-i ${interface} -p tcp --dport ${toString port.from}:${toString port.to}"; target = "ACCEPT"; }) interfaceConfig.allowedTCPPortRanges)
(map (portRange: { predicate = "-i ${interface} -p udp --dport ${toString port.from}:${toString port.to}"; target = "ACCEPT"; }) interfaceConfig.allowedUDPPortRanges)
])
config.networking.firewall.interfaces
);
})
];
2015-07-16 13:48:56 +00:00
#buildTable :: iptablesVersion -> iptablesAttrSet` -> str
2015-07-16 13:48:56 +00:00
#todo: differentiate by iptables-version
buildTables = v: ts:
2015-07-16 13:48:56 +00:00
let
2015-07-16 13:48:56 +00:00
declareChain = t: cn:
#TODO: find out what to do whit these count numbers
":${cn} ${t."${cn}".policy} [0:0]";
buildChain = tn: cn:
let
filteredRules = filter (r: r."${v}") ts."${tn}"."${cn}".rules;
sortedRules = sort (a: b: a.precedence > b.precedence) filteredRules;
in
#TODO: double check should be unneccessary, refactor!
2015-10-01 20:10:21 +00:00
if ts.${tn}.${cn}.rules or null != null then
concatMapStringsSep "\n" (rule: "\n-A ${cn} ${rule}") ([]
++ map (buildRule tn cn) sortedRules
)
2015-07-16 13:48:56 +00:00
else
""
;
2015-07-16 13:48:56 +00:00
buildRule = tn: cn: rule:
2015-07-16 13:48:56 +00:00
"${rule.predicate} -j ${rule.target}";
buildTable = tn:
"*${tn}\n" +
concatStringsSep "\n" ([]
++ map (declareChain ts."${tn}") (attrNames ts."${tn}")
) +
#this looks dirty, find a better way to do this (maybe optionalString)
concatStringsSep "" ([]
++ map (buildChain tn) (attrNames ts."${tn}")
) +
"\nCOMMIT";
in
concatStringsSep "\n" ([]
++ map buildTable (attrNames ts)
2015-07-16 13:48:56 +00:00
);
#=====
rules = iptables-version:
2016-11-28 12:06:00 +00:00
pkgs.writeText "krebs-iptables-rules${iptables-version}" ''
${buildTables iptables-version cfg.tables}
'';
2015-07-16 13:48:56 +00:00
2016-06-13 00:04:22 +00:00
startScript = pkgs.writeDash "krebs-iptables_start" ''
2015-07-16 13:48:56 +00:00
set -euf
iptables-restore < ${rules "v4"}
ip6tables-restore < ${rules "v6"}
2015-07-16 13:48:56 +00:00
'';
in
out