An OpenVPN client dials one address, the server answers from a different one, and the tunnel never comes up. The server log shows the packet arriving and a capture shows a reply leaving, so the failure gets blamed on the client. On a host with several interfaces, or several addresses on one interface, the two sides simply disagree about which address is in use. The reply is valid at the IP layer, yet many clients discard a datagram whose source is not the address they contacted.

What the client sees when the source changes

A UDP socket that is not bound to a specific local address has no fixed source, so the kernel picks one at send time. That choice comes from a route lookup towards the client's address, and the source becomes the address of the interface the lookup selects. On a single-homed machine the choice is invisible; on a host with a management address, a public address and a secondary address on the same NIC, it depends on routing metrics and policy. Policy routing makes the mismatch more likely rather than less, because a rule can select an uplink the client never reached. A default route learned from one provider plus a source rule pointing at another is enough to produce it.

Clients that filter replies, and connection tracking that expects the exact four-tuple and source, will drop the response without a useful message. The tunnel then times out as if nothing had arrived, which is why this gets mistaken for a client-side firewall problem. A capture taken only on the server confirms the mistake rather than explaining it, because the reply really does leave. Compare the reply's source with the address the client dialled before changing anything else.

What the multihome option actually does

The directive is written multihome in a configuration file and --multihome on the command line, and it makes a UDP server answer from the address the client's packet reached. The kernel delivers the original destination address as ancillary data on receive, and OpenVPN uses that value as the source for the response. A server listening on a wildcard address, local 0.0.0.0 for IPv4 or its IPv6 equivalent, then behaves as if each client had reached a dedicated listener. Clients that came in through the public address get replies from the public address, and clients on an internal address get replies from that one. Nothing else in the packet path moves: the route, the filter rules and the tunnel configuration stay exactly as they were.

That last property is why the option is safe to add to an otherwise working server, and also why it cannot repair a filter that only permits one address. The packet still has to be accepted on the path it takes, so the source correction changes the reply's origin and nothing more. It is also UDP-only: a TCP listener does not have this problem in the same form, because the connection is identified by the four-tuple rather than by the reply's source address.

When a fixed local address is the wrong default

Before reaching for the option, check whether the server binds one specific local address, because a bound listener always answers from that address. That is correct for a single-homed deployment and wrong as soon as clients legitimately use more than one address. If the binding was deliberate, decide whether the server should accept traffic on additional addresses at all. Removing the binding increases exposure, so the permitted interfaces and source networks have to be enforced by the service and the filter rather than by the bind address alone.

The OpenVPN reference limits the option to UDP servers, notes the extra packet-path processing, and records which platforms support it. Confirm that on the installed release before planning around it. Where it is unsupported, binding the specific address or fixing the return routing is the alternative, and both are narrower changes than they first appear. Wildcard listening also has consequences beyond replies: a server on all addresses is reachable from every network the host is attached to, which may not be the exposure anyone intended.

Prove the reply source from outside

Test from outside the server, and record the exact address and transport the client used before capturing anything. The three probes below answer three different questions, and the order matters.

tcpdump -ni any udp port 1194
ss -lunp 'sport = :1194'
ip route get 203.0.113.10 from 198.51.100.20

The capture shows the source address on the reply, which is the fact this whole article turns on. The socket listing shows what the server actually bound, because a wildcard listener and a specific one look identical in a configuration file and behave differently on the wire. The route lookup shows the source the kernel would choose for that flow, which explains the capture before you change anything. Repeat all three for IPv4 and IPv6 separately, since they are separate listeners and separate lookups, and a wildcard entry for one family says nothing about the other.

Routing, discovery and filtering stay separate

Preserving the reply's source does not install an outgoing route, update dynamic DNS, or make one address family accept the other. On a server with several uplinks the return path for each source has to be agreed deliberately, or replies leave by an interface the client's filter never permitted. Likewise, a new address after a prefix change has to reach clients through discovery and the supported reconnect flow rather than through the old record.

Leave server identity checks and certificate verification exactly as they are, because a changed address does not justify accepting an unverified peer. If the reply now leaves from the intended source and the tunnel still fails, treat the source problem as solved and move on. The next observed error belongs to routing, filtering or authentication, and changing the listener again will not reach it. Write the reply source into the ticket beside the address the client dialled, so the next person can check the same fact with one command.

Inyandiko zihuye