【VPN】OpenConnect

Posted by 西维蜀黍 on 2022-03-04, Last Modified on 2023-05-02

Install

# macOS
$ brew install openconnect
# Ubuntu
$ sudo apt-get install openconnect

Connect

$ echo "<your pwd>" | sudo openconnect -c ~/Downloads/my.pem --user bob --passwd-on-stdin -b https://your.company.vpn.com/

# If the private key is in a separate file from the certificate, this must be specified with -k
$ openconnect -c certificate.pem -k private_key.pem https://vpn.mycompany.com/

# When debugging
$ openconnect --timestamp -vvvv https://vpn.mycompany.com/

Running as non-root user

Error

Under normal circumstances OpenConnect needs to be run as the root user. If it cannot create the local tun network interface, you will see an error such as:

$ openconnect -c ~/my.pem --user shiwei --passwd-on-stdin -b https://oneconnect.xxx.com/
mkdir: cannot create directory '/var/run/vpnc': Permission denied
Failed to bind local tun device (TUNSETIFF): Operation not permitted
To configure local networking, openconnect must be running as root

Solution - Pre-configured tun device

On Linux, it’s possible to create its tun device in advance. For example:

# view interfaces
$ ipconfig -a
...

# add vpn0
$ sudo ip tuntap add vpn0 mode tun user dwmw2

# view interfaces
$ ipconfig -a
...
vpn0: flags=4240<POINTOPOINT,NOARP,MULTICAST>  mtu 1500
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
       

This creates a device vpn0 which can be opened by user dwmw2 who can pass traffic to/from it without needing any elevated privileges. You can now tell OpenConnect to use that device by adding “-i vpn0” to its command-line arguments. Note that the /dev/net/tun device node should be readable and writeable by everyone.


Of course, something does also need to configure the IP addresses and routing. You could either add “-s /bin/true” to OpenConnect’s command line to stop it trying to run vpnc-script for itself, and manually configure the network as root too. Or you could use “-s 'sudo -E /etc/vpnc/vpnc-script'” so that OpenConnect itself runs without elevated privileges but can still invoke vpnc-script as root. Note the -E part which ensures the environment variables with the configuration are actually passed through to vpnc-script.

NetworkManager usually has a dedicated unprivileged user nm-openconnect and runs OpenConnect as that user, having pre-created the tun device for it. OpenConnect then invokes a “vpnc-script” provided by NetworkManager which just passes all the configuration back to NetworkManager over DBus.

$ openconnect -c ~/my.pem --user shiwei --passwd-on-stdin -i vpn0 -b https://oneconnect.xxx.com/        
...
mkdir: cannot create directory '/var/run/vpnc': Permission denied
SIOCSIFMTU: Operation not permitted
mkdir: cannot create directory '/var/run/vpnc': Permission denied

Ref

Status

$ ps aux | grep openconnect

Stop

$ sudo killall -SIGINT openconnect"

Routing and DNS

OpenConnect just handles the communication with the VPN server; it does not know how to configure the network routing and name service on all the various operating systems that it runs on.

To set the routing and name service up, it uses an external script which is usually called vpnc-script. It’s exactly the same script that vpnc uses. You may already have a vpnc-script installed on your system, perhaps in a location such as /etc/vpnc/vpnc-script.

Split tunneling

Split tunneling is a computer networking concept which allows a user to access dissimilar security domains like a public network (e.g., the Internet) and a local LAN or WAN at the same time, using the same or different network connections. This connection state is usually facilitated through the simultaneous use of a Local Area Network (LAN) Network Interface Card (NIC), radio NIC, Wireless Local Area Network (WLAN) NIC, and VPN client software application without the benefit of access control.

For example, suppose a user utilizes a remote access VPN software client connecting to a corporate network using a hotel wireless network. The user with split tunneling enabled is able to connect to file servers, database servers, mail servers and other servers on the corporate network through the VPN connection. When the user connects to Internet resources (Web sites, FTP sites, etc.), the connection request goes directly out the gateway provided by the hotel network.

vpn-slice

Install

macOS

$ brew install vpn-slice

Ubuntu

$ sudo pip3 install "vpn-slice[dnspython,setproctitle]"

First steps

Before trying to use vpn-slice with openconnect or vpnc, check that it works properly on your platform, and can verify that it has all of the access and dependencies that it needs (to modify /etc/hosts, alter routing table, etc.):

$ sudo vpn-slice --self-test
***************************************************************************
*** Self-test passed. Try using vpn-slice with openconnect or vpnc now. ***
***************************************************************************

When you start trying to use vpn-slice for real, you should use the diagnostic options (e.g openconnect -s 'vpn-slice --verbose --dump') to troubleshoot and understand its behavior.

Using vpn-slice

# route to VPN by subnet
$ sudo openconnect gateway.bigcorp.com -u user1234 \
    -s 'vpn-slice 192.168.1.0/24'

# route to VPN by domains
$ sudo openconnect gateway.bigcorp.com -u user1234 \
    -s 'vpn-slice <domain>'
e.g., 
$ sudo openconnect gateway.bigcorp.com -u user1234 \
    -s 'vpn-slice git.my_company.com jira.my_company.com'

$ cat /etc/hosts

Ref

Test Routing

IP info

$ ifconfig
...
utun3: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1230
	inet 10.22.60.175 --> 10.22.60.175 netmask 0xffffffff

Routing Info``

$  netstat -nr
Routing tables
Internet:
Destination        Gateway            Flags           Netif Expire
default            10.22.60.175       UGScg           utun3
10.22.56/21        10.22.60.175       UGSc            utun3
10.22.60.175       10.22.60.175       UHr             utun3
10.22.60.175/32    link#16            UCS             utun3
...

Testing

$ route get 10.129.80.19
   route to: git.my_company.com
destination: default
       mask: default
    gateway: 10.22.60.175
  interface: utun3
      flags: <UP,GATEWAY,HOST,DONE,WASCLONED,IFSCOPE,IFREF,GLOBAL>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
       0         0         0         0         0         0      1230         0
$ route get 192.168.18.1
   route to: 192.168.18.1
destination: 192.168.18.1
  interface: en0
      flags: <UP,HOST,DONE,LLINFO,WASCLONED,IFSCOPE,IFREF,ROUTER>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
       0         0         0         0         0         0      9000      1200	
       
$ route get google.com
   route to: 192.168.18.1
destination: 192.168.18.1
  interface: en0
      flags: <UP,HOST,DONE,LLINFO,WASCLONED,IFSCOPE,IFREF,ROUTER>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
       0         0         0         0         0         0      9000      1200	       

How to List all Subdomians

思路1 - 暴力穷举所有subdomains

refer to https://swsmile.info/post/brute-force-subdomains/

思路2 - auto switch to VPN

Refer to https://swsmile.info/post/VPN-dynamic-split-tunneling/

类似问题

Keep the VPN Alive

# after running openconnect
...
Mar 23 00:21:52 esxiubuntu bash[2511]: Error: any valid prefix is expected rather than "local/32".
Mar 23 06:46:14 esxiubuntu bash[2280]: Received server disconnect: b0 'Idle Timeout'
Mar 23 06:46:14 esxiubuntu bash[2280]: Send BYE packet: Server request
Mar 23 06:46:14 esxiubuntu bash[15667]: RTNETLINK answers: No such process
Mar 23 06:46:14 esxiubuntu bash[2280]: Session terminated by server; exiting.
...

Basically most VPNs (certainly at least GlobalProtect, and I think AnyConnect too) differentiate between…

  1. A disconnect-if-idle time: the VPN gateway will drop the connection (and invalidate the session authentication cookie) if there’s no “real” traffic after that period of time. What vpn-slice -K tries to do is generate some “real-looking” traffic (not entirely repetitive, but low volume) to prevent such a drop.
  2. A total session lifetime: the VPN gateway will drop the connection and invalidate the session authentication cookie after this period of time, no matter what. Client software can’t do anything about this.
  3. (possibly) A key lifetime: the VPN will need to be re-keyed with new encryption keys (for ESP, TLS, DTLS, etc.) after a certain period of time. Fully-implemented client software should handle this automatically; OpenConnect does for AnyConnect, GlobalProtect, and Juniper NC at least.

Solution 1 - Use vpn-slice

$ echo "<your pwd>" | sudo openconnect -s 'vpn-slice --prevent-idle-timeout <domain>' -c ~/Downloads/my.pem --user bob --passwd-on-stdin -b https://your.company.vpn.com/

Ref

Solution 2 - a script

Let’s create a script that will:

  1. connect to your VPN;
  2. check every x seconds whether it is still connected
  3. reconnect to the VPN if the connection is broken

In the below example we’ll create a sw_vpn.sh script.

sudo vim ~/sw_vpn.sh

Copy the following into in your script:

#!/bin/bash
 
function checkOpenconnect() {
  if [ $(pgrep -l openconnect | wc -l) == "1" ]; then
    echo "$(date) - openconnect is still running"
  else
    echo "$(date) - about to init openconnect"
    startOpenConnect
  fi
}
 
function startOpenConnect {
    # start here open connect with your params and grab its pid
    echo "<PASSWORD>" | openconnect --no-cert-check -u <USER> -b --passwd-on-stdin <VPN.ADDRESS> 2>&1
}
 
startOpenConnect
 
while true; do
  # sleep a bit of time
  sleep 10
  echo "$(date) - checking conn"
  checkOpenconnect
done
echo "$(date) - about to exit the script"

Let’s at least lock this file down to be only readable by root:

sudo chown root:root sw_vpn.sh
sudo chmod 711 sw_vpn.sh

Running script in background

Once your happy with your script you can run said script as a background script:

cd ~/
sudo ./sw_vpn.sh &

Or run on-boot

$ sudo vim /etc/systemd/system/sw_vpn.service
[Unit]
Description=SW VPN
After=network.target

[Service]
ExecStart=/bin/bash /home/sw/my_vpn.sh

[Install]
WantedBy=multi-user.target

$ sudo systemctl enable sw_vpn.service; sudo systemctl start sw_vpn.service; sudo systemctl status sw_vpn.service

View Logs

$ journalctl -f -u sw_vpn.service

Stopping background script

To stop/disconnect the VPN and script, use ps to find the PID’s of the VPN script and the openconnect process by:

sudo ps -aux | grep vpn

I would kill the VPN process by PID

sudo kill 10525 28445

Ref

Reference