123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- <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. (See <a href="#antimitm">below</a>, for why an explicit proxy is unlikely to work.)</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 <a href="#antimitm">below</a> 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>
- <h3 id="antimitm">Defeating anti-MITM measures</h3>
- <p>Many proprietary VPN clients will ignore <i>explicit</i> system/browser
- proxy settings and attempt to establish direct connections to VPN servers,
- which is why explicit proxy setups often will not work, and transparent
- proxying is required.</p>
- <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>
|