Practical Network Traffic Analysis with Tshark

Wireshark is the undisputed gold standard for GUI-based packet analysis, but it quickly hits a wall when faced with multi-gigabyte PCAP files or headless Linux enterprise servers. Opening a 5GB packet capture in a graphical environment will consume your workstation system memory and bring your incident response process to a screeching halt.
Enter Tshark. As the terminal-based counterpart to Wireshark, Tshark uses the exact same packet dissection engine under the hood. It allows threat hunters, SOC analysts, and security engineers to filter, slice, and extract granular metadata from massive network captures in seconds using Unix standard input and output streams.
In this guide, we will step beyond basic packet capturing and explore advanced, practical CLI techniques to audit network traffic, hunt for Indicators of Compromise (IOCs), and script your triage workflows.
Understanding the Tshark Execution Model
Before running complex extraction strings, it helps to understand how Tshark processes data. By default, running tshark -r capture.pcap outputs packet summaries line-by-line, mimicking the default Wireshark top panel.
However, the real power of Tshark lies in three primary execution switches:
-Y: Applies a Wireshark display filter (evaluated post-dissection).-f: Applies a Berkeley Packet Filter (BPF) capture filter (evaluated at capture time or file read level).-T fields: Switches the output format from standard textual summary to formatted key-value field extraction.
Combining -T fields with -e [field_name] allows you to turn raw network traffic into clean, tab-separated structured text ready for processing with awk, sed, sort, and uniq.
Extracting Core Metadata with Field Specifics
When investigating an alert, your first goal is usually generating an overview of involved hosts, protocols, and transaction volumes. Instead of manually scrolling through thousands of lines, you can extract specific header values directly.
To view all source and destination IP address pairs along with transport protocols, execute:
tshark -r incident.pcap -T fields -e frame.number -e ip.src -e ip.dst -e _ws.col.Protocol
Notice the use of _ws.col.Protocol. This custom field extracts the exact protocol column display string that Wireshark calculates, providing instant visibility into encapsulated protocols like DNS, HTTP, or SSH.
If you want to isolate unique internal endpoints making outbound connections on non-standard ports, filter down to RFC 1918 addresses:
tshark -r incident.pcap -Y 'ip.src == 10.0.0.0/8 and not (tcp.dstport == 80 or tcp.dstport == 443)' -T fields -e ip.src -e ip.dst -e tcp.dstport | sort | uniq -c | sort -nr
This single pipeline aggregates outbound non-web traffic, counts occurrences, and sorts them by volume, immediately highlighting anomalous persistent connections.
Deep Dive into Unencrypted Web Protocols
While modern web traffic relies heavily on encryption, cleartext HTTP still appears regularly in corporate networks, legacy environments, and initial malware stage drops.
Tshark allows you to dissect every component of an HTTP session. To extract every requested host name, URI path, and User-Agent string from a PCAP, use the following syntax:
tshark -r malware_sample.pcap -Y 'http.request' -T fields -e ip.src -e http.host -e http.request.uri -e http.user_agent
Threat actors frequently use distinct or anomalous User-Agent strings (or omit them entirely) during C2 beaconing. To quickly list all unique User-Agent strings present in a capture alongside their request count:
tshark -r malware_sample.pcap -Y 'http.request' -T fields -e http.user_agent | sort | uniq -c | sort -nr
If an attacker drops a payload over HTTP, you can also reconstruct and extract the transmitted file directly from the command line using the export objects engine:
tshark -r capture.pcap --export-objects 'http,./extracted_files'
This command automatically reassembles file fragments stream-by-stream and saves them into the ./extracted_files directory for static analysis or submission to a sandbox.
Inspecting Encrypted TLS Handshakes
Because the vast majority of web traffic is encrypted, you cannot read HTTP headers inside TLS sessions without private keys or session secrets. However, the initial unencrypted TLS handshake reveals critical telemetry through Server Name Indication (SNI).
When a client initiates an encrypted session, it sends a TLS Client Hello containing the domain name it intends to reach in plain text. Tshark can parse this field directly:
tshark -r tls_traffic.pcap -Y 'tls.handshake.type == 1' -T fields -e ip.src -e ip.dst -e tls.handshake.extensions_server_name
This filter targets Client Hello packets (tls.handshake.type == 1) and isolates the destination hostname before encryption is established.
To hunt for potential data exfiltration or domain fronting, compare the TLS SNI host header against the destination IP address resolution or look for abnormally long, randomized domain strings that resemble dynamic DNS services.
Additionally, you can audit the TLS versions supported across your infrastructure to spot legacy, insecure ciphers:
tshark -r tls_traffic.pcap -Y 'tls.handshake.type == 1' -T fields -e tls.handshake.version | sort | uniq -c
Leveraging the Built-in Statistics Engine
Beyond field extraction, Tshark contains a built-in statistics engine accessed via the -z flag. This tool allows you to build quick summaries of traffic distribution without piping output to external shell utilities.
To view a complete breakdown of hierarchy statistics and protocol percentages within a capture file, run:
tshark -r network_audit.pcap -z io,phs
To analyze conversations between endpoints at the IP layer:
tshark -r network_audit.pcap -z conv,ip
This outputs tabular data detailing packet count, byte count, total duration, and bidirectional transfer speeds for every communicating IP pair. It is an indispensable command when identifying top talkers during a denial-of-service condition or large-scale data exfiltration event.
For DNS specific analysis, the DNS statistics plugin aggregates query types and response codes instantly:
tshark -r network_audit.pcap -z dns,tree
Automating PCAP Triage with Shell Functions
You can turn these individual Tshark patterns into reusable shell scripts or bash functions inside your .bashrc or .zshrc profile for quick triage during incident response.
Here is a lightweight triage pipeline that extracts top DNS queries, TLS destinations, and unusual IP traffic from any target PCAP file:
function pcap_summary() {
echo '=== TOP DNS QUERIES ==='
tshark -r '$1' -Y 'dns.flags.response == 0' -T fields -e dns.qry.name | sort | uniq -c | sort -nr | head -n 10
echo ''
echo '=== TOP TLS SNI TARGETS ==='
tshark -r '$1' -Y 'tls.handshake.type == 1' -T fields -e tls.handshake.extensions_server_name | sort | uniq -c | sort -nr | head -n 10
echo ''
echo '=== TOP CONVERSATIONS BY BYTE COUNT ==='
tshark -r '$1' -z conv,ip | head -n 20
}
Passing any capture file into this function provides an actionable high-level summary of network activity in under three seconds, saving crucial minutes during initial incident intake.
Conclusion
GUI tools like Wireshark remain valuable for deep frame-by-frame inspection, but speed, scale, and automation require mastering the terminal. Incorporating Tshark into your daily analytical workflow lets you handle large datasets effortlessly, build robust SOC automation scripts, and rapidly isolate threats concealed in network traffic.