-
-
Notifications
You must be signed in to change notification settings - Fork 13.9k
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
Option to allow containers to bind to specific interfaces #328812
base: master
Are you sure you want to change the base?
Conversation
machine.fail("curl --fail --connect-timeout 2 http://${hostIp}:${toString hostPort}/ > /dev/null") | ||
|
||
# This should pass and works outside tests | ||
machine.succeed("curl --fail http://192.168.0.1:${toString hostPort}/ > /dev/null") |
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 someone point me in the right direction for getting this test to work? It's the only part I'm struggling with.
I think I'd need to bring both interfaces up with the correct IPs for it to work but I'm unsure how to do that in the test
++ (forEach portForwarding (portForward: { | ||
name = "container@${portForward.containerName}-forward-${portForward.interface}-${toString portForward.hostPort}-${portForward.protocol}"; | ||
value = { | ||
bindsTo = if portForward.interface != "" && portForward.interface != "lo" then ["sys-subsystem-net-devices-${portForward.interface}.device"] else []; |
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 added this so that if the IP on the host changes the service will restart
This adds the following option in `containers..forwardPorts`: ``` forwardPorts = [ { containerPort = 80; hostPort = 8080; protocol = "tcp"; interfaces = [ "lo" ]; } ``` A list of interfaces can be specified so that different services can listen on IP addresses. In addition, it allows the loopback interface to be bound
16784a8
to
7118258
Compare
@@ -910,7 +962,7 @@ in | |||
|
|||
environment.systemPackages = [ | |||
nixos-container | |||
]; | |||
] ++ (if portForwarding != [] then [pkgs.socat] else []); |
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 there a nicer way of doing that?
For something more complicated like this we simply use the more advanced NAT features of nixos like here: https://gitlab.com/garuda-linux/infra-nix/-/blob/main/nixos/modules/nspawn-containers.nix?ref_type=heads#L150 |
Thanks, I can't find very much documentation on that and the test coverage is minimal. Do you have an example of binding a port to I have this setup:
I'll update the PR to add the NAT portforwarding rules instead of using socat if I can get it to work. I'm trying to map I have the various sysctl options set to allow forwarding:
edit: And looking at the options, I don't think that approach will allow me to have different port forwarding rules for different external interfaces? Seems I'm not the only one: https://discourse.nixos.org/t/networking-nat-not-working-as-expected-for-nixos-container-networking/41050 |
edit: Ignore below, I think there's a bug in how it works. There is a
But it doesn't work unless nftables is enabled. There's a bug somewhere in
So my questions are:
|
I wouldn't suggest you change anything about the nat stuff right now, I have an open pull request that makes major changes and introduces more tests to nat here: #277016 If you have a test case for NAT that isn't being tested here that should work, please let me know and I'll add them to the PR.
I don't think you can do that directly using NAT honestly. What you can do is directly access the service through the bridge interface's address. If you do port forward and use `loopbackIPs then you can also make a connection from the server to its own public IP to access services behind NAT like that. You would need a custom iptables/nftables rule to allow 127.0.0.1 directly though. |
This adds the following option in
containers..forwardPorts
:A list of interfaces can be specified so that different services can listen on IP addresses.
In addition, it allows the loopback interface to be bound
Description of changes
Feedback is welcome, this is my first time doing anything in the nix language that isn't just defining data structures for system configuration so no doubt there are better ways to achieve what I've done here.
The current containers implementation has a few limitations when it comes to port forwarding:
The last one is a little surprising. Tools like docker make us used to being able to access a container via
127.0.0.1:80
or whatever.There are quite a few times when I'd like to access a container locally but not expose it to the rest of the network. For example a web development machine. While the firewall can do this, why bind the port only to have the firewall block access to it?
Alternatively, a machine with a public and local interface on the network, I can differentiate between internet facing services and local only services.
Implementation
There is a new
interfaces
option inforwardPorts
when declaring a container.Example:
Implementation choices
Nspawn's port options are very limited. This implementation skips it and manually configures port forwarding from the host to the container.
Interface names were chosen over IP addresses as IPs can change. For example, running a service on a machine on the local network and accessing it via the hostname is not uncommon. By using interface it doesn't matter if the IP changes
machinename:port
will still work to other machines on the network if the host IP changes.I'm using
socat
to handle the forwarding. It may be possible to do this with IP tables but regardless what I tried I could not get forwarding to work on the loopback address. Though I'm no iptables expert. Similar issue described hereThings done
nix.conf
? (See Nix manual)sandbox = relaxed
sandbox = true
nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)Add a 👍 reaction to pull requests you find important.