Routing in DCO
When OpenVPN is operating in multi-peer mode it requires a way to understand which peer outgoing packets should be forwarded to.
If DCO is not enabled, OpenVPN creates an internal mapping where specific destinations
are associated with specific peers. This mapping is created following the --iroute and
--iroute-ipv6 directives configured by the user.
With DCO there is no access to any mapping in userspace, therefore DCO must come up with its own solution.
Linux
On Linux DCO simply relies on the system routing table to tell it which peer is responsible for a destination.
Specifically, DCO looks up the destination adress in the main system routing table and uses the nexthop IP to match the responsible peer.
Example:
100.100.0.0/24 via 10.10.0.5 dev ovpn0
This route entry tells DCO that any packet going to 100.100.0.0/24 should be sent to the peer having VPN IP 10.10.0.5.
The matching between the VPN IP and the actual peer instance is performed internally to DCO.
One of the benefit give by this approach, is that any component external to OpenVPN may add or remove VPN routes without directly interacting with OpenVPN. Think about external routing daemons or other processes listening to link notifications.
Userspace
Due to the logic described above, OpenVPN in userspace has been adapted to add such routes when the user specifies any
--iroute or --iroute-ipv6.
