Opened 5 years ago

Last modified 3 years ago

#1046 assigned Feature Wish

Allow modifying OpenVPN internal routing table

Reported by: niksa Owned by:
Priority: minor Milestone:
Component: Management Version: OpenVPN 2.4.6 (Community Ed)
Severity: Not set (select this one, unless your'e a OpenVPN developer) Keywords:
Cc: Selva Nair


On OpenVPN server side, when you want to route a network to a specific client, you add route directive to server config file (adds route to system routing table) and iroute directive to client config file in ccd directory (adds route to OpenVPN internal routing table). However, if the client is already connected, it needs to disconnect and reconnect in order for route to become active. I'd like to have the ability to activate the route without dropping client connection. Adding a route to system routing table is easy enough, but there is no way (that I can see) to modify OpenVPN internal routing table. Please allow modifying the internal routing table via management interface or some other means.

Change History (13)

comment:1 Changed 5 years ago by Gert Döring

Cc: Selva Nair added
Owner: jamesyonan deleted
Status: newassigned

@selvanair: do you understand the management interface intricacies on the server side well enough to estimate how complicated this is?

The whole "multi-instance stuff" is full of magic.

comment:2 Changed 5 years ago by Selva Nair

To add an iroute one needs the multi_context pointer (m) and the multi_instance pointer (mi) for the client. Getting mi from client id (CID) is easy (use lookup_by_cid()) getting it from common-name is a little more work but not hard. So that part is fairly simple and the command could be:

client-add-iroute CID network netmask

Adding and deleting an adhoc iroute may be the trickier part -- we can't just call multi_add_iroutes() again as it iterates through the whole list of iroutes for the client and is already run just before push_reply is sent. But doesn't look too complicated.

Such iroutes will not persist if the client reconnects (i.e the management will need to set it again) and the logic of filtering pushed routes based on client-specific iroute obviously will not work. A pull-filter in the client config will take care of that, though. (An obvious plug for pull-filter :)

comment:3 Changed 5 years ago by niksa

I would be fine with a command which reads client config file again and reloads routes, something like:

client-reload-routes common-name

I would prefer common-name, CID is not very convenient.

comment:4 Changed 5 years ago by Selva Nair

Rereading the ccd file and recreating iroutes look way more complicated to implement than something like client-add-iroute CID/common-name network netmask.

The former involves messy parsing (skip all lines but iroute), need to delete previous iroutes and then set ones found on reload, handle the case of a deleted ccd file etc. An iroute previously set by a client-connect script or plugin may disappear if not found in the reloaded ccd file. Too many corner cases to worry about.

comment:5 Changed 5 years ago by niksa

I would certainly prefer a direct control over routing table. Anyway, I believe it would be useful to be able to manipulate routes without the need to drop the connection. That's pretty much the standard in networking in general.

BTW, client-del-route command would also be necessary.

comment:6 Changed 4 years ago by Antonio Quartulli

This is actually an interesting feature. @selvanair @cron2 are you still planning to work on this? (if you ever had :-P)

I am asking because I wouldn't mind digging into it a little bit

comment:7 Changed 4 years ago by Selva Nair

This is actually an interesting feature. @selvanair @cron2 are you still planning to work on this? (if you ever had :-P

I did implement add-iroute, but got stuck trying to implement delete-iroute -- I think the option to delete is essential to complete this feature.

Just pushed my feature branch on this to github if you would like to take a look.There are three related commits in there but may not be in the best shape. And does not include my attempts at delete-iroute.

comment:8 in reply to:  6 Changed 4 years ago by Gert Döring

Replying to Antonio:

This is actually an interesting feature. @selvanair @cron2 are you still planning to work on this? (if you ever had :-P)

I'm not planning to work on this - mostly due to "I do not have a current need for it, and there are things that I want to get done more urgently". I can see where it is coming from, but it's somewhat similar to "a dial-in user at an ISP needs to have a new subnet routed" - you just add it to the config and bump the user, and on reconnect everything is there. So, you can get it done today, but "reestablishing the VPN" is certainly more heavy than "just add it and be done".

So, whatever :-) - I'm not standing in your way here.

comment:9 Changed 3 years ago by csrf

I'm new here.
what's the status of development for this feature? I've also found a need for this feature. How can i help? I'd be willing to help with either testing or development. I'm not a formal openvpn developer/haven't studied the code too thoroughly, but I'd be willing to give it a shot...

apparently, things stalled with the implementation of the 'delete-iroute', correct? Where should we go from here?

comment:10 Changed 3 years ago by tct


comment:11 Changed 3 years ago by petiepooo

Just a couple of thoughts to help push this feature along.

@niksa, while I agree that client-delete-iroute would make this feature complete, I think there's sufficient utility in just the add ability to be worthwhile. If an iroute to a specific network is no longer needed, it would often be sufficient to remove the route from the host's routing table and leave the orphaned iroute present but unused. This whole feature smells like a "we need to set this up now, but we're not in our maintenance window so we can't bounce the link" emergency case anyway.

If the network route is still needed, but to a different destination, only then does it get a little messy. Bouncing the client would still work to clear and rebuild iroutes, of course. An alternative, if it's not already a host route, is to use a more specific netmask than the prior iroute, just like routes to 0/1 and 128/1 can override the default route of 0/0.

Out of curiosity, what happens now if you try to add a second iroute to the same network/mask but to a different client? Does the second one fail to go in, or does it override the previously entered iroute? If the later, then the alternative above isn't even needed; the iroute can just be overwritten to go where it needs to go. If the destination would be handled by an existing route such as the default route, you may have a redundant iroute until the link is bounced, but that's not a breaking problem.

@selvanair, I've reviewed your git commits in the manage-add-route branch. Your refactors and new code are clean and logical, and go along ways toward completing this feature. Thank you.

Wouldn't adding a client-delete-iroute call be as simple as calling the mroute_helper_del_iroute46() instead of mroute_helper_add_iroute46()? I believe check_stale_routes() would eventually delete everything else. If immediate removal is really needed, that function could serve as a template for what needs to be done after calling mroute_helper_del_iroute46().

I wish I had time to clone, code and test, but I'm afraid I have to play armchair developer today.. :)

comment:12 Changed 3 years ago by niksa

@petiepoo, I have just tried, and it appears that new iroute overrides the previous one. So client-delete-iroute might not be necessary for this to be functional.

comment:13 in reply to:  12 Changed 3 years ago by petiepooo

Replying to niksa:

@petiepoo, I have just tried, and it appears that new iroute overrides the previous one. So client-delete-iroute might not be necessary for this to be functional.

That's great news! Thanks for testing that.

It also brings up a workaround for deletion: add the undesired iroute to a client destination with a link that can be bounced, then bounce that client and the iroute should be gone.

Note: See TracTickets for help on using tickets.