Two uplinks, one gateway, and a WireGuard peer whose traffic keeps surfacing on the backup line. The handshake stays healthy throughout. That is why the symptom is easy to misread as a WireGuard fault rather than a routing one.

Work the checks below in order. Each one has a stop condition, and skipping ahead usually produces a confident wrong answer.

Separate the Handshake From the Forwarded Flow

The encrypted peer exchange has an endpoint route to the server's public address. Forwarded client traffic has a different destination and may be selected by marks or policy rules. They are two routing decisions that share an interface. Treating one as evidence about the other is the first mistake.

Stop as soon as you catch yourself reasoning from the handshake. It is evidence about the endpoint path only.

Read the Policy Rule, Not the Default Table

A default table shows what happens when no policy rule matches. On a gateway that routes by source, mark or destination, the deciding rule lives elsewhere. The plain table can look perfectly reasonable while the real choice is made above it.

ip rule show
ip route show table main
ip -4 route get 203.0.113.9 from 10.30.8.2

Read the policy rules and the tables they point to. Then confirm which rule matches your test flow. A rule that references an interface which no longer carries the intended uplink is a finding, not a detail. The route lookup at the end shows the answer far faster than reading a table and guessing.

Check the Mark and the Translation Together

Policy routing keys on a packet mark set earlier in the chain. If the marking rule misses your traffic, the flow falls through to the main table and leaves by whatever default is there. Forwarded packets often skip chains that were written for locally generated traffic.

nft list chain inet filter prerouting
conntrack -L -s 10.30.8.2 2>/dev/null | head
ip -s link show dev eth1

Translation has to agree with the uplink that carries the flow. A rule that translates to the primary address while the packet leaves by the backup line produces replies addressed to an interface the flow never used. Check the translation rule's own interface condition. An unconditional rule works until the second uplink is used, then fails in a way that looks intermittent.

Watch Which Interface Carries the Reply

Capture on both uplinks while one request runs. Note which interface carries the request and which carries the reply. Asymmetric paths are much easier to see than to predict.

If the reply arrives on the wrong uplink, the problem has moved from WireGuard to connection tracking or translation. No change to the peer configuration will fix it.

Change One Thing With a Way Back

Keep console or out-of-band access before editing policy rules on a gateway. Make one change, test the same authorized destination, then reconnect and confirm the handshake still uses the intended endpoint path. Add a numeric test on the second address family, because a v4-only policy leaves the same mistake available.

Record which uplink each flow used. That record turns the next report into a two-minute check instead of an afternoon. WireGuard's notes on namespaces and routing describe how to separate the endpoint path from tunnelled traffic deliberately, which is usually cleaner than copying a default-route workaround.

Related articles