[PATCH] Persistent SSH forwarding service

  • Open
  • quality assurance status badge
Details
4 participants
  • Maze
  • Bruno Victal
  • Runciter
  • Runciter
Owner
unassigned
Submitted by
Maze
Severity
normal
M
[PATH] Guix service for robust and flexible persistent ssh forwarding
(address . guix-patches@gnu.org)
87352a4541.fsf@pkbd.org
Hello Guix!

I have written a Guix service module to daemonize various types of ssh
forwardings. Basic uses should be very easy to configure.

I am a beginner so you guys will probably laugh at my Scheme. But I have
been using this for remote access to my computers and to daemonize socks
proxies on localhost, I'll say it's pretty damned robust even when the
network is extremely slow, and I think port [reverse] forwardings and
dynamic forwardings are things that quite a few users like to have, even
stand-alone.

Anyway, as the Guix manual recommends I'm just checking if you're
interested to integrate part or all of this into the Guix mainline, or
cannibalize for GNU in any way you see fit. Regardless of outcome, my
goal now is to continue to build another layer on top to turn this into
a full-blown VPN, as zeronconf as these things can get. But at the pace
at which I'm going it's going to be 4 months at the very least before I
have a semi-finished VPN for experimental use. The stand-alone
forwardings of this patch, on the other hand, are working right here
right now.

CONFIGURING FOR ACCESS:

* Your setup better be secure and never allow unauthenticated access to
the remote server or the local client... If you don't have this in
place, using this module could take you from bad to worse.

* Don't forget to set GatewayPorts=yes on the sshd if necessary for your
case! For example in the sshd_config file. Chances are, you probably
need it if you're looking to evade internet censorship, and it will
make your life easier if you're looking for remote access to your home
computer.

* Rarely, and depending on your application it might also be necessary to
enable gateway ports for the ssh client, there's a configuration switch
for that in the record which does it on a connection basis.
* Currently, for the most default use the local ssh tries to get access
to the remote sshd as root. But it's better to change from that
default if you can, like in the basic examples below, unless you need
to forward a priviledged port of the remote sshd.

* By default access is to be granted by the remote sshd through a rsa
private key at /root/id_rsa on the local client machine. You can
change and it might work but you must feed it a file - no agent
currently. See the record fields for details. As you're probably aware
if you read this, when the sshd runs under Guix, a very nice facility
is provided to take care of the public auth keys.

* If you must use a password (don't!), the relevant fields of the
configuration record should be self-explanatory.
SERVICE RECORD BASIC EXAMPLES:
On the client end, somewhat minimal configuration records might look
something like this:

* For a dynamic forward which can support the client end of a persistent
socks proxy:

(service persistent-ssh-service-type
(ssh-connection-configuration
(sshd-user "joe-chip") ; Default is root, better change if you can
(sshd-host "1.2.3.4") ; Try with an IP address here at first
(forwards
(list (dynamic-forward-configuration
(entry-port 1234)))))) ; you may want to change from default

* For a port forwarding:

(service persistent-ssh-service-type
(ssh-connection-configuration
(sshd-user "joe-chip") ; Default is root, better change if you can
(sshd-host "1.2.3.4") ; Try with an IP address here at first
(forwards
(list (port-forward-configuration
(entry-port 1234) ; you may want to change from default
(exit-port 22)))))) ; default 22 here, could be what
; you need or not

* For a reverse port forwarding:

(service persistent-ssh-service-type
(ssh-connection-configuration
(sshd-user "joe-chip") ; Default is root, better change if you can
(sshd-host "1.2.3.4") ; Try with an IP address here at first
(forwards
(list (reverse-port-forward-configuration
(entry-port 1234) ; you may want to change from default
(exit-port 22)))))) ; default 22 here, could be what
; you need or not

Only the local client needs to use the facilities of the module in this
patch, which means only the client must run Guix to enjoy the below
service.

STATE OF THE ART:
Features expected to work, from test script and/or my own daily use:

* Dynamic forwards, port to port forwards or reverse forwards, tunnels.

* Opening a forwarding while using a dynamic forward from the same guix
service extended with this module as the entry point of its socks
proxy. When using this underneath a tunnel forwarding supporting a VPN
network, it's a very potent tool to workaround even the most advanced
nation-state and megacorporation censorship technologies!.. brought to
you by a dirty recourse to netcat-openbsd (not my original idea
though, it's a nice little trick which has been floating around for
some time).
* Being wrapped under sshpass. Boooh! As unrecommended as it may be, it
can be a necessity sometimes such as with some commercial providers of
the sshd end of a socks proxy...
* The resurrect and force-resurrect actions, actionnable from cron
jobs. Nice when you spend a few days to a few weeks away from home and
need remote access to your desktops and servers despite a dynamic IP
and/or an uncooperative phone company.

Available features that might work but are untested:

* I recently added the feature that you can define multiple forwardings
for a single ssh process. I have not begun testing any ssh connection
with 2 or more forwardings, but there's a chance it already works
because I extend the forwardings from basically just mapping a list in
the configuration record.
* Socket-to-socket and port-to-socket [reverse] forwardings are also
implemented but not yet tested.

* There's still a home shepherd service type available. I used it some
months ago then I stopped, it may or may not still work.

* It can probably chain an in-practice-arbitrary number of socks
proxies, but I have not tried yet.

Suspected and known issue:

* The log rotation apparently goes through a system reconfiguration if
activated in the record, but then I think it does nothing. I probably
did something incorrect, will look at it when I have time.

* Auto-starting at boot is unreliable. One issue (maybe?) is I don't
know how to really depend on the physical networking being fully
established, but I'm not sure that's even the only problem. When I
change nothing, I notice it's not deterministic at all. By the time I
get a handle, I can start my failed auto-start connections with herd
no problem.

* In my own system configuration, I don't know why it seems that some
forwardings accept a sshd host in the form of a resolvable hostname,
others will only take an IP address. Not sure, it could be a subtlety
with ssh or even a mistake in my system configurations file... But for
the time being, I would recommend using IP addresses not hostnames if
you trial this module. If it works, you can then shift to trying with
a hostname and let me know if you experience issues.

Missing:

* I have not started to work on control masters. When one has many
connections daemonized to the same remote host, there could (should?)
be a specialized service type extended only to serve as a control
master for multiple other forwarding services. It's probably not that
easy to program correctly.

* It only loads a private key directly from file, no ssh agent. I think
it's probably quite easy to add.

* I haven't even tried to make host knowing configurable the
slightest. No one is there to input "yes" when it starts, so I just
hard coded ssh command switches that should completely tame the
dreaded "SOMEONE MAY BE DOING SOMETHING NASTY!" and its little
friends. Still, in the event this module would start to have its small
user base, I might kind of feel bad about this and something would
preferably have to be done... if that can possibly be practical.
* I think it can only do point-to-point tunnels, that is to say tun
devices. Ssh documentation says it also can do tap devices, what they
call layer 2, which can support DHCP, but in trials I never could get
it to spit out a working tap tunnel... By using ssh for the network
side of the tunnel and tunctl or POSIX or whatever applicable system
calls from a program for the host sides of the tunnel, maybe it's
possible to do tap devices. It's hard, probably.

* No documentation as of yet. The author also still has to learn how to
write actual Texinfo docstrings for procedures, sorry about that.

* I have a test script (not shared here) but it does not plug into the
build system. Also, it deploys multiples VMs to test forwardings in
situation, which means it can do some very strong testing but it's too
heavy for a routine build. And the script does other things which are
either crazy and/or very badly written. I could never have pulled this
without my horrible shell script, but still, a simple script which
plugs into the build system would be more desirable.

---
gnu/services/ssh-tunneler.scm | 834 ++++++++++++++++++++++++++++++++++
1 file changed, 834 insertions(+)
create mode 100644 gnu/services/ssh-tunneler.scm

Toggle diff (233 lines)
diff --git a/gnu/services/ssh-tunneler.scm b/gnu/services/ssh-tunneler.scm
new file mode 100644
index 0000000000..0163aa9e65
--- /dev/null
+++ b/gnu/services/ssh-tunneler.scm
@@ -0,0 +1,834 @@
+;;; Whispers --- Stealth VPN and ssh tunneler
+;;; Copyright © 2023 Maze <maze@whispers-vpn.org>
+;;;
+;;; This file is part of Whispers.
+;;;
+;;; Whispers is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; Whispers is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with Whispers. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu services ssh-tunneler)
+ #:use-module (guix gexp)
+ #:use-module (guix records)
+ #:use-module (gnu services)
+ #:use-module (gnu services shepherd)
+ #:use-module (gnu services admin)
+ #:use-module (gnu services mcron)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages admin)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages ssh)
+ #:use-module (gnu home services)
+ #:use-module (gnu home services shepherd)
+ #:export (ssh-connection-configuration
+ make-ssh-connection-configuration
+ ssh-connection-configuration?
+ this-ssh-connection-configuration
+ ssh-forward-configuration
+ this-ssh-forward-configuration
+ ssh-forward-configuration?
+ make-ssh-forward-configuration
+ socks-proxy-configuration
+ this-socks-proxy-configuration
+ socks-proxy-configuration?
+ make-socks-proxy-configuration
+ dynamic-forward-configuration
+ port-forward-configuration
+ reverse-port-forward-configuration
+ tunnel-forward-configuration
+ persistent-ssh-service-type
+ home-persistent-ssh-service-type))
+
+(define-record-type* <ssh-connection-configuration>
+ ssh-connection-configuration make-ssh-connection-configuration
+ ssh-connection-configuration?
+ this-ssh-connection-configuration
+ ;; A file-like object.
+ (shepherd-package ssh-connection-configuration-shepherd-package
+ (default shepherd))
+ ;; A file-like object.
+ (ssh-package ssh-connection-configuration-ssh-package
+ (default openssh))
+ ;; A file-like object.
+ (netcat-package ssh-connection-configuration-netcat-package
+ (default netcat-openbsd))
+ ;; A file-like object.
+ (sshpass-package ssh-connection-configuration-sshpass-package
+ (default sshpass))
+ ;; A file-like object.
+ (ineutils-package ssh-connection-configuration-inetutils-package
+ (default inetutils))
+ ;; A file-like object.
+ (procps-package ssh-connection-configuration-procps-package
+ (default procps))
+ ;; A guix record of type <socks-proxy-configuration>
+ (socks-proxy-config ssh-connection-configuration-socks-proxy-config
+ (default (socks-proxy-configuration)))
+ ;; A boolean value.
+ (id-rsa-file? ssh-connection-configuration-id-rsa-file?
+ (default #t))
+ ;; A string.
+ (id-rsa-file ssh-connection-configuration-id-rsa-file
+ (default "/root/.ssh/id_rsa"))
+ ;; A boolean value.
+ (clear-password? ssh-connection-configuration-clear-password?
+ (default #f))
+ ;; A string.
+ (sshd-user-password ssh-connection-configuration-sshd-user-password
+ (default "none"))
+ ;; A string.
+ (sshd-user ssh-connection-configuration-sshd-user
+ (default "root"))
+ ;; A string.
+ (sshd-host ssh-connection-configuration-sshd-host
+ (default "localhost"))
+ ;; An integer.
+ (sshd-port ssh-connection-configuration-sshd-port
+ (default 22))
+ ;; A boolean value.
+ (gateway-ports? ssh-connection-configuration-gateway-ports?
+ (default #t))
+ ;; A string.
+ (name-prefix ssh-connection-configuration-name-prefix
+ (default "ssh-forwards"))
+ ;; A boolean value
+ (suffix-name? ssh-connection-configuration-suffix-name?
+ (default #t))
+ ;; A list of strings.
+ (special-options ssh-connection-configuration-special-options
+ (default (list)))
+ ;; A list of <ssh-forward-configuration> records.
+ (forwards ssh-connection-configuration-forwards
+ (default '()))
+ ;; A boolean value.
+ (exit-forward-failure? ssh-connection-configuration-exit-forward-failure?
+ (default #t))
+ ;; An integer.
+ (connection-attempts ssh-connection-configuration-connection-attempts
+ (default 1))
+ ;; A boolean value.
+ (local-command? ssh-connection-configuration-local-command?
+ (default (ssh-connection-configuration-pid-file?
+ this-ssh-connection-configuration))
+ (thunked))
+ ;; A list of strings
+ (extra-local-commands ssh-connection-configuration-extra-local-commands
+ (default '()))
+ ;; A boolean value.
+ (require-networking? ssh-connection-configuration-require-networking?
+ (default #t))
+ ;; A list of symbols.
+ (extra-requires ssh-connection-configuration-extra-requires
+ (default '()))
+ ;; A boolean value.
+ (elogind? ssh-connection-configuration-elogind?
+ (default #f))
+ ;; A boolean value.
+ (pid-file? ssh-connection-configuration-pid-file?
+ (default #t))
+ ;; A boolean value.
+ (pid-folder-override? ssh-connection-configuration-pid-folder-override?
+ (default #f))
+ ;; A string.
+ (pid-folder-override ssh-connection-configuration-pid-folder-override
+ (default "/var/run"))
+ ;; A boolean value.
+ (timeout-override? ssh-connection-configuration-timeout-override?
+ (default #f))
+ ;; An integer.
+ (timeout-override ssh-connection-configuration-timeout-override
+ (default 5))
+ ;; A boolean value.
+ (dedicated-log-file? ssh-connection-configuration-dedicated-log-file?
+ (default #f))
+ ;; A boolean value.
+ (log-rotate? ssh-connection-configuration-log-rotate?
+ (default #f))
+ ;; A boolean value.
+ (log-folder-override? ssh-connection-configuration-log-folder-override?
+ (default #f))
+ ;; A string.
+ (log-folder-override ssh-connection-configuration-log-folder-override
+ (default "/var/run"))
+ ;; An integer between 0 and 3, both included.
+ (verbosity ssh-connection-configuration-verbosity
+ (default 0))
+ ;; A boolean value.
+ (command? ssh-connection-configuration-command?
+ (default #f))
+ ;; A string.
+ (command ssh-connection-configuration-command
+ (default '()))
+ ;; A quoted cron job time specification.
+ (resurrect-time-spec ssh-connection-configuration-resurrect-time-spec
+ (default ''(next-minute '(47))))
+ ;; A boolean
+ (flat-resurrect? ssh-connection-configuration-flat-resurrect?
+ (default #f))
+ ;; A quoted cron job time specification.
+ (force-resurrect-time-spec
+ ssh-connection-configuration-force-resurrect-time-spec
+ (default ''(next-hour '(3))))
+ ;; A boolean
+ (flat-force-resurrect? ssh-connection-configuration-flat-force-resurrect?
+ (default #f))
+ ;; A boolean value.
+ (%cron-resurrect? ssh-connection-configuration-cron-resurrect?
+ (default #f))
+ ;; A boolean value.
+ (%cron-force-resurrect? ssh-connection-configuration-cron-force-resurrect?
+ (default #f))
+ ;; A boolean value.
+ (%auto-start? ssh-connection-configuration-auto-start?
+ (default #t)))
+
+(define-record-type* <ssh-forward-configuration>
+ ssh-forward-configuration make-ssh-forward-configuration
+ ssh-forward-configuration?
+ this-ssh-forward-configuration
+ ;; A symbol which can be 'dynamic, 'port, 'reverse-port or 'tunnel
+ (forward-type ssh-forward-configuration-forward-type
+ (default 'dynamic))
+ ;; 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-type ssh-forward-configuration-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 evaluates to 'dynamic.
+ (exit-type ssh-forward-configuration-exit-type
+ (default 'port))
+ ;; An integer
+ (entry-port ssh-forward-configuration-entry-port
+ (default 8971))
+ ;; An integer
+ (exit-port ssh-forward-configuration-exit-port
+ (default 22))
+ ;; A string
+ (entry-socket ssh-forward-configuration-entry-socket
+ (default ""))
+ ;; A string
+ (exit-socket ssh-forward-configuration-exit-socket
+ (default ""))
+ ;; A string
+ (forward-host ssh-forward-configuration-exit-host
+ (default "localhost"))
+ ;; An integer
+ (entry-tun ssh-forward-configuration-ent
This message was truncated. Download the full message here.
B
B
Bruno Victal wrote on 10 Oct 2023 16:33
(name . Maze)(address . maze@whispers-vpn.org)(address . 64349@debbugs.gnu.org)
54efe1c6-6a81-497d-8b8b-0b499cfc2acb@makinata.eu
Hi,

Toggle quote (30 lines)
> Missing:
>
> * I have not started to work on control masters. When one has many
> connections daemonized to the same remote host, there could (should?)
> be a specialized service type extended only to serve as a control
> master for multiple other forwarding services. It's probably not that
> easy to program correctly.
>
> * It only loads a private key directly from file, no ssh agent. I think
> it's probably quite easy to add.
>
> * I haven't even tried to make host knowing configurable the
> slightest. No one is there to input "yes" when it starts, so I just
> hard coded ssh command switches that should completely tame the
> dreaded "SOMEONE MAY BE DOING SOMETHING NASTY!" and its little
> friends. Still, in the event this module would start to have its small
> user base, I might kind of feel bad about this and something would
> preferably have to be done... if that can possibly be practical.
>
> * I think it can only do point-to-point tunnels, that is to say tun
> devices. Ssh documentation says it also can do tap devices, what they
> call layer 2, which can support DHCP, but in trials I never could get
> it to spit out a working tap tunnel... By using ssh for the network
> side of the tunnel and tunctl or POSIX or whatever applicable system
> calls from a program for the host sides of the tunnel, maybe it's
> possible to do tap devices. It's hard, probably.
>
> * No documentation as of yet. The author also still has to learn how to
> write actual Texinfo docstrings for procedures, sorry about that.

Any updates regarding these items?

Toggle quote (8 lines)
> * I have a test script (not shared here) but it does not plug into the
> build system. Also, it deploys multiples VMs to test forwardings in
> situation, which means it can do some very strong testing but it's too
> heavy for a routine build. And the script does other things which are
> either crazy and/or very badly written. I could never have pulled this
> without my horrible shell script, but still, a simple script which
> plugs into the build system would be more desirable.

Can you adapt it or write a test suite for this service? (see gnu/tests/…
for inspiration)
It makes it easier for everyone to test/review and maintain this addition.

--
Furthermore, I consider that nonfree software must be eradicated.

Cheers,
Bruno.
B
B
Bruno Victal wrote on 10 Oct 2023 21:26
control-msg
(address . control@debbugs.gnu.org)
87bkd62s9o.fsf@makinata.eu
tags 64349 + patch moreinfo
retitle 64349 [PATCH] Persistent SSH forwarding service
retitle 66424 [PATCH core-updates] gnu: libxkbcommon: Fix cross-compile.
quit

--
Thanks,
Bruno.
R
R
Runciter wrote on 12 Oct 2023 16:32
Re: [bug#64349] [PATH] Guix service for robust and flexible persistent ssh forwarding
(name . Bruno Victal)(address . mirai@makinata.eu)
87cyxj7vyu.fsf@pkbd.org
Bruno Victal <mirai@makinata.eu> writes:

Hello,

Toggle quote (34 lines)
> Hi,
>
>> Missing:
>>
>> * I have not started to work on control masters. When one has many
>> connections daemonized to the same remote host, there could (should?)
>> be a specialized service type extended only to serve as a control
>> master for multiple other forwarding services. It's probably not that
>> easy to program correctly.
>>
>> * It only loads a private key directly from file, no ssh agent. I think
>> it's probably quite easy to add.
>>
>> * I haven't even tried to make host knowing configurable the
>> slightest. No one is there to input "yes" when it starts, so I just
>> hard coded ssh command switches that should completely tame the
>> dreaded "SOMEONE MAY BE DOING SOMETHING NASTY!" and its little
>> friends. Still, in the event this module would start to have its small
>> user base, I might kind of feel bad about this and something would
>> preferably have to be done... if that can possibly be practical.
>>
>> * I think it can only do point-to-point tunnels, that is to say tun
>> devices. Ssh documentation says it also can do tap devices, what they
>> call layer 2, which can support DHCP, but in trials I never could get
>> it to spit out a working tap tunnel... By using ssh for the network
>> side of the tunnel and tunctl or POSIX or whatever applicable system
>> calls from a program for the host sides of the tunnel, maybe it's
>> possible to do tap devices. It's hard, probably.
>>
>> * No documentation as of yet. The author also still has to learn how to
>> write actual Texinfo docstrings for procedures, sorry about that.
>
> Any updates regarding these items?

No update as of yet on any of these items.

I've been working on a VPN on top of the ssh tunneler. For which I have
obtained basic functionality, but it's still not quite ready even for my
personal use. While I'm gradually improving the VPN I'm reluctant to add
features to the underlying ssh tunneler services.

Still, I can focus on documenting the services I submitted right now,
and make clean docstrings for the procedures.

Toggle quote (13 lines)
>
>> * I have a test script (not shared here) but it does not plug into the
>> build system. Also, it deploys multiples VMs to test forwardings in
>> situation, which means it can do some very strong testing but it's too
>> heavy for a routine build. And the script does other things which are
>> either crazy and/or very badly written. I could never have pulled this
>> without my horrible shell script, but still, a simple script which
>> plugs into the build system would be more desirable.
>
> Can you adapt it or write a test suite for this service? (see gnu/tests/…
> for inspiration)
> It makes it easier for everyone to test/review and maintain this addition.

There's facilities that are used in the test suite of gdm to create a
"marionette" operating system, probably this is what I should look into.

So I'll stop working on my VPN for a little while and do 2 things:
* Document the ssh-tunneler.scm service file which I previously submitted.
* Try to create a scheme test suite for the services in ssh-tunneler.scm.

I have to learn a few things to do this. Hopefully I can get back to you
at the end of this month with a submission.
R
R
Runciter wrote on 21 Nov 2023 17:08
87y1erks2j.fsf@whispers-vpn.org
Runciter <runciter@pkbd.org> writes:

Hi,

I've been busy with the job sending me on trips all the time, making it
difficult to progress as I'd have liked to.

I only just finished writing a documentation for the module (gnu
services ssh-tunneler). It comes as a standalone manual.

I will now try to add a test for the module with a marionette, as I said
before.

The following patch add doc/ssh-tunneler.texi to the source tree as well
as a minimal stance to compile it into doc/ssh-tunneler.info, and
making git ignore the compile info manual.

Also in the patch, some very minor changes to
gnu/services/ssh-tunneler.scm, which probably and hopefully shouldn't
break the module.

---
.gitignore | 1 +
doc/local.mk | 3 +-
doc/ssh-tunneler.texi | 979 ++++++++++++++++++++++++++++++++++
gnu/services/ssh-tunneler.scm | 837 +++++++++++++++++++++++++++++
4 files changed, 1819 insertions(+), 1 deletion(-)
create mode 100644 doc/ssh-tunneler.texi
create mode 100644 gnu/services/ssh-tunneler.scm

Toggle diff (475 lines)
diff --git a/.gitignore b/.gitignore
index 0f74b5da3d..57086aac7b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,6 +67,7 @@
/doc/stamp-vti
/doc/version.texi
/doc/version-*.texi
+/doc/ssh-tunneler.info
/etc/committer.scm
/etc/gnu-store.mount
/etc/guix-daemon.cil
diff --git a/doc/local.mk b/doc/local.mk
index 97f0c3a92a..94c12456cd 100644
--- a/doc/local.mk
+++ b/doc/local.mk
@@ -42,7 +42,8 @@ info_TEXINFOS = %D%/guix.texi \
%D%/guix-cookbook.de.texi \
%D%/guix-cookbook.fr.texi \
%D%/guix-cookbook.ko.texi \
- %D%/guix-cookbook.sk.texi
+ %D%/guix-cookbook.sk.texi \
+ %D%/ssh-tunneler.texi
%C%_guix_TEXINFOS = \
%D%/contributing.texi \
diff --git a/doc/ssh-tunneler.texi b/doc/ssh-tunneler.texi
new file mode 100644
index 0000000000..fad6a5ec34
--- /dev/null
+++ b/doc/ssh-tunneler.texi
@@ -0,0 +1,979 @@
+\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 31 October 2023
+@set UPDATED-MONTH October 2023
+@set EDITION 0.1.0
+@set VERSION 0.1.0
+
+@copying
+Copyright @copyright{} 2023 Runciter@*
+
+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.
+
+The @code{(gnu 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::
+@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{(gnu 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::
+* 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{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{'pres
This message was truncated. Download the full message here.
R
R
Runciter wrote on 23 Nov 2023 17:02
87cyw0a26b.fsf@whispers-vpn.org
Hi,

I now added a system test in gnu/tests/ssh-tunneler.scm. Very minimal,
for a start, the maionette host only creates a reverse port forwarding
service to itself and tests that the shepherd service starts
successfully.

The test passes for me.

If anyone wants to experiment with the services, the easiest starting
point might be from the example configurations I put in the info manual
at doc/ssh-tunneler.texi.

I'll now go back to working on my insane VPN based off this module. If
there's any interest in integrating the ssh-tunneler module below to the
Guix mainline channel, let me know about any questions or improvement
requests.

From 664da4eb74ae6970720e055ee2e3c76b452f0f6d Mon Sep 17 00:00:00 2001
Message-ID: <664da4eb74ae6970720e055ee2e3c76b452f0f6d.1700753985.git.runciter@whispers-vpn.org>
From: Runciter <runciter@whispers-vpn.org>
Date: Thu, 23 Nov 2023 23:25:40 +0800
Subject: [PATCH] ssh-tunneler services: Guix services daemonizing ssh
forwardings

M .gitignore
Add doc/ssh-tunneler.info to the version control ignored files
M doc/local.mk
Add doc/ssh-tunneler.texi to the list of files to be compiled into
.info manuals
A doc/ssh-tunneler.texi
Standalone TexInfo manual for the services.
A gnu/services/ssh-tunneler.scm
Guix service module for ssh forwardings of all types:
- port forwardings
- reverse port forwardings
- dynamic forwardings
- tunnel forwardings
A gnu/tests/ssh-tunneler.scm
System test in which a marionette host extends a service creating
a reverse port forward to itself, tests that it starts successfully

Signed-off-by: Runciter <runciter@whispers-vpn.org>
---
.gitignore | 1 +
doc/local.mk | 3 +-
doc/ssh-tunneler.texi | 979 ++++++++++++++++++++++++++++++++++
gnu/services/ssh-tunneler.scm | 837 +++++++++++++++++++++++++++++
gnu/tests/ssh-tunneler.scm | 107 ++++
5 files changed, 1926 insertions(+), 1 deletion(-)
create mode 100644 doc/ssh-tunneler.texi
create mode 100644 gnu/services/ssh-tunneler.scm
create mode 100644 gnu/tests/ssh-tunneler.scm

Toggle diff (453 lines)
diff --git a/.gitignore b/.gitignore
index 0f74b5da3d..57086aac7b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,6 +67,7 @@
/doc/stamp-vti
/doc/version.texi
/doc/version-*.texi
+/doc/ssh-tunneler.info
/etc/committer.scm
/etc/gnu-store.mount
/etc/guix-daemon.cil
diff --git a/doc/local.mk b/doc/local.mk
index 97f0c3a92a..94c12456cd 100644
--- a/doc/local.mk
+++ b/doc/local.mk
@@ -42,7 +42,8 @@ info_TEXINFOS = %D%/guix.texi \
%D%/guix-cookbook.de.texi \
%D%/guix-cookbook.fr.texi \
%D%/guix-cookbook.ko.texi \
- %D%/guix-cookbook.sk.texi
+ %D%/guix-cookbook.sk.texi \
+ %D%/ssh-tunneler.texi
%C%_guix_TEXINFOS = \
%D%/contributing.texi \
diff --git a/doc/ssh-tunneler.texi b/doc/ssh-tunneler.texi
new file mode 100644
index 0000000000..3c21bf3c2f
--- /dev/null
+++ b/doc/ssh-tunneler.texi
@@ -0,0 +1,979 @@
+\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 31 October 2023
+@set UPDATED-MONTH October 2023
+@set EDITION 0.1.0
+@set VERSION 0.1.0
+
+@copying
+Copyright @copyright{} 2023 Runciter@*
+
+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.
+
+The @code{(gnu 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::
+@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{(gnu 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::
+* 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{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 t
This message was truncated. Download the full message here.
?