Closed RossBoylan closed 3 weeks ago
Quick comment: use option --validate=pid
to skip the ipinfo validation. This can also be controlled via an env var (see the help).
I'll have to try that. Thanks for the tip. I assume using it causes some loss of reliability of the tests.
Alternately, there's a simple solution that involves no code change. Just add the IP range for the server ipinfo.io
to the file of intranet IPs and everything works. I used
# ensure that our queries go through VPN
# a totally non-robust hack
# ipinfo.io
# # dig +noall +answer ipinfo.io
# ipinfo.io. 300 IN A 216.239.38.21
# ipinfo.io. 300 IN A 216.239.34.21
# ipinfo.io. 300 IN A 216.239.36.21
# ipinfo.io. 300 IN A 216.239.32.21
216.239.32.0/21
It would be more robust to do a dns lookup dynamically, parse the results, and forward just for those specific IPs. That would involve code changes, the need to identify a dns lookup tool, etc.
Just for the record, --validate=pid
also allowed the program to conclude it was on the VPN.
ipinfo.io
is not the only server the script uses to check status. There is also
UCSF_VPN_PING_SERVER Ping server to validate internet (default: 9.9.9.9)
.
This has caused me no trouble, but if the point is to see if it is reachable through the VPN that probably should be added to the list of IPs to send through the VPN (the one with 216.239.32.0/21 above).
When I connect I frequently get a message that I'm not connected along with a string indicating a connection through my ISP rather than UCSF. But the connection works, and when I test status again all is well.
I suspect this is a race condition in which the commands that reset the routing info, in particular for 216.239.3x.21, have either not executed or not taken effect before the status check. The route is reset by the modified version of vpnc-script I use.
When I discovered that
curl
had an--interface
argument I thought I could use it to guarantee that the query went out through the VPN. But nothing ever comes back when I do that. I don't know why.
I started to dig into this. I got this working. As a starter, when I'm connected to the VPN, my IP routing shows:
$ ip route show | grep -E "^default "
default dev tun0 scope link
default via 192.168.1.1 dev wlp0s20f3 proto dhcp metric 600
Based on this, I use:
$ interface=$(ip route show | grep -E "^default " | grep -vF " tun" | cut -d ' ' -f 5)
$ echo "$interface"
wlp0s20f3
When I use this network interface with curl
, I circumvent the VPN connection;
$ curl --interface "${interface}" https://ipinfo.io/json
{
"ip": "123.123.123.123",
"hostname": "123.123.123.123.example.org",
"city": "SomeCity",
"region": "SomeState",
"country": "SomeCountry",
"loc": "123.123,123.123",
"org": "AS12312 Foo Bar",
"postal": "12312",
"timezone": "America/Los_Angeles",
"readme": "https://ipinfo.io/missingauth"
}
ucsf vpn routing
will now report on this interface;
$ ucsf vpn routing
Default non-VPN network interface: wlp0s20f3
IP routing table (126 entries):
default dev tun0 scope link
default via 192.168.1.1 dev wlp0s20f3 proto dhcp metric 600
...
$ ucsf vpn --version
5.7.0-9006
It cut off my local network. I couldn't print, and other computers in my house couldn't use my machine, which, among other things was serving as the internet gateway and primary server.
This seems to no longer be the case, or, at least it's not happening to me. I can access my local 192.168.1.*
network after connecting to the VPN. I think the proof lies in:
$ ucsf vpn status
OpenConnect status: 'openconnect' process running (PID=1469057)
Connected to the VPN
$ ip route show | grep -E "^192[.]168[.]"
192.168.1.0/24 dev wlp0s20f3 proto kernel scope link src 192.168.1.19 metric 600
FWIW, I have the above both when I'm connected to the VPN and not.
Testing it while connected gives:
$ ping -c 1 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=2.78 ms
--- 192.168.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 2.777/2.777/2.777/0.000 ms
$ curl --head 192.168.1.41
HTTP/1.1 411 Length Required
Cache-Control: no-cache
Content-Length: 974
Content-Type: text/html
Connection: close
Server: debut/1.30
Pragma: no-cache
This is with:
$ bin/ucsf-vpn --version --full
ucsf-vpn 5.7.0-9009
OpenConnect 8.20-1
I've updated ucsf-vpn
so that it passes any options following --args
to the openconnect
tool, e.g.
ucsf vpn start --args --script=$PWD/selectiveTunnel
@RossBoylan , could you please see if this works for your selectiveTunnel
script? You need to grab bin/ucsf-vpn
from the develop branch. If this works, then it's the first baby step towards providing built-in support for selective tunneling.
I've got everything working for manually tweaking the IP routing using ucsf vpn start --args --script=$PWD/selectiveTunnel
. I've also started on a more user-friendly approach to customize this. The skeleton for this is in the new ucsf-vpn 5.8.0, but more to come next.
WHY
The standard way this tool, and AFAIK other UCSF VPN clients, work is that all traffic gets sent through the UCSF network. This seemed undesirable to me because
On the other hand:
HOW
The
selective
branch of https://github.com/RossBoylan/ucsf-vpn/ has the code I've been using for quite awhile to do selective tunneling. Most of the action is in theselectiveTunnel
script, which is a modified version of the standard helper script thatopenConnect
uses to manage networking. It works in connection with a file of the IP ranges that make up the internal network to which one is connecting. UCSF network services has requested that this not be made public, and so it is not on github.ucsf-vpn
needs two types of changes. It needs to call openconnect with the name of the revised helper script; for now that is hard-coded. Second, the selective tunneling violates some of the assumptions the script makes in identifying whether one is connected. It does this by executingand seeing what comes back. But, since
ipinfo.io
is not inside the VPN, the traffic doesn't go through the VPN, and so the info that comes back indicates there is no VPN connection--even though there is.When I discovered that
curl
had an--interface
argument I thought I could use it to guarantee that the query went out through the VPN. But nothing ever comes back when I do that. I don't know why.If you go a couple of commits back, to 7974b85a59eaecc092c8156b85869ee9520e1eda, you'll see the code I was using that was working. That was based on a much older version of master, which used different strategies for figuring out the connection info. Those strategies also needed to be tweaked for the selective tunneling. The current code in master is more robust, but it still can't deal with the selective tunneling.
I should also note that the new code in
selectiveTunnel
works for me on Debian GNU/Linux 10. It will probably work on most linux's; it is unlikely it will work in other OS's.QUESTIONS
Do you think selective tunneling is a desirable feature? A security risk?
How can we determine if we have a connection to the VPN when selective tunneling is in place?
STATUS
If you use the current tip of my
selective
branch it won't work [actually it will with either of the 2 approaches describe in later posts]. You'll get a selective connection, butucsf-vpn
won't realize that. Also, it won't work unless you have a list of IP ranges considered inside the vpn in/etc/vpnc/UCSFIntranet
.I'm going to continue using the older version mentioned above pending a better solution.