summaryrefslogtreecommitdiffstats
path: root/old/modules/lass/iptables/config.nix
blob: be521feb96ef718c3b19100cba4ecab2f7c23db8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
{ cfg, lib, pkgs, ... }:

let
  inherit (pkgs) writeScript writeText;
  inherit (lib) concatMapStringsSep concatStringsSep attrNames unique fold any attrValues catAttrs filter flatten length hasAttr;

#===== new api v4

  #buildTable :: iptablesAttrSet` -> str
  #todo: differentiate by iptables-version
  buildTables = iptv: ts:
    let
      declareChain = t: cn:
        #TODO: find out what to do whit these count numbers
        ":${cn} ${t."${cn}".policy} [0:0]";

      buildChain = tn: cn:
      #"${concatStringsSep " " ((attrNames t."${cn}") ++ [cn])}";

      #TODO: sort by precedence
      #TODO: double check should be unneccessary, refactor!
        if (hasAttr "rules" ts."${tn}"."${cn}") then
          if (ts."${tn}"."${cn}".rules == null) then
            ""
          else
            concatMapStringsSep "\n" (rule: "\n-A ${cn} ${rule}") ([]
              ++ map buildRule ts."${tn}"."${cn}".rules
            )
        else
          ""
        ;


      buildRule = rule:
        #TODO implement rule validation-test here
        #
        #target:
        #target needs to be an existing chain (in the same table) or ACCEPT, REJECT, DROP, LOG, QUEUE, RETURN

        #predicate:
        #maybe use iptables-test
        #TODO: howto exit with evaluation error by shellscript?
          #apperantly not possible from nix because evalatution wouldn't be deterministic.
        "${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)
      );

#=====

  rules4 = iptables-version:
    let
      #TODO: find out good defaults.
      tables-defaults = {
        nat.PREROUTING.policy = "ACCEPT";
        nat.INPUT.policy = "ACCEPT";
        nat.OUTPUT.policy = "ACCEPT";
        nat.POSTROUTING.policy = "ACCEPT";
        filter.INPUT.policy = "ACCEPT";
        filter.FORWARD.policy = "ACCEPT";
        filter.OUTPUT.policy = "ACCEPT";

        #if someone specifies any other rules on this chain, the default rules get lost.
        #is this wanted beahiviour or a bug?
        #TODO: implement abstraction of rules
        filter.INPUT.rules = [
          { predicate = "-m conntrack --ctstate RELATED,ESTABLISHED"; target = "ACCEPT"; }
        ];
      };
      tables = tables-defaults // cfg.tables;

    in
      writeText "lass-iptables-rules${toString iptables-version}" ''
        ${buildTables iptables-version tables}
      '';

  startScript = writeScript "lass-iptables_start" ''
    #! /bin/sh
    set -euf
    iptables-restore < ${rules4 4}
    ip6tables-restore < ${rules4 6}
  '';
in

{
  networking.firewall.enable = false;

  systemd.services.lass-iptables = {
    description = "lass-iptables";
    wantedBy = [ "network-pre.target" ];
    before = [ "network-pre.target" ];
    after = [ "systemd-modules-load.service" ];

    path = with pkgs; [
      iptables
    ];

    restartIfChanged = true;

    serviceConfig = {
      Type = "simple";
      RemainAfterExit = true;
      Restart = "always";
      ExecStart = "@${startScript} lass-iptables_start";
    };
  };
}