{ config, lib, pkgs, ... }: with lib; let cfg = config.local.auth.openssh; withOath = config.local.auth.oath.enable; in { options.local.auth.openssh = { enable = mkEnableOption "openssh"; tunnel.enable = mkEnableOption "ssh tunnel user"; #TODO: Desfasar ecdsa, inseguro hostKeys = listToAttrs (map (name: { inherit name; value = mkOption { type = types.bool; default = false; }; }) [ "ecdsa" "ed25519" "rsa" ]); }; config = lib.mkIf cfg.enable { assertions = [ { assertion = cfg.tunnel.enable -> withOath; message = "SSH tunnel requires oath"; } ]; local.boot.impermanence.files = flatten (map (key: [ key.path "${key.path}.pub" ]) config.services.openssh.hostKeys); services.openssh = { enable = true; openFirewall = true; ports = [ 2234 ]; startWhenNeeded = true; hostKeys = map (name: { path = "/etc/ssh/ssh_host_${name}_key"; type = name; } // optionalAttrs (name == "rsa") { bits = 4096; }) (attrNames (filterAttrs (name: enable: enable) cfg.hostKeys)); settings = { X11Forwarding = true; PermitRootLogin = "prohibit-password"; PasswordAuthentication = withOath; # Necesario para oath, no reemplaza a oath }; extraConfig = optionalString cfg.tunnel.enable '' # User 'tunnel' has no password. Use PAM OATH # and connect with -N, forward with -R. Match User tunnel AllowTcpForwarding remote AllowStreamLocalForwarding no X11Forwarding no PermitTunnel no GatewayPorts no AllowAgentForwarding no PermitOpen none PermitListen 60220 60221 60222 60223 60224 60225 60226 60227 60228 60229 Banner ${pkgs.writeText "tunnel-banner" '' This is a reverse tunnel ''} ''; }; users.users.tunnel = mkIf cfg.tunnel.enable { uid = 1100; group = "nogroup"; isSystemUser = true; # Requiere oath password = "tunnel"; home = "/var/empty"; shell = "${pkgs.coreutils}/bin/true"; }; }; }