diff --git a/doc/guix.texi b/doc/guix.texi index 54793c9648..59db00e581 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -18962,6 +18962,12 @@ Name of the file where @command{sshd} writes its PID. @item @code{port-number} (default: @code{22}) TCP port on which @command{sshd} listens for incoming connections. +@item @code{max-connections} (default: @code{200}) +Hard limit on the maximum number of simultaneous client connections, +enforced by the inetd-style Shepherd service (@pxref{Service De- and +Constructors, @code{make-inetd-constructor},, shepherd, The GNU Shepherd +Manual}). + @item @code{permit-root-login} (default: @code{#f}) This field determines whether and when to allow logins as root. If @code{#f}, root logins are disallowed; if @code{#t}, they are allowed. diff --git a/gnu/services/ssh.scm b/gnu/services/ssh.scm index 5c8fe4eef4..7fbbe383e5 100644 --- a/gnu/services/ssh.scm +++ b/gnu/services/ssh.scm @@ -292,6 +292,9 @@ The other options should be self-descriptive." ;; integer (port-number openssh-configuration-port-number (default 22)) + ;; integer + (max-connections openssh-configuration-max-connections + (default 200)) ;; Boolean | 'prohibit-password (permit-root-login openssh-configuration-permit-root-login (default #f)) @@ -515,6 +518,12 @@ of user-name/file-like tuples." (define pid-file (openssh-configuration-pid-file config)) + (define port-number + (openssh-configuration-port-number config)) + + (define max-connections + (openssh-configuration-max-connections config)) + (define openssh-command #~(list (string-append #$(openssh-configuration-openssh config) "/sbin/sshd") "-D" "-f" #$(openssh-config-file config))) @@ -523,9 +532,17 @@ of user-name/file-like tuples." (documentation "OpenSSH server.") (requirement '(syslogd loopback)) (provision '(ssh-daemon ssh sshd)) - (start #~(make-forkexec-constructor #$openssh-command - #:pid-file #$pid-file)) - (stop #~(make-kill-destructor)) + (start #~(if (defined? 'make-inetd-constructor) + (make-inetd-constructor + (append #$openssh-command '("-i")) + (make-socket-address AF_INET INADDR_ANY + #$port-number) + #:max-connections #$max-connections) + (make-forkexec-constructor #$openssh-command + #:pid-file #$pid-file))) + (stop #~(if (defined? 'make-inetd-destructor) + (make-inetd-destructor) + (make-kill-destructor))) (auto-start? (openssh-auto-start? config))))) (define (openssh-pam-services config) diff --git a/gnu/tests/ssh.scm b/gnu/tests/ssh.scm index 791ff7b73f..e3dd601603 100644 --- a/gnu/tests/ssh.scm +++ b/gnu/tests/ssh.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès +;;; Copyright © 2016-2022 Ludovic Courtès ;;; Copyright © 2017, 2018 Clément Lassieur ;;; Copyright © 2017 Marius Bakke ;;; @@ -120,19 +120,21 @@ root with an empty password." marionette)) ;; Check sshd's PID file. - (test-equal "sshd PID" - (wait-for-file #$pid-file marionette) - (marionette-eval - '(begin - (use-modules (gnu services herd) - (srfi srfi-1)) + (test-assert "sshd PID" + (let ((pid (marionette-eval + '(begin + (use-modules (gnu services herd) + (srfi srfi-1)) - (live-service-running - (find (lambda (live) - (memq 'ssh-daemon - (live-service-provision live))) - (current-services)))) - marionette)) + (live-service-running + (find (lambda (live) + (memq 'ssh-daemon + (live-service-provision live))) + (current-services)))) + marionette))) + (if #$pid-file + (= pid (wait-for-file #$pid-file marionette)) + pid))) (test-assert "wait for port 22" (wait-for-tcp-port 22 marionette)) @@ -222,7 +224,7 @@ root with an empty password." (openssh-configuration (permit-root-login #t) (allow-empty-passwords? #t))) - "/var/run/sshd.pid" + #f ;inetd-style, no PID file #:sftp? #t)))) (define %test-dropbear