A remote user connects to the hub, reaches the file server on the hub's own LAN, and everything looks healthy. Then they open a share on 10.20.0.50 at headquarters, which the hub reaches over a separate site-to-site tunnel, and it times out. Both tunnels are up and both counters climb, so neither tunnel is broken. Crossing the hub is three routing decisions on three devices, and a tunnel carries only the prefixes it was built for. Here is the order I check, and the command that shows whether each step is true.

Transit needs three lookups, not one tunnel

Every device makes its own longest-prefix match and forgets it. The laptop must send 10.20.0.50 into the tunnel rather than to its local router. The hub must take a packet that arrived on the remote-access interface and hand it to the site-to-site interface. Headquarters must send a reply for the user's address back through the tunnel. Any one of the three failing looks the same in the browser: silence.

That is why testing each tunnel alone proves so little. Pinging the hub's LAN address exercises the first decision, and pinging the hub from headquarters exercises the third. The packet that fails has the user pool as its source and the second site as its destination, so write those prefixes down first. Here the pool is 10.80.0.0/24, the hub LAN is 10.10.0.0/24 and headquarters is 10.20.0.0/24.

Push the far prefix to the remote client

On an OpenVPN remote-access server the client learns routes at connect time. Without a push, a split-tunnel client sends 10.20.0.50 to its own gateway and the packet never enters the tunnel.

push "route 10.20.0.0 255.255.255.0"

A pushed route lands when the client connects, so a user who stays online sees nothing until they reconnect. Verify on the client: ip route get 10.20.0.50 on Linux, route print on Windows. The output should name the tunnel interface.

The push does not help the hub. It is a message to the client, not a route on the server and not a permission to forward, so a hub with the perfect push line still drops the flow one hop later. That is the usual reason people conclude the push failed.

Give the hub a real egress route

The hub needs its own next hop for the headquarters prefix. On a routed tunnel that is an ordinary route through the site-to-site interface, and one command shows both the chosen route and the chosen source:

ip route get 10.20.0.50 from 10.80.0.25
sudo ip route add 10.20.0.0/24 via 172.30.0.2 dev s2s0

Where the site-to-site leg is itself OpenVPN, the route can live in that configuration with the peer's tunnel address as gateway: route 10.20.0.0 255.255.255.0 172.30.0.2. The gateway is not optional. Leave it out and the next hop falls to an implementation default, which differs between a single-remote client and a multi-peer hub.

Policy-based IPsec is different: the hub's kernel sends the packet to its normal LAN gateway and the policy catches it on the way out, so a tunnel route either does nothing or steers traffic past the policy. Watch the source in the command above, because 10.10.0.1 instead of the pool address means the kernel chose an address the far side will reject. iroute is not the answer either; it tells the server which client owns a subnet behind its own tunnel, not where to send traffic for a third site.

Extend the far side to the user pool

Headquarters already covers the hub LAN, 10.10.0.0/24. The user pool is a second prefix and has to be in the selectors too, or no policy covers a reply addressed to 10.80.0.25. Each peer names the same pair of prefix sets from its own side:

# strongSwan swanctl.conf, on the hub
local_ts  = 10.10.0.0/24, 10.80.0.0/24
remote_ts = 10.20.0.0/24
# on the headquarters peer
local_ts  = 10.20.0.0/24
remote_ts = 10.10.0.0/24, 10.80.0.0/24

One device's local_ts is the other's remote_ts. Copy the hub block onto headquarters and the pair is inverted, so the child SA never comes up.

The older ipsec.conf syntax uses a comma-separated leftsubnet. The running security association keeps the selectors it negotiated, so re-establish the tunnel after the edit. A selector changed at 10:00 and tested against an SA that came up at 09:40 still fails, while the config file looks correct throughout.

Then check the last hop. ip route get 10.80.0.25 on the far endpoint should point into the tunnel. If the service uses a LAN router as its default gateway, that router needs the return route as well, or the reply dies there. Running tcpdump -ni eth1 host 10.80.0.25 on that segment shows whether the reply left the endpoint at all.

Permit the flow at the hub

Forwarding must be enabled and the path allowed. Scope the rules to the two prefixes instead of accepting everything between the interfaces.

sysctl -w net.ipv4.ip_forward=1
iptables -I FORWARD -i tun0 -o s2s0 -s 10.80.0.0/24 -d 10.20.0.0/24 -j ACCEPT
iptables -I FORWARD -i s2s0 -o tun0 -s 10.20.0.0/24 -d 10.80.0.0/24 -j ACCEPT

Reverse-path filtering is the quiet failure beside it: with the two legs on different interfaces, rp_filter=1 can drop the reply while the accept rule's counter never moves. Compare iptables -vnL FORWARD before and after an attempt. A rule that never increments is not being reached, so look a layer down rather than rewriting it.

If only one group needs transit, put the route in a per-client file under client-config-dir instead of widening the global push. Source NAT on the hub also removes the need for a far-side return route, but it hides the user's address, so the far site's logs and address-based rules stop telling users apart.

Verify from the client, then roll back in reverse

Test a TCP port, not just ICMP, because a ping can pass while the service stays blocked. nc -vz 10.20.0.50 445 and traceroute -n 10.20.0.50 from the client show whether the second hop is the hub tunnel address. On the hub, tcpdump -ni tun0 host 10.20.0.50 and the same filter on the site-to-site interface: a request on both with no reply on either moves the problem to the far side.

Then test something that must stay blocked. If a host the pool should never reach answers too, you opened more than transit and should narrow the rules. A hub that forwards everything to every spoke passes the first test and fails the second.

Keep a rollback list, because four objects changed and three are easy to forget: the pushed route, the hub's route, the selectors and the firewall rules. Undo them in reverse, re-establish the SA, and have one user reconnect. A partial rollback leaves a route pointing at a tunnel that no longer matches, which is harder to read than the original silence. The OpenVPN 2.6 manual documents push, route and iroute for your version.

Pennadoù liammet