diff mbox series

[bug#70341,v8] services: tor: Add support for pluggable transports.

Message ID b93fe9b750452ce3c86c2dc82040e0c0e2c0af1e.1726578688.git.nigko.yerden@gmail.com
State New
Headers show
Series [bug#70341,v8] services: tor: Add support for pluggable transports. | expand

Commit Message

Nigko Yerden Sept. 17, 2024, 1:11 p.m. UTC
Pluggable transports are programs that disguise Tor traffic, which
can be useful in case Tor is censored.  Pluggable transports
cannot be configured by #:config-file file exclusively because Tor
process is run via 'least-authority-wrapper' and cannot have access
to transport plugin, which is a separate executable (Bug#70302,
Bug#70332).

;;; Copyright © 2024 Nigko Yerden <nigko.yerden@gmail.com>

* doc/guix.texi (Networking Services): Document 'tor-transport-plugin'
data type and 'transport-plugins' option for 'tor-configuration.
* gnu/services/networking.scm: Export
'tor-configuration-transport-plugins', 'tor-transport-plugin',
'tor-transport-plugin?', 'tor-plugin-role',
'tor-plugin-protocol', and 'tor-plugin-program'.
(<tor-configuration>): Add 'transport-plugins' field.
(<tor-transport-plugin>): New variable.
(tor-configuration->torrc): Add content to 'torrc' computed-file.
(tor-shepherd-service): Add file-system-mapping(s).

Change-Id: I1b0319358778c7aee650bc843e021a6803a1cf3a
---
Hello Ludo,

Thanks for looking at and sorry for delay. I have made corrections
in accordance with your suggestions:

1. Move example from commit message to doc/guix.tex.
2. Replace 'path-to-binary' field with 'program'.
3. Replace 'tor-transport-plugin-{role,protocol,path-to-binary}'
accessors with 'tor-plugin-{role,protocol,program}'.
4. Use @code{ClientTransportPlugin ...} instead of quotes and
@command{man tor} instead of @code{man tor}.

Regards,
Nigko

 doc/guix.texi               | 68 ++++++++++++++++++++++++++++++++++++
 gnu/services/networking.scm | 69 ++++++++++++++++++++++++++++++-------
 2 files changed, 124 insertions(+), 13 deletions(-)


base-commit: 8dae6b47542b906682f83b06b0478fcbd0776fd6
diff mbox series

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index bc4d306c2d..ad785f97e6 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -22045,6 +22045,12 @@  Networking Services
 @file{/var/run/tor/control-sock}, which will be made writable by members of the
 @code{tor} group.
 
+@item @code{transport-plugins} (default: @code{'()})
+The list of @code{<tor-transport-plugin>} records to use.
+For any transport plugin you include in this list, appropriate
+configuration line to enable transport plugin will be automatically
+added to the default configuration file.
+
 @end table
 @end deftp
 
@@ -22073,6 +22079,68 @@  Networking Services
 @end table
 @end deftp
 
+@cindex pluggable transports, tor
+@deftp {Data Type} tor-transport-plugin
+Data type representing a Tor pluggable transport plugin in
+@code{tor-configuration}.  Plugguble transports are programs
+that disguise Tor traffic, which can be useful in case Tor is
+censored.  See the the Tor project's
+@url{https://tb-manual.torproject.org/circumvention/,
+documentation} and
+@url{https://spec.torproject.org/pt-spec/index.html,
+specification} for more information.
+
+Each transport plugin corresponds either to
+@code{ClientTransportPlugin ...} or to
+@code{ServerTransportPlugin ...} line in the default
+configuration file, see @command{man tor}.
+Available @code{tor-transport-plugin} fields are:
+
+@table @asis
+@item @code{role} (default: @code{'client})
+This must be either @code{'client} or @code{'server}.  Otherwise,
+an error is raised.  Set the @code{'server} value if you want to
+run a bridge to help censored users connect to the Tor network, see
+@url{https://community.torproject.org/relay/setup/bridge/,
+the Tor project's brige guide}.  Set the @code{'client} value
+if you want to connect to somebody else's bridge, see
+@url{https://bridges.torproject.org/, the Tor project's
+``Get Bridges'' page}.  In both cases the required
+additional configuration should be provided via
+@code{#:config-file} option of @code{tor-configuration}.
+@item @code{protocol} (default: @code{"obfs4"})
+A string that specifies a pluggable transport protocol.
+@item @code{program}
+This must be a ``file-like'' object or a string
+pointing to the pluggable transport plugin executable.
+This option allows the Tor daemon run inside the container
+to access the executable and all the references
+(e.g. package dependencies) attached to it.
+@end table
+
+Suppose you would like Tor daemon to use obfs4 type obfuscation and
+to connect to Tor network via obfs4 bridge (a nonpublic Tor relay with
+support for obfs4 type obfuscation). Then you may go to
+@url{https://bridges.torproject.org/, https://bridges.torproject.org/}
+and get there a couple of bridge lines (each starts with @code{obfs4 ...})
+and use these lines in tor-service-type configuration as follows:
+@lisp
+(service tor-service-type
+	 (tor-configuration
+	  (config-file (plain-file "torrc"
+				   "\
+UseBridges 1
+Bridge obfs4 ...
+Bridge obfs4 ..."))
+	  (transport-plugins
+	   (list (tor-transport-plugin
+		  (program
+		   (file-append
+		    go-gitlab-torproject-org-tpo-anti-censorship-pluggable-transports-lyrebird
+		    "/bin/lyrebird")))))))
+@end lisp
+@end deftp
+
 The @code{(gnu services rsync)} module provides the following services:
 
 You might want an rsync daemon if you have files that you want available
diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
index 12d8934e43..5a4e3a960d 100644
--- a/gnu/services/networking.scm
+++ b/gnu/services/networking.scm
@@ -160,10 +160,16 @@  (define-module (gnu services networking)
             tor-configuration-hidden-services
             tor-configuration-socks-socket-type
             tor-configuration-control-socket-path
+            tor-configuration-transport-plugins
             tor-onion-service-configuration
             tor-onion-service-configuration?
             tor-onion-service-configuration-name
             tor-onion-service-configuration-mapping
+	    tor-transport-plugin
+	    tor-transport-plugin?
+	    tor-plugin-role
+	    tor-plugin-protocol
+	    tor-plugin-program
             tor-hidden-service  ; deprecated
             tor-service-type
 
@@ -966,7 +972,9 @@  (define-record-type* <tor-configuration>
   (socks-socket-type tor-configuration-socks-socket-type ; 'tcp or 'unix
                      (default 'tcp))
   (control-socket?  tor-configuration-control-socket-path
-                    (default #f)))
+                    (default #f))
+  (transport-plugins tor-configuration-transport-plugins
+                    (default '())))
 
 (define %tor-accounts
   ;; User account and groups for Tor.
@@ -996,10 +1004,24 @@  (define-configuration/no-serialization tor-onion-service-configuration
 @end lisp
 maps ports 22 and 80 of the Onion Service to the local ports 22 and 8080."))
 
+(define-record-type* <tor-transport-plugin>
+  tor-transport-plugin make-tor-transport-plugin
+  tor-transport-plugin?
+  (role           tor-plugin-role
+		  (default 'client)
+		  (sanitize (lambda (value)
+			      (if (memq value '(client server))
+				  value
+				  (configuration-field-error #f 'role value)))))
+  (protocol       tor-plugin-protocol
+		  (default "obfs4"))
+  (program        tor-plugin-program))
+
 (define (tor-configuration->torrc config)
   "Return a 'torrc' file for CONFIG."
   (match-record config <tor-configuration>
-    (tor config-file hidden-services socks-socket-type control-socket?)
+    (tor config-file hidden-services socks-socket-type control-socket?
+         transport-plugins)
     (computed-file
      "torrc"
      (with-imported-modules '((guix build utils))
@@ -1038,6 +1060,20 @@  (define (tor-configuration->torrc config)
                                     (cons name mapping)))
                                  hidden-services))
 
+               (for-each (match-lambda
+                           ((role-string protocol program)
+                            (format port "\
+~aTransportPlugin ~a exec ~a~%"
+                                    role-string protocol program)))
+                         '#$(map (match-lambda
+                                   (($ <tor-transport-plugin> role protocol program)
+                                    (list (if (eq? role 'client)
+                                              "Client"
+                                              "Server")
+                                          protocol
+                                          program)))
+                                 transport-plugins))
+
                (display "\
 ### End of automatically generated lines.\n\n" port)
 
@@ -1050,20 +1086,27 @@  (define (tor-configuration->torrc config)
 (define (tor-shepherd-service config)
   "Return a <shepherd-service> running Tor."
   (let* ((torrc (tor-configuration->torrc config))
+         (transport-plugins (tor-configuration-transport-plugins config))
          (tor   (least-authority-wrapper
                  (file-append (tor-configuration-tor config) "/bin/tor")
                  #:name "tor"
-                 #:mappings (list (file-system-mapping
-                                   (source "/var/lib/tor")
-                                   (target source)
-                                   (writable? #t))
-                                  (file-system-mapping
-                                   (source "/var/run/tor")
-                                   (target source)
-                                   (writable? #t))
-                                  (file-system-mapping
-                                   (source torrc)
-                                   (target source)))
+                 #:mappings (append
+                             (list (file-system-mapping
+                                    (source "/var/lib/tor")
+                                    (target source)
+                                    (writable? #t))
+                                   (file-system-mapping
+                                    (source "/var/run/tor")
+                                    (target source)
+                                    (writable? #t))
+                                   (file-system-mapping
+                                    (source torrc)
+                                    (target source)))
+                             (map (lambda (plugin)
+				    (file-system-mapping
+				     (source (tor-plugin-program plugin))
+				     (target source)))
+				  transport-plugins))
                  #:namespaces (delq 'net %namespaces))))
     (list (shepherd-service
            (provision '(tor))