You asked: "Can someone explain why this problem occurs in the first place?"
Based on what is reported in the official OpenVPN FAQ I bet it's caused by a routing problem within the OpenVPN engine.
To better clarify the scenario, let me refer to following diagram:
Here you can see:
- an OpenVPN "server" connected to the HEADQUARTER internal network (10.0.1.0/24)
- an OpenVPN "client" running at a Remote Site, and connected to the remote 192.168.1.0/24 network
- we're assuming that the OpenVPN tunnel is established and:
- OpenVPN "server" is reachable via its own tun interface, with address 10.10.0.1. Also the P2P address, used by the tun interface is 10.10.0.2 (this is important for later discussion, so let's emphasize it)
- OpenVPN "client" has a tun interface with IP 10.10.0.2
Now, let's assume that:
- the OpenVPN "Client" has redefined it's default gateway, so to redirect within the tunnel all the outgoing IP traffic;
- the OpenVPN "Client" has IP_FORWARDING enabled and, as such, can route packets coming from its internal LAN (192.168.1.0/24) (I'm emphasizing this point, as it's critical for our discussion).
With such a scenario in place, let's check in detail what happens when R_PC1 (192.168.1.2) send a packet, like an echo-request, to L_PC1 (10.0.1.2):
- after leaving R_PC1 NIC, the packet reach OpenVPN client;
- OpenVPN client (that is configured to act as a common router), route it according to it's routing table. As it's default-gateway is the tunnel, it sends the packet to the tunnel;
- Packet reach the tun interface of the OpenVPN server. OpenVPN will "see" it and, as it (OpenVPN server) knows that 10.0.1.2 is an address belonging to its LAN subnet, it "forward" the packet, from TUN to LAN;
- Packet reach L_PC1.
So everything is fine...
Now let's check what happens with the echo-reply that L_PC1 reply to R_PC1.
- echo-reply leaves L_PC1 NIC and reach OpenVPN server LAN interface (10.0.1.1);
Now, if we want OpenVPN Server being able to reach the remote site, we need to define the routing with a "static route". Something like:
route add -net 192.168.1.0 netmask 255.255.255.0 gw 10.10.0.2
Please note the P2P address used as gateway.
Such static routes will operate at OS-level. In other words, it's needed for the operating system to properly route the packet. It means something like: "Please, all the traffic addressed to 192.168.1.0/24 subnet needs to be forwarded to the OpenVPN engine, with whom the OS is able to talk via the P2P address". Thanks to such static route, now...
- the packet leaves the OS-routing context and reaches OpenVPN. The OpenVPN instance running on the OpenVPN Server. So, at this point, the OS has nothing more to do and all the routing (within the VPN) is left to the OpenVPN server software.
So, now, the problem is: how, the openvpn server software, will be able to decide the route of a packet, with SRC_IP 10.0.1.2 and DST_IP 192.168.1.2?
Please note that, based on the configuration of OpenVPN server, it knows nothing about the 192.168.1.0/24 network, nor the 192.168.1.2 host. It's not a connected client. It's not a local client.
OpenVPN, also, knows that it is not the "OS-Router", so it doesn't really want (and can....) send the packet back to the local gateway. So the only option, here, is to raise an error. Exactly the error you're experiencing
To say it with the language of the FAQ: "...it doesn't know how to route the packet to this machine, so it drops the packet...".
How can we solve the problem?
As you can see from the official documentation, the option iroute serves exactly to our scope:
--iroute network [netmask]
Generate an internal route to a specific client. The netmask
parameter, if omitted, defaults to 255.255.255.255.
This directive can be used to route a fixed subnet from the server
to a particular client, regardless of where the client is
connecting from. Remember that you must also add the route to the
system routing table as well (such as by using the --route
directive). The reason why two routes are needed is that the
--route directive routes the packet from the kernel to OpenVPN.
Once in OpenVPN, the --iroute directive routes to the specific
So you need a:
--iroute 192.168.1.0 255.255.255.0
to be applied (to the server) when your OpenVPN client connect, for example via an ad-hoc configuration file defined on the server (client-config-dir, etc.).
Should you wonder why this problem does not happen at step 2) above, my understanding is that OpenVPN Client knows how to route it, 'cause it knows that the VPN-tunnel is a default-gateway.
The same cannot be done at OpenVPN Server, 'cause there the default gateway is tipically not overridden. Also, consider that you could have a single OpenVPN server with plenty of OpenVPN client: each client knows how to reach the server but... how can, the server, decide which is the client acting as a gateway for an unknown subnet?
As for your first question(Can the required rules be written in a generic/one-off way?), I'm sorry but I'm not getting your very problem. Can you rephrase providing more details?