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
docker-proxy processes UDP packets from a remote host #44688
Comments
I believe #8795 On my tests, I used
For completeness, I also used #43409 assumes there's a race condition between the userland proxy start up and iptables rules setup. In fact this issue shows the problem only lies in conntrack entries being created before nat rules are applied, and thus are totally ignored by netfilter. Moreover, this fix is incomplete because it calls Also note that, unlike UDP, TCP and probably SCTP are totally immune to this issue since the handshake is aborted if nothing listen on dest port, and thus no conntrack entry is created. I'm going to submit a patch today 🙂 EDIT: This is a duplicate of #16720. |
Conntrack entries are created for UDP flows even if there's nowhere to route these packets (ie. no listening socket and no NAT rules to apply). Moreover, iptables NAT rules are evaluated by netfilter only when creating a new conntrack entry. When Docker adds NAT rules, netfilter will ignore them for any packet matching a pre-existing conntrack entry. In such case, when dockerd runs with userland proxy enabled, packets got routed to it and the main symptom will be bad source IP address (as shown by moby#44688). If the publishing container is run through Docker Swarm or in "standalone" Docker but with no userland proxy, affected packets will be dropped (eg. routed to nowhere). As such, Docker needs to flush all conntrack entries for published UDP ports to make sure NAT rules are correctly applied to all packets. Fixes (at least) moby#44688, moby#8795, moby#16720, moby#7540. Signed-off-by: Albin Kerouanton <albinker@gmail.com>
Conntrack entries are created for UDP flows even if there's nowhere to route these packets (ie. no listening socket and no NAT rules to apply). Moreover, iptables NAT rules are evaluated by netfilter only when creating a new conntrack entry. When Docker adds NAT rules, netfilter will ignore them for any packet matching a pre-existing conntrack entry. In such case, when dockerd runs with userland proxy enabled, packets got routed to it and the main symptom will be bad source IP address (as shown by moby#44688). If the publishing container is run through Docker Swarm or in "standalone" Docker but with no userland proxy, affected packets will be dropped (eg. routed to nowhere). As such, Docker needs to flush all conntrack entries for published UDP ports to make sure NAT rules are correctly applied to all packets. Fixes (at least) moby#44688, moby#8795, moby#16720, moby#7540. Signed-off-by: Albin Kerouanton <albinker@gmail.com>
Conntrack entries are created for UDP flows even if there's nowhere to route these packets (ie. no listening socket and no NAT rules to apply). Moreover, iptables NAT rules are evaluated by netfilter only when creating a new conntrack entry. When Docker adds NAT rules, netfilter will ignore them for any packet matching a pre-existing conntrack entry. In such case, when dockerd runs with userland proxy enabled, packets got routed to it and the main symptom will be bad source IP address (as shown by moby#44688). If the publishing container is run through Docker Swarm or in "standalone" Docker but with no userland proxy, affected packets will be dropped (eg. routed to nowhere). As such, Docker needs to flush all conntrack entries for published UDP ports to make sure NAT rules are correctly applied to all packets. - Fixes moby#44688 - Fixes moby#8795 - Fixes moby#16720 - Fixes moby#7540 - Fixes moby/libnetwork#2423 - and probably more. As a precautionary measure, those conntrack entries are also flushed when revoking external connectivity to avoid those entries to be reused when a new sandbox is created (although the kernel should already prevent such case). Signed-off-by: Albin Kerouanton <albinker@gmail.com>
Thank you, @akerouanton! I've tested e927539, the source address is correct. |
Conntrack entries are created for UDP flows even if there's nowhere to route these packets (ie. no listening socket and no NAT rules to apply). Moreover, iptables NAT rules are evaluated by netfilter only when creating a new conntrack entry. When Docker adds NAT rules, netfilter will ignore them for any packet matching a pre-existing conntrack entry. In such case, when dockerd runs with userland proxy enabled, packets got routed to it and the main symptom will be bad source IP address (as shown by moby#44688). If the publishing container is run through Docker Swarm or in "standalone" Docker but with no userland proxy, affected packets will be dropped (eg. routed to nowhere). As such, Docker needs to flush all conntrack entries for published UDP ports to make sure NAT rules are correctly applied to all packets. - Fixes moby#44688 - Fixes moby#8795 - Fixes moby#16720 - Fixes moby#7540 - Fixes moby/libnetwork#2423 - and probably more. As a precautionary measure, those conntrack entries are also flushed when revoking external connectivity to avoid those entries to be reused when a new sandbox is created (although the kernel should already prevent such case). Signed-off-by: Albin Kerouanton <albinker@gmail.com> (cherry picked from commit b37d343) Signed-off-by: Cory Snider <csnider@mirantis.com>
Conntrack entries are created for UDP flows even if there's nowhere to route these packets (ie. no listening socket and no NAT rules to apply). Moreover, iptables NAT rules are evaluated by netfilter only when creating a new conntrack entry. When Docker adds NAT rules, netfilter will ignore them for any packet matching a pre-existing conntrack entry. In such case, when dockerd runs with userland proxy enabled, packets got routed to it and the main symptom will be bad source IP address (as shown by moby#44688). If the publishing container is run through Docker Swarm or in "standalone" Docker but with no userland proxy, affected packets will be dropped (eg. routed to nowhere). As such, Docker needs to flush all conntrack entries for published UDP ports to make sure NAT rules are correctly applied to all packets. - Fixes moby#44688 - Fixes moby#8795 - Fixes moby#16720 - Fixes moby#7540 - Fixes moby/libnetwork#2423 - and probably more. As a precautionary measure, those conntrack entries are also flushed when revoking external connectivity to avoid those entries to be reused when a new sandbox is created (although the kernel should already prevent such case). Signed-off-by: Albin Kerouanton <albinker@gmail.com> (cherry picked from commit b37d343)
Description
A remote host (10.8.4.1) is sending a stream of UDP packets to the Docker host (10.8.4.2), e.g. 10.8.4.1:10000 → 10.8.4.2:9555, so that there is a conntrack record in the kernel. Then a container listening for this UDP stream starts. Despite originating from the remote host, the stream gets handled by docker-proxy. The source address of the packets seen in the container is replaced by the address of the Docker bridge. If conntrack records are flushed or the UDP stream is restarted, the packets start reaching the container with the original source address (10.8.4.1).
Reproduce
On the remote host (10.8.4.1),
hping3
must be installed.On the Docker host (10.8.4.2),
conntrack
,ss
, andtcpdump
must be installed.Docker daemon settings are the default.
sudo hping3 --udp --flood --keep --destport 9555 --data 1 10.8.4.2
conntrack -L -p 17
docker run --rm -d --name server -p 9555:9555/udp raesene/ncat -nul 0.0.0.0 9555
nsenter -n -t
docker inspect -f '{{ .State.Pid }}' servertcpdump -nvi eth0 udp | head
ss -aunp | grep docker-proxy
conntrack -D -p 17 --dport 9555
nsenter -n -t $(docker inspect -f '{{ .State.Pid }}' server) tcpdump -nvi eth0 udp | head
docker stop server
Expected behavior
The container receives packets with the remote host source address from the start.
docker version
docker info
Additional Info
No response
The text was updated successfully, but these errors were encountered: