Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for adding a specified route #371

Closed
Ape opened this issue Sep 12, 2018 · 29 comments
Closed

Support for adding a specified route #371

Ape opened this issue Sep 12, 2018 · 29 comments

Comments

@Ape
Copy link

Ape commented Sep 12, 2018

I would like to add a custom route on the ppp interface after the VPN connection has been established. I can currently manually run sudo ip route add 1.2.3.4/32 via 10.20.30.40 dev ppp0 to do this. But it would be a lot easier if openfortivpn did that for me when the interface is created and/or there is a working VPN connection. This way it wouldn't require manual intervention everytime my systems boots (and starts openfortivpn) or after VPN reconnect.

I would suggest something like --add-route 1.2.3.4/32 which would automatically determine the correct gateway address and interface name from the VPN connection.

I would like to avoid --set-routes and --half-internet-routes because I have other networking and VPN connections on the same system.

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented Sep 12, 2018

Duplicate of #22 as far as I can see. See pppd ip-up scripts and option --pppd-ipparam.

Please do not hesitate reopen if that doesn't help.

@thackel
Copy link

thackel commented Sep 12, 2018

I have similar "problems".

As a "normal" user i don't want to modify/create any pppd/ifup/down scripts on a system global scale.
In the future it might be possible to let the Networkmanager do this like i want, but today at least the KDE version does not support any OTP dialog.

For now i created a script which starts and forks openfortivpn and then adds the routes as desired.
So a one-shot like the OP requested would be nice.

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented Sep 12, 2018

I believe --add-route 1.2.3.4/32 would only address part of the requests we have seen. We cannot possibly add multiple options for each different need.

Also I'm not certain it's (currently) possible to clean up the modified route from openfortivpn, after having forked pppd. Perhaps this is best left to pppd. Unfortunately the privileged way to interact with pppd seems to be through scripts in /etc/ppp.

For the above reasons I still believe such needs would be better handled by scripts, either scripts run by pppd or (at the other end) scripts that fork openfortivpn, as suggested above. Hell, I could even agree to a script directly run by openfortivpn if there is no other easy way - but then again we cannot easily clean up when pppd exits.

You are also raising the question how to help normal users. Some ideas, probably not perfect:

  • write documentation,
  • provide sample scripts,
  • have NetworkManager generate scripts,
  • have pppd run a script outside /etc/ppp (but how?),
  • or as a last resort even have openfortivpn run a startup script.

@DimitriPapadopoulos
Copy link
Collaborator

Also I'm not certain a user who runs multiple VPN concurrently with multiple network connections qualifies as normal (with all due respect of course :-).

Such users will probably require different and complex networking options that seem best left to scripting.

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented Sep 12, 2018

Finally please note pull request #370 that will notify the pppd tunnel is up using systemd. Perhaps it can help in this context.

@DimitriPapadopoulos
Copy link
Collaborator

Additional note: Notifying that the pppd tunnel is up may be best left to pppd itself.

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented Sep 12, 2018

One last suggestion: It could be up to the packager to have /etc/ppp/ip-up start a script found in ~/.ppp/ or elsewhere. But then there are probably associated security issues...

I realize I'm desperately trying to have pppd run your startup scripts instead of openfortivpn. Am I completely wrong?

There are many issues at hand:

  1. Detect/notify the pppd tunnel is up (or down for the purpose of cleaning up). I believe this is best left to pppd itself. Unfortunately it seems there is no easy way to have pppd notify the IPv4 tunnel is up (and perhaps IPv6 tunnel some day). Ideas?
  2. How to notify pppd is up (or down)? systemd as in Notify tunnel up to systemd with sd_notify #370 ? D-Bus? Suggestions?
  3. Supposing there is a way to get notified of pppd events, which of pppd or openfortivpn should run startup commands when the pppd tunnel is up (respectively cleanup commands when the pppd tunnel is down)? Perhaps neither of them if D-Bus can notify a 3rd party software the tunnel is up or down? Can we easily perform cleanup from openfortivpn when pppd is down? Ideas?
  4. Because the spectrum of functions to be run at startup is infinite, I believe in scripting instead of constantly adding new options to openfortivpn. The form taken by scripting depends on whether openfortivpn, pppd or 3rd party software notified by D-Bus run the startup commands. Opinions?

More opinions and ideas?

@DimitriPapadopoulos
Copy link
Collaborator

After reading this thread I am convinced one of the most elegant solutions would be to have pppd emit systemd/D-Bus notifications.

Either ask the pppd maintainers or write a pppd plugin.

@feugy
Copy link

feugy commented Nov 12, 2018

@thackel, for what it worth, here is how I've configured pppd to implement selecting routing through openfortivpn:

  1. run openfortivpn with no-route flag, or add set-routes = 0 in your configuration file
  2. create a ppp script when link is up: sudo touch /etc/ppp/ip-up.d/fortivpn
  3. make it executable: sudo chmod a+x /etc/ppp/ip-up.d/fortivpn
  4. add your own routes. I've decided to look up domains by their name:
    #!/bin/bash
    #
    # Whitelist here all domains that need to go through FortiVPN
    # Domains are separated by a space
    #
    domains='example.com example.fr'
    
    let ip
    for domain in $domains; do
      ip=`dig +short $domain | tail -n1`
      route add $ip dev ppp0
    done
    
  5. check the created routes:
    $ route
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    default         192.168.10.254  0.0.0.0         UG    600    0        0 wlp3s0
    one.one.one.one *               255.255.255.255 UH    0      0        0 ppp0
    IP-OF-FIRST-DOMAIN *               255.255.255.255 UH    0      0        0 ppp0
    IP-OF-SECOND-DOMAIN *               255.255.255.255 UH    0      0        0 ppp0
    link-local      *               255.255.0.0     U     1000   0        0 br-cc6b09fa8986
    172.16.238.0    *               255.255.255.0   U     0      0        0 br-30ec352ff3e1
    172.17.0.0      *               255.255.0.0     U     0      0        0 docker0
    172.18.0.0      *               255.255.0.0     U     0      0        0 br-44b22a74e13d
    172.19.0.0      *               255.255.0.0     U     0      0        0 br-cc6b09fa8986
    172.20.0.0      *               255.255.0.0     U     0      0        0 br-2718c069c2ed
    192.168.10.0    *               255.255.255.0   U     600    0        0 wlp3s0
    
  6. check your IP: https://duckduckgo.com/?q=what%27s+my+ip&t=lm&atb=v110-5_h&ia=answer
    It should be your regular IP, while you should have access to white-listed domains through the VPN.

PPP documentation
Hope it helps!

@Eerovil
Copy link

Eerovil commented Nov 15, 2018

@feugy
Wow, thanks for the detailed guide!

I gotta ask, how would you add a route for a specific ip (i.e. no domain available)?
There is info about that in the route manual but I couldn't quite grasp it just yet.

@mrbaseman
Copy link
Collaborator

@DimitriPapadopoulos should we put this on the wiki? (I have just discovered it recently. I guess you have started it in the context of troubleshooting.) We have also thought about putting together an FAQ guide on the wiki in the context of starting openfortivpn as a service and about respawning it.

@DimitriPapadopoulos
Copy link
Collaborator

Sure, let's improve the wiki!

@mrbaseman
Copy link
Collaborator

I have done so, copied a few parts from the issues to the wiki. The sections can still be improved, but at least the topics that we have identified as important get more attention than in closed issues

@feugy
Copy link

feugy commented Nov 30, 2018

Hi @Eerovil, sorry for the delay.

Adding route for specific IP is actually simpler than for domains:

#!/bin/bash
#
# Whitelist here all domains that need to go through FortiVPN
# Domains are separated by a space
#
domains='example.com example.fr'
ips='192.168.0.15'

let resolved
for domain in $domains; do
  resolved=`dig +short $domain | tail -n1`
  ips="$ips $resolved"
done

for ip in $ips; do
  route add $ip dev ppp0
done

I hope it helps!

edited: removed echo 😅

@mrbaseman
Copy link
Collaborator

thanks @feugy I have updated the example on the wiki as well

@mrbaseman
Copy link
Collaborator

I think we can close this issue now. An answer has been provided and we have created the wiki so that users who might not check closed issues can easily find the instructions

@rohanrajpal
Copy link

rohanrajpal commented Apr 28, 2020

Thanks, @feugy for the solution. I went ahead and wrote a blog for any beginner to be able to do this.
https://rohanrajpal.github.io/workfromhome/vpn/networking/selective/routing/systemd/2020/04/25/Selective-network-routing.html
Let me know if I have missed giving credit to this solution or the wiki. I'll update it ASAP.

@DimitriPapadopoulos
Copy link
Collaborator

@rohanrajpal There's already a systemd service file here:
https://github.com/adrienverge/openfortivpn/blob/master/lib/systemd/system/openfortivpn%40.service.in

Since I'm new to these systemd service files, I'm interested in any feedback you may have. I have seen a few differences between our service files:

  • Type: simple or idle, is idle better?
  • In your case aren't these contradictory?
     After=[...] multi-user.target
     
     WantedBy=multi-user.target
    
  • I had initially left this one out, it's probably a good idea to have it so I'll add it:
    Documentation=man:openfortivpn(1)
    
  • I think User=root and KillSignal=SIGTERM are the default so I have left them out. Happy to change that in our own service file if required.

@rohanrajpal
Copy link

Hey, even I'm new to systemd services. Thanks for pointing these things out, I learned a few new things

@rohanrajpal There's already a systemd service file here:
https://github.com/adrienverge/openfortivpn/blob/master/lib/systemd/system/openfortivpn%40.service.in

Since I'm new to these systemd service files, I'm interested in any feedback you may have. I have seen a few differences between our service files:

* `Type`: `simple` or `idle`, is `idle` better?

I prefer idle because the service waits until all active jobs are dispatched, I was just trying to avoid any conflict. However, as we have set After, I don't think simple should cause any problem. I referred to this link.

* In your case aren't these contradictory?
  ```
   After=[...] multi-user.target
   
   WantedBy=multi-user.target
  ```

Oh, my bad, I'll update this in my service.

* I had initially left this one out, it's probably a good idea to have it so I'll add it:
  ```
  Documentation=man:openfortivpn(1)
  ```

great

* I think `User=root` and `KillSignal=SIGTERM` are the [default](https://www.freedesktop.org/software/systemd/man/systemd.kill.html#KillSignal=) so I have left them out. Happy to change that in our own service file if required.

Oh yes, I missed this. I will remove them from mine as well.

@yeya
Copy link

yeya commented Dec 21, 2020

How this script can be used when I use several instances of openfortivpn in parallel?
It will be ppp0 only in the first instance. The interface name will change each time.

Edit: Never mind, I found the answer in ppp docs

this line
route add $ip dev ppp0
should be changed to
route add $ip dev $1

@stevenwjy
Copy link

Hello there, I encountered a similar issue with #291 and tried to use the solution described in this thread and article (thanks @rohanrajpal!) to add the route manually. I have managed to run the openfortivpn successfully and add the ip to my routing table. However, my ssh still hangs as if it is unable to connect to the port 22 of the given ip (which needs the vpn to connect). Any tips on how to check whether my routing works and things that I could potentially miss when trying to connect?

@mrbaseman
Copy link
Collaborator

@stevenwjy simply adding a route does not necessarily give you ssh access to that IP. Usually, the Fortigate Appliance pushes the routes to those IPs / networks for which a firewall rule is configured that allows your account to access them.
Adding a route manually can help in some situations, e.g. when you are dealing with several VPNs or the machine that runs openfortivpn has several interfaces or a complex routing table for some other reasons.

@ayaka14732
Copy link

On Arch Linux, the proposed method does not work.

To make it work, the file name /etc/ppp/ip-up.d/fortivpn should be /etc/ppp/ip-up.d/fortivpn.sh.

This is because, according to /etc/ip-{up,down}, script names in /etc/ip-{up,down}.d need to end with .sh. (See thread)

We can edit the wiki page accordingly.

@deadalnix
Copy link

I have a tunnel that is setup with openforti vpn and require custom routes using debian.

It used to work great with the proposed solution. Now the script in /etc/ppp/ip-up.d stopped running. I have no idea why, no error message no nothing. It just doesn't run anymore and so the routes are not set. I tried the .sh rename in case the same thing was happening as in arch, but it changed exactly nothing.

To be honest, this whole thing is very frustrating and clearly not how it should work.

@DimitriPapadopoulos
Copy link
Collaborator

@deadalnix Please open a separate issue on an Arch Linux site. This doesn't look like it's directly related to openfortivpn.

@deadalnix
Copy link

It's not an arch problem. Sure technically it is not an issue with openforti vpn, but is it really? People keep having problems with the advised solution,a nd because the whole thign happens through openfortivpn, debuggability is really poor.

@DimitriPapadopoulos
Copy link
Collaborator

OK, but please open a new ticket for new issues. Not certain about "people keep having problems with the advised solution". Please provide logs.

@tomaszkubacki
Copy link

just wanted to mention I created simplified version of adding custom routes via config file simply by passing custom routes array through pppd-ipparam details here:
https://github.com/adrienverge/openfortivpn/wiki#method-one---short-version---pass-routes-by-pppd-ipparam

@ailequal
Copy link

ailequal commented Aug 1, 2023

just wanted to mention I created simplified version of adding custom routes via config file simply by passing custom routes array through pppd-ipparam details here: https://github.com/adrienverge/openfortivpn/wiki#method-one---short-version---pass-routes-by-pppd-ipparam

I just updated your snippet by adding support for macOS as well. Thank you a lot!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests