-
Notifications
You must be signed in to change notification settings - Fork 18.6k
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
Proper handling of NAT corner cases #137
Comments
+1 for making it possible to connect to localhost:port With my vagrant install connecting to $(hostname) (as in the example) also doesn't work because it also resolves to 127.0.0.1 |
I've looked into this and it won't be possible to use localhost at all without something like portfwd. I'll provide a solution for the second problem (the one which causes ports to loop back to the container). @jpetazzo You can assign this issue to me. |
Instead of trying to list all IPs of the host so that we allow the containers to connect on any of them, we could just pass to docker the interfaces we want it to take into account. For example, I might have 6 interfaces and only care about allowing docker hosts to connect to each other via the IP of one single interface. So I'd pass docker -d some argument like -forward-if=tap0. Also, if I want to connect to any container, I have to use that IP + port, not localhost, nor any other IP of the host. |
Assigned to you, thanks! Agreed on first issue (using localhost): it requires some userland proxy. About second issue: "we could just pass to docker the interfaces we want it to take into account" — I think it won't be simpler than enumerating all of them, and some cases might even be tricky (e.g. what if I want to catch traffic directed to one specific secondary address or alias?) IMHO, using all addresses would be "good enough" at first; and having a way to specify interfaces and/or IP addresses would be a nice bonus. |
@jpetazzo In that case, we could specify IPs on which we want docker to make the mapped ports available. Also, it's easier to specify the IPs from which we map those ports from to the containers than enumerating all the interfaces and letting traffic through for all of them. It's also better to make things explicit than implicit in this case. Specifying the IPs means we don't need to add code to get the list of interfaces. So the flags would look something like: -map-ip=192.168.1.24 -map-ip=10.4.0.2. For those who don't want to have to pass IPs to docker, we can also allow them to use the interface name. We won't have to obtain the IP or IPs of the interface(s) in that case either. |
Yes, I think that would be perfect.
I don't understand — if people specify an interface name, how are we going to build the iptables rules? |
This issue is done, so it can be closed. |
When allocating a port for a container (with
-p 42
), a NAT rule is inserted into the host's netfilter tables.The initial implementation did insert a single rule in the
PREROUTING
table, which led to two issues:The first issue is partially addressed by #98. However, it doesn't handle traffic directed to localhost.
We want to address the following problems. In the following examples, let's assume that with started a container with
-p 42
, and that it was mapped to port 42424.telnet localhost 42424
doesn't work.telnet google.com 42424
will loop back to our container.Both problems are hard.
I don't know if it is possible to solve the first one with netfilter. I thought that it would involve one
OUTPUT
rule (toDNAT
the traffic) and onePOSTROUTING
rule (toSNAT
the traffic), but the latter doesn't work (the rule is never matched by the traffic).The workaround might be to setup an userland proxy, bound to 127.0.0.1:42424, redirecting connections to the container. Not very elegant, though.
To solve the second problem, we need fine-scoped rules. It would be convenient to know the outbound interface (i.e., if the traffic is outbound to eth0, do not
DNAT
it), but unfortunately, that cannot work, since the outbound interface is known after thePREROUTING
chain is traversed (and this is the chain where we would insert theDNAT
rule).It looks like the only solution would be to enumerate all the local addresses of the host, and to maintain rules for all of them.
The text was updated successfully, but these errors were encountered: