{ lib, pkgs, ... }: { name = "reaction"; nodes.server = _: { services.reaction = { enable = true; stopForFirewall = false; # example.jsonnet or example.yml can be copied and modified from ${pkgs.reaction}/share/examples settingsFiles = [ "${pkgs.reaction}/share/examples/example.jsonnet" ]; runAsRoot = false; }; services.openssh.enable = true; # If not running as root you need to give the reaction user and service the proper permissions # allows reading journal logs of processess users.users.reaction.extraGroups = [ "systemd-journal" ]; # allows modifying ip firewall rules systemd.services.reaction.unitConfig.ConditionCapability = "CAP_NET_ADMIN"; systemd.services.reaction.serviceConfig = { CapabilityBoundingSet = [ "CAP_NET_ADMIN" ]; AmbientCapabilities = [ "CAP_NET_ADMIN" ]; }; users.users.nixos.isNormalUser = true; # neeeded to establish a ssh connection, by default root login is succeeding without any password }; nodes.client = _: { environment.systemPackages = [ pkgs.sshpass pkgs.libressl.nc ]; }; testScript = { nodes, ... }: # py '' start_all() # Wait for everything to be ready. server.wait_for_unit("multi-user.target") server.wait_for_unit("reaction") server.wait_for_unit("sshd") client_addr = "${(lib.head nodes.client.networking.interfaces.eth1.ipv4.addresses).address}" server_addr = "${(lib.head nodes.server.networking.interfaces.eth1.ipv4.addresses).address}" # Verify there is not ban and the port is reachable from the client. server.succeed(f"reaction show | grep -q {client_addr} || test $? -eq 1") client.succeed(f"nc -w3 -z {server_addr} 22") # Cause authentication failure log entries. for _ in range(2): client.fail(f""" sshpass -p 'wrongpassword' \ ssh -o StrictHostKeyChecking=no \ -o User=nixos \ -o ServerAliveInterval=1 \ -o ServerAliveCountMax=2 \ {server_addr} """) # Verify there is a ban and the port is unreachable from the client. server.sleep(2) output = server.succeed("reaction show") print(output) assert client_addr in output, f"client did not get banned, {client_addr}" client.fail(f"nc -w3 -z {server_addr} 22") # Check that unbanning works output = server.succeed("reaction flush") print(output) client.succeed(f"nc -w3 -z {server_addr} 22") ''; # Debug interactively with: # - nix run .#nixosTests.reaction.driverInteractive -L # - run_tests() interactive.sshBackdoor.enable = true; interactive.nodes.server = { config, ... }: { # not needed, only for manual interactive debugging virtualisation.memorySize = 4096; virtualisation.graphics = false; environment.systemPackages = with pkgs; [ btop sysz sshpass libressl.nc ]; }; meta.maintainers = with lib.maintainers; [ ppom ] ++ lib.teams.ngi.members; }