NetworkManager-openconnect with X.509 Certificates

Daniel Lenski dlenski at gmail.com
Mon Jan 2 13:29:47 PST 2017


On Sun, Jan 1, 2017 at 6:53 AM, Gareth Williams
<gareth at garethwilliams.me.uk> wrote:
>
> I'm trying to figure out why I can easily connect to my openconnect
> server when using the command line, but cannot connect when using
> NetworkManager-openconnect.
>
> The successful command line is simply:
>
> /usr/sbin/openconnect <hostname>:444 --certificate gareth.crt --sslkey
> gareth.key --cafile cert1.crt

What you are doing here could be called a "single-pass" connection:
you are telling OpenConnect to connect to the gateway, authenticate,
obtain a session cookie, and then use that cookie to set up the VPN
tunnel… all at once.

> However, if I transpose that to NetworkManager's openconnect GUI and try
> to connect, it instantly fails.  I used the --cafile above for 'CA
> Certificate', --certificate above for 'User Certificate' and --sslkey
> for 'Private Key'.
>
> running:
>
> execsnoop -a16
>
> shows that NetworkManager is running the following when I attempt to
> connect:
>
> /usr/sbin/openconnect --servercert
> sha1:11e55e29dceaf27a52a039af9844c0b6d2b9abda --syslog --cookie-on-stdin
> --script
> /usr/lib/NetworkManager/nm-openconnect-service-openconnect-helper
> --interface vpn0 <IP address>:444
>
> I noticed that there is no mention of certificates in that command.

NetworkManager, by contrast, uses a "two-pass" connection approach.
Per the OC manual, there are two phases of the VPN setup, which can be
run *separately*: http://www.infradead.org/openconnect/manual.html

    The connection happens in two phases. First there is a simple
HTTPS connection over which the user authenticates somehow - by using
a certificate, or password or SecurID, etc.
    Having authenticated, the user is rewarded with an HTTP cookie
which can be used to make the real VPN connection.

    The second phase uses that cookie in an HTTPS CONNECT request, and
data packets can be passed over the resulting connection. In auxiliary
headers exchanged with the
    CONNECT request, a Session-ID and Master Secret for a DTLS
connection are also exchanged, which allows data  transport over UDP
to occur.

As far as I know, recent versions of NM-openconnect use libopenconnect
for the first phase, and run the actual openconnect binary for the
second phase. When you copy the command used by NM-openconnect, you
are only doing the second phase of the connection, which will always
fail because you aren't giving it a valid cookie.

You should try doing a two-pass connection from the CLI:

$ /usr/sbin/openconnect <hostname>:444 --certificate gareth.crt
--sslkey gareth.key --cafile cert1.crt --authenticate
...
Enter your username and password
Username: …
Password: …
…
COOKIE=3311180634 at 13561856@1339425499 at B315A0E29D16C6FD92EE
HOST=10.0.0.1:444
FINGERPRINT=sha1:11e55e29dceaf27a52a039af9844c0b6d2b9abda

$ <use the variables shown above>

$ echo $COOKIE | /usr/sbin/openconnect $HOST --cookie-on-stdin
--servercert $FINGERPRINT
…
Connection established.

Notice that the certificate and login credentials are NOT used in the
second pass; only the cookie is used. Does this work? If so, then we
know the two-pass connection works from the command-line, so there
must be something missing in how NM is invoking the second phase.

-Dan



More information about the openconnect-devel mailing list