From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id ENhyMa/uKGB0ZQAA0tVLHw (envelope-from ) for ; Sun, 14 Feb 2021 09:34:39 +0000 Received: from aspmx1.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id yEA9La/uKGBwMAAA1q6Kng (envelope-from ) for ; Sun, 14 Feb 2021 09:34:39 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 33808227E6 for ; Sun, 14 Feb 2021 10:34:39 +0100 (CET) Received: from localhost ([::1]:52606 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lBDna-0005Jt-9x for larch@yhetil.org; Sun, 14 Feb 2021 04:34:38 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45584) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lBDn0-0005IB-GA for guix-patches@gnu.org; Sun, 14 Feb 2021 04:34:02 -0500 Received: from debbugs.gnu.org ([209.51.188.43]:52122) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lBDn0-0001iX-86 for guix-patches@gnu.org; Sun, 14 Feb 2021 04:34:02 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1lBDn0-0006b9-4a for guix-patches@gnu.org; Sun, 14 Feb 2021 04:34:02 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#46504] [PATCH] services: wireguard: New service. Resent-From: Mathieu Othacehe Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sun, 14 Feb 2021 09:34:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 46504 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 46504@debbugs.gnu.org Cc: Mathieu Othacehe X-Debbugs-Original-To: guix-patches@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.161329520425315 (code B ref -1); Sun, 14 Feb 2021 09:34:01 +0000 Received: (at submit) by debbugs.gnu.org; 14 Feb 2021 09:33:24 +0000 Received: from localhost ([127.0.0.1]:35435 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lBDmN-0006aF-WD for submit@debbugs.gnu.org; Sun, 14 Feb 2021 04:33:24 -0500 Received: from lists.gnu.org ([209.51.188.17]:53468) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lBDmM-0006a7-8a for submit@debbugs.gnu.org; Sun, 14 Feb 2021 04:33:23 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45458) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lBDmM-0004tK-1a for guix-patches@gnu.org; Sun, 14 Feb 2021 04:33:22 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]:36061) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lBDmL-0001YL-Qw for guix-patches@gnu.org; Sun, 14 Feb 2021 04:33:21 -0500 Received: from [2a01:e0a:19b:d9a0:ed4f:d6a:d2d6:56bd] (port=48732 helo=localhost.localdomain) by fencepost.gnu.org with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1lBDmK-0000rW-Qr; Sun, 14 Feb 2021 04:33:21 -0500 From: Mathieu Othacehe Date: Sun, 14 Feb 2021 10:33:01 +0100 Message-Id: <20210214093301.348381-1-othacehe@gnu.org> X-Mailer: git-send-email 2.30.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: 2.14 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of guix-patches-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-patches-bounces@gnu.org X-Migadu-Queue-Id: 33808227E6 X-Spam-Score: 2.14 X-Migadu-Scanner: scn1.migadu.com X-TUID: USyL1518JBzJ * gnu/services/vpn.scm (wireguard-peer, wireguard-configuration): New records. (wireguard-service-type): New variable. * doc/guix.texi (VPN Services): Document it. --- doc/guix.texi | 78 +++++++++++++++++++++- gnu/services/vpn.scm | 152 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 226 insertions(+), 4 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 68abb968b0..03ad7b0357 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -26243,9 +26243,12 @@ Defaults to @samp{()}. @cindex virtual private network (VPN) The @code{(gnu services vpn)} module provides services related to -@dfn{virtual private networks} (VPNs). It provides a @emph{client} service for -your machine to connect to a VPN, and a @emph{server} service for your machine -to host a VPN@. Both services use @uref{https://openvpn.net/, OpenVPN}. +@dfn{virtual private networks} (VPNs). + +@subsubheading OpenVPN + +It provides a @emph{client} service for your machine to connect to a +VPN, and a @emph{server} service for your machine to host a VPN@. @deffn {Scheme Procedure} openvpn-client-service @ [#:config (openvpn-client-configuration)] @@ -26624,6 +26627,75 @@ Defaults to @samp{#f}. @c %end of automatic openvpn-server documentation +@subsubheading Wireguard + +@defvr {Scheme Variable} wireguard-service-type +A service type for a Wireguard tunnel interface. Its value must be a +@code{wireguard-configuration} record as in this example: + +@lisp +(service wireguard-service-type + (wireguard-configuration + (peers + (list + (wireguard-peer + (name "my-peer") + (endpoint "my.wireguard.com:51820") + (public-key "hzpKg9X1yqu1axN6iJp0mWf6BZGo8m1wteKwtTmDGF4=") + (allowed-ips '("10.0.0.2/32"))))))) +@end lisp + +@end defvr + +@deftp {Data Type} wireguard-configuration +Data type representing the configuration of the Wireguard service. + +@table @asis +@item @code{wireguard} +The wireguard package to use for this service. + +@item @code{interface} (default: @code{"wg0"}) +The interface name for the VPN. + +@item @code{address} (default: @code{"10.0.0.1/32"}) +The address to be assigned to the above interface. + +@item @code{public-key} (default: @code{"/etc/wireguard/public.key"}) +The public key file for the interface. It is automatically generated +from the private key file below if it does not exit. + +@item @code{private-key} (default: @code{"/etc/wireguard/private.key"}) +The private key file for the interface. It is automatically generated if +the file does not exist. + +@item @code{peers} (default: @code{'()}) +The authorized peers on this interface. This is a list of +@var{wireguard-peer} records. + +@end table +@end deftp + +@deftp {Data Type} wireguard-peer +Data type representing a Wireguard peer attached to a given interface. + +@table @asis +@item @code{name} +The peer name. + +@item @code{endpoint} (default: @code{#f}) +The optional endpoint for the peer, such as +@code{"demo.wireguard.com:51820"}. + +@item @code{public-key} +The peer public-key represented as a base64 string. + +@item @code{allowed-ips} +A list of IP addresses with CIDR masks from which incoming traffic for +this peer is allowed and to which incoming traffic for this peer is +directed. + +@end table +@end deftp @node Network File System @subsection Network File System diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm index 70f2617c7e..51cdf595a5 100644 --- a/gnu/services/vpn.scm +++ b/gnu/services/vpn.scm @@ -40,7 +40,26 @@ openvpn-remote-configuration openvpn-ccd-configuration generate-openvpn-client-documentation - generate-openvpn-server-documentation)) + generate-openvpn-server-documentation + + wireguard-peer + wireguard-peer? + wireguard-peer-name + wireguard-peer-endpoint + wireguard-peer-public-key + wireguard-peer-allowed-ips + + wireguard-configuration + wireguard-configuration? + wireguard-configuration-wireguard + wireguard-configuration-interface + wireguard-configuration-address + wireguard-configuration-port + wireguard-configuration-public-key + wireguard-configuration-private-key + wireguard-configuration-peers + + wireguard-service-type)) ;;; ;;; OpenVPN. @@ -507,3 +526,134 @@ is truncated and rewritten every minute.") (remote openvpn-remote-configuration)) (openvpn-remote-configuration ,openvpn-remote-configuration-fields)) 'openvpn-client-configuration)) + + +;;; +;;; Wireguard. +;;; + +(define-record-type* + wireguard-peer make-wireguard-peer + wireguard-peer? + (name wireguard-peer-name) + (endpoint wireguard-peer-endpoint + (default #f)) ;string + (public-key wireguard-peer-public-key) ;string + (allowed-ips wireguard-peer-allowed-ips)) ;list of strings + +(define-record-type* + wireguard-configuration make-wireguard-configuration + wireguard-configuration? + (wireguard wireguard-configuration-wireguard ; + (default wireguard-tools)) + (interface wireguard-configuration-interface ;string + (default "wg0")) + (address wireguard-configuration-address ;string + (default "10.0.0.1/32")) + (port wireguard-configuration-port ;integer + (default 51820)) + (public-key wireguard-configuration-public-key ;string + (default "/etc/wireguard/public.key")) + (private-key wireguard-configuration-private-key ;string + (default "/etc/wireguard/private.key")) + (peers wireguard-configuration-peers ;list of + (default '()))) + +(define (wireguard-configuration-file config) + (define (peer->config peer) + (let ((name (wireguard-peer-name peer)) + (public-key (wireguard-peer-public-key peer)) + (endpoint (wireguard-peer-endpoint peer)) + (allowed-ips (wireguard-peer-allowed-ips peer))) + (format #f "[Peer] #~a +PublicKey = ~a +AllowedIPs = ~a +~a" + name + public-key + (string-join allowed-ips ",") + (if endpoint + (format #f "Endpoint = ~a\n" endpoint) + "\n")))) + + (match-record config + (wireguard interface address port private-key peers) + (let* ((config-file (string-append interface ".conf")) + (peers (map peer->config peers)) + (config + (computed-file + "wireguard-config" + #~(begin + (mkdir #$output) + (chdir #$output) + (call-with-output-file #$config-file + (lambda (port) + (let ((format (@ (ice-9 format) format))) + (format port "[Interface] +Address = ~a +PostUp = ~a set %i private-key ~a +~a +~{~a~^~%~}" + #$address + #$(file-append wireguard "/bin/wg") + #$private-key + #$(if port + (format #f "ListenPort = ~a" port) + "") + (list #$@peers))))))))) + (file-append config "/" config-file)))) + +(define (wireguard-activation config) + (match-record config + (public-key private-key) + #~(begin + (use-modules (guix build utils) + (ice-9 popen) + (ice-9 rdelim)) + (mkdir-p (dirname #$private-key)) + (unless (file-exists? #$private-key) + (let* ((pipe + (open-input-pipe (string-append + #$(file-append wireguard-tools "/bin/wg") + " genkey"))) + (key (read-line pipe))) + (call-with-output-file #$private-key + (lambda (port) + (display key port))) + (chmod #$private-key #o400) + (close-pipe pipe))) + + (mkdir-p (dirname #$public-key)) + (unless (file-exists? #$public-key) + (let* ((pipe + (open-input-pipe (string-append + #$(file-append wireguard-tools "/bin/wg") + " genkey < " #$private-key))) + (key (read-line pipe))) + (call-with-output-file #$public-key + (lambda (port) + (display key port))) + (close-pipe pipe)))))) + +(define (wireguard-shepherd-service config) + (match-record config + (wireguard) + (let ((wg-quick (file-append wireguard "/bin/wg-quick")) + (config (wireguard-configuration-file config))) + (list (shepherd-service + (requirement '(networking)) + (provision '(wireguard)) + (start #~(lambda _ + (invoke #$wg-quick "up" #$config))) + (stop #~(lambda _ + (invoke #$wg-quick "down" #$config))) + (documentation "Run the Wireguard VPN tunnel")))))) + +(define wireguard-service-type + (service-type + (name 'wireguard) + (extensions + (list (service-extension shepherd-root-service-type + wireguard-shepherd-service) + (service-extension activation-service-type + wireguard-activation))))) -- 2.30.0