summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominique Martinet @ jormungand <asmadeus@codewreck.org>2020-10-01 14:52:33 +0200
committerDominique Martinet @ jormungand <asmadeus@codewreck.org>2020-10-01 14:52:33 +0200
commit4a3b908371c2695734e4b846f1c2f0805fdbf4f2 (patch)
tree73abaa6101a3450cb9a0a8358363480151211bd6
parentca37da39dc71295beda370e6dc9b071addc9d3fd (diff)
jormungand: add bitlbee with pantalaimon & stunnel
-rw-r--r--machines/jormungand/configuration.nix1
-rw-r--r--modules/services/stunnel.nix234
-rw-r--r--pkgs/default.nix11
-rw-r--r--profiles/bitlbee.nix89
-rw-r--r--profiles/common.nix3
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" ];