<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marco Introini</title>
    <description>The latest articles on DEV Community by Marco Introini (@marcointroini).</description>
    <link>https://dev.to/marcointroini</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F839857%2F57a027a2-6400-40fd-acbf-6766e5f22a8b.jpeg</url>
      <title>DEV Community: Marco Introini</title>
      <link>https://dev.to/marcointroini</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marcointroini"/>
    <language>en</language>
    <item>
      <title>Debug mTLS HTTPS connections using Wireshark</title>
      <dc:creator>Marco Introini</dc:creator>
      <pubDate>Tue, 16 May 2023 14:26:57 +0000</pubDate>
      <link>https://dev.to/marcointroini/debug-mtls-using-wireshark-7ll</link>
      <guid>https://dev.to/marcointroini/debug-mtls-using-wireshark-7ll</guid>
      <description>&lt;p&gt;Transport Layer Security (TLS) is a widely used cryptographic protocol for securing communications over the internet. TLS provides encryption and authentication services that protect data in transit between client and server applications. Mutual Transport Layer Security (MTLS) is an extension of TLS that provides two-way authentication between client and server applications. In mTLS, both the client and server present their digital certificates to each other and verify each other's identity before establishing a secure communication channel.&lt;/p&gt;

&lt;p&gt;When working with mTLS connections, it is important to be able to debug the handshake process to identify and resolve issues with certificate validation, key exchange, and other cryptographic protocols. Wireshark is a powerful tool that can be used to capture, analyze, and debug network traffic, including TLS and mTLS connections.&lt;/p&gt;

&lt;p&gt;This article will discuss how to use Wireshark to debug mTLS connections, capture traffic and analyze the TLS handshake process.&lt;br&gt;
This can be useful for checking if the client doesn't send the correct certificate.&lt;/p&gt;

&lt;p&gt;After the handshake, in TLS 1.3, the packets are encrypted, so getting them in plain text is impossible. We will see this in more detail at the end of this article.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a Server with mTLS
&lt;/h2&gt;

&lt;p&gt;For our testing purposes, we create an elementary mTLS server in PHP.&lt;br&gt;
You can find the full source code here: &lt;a href="https://github.com/marco-introini/mtls-example"&gt;https://github.com/marco-introini/mtls-example&lt;/a&gt;&lt;br&gt;
First, we must configure the Apache server to use our generated certificates. This can be done in the configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SSLEngine on  
SSLCertificateFile /etc/apache2/ssl/ssl.crt
SSLCertificateKeyFile /etc/apache2/ssl/ssl.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in the same configuration file, we accept the client certificate but do not force it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +StdEnvVars
SSLCACertificateFile /etc/apache2/ssl/ssl.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's crucial to add &lt;code&gt;SSLOptions +StdEnvVars&lt;/code&gt; because we can check the certificate using Superglobals.&lt;/p&gt;

&lt;p&gt;The server PHP code is very simple: it checks if the client used an actual certificate and prints its Common Name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'SSL_CLIENT_VERIFY'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'SUCCESS'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;die&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SSL client verification failed'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Welcome "&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"SSL_CLIENT_S_DN_CN"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a Client with mTLS
&lt;/h2&gt;

&lt;p&gt;There is no need to create a client: we can simply use curl or OpenSSL&lt;/p&gt;

&lt;p&gt;With curl, we can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'https://localhost/server.php'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--key&lt;/span&gt; &lt;span class="s2"&gt;"./certs/client_key.pem"&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt; 
&lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"./certs/client_cert.pem"&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt; 
&lt;span class="nt"&gt;--cacert&lt;/span&gt; &lt;span class="s2"&gt;"./certs/ssl.crt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In OpenSSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl s_client &lt;span class="nt"&gt;-connect&lt;/span&gt; localhost:443 &lt;span class="nt"&gt;-status&lt;/span&gt; &lt;span class="nt"&gt;-msg&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; certs/client_key.pem &lt;span class="nt"&gt;-cert&lt;/span&gt; certs/client_cert.pem &lt;span class="nt"&gt;-CAfile&lt;/span&gt; certs/ssl.crt &lt;span class="nt"&gt;-state&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that using OpenSSL we can check only the root of our server, not a single page like in curl.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;For having different IP for client and server machines I used a virtual machine with Kali Linux installed for the curl client and Wireshark and the macOS with docker desktop for the server.&lt;br&gt;
In the following example, the client IP is 192.168.64.6 and the server IP is 192.168.64.1&lt;/p&gt;

&lt;p&gt;Of course, we must copy all certificates inside the Kali Linux VM before using curl.&lt;br&gt;
Because the server certificate is generated using localhost as CN we must add the -k option too.&lt;/p&gt;
&lt;h3&gt;
  
  
  Wireshark capture without client certificate
&lt;/h3&gt;

&lt;p&gt;Let's begin with a client call without a client certificate. Open Wireshark and in a terminal write&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --tlsv1.2 --tls-max 1.2 \
--location 'https://192.168.64.1/server.php' \
--cacert "/media/shared/ssl.crt" -k
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviously, the curl fails.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SSL client verification failed 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see what happened.&lt;br&gt;
Firstly the client sent the Client Hello Message; the server response was a Server Hello, sending its own (server) certificate. Then the server sent another message requesting a client certificate (Certificate Request Message - Type 13):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v0RmR_TD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q5j7722dgjt082otvb11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v0RmR_TD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q5j7722dgjt082otvb11.png" alt="No Certificate Used - Server Hello" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The client has not a certificate, so its response is without it, as you can see from the following capture&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jhfg3DFh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2s2l9dctockjl6av1hmb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jhfg3DFh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2s2l9dctockjl6av1hmb.png" alt="No Certificate Used - Request Certificate" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Wireshark capture with client certificate
&lt;/h3&gt;

&lt;p&gt;Now let's try it again, but using the correct client certificate&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --tlsv1.2 --tls-max 1.2 \
--location 'https://192.168.64.1/server.php' \
--key "/media/shared/client_key.pem" \
-E "/media/shared/client_cert.pem" \
--cacert "/media/shared/ssl.crt" -k
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response now is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Welcome TestClient
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's dig inside Wireshark.&lt;br&gt;
The Client Hello and Server Hello (including Certificate Request) is the same. But the client has sent the certificate this time, as it is evident that they possess one from this packet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ViO1gutL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ulgne6s9ggoily6fz8ci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ViO1gutL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ulgne6s9ggoily6fz8ci.png" alt="Certificate Used - Certificate" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can further analyze the certificate used:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jv1DBx2U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ve4nrsco332hfog20uy2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jv1DBx2U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ve4nrsco332hfog20uy2.png" alt="Certificate Used - Certificate Details" width="800" height="262"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem with TLS 1.3
&lt;/h2&gt;

&lt;p&gt;We have seen the mTLS connection forcing the TLS version to 1.2. We did it because debugging a TLS 1.3 connection is way more challenging because everything after the Server Hello is encrypted.&lt;/p&gt;

&lt;p&gt;Let's demonstrate it. &lt;br&gt;
We can force the TLS 1.3 in the same curl call.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --tlsv1.3 --tls-max 1.3 \
--location 'https://192.168.64.1/server.php' \
--key "/media/shared/client_key.pem" \
-E "/media/shared/client_cert.pem" \
--cacert "/media/shared/ssl.crt" -k
Welcome TestClient   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see what Wireshark can see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LkIu2pLG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unroqtimu92htkyik6j5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LkIu2pLG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unroqtimu92htkyik6j5.png" alt="TLS 1.3" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this packet, there is the Client Certificate request, as we saw in the 1.2 example, but this time the whole data are encrypted and unavailable to Wireshark.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;In conclusion, Transport Layer Security (TLS) and Mutual Transport Layer Security (mTLS) play crucial roles in securing communications over the Internet. Wireshark is a valuable tool for debugging mTLS connections, capturing network traffic, and analyzing the TLS handshake process. By using Wireshark, developers can identify and resolve issues related to certificate validation, key exchange, and other cryptographic protocols.&lt;/p&gt;

&lt;p&gt;When establishing an mTLS connection, both the client and server exchange digital certificates to verify each other's identity, ensuring a secure communication channel. Wireshark allows us to observe the handshake process, providing insights into the exchange of certificates and other relevant information.&lt;/p&gt;

&lt;p&gt;Through practical examples, this article demonstrated how to create an mTLS server and client using PHP, curl, and OpenSSL. Wireshark was then used to capture and analyze the network traffic between the server and the client. By examining the captured packets, we could observe the differences in behavior when a client certificate was present or absent.&lt;/p&gt;

&lt;p&gt;It is important to note that debugging TLS 1.3 connections can be more challenging due to encryption. In TLS 1.3, after the Server Hello, the packets become encrypted, making it impossible for Wireshark to access the plaintext data. However, Wireshark can still provide valuable insights into the handshake process and the initial stages of communication.&lt;/p&gt;

&lt;p&gt;Overall, Wireshark is a powerful tool for troubleshooting mTLS connections and gaining a deeper understanding of the TLS handshake. It allows developers to diagnose and resolve issues related to certificate verification and other aspects of secure communication, ultimately enhancing the security and reliability of Internet-based applications.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>network</category>
      <category>cybersecurity</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
