testing a new SSL+ESP VPN

Daniel Lenski dlenski at gmail.com
Fri Oct 7 23:52:42 PDT 2016

On Wed, Oct 5, 2016 at 3:58 AM, David Woodhouse <dwmw2 at infradead.org> wrote:
> On Wed, 2016-10-05 at 00:38 -0500, Daniel Lenski wrote:
> > On Tue, Oct 4, 2016 at 1:47 PM, David Woodhouse <dwmw2 at infradead.org> wrote:
> > > At least Cisco had the decency to call this a 'CONNECT' request :)
> >
> > Gotcha. Clearly more than one brilliant mind has thought, "IP over TCP
> > is such a beautiful idea. Let's add HTTP and make it even more
> > beautiful."
> I detect sarcasm, but this is actually a sane design choice. If you
> want a VPN to work from anywhere, you *have* to run it over HTTPS.
> There are *plenty* of networks from which a client can't connect to
> *anything* except HTTPS in the outside world.
> Coupled with SOCKS/HTTP proxy support in the client, you can connect to
> an HTTPS service from fairly much *anything*.
> Having the UDP connectivity is needed too, of course, but you *have* to
> fall back to actually passing traffic over HTTPS if you want to provide
> a reliable service.

Fair enough :-). It turns out that the stream format in this
particular case is pretty simple, so I should quit my whining and/or

I ended up using a modified version of this Python SSL proxy
(https://github.com/inaz2/proxy2) to capture the
CONNECT-masquerading-as-GET tunnel traffic. It took me quite a while
to get the client-to-proxy and server-to-proxy connections set up just
right... I'll post the code once I've cleaned it up a bit, since it
may be useful for others trying to log similar proxies.

After I got all that sorted out, I was able to decode the IP-over-SSL
stream from the tunnel (< means gateway-to-client, > means
client-to-gateway, both followed by hex byte strings):

     GET /ssl-tunnel-connect.sslvpn?user=Myusername&authcookie=deadbeefdeadbeefdeadbeefdeadbeef

    < 53544152545f54554e4e454c
    < 1a2b3c4d0800005401000000000000004500005461e400007e11f5520a100f030a12c23d[...]
    > 1a2b3c4d08000034010000000000000045000034038f0000011108df0a12c23de00000fc[...]

In other words:

1. The gateway sends the 12 bytes 53544152545f54554e4e454c
("START_TUNNEL" in ASCII) to indicate the tunnel has started
2. Every packet begins with 4 magic bytes: 1a2b3c4d
3. The next 2 bytes are probably the Ethertype: 0800 (= IPv4)
4. The next 2 bytes are the packet size (as int16_le)
5. The next 8 bytes are always 0100000000000000 in my testing (1 as an
6. The remainder is the Layer 3 IPv4 packet (starting with 45 in the
examples above)

For some reason, the Windows client drops the tunnel connection after
a few seconds of running it through a (non-transparent) proxy. It
seems to get stupidly confused as soon as it changes the default route
and thinks it has lost communication with the proxy. However, I've
captured enough to be pretty confident about this format. I started
logging the stream in a format that can be read by text2pcap, so it's
pretty easy to verify the correctness of the IPv4 packets.

> Sounds good. I think it should fit into the OpenConnect two-phase model
> relatively well. For the authentication phase (obtain_cookie) we
> probably use just your Request #1 and Response #2. Remember, this runs
> in the *user's* session, and can interact with the user for passwords
> and can have access to client certificate if there is one.

Yes, I was thinking the same thing. It fits in nicely with the
--authenticate flag that I know and love and frequently abuse with
OpenConnect :-D

> The "cookie" is an arbitrary opaque string passed from the
> authentication phase (potentially via NetworkManager) to the connection
> phase. In your case you'd want it to contain at least the "Myusername",
> "Gateway-Name", "cookie" and perhaps also the 'company domain name'.
> Then the tcp_connect() function makes Request #2 and receives the IP
> and routing information, then tcp_mainloop() passes traffic.
> Personally, I'd worry about doing the ESP later, after all that is
> working.

I'll start hacking on the OpenConnect code and will try to get the SSL
tunnel working before ESP.

> I note your example is all Legacy IP — can you observe it using IPv6?

The VPN that I have access to provides only IPv4 routing. Since the
IP-over-SSL stream protocol is so simple, IPv6 should just mean a
change of Ethertype... however, according to the vendor they don't
actually support IPv6 on the SSL VPN tunnel:

I don't know what the getconfig XML will look like for an IPv6 network
configuration. A few minutes of googling didn't turn up anything very


More information about the openconnect-devel mailing list