diff --git a/nixos/modules/services/networking/sslh.nix b/nixos/modules/services/networking/sslh.nix index c4fa370a5fef..0921febba668 100644 --- a/nixos/modules/services/networking/sslh.nix +++ b/nixos/modules/services/networking/sslh.nix @@ -15,7 +15,11 @@ let listen: ( - { host: "${cfg.listenAddress}"; port: "${toString cfg.port}"; } + ${ + concatMapStringsSep ",\n" + (addr: ''{ host: "${addr}"; port: "${toString cfg.port}"; }'') + cfg.listenAddresses + } ); ${cfg.appendConfig} @@ -33,6 +37,10 @@ let ''; in { + imports = [ + (mkRenamedOptionModule [ "services" "sslh" "listenAddress" ] [ "services" "sslh" "listenAddresses" ]) + ]; + options = { services.sslh = { enable = mkEnableOption "sslh"; @@ -55,10 +63,10 @@ in description = "Will the services behind sslh (Apache, sshd and so on) see the external IP and ports as if the external world connected directly to them"; }; - listenAddress = mkOption { - type = types.str; - default = "0.0.0.0"; - description = "Listening address or hostname."; + listenAddresses = mkOption { + type = types.coercedTo types.str singleton (types.listOf types.str); + default = [ "0.0.0.0" "[::]" ]; + description = "Listening addresses or hostnames."; }; port = mkOption { diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 7056d414e9e9..125dad9f83f2 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -307,6 +307,7 @@ in spacecookie = handleTest ./spacecookie.nix {}; spike = handleTest ./spike.nix {}; sonarr = handleTest ./sonarr.nix {}; + sslh = handleTest ./sslh.nix {}; strongswan-swanctl = handleTest ./strongswan-swanctl.nix {}; sudo = handleTest ./sudo.nix {}; switchTest = handleTest ./switch-test.nix {}; diff --git a/nixos/tests/sslh.nix b/nixos/tests/sslh.nix new file mode 100644 index 000000000000..2a800aa52d0a --- /dev/null +++ b/nixos/tests/sslh.nix @@ -0,0 +1,83 @@ +import ./make-test-python.nix { + name = "sslh"; + + nodes = { + server = { pkgs, lib, ... }: { + networking.firewall.allowedTCPPorts = [ 443 ]; + networking.interfaces.eth1.ipv6.addresses = [ + { + address = "fe00:aa:bb:cc::2"; + prefixLength = 64; + } + ]; + # sslh is really slow when reverse dns does not work + networking.hosts = { + "fe00:aa:bb:cc::2" = [ "server" ]; + "fe00:aa:bb:cc::1" = [ "client" ]; + }; + services.sslh = { + enable = true; + transparent = true; + appendConfig = '' + protocols: + ( + { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; probe: "builtin"; }, + { name: "http"; host: "localhost"; port: "80"; probe: "builtin"; }, + ); + ''; + }; + services.openssh.enable = true; + users.users.root.openssh.authorizedKeys.keyFiles = [ ./initrd-network-ssh/id_ed25519.pub ]; + services.nginx = { + enable = true; + virtualHosts."localhost" = { + addSSL = false; + default = true; + root = pkgs.runCommand "testdir" {} '' + mkdir "$out" + echo hello world > "$out/index.html" + ''; + }; + }; + }; + client = { ... }: { + networking.interfaces.eth1.ipv6.addresses = [ + { + address = "fe00:aa:bb:cc::1"; + prefixLength = 64; + } + ]; + networking.hosts."fe00:aa:bb:cc::2" = [ "server" ]; + environment.etc.sshKey = { + source = ./initrd-network-ssh/id_ed25519; # dont use this anywhere else + mode = "0600"; + }; + }; + }; + + testScript = '' + start_all() + + server.wait_for_unit("sslh.service") + server.wait_for_unit("nginx.service") + server.wait_for_unit("sshd.service") + server.wait_for_open_port(80) + server.wait_for_open_port(443) + server.wait_for_open_port(22) + + for arg in ["-6", "-4"]: + client.wait_until_succeeds(f"ping {arg} -c1 server") + + # check that ssh through sslh works + client.succeed( + f"ssh {arg} -p 443 -i /etc/sshKey -o StrictHostKeyChecking=accept-new server 'echo $SSH_CONNECTION > /tmp/foo{arg}'" + ) + + # check that 1/ the above ssh command had an effect 2/ transparent proxying really works + ip = "fe00:aa:bb:cc::1" if arg == "-6" else "192.168.1." + server.succeed(f"grep '{ip}' /tmp/foo{arg}") + + # check that http through sslh works + assert client.succeed(f"curl {arg} http://server:443").strip() == "hello world" + ''; +} diff --git a/pkgs/servers/sslh/default.nix b/pkgs/servers/sslh/default.nix index cbeacece3e1e..68fe9c4b08ed 100644 --- a/pkgs/servers/sslh/default.nix +++ b/pkgs/servers/sslh/default.nix @@ -1,4 +1,4 @@ -{ stdenv, fetchurl, libcap, libconfig, perl, tcp_wrappers, pcre }: +{ stdenv, fetchurl, libcap, libconfig, perl, tcp_wrappers, pcre, nixosTests }: stdenv.mkDerivation rec { pname = "sslh"; @@ -19,6 +19,10 @@ stdenv.mkDerivation rec { hardeningDisable = [ "format" ]; + passthru.tests = { + inherit (nixosTests) sslh; + }; + meta = with stdenv.lib; { description = "Applicative Protocol Multiplexer (e.g. share SSH and HTTPS on the same port)"; license = licenses.gpl2Plus;