Skip to content

Instantly share code, notes, and snippets.

@moklett
Created July 24, 2012 15:21
Show Gist options
  • Save moklett/3170636 to your computer and use it in GitHub Desktop.
Save moklett/3170636 to your computer and use it in GitHub Desktop.
OpenConnect VPN on Mac OS X

Unfortunately, the Cisco AnyConnect client for Mac conflicts with Pow. And by "conflicts", I mean it causes a grey-screen-of-death kernel panic anytime you connect to the VPN and Pow is installed.

As an alternative, there is OpenConnect, a command-line client for Cisco's AnyConnect SSL VPN.

Here's how to get it set up on Mac OS X:

  1. OpenConnect can be installed via homebrew:

     brew update
     brew install openconnect
    
  2. Install the Mac OS X TUN/TAP driver

  3. (Optional) Running openconnect requires sudo, presumably because it affects resolution of DNS. So, I added password-less sudo ability for the openconnect command.

     sudo visudo -f /etc/sudoers
    

And added this line:

    %admin  ALL=(ALL) NOPASSWD: /usr/local/bin/openconnect
  1. (Optional) When connecting to your SSL VPN, openconnect may complain about a "self-signed certificate" being in the chain and force you to explicitly accept it every time. The self-signed cert is actually the root certficate and (hopefully) is one with implicit trust (i.e. trusted by browsers), so we can safely trust it by specifying the CA file after exporting it from KeyChain:

  2. Determine the name your root certificate (i.e. visit your SSL VPN in Chrome, click the green lock, click "Certificate Information") Find Certificate Information Observe Root Certificate

  3. Open the Keychain Access App

  4. Search the "System Roots" keychain to find your root certificate and select it Keychain Access

  5. File > Export Items... the certificate as a .pem file somewhere on your hard drive (I put it in ~/.ssh/<certificate name>.pem

  6. Connect!

     sudo openconnect --user=<VPN username> --cafile=<.pem file from step 4.3> <your vpn hostname>
    

    The only thing you should be prompted for is your VPN password. I added the command to my aliases file.

  7. To disconnect, just Ctrl-c in the window where you started the VPN connection.

Note

I had an incident after an unclean VPN exit where later the VPN hostname could not be found. I guess the DNS resolver was messed up. I was forced to reboot to fix it so I could reconnect to the VPN.

@ralberts
Copy link

ralberts commented Feb 2, 2018

Thank you!

@AlJohri
Copy link

AlJohri commented May 28, 2018

In case it helps anyone, I used these bash functions to start and stop the vpn more easily with openconnect and juniper (junos pulse):

vpnsetup() {
    sudo sh -c 'echo "%admin ALL=(ALL) NOPASSWD: /usr/local/bin/openconnect, /bin/kill" > /etc/sudoers.d/openconnect'
}

vpnstart() {
    cat ~/.work_password | sudo openconnect \
        --background \
        --pid-file="$HOME/.openconnect.pid" \
        --juniper \
        --user=$USERNAME \
        --authgroup=$AUTHGROUP $ADDRESS \
        --passwd-on-stdin
}

vpnstop() {
    if [[ -f "$HOME/.openconnect.pid" ]]; then
        sudo kill -2 $(cat "$HOME/.openconnect.pid") && rm -f "$HOME/.openconnect.pid"
    else
        echo "openconnect pid file does not exist, probably not running"
    fi
}

$USERNAME is your username, cat ~/.work_password has your password vpn password, $AUTHGROUP is your authgroup, and $ADDRESS is like address where you connect to the vpn (like ra.blah.com)

@nhajratw
Copy link

nhajratw commented Sep 14, 2018

Hopefully this can help someone (@hadifarnoud) building on @AlJohri 's functions, I did this in ZSH. My networking also was getting messed up after disconnect, but stopping and starting the WIFI & Ethernet seems to have done the trick:

en0 is my wifi, and en7 is my ethernet:

function vpnstart() {
  echo 'MY_PASSWORD' | sudo openconnect --background --pid-file=$HOME/.openconnect.pid --user=nayan --passwd-on-stdin --protocol=gp vpn.hq.nodalexchange.com
}

function vpnstop() {
  sudo kill -2 `cat "$HOME/.openconnect.pid"` && rm -f "$HOME/.openconnect.pid"
  sleep 3
  sudo ifconfig en7 down
  networksetup -setairportpower en0 off
  sudo ifconfig en7 up
  networksetup -setairportpower en0 on
}

@jankkm
Copy link

jankkm commented Oct 11, 2018

Thank you so much for this tutorial. It still works on Mohave.
I just had to do 2 steps:

  1. Install openconnect via homebrew
  2. Do sudo openconnect --user=<user> <server>

After typing the password I am already connected.

I did a third step to allow my standard user account to use it:
3. Add user ALL=PASSWD: /usr/local/bin/openconnect to /etc/sudoers with command sudo visudo
with NOPASSWD it can be used without a password if you want to use a script.

@bdarge
Copy link

bdarge commented Oct 25, 2018

@jankkm I'm using openconnect version v7.08 in Mojave but It is not working for me, the last error is "route: writing to routing socket: Can't assign requested address". It happened after I upgraded OS to Mojave.

The complete command is, sudo openconnect --protocol=nc $VPN_HOST -b -v --pid-file=$PID_FILE --user $user --servercert $cert. What could be the cause?

thanks

@tibraga
Copy link

tibraga commented Jan 15, 2019

I have same problem of @bdarge :(

@tibraga
Copy link

tibraga commented Jan 15, 2019

For users mac os:

Create file with content: https://gist.github.com/cattyhouse/f3e2d1621e731ea7e26f

and in comand, add this parameter --script with locale of file

For me, this works in mac Sierra and Mojave.

@lxnk
Copy link

lxnk commented Jan 19, 2019

Guys, did anyone tried to integrate openconnect with a native MacOS VPN interfaces?

@moklett
Copy link
Author

moklett commented Mar 26, 2019

A friend just alerted me that he found these instructions I wrote here ~7 years ago via a Google search. I didn't even realize it had all of these comments on it 😆 . I'm glad its been useful.

FWIW, these days I just use Tunnelblick: https://www.tunnelblick.net/

So, go grab Tunnelblick and then consult one of my other gists to make The Perfect Margarita. Cheers!

@vegerot
Copy link

vegerot commented Apr 16, 2019

@tibraga your link is dead

@sahelidey
Copy link

Hi I followed the instructions above and was able to connect to vpn server using openconnect command line. But it displays the following lines -

add host : gateway
add net : gateway
delete net default: gateway
add net default: gateway

Where does the above have to be set in MacOS

@huataihuang
Copy link

huataihuang commented Jul 4, 2019

Q: How to solve "Failed to connect utun unit: Operation not permitted" ?

If you use sudo openconnect vpn.example.com , it seems create vpn connect, but after a moment, the connection will lost:

DTLS handshake failed: Resource temporarily unavailable, try again.
Failed to connect utun unit: Operation not permitted
Failed to open tun device: Operation not permitted
Set up tun device failed
Unknown error; exiting.

A: In macOS, you need switch to root, then use openconnect.

Don't use sudo openconnect vpn.example.com , you need:

# FIRST switch to root
sudo su -
# THEN create vpn as root
openconnect vpn.example.com

Now openconnect use utun device in macOS, you DO NOT need install Mac OS X TUN/TAP driver any more.

OS X (native support only for TUN (utun))

@todgru
Copy link

todgru commented Nov 2, 2019

Originally, I used Cisco AnyConnect to connect to my work vpn and OpenVPN client to connect to a second vpn.

I was able to install openconnect on OS X 10.14.5 using brew install openconnect .
to connect to my work vpn, from the command line I use sudo openconnect https://vpn.my-office.com
I enter username and password.

I did not run into any issues with keychain or certificates. I did not need to install any other software, drivers or libs.

Thanks for the gist!

@sangnguyen7
Copy link

sangnguyen7 commented Nov 27, 2019

Did anyone successfully install OpenConnect VPN or Cisco AnyConnect on Mac OS 10.15?

@lamoboos223
Copy link

can i login to global protect via mac terminal? if so, how to do it?

@BitLox
Copy link

BitLox commented Jan 7, 2020

Did anyone successfully install OpenConnect VPN or Cisco AnyConnect on Mac OS 10.15?

10.15.2 using OpenConnect-GUI works fine for me
I set everything up via the Streisand Project

@colceagus
Copy link

Guys, did anyone tried to integrate openconnect with a native MacOS VPN interfaces?

+1

@nsayer
Copy link

nsayer commented Sep 14, 2020

OpenConnect (from brew) on Big Sur is giving me a problem:
getaddrinfo failed for host '_host_': nodename nor servname provided, or not known Failed to open HTTPS connection to _host_ Failed to obtain WebVPN cookie

But I can look up the IP address of the host from the command line just fine, ping it etc.

Substituting the IP address in the URL works (though I have to accept the SSL cert identity).

What's going on?

@davidguerrero5
Copy link

Experiencing this on the macOS 11.0 Big Sur beta.
Was able to get VPN to work by:

  1. Uninstalling Cisco AnyConnect
  2. Install Homebrew - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
  3. brew install openconnect
  4. sudo openconnect {server address}

@santi-d
Copy link

santi-d commented Sep 22, 2020

anyone know how to use user and password from LDAP or SAML?

@bms8197
Copy link

bms8197 commented Oct 14, 2020

It's working on MacOS Catalina even with Cisco AnyConnect installed. Route problem solved (Cisco was not allowing me to override some routes that I needed).

Installed openconnect using brew, then the command I used is this:
sudo openconnect -b --pid-file=vpn.pid--user=vpnuser --cafile=vpn-server-cert.pem --servercert pin-sha256:generated-hash vpn-server-hostname

vpnuser = your user
vpn-server-cert.pem - cert file saved while accessing the vpn server hostname in a browser (I used Firefox)
generated-hash - if you try to directly connect to the vpn server, there's a warning about not recognizing the certificate and it's showing a hash. That's the hash I used
vpn-server-hostname - you can use either hostname or the ip of the vpn server (I've used the hostname to get rid of that certificate warning)

Hope it helps!

@kabenin
Copy link

kabenin commented Oct 21, 2020

It's working on MacOS Catalina even with Cisco AnyConnect installed. Route problem solved (Cisco was not allowing me to override some routes that I needed).

Hi, can you please share how you resolved to routing problem? This is something I'm struggling with, trying to have both AnyConnect and openconnect, connected to 2 different VPNs .
Thanks.

@bms8197
Copy link

bms8197 commented Oct 22, 2020

It's working on MacOS Catalina even with Cisco AnyConnect installed. Route problem solved (Cisco was not allowing me to override some routes that I needed).

Hi, can you please share how you resolved to routing problem? This is something I'm struggling with, trying to have both AnyConnect and openconnect, connected to 2 different VPNs .
Thanks.

I'm not running AnyConnect and OpenConnect in parallel. I was saying that I've solved the routing issues generated by Cisco AnyConnect. By that I mean that I switched from AnyConnect to OpenConnect.

Using Cisco Anyconnect, I always got a 10. route which was messing up other custom routes I had. Cisco AnyConnect takes over the routing table and it's not allowing you to modify the routes even if I was manually adding a route it was not actually reflecting in the routing table. So I've stopped using Cisco Anyconnect and replace it with openconnect.

I don't have a solution to your problem. I guess you could run 2 openconnect in parallel, one for a VPN and the other open to replace the Cisco AnyConnect. At least this is how I would do it.

@rschwass
Copy link

Modifying the sudoers file in this manner is a bad idea. Anyone running a configuration like this will open themselves up to a local privilege escalation vulnerability. An attacker that gains unprived access to your system can use openconnect's --script option to run other commands on the box as root.

@choodique
Copy link

hi 👋

Maybe someone has faced the situation and can help?
The situation is that recently a second password is required to connect to the VPN.
Is there any way to implement the second password through the command line?

Cisco AnyConnect Window

@socialsorcery
Copy link

Hi @choodique
The open connect CLI supports two options, token-secret and token-mode which will let you enter a second password assuming it's based around a common method of 2FA. For a typical totp code (like you'd use with google authenticator on your phone), you'd add the following:
--token-mode=totp
--token-secret=base32:$VPN_TOTP_SECRET \

Here, the TOTP_SECRET is not the 6 digit code, but rather the long secret key which the app will use to generate these codes. Here I've encoded it using base32 and stored it securely.

Note: This will completely negate the protection of 2FA if your device is compromised, at the very least you should be storing these credentials somewhere only you can access, preferably using a proper secrets manager.

From the openconnect man page:

       --token-mode=MODE
              Enable one-time password generation using the MODE algorithm.
              --token-mode=rsa will call libstoken to generate an RSA SecurID
              tokencode, --token-mode=totp will call liboath to generate an RFC
              6238 time-based password, and --token-mode=hotp will call liboath
              to generate an RFC 4226 HMAC-based password. Yubikey tokens which
              generate OATH codes in hardware are supported with
              --token-mode=yubioath. --token-mode=oidc will use the provided
              OpenIDConnect token as an RFC 6750 bearer token.

       --token-secret={ SECRET[,COUNTER] | @FILENAME }
              The secret to use when generating one-time passwords/verification
              codes.  Base 32-encoded TOTP/HOTP secrets can be used by
              specifying "base32:" at the beginning of the secret, and for HOTP
              secrets the token counter can be specified following a comma.

              RSA SecurID secrets can be specified as an Android/iPhone URI or a
              raw numeric CTF string (with or without dashes).

              For Yubikey OATH the token secret specifies the name of the
              credential to be used. If not provided, the first OATH credential
              found on the device will be used.

              For OIDC the secret is the bearer token to be used.

              FILENAME, if specified, can contain any of the above strings.  Or,
              it can contain a SecurID XML (SDTID) seed.

              If this option is omitted, and --token-mode is "rsa", libstoken
              will try to use the software token seed saved in ~/.stokenrc by
              the "stoken import" command.

@choodique
Copy link

Hi @choodique The open connect CLI supports two options, token-secret and token-mode which will let you enter a second password assuming it's based around a common method of 2FA. For a typical totp code (like you'd use with google authenticator on your phone), you'd add the following: --token-mode=totp --token-secret=base32:$VPN_TOTP_SECRET
...

In my situation, "Password" and "Second password" are identical and must be set at the same time.
Because of this echo MyPassword before openconnect... command doesn't work =(

@architegrity
Copy link

I've created a shell script (https://github.com/sorinipate/vpn-up-for-openconnect) that automates some of this stuff. I hope it helps!

@webmaster777
Copy link

Use security to store and retrieve passwords from your Keychain if you use that as password manager: https://www.netmeister.org/blog/keychain-passwords.html

I use security find-generic-password -a myuser -s "mydomain" -w | sudo openconnect --passwd-on-stdin ... which removes the extra password prompt.

@rayovims
Copy link

there is just one big issue with openconnect, if you kill the process via "Activity Monitor", it messes up with networking. nothing works! LAN and WiFi.

is there any way to fix the networking issue after killing the process? I'm using Applescript to automate connection. sometimes openconnect stops working and all I can do is killing it via Activity Monitor.

Did you ever figure this out? I’m in this exact same scenario. It was working then I got disconnected from inactivity then my WiFi doesn’t work anymore

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment