dnsmasq exits with an address already in use, and the log names the port rather than the culprit. On a machine that also runs a VPN, the reflex is to blame the pushed routes, but a bind failure happens before any client sends a query. Something already holds the socket, and the job is to identify it. Route changes cannot free a port.

Five steps, in this order: reproduce the error, list the listeners, understand the wildcard, assign the job, then verify.

Step 1: reproduce and read the error

Start dnsmasq in the foreground with the same configuration the service uses, so the error appears in your terminal instead of a log you have to guess at. Note the address family and the local address in the message. A bind to a specific address and a bind to the wildcard are different failures with different owners.

Keep the exact text. An address in use, a permission failure and a missing interface all arrive as a failure to start, and they point at three different repairs.

Step 2: list the owners

List the sockets first. A filter on source port 53 shows both transports and the owning process when you have privilege to see it:

ss -lntup 'sport = :53'

Read the output in columns: transport, local address, port, process. A TCP listener and a UDP listener are separate sockets, so stopping one does not free the other. A wildcard address covers every interface, which means the VPN address is already taken even though no line mentions it by name. And the process name tells you whether this is a distribution-managed resolver, a container, or something a previous experiment left running.

Step 3: the wildcard trap

The bind-interfaces option changes whether dnsmasq binds a wildcard socket or one socket per configured interface, as the dnsmasq reference describes. Without it, dnsmasq may bind the wildcard and filter requests by interface instead, which fails immediately when another daemon holds the wildcard. Linux adds bind-dynamic, which handles interfaces created after startup, a real concern when the VPN interface appears only on connect.

That is why two daemons that both look configured for different interfaces still collide. The conflict is at the socket, not at the intent. Choose the binding mode deliberately and read the documented behaviour for your version before changing it.

Step 4: assign the job

Decide which daemon answers VPN clients and which answers the host. One resolver listening on the tunnel address and forwarding upstream is a common arrangement; two resolvers each assuming it owns port 53 is not an arrangement at all.

Then express that decision in each service's own configuration: listen addresses, interface filters and forwarding. Change them through the service's owner, whether that is the distribution unit, the network manager or the container runtime, so the change survives a restart.

Step 5: verify the socket, then the path

After the restart, confirm the intended sockets exist before testing a client. A daemon that never bound cannot be rescued by a route, and a client failure against a correctly bound socket is a different problem with a different fix. Then check reachability from a client on the tunnel. Only after that is it worth asking whether the required names resolve.

Three separate results to keep apart: the socket exists, the client reaches it, the answer is correct.

What not to do

Do not stop an unfamiliar resolver to free the port without knowing what depends on it, because the host's own lookups usually do. Do not copy an old recipe that moves the second daemon onto a public listen address, since that decides who may query you as a side effect. And do not add a forward when the failure was local.

If the machine is managed, record the ownership decision where the next administrator will find it. Port conflicts return whenever an image is rebuilt.

Barruulee wal qabatan