23

I have a server to which many clients connect using SSL. Recently I'm observing SSL handshake errors in the server logs (ex SSL MAC error). The error itself is not important, but I want to see why some clients are able to connect while others are failing, and also need to identify which clients are failing.

For debugging this issue, I want to capture all SSL handshakes happening at server and since I don't know when the problematic clients connect, I don't want to capture all the traffic till that happens. I just want to capture all the SSL handshakes and later analyze them with Wireshark. Assume that I only have access to tcpdump and no other tools for capturing.

sadiq.ali
  • 526
  • 1
  • 6
  • 16
  • You can mention the SSL port in tcpdump for capture isn't? – Prabhu Sep 22 '16 at 03:34
  • @Prabhu yes, but it will capture all data of that port. I just want to capture data till the SSL/TLS handshake completes for each request. – sadiq.ali Sep 23 '16 at 13:08

3 Answers3

46

I don't know what exactly you are calling handshake, but I propose this command that will probably capture more than 95% of what you can want:

tcpdump -ni eth0 "tcp port 443 and (tcp[((tcp[12] & 0xf0) >> 2)] = 0x16)"

Now what does it do:

  • eth0: is my network interface, change it if you need
  • tcp port 443: I suppose this is the port your server is listening on, change it if you need
  • tcp[((tcp[12] & 0xf0) >> 2)] = 0x16: a bit more tricky, let's detail this below

tcp[12] means capturing the 13th byte of the tcp packet, corresponding to first half being the offset, second half being reserved. The offset, once multiplied by 4 gives the byte count of the TCP header, meaning ((tcp[12] & 0xf0) >> 2) provides the size of the TCP header.

The first byte of a TLS packet define the content type. The value 22 (0x16 in hexadecimal) has been defined as being "Handshake" content.

As a consequence, tcp[((tcp[12] & 0xf0) >> 2)] = 0x16 captures every packet having the first byte after the TCP header set to 0x16.

More filtering can be performed, but this strictly answers your question.

Jyo de Lys
  • 1,127
  • 8
  • 12
  • 1
    By handshake, I mean the packets which are used during SSL connection establishment. These are packets corresponding to "ClientHello", "ServerHello", "Certificate" etc till "ApplicationData" part of communication. – sadiq.ali Sep 23 '16 at 13:01
  • Yes, it is capturing packets only for the duration of handshake. But when I open the resulting file in Wireshark, it is only showing TCP packets and not able to reconstruct the SSL messages (example ClientHello) completely. Could this be because this filter is removing some packets? – sadiq.ali Sep 23 '16 at 13:13
  • 1
    Yes probably. During my test, Wireshark automatically decodes packets as TLSv1.2, but if for instance you have truncated packets at TCP level, you won't be able to reconstruct the full handshake. I guess you cannot solve this using only tcpdump. – Jyo de Lys Sep 23 '16 at 13:27
  • If the above filter matches no packets you may be in a vlan'd environment. Expand "(tcp[((tcp[12] & 0xf0) >> 2)] = 0x16)" to "vlan and (tcp..." to capture in that environment. – MichaelRpdx Dec 05 '16 at 19:44
  • 1
    I had the same issue where wireshark could not interpret the tcp traffic as TLS/SSL. I followed the advice [https://ask.wireshark.org/questions/34075/why-wireshark-cannot-display-tlsssl]here to solve this as I was capturing traffic on a non-standard ssl port. – joe90p Dec 09 '16 at 16:08
  • you might try changing the -nn to -Xnnvvv – figtrap Apr 09 '18 at 19:59
  • It doesn't capture errors in TLS like "Certificate Unknown"(46). Expand it please – Alexander Cherkendov Dec 13 '20 at 22:50
  • This works with tcpdump but not with libpcap for some reason. – Peter Jun 01 '21 at 17:58
  • "(tcp[12] & 0xf0) >> 2" can be shorten to "tcp[12] >> 2", as ">>2" would just ignore lower two 4 bit. – liudongmiao Aug 27 '22 at 01:35
1

I think the accepted answer is a premature optimization with a fragile solution.

SSL handshake occurs as soon at the connection is established.

Easy approach: start the capture before the client connects to the remote host, and capture the first, full N packets.

For example, for 300 packets:

/usr/sbin/tcpdump -i eth0 -p -s 65535 -c 300 "tcp and host 1.2.3.4 and port 443"

This way wireshark has the full payload of the SSL handshake, can decode it and show you all the bits.

Massimo
  • 3,171
  • 3
  • 28
  • 41
1

If you also want to grab SQL Server encryption then you also need to look at +8.

tcp[((tcp[12] & 0xf0) >> 2)] = 0x16  or (tcp port 1433 and tcp[((tcp[12] & 0xf0) >> 2) + 8] = 0x16)
user594102
  • 21
  • 5