-
Notifications
You must be signed in to change notification settings - Fork 110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Network Namespaces #187
Network Namespaces #187
Conversation
Regarding 4) I solved a similar problem for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't tested or thought much about the actual functionality but left a few nitpicks regarding implementation.
modules/netns-chef.nix
Outdated
netns = builtins.mapAttrs (n: v: { | ||
inherit (v) id; | ||
address = "169.254.${toString cfg.addressblock}.${toString v.id}"; | ||
availableNetns = builtins.filter (x: config.services.${x}.enable) availableNetns.${n}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps you can call isEnabled
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this better? @erikarvstedt wrote this function, mabye he can take a look. I'm not competent enough yet to fully understand it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented under d3a8abc
modules/netns-chef.nix
Outdated
|
||
nix-bitcoin.netns-isolation.services = { | ||
bitcoind = { | ||
id = 12; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it desirable for two services to have the same id
, or do the ids need to be persistent? If not you should be able to assign the ids automatically, e.g. by defining serviceName -> id
map like:
idMap = builtins.listToAttrs (lib.imap1 (num: srvName: lib.nameValuePair srvName num) (lib.attrNames cfg.services))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would you want to do that? It makes everything simpler IMO to just have hardcoded addresses in a changeable addressblock.
modules/netns-chef.nix
Outdated
isEnabled = x: config.services.${x}.enable; | ||
|
||
ip = "${pkgs.iproute}/bin/ip"; | ||
iptables = "${pkgs.iptables}/bin/iptables"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using config.networking.firewall.package
instead for nftables. (Though if NixOS/nixpkgs#81172 should make this uneccessary.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is nftables better than iptables for what we're trying to do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I meant to write "... instead for compatibility with nftables". Using config.networking.firewall.package
instead of a concrete package would make it work regardless of whether the system is set to use iptables or nftables.
IMO nftables is the future but both work fine for this use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See fixup! architecture: pkgs.iptables -> config.networking.firewall.package
modules/netns-chef.nix
Outdated
networking.firewall.interfaces.br0.allowedTCPPorts = [ 9050 ]; | ||
boot.kernel.sysctl."net.ipv4.ip_forward" = true; | ||
|
||
nix-bitcoin.netns-isolation.services = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the sake of modularity it might be preferable to define the implementation in this file and then set the concrete mapping and other parameters elsewhere, e.g. in secure-node.nix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jonasnick and I talked about restructuring this file like so: parameters in each individual module, mapping in secure-node.nix
and general implementation in netns-chef.nix
. What are your thoughts on this approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable!
We've used wrappers before, check out this. The problem is that I've been thinking about how to solve 4. and I think the best idea is to create a separate |
What about setcap wrapper? Namespaces require CAP_SYS_ADMIN which is pretty much root but I guess it's marginally better than the sudo rule and the capability won't be inherited by the program passed to |
Please rename |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK. Really cool and thanks to abstractions much simpler than I had imagined.
modules/netns-chef.nix
Outdated
default = {}; | ||
type = types.attrsOf (types.submodule { | ||
options = { | ||
id = mkOption { type = types.int; }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Description would be helpful. "must be unique", "must not be 10"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See fixup! id option: add description
I force pushed a new and improved HEAD that includes lnd, an operator namespace, and several fixes. It also removes the clightning autolisten option, as documented in the commit. These todos remain: I've tried implementing these and have gotten errors that I can't solve (please help @erikarvstedt @jonasnick):
I need your conceptual input on these:
I can take care of these but they depend on the above:
|
Force pushed a new and improved HEAD, that fixes most issues. Only three issues remaining are
I will document clearnet and wireguard access in a later PR. Out of scope for now. |
I got rid of the operator shell and replaced it with custom cli scripts that use Jonas Nick's I also rewrote the Only remaining issues are the breaking changes to Very close to mergeable IMO. |
Fixed some nits. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The netns-exec operator access works well. And nice to see that you managed to get the tests to pass.
I'm not concerned about the breaking changes to lnd. The hardcoded ip isn't a problem unless in very very rare cases. We mention the new onion adress and the requirement in the release notes and can make a minor version bump to signal that users may have to take action.
I'd suggest to disable this module by default for now. That way we can merge this PR with little risk and work on reliability and usability until we make it default. To do this effectively it would be really helpful to be able to test with and without netns isolation.
modules/bitcoind.nix
Outdated
@@ -68,6 +70,13 @@ in { | |||
default = "/var/lib/bitcoind"; | |||
description = "The data directory for bitcoind."; | |||
}; | |||
host = mkOption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like we don't really need these host options. In some modules (like bitcoind) they aren't even used. As far as I can see they are mainly used for the hidden service toHost
option. For clightning for example we can directly use bind-addr. For lnd we can keep host (or rename to listen, because that's how the option is called in lnd). For bitcoind we can add a bind
option (we should do that anyway) which if set will result in an additional line bind=${...}
in the bitcoind config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed where possible. Nanopos, lightning-charge and spark-wallet actually have a host option, so naming is correct. It's needed in electrs for now to direct traffic to the nginx netns, can be removed when #203 is merged.
modules/netns-isolation.nix
Outdated
${ip} link set br-${vethName} master br0 | ||
${ipNetns} route add default via ${bridgeIp} | ||
${netnsIptables} -w -P INPUT DROP | ||
${netnsIptables} -w -A INPUT -s 127.0.0.1,${bridgeIp} -j ACCEPT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be possible to allow the ipNetns
to connect to ipNetns
. In order to allow that I think we need to add ${ipNetns}
here and in the OUTPUT
rule below. That allows simplifying the tests by testing connectivity from the same container. Also we can remove additional connection from clightning to spark in the tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 43a34be
Rebased and fixed @jonasnick comments. a2dc3da notes
Running tests with and without
where |
test/test-script.py
Outdated
|
||
# Positive ping tests | ||
machine.succeed( | ||
"ip netns exec nb-bitcoind ping -c 1 -w 1 169.254.1.12 && \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you define constants for these addresses? That would give them a name and make it easy to see what they're referring to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 9d7181b5aaadf326728a3a5c9b255f0cae36598c
test/test-script.py
Outdated
) | ||
|
||
# netns-exec tests | ||
machine.fail("netns-exec nb-electrs ip a") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment to explain what this does and why this must fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And how about checking that netns-exec can not be executed by users that are not operator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both fixed in 9d7181b5aaadf326728a3a5c9b255f0cae36598c
test/test-script.py
Outdated
machine.fail("netns-exec nb-electrs ip a") | ||
assert_matches_exactly( | ||
"su operator -c 'netns-exec nb-bitcoind capsh --print | grep Current | tr -d \"\\n\"'", | ||
"Current: =", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you match against "Current: =\n" instead of using tr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in a3aaff1
Moved |
c program allows executing commands in nb-bitcoind, nb-lnd, nb-liquidd (the netns's needed for operator cli scripts).
- Adds network namespace instantiation and routing architecture. - netns-isolation disabled by default. Can be enabled with configuration.nix FIXME. - Uses mkMerge to toggle certain options for non netns and netns systems. - Adds security wrapper for netns-exec which allows operator to exec with cap_sys_admin - User can select the 169.254.N.0/24 addressblock netns's are created in. - nix-bitcoin-services IpAddressAllow is amended with link-local addresses
- Adds bitcoind to netns-isolation.services - Adds rpcbind and rpcallowip options to allow using bitcoind with network namespaces - Adds bind option (defaults to localhost), used as target of hidden service - Makes bitcoind-import-banlist run in netns
nonetns script needed for bitcoind-import-banlist
From the clightning manpage: autolisten=BOOL By default, we bind (and maybe announce) on IPv4 and IPv6 interfaces if no addr, bind-addr or announce-addr options are specified. Setting this to false disables that. We already set bind-addr by default, so autolisten had no effect. Therefore, this commit replaces autolisten with the more granular announce-addr option. For now we are Tor-only, so we only need to announce our hidden service to accept incoming connections. In the future, we can add clearnet connectivity with `addr` and route connections into our netns with NAT.
Simplifies the clightning module.
- Adds clightning to netns-isolation.services - Adds bitcoin-rpcconnect option to allow using clightning with network namespaces - Uses bind-addr option (defaults to localhost) as target of hidden service - Adds different bind-addr options depending on if netns-isolation is enabled or not.
- Adds bitcoind-host, and tor-socks options to allow using with network namespaces. - Adds listen, rpclisten, and restlisten option to specify host on which to listen on for peer, rpc and rest connections respectively - Adds announce-tor option and generates Tor Hidden Service with nix instead of lnd to bring in line with clightning. WARNING: Breaking changes for Tor Hidden Service. Manual migration necessary.
- Adds lnd to netns-isolation.services - Specifies listen option (defaults to localhost) as target of hiddenService. - Amends hardcoded lnd ip to lnd-cert WARNING: Breaking changes for lnd cert. lnd-key and lnd-cert will have to be deleted and redeployed.
- Adds liquidd to netns-isolation.services - Adds rpcbind, rpcallowip, and mainchainrpchost options to allow using liquidd with network namespaces - Adds bind option (defaults to localhost) as target of hidden service
- Adds electrs to netns-isolation.services - Adds daemonrpc option and specifies address option to allow using electrs with network namespaces - Adds host option (defaults to localhost) as target of hidden service
- Adds spark-wallet to netns-isolation.services - Adds extraArgs option to allow using spark-wallet with network namespaces - Adds host option (defaults to localhost) as target of hidden service - Adds enforceTor option to bring in line with other services
- Adds lightning-charge to netns-isolation.services - Adds cfg.enforceTor to bring lightning-charge in line with other services - Adds extraArgs option to allow using lightning-charge with network namespaces - Adds host option (defaults to localhost) as target of hidden service
- Adds nanopos to netns-isolation.services - Adds cfg.enforceTor and extraArgs to bring nanopos in line with other services - Adds charged-url option to allow using nanopos with network namespaces. - Modularizes nginx so webindex can be used without nanopos. - Adds host option (defaults to localhost) as target of hidden service - Removes unnecessary after
- Adds recurring-donations to netns-isolation.services - Adds cfg.enforceTor to bring recurring-donations in line with other services - Removes torsocks dependency in favor of `curl --socks-hostname`
- Adds nginx to netns-isolation.services - Adds host option (defaults to localhost) as target of hidden service
Fixed final nits |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 6817282
epic merge is epic
Network Namespaces are a significant security improvement, mitigating the bind race leak security vulnerability and unnecessary communications between nix-bitcoin services. Network namespaces round-off our service isolation to cover all levels of inter-service interaction.
Special thank you to @erikarvstedt for generalizing the
makeNetnsServices
🚀