diff options
author | Dominique Martinet @ jormungand <asmadeus@codewreck.org> | 2020-10-01 14:52:33 +0200 |
---|---|---|
committer | Dominique Martinet @ jormungand <asmadeus@codewreck.org> | 2020-10-01 14:52:33 +0200 |
commit | 4a3b908371c2695734e4b846f1c2f0805fdbf4f2 (patch) | |
tree | 73abaa6101a3450cb9a0a8358363480151211bd6 | |
parent | ca37da39dc71295beda370e6dc9b071addc9d3fd (diff) |
jormungand: add bitlbee with pantalaimon & stunnel
-rw-r--r-- | machines/jormungand/configuration.nix | 1 | ||||
-rw-r--r-- | modules/services/stunnel.nix | 234 | ||||
-rw-r--r-- | pkgs/default.nix | 11 | ||||
-rw-r--r-- | profiles/bitlbee.nix | 89 | ||||
-rw-r--r-- | profiles/common.nix | 3 |
5 files changed, 338 insertions, 0 deletions
diff --git a/machines/jormungand/configuration.nix b/machines/jormungand/configuration.nix index 6fb1e2f..4a5a794 100644 --- a/machines/jormungand/configuration.nix +++ b/machines/jormungand/configuration.nix @@ -16,6 +16,7 @@ ./matrix.nix ./mpd.nix ./nginx.nix + ../../profiles/bitlbee.nix ]; # disable documentation to save some time diff --git a/modules/services/stunnel.nix b/modules/services/stunnel.nix new file mode 100644 index 0000000..9dabcc5 --- /dev/null +++ b/modules/services/stunnel.nix @@ -0,0 +1,234 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.stunnel; + yesNo = val: if val then "yes" else "no"; + + verifyChainPathAssert = n: c: { + assertion = c.verifyHostname == null || (c.verifyChain || c.verifyPeer); + message = "stunnel: \"${n}\" client configuration - hostname verification " + + "is not possible without either verifyChain or verifyPeer enabled"; + }; + + serverConfig = { + options = { + accept = mkOption { + type = types.either types.str types.int; + description = "On which [host:]port stunnel should listen for incoming TLS connections."; + }; + + connect = mkOption { + type = types.int; + description = "To which port the decrypted connection should be forwarded."; + }; + + cert = mkOption { + type = types.path; + description = "File containing both the private and public keys."; + }; + }; + }; + + clientConfig = { + options = { + accept = mkOption { + type = types.str; + description = "IP:Port on which connections should be accepted."; + }; + + connect = mkOption { + type = types.str; + description = "IP:Port destination to connect to."; + }; + + verifyChain = mkOption { + type = types.bool; + default = true; + description = "Check if the provided certificate has a valid certificate chain (against CAPath)."; + }; + + verifyPeer = mkOption { + type = types.bool; + default = false; + description = "Check if the provided certificate is contained in CAPath."; + }; + + CAPath = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to a directory containing certificates to validate against."; + }; + + CAFile = mkOption { + type = types.nullOr types.path; + default = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; + description = "Path to a file containing certificates to validate against."; + }; + + verifyHostname = mkOption { + type = with types; nullOr str; + default = null; + description = "If set, stunnel checks if the provided certificate is valid for the given hostname."; + }; + }; + }; + + +in + +{ + + ###### interface + + options = { + + services.stunnel = { + + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the stunnel TLS tunneling service."; + }; + + user = mkOption { + type = with types; nullOr str; + default = "nobody"; + description = "The user under which stunnel runs."; + }; + + group = mkOption { + type = with types; nullOr str; + default = "nogroup"; + description = "The group under which stunnel runs."; + }; + + logLevel = mkOption { + type = types.enum [ "emerg" "alert" "crit" "err" "warning" "notice" "info" "debug" ]; + default = "info"; + description = "Verbosity of stunnel output."; + }; + + fipsMode = mkOption { + type = types.bool; + default = false; + description = "Enable FIPS 140-2 mode required for compliance."; + }; + + enableInsecureSSLv3 = mkOption { + type = types.bool; + default = false; + description = "Enable support for the insecure SSLv3 protocol."; + }; + + + servers = mkOption { + description = "Define the server configuations."; + type = with types; attrsOf (submodule serverConfig); + example = { + fancyWebserver = { + enable = true; + accept = 443; + connect = 8080; + cert = "/path/to/pem/file"; + }; + }; + default = { }; + }; + + clients = mkOption { + description = "Define the client configurations."; + type = with types; attrsOf (submodule clientConfig); + example = { + foobar = { + accept = "0.0.0.0:8080"; + connect = "nixos.org:443"; + verifyChain = false; + }; + }; + default = { }; + }; + }; + }; + + + ###### implementation + + config = mkIf cfg.enable { + + assertions = concatLists [ + (singleton { + assertion = (length (attrValues cfg.servers) != 0) || ((length (attrValues cfg.clients)) != 0); + message = "stunnel: At least one server- or client-configuration has to be present."; + }) + + (mapAttrsToList verifyChainPathAssert cfg.clients) + ]; + + environment.systemPackages = [ pkgs.stunnel ]; + + environment.etc."stunnel.cfg".text = '' + ${ if cfg.user != null then "setuid = ${cfg.user}" else "" } + ${ if cfg.group != null then "setgid = ${cfg.group}" else "" } + + debug = ${cfg.logLevel} + + ${ optionalString cfg.fipsMode "fips = yes" } + ${ optionalString cfg.enableInsecureSSLv3 "options = -NO_SSLv3" } + + ; ----- SERVER CONFIGURATIONS ----- + ${ lib.concatStringsSep "\n" + (lib.mapAttrsToList + (n: v: '' + [${n}] + accept = ${toString v.accept} + connect = ${toString v.connect} + cert = ${v.cert} + + '') + cfg.servers) + } + + ; ----- CLIENT CONFIGURATIONS ----- + ${ lib.concatStringsSep "\n" + (lib.mapAttrsToList + (n: v: '' + [${n}] + client = yes + accept = ${v.accept} + connect = ${v.connect} + verifyChain = ${yesNo v.verifyChain} + verifyPeer = ${yesNo v.verifyPeer} + ${optionalString (v.CAPath != null) "CApath = ${v.CAPath}"} + ${optionalString (v.CAFile != null) "CAFile = ${v.CAFile}"} + ${optionalString (v.verifyHostname != null) "checkHost = ${v.verifyHostname}"} + OCSPaia = yes + + '') + cfg.clients) + } + ''; + + systemd.services.stunnel = { + description = "stunnel TLS tunneling service"; + after = [ "network.target" ]; + wants = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + restartTriggers = [ config.environment.etc."stunnel.cfg".source ]; + serviceConfig = { + ExecStart = "${pkgs.stunnel}/bin/stunnel ${config.environment.etc."stunnel.cfg".source}"; + Type = "forking"; + }; + }; + + meta.maintainers = with maintainers; [ + # Server side + lschuermann + # Client side + das_j + ]; + }; + +} diff --git a/pkgs/default.nix b/pkgs/default.nix index 5e48de4..b8e8190 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -34,6 +34,17 @@ self: super: { ganesha = super.callPackage ./ganesha { }; + purple-matrix = super.purple-matrix.overrideAttrs (oldAttrs: rec { + version = "2020-09-28"; + + src = super.fetchFromGitHub { + owner = "matrix-org"; + repo = "purple-matrix"; + rev = "1d23385e6c22f63591fcbfc85c09999953c388ed"; + sha256 = "18ghdhn7m3jzp5zgyggip70icdn01wdvkin8vm915v79jc0xcxh7"; + }; + }); + robinhood-v3 = super.callPackage ./robinhood-v3 { }; robinhood = super.callPackage ./robinhood { }; diff --git a/profiles/bitlbee.nix b/profiles/bitlbee.nix new file mode 100644 index 0000000..0b3f39f --- /dev/null +++ b/profiles/bitlbee.nix @@ -0,0 +1,89 @@ +{ config, pkgs, ... }: + +let + + pantalaimonConf = pkgs.writeText "pantalaimon.conf" '' + [Default] + Notifications = Off + LogLevel = debug + + [codewreck] + Homeserver = http://[::1]:8008 + ListenPort = 8009 + SSL = False + UseKeyring = False + ''; + +in { + + services.bitlbee = { + enable = true; + portNumber = 16667; + libpurple_plugins = [ pkgs.purple-matrix ]; + }; + systemd.services.bitlbee = { + serviceConfig.BindPaths = [ "/var/lib/bitlbee" ]; + serviceConfig.BindReadOnlyPaths = [ + "/dev/urandom" + "/dev/log" + ]; + confinement = { + enable = true; + binSh = null; + mode = "chroot-only"; + packages = [ pkgs.purple-matrix ]; + }; + }; + + # matrix proxy + systemd.services.pantalaimon = { + description = "matrix E2EE proxy"; + serviceConfig = { + Type = "simple"; + User = "asmadeus"; + BindPaths = [ "/home/asmadeus/.local/share/pantalaimon" ]; + BindReadOnlyPaths = [ + "/run/user/1000/bus" "/etc/machine-id" + "/etc/passwd" "/etc/group" + ]; + Environment = "XDG_RUNTIME_DIR=/run/user/1000"; + ExecStart = "${pkgs.pantalaimon}/bin/pantalaimon --config ${pantalaimonConf}"; + Restart = "always"; + NoNewPrivileges = "yes"; + }; + wantedBy = [ "default.target" ]; + confinement = { + enable = true; + binSh = null; + mode = "chroot-only"; + }; + }; + # for panctl + environment.systemPackages = with pkgs; [ pantalaimon ]; + + # ssl front to bitlbee + services.stunnel = { + enable = true; + servers = { + bitlbee = { + accept = ":::16697"; + connect = 16667; + cert = "/var/lib/acme/jormungand.codewreck.org/full.pem"; + }; + }; + }; + systemd.services.stunnel = { + serviceConfig.BindReadOnlyPaths = [ + "/var/lib/acme/jormungand.codewreck.org/full.pem" + "/dev/null" "/etc/passwd" "/etc/group" + ]; + confinement = { + enable = true; + binSh = null; + mode = "chroot-only"; + }; + }; + networking.firewall.extraCommands = '' + ip6tables -A nixos-fw -p tcp -m tcp --dport 16697 -s 2001:41d0:1:7a93::1 -j ACCEPT + ''; +} diff --git a/profiles/common.nix b/profiles/common.nix index 55bca1e..07a6c61 100644 --- a/profiles/common.nix +++ b/profiles/common.nix @@ -22,6 +22,9 @@ in { imports = findFiles ".*\\.nix" ../modules ++ [ ./hardened.nix ]; + disabledModules = [ + "services/networking/stunnel.nix" + ]; # less locales supported i18n.supportedLocales = [ "en_US.UTF-8/UTF-8" ]; |