Digital forensics

Eyesight to the Blind – SSL Decryption for Network Monitoring [Updated 2019]

August 29, 2019 by Alec Waters

SSL and network monitoring aren’t the most compatible of partners – even with the most sophisticated detection infrastructure in the world, you’ll not derive many useful indicators from the barren randomness of encrypted traffic. Consider the plight of the Sguil sensor shown below:

The webserver’s use of SSL means that network-based incident detection is problematic. No amount of tuning of the sensor’s Snort instance will help it detect intrusion attempts – the only traffic it will see is HTTPS. Also, if an incident is detected by other means (e.g., customer notification, web server log file monitoring, etc.) the investigative value of Sguil’s full packet capture is greatly diluted.

There are a number of ways to get back the visibility stolen by SSL, including the following. You could:

  • Terminate the SSL “in front of” the webserver, perhaps on a reverse-proxying loadbalancer or web application firewall. You can then monitor the decrypted traffic between the loadbalancer and the webserver.
  • Perform monitoring tasks on the webserver itself, perhaps by increasing the level of web and application logging.
  • Give your existing sensor platforms the means to decrypt the SSL sessions.

Each approach has its pros and cons; this article will show you how to leverage the latter technique to restore the eyesight of your blind Sguil sensors.

SSL Decryption

We first need to understand a little about the mechanics of SSL decryption; you can read about it in depth here. In a nutshell there are two conditions that must be met before we can proceed:

  1. The server must be using the RSA key exchange mechanism (see here, bottom of page, and here, section F.1.1.2). Fortunately, this is the most common form of key exchange for SSL based servers; if you’re using DSA keypairs or the Diffie-Hellman key exchange mechanism you’re probably out of luck.
  2. You must have access to the server’s private RSA key, and be able to copy it onto your Sguil sensor.

The latter point means that the only SSL decryption we’re going to be able to pull off is decryption of traffic to and from servers that we own – we’re not going to be able to magically decrypt arbitrary SSL traffic (darn!) However, this is quite adequate from the viewpoint of intrusion detection and network forensics.

Now, where did I leave my keys…?

Getting the server’s private key onto the Sguil sensor could take a bit of work. The key might be stored in a .pem file somewhere on the server, making it child’s play to copy it to the Sguil sensor. However, certain operating systems like Windows store certificates and keys in a “certificate store” instead of .pem files. In order to get the private key, we need to first export the certificate and key together as a PKCS12 file (read about that here). Once we’ve got the exported certificate, we can proceed to extract the private key using openssl like this:

C:>openssl pkcs12 -in c:myExportedCertificate.pfx –out c:myExportedCertificate.pem -nodes

When prompted, enter the password you gave when you exported the certificate and key. The file myExportedCertificate.pem will contain a block of text that looks like this:


Copy and paste this block into a file called myPrivateKey.pem and save it on your Sguil sensor.

Windows also has the concept of a non-exportable private key; a key stored in this way cannot normally be exported by the Windows certificate management tools (although tools like Jailbreak claim to be able to do it).

A word of warning

As noted in the article on decrypting SSL, your server’s private key is a very sensitive thing indeed. With it, an attacker can decrypt the server’s SSL traffic or use it together with the server’s certificate in order to masquerade as a legitimate site. You must take extreme care with the handling of the private key – don’t leave copies of it lying around in temporary directories, make very sure it doesn’t end up on the Internet by accident, and make certain that the Sguil sensor you copy it to is as locked down as much as possible. Think of this key as the combination to a safe guarding your valuables—make very sure that you only share it with trusted sources. Leaking a private key is too high a price to pay for visibility into your SSL traffic, so take care!

Putting the key to work

Private key in hand, we could clearly point Wireshark at Sguil’s full-content capture directories. This approach hardly lends itself to efficient network security monitoring; it would be much better if we could pipe our decrypts straight into Sguil in near real-time, leveraging the benefits of Snort, SANCP, PADS, and whatever else you’ve got running.

Dmitry Plashchynski’s viewssld package is just the tool for the job. I’ve recently made some additions to the code to ease integration with Sguil and to produce richer decrypts. Conceptually, viewssld looks like this:

viewssld listens on a given interface via the usual libpcap for nominated SSL traffic. The captured frames are then passed on to Atomic Labs’ libdssl library which handles the actual decryption (the latest version of libdssl at the time of writing is 2.1.1, available via svn here).

The output of the libdssl code is the decrypted packet contents only (no headers or anything like that), so libnet is used to build a “fake” traffic stream containing the decrypted SSL. This fake stream is pumped out through the output interface, where Sguil is listening.

Earlier versions of viewssld would only output the client->server traffic (e.g., HTTP requests). My modifications to viewssld include:

  1. Outputting a fake 3-way TCP handshake for the decrypted traffic
  2. Outputting the decrypted server replies as well as the client requests, keeping the (fake) TCP sequence numbers properly up to date. The sequence numbers and other TCP/IP header “furniture” are of course complete fiction – because the decrypted traffic is a different size to the encrypted traffic, it’s not possible to use the “real” values. The decrypted stream may also be fragmented/segmented differently to the encrypted one, but again there’s little you can do about this
  3. Outputting a fake RST at the end of each session
  4. Using an easily-searchable IP Ident number for all the fake frames so you can tell which ones were output by viewssld (54609 == 0xd551 == DSSL )
  5. Outputting the decrypted frames on a different port to which they were captured on (e.g. 443->80, 465->25, 993->143, etc.)

The first three points help to keep Sguil’s SANCP instance happy, since viewssld’s output is now a reasonably well-formed TCP stream with a defined beginning and end. Point four reminds us that although the decrypted traffic is available to Sguil, it is a complete fabrication – no such traffic ever existed in this form on the network. By tagging decrypted IP datagrams with an ident of 0xd551 you can sort the recorded facts from the decrypts.

Point five aids with integrating viewssld and Sguil as shown in the diagram below:

It goes like this:

  1. Raw traffic (blue arrows) enters Sguil’s usual monitoring interface.
  2. This traffic is captured by both Sguil and viewssld.
  3. viewssld decrypts what it can and pumps it back onto the interface it captured it from (red arrows). This is only made possible by using a different TCP port for the decrypted frames – if it used the same port it would re-enter viewssld again.
  4. The fake stream of decrypted SSL is picked up by Sguil.

Sguil/SANCP/Snort/PADS/etc. therefore see both the encrypted and the decrypted traffic, as shown in the screenshot below. In the background you can see a SANCP query with two rows of results. The first row is the raw SSL traffic captured by Sguil on port 443; the second row shows Sguil capturing the corresponding fake decrypted stream output by viewssld on port 80. The two transcript windows tell the rest of the story:

I’ve tested viewssld with HTTPS, SMTPS, POP3S and IMAPS – all perform as expected. A sample viewssld.conf file for these four protocols might look like this:

# PID-file path (default: /var/run/
pid = /var/run/

# daemonize? on/off (default: off)
daemon = on

# loglevel 0-10 (default: 0)
loglevel = 10

# SSL protocols to decrypt

src = eth1
dst = eth1
ip =
port = 443
key = /etc/viewssld/webserver.key
dsslport = 80

src = eth1
dst = eth1
ip =
port = 465
key = /etc/viewssld/mailserver.key
dsslport = 25

src = eth1
dst = eth1
ip =
port = 993
key = /etc/viewssld/mailserver.key
dsslport = 143

src = eth1
dst = eth1
ip =
port = 995
key = /etc/viewssld/mailserver.key
dsslport = 110

Notice how the src and dst interfaces are the same in all cases, and that the non-SSL port is specified (dsslport=) as well as the SSL port (port=).

Another word of warning

There are a couple of things to consider when employing viewssld on a Sguil sensor:

  • SSL decryption has a computational cost associated with it. If your sensor’s CPU is normally very busy, the extra crypto load may push it over the edge.
  • The decryption process is very sensitive to packet loss. If viewssld misses a packet, decryption of the stream will stop at that point; if it misses the SSL handshake at the start of an encrypted session, it won’t decrypt anything at all.
  • You’re now storing both the encrypted and decrypted traffic, so there may be a disk utilisation impact.

Show me the money!

viewssld can be obtained from GitHub here. You’ll need libpcap, libssl, libnet and libdssl installed to compile the code. Certain versions of libdssl don’t seem to compile up a shared library, so you might need to statically link viewssld to libdssl.a if this is the case. If you get a link error when compiling like this one:

sensor:~/viewssld/src# make
gcc -g -O2 -lpcap -lssl -lnet -ldssl -o viewssld viewssld.o utils.o
viewssld.o: In function `proceed’:
/user/viewssld/src/viewssld.c:339: undefined reference to `CapEnvCreate’
/user/viewssld/src/viewssld.c:341: undefined reference to `CapEnvSetSSL_ServerInfo’
/user/viewssld/src/viewssld.c:368: undefined reference to `CapEnvDestroy’
/user/viewssld/src/viewssld.c:354: undefined reference to `CapEnvSetSessionCallback’
/user/viewssld/src/viewssld.c:356: undefined reference to `CapEnvCapture’
viewssld.o: In function `error_callback_proc’:
/user/viewssld/src/viewssld.c:773: undefined reference to `SessionToString’
viewssld.o: In function `session_event_handler’:
/user/viewssld/src/viewssld.c:444: undefined reference to `SessionToString’
/user/viewssld/src/viewssld.c:462: undefined reference to `SessionSetCallback’
/user/viewssld/src/viewssld.c:464: undefined reference to `SessionSetMissingPacketCallback’
collect2: ld returned 1 exit status
make: *** [viewssld] Error 1

…you can fix it like this:

sensor:~/viewssld/src# gcc -g -O2 -lpcap -lssl -lnet -ldssl -o viewssld viewssld.o utils.o /usr/local/lib/libdssl.a

Get it up and running, and give your Sguil sensors sight beyond sight! For more info on SSL, check out our Cryptography 101 article.

Posted: August 29, 2019
Articles Author
Alec Waters
View Profile

Alec Waters is a security researcher for InfoSec Institute and a network security specialist working for Dataline Software in the UK. Working with defense and healthcare clients, his focus is on incident response, network forensics and secure infrastructure design.

10 responses to “Eyesight to the Blind – SSL Decryption for Network Monitoring [Updated 2019]”

  1. Roland Dobbins says:

    I really appreciate the hard work you’ve put into coding and writing this up!

    One suggestion – rather than re-outputting the decrypted traffic out the same interface with changed TCP port numbers, which is a bit confusing, how about an option to output it via a completely separate interface, with the TCP port numbers intact?

    Thanks again!

  2. Alec Waters says:

    Hi Roland,

    You can do that – just omit the dsslport= parameter from the viewssld.config file (this will make it use the original port), and specify a different interface for dst=


  3. Roland Dobbins says:

    Ah, super – thanks so much!

  4. Stephen Canell says:

    Is there anything special about the dest interface configuration that is required to see unencrypted traffic?
    src eth1
    dst eth2
    tcpdump -i eth2

  5. Stephen Canell says:

    Sorry…. No Traffic!

  6. codeman says:

    Good article! Have a compile problem with viewssld.. I ran the following to fix the errors for ssl, but it seems I have the same problem for libnet library

    gcc -g -O2 -lpcap -lssl -lnet -ldssl -o viewssld viewssld.o utils.o /usr/local/lib/libdssl.a

    Is there something similar I can run to fix the libnet “make” errors I get when running “make” on viewssld?

    viewssld.o: In function `sendEmptyTCPSegment’:
    /home/viewssld-0.7.0/src/viewssld.c:535: undefined reference to `libnet_build_tcp’
    /home/viewssld-0.7.0/src/viewssld.c:559: undefined reference to `libnet_build_ipv4′
    /home/viewssld-0.7.0/src/viewssld.c:583: undefined reference to `libnet_build_ethernet’

  7. Hamerling says:

    DVD Shrink and this thing are requantizing the MPEG2 staerm. MPEG video compression works by periodically using full frames then calculating those in-between base on differences from the surrounding frames. These apps reduce the amount of information that represents the differences. The same process is used with a lot of digital television. DVD Shrink (which begeat Nero’s shrinker) has a high-quality mode which does 2-passes. The first pass analyzes the complexity of the image so more busy parts of the video will have more data. Amok DVD doesn’t do that which means the result cannot be as good as a 2-pass DVD Shrink operation. If you like to strip contents with DVD Shrink, consider using PGCEdit and Vob Blanker to get rid of extra junk because they are more complete than the simple editing of DVD Shrink. The most popular app for automating DVD-9 to DVD-5 with actual re-encoding is DVD Rebuilder. There is a free version and a commercial version. Depending on the source material and the filtering used, it’s actually possible to get a higher quality DVD-5 from a DVD-9 original if the source is a low quality transfer.

  8. Shankar says:

    Hi Alec!

    Do you think that is it possible to enable IDS to decrypt SSL traffic by forming a special key(may be called read only decrypting key but not the master key) which only give access to decrypted data for read only purpose so that IDS can not modify it after decyrpting and send it to the server (In case if IDS is compromised). This is also important in some application where IDS is outsource (due to some valid reasons).

    Do you think its possible?

  9. mihai rosca says:

    Hi Alec,
    I am struggling to get the viewssld to work, I’ve issues the following command to test the functionality
    viewssld -k /etc/ssl/ca.key -. -i -s eth2 -d eth1 -n -v -p 8080.
    All that I see currently is the following:

    [root@centos sssd]# viewssld -k /etc/ssl/ca.key -w Websense1. -i -s eth2 -d eth1 -n -v -p 8080

    | Common config |
    | Config file: |
    | PID file: /var/run/ |
    | loglevel: 1 |
    | daemon: off |

    | Config capture |
    | Keyfile: /etc/ssl/ca.key |
    | Source Interface: eth2 |
    | Destination Interface: eth1 |
    | Server IP address: |
    | TCP Port: 8080 |
    | TCP DSSL Port: 0 |

    => New Session:
    ERROR: SSL session:, error code: -5: Unknown version of SSL.

    ERROR: SSL session:, error code: -5: Unknown version of SSL.

    <= Session closing: pkts recv: 53 pkts drop: 0
    => New Session:
    ERROR: SSL session:, error code: -5: Unknown version of SSL.

    ERROR: SSL session:, error code: -5: Unknown version of SSL.

    <= Session closing: pkts recv: 65 pkts drop: 0
    => New Session:
    ERROR: SSL session:, error code: -5: Unknown version of SSL.

    ERROR: SSL session:, error code: -5: Unknown version of SSL.

    <= Session closing: pkts recv: 73 pkts drop: 0
    => New Session:
    ERROR: SSL session:, error code: -5: Unknown version of SSL.

    Do you have any idea what is the problem here?

Leave a Reply

Your email address will not be published. Required fields are marked *