Before container is started, docker daemon check available of published port by binding to published port. For sip port 5060 this looks as
[root@aeyears ~]# netstat -anp | grep 5060
udp6 0 0 :::5060 :::* 102113/dockerd
If bind successful, then configured iptables rules for container.
Issue rise when inbound UDP packet populate conntrack table when dockerd daemon bound to host port, but iptables rules for container is not populated.
In this case conntrarck tables contains row like
udp 17 17 src=208.68.17.52 dst=192.168.4.16 sport=5060 dport=5060 [UNREPLIED] src=192.168.4.16 dst=208.68.17.52 sport=5060 dport=5060 mark=0 secctx=system_u:object_r:unlabeled_t:s0 use=1
Here you can find substring
dst=192.168.4.16 sport=5060 dport=5060 [UNREPLIED] src=192.168.4.16
Where dst address is packet L3 destination address when packet is received.
And src address of process/daemon bind that receive packet stream.
As you can see here packets received to IP 192.168.4.16 via UDP transport to port 5060 and processed by daemon that bound to socket IP 192.168.4.16 via UDP transport to port 5060.
To this socket is bound dockerd daemon. This daemon silently drop received UDP traffic when userland-proxy disabled.
In this case permanent UDP streams like syslog messages, SIP OPTIONS check newer reach container process and always connected to docker daemon black hole bind.
How it can be reproduced
On other host need to start UDP stream like
export SERVER_IP=217.12.247.220
nc -u ${SERVER_IP} 5060 < /dev/zero
Then on docker host need to populate /etc/docker/daemon.json file like this:
{
"userland-proxy": false
}
Restart docker daemon
Then start test using command
conntrack -D
docker run --rm=true -d --network=host --name host_bind kamailio/kamailio-ci
sleep 10 \
docker stop host_bind \
docker run -it --rm -p 5060:5060/udp --entrypoint=tcpdump --name tcpdump kamailio/kamailio-ci -ni any
After last command container not able to receive UDP stream started on other host.
How to fix
When userland-proxy disabled and dockerd daemon received packet, then need reset related connection tracking record using command like
conntrack -D \
--reply-src {dockerd_bind_ip} \
--proto ${dockerd_bind_proto} \
--reply-port-src {dockerd_bind_port} \
--src ${client_source_ip} \
--sport ${client_source_port}
Before container is started, docker daemon check available of published port by binding to published port. For sip port 5060 this looks as
If bind successful, then configured
iptablesrules for container.Issue rise when inbound UDP packet populate conntrack table when
dockerddaemon bound to host port, but iptables rules for container is not populated.In this case conntrarck tables contains row like
Here you can find substring
Where
dstaddress is packet L3 destination address when packet is received.And
srcaddress of process/daemon bind that receive packet stream.As you can see here packets received to IP 192.168.4.16 via UDP transport to port 5060 and processed by daemon that bound to socket IP 192.168.4.16 via UDP transport to port 5060.
To this socket is bound
dockerddaemon. This daemon silently drop received UDP traffic whenuserland-proxydisabled.In this case permanent UDP streams like syslog messages, SIP OPTIONS check newer reach container process and always connected to
dockerdaemon black hole bind.How it can be reproduced
On other host need to start UDP stream like
Then on docker host need to populate
/etc/docker/daemon.jsonfile like this:{ "userland-proxy": false }Restart docker daemon
Then start test using command
After last command container not able to receive UDP stream started on other host.
How to fix
When
userland-proxydisabled anddockerddaemon received packet, then need reset related connection tracking record using command likeconntrack -D \ --reply-src {dockerd_bind_ip} \ --proto ${dockerd_bind_proto} \ --reply-port-src {dockerd_bind_port} \ --src ${client_source_ip} \ --sport ${client_source_port}