From a089d65d256d718757dbd15a25f6965562d1b73e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 27 Apr 2019 19:21:45 +0000 Subject: [PATCH 1/7] Move service hardening flags into separate file --- modules/bitcoind.nix | 12 +++--------- modules/clightning.nix | 8 ++------ modules/electrs.nix | 7 ++----- modules/lightning-charge.nix | 7 ++----- modules/liquid.nix | 10 ++-------- modules/nanopos.nix | 7 ++----- modules/nix-bitcoin-services.nix | 12 ++++++++++++ modules/nix-bitcoin-webindex.nix | 3 ++- modules/onion-chef.nix | 7 ++----- modules/recurring-donations.nix | 7 ++----- modules/spark-wallet.nix | 7 ++----- 11 files changed, 33 insertions(+), 54 deletions(-) create mode 100644 modules/nix-bitcoin-services.nix diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index bf44035..ded8ce4 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -3,6 +3,7 @@ with lib; let + nix-bitcoin-services = import ./nix-bitcoin-services.nix; cfg = config.services.bitcoind; pidFile = "${cfg.dataDir}/bitcoind.pid"; configFile = pkgs.writeText "bitcoin.conf" '' @@ -235,7 +236,7 @@ in { # Permission for preStart PermissionsStartOnly = "true"; - }; + } // nix-bitcoin-services.defaultHardening; }; systemd.services.bitcoind-import-banlist = { description = "Bitcoin daemon banlist importer"; @@ -269,16 +270,9 @@ in { ExecStart = "${pkgs.bash}/bin/bash ${pkgs.banlist}/bin/banlist ${pkgs.altcoins.bitcoind}"; StateDirectory = "bitcoind"; - # Hardening measures - PrivateTmp = "true"; - ProtectSystem = "full"; - NoNewPrivileges = "true"; - PrivateDevices = "true"; - MemoryDenyWriteExecute = "true"; - # Permission for preStart PermissionsStartOnly = "true"; - }; + } // nix-bitcoin-services.defaultHardening; }; users.users.${cfg.user} = { diff --git a/modules/clightning.nix b/modules/clightning.nix index 6d02cb4..10f1b3b 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -3,6 +3,7 @@ with lib; let + nix-bitcoin-services = import ./nix-bitcoin-services.nix; cfg = config.services.clightning; configFile = pkgs.writeText "config" '' autolisten=${if cfg.autolisten then "true" else "false"} @@ -93,12 +94,7 @@ in { User = "clightning"; Restart = "on-failure"; RestartSec = "10s"; - PrivateTmp = "true"; - ProtectSystem = "full"; - NoNewPrivileges = "true"; - PrivateDevices = "true"; - MemoryDenyWriteExecute = "true"; - }; + } // nix-bitcoin-services.defaultHardening; }; }; } diff --git a/modules/electrs.nix b/modules/electrs.nix index bb9795a..bf4b850 100644 --- a/modules/electrs.nix +++ b/modules/electrs.nix @@ -3,6 +3,7 @@ with lib; let + nix-bitcoin-services = import ./nix-bitcoin-services.nix; cfg = config.services.electrs; index-batch-size = "${if cfg.high-memory then "" else "--index-batch-size=10"}"; jsonrpc-import = "${if cfg.high-memory then "" else "--jsonrpc-import"}"; @@ -74,11 +75,7 @@ in { User = "electrs"; Restart = "on-failure"; RestartSec = "10s"; - PrivateTmp = "true"; - ProtectSystem = "full"; - NoNewPrivileges = "true"; - PrivateDevices = "true"; - }; + } // nix-bitcoin-services.defaultHardening; }; services.nginx = { diff --git a/modules/lightning-charge.nix b/modules/lightning-charge.nix index 277d5f3..612c6c9 100644 --- a/modules/lightning-charge.nix +++ b/modules/lightning-charge.nix @@ -3,6 +3,7 @@ with lib; let + nix-bitcoin-services = import ./nix-bitcoin-services.nix; cfg = config.services.lightning-charge; in { options.services.lightning-charge = { @@ -37,11 +38,7 @@ in { User = "clightning"; Restart = "on-failure"; RestartSec = "10s"; - PrivateTmp = "true"; - ProtectSystem = "full"; - NoNewPrivileges = "true"; - PrivateDevices = "true"; - }; + } // nix-bitcoin-services.defaultHardening; }; }; } diff --git a/modules/liquid.nix b/modules/liquid.nix index 7b7bd6b..2112c37 100644 --- a/modules/liquid.nix +++ b/modules/liquid.nix @@ -3,6 +3,7 @@ with lib; let + nix-bitcoin-services = import ./nix-bitcoin-services.nix; cfg = config.services.liquidd; pidFile = "${cfg.dataDir}/liquidd.pid"; configFile = pkgs.writeText "liquid.conf" '' @@ -195,16 +196,9 @@ in { PIDFile = "${pidFile}"; Restart = "on-failure"; - # Hardening measures - PrivateTmp = "true"; - ProtectSystem = "full"; - NoNewPrivileges = "true"; - PrivateDevices = "true"; - MemoryDenyWriteExecute = "true"; - # Permission for preStart PermissionsStartOnly = "true"; - }; + } // nix-bitcoin-services.defaultHardening; }; users.users.${cfg.user} = { name = cfg.user; diff --git a/modules/nanopos.nix b/modules/nanopos.nix index e018182..ef1d356 100644 --- a/modules/nanopos.nix +++ b/modules/nanopos.nix @@ -3,6 +3,7 @@ with lib; let + nix-bitcoin-services = import ./nix-bitcoin-services.nix; cfg = config.services.nanopos; defaultItemsFile = pkgs.writeText "items.yaml" '' tea: @@ -73,11 +74,7 @@ in { User = "nanopos"; Restart = "on-failure"; RestartSec = "10s"; - PrivateTmp = "true"; - ProtectSystem = "full"; - NoNewPrivileges = "true"; - PrivateDevices = "true"; - }; + } // nix-bitcoin-services.defaultHardening; }; }; } diff --git a/modules/nix-bitcoin-services.nix b/modules/nix-bitcoin-services.nix new file mode 100644 index 0000000..c4fac75 --- /dev/null +++ b/modules/nix-bitcoin-services.nix @@ -0,0 +1,12 @@ +{ + defaultHardening = { + PrivateTmp = "true"; + ProtectSystem = "full"; + NoNewPrivileges = "true"; + PrivateDevices = "true"; + MemoryDenyWriteExecute = "true"; + }; +} + + + diff --git a/modules/nix-bitcoin-webindex.nix b/modules/nix-bitcoin-webindex.nix index c8748a4..8cd7e74 100644 --- a/modules/nix-bitcoin-webindex.nix +++ b/modules/nix-bitcoin-webindex.nix @@ -3,6 +3,7 @@ with lib; let + nix-bitcoin-services = import ./nix-bitcoin-services.nix; cfg = config.services.nix-bitcoin-webindex; indexFile = pkgs.writeText "index.html" '' @@ -80,7 +81,7 @@ in { RemainAfterExit="yes"; Restart = "on-failure"; RestartSec = "10s"; - }; + } // nix-bitcoin-services.defaultHardening; }; }; } diff --git a/modules/onion-chef.nix b/modules/onion-chef.nix index 9a71e0b..71628ed 100644 --- a/modules/onion-chef.nix +++ b/modules/onion-chef.nix @@ -8,6 +8,7 @@ with lib; let + nix-bitcoin-services = import ./nix-bitcoin-services.nix; cfg = config.services.onion-chef; dataDir = "/var/lib/onion-chef/"; onion-chef-script = pkgs.writeScript "onion-chef.sh" '' @@ -77,11 +78,7 @@ in { ExecStart = "${pkgs.bash}/bin/bash ${onion-chef-script}"; User = "root"; Type = "oneshot"; - PrivateTmp = "true"; - ProtectSystem = "full"; - NoNewPrivileges = "true"; - PrivateDevices = "true"; - }; + } // nix-bitcoin-services.defaultHardening; }; }; } diff --git a/modules/recurring-donations.nix b/modules/recurring-donations.nix index 00384bc..6d770cf 100644 --- a/modules/recurring-donations.nix +++ b/modules/recurring-donations.nix @@ -3,6 +3,7 @@ with lib; let + nix-bitcoin-services = import ./nix-bitcoin-services.nix; cfg = config.services.recurring-donations; recurring-donations-script = pkgs.writeScript "recurring-donations.sh" '' LNCLI="lightning-cli --lightning-dir=${config.services.clightning.dataDir}" @@ -88,11 +89,7 @@ in { # working inside the shell script User = "clightning"; Type = "oneshot"; - PrivateTmp = "true"; - ProtectSystem = "full"; - NoNewPrivileges = "true"; - PrivateDevices = "true"; - }; + } // nix-bitcoin-services.defaultHardening; }; systemd.timers.recurring-donations = { requires = [ "clightning.service" ]; diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix index d727e16..7ed7a64 100644 --- a/modules/spark-wallet.nix +++ b/modules/spark-wallet.nix @@ -3,6 +3,7 @@ with lib; let + nix-bitcoin-services = import ./nix-bitcoin-services.nix; cfg = config.services.spark-wallet; dataDir = "/var/lib/spark-wallet/"; onion-chef-service = (if cfg.onion-service then [ "onion-chef.service" ] else []); @@ -63,11 +64,7 @@ in { User = "clightning"; Restart = "on-failure"; RestartSec = "10s"; - PrivateTmp = "true"; - ProtectSystem = "full"; - NoNewPrivileges = "true"; - PrivateDevices = "true"; - }; + } // nix-bitcoin-services.defaultHardening; }; }; } From d9533edad16c542fa46d1f2c0018e234d3228453 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 27 Apr 2019 22:27:25 +0000 Subject: [PATCH 2/7] Fix memory deny write execute for nodejs services --- modules/lightning-charge.nix | 2 +- modules/nanopos.nix | 2 +- modules/nix-bitcoin-services.nix | 13 ++++++++++++- modules/spark-wallet.nix | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/modules/lightning-charge.nix b/modules/lightning-charge.nix index 612c6c9..629eb81 100644 --- a/modules/lightning-charge.nix +++ b/modules/lightning-charge.nix @@ -38,7 +38,7 @@ in { User = "clightning"; Restart = "on-failure"; RestartSec = "10s"; - } // nix-bitcoin-services.defaultHardening; + } // nix-bitcoin-services.nodeHardening; }; }; } diff --git a/modules/nanopos.nix b/modules/nanopos.nix index ef1d356..67c872d 100644 --- a/modules/nanopos.nix +++ b/modules/nanopos.nix @@ -74,7 +74,7 @@ in { User = "nanopos"; Restart = "on-failure"; RestartSec = "10s"; - } // nix-bitcoin-services.defaultHardening; + } // nix-bitcoin-services.nodeHardening; }; }; } diff --git a/modules/nix-bitcoin-services.nix b/modules/nix-bitcoin-services.nix index c4fac75..c3150df 100644 --- a/modules/nix-bitcoin-services.nix +++ b/modules/nix-bitcoin-services.nix @@ -1,11 +1,22 @@ -{ +let defaultHardening = { PrivateTmp = "true"; ProtectSystem = "full"; + ProtectHome = "true"; NoNewPrivileges = "true"; PrivateDevices = "true"; MemoryDenyWriteExecute = "true"; + ProtectKernelTunables = "true"; + ProtectKernelModules = "true"; + ProtectControlGroups = "true"; + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; + LockPersonality = "true"; }; +in +{ + inherit defaultHardening; + # node applications apparently rely on memory write execute + nodeHardening = defaultHardening // { MemoryDenyWriteExecute = "false"; }; } diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix index 7ed7a64..817c377 100644 --- a/modules/spark-wallet.nix +++ b/modules/spark-wallet.nix @@ -64,7 +64,7 @@ in { User = "clightning"; Restart = "on-failure"; RestartSec = "10s"; - } // nix-bitcoin-services.defaultHardening; + } // nix-bitcoin-services.nodeHardening; }; }; } From eaaf8e9aab8d559e77f7a2b10090a5cb89a0d703 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 27 Apr 2019 23:53:26 +0000 Subject: [PATCH 3/7] Use IPAddress{Allow,Deny} by default for systemd services --- modules/bitcoind.nix | 12 +++++++++--- modules/clightning.nix | 9 +++++++-- modules/electrs.nix | 9 +++++++-- modules/lightning-charge.nix | 6 ++++-- modules/liquid.nix | 9 +++++++-- modules/nanopos.nix | 6 ++++-- modules/nix-bitcoin-services.nix | 20 +++++++++++++++++++- modules/nix-bitcoin-webindex.nix | 9 +++++++-- modules/nix-bitcoin.nix | 8 +++++++- modules/onion-chef.nix | 2 +- modules/recurring-donations.nix | 5 +++-- modules/spark-wallet.nix | 6 ++++-- 12 files changed, 79 insertions(+), 22 deletions(-) diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index ded8ce4..38f4f7c 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -3,7 +3,7 @@ with lib; let - nix-bitcoin-services = import ./nix-bitcoin-services.nix; + nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { }; cfg = config.services.bitcoind; pidFile = "${cfg.dataDir}/bitcoind.pid"; configFile = pkgs.writeText "bitcoin.conf" '' @@ -193,6 +193,7 @@ in { to stay under the specified target size in MiB) ''; }; + enforceTor = nix-bitcoin-services.enforceTor; }; }; @@ -236,7 +237,11 @@ in { # Permission for preStart PermissionsStartOnly = "true"; - } // nix-bitcoin-services.defaultHardening; + } // nix-bitcoin-services.defaultHardening + // (if cfg.enforceTor + then nix-bitcoin-services.allowTor + else nix-bitcoin-services.allowAnyIP + ); }; systemd.services.bitcoind-import-banlist = { description = "Bitcoin daemon banlist importer"; @@ -272,7 +277,8 @@ in { # Permission for preStart PermissionsStartOnly = "true"; - } // nix-bitcoin-services.defaultHardening; + } // nix-bitcoin-services.defaultHardening + // nix-bitcoin-services.allowTor; }; users.users.${cfg.user} = { diff --git a/modules/clightning.nix b/modules/clightning.nix index 10f1b3b..235be41 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -3,7 +3,7 @@ with lib; let - nix-bitcoin-services = import ./nix-bitcoin-services.nix; + nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { }; cfg = config.services.clightning; configFile = pkgs.writeText "config" '' autolisten=${if cfg.autolisten then "true" else "false"} @@ -57,6 +57,7 @@ in { default = "/var/lib/clightning"; description = "The data directory for clightning."; }; + enforceTor = nix-bitcoin-services.enforceTor; }; config = mkIf cfg.enable { @@ -94,7 +95,11 @@ in { User = "clightning"; Restart = "on-failure"; RestartSec = "10s"; - } // nix-bitcoin-services.defaultHardening; + } // nix-bitcoin-services.defaultHardening + // (if cfg.enforceTor + then nix-bitcoin-services.allowTor + else nix-bitcoin-services.allowAnyIP + ); }; }; } diff --git a/modules/electrs.nix b/modules/electrs.nix index bf4b850..524bbd1 100644 --- a/modules/electrs.nix +++ b/modules/electrs.nix @@ -3,7 +3,7 @@ with lib; let - nix-bitcoin-services = import ./nix-bitcoin-services.nix; + nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { }; cfg = config.services.electrs; index-batch-size = "${if cfg.high-memory then "" else "--index-batch-size=10"}"; jsonrpc-import = "${if cfg.high-memory then "" else "--jsonrpc-import"}"; @@ -43,6 +43,7 @@ in { default = 50003; description = "Override the default port on which to listen for connections."; }; + enforceTor = nix-bitcoin-services.enforceTor; }; config = mkIf cfg.enable { @@ -75,7 +76,11 @@ in { User = "electrs"; Restart = "on-failure"; RestartSec = "10s"; - } // nix-bitcoin-services.defaultHardening; + } // nix-bitcoin-services.defaultHardening + // (if cfg.enforceTor + then nix-bitcoin-services.allowTor + else nix-bitcoin-services.allowAnyIP + ); }; services.nginx = { diff --git a/modules/lightning-charge.nix b/modules/lightning-charge.nix index 629eb81..a6d6b19 100644 --- a/modules/lightning-charge.nix +++ b/modules/lightning-charge.nix @@ -3,7 +3,7 @@ with lib; let - nix-bitcoin-services = import ./nix-bitcoin-services.nix; + nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { }; cfg = config.services.lightning-charge; in { options.services.lightning-charge = { @@ -38,7 +38,9 @@ in { User = "clightning"; Restart = "on-failure"; RestartSec = "10s"; - } // nix-bitcoin-services.nodeHardening; + } // nix-bitcoin-services.defaultHardening + // nix-bitcoin-services.node + // nix-bitcoin-services.allowTor; }; }; } diff --git a/modules/liquid.nix b/modules/liquid.nix index 2112c37..f66b78b 100644 --- a/modules/liquid.nix +++ b/modules/liquid.nix @@ -3,7 +3,7 @@ with lib; let - nix-bitcoin-services = import ./nix-bitcoin-services.nix; + nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { }; cfg = config.services.liquidd; pidFile = "${cfg.dataDir}/liquidd.pid"; configFile = pkgs.writeText "liquid.conf" '' @@ -166,6 +166,7 @@ in { to stay under the specified target size in MiB) ''; }; + enforceTor = nix-bitcoin-services.enforceTor; }; }; @@ -198,7 +199,11 @@ in { # Permission for preStart PermissionsStartOnly = "true"; - } // nix-bitcoin-services.defaultHardening; + } // nix-bitcoin-services.defaultHardening + // (if cfg.enforceTor + then nix-bitcoin-services.allowTor + else nix-bitcoin-services.allowAnyIP + ); }; users.users.${cfg.user} = { name = cfg.user; diff --git a/modules/nanopos.nix b/modules/nanopos.nix index 67c872d..729f65c 100644 --- a/modules/nanopos.nix +++ b/modules/nanopos.nix @@ -3,7 +3,7 @@ with lib; let - nix-bitcoin-services = import ./nix-bitcoin-services.nix; + nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { }; cfg = config.services.nanopos; defaultItemsFile = pkgs.writeText "items.yaml" '' tea: @@ -74,7 +74,9 @@ in { User = "nanopos"; Restart = "on-failure"; RestartSec = "10s"; - } // nix-bitcoin-services.nodeHardening; + } // nix-bitcoin-services.defaultHardening + // nix-bitcoin-services.node + // nix-bitcoin-services.allowTor; }; }; } diff --git a/modules/nix-bitcoin-services.nix b/modules/nix-bitcoin-services.nix index c3150df..9ed5926 100644 --- a/modules/nix-bitcoin-services.nix +++ b/modules/nix-bitcoin-services.nix @@ -1,3 +1,7 @@ +{ config, lib, pkgs, ... }: + +with lib; + let defaultHardening = { PrivateTmp = "true"; @@ -11,12 +15,26 @@ let ProtectControlGroups = "true"; RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; LockPersonality = "true"; + IPAddressDeny = "any"; }; in { inherit defaultHardening; # node applications apparently rely on memory write execute - nodeHardening = defaultHardening // { MemoryDenyWriteExecute = "false"; }; + node = { MemoryDenyWriteExecute = "false"; }; + # Allow tor traffic. Allow takes precedence over Deny. + allowTor = { IPAddressAllow = "127.0.0.1/32"; }; + # Allow any traffic + allowAnyIP = { IPAddressAllow = "any"; }; + + enforceTor = mkOption { + type = types.bool; + default = false; + description = '' + "Whether to force Tor on a service by only allowing connections from and + to 127.0.0.1;"; + ''; + }; } diff --git a/modules/nix-bitcoin-webindex.nix b/modules/nix-bitcoin-webindex.nix index 8cd7e74..96849bf 100644 --- a/modules/nix-bitcoin-webindex.nix +++ b/modules/nix-bitcoin-webindex.nix @@ -3,7 +3,7 @@ with lib; let - nix-bitcoin-services = import ./nix-bitcoin-services.nix; + nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { }; cfg = config.services.nix-bitcoin-webindex; indexFile = pkgs.writeText "index.html" '' @@ -44,6 +44,7 @@ in { If enabled, the webindex service will be installed. ''; }; + enforceTor = nix-bitcoin-services.enforceTor; }; config = mkIf cfg.enable { @@ -81,7 +82,11 @@ in { RemainAfterExit="yes"; Restart = "on-failure"; RestartSec = "10s"; - } // nix-bitcoin-services.defaultHardening; + } // nix-bitcoin-services.defaultHardening + // (if cfg.enforceTor + then nix-bitcoin-services.allowTor + else nix-bitcoin-services.allowAnyIP + ); }; }; } diff --git a/modules/nix-bitcoin.nix b/modules/nix-bitcoin.nix index ac277f9..55fc4df 100644 --- a/modules/nix-bitcoin.nix +++ b/modules/nix-bitcoin.nix @@ -60,6 +60,7 @@ in { services.bitcoind.sysperms = if config.services.electrs.enable then true else null; services.bitcoind.disablewallet = if config.services.electrs.enable then true else null; services.bitcoind.proxy = config.services.tor.client.socksListenAddress; + services.bitcoind.enforceTor = true; services.bitcoind.port = 8333; services.bitcoind.rpcuser = "bitcoinrpc"; services.bitcoind.extraConfig = '' @@ -82,6 +83,7 @@ in { # clightning services.clightning.bitcoin-rpcuser = config.services.bitcoind.rpcuser; services.clightning.proxy = config.services.tor.client.socksListenAddress; + services.clightning.enforceTor = true; services.clightning.always-use-proxy = true; services.clightning.bind-addr = "127.0.0.1:9735"; services.tor.hiddenServices.clightning = { @@ -128,6 +130,8 @@ in { }; }; + services.nix-bitcoin-webindex.enforceTor = true; + services.liquidd.rpcuser = "liquidrpc"; services.liquidd.prune = 1000; services.liquidd.extraConfig = " @@ -136,6 +140,7 @@ in { "; services.liquidd.listen = true; services.liquidd.proxy = config.services.tor.client.socksListenAddress; + services.liquidd.enforceTor = true; services.liquidd.port = 7042; services.tor.hiddenServices.liquidd = { map = [{ @@ -143,9 +148,10 @@ in { }]; version = 3; }; - + services.spark-wallet.onion-service = true; services.electrs.port = 50001; + services.electrs.enforceTor = true; services.electrs.onionport = 50002; services.electrs.nginxport = 50003; services.electrs.high-memory = false; diff --git a/modules/onion-chef.nix b/modules/onion-chef.nix index 71628ed..c222015 100644 --- a/modules/onion-chef.nix +++ b/modules/onion-chef.nix @@ -8,7 +8,7 @@ with lib; let - nix-bitcoin-services = import ./nix-bitcoin-services.nix; + nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { }; cfg = config.services.onion-chef; dataDir = "/var/lib/onion-chef/"; onion-chef-script = pkgs.writeScript "onion-chef.sh" '' diff --git a/modules/recurring-donations.nix b/modules/recurring-donations.nix index 6d770cf..a4f46b0 100644 --- a/modules/recurring-donations.nix +++ b/modules/recurring-donations.nix @@ -3,7 +3,7 @@ with lib; let - nix-bitcoin-services = import ./nix-bitcoin-services.nix; + nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { }; cfg = config.services.recurring-donations; recurring-donations-script = pkgs.writeScript "recurring-donations.sh" '' LNCLI="lightning-cli --lightning-dir=${config.services.clightning.dataDir}" @@ -89,7 +89,8 @@ in { # working inside the shell script User = "clightning"; Type = "oneshot"; - } // nix-bitcoin-services.defaultHardening; + } // nix-bitcoin-services.defaultHardening + // nix-bitcoin-services.allowTor; }; systemd.timers.recurring-donations = { requires = [ "clightning.service" ]; diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix index 817c377..2a6de71 100644 --- a/modules/spark-wallet.nix +++ b/modules/spark-wallet.nix @@ -3,7 +3,7 @@ with lib; let - nix-bitcoin-services = import ./nix-bitcoin-services.nix; + nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { }; cfg = config.services.spark-wallet; dataDir = "/var/lib/spark-wallet/"; onion-chef-service = (if cfg.onion-service then [ "onion-chef.service" ] else []); @@ -64,7 +64,9 @@ in { User = "clightning"; Restart = "on-failure"; RestartSec = "10s"; - } // nix-bitcoin-services.nodeHardening; + } // nix-bitcoin-services.defaultHardening + // nix-bitcoin-services.node + // nix-bitcoin-services.allowTor; }; }; } From 6f8dac6e0732c2afc24cd38e3a3c34ae1a9c5c87 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sun, 28 Apr 2019 13:11:27 +0000 Subject: [PATCH 4/7] Restrict namespaces for systemd services by default --- modules/nix-bitcoin-services.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/nix-bitcoin-services.nix b/modules/nix-bitcoin-services.nix index 9ed5926..c3607cd 100644 --- a/modules/nix-bitcoin-services.nix +++ b/modules/nix-bitcoin-services.nix @@ -14,6 +14,7 @@ let ProtectKernelModules = "true"; ProtectControlGroups = "true"; RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; + RestrictNamespaces = "true"; LockPersonality = "true"; IPAddressDeny = "any"; }; From 7fb1cc1e931601a77dbfa56b0fb01771e930edb4 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sun, 28 Apr 2019 13:11:53 +0000 Subject: [PATCH 5/7] Add security section to README --- README.md | 15 ++++++++++++++- docs/install.md | 4 ++++ modules/liquid.nix | 2 -- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 48bd4d1..fbd9ddd 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ nix-bitcoin === -Nix packages and nixos modules for easily installing Bitcoin nodes and higher layer protocols. +Nix packages and nixos modules for easily installing Bitcoin nodes and higher layer protocols with an emphasis on security. This is a work in progress - don't expect it to be bug free or secure. The default configuration sets up a Bitcoin Core node and c-lightning. The user can enable spark-wallet in `configuration.nix` to make c-lightning accessible with a smartphone using spark-wallet. @@ -49,6 +49,19 @@ The easiest way is to run `nix-shell` (on a Linux machine) in the nix-bitcoin di Fix the FIXMEs in configuration.nix and deploy with nixops in nix-shell. See [install.md](docs/install.md) for a detailed tutorial. +Security +--- +* Nix package manager, NixOS and packages can be built from source to reduce reliance on binary caches. +* Builds happen in a [sandboxed environment](https://nixos.org/nix/manual/). +* Packages dependencies are [pinned](pkgs/nixpkgs-pinned.nix). Most packages are built from the [nixos stable channel](https://github.com/NixOS/nixpkgs-channels/tree/nixos-19.03), with a few exceptions that are built from the nixpkgs unstable channel. +* nix-bitcoin merge commits are signed. +* nix-bitcoin is built with a [hardened kernel](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/hardened.nix) by default. +* Services operate with least privileges. They each have their own user and are restricted further with [systemd options](modules/nix-bitcoin-services.nix). +* There's a non-root user *operator* to interact with the various services. + +Note that nix-bitcoin is still experimental. +Also, by design if the machine you're deploying *from* is insecure, there is nothing nix-bitcoin can do to protect itself. + Hardware requirements --- * Disk space: 300 GB (235GB for Bitcoin blockchain + some room) diff --git a/docs/install.md b/docs/install.md index 6ac586a..192dabc 100644 --- a/docs/install.md +++ b/docs/install.md @@ -165,6 +165,10 @@ This is borrowed from the [NixOS manual](https://nixos.org/nixos/manual/index.ht swapon /dev/sda2 ``` +4. Option 3: Set up encrypted partitions: + + Follow the guide at https://gist.github.com/martijnvermaat/76f2e24d0239470dd71050358b4d5134. + 5. Generate NixOS config ``` diff --git a/modules/liquid.nix b/modules/liquid.nix index f66b78b..acff282 100644 --- a/modules/liquid.nix +++ b/modules/liquid.nix @@ -207,7 +207,6 @@ in { }; users.users.${cfg.user} = { name = cfg.user; - #uid = config.ids.uids.liquid; group = cfg.group; extraGroups = [ "keys" ]; description = "Liquid daemon user"; @@ -215,7 +214,6 @@ in { }; users.groups.${cfg.group} = { name = cfg.group; - #gid = config.ids.gids.liquid; }; }; } From 469c1de6a90d385696bba63b3defb077ca3d2bed Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sun, 28 Apr 2019 18:54:13 +0000 Subject: [PATCH 6/7] Fix electrum after disallowing anything but localhost by adding ipv6 local address --- modules/nix-bitcoin-services.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/nix-bitcoin-services.nix b/modules/nix-bitcoin-services.nix index c3607cd..ac687cc 100644 --- a/modules/nix-bitcoin-services.nix +++ b/modules/nix-bitcoin-services.nix @@ -24,7 +24,9 @@ in # node applications apparently rely on memory write execute node = { MemoryDenyWriteExecute = "false"; }; # Allow tor traffic. Allow takes precedence over Deny. - allowTor = { IPAddressAllow = "127.0.0.1/32"; }; + allowTor = { + IPAddressAllow = "127.0.0.1/32 ::1/128"; + }; # Allow any traffic allowAnyIP = { IPAddressAllow = "any"; }; From e1ee5023e2273fab99fc38d745676cea7d751952 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 3 May 2019 10:44:16 +0000 Subject: [PATCH 7/7] Rename service settings for 'node' to 'nodejs' to avoid confusion --- modules/lightning-charge.nix | 2 +- modules/nanopos.nix | 2 +- modules/nix-bitcoin-services.nix | 4 ++-- modules/spark-wallet.nix | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/lightning-charge.nix b/modules/lightning-charge.nix index a6d6b19..bd0e371 100644 --- a/modules/lightning-charge.nix +++ b/modules/lightning-charge.nix @@ -39,7 +39,7 @@ in { Restart = "on-failure"; RestartSec = "10s"; } // nix-bitcoin-services.defaultHardening - // nix-bitcoin-services.node + // nix-bitcoin-services.nodejs // nix-bitcoin-services.allowTor; }; }; diff --git a/modules/nanopos.nix b/modules/nanopos.nix index 729f65c..300da4b 100644 --- a/modules/nanopos.nix +++ b/modules/nanopos.nix @@ -75,7 +75,7 @@ in { Restart = "on-failure"; RestartSec = "10s"; } // nix-bitcoin-services.defaultHardening - // nix-bitcoin-services.node + // nix-bitcoin-services.nodejs // nix-bitcoin-services.allowTor; }; }; diff --git a/modules/nix-bitcoin-services.nix b/modules/nix-bitcoin-services.nix index ac687cc..685d668 100644 --- a/modules/nix-bitcoin-services.nix +++ b/modules/nix-bitcoin-services.nix @@ -21,8 +21,8 @@ let in { inherit defaultHardening; - # node applications apparently rely on memory write execute - node = { MemoryDenyWriteExecute = "false"; }; + # nodejs applications apparently rely on memory write execute + nodejs = { MemoryDenyWriteExecute = "false"; }; # Allow tor traffic. Allow takes precedence over Deny. allowTor = { IPAddressAllow = "127.0.0.1/32 ::1/128"; diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix index 2a6de71..e2d6226 100644 --- a/modules/spark-wallet.nix +++ b/modules/spark-wallet.nix @@ -65,7 +65,7 @@ in { Restart = "on-failure"; RestartSec = "10s"; } // nix-bitcoin-services.defaultHardening - // nix-bitcoin-services.node + // nix-bitcoin-services.nodejs // nix-bitcoin-services.allowTor; }; };