Capture only ssl handshake with tcpdump
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.
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.