diff options
| author | Domagoj Stolfa <ds815@gmx.com> | 2021-06-13 16:08:53 +0100 |
|---|---|---|
| committer | Tobias Geerinckx-Rice <me@tobias.gr> | 2021-06-25 00:39:32 +0200 |
| commit | 66be80fabb9af0a570aee4c2e96886267a613e8e (patch) | |
| tree | e56be781fd031d24d3da987f06f9977ceb1317b8 | |
| parent | 1baaf599a4000451a54dcf30098a998f1b5bc70f (diff) | |
gnu: Add strongswan service.
* gnu/services/vpn.scm (<strongswan-configuration>): New record type.
(charon-plugins, strongswan-configuration-file)
(strongswan-shepherd-service, strongswan-service-type): New variables.
* doc/guix.tex (VPN Services): Document them all.
| -rw-r--r-- | doc/guix.texi | 39 | ||||
| -rw-r--r-- | gnu/services/vpn.scm | 140 |
2 files changed, 178 insertions, 1 deletions
diff --git a/doc/guix.texi b/doc/guix.texi index 560d7af83f2..4456f9a0555 100644 --- a/doc/guix.texi +++ b/doc/guix.texi | |||
| @@ -92,6 +92,7 @@ Copyright @copyright{} 2021 Maxime Devos@* | |||
| 92 | Copyright @copyright{} 2021 B. Wilson@* | 92 | Copyright @copyright{} 2021 B. Wilson@* |
| 93 | Copyright @copyright{} 2021 Xinglu Chen@* | 93 | Copyright @copyright{} 2021 Xinglu Chen@* |
| 94 | Copyright @copyright{} 2021 Raghav Gururajan@* | 94 | Copyright @copyright{} 2021 Raghav Gururajan@* |
| 95 | Copyright @copyright{} 2021 Domagoj Stolfa@* | ||
| 95 | 96 | ||
| 96 | Permission is granted to copy, distribute and/or modify this document | 97 | Permission is granted to copy, distribute and/or modify this document |
| 97 | under the terms of the GNU Free Documentation License, Version 1.3 or | 98 | under the terms of the GNU Free Documentation License, Version 1.3 or |
| @@ -27107,9 +27108,45 @@ Defaults to @samp{#f}. | |||
| 27107 | 27108 | ||
| 27108 | @end deftypevr | 27109 | @end deftypevr |
| 27109 | 27110 | ||
| 27110 | |||
| 27111 | @c %end of automatic openvpn-server documentation | 27111 | @c %end of automatic openvpn-server documentation |
| 27112 | 27112 | ||
| 27113 | @subheading strongSwan | ||
| 27114 | |||
| 27115 | Currently, the strongSwan service only provides legacy-style configuration with | ||
| 27116 | @file{ipsec.conf} and @file{ipsec.secrets} files. | ||
| 27117 | |||
| 27118 | @defvr {Scheme Variable} strongswan-service-type | ||
| 27119 | A service type for configuring strongSwan for IPsec @acronym{VPN, | ||
| 27120 | Virtual Private Networking}. Its value must be a | ||
| 27121 | @code{strongswan-configuration} record as in this example: | ||
| 27122 | |||
| 27123 | @lisp | ||
| 27124 | (service strongswan-service-type | ||
| 27125 | (strongswan-configuration | ||
| 27126 | (ipsec-conf "/etc/ipsec.conf") | ||
| 27127 | (ipsec-secrets "/etc/ipsec.secrets"))) | ||
| 27128 | @end lisp | ||
| 27129 | |||
| 27130 | @end defvr | ||
| 27131 | |||
| 27132 | @deftp {Data Type} strongswan-configuration | ||
| 27133 | Data type representing the configuration of the StrongSwan service. | ||
| 27134 | |||
| 27135 | @table @asis | ||
| 27136 | @item @code{strongswan} | ||
| 27137 | The strongSwan package to use for this service. | ||
| 27138 | |||
| 27139 | @item @code{ipsec-conf} (default: @code{#f}) | ||
| 27140 | The file name of your @file{ipsec.conf}. If not @code{#f}, then this and | ||
| 27141 | @code{ipsec-secrets} must both be strings. | ||
| 27142 | |||
| 27143 | @item @code{ipsec-secrets} (default @code{#f}) | ||
| 27144 | The file name of your @file{ipsec.secrets}. If not @code{#f}, then this and | ||
| 27145 | @code{ipsec-conf} must both be strings. | ||
| 27146 | |||
| 27147 | @end table | ||
| 27148 | @end deftp | ||
| 27149 | |||
| 27113 | @subsubheading Wireguard | 27150 | @subsubheading Wireguard |
| 27114 | 27151 | ||
| 27115 | @defvr {Scheme Variable} wireguard-service-type | 27152 | @defvr {Scheme Variable} wireguard-service-type |
diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm index 2bcbf767279..6804e3ff9cd 100644 --- a/gnu/services/vpn.scm +++ b/gnu/services/vpn.scm | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com> | 4 | ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com> |
| 5 | ;;; Copyright © 2021 Guillaume Le Vaillant <glv@posteo.net> | 5 | ;;; Copyright © 2021 Guillaume Le Vaillant <glv@posteo.net> |
| 6 | ;;; Copyright © 2021 Solene Rapenne <solene@perso.pw> | 6 | ;;; Copyright © 2021 Solene Rapenne <solene@perso.pw> |
| 7 | ;;; Copyright © 2021 Domagoj Stolfa <ds815@gmx.com> | ||
| 8 | ;;; Copyright © 2021 Tobias Geerinckx-Rice <me@tobias.gr> | ||
| 7 | ;;; | 9 | ;;; |
| 8 | ;;; This file is part of GNU Guix. | 10 | ;;; This file is part of GNU Guix. |
| 9 | ;;; | 11 | ;;; |
| @@ -26,10 +28,13 @@ | |||
| 26 | #:use-module (gnu services shepherd) | 28 | #:use-module (gnu services shepherd) |
| 27 | #:use-module (gnu system shadow) | 29 | #:use-module (gnu system shadow) |
| 28 | #:use-module (gnu packages admin) | 30 | #:use-module (gnu packages admin) |
| 31 | #:use-module (gnu packages networking) | ||
| 29 | #:use-module (gnu packages vpn) | 32 | #:use-module (gnu packages vpn) |
| 30 | #:use-module (guix packages) | 33 | #:use-module (guix packages) |
| 31 | #:use-module (guix records) | 34 | #:use-module (guix records) |
| 32 | #:use-module (guix gexp) | 35 | #:use-module (guix gexp) |
| 36 | #:use-module (guix i18n) | ||
| 37 | #:use-module (guix utils) | ||
| 33 | #:use-module (srfi srfi-1) | 38 | #:use-module (srfi srfi-1) |
| 34 | #:use-module (ice-9 match) | 39 | #:use-module (ice-9 match) |
| 35 | #:use-module (ice-9 regex) | 40 | #:use-module (ice-9 regex) |
| @@ -44,6 +49,9 @@ | |||
| 44 | generate-openvpn-client-documentation | 49 | generate-openvpn-client-documentation |
| 45 | generate-openvpn-server-documentation | 50 | generate-openvpn-server-documentation |
| 46 | 51 | ||
| 52 | strongswan-configuration | ||
| 53 | strongswan-service-type | ||
| 54 | |||
| 47 | wireguard-peer | 55 | wireguard-peer |
| 48 | wireguard-peer? | 56 | wireguard-peer? |
| 49 | wireguard-peer-name | 57 | wireguard-peer-name |
| @@ -530,6 +538,138 @@ is truncated and rewritten every minute.") | |||
| 530 | 'openvpn-client-configuration)) | 538 | 'openvpn-client-configuration)) |
| 531 | 539 | ||
| 532 | ;;; | 540 | ;;; |
| 541 | ;;; Strongswan. | ||
| 542 | ;;; | ||
| 543 | |||
| 544 | (define-record-type* <strongswan-configuration> | ||
| 545 | strongswan-configuration make-strongswan-configuration | ||
| 546 | strongswan-configuration? | ||
| 547 | (strongswan strongswan-configuration-strongswan ;<package> | ||
| 548 | (default strongswan)) | ||
| 549 | (ipsec-conf strongswan-configuration-ipsec-conf ;string|#f | ||
| 550 | (default #f)) | ||
| 551 | (ipsec-secrets strongswan-configuration-ipsec-secrets ;string|#f | ||
| 552 | (default #f))) | ||
| 553 | |||
| 554 | ;; In the future, it might be worth implementing a record type to configure | ||
| 555 | ;; all of the plugins, but for *most* basic use cases, simply creating the | ||
| 556 | ;; files will be sufficient. Same is true of charon-plugins. | ||
| 557 | (define strongswand-configuration-files | ||
| 558 | (list "charon" "charon-logging" "pki" "pool" "scepclient" | ||
| 559 | "swanctl" "tnc")) | ||
| 560 | |||
| 561 | ;; Plugins to load. All of these plugins end up as configuration files in | ||
| 562 | ;; strongswan.d/charon/. | ||
| 563 | (define charon-plugins | ||
| 564 | (list "aes" "aesni" "attr" "attr-sql" "chapoly" "cmac" "constraints" | ||
| 565 | "counters" "curl" "curve25519" "dhcp" "dnskey" "drbg" "eap-aka-3gpp" | ||
| 566 | "eap-aka" "eap-dynamic" "eap-identity" "eap-md5" "eap-mschapv2" | ||
| 567 | "eap-peap" "eap-radius" "eap-simaka-pseudonym" "eap-simaka-reauth" | ||
| 568 | "eap-simaka-sql" "eap-sim" "eap-sim-file" "eap-tls" "eap-tnc" | ||
| 569 | "eap-ttls" "ext-auth" "farp" "fips-prf" "gmp" "ha" "hmac" | ||
| 570 | "kernel-netlink" "led" "md4" "md5" "mgf1" "nonce" "openssl" "pem" | ||
| 571 | "pgp" "pkcs12" "pkcs1" "pkcs7" "pkcs8" "pubkey" "random" "rc2" | ||
| 572 | "resolve" "revocation" "sha1" "sha2" "socket-default" "soup" "sql" | ||
| 573 | "sqlite" "sshkey" "tnc-tnccs" "vici" "x509" "xauth-eap" "xauth-generic" | ||
| 574 | "xauth-noauth" "xauth-pam" "xcbc")) | ||
| 575 | |||
| 576 | (define (strongswan-configuration-file config) | ||
| 577 | (match-record config <strongswan-configuration> | ||
| 578 | (strongswan ipsec-conf ipsec-secrets) | ||
| 579 | (if (eq? (string? ipsec-conf) (string? ipsec-secrets)) | ||
| 580 | (let* ((strongswan-dir | ||
| 581 | (computed-file | ||
| 582 | "strongswan.d" | ||
| 583 | #~(begin | ||
| 584 | (mkdir #$output) | ||
| 585 | ;; Create all of the configuration files strongswan.d/. | ||
| 586 | (map (lambda (conf-file) | ||
| 587 | (let* ((filename (string-append | ||
| 588 | #$output "/" | ||
| 589 | conf-file ".conf"))) | ||
| 590 | (call-with-output-file filename | ||
| 591 | (lambda (port) | ||
| 592 | (display | ||
| 593 | "# Created by 'strongswan-service'\n" | ||
| 594 | port))))) | ||
| 595 | (list #$@strongswand-configuration-files)) | ||
| 596 | (mkdir (string-append #$output "/charon")) | ||
| 597 | ;; Create all of the plugin configuration files. | ||
| 598 | (map (lambda (plugin) | ||
| 599 | (let* ((filename (string-append | ||
| 600 | #$output "/charon/" | ||
| 601 | plugin ".conf"))) | ||
| 602 | (call-with-output-file filename | ||
| 603 | (lambda (port) | ||
| 604 | (format port "~a { | ||
| 605 | load = yes | ||
| 606 | }" | ||
| 607 | plugin))))) | ||
| 608 | (list #$@charon-plugins)))))) | ||
| 609 | ;; Generate our strongswan.conf to reflect the user configuration. | ||
| 610 | (computed-file | ||
| 611 | "strongswan.conf" | ||
| 612 | #~(begin | ||
| 613 | (call-with-output-file #$output | ||
| 614 | (lambda (port) | ||
| 615 | (display "# Generated by 'strongswan-service'.\n" port) | ||
| 616 | (format port "charon { | ||
| 617 | load_modular = yes | ||
| 618 | plugins { | ||
| 619 | include ~a/charon/*.conf" | ||
| 620 | #$strongswan-dir) | ||
| 621 | (if #$ipsec-conf | ||
| 622 | (format port " | ||
| 623 | stroke { | ||
| 624 | load = yes | ||
| 625 | secrets_file = ~a | ||
| 626 | } | ||
| 627 | } | ||
| 628 | } | ||
| 629 | |||
| 630 | starter { | ||
| 631 | config_file = ~a | ||
| 632 | } | ||
| 633 | |||
| 634 | include ~a/*.conf" | ||
| 635 | #$ipsec-secrets | ||
| 636 | #$ipsec-conf | ||
| 637 | #$strongswan-dir) | ||
| 638 | (format port " | ||
| 639 | } | ||
| 640 | } | ||
| 641 | include ~a/*.conf" | ||
| 642 | #$strongswan-dir))))))) | ||
| 643 | (throw 'error | ||
| 644 | (G_ "strongSwan ipsec-conf and ipsec-secrets must both be (un)set"))))) | ||
| 645 | |||
| 646 | (define (strongswan-shepherd-service config) | ||
| 647 | (let* ((ipsec (file-append strongswan "/sbin/ipsec")) | ||
| 648 | (strongswan-conf-path (strongswan-configuration-file config))) | ||
| 649 | (list (shepherd-service | ||
| 650 | (requirement '(networking)) | ||
| 651 | (provision '(ipsec)) | ||
| 652 | (start #~(make-forkexec-constructor | ||
| 653 | (list #$ipsec "start" "--nofork") | ||
| 654 | #:environment-variables | ||
| 655 | (list (string-append "STRONGSWAN_CONF=" | ||
| 656 | #$strongswan-conf-path)))) | ||
| 657 | (stop #~(make-kill-destructor)) | ||
| 658 | (documentation | ||
| 659 | "strongSwan's charon IKE keying daemon for IPsec VPN."))))) | ||
| 660 | |||
| 661 | (define strongswan-service-type | ||
| 662 | (service-type | ||
| 663 | (name 'strongswan) | ||
| 664 | (extensions | ||
| 665 | (list (service-extension shepherd-root-service-type | ||
| 666 | strongswan-shepherd-service))) | ||
| 667 | (default-value (strongswan-configuration)) | ||
| 668 | (description | ||
| 669 | "Connect to an IPsec @acronym{VPN, Virtual Private Network} with | ||
| 670 | strongSwan."))) | ||
| 671 | |||
| 672 | ;;; | ||
| 533 | ;;; Wireguard. | 673 | ;;; Wireguard. |
| 534 | ;;; | 674 | ;;; |
| 535 | 675 | ||
