--- /dev/null
+<PAGE>
+ <INCLUDE file="inc/header.tmpl" />
+
+ <VAR match="VAR_SEL_CONTRIBUTE" replace="selected" />
+ <VAR match="VAR_SEL_CONTRIB_MITM" replace="selected" />
+ <PARSE file="menu1.xml" />
+ <PARSE file="menu2-contribute.xml" />
+
+ <INCLUDE file="inc/content.tmpl" />
+
+<h1>Observing VPN clients</h1>
+
+<p>Most of the VPN <a href="protocols.html">protocols supported by
+OpenConnect</a> are proprietary, undocumented, and in many cases
+overly-complex, perhaps intentionally obfuscated.</p>
+
+<p>In order to add support for <a
+href="contribute.html#new-protocols">new protocols</a>, and sometimes
+even to improve or update support for existing ones, it is often
+necessary to observe existing clients and servers in order to
+understand how they work.</p>
+
+<h2>Observing TLS/SSL connections</h2>
+
+<p>Modern VPN protocols almost always support a UDP-based transport
+for tunneled packets, e.g. DTLS for the Cisco AnyConnect protocol, or
+ESP for the GlobalProtect protocol. This is because <a
+href="http://sites.inka.de/~W1011/devel/tcp-tcp.html">TCP over TCP is
+very suboptimal</a> in terms of performance. However, most VPN
+protocols also support TLS/SSL for connection initiation and as a
+fallback, due to its universal availability even in highly filtered or
+firewalled network environments. <b>It is typically more
+straightforward and productive to start out by observing the TLS/SSL
+side of a new VPN protocol, and saving the UDP-based transport for
+later</b> (See <a
+href="http://lists.infradead.org/pipermail/openconnect-devel/2016-October/004015.html">this
+discussion thread</a> from the <a href="mail.html">mailing list</a>
+during the initial work on the <a
+href="globalprotect.html">GlobalProtect protocol</a>.)</p>
+
+<p>The content of a TLS/SSL connection is end-to-end encrypted and
+authenticated, and the session keys are normally kept only in memory
+by the applications using these connections. Therefore, special
+techniques are needed to decrypt traffic and observe the plaintext
+bytes-on-the-wire of any TLS-based communications protocol.</p>
+
+<p>There are more-or-less 3 possible techniques for decrypting
+TLS-based communications and observing the plaintext. The first two
+shown here are quite simply, but not universally usable; the
+third is more complex but should be applicable to any TLS-based
+VPN protocol.</p>
+
+<h3>(1) Using SSLKEYLOGFILE</h3>
+
+<p>If your VPN client is based on a standard TLS library and does not
+disable this mechanism, it is likely the most straightforward way to
+decrypt TLS traffic.</p>
+
+<p>Most <a
+href="https://en.wikipedia.org/wiki/Comparison_of_TLS_implementations">TLS
+libraries</a> (including OpenSSL, GnuTLS, and LibNSS) support an
+environment variable called <tt>SSLKEYLOGFILE</tt>, which will cause
+applications using those libraries to write "premaster secrets" for
+their TLS/DTLS sessions to a file. This makes it straightforward to
+automatically decrypt the traffic using the Wireshark network protocol
+analyzer. Basically, you should run the VPN client that you're
+observing with this environment variable set, run Wireshark on the
+same computer, and configure Wireshark to use the resulting log file;
+see <a href="https://wiki.wireshark.org/TLS#tls-decryption">Wireshark's
+TLS decryption documentation for details.</a></p>
+
+<p>Note that some proprietary VPN clients disable the
+<tt>SSLKEYLOGFILE</tt> mechanism to prevent decryption of their
+traffic, but many developers overlook this especially in early
+releases of their client software.</p>
+
+<h3>(2) Using server's RSA private key</h3>
+
+<p>If you have access to the RSA private key of a VPN <i>server</i>
+supporting the protocol you're observing (likely because you
+administer such a VPN), and can use RSA key exchange, then you can
+provide this RSA private key to Wireshark and automatically decrypt
+TLS traffic to and from <i>this server</i> using Wireshark; again, see
+<a href="https://wiki.wireshark.org/TLS#tls-decryption">Wireshark's
+TLS decryption documentation for details and limitations.</a></p>
+
+<p>This works because the RSA key exchange supported by TLS (re)uses
+the server's private key for encryption of the ephemeral session keys,
+unlike Diffie-Helman or Elliptic Curve Diffie-Helman exchanges which
+do not. (<a href="https://security.stackexchange.com/a/35521">More
+detailed explanation on StackExchange.</a>)</p>
+
+<p>This lack of <a href="https://en.wikipedia.org/wiki/Forward_secrecy">forward
+secrecy</a> of session keys is indeed why RSA key exchange has been
+deprecated in TLS 1.2 and <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security#Key_exchange_or_key_agreement">removed
+in TLS 1.3</a>. However, most VPN servers and clients continue to
+support TLS 1.2 or older with RSA key exchange for backwards
+compatibility, so this is still a viable option for decrypting traffic
+as of 2022.</p>
+
+<h3>(3) MITM</h3>
+
+<p>If you cannot use either of the above mechanisms, then you will
+need to use the <a
+href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">MITM
+technique</a> to decrypt traffic to/from the VPN client you are
+observing.</p>
+
+<p>The basic idea is to convince the two peers of the TLS connection
+(VPN client and server) that they are communicating directly with each
+other via an end-to-end encrypted TLS session, when in fact each of
+them is in fact communicating with an intermediary (the
+"man-in-the-middle"). The intermediary creates two <i>separate</i>
+TLS sessions: one between the real client and the intermediary, and
+one between the intermediary and the real server. The intermediary can
+inspect and modify traffic before relaying it between the the peers,
+who continue to believe that they are communicating directly with each
+other.</p>
+
+<p>In order to MITM-capture the traffic from a typical proprietary VPN
+client:</p>
+
+<ol>
+ <li>Use <a href="https://mitmproxy.org">mitmproxy</a>, running on
+ Linux. (There are other similar tools available, but the rest of
+ this document will assume you are running <tt>mitmproxy</tt> on
+ Linux.)</li>
+
+ <li>Set up a virtual machine and install the required operating and
+ VPN client. (It is possible to do this using a physical system as
+ well, but this will make transparent routing more complex.) We
+ recommend:
+ <ul>
+ <li>Linux host OS with <a href="https://en.wikipedia.org/wiki/Kernel-based_Virtual_Machine">KVM/QEMU</a>
+ as a hypervisor</li>
+ <li>Guest/VM configured for <a href="https://en.wikibooks.org/wiki/QEMU/Networking#User_mode_networking">user
+ mode networking</a></li>
+ <li>Assuming the guest is running Microsoft Windows as its OS, install <a href="https://access.redhat.com/articles/2488201">RedHat's
+ paravirtualized I/O drivers</a> to improve performance.</li>
+ </ul></li>
+
+ <li><p>Run <tt>mitmproxy</tt> on the host system, and route traffic
+ from the VM through it <i>transparently</i>, that is without setting
+ an explicit proxy.</p><p>With KVM/QEMU and user-mode networking, this
+ consists of setting the guest system's IPv4 gateway to
+ <tt>10.0.2.2</tt> and setting up <tt>iptables</tt> rules on the
+ Linux host to redirect traffic. (Described in more detail in
+ <a href="https://docs.mitmproxy.org/stable/howto-transparent-vms">mitmproxy's
+ guide to transparently proxying virtual machines</a>).</p></li>
+
+ <li><p><b>Browse to the URL <a
+ href="https://mitm.it">https://mitm.it</a> on the VM</b>; this is a
+ special domain intercepted by <tt>mitmproxy</tt> itself.</p><p>The
+ web page shown will help you verify that (a) the VM's traffic is
+ really passing through MITMproxy and (b) the VM's operating system
+ trusts <tt>mitmproxy</tt>'s certificates.</p></li>
+
+ <li>Run the VPN client on the VM, and capture and study its traffic
+ using <tt>mitmproxy</tt> (or <tt>mitmdump</tt>) on the host.</li>
+
+ <li><p>The client and/or server may employ various mechanisms to detect
+ MITM and shut down the MITM'ed connection. <b>Trick,
+ bludgeon, or confuse the client and server into ignoring this</b>;
+ see below for specific examples.</p><p>This usually works by
+ sending a copy or hash/fingerprint of the server's TLS certificate
+ as part of the in-band protocol data, and checking for differences
+ from the certificate exchanged in the TLS handshake. </p></li>
+
+ <li>Repeat these steps iteratively to understand how the VPN
+ client's interaction with the VPN server works.</li>
+</ol>
+
+<p>In cases where your VPN client/server detect MITM'ed connections
+and stop communicating (6), it's typically necessary to write a script
+which will detect and rewrite in-band protocol data containing the
+server's TLS certificate (or a hash/fingerprint of it). This requires
+a recent version of <tt>mitmproxy</tt> containing <a
+href="https://github.com/mitmproxy/mitmproxy/pull/1935">pull request
+#1935</a> which was contributed by OpenConnect developers for this
+purpose.</p>
+
+<p>An example of such a script may be useful:
+<a href="https://gitlab.com/dlenski/pangp-hacks/-/blob/master/gp_ssl_log.py">gp_ssl_log.py</a>.
+This script works with <tt>mitmproxy</tt> or <tt>mitmdump</tt> to modify
+traffic to/from with a GlobalProtect server; specifically it <a
+href="https://gitlab.com/dlenski/pangp-hacks/-/blob/master/gp_ssl_log.py#L63-68">mangles
+the <tt><root-ca></tt> XML tag</a> sent by GlobalProtect portal
+servers, which GlobalProtect's official client software uses to verify
+that certificates of servers it connects to. It can be used with
+<tt>mitmdump</tt> as follows:</p>
+
+<pre>
+ ./mitmdump -vvv --tcp $YOUR_GP_SERVER_IP -s /path/to/gp_ssl_log.py --ssl-version-server all --insecure
+</pre>
+
+<h2>Documenting VPN protocols</h2>
+
+<p>Sometimes it's most satisfying and productive to simply start
+coding up support for a new protocol or feature in OpenConnect
+itself. However, if you don't understand the structure of the
+OpenConnect codebase well, this may make it difficult to explain and
+discuss the code with more experienced developers.</p>
+
+<p>Often it is very useful to take a step back and explain how the VPN
+protocol works in more human-readable terms before implementing it in
+OpenConnect's codebase. Preparing a document that intersperses prose
+explanations with captured traffic can aid in communication. See
+<a href="https://github.com/dlenski/openconnect/blob/master/PAN_GlobalProtect_protocol_doc.md">PAN_GlobalProtect_protocol_doc.md</a>,
+(prepared during the implementation of the GlobalProtect protocol in
+OpenConnect, and subsequently updated) for a complete example.</p>
+
+<h2>Ask for help</h2>
+
+<p>Ask on the <a href="mail.html">mailing list</a> for help with new
+protocol implementations, or show us your code via Merge Requests
+on GitLab.</p>
+
+<INCLUDE file="inc/footer.tmpl" />
+</PAGE>