diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index c7cd1ae..d6b1ae0 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -157,7 +157,7 @@ let }; proxy = mkOption { type = types.nullOr types.str; - default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null; + default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null; description = "Connect through SOCKS5 proxy"; }; i2p = mkOption { @@ -262,7 +262,7 @@ let ''; description = "Binary to connect with the bitcoind instance."; }; - enforceTor = nbLib.enforceTor; + tor = nbLib.tor; }; }; @@ -407,7 +407,7 @@ in { Restart = "on-failure"; UMask = mkIf cfg.dataDirReadableByGroup "0027"; ReadWritePaths = cfg.dataDir; - } // nbLib.allowedIPAddresses cfg.enforceTor + } // nbLib.allowedIPAddresses cfg.tor.enforce // optionalAttrs zmqServerEnabled nbLib.allowNetlink; }; diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index a90c611..94f6074 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -54,7 +54,7 @@ let default = cfg.btcpayserver.user; description = "The group as which to run btcpayserver."; }; - enforceTor = nbLib.enforceTor; + tor.enforce = nbLib.tor.enforce; }; nbxplorer = { @@ -96,7 +96,7 @@ let default = cfg.nbxplorer.user; description = "The group as which to run nbxplorer."; }; - enforceTor = nbLib.enforceTor; + tor.enforce = nbLib.tor.enforce; }; }; @@ -185,7 +185,7 @@ in { RestartSec = "10s"; ReadWritePaths = cfg.nbxplorer.dataDir; MemoryDenyWriteExecute = "false"; - } // nbLib.allowedIPAddresses cfg.nbxplorer.enforceTor; + } // nbLib.allowedIPAddresses cfg.nbxplorer.tor.enforce; }; systemd.services.btcpayserver = let @@ -238,7 +238,7 @@ in { RestartSec = "10s"; ReadWritePaths = cfg.btcpayserver.dataDir; MemoryDenyWriteExecute = "false"; - } // nbLib.allowedIPAddresses cfg.btcpayserver.enforceTor; + } // nbLib.allowedIPAddresses cfg.btcpayserver.tor.enforce; }; in self; users.users.${cfg.nbxplorer.user} = { diff --git a/modules/clightning-plugins/clboss.nix b/modules/clightning-plugins/clboss.nix index c07122c..fe48358 100644 --- a/modules/clightning-plugins/clboss.nix +++ b/modules/clightning-plugins/clboss.nix @@ -28,6 +28,6 @@ let cfg = config.services.clightning.plugins.clboss; in ''; systemd.services.clightning.path = [ pkgs.dnsutils - ] ++ optional config.services.clightning.enforceTor (hiPrio config.nix-bitcoin.torify); + ] ++ optional config.services.clightning.tor.proxy (hiPrio config.nix-bitcoin.torify); }; } diff --git a/modules/clightning.nix b/modules/clightning.nix index f9a41d3..1c0cabf 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -16,14 +16,14 @@ let }; proxy = mkOption { type = types.nullOr types.str; - default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null; + default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null; description = '' Socks proxy for connecting to Tor nodes (or for all connections if option always-use-proxy is set). ''; }; always-use-proxy = mkOption { type = types.bool; - default = cfg.enforceTor; + default = cfg.tor.proxy; description = '' Always use the proxy, even to connect to normal IP addresses. You can still connect to Unix domain sockets manually. @@ -79,7 +79,7 @@ let If left empty, no address is announced. ''; }; - inherit (nbLib) enforceTor; + tor = nbLib.tor; }; cfg = config.services.clightning; @@ -156,7 +156,7 @@ in { # # Disable seccomp filtering because clightning depends on this syscall. SystemCallFilter = []; - } // nbLib.allowedIPAddresses cfg.enforceTor; + } // nbLib.allowedIPAddresses cfg.tor.enforce; # Wait until the rpc socket appears postStart = '' while [[ ! -e ${cfg.networkDir}/lightning-rpc ]]; do diff --git a/modules/electrs.nix b/modules/electrs.nix index 5f9b042..76c6f09 100644 --- a/modules/electrs.nix +++ b/modules/electrs.nix @@ -39,7 +39,7 @@ let default = cfg.user; description = "The group as which to run electrs."; }; - enforceTor = nbLib.enforceTor; + tor.enforce = nbLib.tor.enforce; }; cfg = config.services.electrs; @@ -94,7 +94,7 @@ in { Restart = "on-failure"; RestartSec = "10s"; ReadWritePaths = cfg.dataDir; - } // nbLib.allowedIPAddresses cfg.enforceTor; + } // nbLib.allowedIPAddresses cfg.tor.enforce; }; users.users.${cfg.user} = { diff --git a/modules/joinmarket-ob-watcher.nix b/modules/joinmarket-ob-watcher.nix index 7353798..27b0b2c 100644 --- a/modules/joinmarket-ob-watcher.nix +++ b/modules/joinmarket-ob-watcher.nix @@ -29,11 +29,9 @@ let default = cfg.user; description = "The group as which to run JoinMarket."; }; - # This option is only used by netns-isolation - enforceTor = mkOption { - readOnly = true; - default = true; - }; + # This option is only used by netns-isolation. + # Tor is always enabled. + tor.enforce = nbLib.tor.enforce; }; cfg = config.services.joinmarket-ob-watcher; @@ -100,7 +98,7 @@ in { SystemCallFilter = nbLib.defaultHardening.SystemCallFilter ++ [ "mbind" ] ; Restart = "on-failure"; RestartSec = "10s"; - } // nbLib.allowTor; + } // nbLib.allowedIPAddresses cfg.tor.enforce; }; users.users.${cfg.user} = { diff --git a/modules/joinmarket.nix b/modules/joinmarket.nix index 58ca77a..94a3479 100644 --- a/modules/joinmarket.nix +++ b/modules/joinmarket.nix @@ -50,11 +50,9 @@ let readOnly = true; default = ircServers; }; - # This option is only used by netns-isolation - enforceTor = mkOption { - readOnly = true; - default = true; - }; + # This option is only used by netns-isolation. + # Tor is always enabled. + tor.enforce = nbLib.tor.enforce; inherit (nbLib) cliExec; yieldgenerator = { @@ -328,7 +326,7 @@ in { Restart = "on-failure"; RestartSec = "10s"; ReadWritePaths = cfg.dataDir; - } // nbLib.allowTor; + } // nbLib.allowedIPAddresses cfg.tor.enforce; }; users.users.${cfg.user} = { diff --git a/modules/lightning-loop.nix b/modules/lightning-loop.nix index 1249a3a..2d2441a 100644 --- a/modules/lightning-loop.nix +++ b/modules/lightning-loop.nix @@ -36,7 +36,7 @@ let }; proxy = mkOption { type = types.nullOr types.str; - default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null; + default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null; description = "host:port of SOCKS5 proxy for connnecting to the loop server."; }; extraConfig = mkOption { @@ -56,7 +56,7 @@ let ''; description = "Binary to connect with the lightning-loop instance."; }; - enforceTor = nbLib.enforceTor; + tor = nbLib.tor; }; cfg = config.services.lightning-loop; @@ -105,7 +105,7 @@ in { Restart = "on-failure"; RestartSec = "10s"; ReadWritePaths = cfg.dataDir; - } // nbLib.allowedIPAddresses cfg.enforceTor; + } // nbLib.allowedIPAddresses cfg.tor.enforce; }; nix-bitcoin.secrets = { diff --git a/modules/lightning-pool.nix b/modules/lightning-pool.nix index 0c69d32..c93aa6a 100644 --- a/modules/lightning-pool.nix +++ b/modules/lightning-pool.nix @@ -36,7 +36,7 @@ let }; proxy = mkOption { type = types.nullOr types.str; - default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null; + default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null; description = "host:port of SOCKS5 proxy for connnecting to the pool auction server."; }; extraConfig = mkOption { @@ -56,7 +56,7 @@ let ''; description = "Binary to connect with the lightning-pool instance."; }; - enforceTor = nbLib.enforceTor; + tor = nbLib.tor; }; cfg = config.services.lightning-pool; @@ -102,7 +102,7 @@ in { Restart = "on-failure"; RestartSec = "10s"; ReadWritePaths = cfg.dataDir; - } // (nbLib.allowedIPAddresses cfg.enforceTor) + } // (nbLib.allowedIPAddresses cfg.tor.enforce) // nbLib.allowNetlink; # required by gRPC-Go }; }; diff --git a/modules/liquid.nix b/modules/liquid.nix index dd8d884..6e7e6ad 100644 --- a/modules/liquid.nix +++ b/modules/liquid.nix @@ -98,7 +98,7 @@ let }; proxy = mkOption { type = types.nullOr types.str; - default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null; + default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null; description = "Connect through SOCKS5 proxy"; }; dbCache = mkOption { @@ -156,7 +156,7 @@ let ''; description = "Binary for managing liquid swaps."; }; - enforceTor = nbLib.enforceTor; + tor = nbLib.tor; }; }; @@ -271,7 +271,7 @@ in { ExecStart = "${nbPkgs.elementsd}/bin/elementsd -datadir='${cfg.dataDir}'"; Restart = "on-failure"; ReadWritePaths = cfg.dataDir; - } // nbLib.allowedIPAddresses cfg.enforceTor; + } // nbLib.allowedIPAddresses cfg.tor.enforce; }; users.users.${cfg.user} = { diff --git a/modules/lnd.nix b/modules/lnd.nix index 0e1c76a..5d14846 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -46,7 +46,7 @@ let }; tor-socks = mkOption { type = types.nullOr types.str; - default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null; + default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null; description = "Socks proxy for connecting to Tor nodes"; }; macaroons = mkOption { @@ -117,7 +117,7 @@ let default = "${secretsDir}/lnd-cert"; description = "LND TLS certificate path."; }; - inherit (nbLib) enforceTor; + tor = nbLib.tor; }; cfg = config.services.lnd; @@ -143,7 +143,7 @@ let bitcoin.active=1 bitcoin.node=bitcoind - ${optionalString (cfg.enforceTor) "tor.active=true"} + ${optionalString (cfg.tor.proxy) "tor.active=true"} ${optionalString (cfg.tor-socks != null) "tor.socks=${cfg.tor-socks}"} bitcoind.rpchost=${bitcoindRpcAddress}:${toString bitcoind.rpc.port} @@ -277,7 +277,7 @@ in { '') (attrNames cfg.macaroons)} '') ]; - } // nbLib.allowedIPAddresses cfg.enforceTor; + } // nbLib.allowedIPAddresses cfg.tor.enforce; }; users.users.${cfg.user} = { diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index 42cf190..09686d6 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -179,7 +179,7 @@ in { ${iptables} -w -A INPUT -s 127.0.0.1,${bridgeIp},${v.address} -j ACCEPT # allow return traffic to outgoing connections initiated by the service itself ${iptables} -w -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT - '' + optionalString (config.services.${n}.enforceTor or false) '' + '' + optionalString (config.services.${n}.tor.enforce or false) '' ${iptables} -w -P OUTPUT DROP ${iptables} -w -A OUTPUT -d 127.0.0.1,${bridgeIp},${v.address} -j ACCEPT '' + optionalString (v.availableNetns != []) '' diff --git a/modules/obsolete-options.nix b/modules/obsolete-options.nix index 137165f..fc79164 100644 --- a/modules/obsolete-options.nix +++ b/modules/obsolete-options.nix @@ -7,6 +7,16 @@ let mkRemovedOptionModule [ "services" service "announce-tor" ] '' Use option `nix-bitcoin.onionServices.${service}.public` instead. ''; + + mkSplitEnforceTorOption = service: + (mkRemovedOptionModule [ "services" service "enforceTor" ] '' + The option has been split into options `tor.proxy` and `tor.enforce`. + Set `tor.proxy = true` to proxy outgoing connections with Tor. + Set `tor.enforce = true` to only allow connections (incoming and outgoing) through Tor. + ''); + mkRenamedEnforceTorOption = service: + (mkRenamedOptionModule [ "services" service "enforceTor" ] [ "services" service "tor" "enforce" ]); + in { imports = [ (mkRenamedOptionModule [ "services" "bitcoind" "bind" ] [ "services" "bitcoind" "address" ]) @@ -33,5 +43,20 @@ in { bitcoin peer connections for syncing blocks. This performs well on low and high memory systems. '') - ]; + ] ++ + # 0.0.59 + (map mkSplitEnforceTorOption [ + "clightning" + "lightning-loop" + "lightning-pool" + "liquid" + "lnd" + "spark-wallet" + "bitcoind" + ]) ++ + (map mkRenamedEnforceTorOption [ + "btcpayserver" + "rtl" + "electrs" + ]); } diff --git a/modules/presets/enable-tor.nix b/modules/presets/enable-tor.nix index ccde835..d61341b 100644 --- a/modules/presets/enable-tor.nix +++ b/modules/presets/enable-tor.nix @@ -1,26 +1,42 @@ { lib, config, ... }: let defaultTrue = lib.mkDefault true; + defaultEnableTorProxy = { + tor.proxy = defaultTrue; + tor.enforce = defaultTrue; + }; + defaultEnforceTor = { + tor.enforce = defaultTrue; + }; in { services.tor = { enable = true; client.enable = true; }; - # Use Tor for all outgoing connections services = { - bitcoind.enforceTor = true; - clightning.enforceTor = true; - lnd.enforceTor = true; - lightning-loop.enforceTor = true; - liquidd.enforceTor = true; - electrs.enforceTor = true; + # Use Tor as a proxy for outgoing connections + # and restrict all connections to Tor + # + bitcoind = defaultEnableTorProxy; + clightning = defaultEnableTorProxy; + lnd = defaultEnableTorProxy; + lightning-loop = defaultEnableTorProxy; + liquidd = defaultEnableTorProxy; # disable Tor enforcement until btcpayserver can fetch rates over Tor - # btcpayserver.enforceTor = true; - nbxplorer.enforceTor = true; - spark-wallet.enforceTor = true; - lightning-pool.enforceTor = true; - rtl.enforceTor = true; + # btcpayserver = defaultEnableTorProxy; + spark-wallet = defaultEnableTorProxy; + lightning-pool = defaultEnableTorProxy; + + # These services don't make outgoing connections + # (or use Tor by default in case of joinmarket) + # but we restrict them to Tor just to be safe. + # + electrs = defaultEnforceTor; + nbxplorer = defaultEnforceTor; + rtl = defaultEnforceTor; + joinmarket = defaultEnforceTor; + joinmarket-ob-watcher = defaultEnforceTor; }; # Add onion services for incoming connections diff --git a/modules/rtl.nix b/modules/rtl.nix index 4d44310..f4111f3 100644 --- a/modules/rtl.nix +++ b/modules/rtl.nix @@ -89,7 +89,7 @@ let description = "Swagger API documentation server port."; }; }; - inherit (nbLib) enforceTor; + tor.enforce = nbLib.tor.enforce; }; cfg = config.services.rtl; @@ -214,7 +214,7 @@ in { Restart = "on-failure"; RestartSec = "10s"; ReadWritePaths = cfg.dataDir; - } // nbLib.allowedIPAddresses cfg.enforceTor + } // nbLib.allowedIPAddresses cfg.tor.enforce // nbLib.nodejs; }; diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix index a55be9a..adf6c87 100644 --- a/modules/spark-wallet.nix +++ b/modules/spark-wallet.nix @@ -38,7 +38,7 @@ let default = cfg.user; description = "The group as which to run spark-wallet."; }; - inherit (nbLib) enforceTor; + tor = nbLib.tor; }; cfg = config.services.spark-wallet; @@ -57,7 +57,7 @@ let --ln-path '${clightning.networkDir}' \ --host ${cfg.address} --port ${toString cfg.port} \ --config '${config.nix-bitcoin.secretsDir}/spark-wallet-login' \ - ${optionalString cfg.enforceTor torRateProvider} \ + ${optionalString cfg.tor.proxy torRateProvider} \ $publicURL \ --pairing-qr --print-key ${cfg.extraArgs} ''; @@ -76,7 +76,7 @@ in { User = cfg.user; Restart = "on-failure"; RestartSec = "10s"; - } // nbLib.allowedIPAddresses cfg.enforceTor + } // nbLib.allowedIPAddresses cfg.tor.enforce // nbLib.nodejs; }; diff --git a/pkgs/lib.nix b/pkgs/lib.nix index 61db1b0..9181796 100644 --- a/pkgs/lib.nix +++ b/pkgs/lib.nix @@ -55,13 +55,20 @@ let self = { then self.allowLocalIPAddresses else self.allowAllIPAddresses; - 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; - ''; + tor = { + proxy = mkOption { + type = types.bool; + default = false; + description = "Whether to proxy outgoing connections with Tor."; + }; + enforce = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enforce Tor on a service by only allowing connections + from and to localhost and link-local addresses. + ''; + }; }; script = name: src: pkgs.writers.writeBash name ''