Fireshark is built from source using the Rust toolchain.
- Rust 1.85 or newer (includes
cargo)
git clone <repository-url>
cd fireshark
cargo build --releaseThe CLI binary is at target/release/fireshark. Copy it anywhere on your PATH:
cp target/release/fireshark /usr/local/bin/List all packets in a capture file with color-coded protocol output:
fireshark summary capture.pcapOutput format:
1 2024-01-15T10:30:45.123Z TCP 192.0.2.10:51514 -> 198.51.100.20:443 54
2 2024-01-15T10:30:45.200Z UDP 10.0.0.5:53214 -> 8.8.8.8:53 72
3 2024-01-15T10:30:45.300Z ARP 00:1a:2b:3c:4d:5e -> ff:ff:ff:ff:ff:ff 42
Each line shows: packet number, timestamp (UTC), protocol, source, destination, and captured length in bytes.
Inspect a single packet with full layer decode and hex dump:
fireshark detail capture.pcap 1Output:
Packet 1 . 54 bytes . 2024-01-15T10:30:45.123Z
-----------------------------------------------
> Ethernet
Destination: 00:1a:2b:3c:4d:5e
Source: aa:bb:cc:dd:ee:ff
EtherType: 0x0800 (IPv4)
> IPv4
Source: 192.0.2.10
Destination: 198.51.100.20
TTL: 64 Protocol: 6 (TCP) ID: 0x1234
DSCP: 0 ECN: 0 Checksum: 0xabcd
> TCP
51514 -> 443 Seq: 100 Ack: 0 [SYN] Win: 65535
Data Offset: 5 (20 bytes)
--- Hex Dump ----------------------------------
0000 00 1a 2b 3c 4d 5e aa bb cc dd ee ff 08 00 45 00 ..+<M^........E.
0010 00 28 12 34 40 00 40 06 ab cd c0 00 02 0a c6 33 .(.4@.@........3
...
# Ethernet # IPv4 # TCP
Each byte in the hex dump is colored by its protocol layer.
Show all packets in a TCP/UDP conversation by stream ID:
fireshark follow capture.pcap 0Output:
Stream 0: TCP 192.0.2.10:51514 ↔ 198.51.100.20:443
3 packets, 162 bytes, duration 0.200s
──────────────────────────────────────
1 2024-01-15T10:30:45.123Z TCP 192.0.2.10:51514 -> 198.51.100.20:443 54
2 2024-01-15T10:30:45.200Z TCP 198.51.100.20:443 -> 192.0.2.10:51514 54
3 2024-01-15T10:30:45.300Z TCP 192.0.2.10:51514 -> 198.51.100.20:443 54
The stream header shows the conversation's protocol, endpoints, packet/byte count, and duration. Use fireshark stats to discover available stream IDs.
The follow command supports reassembled stream views via the tshark backend:
# Show reassembled TCP payload as hex dump
fireshark follow capture.pcap 0 --payload
# Show HTTP request/response for a stream
fireshark follow capture.pcap 0 --httpThe --payload flag shows the reassembled TCP payload as a hex dump, reconstructing the byte stream from individual TCP segments. The --http flag shows the HTTP request and response for HTTP streams. Both flags require tshark to be installed.
TLS certificate details can be extracted from captures using the get_certificates MCP tool (requires tshark backend). This extracts:
- Subject Common Name (CN)
- Subject Alternative Name (SAN) DNS entries
- Organization name
This is useful for identifying which services are being contacted and verifying certificate validity during security audits.
Compare a baseline and suspect capture to find new or missing hosts, protocols, and ports:
fireshark diff baseline.pcap suspect.pcapThe output shows which hosts, protocols, and ports appeared in one capture but not the other — useful for detecting changes between a known-good baseline and a new capture.
Add --json to summary, stats, issues, or audit to get machine-readable output. Each line is one JSON object (JSONL format), with no ANSI color codes:
# JSONL packet summaries
fireshark summary capture.pcap --json
# JSONL statistics
fireshark stats capture.pcap --json
# JSONL decode issues
fireshark issues capture.pcap --json
# JSONL audit findings
fireshark audit capture.pcap --jsonThis is useful for piping into jq, feeding into scripts, or integrating with other tools.
Fireshark validates IPv4 header, TCP, and UDP checksums during dissection. If a checksum does not match the computed value, a ChecksumMismatch decode issue is recorded on the packet. Zero checksums (common when NIC offload is enabled, meaning the checksum was computed by hardware after capture) are skipped — they are not flagged as errors.
Checksum issues appear in the issues command output and in detail view decode issue indicators.
fireshark supports two analysis backends. The choice affects which features are available and how broad protocol coverage is.
The native backend uses fireshark's built-in Rust dissectors. This is the default and provides the full feature set:
- Deep protocol analysis with typed field extraction (11 protocols)
- Security audit heuristics (scan detection, DNS tunneling, cleartext credentials, etc.)
- TCP/UDP stream tracking with
followcommand andtcp.stream/udp.streamfilters - Display filter evaluation on all supported fields (
tcp.flags.syn and ip.ttl > 64) - Color-coded hex dump with per-layer byte spans in
detailview - Zero external dependencies -- works without Wireshark installed
fireshark summary capture.pcap # native is the default
fireshark summary --backend native capture.pcap # explicit
fireshark audit capture.pcap # audit requires native
fireshark follow capture.pcap 0 # follow requires nativeThe tshark backend delegates analysis to Wireshark's tshark command-line tool. It provides broader protocol recognition (3,000+ protocols) but with reduced feature depth:
- Protocol identification and packet summaries work for all protocols tshark supports
- Capture statistics (
statscommand) work - Stream reassembly is available --
follow --payload(hex dump) andfollow --http(HTTP request/response) - TLS certificate extraction is available --
get_certificatesMCP tool - Stream tracking (native) is not available -- no
tcp.stream/udp.streamfilters - Security audit is not available -- no
auditcommand - Display filters are not available -- fireshark's filter engine requires typed native layers
- Detail hex dump is not available -- tshark does not expose per-layer byte offsets
fireshark summary --backend tshark capture.pcap
fireshark stats --backend tshark capture.pcap| Scenario | Recommended backend |
|---|---|
| Deep analysis of TCP/IP traffic | native |
| Security audit of a capture | native |
| Following a TCP/UDP conversation | native |
| Filtering packets by field values | native |
| Inspecting packet bytes with hex dump | native |
| Reassembled TCP stream payload | tshark |
| HTTP request/response extraction | tshark |
| TLS certificate extraction | tshark |
| Triage of a capture with many unknown protocols | tshark |
| Quick protocol distribution overview | either |
| Validating fireshark output against Wireshark | tshark |
Note: tshark must be installed on your system for --backend tshark to work. If tshark is not found, fireshark will report an error. See the operations guide for tshark discovery details.
fireshark stats capture.pcapShows packet count, stream count, capture duration, protocol distribution, and top endpoints.
Apply a display filter to show only matching packets:
fireshark summary capture.pcap -f "tcp and port 443"Fireshark supports a Wireshark-style display filter language. Pass a filter expression with the -f flag on the summary command.
Match packets containing a specific protocol:
| Expression | Matches |
|---|---|
tcp |
Any packet with a TCP layer |
udp |
Any packet with a UDP layer |
arp |
Any packet with an ARP layer |
icmp |
Any packet with an ICMP layer |
dns |
Any packet with a DNS layer |
tls |
Any packet with a TLS layer (ClientHello or ServerHello) |
http |
Any packet with an HTTP layer |
ipv4 |
Any packet with an IPv4 layer |
ipv6 |
Any packet with an IPv6 layer |
ethernet |
Any packet with an Ethernet layer |
Combine expressions with and, or, and not:
| Operator | Example | Meaning |
|---|---|---|
and |
tcp and udp |
Both must be present |
or |
tcp or udp |
Either must be present |
not |
not arp |
ARP must not be present |
() |
(tcp or udp) and port 53 |
Grouping for precedence |
Operator precedence (highest to lowest): not, and, or. Use parentheses to override.
Convenience expressions that expand to common multi-field checks:
| Shorthand | Equivalent | Meaning |
|---|---|---|
port 443 |
tcp.port == 443 or udp.port == 443 |
TCP or UDP port, either direction |
src 192.168.1.2 |
ip.src == 192.168.1.2 |
Source IP address |
dst 10.0.0.0/8 |
ip.dst == 10.0.0.0/8 |
Destination IP with CIDR |
host 192.168.1.1 |
ip.src == 192.168.1.1 or ip.dst == 192.168.1.1 |
Source or destination IP |
Compare specific protocol fields against values:
<field> <operator> <value>
| Operator | Meaning |
|---|---|
== |
Equal |
!= |
Not equal |
> |
Greater than |
< |
Less than |
>= |
Greater than or equal |
<= |
Less than or equal |
| Operator | Meaning |
|---|---|
contains |
Case-insensitive substring match |
matches |
Regular expression match (regex crate syntax) |
String operators work on any field type. Non-string fields are converted to their string representation before matching.
# Find DNS queries for a specific domain (case-insensitive)
fireshark summary capture.pcap -f 'dns.qname contains "evil.com"'
# Find TLS connections to CDN hosts using regex
fireshark summary capture.pcap -f 'tls.sni matches "^cdn\d+\.example\.com"'
# Works on non-string fields too (via string conversion)
fireshark summary capture.pcap -f 'ip.src contains "192.168"'Frame fields:
| Field | Type | Description |
|---|---|---|
frame.len |
integer | Original wire length |
frame.cap_len |
integer | Captured length |
Ethernet fields:
| Field | Type | Description |
|---|---|---|
eth.type |
integer | EtherType value |
IPv4 fields:
| Field | Type | Description |
|---|---|---|
ip.src |
address | Source IP (also matches IPv6) |
ip.dst |
address | Destination IP (also matches IPv6) |
ip.ttl |
integer | Time to live |
ip.id |
integer | Identification |
ip.proto |
integer | Protocol number |
ip.dscp |
integer | DSCP value |
ip.ecn |
integer | ECN value |
ip.checksum |
integer | Header checksum |
ip.flags.df |
boolean | Don't Fragment flag |
ip.flags.mf |
boolean | More Fragments flag |
ip.frag_offset |
integer | Fragment offset |
IPv6 fields:
| Field | Type | Description |
|---|---|---|
ip.src |
address | Source IP (dual-stack, shared with IPv4) |
ip.dst |
address | Destination IP (dual-stack, shared with IPv4) |
ipv6.hlim |
integer | Hop limit |
ipv6.flow |
integer | Flow label |
ipv6.tc |
integer | Traffic class |
ipv6.nxt |
integer | Next header |
TCP fields:
| Field | Type | Description |
|---|---|---|
tcp.srcport |
integer | Source port |
tcp.dstport |
integer | Destination port |
tcp.port |
integer | Either source or destination port |
tcp.seq |
integer | Sequence number |
tcp.ack |
integer | Acknowledgment number |
tcp.window |
integer | Window size |
tcp.hdr_len |
integer | Header length in bytes |
tcp.flags.syn |
boolean | SYN flag |
tcp.flags.ack |
boolean | ACK flag |
tcp.flags.fin |
boolean | FIN flag |
tcp.flags.rst |
boolean | RST flag |
tcp.flags.psh |
boolean | PSH flag |
tcp.flags.urg |
boolean | URG flag |
tcp.flags.ece |
boolean | ECE flag |
tcp.flags.cwr |
boolean | CWR flag |
tcp.stream |
integer | TCP stream ID (conversation number, assigned by TrackingPipeline) |
UDP fields:
| Field | Type | Description |
|---|---|---|
udp.srcport |
integer | Source port |
udp.dstport |
integer | Destination port |
udp.port |
integer | Either source or destination port |
udp.length |
integer | UDP datagram length |
udp.stream |
integer | UDP stream ID (conversation number, assigned by TrackingPipeline) |
ICMP fields:
| Field | Type | Description |
|---|---|---|
icmp.type |
integer | ICMP message type |
icmp.code |
integer | ICMP message code |
DNS fields:
| Field | Type | Description |
|---|---|---|
dns.id |
integer | Transaction ID |
dns.qr |
boolean | Query/response flag (true=response) |
dns.opcode |
integer | Operation code |
dns.qcount |
integer | Question count |
dns.acount |
integer | Answer count |
dns.qtype |
integer | Query type (1=A, 28=AAAA, etc.) |
dns.qname |
string | Query name (e.g., "example.com") |
dns.rcode |
integer | Response code (0=NOERROR, 3=NXDOMAIN, etc.) |
TLS fields:
| Field | Type | Description |
|---|---|---|
tls.handshake.type |
integer | Handshake type (1=ClientHello, 2=ServerHello) |
tls.record_version |
integer | TLS record layer version |
tls.client_version |
integer | ClientHello version (ClientHello only) |
tls.selected_version |
integer | Selected version from supported_versions extension (ServerHello only) |
tls.cipher_suite |
integer | Selected cipher suite (ServerHello only) |
tls.sni |
string | Server Name Indication (ClientHello only) |
HTTP fields:
| Field | Type | Description |
|---|---|---|
http.method |
string | HTTP method (GET, POST, etc.) |
http.uri |
string | Request URI |
http.host |
string | Host header value |
http.status_code |
integer | Response status code |
http.content_type |
string | Content-Type header value |
ARP fields:
| Field | Type | Description |
|---|---|---|
arp.opcode |
integer | ARP operation (1=request, 2=reply) |
arp.spa |
address | Sender protocol address |
arp.tpa |
address | Target protocol address |
IP address fields support CIDR subnet matching:
ip.src == 10.0.0.0/8
ip.dst == 192.168.1.0/24
dst 172.16.0.0/12
Boolean fields (TCP flags, IP flags) can be compared against true or false:
tcp.flags.syn == true
ip.flags.df == true
tcp.flags.ack == false
Or used as bare expressions for protocol presence checks.
Summary output is color-coded by the highest-layer protocol:
| Protocol | Color |
|---|---|
| TCP | Green |
| UDP | Blue |
| ARP | Yellow |
| ICMP | Cyan |
| DNS | Magenta |
| TLS | Bright Green |
| HTTP | Bright Cyan |
| Ethernet, IPv4, IPv6 | White |
| Unknown / other | Red |
Colors follow Wireshark conventions. The hex dump in the detail view colors each byte by its protocol layer, with a legend at the bottom.
The detail command shows three sections for a single packet:
Packet 1 . 54 bytes . 2024-01-15T10:30:45.123Z
Packet number, captured length, and UTC timestamp.
Each decoded protocol layer is shown with all extracted fields:
- Ethernet -- destination MAC, source MAC, EtherType
- ARP -- operation, sender IP, target IP
- IPv4 -- source, destination, TTL, protocol, ID, flags (DF/MF), DSCP, ECN, checksum
- IPv6 -- source, destination, next header, hop limit, traffic class, flow label
- TCP -- ports, sequence, acknowledgment, flags (SYN/ACK/FIN/RST/PSH/URG/ECE/CWR), window, data offset
- UDP -- ports, length
- ICMP -- type (with name), code, and type-specific detail (echo ID/seq, next hop MTU)
- DNS -- transaction ID, query/response, opcode, question count, answer count, query name, query type, A/AAAA answer records
- TLS ClientHello -- record version, client version, cipher suites, SNI, ALPN, supported versions, signature algorithms, key share groups
- TLS ServerHello -- record version, server version, cipher suite, selected version, ALPN, key share group
- HTTP -- method, URI, host, status code, content type
If a packet has decode issues, they appear after the layer tree:
! Truncated at offset 34
! Malformed at offset 14
A 16-bytes-per-line hex dump with:
- Offset column (hex)
- Hex bytes colored by protocol layer
- ASCII column (printable characters, dots for non-printable)
- Legend mapping colors to protocol names
The MCP server provides LLM-driven capture analysis over stdio transport. For the complete MCP tool reference with all parameters, see MCP Server Reference.
# From source
cargo run -p fireshark-mcp
# Or the release binary
fireshark-mcpThe server communicates over stdin/stdout using the Model Context Protocol.
# Build the release binary
cargo build -p fireshark-mcp --release
# Register with Claude Code
claude mcp add fireshark ./target/release/fireshark-mcpOr add manually to ~/.claude/mcp.json:
{
"mcpServers": {
"fireshark": {
"command": "/path/to/fireshark/target/release/fireshark-mcp"
}
}
}Once connected, Claude can analyze captures directly:
"Open
/tmp/traffic.pcapand audit it for security issues"
Add to your Codex MCP configuration:
{
"servers": {
"fireshark": {
"command": "/path/to/fireshark/target/release/fireshark-mcp",
"transport": "stdio"
}
}
}A typical LLM-driven session through MCP:
open_capture({ path: "/tmp/traffic.pcap" })→ session_id + protocol breakdownsummarize_capture({ session_id })→ protocols, endpoints, streams, findingsaudit_capture({ session_id })→ security findings with evidenceget_packet({ session_id, packet_index: 42 })→ full layer decodelist_packets({ session_id, filter: "tls and tls.handshake.type == 1" })→ TLS ClientHellosget_stream({ session_id, stream_id: 5 })→ follow a conversationescalate_finding({ session_id, finding_id: "f1", notes: "confirmed C2 beacon" })→ mark finding for reviewclose_capture({ session_id })→ free resources
Any MCP-compatible client can connect by spawning the binary as a subprocess over stdio.
| Tool | Parameters | Returns |
|---|---|---|
open_capture |
path (string), optional max_packets (integer, default 100000, max 1000000) |
Session ID, packet count, protocol summary |
describe_capture |
session_id (string) |
Capture metadata, protocol breakdown, top endpoints |
close_capture |
session_id (string) |
Confirmation |
| Tool | Parameters | Returns |
|---|---|---|
list_packets |
session_id, optional offset, limit, protocol, has_issues |
Paginated packet summaries |
get_packet |
session_id, packet_number |
Full packet detail with all layer fields |
search_packets |
session_id, search criteria (protocol, address, port, text, issues) |
Matching packet list |
list_decode_issues |
session_id, optional kind filter |
Paginated decode issues |
summarize_protocols |
session_id |
Protocol distribution table |
top_endpoints |
session_id |
Most active endpoints by packet count |
| Tool | Parameters | Returns |
|---|---|---|
list_streams |
session_id, optional offset, limit |
Paginated TCP/UDP conversation metadata |
get_stream |
session_id, stream_id |
Stream metadata plus all packets in the conversation |
get_stream_payload |
session_id, stream_id |
Reassembled TCP payload hex dump (requires tshark backend) |
| Tool | Parameters | Returns |
|---|---|---|
summarize_capture |
session_id |
Single-call summary: packets, streams, protocols, endpoints, timestamps, findings |
| Tool | Parameters | Returns |
|---|---|---|
compare_captures |
session_id_a, session_id_b |
New/missing hosts, protocols, and ports between two captures |
| Tool | Parameters | Returns |
|---|---|---|
audit_capture |
session_id, optional profile ("security", "dns", "quality") |
Heuristic security analysis results (filtered by profile if specified) |
list_findings |
session_id |
Audit findings with severity and evidence |
explain_finding |
session_id, finding_id |
Detailed explanation of a specific finding |
escalate_finding |
session_id, finding_id, optional notes |
Mark a finding as escalated with investigation notes |
| Tool | Parameters | Returns |
|---|---|---|
get_certificates |
session_id |
TLS certificate details: subject CN, SAN DNS names, organization (requires tshark backend) |
A typical MCP session:
Client: open_capture(path: "/tmp/suspect.pcap")
Server: { session_id: "abc123", packets: 1500, protocols: { TCP: 1200, UDP: 250, ARP: 50 } }
Client: describe_capture(session_id: "abc123")
Server: { packet_count: 1500, duration: "5m30s", top_endpoints: [...] }
Client: audit_capture(session_id: "abc123")
Server: { findings: [{ id: "f1", severity: "high", title: "Port scan detected", ... }] }
Client: explain_finding(session_id: "abc123", finding_id: "f1")
Server: { detail: "Sequential SYN packets to ports 22, 80, 443, 8080 from 10.0.0.5...", evidence: [...] }
Client: search_packets(session_id: "abc123", address: "10.0.0.5")
Server: { packets: [{ number: 1, protocol: "TCP", ... }, ...] }
Client: close_capture(session_id: "abc123")
Server: { status: "closed" }
- Stdio transport only -- no HTTP or WebSocket
- Offline captures only -- no live packet capture
- Default packet limit: 100,000 (configurable via
max_packetsparameter inopen_capture, capped at 1,000,000) - Maximum 8 concurrent sessions
- Sessions expire after 15 minutes of inactivity
| Surface | Packet limit | Behavior |
|---|---|---|
summary, detail, stats, issues, follow |
None -- streaming | Processes any capture size |
audit CLI command |
100,000 (configurable via --max-packets) |
Rejects capture if exceeded |
MCP open_capture |
100,000 (configurable via max_packets parameter) |
Rejects capture if exceeded |
| tshark backend | None | Loads whatever tshark outputs |
The streaming CLI commands (summary, detail, stats, issues, follow) iterate packets one at a time and have no memory limit. The audit command and MCP tools load all packets into memory for indexing and cross-referencing, so they enforce a configurable packet limit (default 100,000).
To analyze larger captures:
# CLI: increase the limit for audit
fireshark audit --max-packets 500000 large-capture.pcapFor MCP, pass max_packets when opening:
{ "path": "/tmp/large.pcap", "max_packets": 500000 }fireshark summary capture.pcap -f "tcp.flags.syn == true and tcp.flags.ack == false"fireshark summary capture.pcap -f "dns"fireshark summary capture.pcap -f "dns and not dns.qr"fireshark summary capture.pcap -f "dns.id == 0x1234"fireshark summary capture.pcap -f "dns.qtype == 1"fireshark summary capture.pcap -f "src 10.0.0.0/8"
fireshark summary capture.pcap -f "dst 192.168.0.0/16"fireshark detail capture.pcap 5fireshark summary capture.pcap -f "arp"fireshark summary capture.pcap -f "tcp.flags.rst == true"fireshark summary capture.pcap -f "host 192.168.1.10 and host 192.168.1.20"fireshark summary capture.pcap -f "icmp"fireshark summary capture.pcap -f "ip.ttl > 200"fireshark summary capture.pcap -f "tcp and not port 80 and not port 443 and not port 22"fireshark summary capture.pcap -f "ip.flags.mf == true"fireshark summary capture.pcap -f "udp and not port 53"fireshark summary capture.pcap -f "http"fireshark summary capture.pcap -f 'http.method contains "POST"'fireshark summary capture.pcap -f 'http.host contains "example.com"'fireshark summary capture.pcap -f 'http.uri contains "/api"'fireshark summary capture.pcap -f "http.status_code == 200"fireshark summary capture.pcap -f "tls"fireshark summary capture.pcap -f "tls.handshake.type == 1"fireshark summary capture.pcap -f "tls.handshake.type == 2"fireshark summary capture.pcap -f "tls.cipher_suite == 0x1301"# Show all packets in TCP conversation 0
fireshark summary capture.pcap -f "tcp.stream == 0"
# Show all packets in UDP conversation 1
fireshark summary capture.pcap -f "udp.stream == 1"fireshark follow capture.pcap 0# Case-insensitive substring match on DNS query name
fireshark summary capture.pcap -f 'dns.qname contains "evil"'
# Regex match on TLS SNI
fireshark summary capture.pcap -f 'tls.sni matches ".*\.example\.com"'
# String conversion: works on any field
fireshark summary capture.pcap -f 'ip.dst contains "10.0"'# Run all heuristics (default)
fireshark audit capture.pcap
# Security-focused audit only
fireshark audit --profile security capture.pcap
# DNS-focused audit only
fireshark audit --profile dns capture.pcap
# Quality-focused audit only
fireshark audit --profile quality capture.pcapVersion: 0.9.0 | Last updated: 2026-03-18 | Maintained by: hendrik.reh@blacksmith-consulting.ai