Subject: bug#55335: [PATCH] services: Allow shepherd to listen for IPv6 connections to openssh.

From: Christopher Baines <[email-masked]>
Date: Fri, 13 May 2022 15:23:12 +0100

Prior to the switch to the openssh service using inetd, you could connect over
IPv4 or IPv6. With inetd, you can only connect over IPv4, meaning for machines
with just IPv6 connectivity, you can't connect.

Switching to listing via IPv6 should support IPv4 connections, as Linux is
capable of translating IPv4 connections to IPv6. I think there's a risk that
switching to this approach will affect some uses of the openssh
service. Therefore, this commit makes this a configuration option, which is #f
by default.

In the future, once it's easy to do so via Guile and the shepherd, it would be
good if two sockets were used, one for IPv4 and one for IPv6. That's not easy
at the moment, as the IPv6 socket conflicts with the IPv4 one, due to the
translation behaviour described above.

* gnu/services/ssh.scm (openssh-listen-via-ipv6?): New procedure.
(openssh-shepherd-service): Factor in listen-via-ipv6? when constructing the
socket address.
* doc/guix.texi (Networking Services): Document the new listen-via-ipv6?
field.
---
 doc/guix.texi        |  9 +++++++++
 gnu/services/ssh.scm | 13 +++++++++++--
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index c168a66072..b168cb379e 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -19119,6 +19119,15 @@ Match Address 192.168.0.1
   PermitRootLogin yes"))
 @end lisp
 
+@item @code{listen-via-ipv6?} (default: @code{#f})
+When listening via a inetd-style Shepherd service, connections will only
+be accepted via IPv4.
+
+To have the shepherd listen instead via IPv6, set this option to
+#t. Depending on how network connections are handled, this will either
+enable connecting via IPv6 and translated IPv4, or just enable IPv6
+connections only.
+
 @end table
 @end deftp
 
diff --git a/gnu/services/ssh.scm b/gnu/services/ssh.scm
index 7fbbe383e5..427f0e4739 100644
--- a/gnu/services/ssh.scm
+++ b/gnu/services/ssh.scm
@@ -363,7 +363,13 @@ (define-record-type* <openssh-configuration>
   ;; proposed in <https://bugs.gnu.org/27155>.  Keep it internal/undocumented
   ;; for now.
   (%auto-start?          openssh-auto-start?
-                         (default #t)))
+                         (default #t))
+
+  ;; Boolean
+  ;; XXX: The service should really listen via IPv4 and IPv6 by default, but
+  ;; this is a little tricky. See https://issues.guix.gnu.org/55335
+  (listen-via-ipv6?      openssh-listen-via-ipv6?
+                         (default #f)))
 
 (define %openssh-accounts
   (list (user-group (name "sshd") (system? #t))
@@ -535,7 +541,10 @@ (define openssh-command
          (start #~(if (defined? 'make-inetd-constructor)
                       (make-inetd-constructor
                        (append #$openssh-command '("-i"))
-                       (make-socket-address AF_INET INADDR_ANY
+                       (make-socket-address #$(if (openssh-listen-via-ipv6? config)
+                                                  #~AF_INET6
+                                                  #~AF_INET)
+                                            INADDR_ANY
                                             #$port-number)
                        #:max-connections #$max-connections)
                       (make-forkexec-constructor #$openssh-command
-- 
2.34.0