SSH Tunneler
************

This document describes SSH Tunneler version 0.1.0, a ssh forwarding service written for GNU Guix.

Copyright © 2023 Runciter <runciter@whispers-vpn.org>

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A copy of the license is included in the section entitled ``GNU Free Documentation License''.

The (whispers packages ssh-tunneler) module provides Guix services extending a root or home shepherd with daemonized client ssh connections establishing all types of ssh forwardings:

Port forwarding
     Port forwardings, which can be established using the -L switch of the ssh command, forward connections to a port or socket of the ssh client to a port or socket of the sshd, or to a port of another remote host whose port becomes reachable through client host's port, transported through the sshd host.

Reverse port forwarding
     Reverse port forwardings, which can be established using the -R switch of the ssh command, forward connections to a port or socket of the sshd to a port or socket of the ssh client, or to a port of another remote host whose port becomes reachable through the sshd host's port, transported through the client host.

Dynamic forwarding
     Dynamic forwardings, which can be established using the -D switch of the ssh command, expose the sshd as a SOCKS proxy that a network program which supports this type of proxying can reach through a port of the ssh client.

TUN device forwarding
     Tun device forwardings, a.k.a. ``ssh tunnels'' in the vernacular, which can be established using the -w switch of the ssh command, create a TUN software network device on the ssh client and another such device on the sshd, such that all network packets routed through either of these TUN device are encrypted and can be de-encrypted by the TUN device on the other end of the tunnel, should they be transported there through other (ultimately physical) network devices.

Purpose
*******

Apart from the proverbial ease with which its adepts are empowered to work-around the firewalls of their place of employment, ssh forwarding has several other useful applications, non-exhaustively listed here. The services that the (whispers packages ssh-tunneler) module extends are an attempt to make these available to Guix users, easily configurable, robustly daemonized, and when needed in their most unstoppable form.

Remote shell access
     Through reverse port forwarding, the sshd of a home computer stuck behind a dynamic IP router can be made permanently available through a chosen port of a VPS. On the shepherd side, ssh-tunneler provides features to resurrect the reverse forwarding in case the connection to the VPS is unreliable. See Remote shell access and Resurrected remote shell access for example configurations.

Censorship-resistant web browsing
     Many web browsers support SOCKS v4 or v5 proxies. Any sshd can act as such a proxy, nearly out-of-the-box (see sshd configuration). The ssh-tunneler module can be used to turn a remote sshd into a SOCKS proxy reachable through a chosen port of localhost. The proxy host can be a VPS with a sshd under the user's full control, or a server from a company offering a simple commercial SOCKS proxying service. When the proxy host is located outside the area where a local censorship IP blacklist is enforced, such censorship is effectively nullified for purpose of web browsing. At the time of writing, proxy hosts reached exclusively in this way seem to be immune to detection by advanced packet-scanning techniques... or at the very least, spared from automatic blacklisting. See Dynamic forwarding to a SOCKS v5 proxy for an example configuration.

VPN
     When augmented with appropriate network addressing, routing and iptables stances on the client and server side, ssh tunnels can support the operation of a VPN. At the time of writing, such augmentations probably have to be setup by the user manually or using shell scripts, since the ssh-tunneler module only supports the creation of the ssh tunnel proper.  See ssh tunnel for a VPN for an example configuration of a service extending a ssh tunnel. There are plans in the works to create other services that will enable a set of computers all running Guix to unite into a small dynamically addressed VPN.

Stealth VPN
     It is possible, albeit in a pretty hackish way, to establish a ssh tunnel through an intermediate SOCKS proxy. At the time of writing, similar to what is mentioned above, when the proxy host is located outside an area where packets are being scanned for VPN connection signatures, this method protects the VPN server host and the proxy host from being blacklisted. The ssh-tunneler module supports the establishment of such ``stealth'' tunnels through a SOCKS proxy. See Proxyed ssh tunnel for a stealth VPN for an example configuration.

Configuration
*************

Client system configuration
===========================

In order to establish the persistent forwardings, the client has to extend a service (see Services (GNU Guix)) from its system configuration file (see Using the Configuration System (GNU Guix)).

 -- Variable: persistent-ssh-service-type
     This is the type for the service extending the shepherd with a daemonized ssh connection. Its value must be an ssh-connection-configuration record.

 -- Data Type: ssh-connection-configuration
     This is the configuration record for a ssh connection daemonized by the shepherd.

     shepherd-package (default shepherd)
          A file-like object. The shepherd package to use.

     ssh-package (default openssh)
          A file-like object. The openssh package to use.

     netcat-package (default netcat-openbsd))
          A file-like object. The netcat-openbsd package to use.

     sshpass-package (default sshpass)
          A file-like object. The sshpass package to use.

     ineutils-package (default inetutils)
          A file-like object. The inetutils package to use.

     procps-package (default procps)
          A file-like object. The procps package to use.

     socks-proxy-config (default (socks-proxy-configuration))
          A guix record of type socks-proxy-configuration, configuring proxying of the connection opened by the service. See below for the record's documentation.

     id-rsa-file? (default #t)
          A boolean value. Whether to authenticate to the sshd from a private key loaded from a file.

     id-rsa-file (default "/root/.ssh/id_rsa")
          A string. When configured to do so, the path to the private key file to load in order to authenticate to the sshd.

     clear-password? (default #f)
          A boolean value. Whether to authenticate to the sshd with a clear password. Setting this field to #t is not recommended for security, especially on a multi-user machine, among other concerns because a password will be written into the Guix store in clear text.

     sshd-user-password (default "none")
          A string. When configured to do so, the clear text password to use to authenticate the connection. About security, see the reservations above.

     sshd-user (default "root")
          A string, the UNIX handle of the user to authenticate as on the sshd.

     sshd-host (default "127.0.0.1")
          A string defining an IP address. The IP of the sshd to connect to.

     sshd-port (default 22)
          An integer. The port used to connect to the sshd.

     gateway-ports? (default #t)
          A boolean value. Whether to activate the GatewayPorts switch on the client side. This is the ssh_config GatewayPorts, not the sshd_config GatewayPorts.

     known-hosts-files (default ("~/.ssh/known_hosts" ~/.ssh/known_hosts2))
          A list of strings, configuring the list of files checked for known host keys of the configured sshd-host by setting the UserKnownHostsFiles option of ssh. The default, which reproduces ssh's default configuration at the time of writing, might cause an otherwise correctly configured service to fail its start action. See Host key troubleshooting.

     strict-check (default "yes")
          A string, configuring the value of the StrictHostKeyChecking configuration option of ssh. The default is changed from ssh's default value of "ask" because it is not possible to answer interactive prompts while starting a Shepherd service. A conservative default value is used for security reasons, which might cause an otherwise correctly configured service to fail its start action. See Host key troubleshooting.

     server-alive-interval (default 30))
          An integer. The value assigned to the ServerAliveInterval ssh configuration option of the connection.

     server-alive-count-max (default 6))
          An integer. The value assigned to the ServerAliveCountMax ssh configuration option of the connection.

     name-prefix (default "ssh-forwards")
          A string. The prefix of the service provision of the shepherd service supporting the connection. To this prefix will be by default appended a suffix computed from the characteristics of the forwarding(s) configured for the connection, and its proxy, if any. The resulting string will be converted to a symbol.

     suffix-name? (default #t)
          A boolean value. Whether to append an automatically computed suffix to the shepherd provision of the service supporting the connection.

     special-options (default '())
          A list of strings. A list of options to add to the ssh command of the connection.

     forwards (default '())
          A list of ssh-forward-configuration records.

     exit-forward-failure? (default #t))
          A boolean value. Whether to active the ExitOnForwardFailure ssh configuration switch for the connection.

     connection-attempts (default 1))
          An integer. the value assigned to to the ConnectionAttempts ssh configuration switch of the connection.

     local-command?
          A boolean value. Its default is computed at system reconfiguration time. Whether to execute a command locally on the client after successfully creating the forwardings of the connection. If the shepherd service uses a PID file, which is the default, setting this options to #f will prevent the service from starting successfully.

     extra-local-commands (default '())
          A list of strings. A list of commands to execute locally on the client after successfully creating the forwardings of the connection and starting the shepherd service.

     require-networking? (default #t)
          A boolean value. Whether the networking service should be included in the requirements of the shepherd service of the connection.

     extra-requires (default '())
          A list of symbols. A list of extra requirements for the shepherd service of the connection.

     elogind? (default #f)
          A boolean value.

     pid-file? (default #t)
          A boolean value. Whether the shepherd should use a PID file for the service of the connection.

     pid-folder-override? (default #f)
          A boolean value. Whether to override the shepherd's global default for the folder of the PID file of the service.

     pid-folder-override (default "/var/run")
          A string. When configured to override the shepherd's global default, the path to the folder where to store the PID file of the service.

     timeout-override? (default #f)
          A boolean value. Whether to override the shepherd's global default for the timeout of the service startup.

     timeout-override (default 5)
          An integer. When configured to override the shepherd's global default, the timeout of the service startup.

     dedicated-log-file? (default #f)
          A boolean value. Whether the service should log to a dedicated file.

     log-rotate? (default #f)
          A boolean value. Whether the dedicated log file of the service should be rotated by rottlog. This is an experimental feature.

     log-folder-override? (default #f)
          A boolean value. Whether to override the shepherd's global default for the log folder of the service.

     log-folder-override (default "/var/run")
          A string. When configured to override the shepherd's global default, the folder where to store the log file of the service.

     verbosity (default 0)
          An integer between 0 and 3, both included. The verbosity level of the ssh command of the connection, equal to the number of times the -v switch of ssh is used.

     command? (default #f)
          A boolean value. Whether to execute a command on the sshd host after successfully creating the forwardings of the connection.

     command (default '())
          A string. When configured to do so, the command to be executed on the sshd after successfully establishing the forwardings of the connection.

     resurrect-time-spec (default ''(next-minute '(47)))
          A quoted cron job time specification, for which the author would like to extend his most sincere apologies to the user. See the default value for an example of this field's format. The quoted time specification of the cron job extended to resurrect the service, when configured to do so. see Shepherd actions.

     flat-resurrect? (default #f)
          A boolean value. Whether to not recursively resurrect the service.

     force-resurrect-time-spec (default ''(next-hour '(3)))
          A quoted cron job time specification. Apologies repeated. The quoted time specification of the cron job extended to force-resurrect the service, when configured to do so. see Shepherd actions.

     flat-force-resurrect? (default #f)
          A boolean value. Whether to not recursively force-resurrect the service.

     %cron-resurrect? (default #f)
          A boolean value. Whether to automatically resurrect the service by means of a cron job.

     %cron-force-resurrect? (default #f)
          A boolean value. Whether to automatically force-resurrect the service by means of a cron job.

     %auto-start? (default #f)
          A boolean value. Whether to automatically start the service on boot. This feature is experimental, and unreliable.

 -- Data Type: ssh-forward-configuration
     This is the configuration record for one of the forwardings provided by a daemonized ssh connection.

     forward-type (default 'dynamic)
          A symbol which can be 'dynamic, 'port, 'reverse-port or 'tunnel.

     entry-type (default 'port)
          A symbol which can be 'preset or 'any when the 'forward-type field is 'tunnel, and which can be 'port or 'socket otherwise. It is ignored when the 'forward-type field is 'dynamic.

     exit-type (default 'port)
          A symbol which can be 'preset or 'any when the forward-type field is 'tunnel, and which can be 'port or 'socket otherwise. It is ignored when the forward-type field is 'dynamic.

     entry-port (default 8971)
          An integer. When the forward-type is 'dynamic, 'port or 'reverse-port and the entry-type is 'port, the port to forward from at the entry of the forwarding.

     exit-port (default 22)
          An integer. When the forward-type is 'port or 'reverse-port and the exit-type is 'port, the port to forward to at the final destination of the forwarding.

     entry-socket (default ""))
          A string. When the forward-type is 'port or 'reverse-port and the entry-type is 'socket, the path to the socket file to forward from at the entry of the forwarding. This is an experimental feature.

     exit-socket (default "")
          A string. When the forward-type is 'port or 'reverse-port and the exit-type is 'socket, the path to the socket file to forward to at the final destination of the forwarding. This is an experimental feature.

     forward-host (default "127.0.0.1")
          A string representing an IP address. The final destination host of the forwarding, applicable when the forward-type is 'port or 'reverse-port.

     entry-tun (default 0)
          An integer. When the forward-type is 'tunnel and the entry-type is 'preset, the TUN interface number (tunX) on the side of the client extending the service.

     exit-tun (default 0)))
          An integer. When the forward-type is 'tunnel and the exit-type is 'preset, the TUN interface number (tunX) on the sshd side.

 -- Data Type: socks-proxy-configuration
     This is the configuration record for the SOCKS proxy used by a daemonized ssh connection to connect to the sshd.

     use-proxy? (default #f)
          A boolean value. Whether to establish the ssh connection configured by the parent record through a SOCKS proxy. For as much as the rest of this record's documentation may be confusing to the first-time reader (sorry), he might feel relieved to note that it is sufficient to set the value of this field to #t to proxy a single daemonized ssh connection through a default port of localhost.

     extend?
          A boolean value. Whether the ssh connection connection supporting the SOCKS proxy should be auto-magically extended as a shepherd service on whose provision the ssh connection configured by the parent record will depend. While, strictly speaking, the default of the extend? field is computed at Guix system-reconfiguration time, the default behavior is to auto-magically extend a shepherd service adequately configured to expose the proxy on localhost whenever the user configuring the Guix system has elected to use such a proxy through the use-proxy? field of this record. Overriding this default behavior is experimental, and can be achieved by explicitly setting the extend? field to #f in your system configuration.

     port
          An integer. Its default is computed at Guix system-reconfiguration time. Overriding this default is experimental. The port of localhost to use to connect to the SOCKS proxy.

     dynamic-forward
          A value which can be #f, or a Guix record returned by a call to ssh-connection-configuration. In the latter case, this field defines the configuration record for the service of type persistent-ssh-service-type that will extend the connection supporting the proxy for the connection configured by the parent record, if any. The value #f is probably always the most adequate when the connection extended by the parent record will not use a SOCKS proxy, and it does not need to be changed by the user. When the user configuring a the system extends a SOCKS proxy, he may optionally wish to change the value of the dynamic-forward field from its computed default, for example if he wants to use a non-default port, one requirement being that it must then be a configuration record for a connection creating a dynamic port forward as the first member of its list of forwards.

For the user's convenience, macros are provided as helpers to instantiate ssh-forward-configuration records with sane defaults preset for the supported types of forwardings. Field values of the record ssh-forward-configuration returned by these macros can be changed from their defaults exactly as if instantiating a ssh-forward-configuration record directly.

 -- Macro: dynamic-forward-configuration ...

     This macro (included for the sake of completeness) returns an ssh-forward-configuration record with sane defaults set to configure a dynamic port forwarding in the service. The defaults of fields are actually not changed from a direct call to dynamic-forward-configuration. see Dynamic forwarding to a SOCKS v5 proxy for an example usage.

 -- Macro: port-forward-configuration ...

     This macro returns an ssh-forward-configuration record with sane defaults set to configure a port forwarding in the service. The default of the forward-type field of the returned record is changed to 'port, and the default of the entry-port field of the record is chanted to 6947. See Port forwarding example for an example usage.

 -- Macro: reverse-port-forward-configuration ...

     This macro returns an ssh-forward-configuration record with sane defaults set to configure a reverse port forwarding in the service. The default of the forward-type field of the returned record is changed to 'reverse-port, and the default of the entry-port field of the record is chanted to 6283. See Remote shell access for an example usage.

 -- Macro: tunnel-forward-configuration ...

     This macro returns an ssh-forward-configuration record with sane defaults set to configure a tunnel forwarding in the service. The default of the forward-type field of the returned record is changed to 'tunnel, the default of the entry-type field of the record is chanted to 'any, and the default of the exit-type field of the record is also changed to 'any . See ssh tunnel for a VPN for an example usage.

Host key troubleshooting
========================

For security reasons, mostly related to the prevention of man-in-the-middle attacks, ssh authenticates the sshd host through its host keys, and by default aborts or pauses establishing a connection when it is unable to verify host keys or when it verifies that a host key previously known to the client for this host has changed. Stemming from the same concerns, the services extended from this module have to implement slightly more conservative defaults than ssh. However, as a result, users might experience less-than-trivial failures to start the services extended from this module.

If a user is certain that he is connecting to the intended host, but this host's key has changed or is currently unknown to the client ssh started by the Shepherd, the following configuration settings for the service should bypass any and all effects of host key verification by ssh:

              (ssh-connection-configuration
               ...
               (strict-check "no")
               (known-hosts-files '("/dev/null"))
               ...)

The above can be tried for troubleshooting purposes.

sshd configuration
==================

Any machine running a sshd can be the server for the connection, it doesn't need to be running Guix System.

By default, the client extending the service will connect to the sshd as root. Depending on the specifics of your sshd host, you might wish to change that in order to improve security. You can do it by setting a non-default value for the sshd-user field of the ssh-connection-configuration record of the client service, and probably still enjoy functionality provided you do not want to extend a ssh tunnel or to reverse forward a priviledged port of the sshd.

Configuring the sshd should be easy, there are 2 items to consider:

Authentication
     The service extended by the client must authenticate its connection to the sshd. The recommended way is through public key authentication. To achieve it, the public key corresponding to the private key configured by the ssh-connection-configuration record of the service must be registered as authorized for the user of the sshd host that the connection authenticates as. In common situations (but see above), and with default values of the id-rsa-file?, id-rsa-file and sshd-user fields of the client's configuration record, you should be able to authenticate by adding the contents of the /root/.ssh/id_rsa.pub file of the client to the /root/.ssh/authorized_keys file of the sshd. Alternatively, when the sshd itself is also extended as a Guix service on the server host, Guix provides a nice facility to extend public key authorizations (see Networking Services (GNU Guix)).

GatewayPorts sshd option
     For most uses of the ssh-tunneler service, it should be either practical or necessary to set GatewayPorts=yes in the configuration of sshd, for example by adding this option switch to the sshd_config file.

Configuration examples
======================

This section provides a collection of client configuration examples for typical uses of the (whispers packages ssh-tunneler) module, including the applications described in Purpose.

Throughout this section, 1.2.3.4 is used as a placeholder for the IP address of the sshd host to which the client extending a forwarding service connects.

Port forwarding
---------------

This example extends a port forwarding service which forwards the Guix client's port 1357 to the port 2468 of a third host, which the sshd at IP 1.2.3.4 reaches at IP 5.6.7.8.

The daemonized ssh forwarding stance is -L 1357:5.6.7.8:2468.

              (ssh-connection-configuration
               (sshd-user "joe-chip")        ; "root" is the default
               (sshd-host "1.2.3.4")         ; change to IP of sshd as string
               (forwards
                (list (port-forward-configuration
                       (entry-port 1357)     ; 6947 is the default
                       (exit-host "5.6.7.8") ; default is the sshd's localhost
                       (exit-port 2468)))))) ; 22 is the default

You can start the extended service with the following shell command as root:

     herd start ssh-forwards@port,1357:5.6.7.8:2468

Remote shell access
-------------------

This example extends a simple reverse port forwarding service, of the kind that can be used for remote shell access to the local machine, should this machine be firewalled or stuck behind a dynamic IP.

The daemonized ssh forwarding stance is -R 1357:localhost:22.

     (service persistent-ssh-service-type
              (ssh-connection-configuration
               (sshd-user "joe-chip")      ; "root" is the default
               (sshd-host "1.2.3.4")       ; change to IP of sshd as string
               (forwards
                (list (reverse-port-forward-configuration
                       (entry-port 1357)   ; 6283 is the default
                       (exit-port 22)))))) ; 22 is the default

Note that if the port 1357 of the sshd is not priviledged, it is possible to extend a connection to the sshd as a non-root user, such as in this example.

You can start the extended service with the following shell command as root:

     herd start ssh-forwards@reverse-port,1357:localhost:22

After setting GatewayPorts=yes on the sshd and starting the extended shepherd service on the client, you can start a remote shell session on the client through the sshd's IP on port 1357, for example by running this command to start a remote shell as the client's UNIX handle pat-conley:

     ssh -p 1357 pat-conley@1.2.3.4

Remote shell access
-------------------

This example defines exactly the same reverse port forwarding service as the previous one, see Remote shell access. As an added feature of the service, mcron jobs are extended to improve its robustness. Those are especially useful and perhaps necessary if you cannot physically attend the machine which daemonizes the connection for prolonged periods of time.

The daemonized ssh forwarding stance is -R 1357:localhost:22.

     (service persistent-ssh-service-type
              (ssh-connection-configuration
               (sshd-user "joe-chip")      ; "root" is the default
               (sshd-host "1.2.3.4")       ; change to IP of sshd as string
               (%cron-resurrect? #t)       ; #f is the default
               (resurrect-time-spec ''(next-minute '(38)))
               (%cron-force-resurrect? #t) ; #f is the default
               (force-resurrect-time-spec  ''(next-hour '(3)))
               (forwards
                (list (reverse-port-forward-configuration
                       (entry-port 1357)   ; 6283 is the default
                       (exit-port 22)))))) ; 22 is the default

You can start the extended service with the following shell command as root:

     herd start ssh-forwards@reverse-port,1357:localhost:22

In this example, the daemonized ssh connection is resurrected at the 38th minute of every hour and forcefully resurrected at 03:00AM every day.

For the sake of the illustration's completeness, 2 mcron jobs are extended by the configured example service. If your situation makes resurrection desirable, you should probably resurrect your tunneler service(s) with a mcron job. If you have decided to resurrect a service, you should only then consider if you also want to force-resurrect this service by means of a second cron job. Forced resurrection can be useful in the event a long-running daemonized ssh connection has stopped providing its forwardings.

Resurrecting a started service should be completely innocuous to the running service being resurrected and consume only a small amount of shepherd run-time. The author considers a frequency of once per hour for the mcron job of the resurrect action to be adequate. By contrast, in most situations, it is expected to be counter-productive to force-resurrect too frequently. The author recommends a maximum frequency of once a day for forced resurrection.

In the event that you resurrect and/or forcefully resurrect multiple services, it might be (tbc) good practice to spread the times at which the mcron jobs are performed by a couple of minutes or more.

Dynamic forwarding to a SOCKS v5 proxy
--------------------------------------

This example extends a dynamic forwarding service, making the sshd host available as a SOCKS proxy.

The daemonized ssh forwarding stance is -D 1357.

     (service persistent-ssh-service-type
              (ssh-connection-configuration
               (sshd-user "joe-chip")         ; "root" is the default
               (sshd-host "1.2.3.4")          ; change to IP of sshd as string
               (forwards
                (list (dynamic-forward-configuration
                       (entry-port 1357)))))) ; 8971 is the default

You can start the extended service with the following shell command as root:

     herd start ssh-forwards@dynamic,1357

In graphical web browsers, proxy settings are generally accessible through a settings dialog. You would setup a proxy of type SOCKS5 or SOCKS v5 with proxy host localhost on port 1357.

For such a general web browsing use case, you definitely need GatewayPorts=yes to be set for the proxy sshd at 1.2.3.4, for example in its sshd_config file.

Clear password authentication
-----------------------------

This example defines exactly the same dynamic forwarding as the previous one, see Dynamic forwarding to a SOCKS v5 proxy. The difference is that authentication is achieved with a password extended in clear text from the Guix service's configuration record, and by wrapping the ssh command in a call to the sshpass program.

This type of configuration might expose a clear password to other users of the machine, and is not recommended. In any case, it should be reserved for situations where key pair authentication is not available, and only when the extended clear password does not protect any confidential data.

When the client extending the service is a multi-user machine, this is even worse security than merely using the sshpass program from command-line, because the clear-text password will end up in the Guix store.

The daemonized ssh forwarding stance is -D 1357.

     (service persistent-ssh-service-type
              (ssh-connection-configuration
               (sshd-user "joe-chip")         ; "root" is the default
               (sshd-host "1.2.3.4")          ; change to IP of sshd as string
               (clear-password? #t)           ; what do you think you're doing?
               (sshd-user-password "12345")   ; here's hoping yours is better
               (forwards
                (list (dynamic-forward-configuration
                       (entry-port 1357)))))) ; 8971 is the default

You can start the extended service with the following shell command as root:

     herd start ssh-forwards@dynamic,1357

ssh tunnel for a VPN
--------------------

This example extends a ssh tunnel for purpose of supporting a connection to the sshd as a VPN server.

The daemonized ssh forwarding stance is -w any:any.

     (service persistent-ssh-service-type
              (ssh-connection-configuration
               (sshd-user "root")    ; "root" is the default
               (sshd-host "1.2.3.4") ; change to IP of sshd as string
               (forwards
                (list (tunnel-forward-configuration)))))

You can start the extended service with the following shell command as root:

     herd start ssh-forwards@tunnel,any:any

Proxyed ssh tunnel for a stealth VPN
------------------------------------

This example extends a ssh tunnel through an inferior socks proxy of which it also extends the dynamic forward, for purpose of supporting a connection to the sshd as a ``stealth'' VPN server.

Under the hood, the daemonized ssh connection uses the command nc from the program netcat-openbsd to direct packets of the connection to the dynamic forward providing access to the SOCKS proxy. This dirty hack is known to work at the time of writing.

The ssh stance directing the connection to transmit through the proxy should be something like the following, with shell quoting added somewhat artificially for clarity to the human reader:

     -o ProxyCommand='/gnu/store/...-netcat-openbsd-x.x-x/bin/nc -X 5 -x localhost:1357 %h %p'

The daemonized ssh forwarding stance is -w any:any.

     (service persistent-ssh-service-type
              (ssh-connection-configuration
               (sshd-user "root")    ; "root" is the default
               (sshd-host "1.2.3.4") ; change to IP of VPN server sshd as string
               (forwards
                (list (tunnel-forward-configuration)))
               (socks-proxy-config
                (socks-proxy-configuration
                 (use-proxy? #t)
                 (dynamic-forward
                  (ssh-connection-configuration
                   (sshd-host "1.2.3.4") ; change to IP of proxy sshd as string
                   (forwards
                    (list (dynamic-forward-configuration
                           (entry-port 1357)))))))))) ; default is 8971

You can start the extended service with the following shell command as root:

     herd start ssh-forwards@tunnel,any:any@1357

In this example, the SOCKS proxy sshd providing stealth and the VPN server sshd are actually one and the same host. In general, you can use the same host or have 2 different hosts according to your preference. While using 2 hosts might provide more privacy, in the author's experience, using the same host as SOCKS proxy and VPN server still grants protection from IP blacklisting to the sshd.

Final note of caution: once a host is blacklisted, connecting to that same host's VPN server stealthily will obviously not unblacklist it. Your luck holds only as long as the server host is only connected to through a SOCKS proxy and never directly by VPN clients. Do not underestimate the evils of this world, we are not defeating censorship, merely flying under the radar for a little while.

Shepherd actions
****************

Shepherd services extended by Guix services of type persistent-ssh-service-type provide 2 special shepherd actions, Jump Start (The GNU Shepherd Manual) on how to use them from command-line.

resurrect
     The resurrect action has no side effects when the service to which is belongs is running. Otherwise, and in this order, it will enable the service, by default recursively perform itself on a service which provides a dynamic forward that the service uses for proxying (if any), then start the service.

force-resurrect
     The force-resurrect always has side effects which include stopping before starting the service to which it belongs when this service is started. It therefore always causes an interruption of connectivity, namely it will enable the service, stop the service, by default recursively perform itself on a service which provides a dynamic forward that the service uses for proxying (if any), then start the service.

GNU Free Documentation License
******************************

     [file fdl-1.3.texi not included]