summaryrefslogtreecommitdiffstats
path: root/nixos/tests/opensnitch.nix
blob: f1a152cbf60792c4b9a28f5e2e9474be1c261404 (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
{ pkgs, lib, ... }:
let
  # opensnitch ebpf seems to handle non-x86 syscalls incorrectly
  test_ebpf = pkgs.stdenv.hostPlatform.isx86;

  monitorMethods = [
    "proc"
    "ftrace"
    "audit"
  ]
  ++ lib.optional test_ebpf "ebpf";
in
{
  name = "opensnitch";

  meta = with pkgs.lib.maintainers; {
    maintainers = [
      onny
      grimmauld
    ];
  };

  nodes = {
    server = {
      networking.firewall.allowedTCPPorts = [ 80 ];
      services.caddy = {
        enable = true;
        virtualHosts."localhost".extraConfig = ''
          respond "Hello, world!"
        '';
      };
    };
  }
  // (lib.listToAttrs (
    map (
      m:
      lib.nameValuePair "client_blocked_${m}" {
        services.opensnitch = {
          enable = true;
          settings.DefaultAction = "deny";
          settings.ProcMonitorMethod = m;
          settings.LogLevel = 1;
        };
      }
    ) monitorMethods
  ))
  // (lib.listToAttrs (
    map (
      m:
      lib.nameValuePair "client_allowed_${m}" {
        services.opensnitch = {
          enable = true;
          settings.DefaultAction = "deny";
          settings.ProcMonitorMethod = m;
          settings.LogLevel = 1;
          rules = {
            curl = {
              name = "curl";
              enabled = true;
              action = "allow";
              duration = "always";
              operator = {
                type = "list";
                operand = "list";
                list = [
                  {
                    type = "simple";
                    sensitive = false;
                    operand = "process.path";
                    data = "${pkgs.curl}/bin/curl";
                  }
                  # Check that network aliases like "LAN" are properly resolved.
                  {
                    type = "network";
                    sensitive = false;
                    operand = "dest.network";
                    data = "LAN";
                  }
                ];
              };
            };
          };
        };
      }
    ) monitorMethods
  ));

  testScript = ''
    start_all()
    server.wait_for_unit("caddy.service")
    server.wait_for_open_port(80)
  ''
  + (
    lib.concatLines (
      map (m: ''
        client_blocked_${m}.wait_for_unit("opensnitchd.service")
        client_blocked_${m}.fail("curl --connect-timeout 3 http://server")

        client_allowed_${m}.wait_for_unit("opensnitchd.service")
        client_allowed_${m}.succeed("curl --connect-timeout 3 http://server")
      '') monitorMethods
    )
    + lib.optionalString test_ebpf ''
      # make sure the kernel modules were actually properly loaded
      client_blocked_ebpf.succeed(r"journalctl -u opensnitchd --grep '\[eBPF\] module loaded: /nix/store/.*/etc/opensnitchd/opensnitch\.o'")
      client_blocked_ebpf.succeed(r"journalctl -u opensnitchd --grep '\[eBPF\] module loaded: /nix/store/.*/etc/opensnitchd/opensnitch-procs\.o'")
      client_blocked_ebpf.succeed(r"journalctl -u opensnitchd --grep '\[eBPF\] module loaded: /nix/store/.*/etc/opensnitchd/opensnitch-dns\.o'")
      client_allowed_ebpf.succeed(r"journalctl -u opensnitchd --grep '\[eBPF\] module loaded: /nix/store/.*/etc/opensnitchd/opensnitch\.o'")
      client_allowed_ebpf.succeed(r"journalctl -u opensnitchd --grep '\[eBPF\] module loaded: /nix/store/.*/etc/opensnitchd/opensnitch-procs\.o'")
      client_allowed_ebpf.succeed(r"journalctl -u opensnitchd --grep '\[eBPF\] module loaded: /nix/store/.*/etc/opensnitchd/opensnitch-dns\.o'")
    ''
  );
}