Detecting Tor Network Traffic with YAF and Python

February 19, 2014 · By Stephen Reese

This article demonstrates how to parse historical YAF mediator output with Python and identify TLS certificate fields that matched patterns used by Tor relays at the time. This article assumes that you have downloaded, compiled, and installed YAF, mediator, and libfixbuf.

Historical detection note: The certificate-name pattern examined in this article was observed in a 2013 capture. It should not be treated as a reliable standalone method for detecting current Tor traffic.

We first generate the YAF records from the acquired PCAP containing the TOR packets.

$ yaf --in tor.pcap --out tor.yaf

Next, use the mediator to write the YAF records to a flat-text file that the Python script can parse. The mediator can alternatively write the records to MySQL.

$ yaf_file_mediator-1.1.0/yaf_file_mediator --input tor.yaf --output tor.txt
**** Total flow count is 29 ****
**** Stats Total Count is 1 ****

Using Python, we can parse the records for patterns historically observed in Tor TLS certificates.

#!/usr/bin/python import re
import sys source_ip_line = None
destination_ip_line = None
issuer_domain = None filename = sys.argv[1]
myfile = open(filename,'r')
sourceIP = 'Source IP:'
destIP = 'Destination IP:'
issuerID = 'Issuer ID:'
subjectID = 'Subject ID:'
for line in myfile.readlines(): line = line.strip() if line.startswith(sourceIP): sourceIPline = line elif line.startswith(destIP): destIPline = line elif line and line.startswith(issuerID): issuerDomain = re.search(r"\bwww\.[A-Za-z0-9-]+\.com\b", line) elif line and line.startswith(subjectID): subjectDomain = re.search(r"\bwww\.[A-Za-z0-9-]+\.net\b", line) if issuerDomain and subjectDomain: print (sourceIPline) print (destIPline) print issuerDomain.group() print subjectDomain.group() print
myfile.close()

The following is an example output from the example PCAP provided earlier in this post. In this sample, many Tor relay certificates used randomized .com issuer names and .net subject names. The script searches for that historical pattern. It may produce false positives when unrelated certificates match the expression and false negatives when Tor certificates use a different format.

$ tor-ssl-parser.py tor.txt
Source IP: 10.0.0.126
Destination IP: 198.27.97.223
www.axslhtfqq.com
www.hkkch64skp7am.net Source IP: 10.0.0.126
Destination IP: 96.127.153.58
www.rtqtkopfct767ai.com
www.facp2b2y5wjffbo5ioy.net Source IP: 10.0.0.126
Destination IP: 192.151.147.5
www.5m6ywj2w7zs.com
www.iolbr3jbfs.net Source IP: 10.0.0.126
Destination IP: 66.18.12.197
www.igdpzct5tauwgyqs.com
www.4tdznzbrfuv.net Source IP: 10.0.0.126
Destination IP: 64.62.249.222
www.3pzqe4en5.com
www.glk3fwiz6.net Source IP: 10.0.0.126
Destination IP: 212.83.158.173
www.lvv4l6sx3qafei2s5u.com
www.vznlngjz7a2fpg.net Source IP: 10.0.0.126
Destination IP: 212.83.155.250
www.mbrdx4tz2ob5wlvazlr.com
www.shxl35n3zt.net

The remaining matching records were omitted for readability.

This example shows how YAF metadata can be converted into a detection heuristic with a small Python parser. Because the certificate pattern was specific to historical Tor behavior, modern investigations should combine maintained relay intelligence with protocol, endpoint, timing, and behavioral evidence.