diff mbox series

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

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

Commit Message

Nigko Yerden Aug. 9, 2024, 9:15 a.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).

Example configuration snippet to be appended to
operation-system services
(see https://bridges.torproject.org/ to get
full bridge's lines):

(service tor-service-type
	 (tor-configuration
	  (config-file (plain-file "torrc"
				   "\
UseBridges 1
Bridge obfs4 ...
Bridge obfs4 ..."))
	  (transport-plugins
	   (list (tor-transport-plugin
		  (path-to-binary
		   (file-append
		    go-gitlab-torproject-org-tpo-anti-censorship-pluggable-transports-lyrebird
		    "/bin/lyrebird")))))))

* 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-transport-plugin-role',
'tor-transport-plugin-protocol', and 'tor-transport-plugin-path'.
(<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
---
 doc/guix.texi               | 47 +++++++++++++++++++++++++
 gnu/services/networking.scm | 69 ++++++++++++++++++++++++++++++-------
 2 files changed, 103 insertions(+), 13 deletions(-)


base-commit: 20dbf225f332ccc707578263ed710dcf2a8fb78e

Comments

Ludovic Courtès Sept. 4, 2024, 2:08 p.m. UTC | #1
Hi Nigko,

Nigko Yerden <nigko.yerden@gmail.com> skribis:

> 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).
>
> Example configuration snippet to be appended to
> operation-system services
> (see https://bridges.torproject.org/ to get
> full bridge's lines):
>
> (service tor-service-type
> 	 (tor-configuration
> 	  (config-file (plain-file "torrc"
> 				   "\
> UseBridges 1
> Bridge obfs4 ...
> Bridge obfs4 ..."))
> 	  (transport-plugins
> 	   (list (tor-transport-plugin
> 		  (path-to-binary
> 		   (file-append
> 		    go-gitlab-torproject-org-tpo-anti-censorship-pluggable-transports-lyrebird
> 		    "/bin/lyrebird")))))))
>
> * 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-transport-plugin-role',
> 'tor-transport-plugin-protocol', and 'tor-transport-plugin-path'.
> (<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

[...]

> +Each transport plugin corresponds either to
> +``ClientTransportPlugin ...'' or to
> +``ServerTransportPlugin ...'' line in the default

Maybe use @code{…} instead of quotes above.

Could you perhaps move the example from the commit log to doc/guix.texi,
enclosed in @lisp, and with one or two sentences explaining what it
does?

> +configuration file, see the @code{man tor}.

Rather: “see @command{man tor}.”

> +(define-record-type* <tor-transport-plugin>
> +  tor-transport-plugin make-tor-transport-plugin
> +  tor-transport-plugin?
> +  (role           tor-transport-plugin-role
> +		  (default 'client)
> +		  (sanitize (lambda (value)
> +			      (if (memq value '(client server))
> +				  value
> +				  (configuration-field-error #f 'role value)))))
> +  (protocol       tor-transport-plugin-protocol
> +		  (default "obfs4"))
> +  (path-to-binary tor-transport-plugin-path))

Rather: (program tor-plugin-program)

The doc needs to be updated as well.

(By convention, in Guix and GNU, “path” refers to “search paths” like
$PATH or $PYTHONPATH; to avoid the ambiguity, we use the term “file
name” or something along these lines.)

Apart from that it looks great to me.

Could you send an updated patch?

Thanks, and apologies for the delay!

Ludo’.
diff mbox series

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index b7eb8fd346..0319003b20 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -22006,6 +22006,13 @@  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
 
@@ -22034,6 +22041,46 @@  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
+``ClientTransportPlugin ...'' or to
+``ServerTransportPlugin ...'' line in the default
+configuration file, see the @code{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{path-to-binary}
+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
+@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..4b1b164845 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-transport-plugin-role
+	    tor-transport-plugin-protocol
+	    tor-transport-plugin-path
             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-transport-plugin-role
+		  (default 'client)
+		  (sanitize (lambda (value)
+			      (if (memq value '(client server))
+				  value
+				  (configuration-field-error #f 'role value)))))
+  (protocol       tor-transport-plugin-protocol
+		  (default "obfs4"))
+  (path-to-binary tor-transport-plugin-path))
+
 (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 path)
+                            (format port "\
+~aTransportPlugin ~a exec ~a~%"
+                                    role-string protocol path)))
+                         '#$(map (match-lambda
+                                   (($ <tor-transport-plugin> role protocol path)
+                                    (list (if (eq? role 'client)
+                                              "Client"
+                                              "Server")
+                                          protocol
+                                          path)))
+                                 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-transport-plugin-path plugin))
+				     (target source)))
+				  transport-plugins))
                  #:namespaces (delq 'net %namespaces))))
     (list (shepherd-service
            (provision '(tor))