{ config, lib, pkgs, ... }: let testServiceConfigs = { zpool_ssds = ""; zpool_hdds = ""; }; securityModule = import ../modules/security.nix; sshModule = { config, lib, pkgs, ... }: { imports = [ (import ../services/ssh.nix { inherit config lib pkgs; username = "testuser"; }) ]; }; in pkgs.testers.runNixOSTest { name = "fail2ban-ssh"; nodes = { server = { config, lib, pkgs, ... }: { imports = [ securityModule sshModule ]; # Override for testing - enable password auth services.openssh.settings.PasswordAuthentication = lib.mkForce true; users.users.testuser = { isNormalUser = true; password = "correctpassword"; }; networking.firewall.allowedTCPPorts = [ 22 ]; }; client = { environment.systemPackages = with pkgs; [ sshpass openssh ]; }; }; testScript = '' import time start_all() server.wait_for_unit("sshd.service") server.wait_for_unit("fail2ban.service") server.wait_for_open_port(22) time.sleep(2) with subtest("Verify sshd jail is active"): status = server.succeed("fail2ban-client status") assert "sshd" in status, f"sshd jail not found in: {status}" with subtest("Generate failed SSH login attempts"): # Use -4 to force IPv4, timeout and NumberOfPasswordPrompts=1 to ensure quick failure # maxRetry is 3 in our config, so 4 attempts should trigger a ban for i in range(4): client.execute( "timeout 5 sshpass -p 'wrongpassword' ssh -4 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=3 -o NumberOfPasswordPrompts=1 testuser@server echo test 2>/dev/null || true" ) time.sleep(1) with subtest("Verify IP is banned"): # Wait for fail2ban to process the logs and apply the ban time.sleep(5) status = server.succeed("fail2ban-client status sshd") print(f"sshd jail status: {status}") # Check that at least 1 IP is banned import re match = re.search(r"Currently banned:\s*(\d+)", status) assert match and int(match.group(1)) >= 1, f"Expected at least 1 banned IP, got: {status}" with subtest("Verify banned client cannot connect"): # Use -4 to test with same IP that was banned exit_code = client.execute("timeout 3 nc -4 -z -w 2 server 22")[0] assert exit_code != 0, "Connection should be blocked for banned IP" ''; }