Understanding the Network Isolation Problem
By default, Docker creates an isolated bridge network for containers. This means that while containers can communicate with each other via their internal IP addresses, they are not directly accessible from outside the Docker daemon unless specific ports are published. When you run a Dnsmasq container, it typically listens on port 53 for DNS queries. If you do not map this port to the host interface, external tools cannot send requests to it.
ZeroTier operates as a virtual overlay network, assigning IPs to your VPS and client devices. Traffic from these clients arrives at the VPS’s physical network interface. However, if the packet destined for the Docker container’s IP is blocked by the host’s firewall (such as firewalld on CentOS 7) or if the container is not bound to the correct interface, the connection fails. The issue is rarely about ZeroTier itself but rather about how Docker handles incoming traffic and how CentOS manages firewall rules.
If you have previously configured Nginx redirects for subdomains, you might be familiar with exposing HTTP/HTTPS ports. DNS requires similar explicit configuration but often gets overlooked because it runs on a different protocol layer. For more details on managing multiple Docker services, see Setting up Nginx Traffic Redirect for Subdomains on VPS with Multiple Docker Containers and Cloudflare.
Step-by-Step Solution
To make your Dnsmasq container accessible via ZeroTier, follow these steps to configure Docker and the CentOS 7 firewall correctly.
1. Configure Docker Compose or Run Command
You must publish the DNS port so that Docker binds it to the host’s network interfaces. If you are using a docker-compose.yml file, ensure the ports section includes the mapping:
services:
dnsmasq:
image: jasonhenry/dnsmasq
container_name: dnsmasq
ports:
- "53:53/tcp"
- "53:53/udp"
volumes:
- ./dnsmasq.conf:/etc/dnsmasq.conf
restart: always
If you are running the container manually, use the -p flag:
docker run -d --name dnsmasq -p 53:53/tcp -p 53:53/udp jasonhenry/dnsmasq
This command tells Docker to forward incoming TCP and UDP traffic on port 53 of the host to the container. Ensure that your dnsmasq.conf inside the container is configured to listen on 0.0.0.0 or specifically on the interface that Docker uses, rather than just 127.0.0.1.
2. Adjust CentOS 7 Firewall Rules
CentOS 7 uses firewalld by default. Even if Docker publishes the port, firewalld may block incoming connections on port 53. You need to allow DNS traffic through the firewall.
First, check the current status:
sudo firewall-cmd --state
To allow DNS traffic permanently, add the service rule:
sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --reload
If you prefer to open the specific port instead of using the service name:
sudo firewall-cmd --permanent --add-port=53/tcp
sudo firewall-cmd --permanent --add-port=53/udp
sudo firewall-cmd --reload
After reloading, verify that the port is open:
sudo firewall-cmd --list-ports
3. Verify ZeroTier Connectivity
Once Docker and the firewall are configured, test the connectivity from a ZeroTier client. Use a tool like dig or nslookup pointing to the VPS’s ZeroTier IP address.
dig @ example.com
If this returns a response, the configuration is successful. If it times out, check if any intermediate firewalls between the client and the VPS are blocking UDP/TCP port 53. Also, ensure that the Dnsmasq container is actually running and listening on the expected interface.
For troubleshooting other Docker process issues on CentOS 7, such as identifying DDOS attacks, refer to Identifying DDOS Attacked Docker Process on CentOS 7 TellIP Server.
Common Pitfalls
- Binding to localhost: If your Dnsmasq configuration forces binding to
127.0.0.1, external connections will fail even if the port is published. Change it to0.0.0.0. - DNS over HTTPS (DoH): Standard Dnsmasq does not support DoH. If clients expect encrypted DNS, you need a different setup involving Nginx or a dedicated DoH proxy.
- IPv6 Issues: If your ZeroTier network uses IPv6, ensure your Docker daemon and firewall rules also handle IPv6 traffic. See Running IPv6 DNS Server Inside CentOS Docker Container for related configurations.
Frequently Asked Questions
Why can I ping the VPS but not reach the Dnsmasq container?
Pinging works at the ICMP level and reaches the host, but DNS requires specific TCP/UDP port access. If the port is not published in Docker or blocked by firewalld, the packet is dropped before reaching the container.
Does ZeroTier require special Docker network modes?
No, you do not need --network host. Using the default bridge network with port publishing is sufficient and safer. Host networking exposes all container ports directly to the host OS, which increases security risks.
How do I test if Dnsmasq is working locally?
Run docker exec -it dnsmasq nslookup google.com inside the container. If this works, the container is functional. Then test from the host using dig @127.0.0.1 to confirm the port forwarding is active.
What if I get a "connection refused" error?
This usually means the port is open but no service is listening. Check if the Dnsmasq container crashed or failed to start. Use docker logs dnsmasq to view startup errors.
Can I use a different port for DNS to avoid conflicts?
Yes, you can map a non-standard port like -p 5353:53. However, most standard DNS clients expect port 53. You would need to configure your clients to use the custom port explicitly.