aboutsummaryrefslogtreecommitdiff
\input texinfo
@c -*-texinfo-*-

@c %**start of header
@setfilename ssh-tunneler.info
@documentencoding UTF-8
@settitle SSH Tunneler Reference Manual
@c %**end of header

@set UPDATED 10 October 2024
@set UPDATED-MONTH October 2024
@set EDITION 0.1.0
@set VERSION 0.1.0

@copying
Copyright @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''.
@end copying

@dircategory System administration
@direntry
* SSH tunneler: (ssh-tunneler).     Daemonized SSH forwardings for GNU Guix
@end direntry

@titlepage
@title SSH Tunneler Reference Manual
@subtitle Daemonized SSH Forwardings for GNU Guix
@author Runciter

@page
@vskip 0pt plus 1filll
Edition @value{EDITION} @*
@value{UPDATED} @*

@insertcopying
@end titlepage

@contents

@c *********************************************************************
@node Top
@top SSH Tunneler

This document describes SSH Tunneler version @value{VERSION}, a ssh
forwarding service written for GNU Guix.

@insertcopying

The @code{(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:

@table @code

@cindex port forwarding
@item Port forwarding
Port forwardings, which can be established using the @command{-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.

@cindex reverse port forwarding
@item Reverse port forwarding
Reverse port forwardings, which can be established using the
@command{-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.

@cindex dynamic forwarding
@item Dynamic forwarding
Dynamic forwardings, which can be established using the @command{-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.

@cindex TUN device forwarding
@item TUN device forwarding
Tun device forwardings, a.k.a. ``ssh tunnels'' in the vernacular, which
can be established using the @command{-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.

@end table

@menu
* Purpose::
* Configuration::
* Shepherd actions::
* GNU Free Documentation License::
* Concept Index::
* Programming Index::

@detailmenu
 --- The Detailed Node Listing ---

Configuration

* Client system configuration::
* Host key troubleshooting::
* sshd configuration::
* Configuration examples::

Configuration examples

* Port forwarding example::
* Remote shell access::
* Resurrected remote shell access::
* Dynamic forwarding to a SOCKS v5 proxy::
* Clear password authentication::
* ssh tunnel for a VPN::
* Proxyed ssh tunnel for a stealth VPN::

@end detailmenu
@end menu

@c *********************************************************************
@node Purpose
@chapter 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 @code{(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.

@table @code

@cindex remote shell access
@item 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 @command{resurrect} the reverse forwarding in case the
connection to the VPS is unreliable. @xref{Remote shell access} and
@ref{Resurrected remote shell access} for example configurations.

@cindex censorship-resistant web browsing
@item 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 (@pxref{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. @xref{Dynamic forwarding to a SOCKS v5 proxy}
for an example configuration.

@cindex VPN
@item VPN
When augmented with appropriate network addressing, routing and
@code{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.  @xref{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.

@cindex stealth VPN
@item 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. @xref{Proxyed ssh tunnel for a stealth VPN} for an example
configuration.

@end table

@c *********************************************************************
@node Configuration
@chapter Configuration

@c *********************************************************************
@menu
* Client system configuration::
* Host key troubleshooting::
* sshd configuration::
* Configuration examples::
@end menu

@node Client system configuration
@section Client system configuration

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

@defvar persistent-ssh-service-type
This is the type for the service extending the shepherd with a
daemonized ssh connection. Its value must be an
@code{ssh-connection-configuration} record.

@end defvar

@deftp {Data Type} ssh-connection-configuration
This is the configuration record for a ssh connection daemonized by the
shepherd.

@table @asis

@item @code{shepherd-package} (default @code{shepherd})
A file-like object. The shepherd package to use.

@item @code{ssh-package} (default @code{openssh})
A file-like object. The openssh package to use.

@item @code{netcat-package} (default @code{netcat-openbsd}))
A file-like object. The netcat-openbsd package to use.

@item @code{sshpass-package} (default @code{sshpass})
A file-like object. The sshpass package to use.

@item @code{ineutils-package} (default @code{inetutils})
A file-like object. The inetutils package to use.

@item @code{procps-package} (default @code{procps})
A file-like object. The procps package to use.

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

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

@item @code{id-rsa-file} (default @code{"/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.

@item @code{clear-password?} (default @code{#f})
A boolean value. Whether to authenticate to the sshd with a clear
password. Setting this field to @code{#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.

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

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

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

@item @code{sshd-port} (default @code{22})
An integer. The port used to connect to the sshd.

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

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

@item @code{strict-check} (default @code{"yes"})
A string, configuring the value of the StrictHostKeyChecking
configuration option of ssh. The default is changed from @command{ssh}'s
default value of @code{"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. @xref{Host key troubleshooting}.

@item @code{server-alive-interval} (default @code{30}))
An integer. The value assigned to the ServerAliveInterval @command{ssh}
configuration option of the connection.

@item @code{server-alive-count-max} (default @code{6}))
An integer. The value assigned to the ServerAliveCountMax @command{ssh}
configuration option of the connection.

@item @code{name-prefix} (default @code{"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.

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

@item @code{special-options} (default @code{'()})
A list of strings. A list of options to add to the ssh command of the
connection.

@item @code{forwards} (default @code{'()})
A list of @code{ssh-forward-configuration} records.

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

@item @code{connection-attempts} (default @code{1}))
An integer. the value assigned to to the ConnectionAttempts ssh
configuration switch of the connection.

@item @code{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
@code{#f} will prevent the service from starting successfully.

@item @code{extra-local-commands} (default @code{'()})
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.

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

@item @code{extra-requires} (default @code{'()})
A list of symbols. A list of extra requirements for the shepherd service
of the connection.

@item @code{elogind?} (default @code{#f})
A boolean value.

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

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

@item @code{pid-folder-override} (default @code{"/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.

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

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

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

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

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

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

@item @code{verbosity} (default @code{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
@command{-v} switch of ssh is used.

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

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

@item @code{resurrect-time-spec} (default @code{''(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 @command{resurrect} the service, when configured to
do so. @pxref{Shepherd actions}.

@item @code{flat-resurrect?} (default @code{#f})
A boolean value. Whether to @emph{not} recursively @command{resurrect}
the service.

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

@item @code{flat-force-resurrect?} (default @code{#f})
A boolean value. Whether to @emph{not} recursively
@command{force-resurrect} the service.

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

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

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

@end table
@end deftp

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

@table @asis

@item @code{forward-type} (default @code{'dynamic})
A symbol which can be @code{'dynamic}, @code{'port},
@code{'reverse-port} or @code{'tunnel}.

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

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

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

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

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

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

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

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

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

@end table
@end deftp

@deftp {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.

@table @asis

@item @code{use-proxy?} (default @code{#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 @code{#t} to proxy a single daemonized ssh
connection through a default port of localhost.

@item @code{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 @code{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
@code{use-proxy?} field of this record. Overriding this default behavior
is experimental, and can be achieved by explicitly setting the
@code{extend?} field to @code{#f} in your system configuration.

@item @code{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.

@item @code{dynamic-forward}
A value which can be @code{#f}, or a Guix record returned by a call to
@code{ssh-connection-configuration}. In the latter case, this field
defines the configuration record for the service of type
@code{persistent-ssh-service-type} that will extend the connection
supporting the proxy for the connection configured by the parent record,
if any. The value @code{#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 @code{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 @code{forwards}.

@end table
@end deftp

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

@defmac dynamic-forward-configuration @dots{}

This macro (included for the sake of completeness) returns an
@code{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
@code{dynamic-forward-configuration}. @pxref{Dynamic forwarding to a
SOCKS v5 proxy} for an example usage.

@end defmac

@defmac port-forward-configuration @dots{}

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

@end defmac

@defmac reverse-port-forward-configuration @dots{}

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

@end defmac

@defmac tunnel-forward-configuration @dots{}

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

@end defmac

@c *********************************************************************
@node Host key troubleshooting
@section Host key troubleshooting

For security reasons, mostly related to the prevention of
man-in-the-middle attacks, @command{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
@command{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
@command{ssh} started by the Shepherd, the following configuration
settings for the service should bypass any and all effects of host key
verification by @command{ssh}:

@cindex bypass host key checking
@lisp
         (ssh-connection-configuration
          ...
          (strict-check "no")
          (known-hosts-files '("/dev/null"))
          ...)
@end lisp

The above can be tried for troubleshooting purposes.

@c *********************************************************************
@node sshd configuration
@section 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 @code{sshd-user} field of the
@code{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:

@table @code

@item 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 @code{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 @code{id-rsa-file?}, @code{id-rsa-file} and
@code{sshd-user} fields of the client's configuration record, you should
be able to authenticate by adding the contents of the
@code{/root/.ssh/id_rsa.pub} file of the client to the
@code{/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
(@pxref{Networking Services,,, guix, GNU Guix}).

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

@end table

@c *********************************************************************
@node Configuration examples
@section Configuration examples

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

Throughout this section, @code{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.

@menu
* Port forwarding example::
* Remote shell access::
* Resurrected remote shell access::
* Dynamic forwarding to a SOCKS v5 proxy::
* Clear password authentication::
* ssh tunnel for a VPN::
* Proxyed ssh tunnel for a stealth VPN::
@end menu

@c *********************************************************************
@node Port forwarding example
@subsection 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 @command{-L 1357:5.6.7.8:2468}.

@cindex port forwarding, example
@lisp
         (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
@end lisp

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

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

@c *********************************************************************
@node Remote shell access
@subsection 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 @command{-R 1357:localhost:22}.

@cindex reverse port forwarding, example
@cindex remote shell access, example
@lisp
(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
@end lisp

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:

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

After setting @code{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
@code{pat-conley}:

@example
ssh -p 1357 pat-conley@@1.2.3.4
@end example

@c *********************************************************************
@node Resurrected remote shell access
@subsection Remote shell access

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

The daemonized ssh forwarding stance is @command{-R 1357:localhost:22}.

@cindex resurrected reverse port forward, ex.
@cindex resurrected remote shell access, ex.
@lisp
(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
@end lisp

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

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

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 @code{resurrect} your
tunneler service(s) with a mcron job. If you have decided to
@code{resurrect} a service, you should only then consider if you also
want to @code{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 @code{resurrect} action to be adequate. By
contrast, in most situations, it is expected to be counter-productive to
@code{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.

@c *********************************************************************
@node Dynamic forwarding to a SOCKS v5 proxy
@subsection 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 @command{-D 1357}.

@cindex dynamic forwarding, example
@cindex SOCKS proxy, example
@cindex censorship-resistant browsing, ex.
@lisp
(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
@end lisp

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

@example
herd start ssh-forwards@@dynamic,1357
@end example

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

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

@c *********************************************************************
@node Clear password authentication
@subsection Clear password authentication

This example defines exactly the same dynamic forwarding as the previous
one, @xref{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 @command{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 @command{-D 1357}.

@cindex clear password, example
@lisp
(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
@end lisp

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

@example
herd start ssh-forwards@@dynamic,1357
@end example

@c *********************************************************************
@node ssh tunnel for a VPN
@subsection 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 @command{-w any:any}.

@cindex TUN device forwarding, example
@cindex ssh tunnel, example
@cindex VPN, example
@lisp
(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)))))
@end lisp

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

@example
herd start ssh-forwards@@tunnel,any:any
@end example

@c *********************************************************************
@node Proxyed ssh tunnel for a stealth VPN
@subsection 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
@command{nc} from the program @code{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:

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

The daemonized ssh forwarding stance is @command{-w any:any}.

@cindex stealth TUN device forwarding, ex.
@cindex stealth ssh tunnel, example
@cindex stealth VPN, example
@lisp
(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
@end lisp

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

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

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 @emph{only}
connected to through a SOCKS proxy and @emph{never} directly by VPN
clients. Do not underestimate the evils of this world, we are not
@emph{defeating} censorship, merely @emph{flying under the radar} for a
little while.

@c *********************************************************************
@node Shepherd actions
@chapter Shepherd actions

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

@table @code

@cindex resurrect, shepherd action
@item resurrect
The @code{resurrect} action has no side effects when the service to
which is belongs is running. Otherwise, and in this order, it will
@code{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 @code{start} the service.

@cindex force-resurrect, shepherd action
@item force-resurrect
The @code{force-resurrect} always has side effects which include
stopping before starting the service to which it belongs when this
service is started. It therefore @emph{always} causes an interruption of
connectivity, namely it will @code{enable} the service, @code{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 @code{start} the service.

@end table


@c *********************************************************************
@node GNU Free Documentation License
@appendix GNU Free Documentation License
@cindex license, GNU Free Documentation License
@include fdl-1.3.texi

@c *********************************************************************
@node Concept Index
@unnumbered Concept Index
@printindex cp

@node Programming Index
@unnumbered Programming Index
@syncodeindex tp fn
@syncodeindex vr fn
@printindex fn

@bye

@c Local Variables:
@c ispell-local-dictionary: "american";
@c End: