network security

Analyzing Network Traffic with Wireshark

Captures and analyzes network packet data using Wireshark and tshark to identify malicious traffic patterns, diagnose protocol issues, extract artifacts, and support incident response investigations on authorized network segments.

network-securitypacket-analysispcaptraffic-analysiswireshark
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

  • Investigating suspected network intrusions by examining packet-level evidence of command-and-control traffic, data exfiltration, or lateral movement
  • Diagnosing network performance issues such as retransmissions, fragmentation, or DNS resolution failures
  • Analyzing malware communication patterns by capturing traffic from sandboxed or isolated hosts
  • Validating firewall and IDS rules by confirming what traffic is actually traversing network segments
  • Extracting files, credentials, or indicators of compromise from captured network sessions

Do not use to capture traffic on networks without authorization, to intercept private communications without legal authority, or as a substitute for full-featured SIEM platforms in production monitoring.

Prerequisites

  • Wireshark 4.0+ and tshark command-line utility installed
  • Root/sudo privileges or membership in the wireshark group for live packet capture
  • Network interface access (physical NIC, span port, or network tap) to the monitored segment
  • Sufficient disk space for packet capture files (estimate 1 GB per minute on busy gigabit links)
  • Familiarity with TCP/IP protocols, HTTP, DNS, TLS, and SMB at the packet level

Workflow

Step 1: Configure Capture Environment

Set up the capture interface and filters to target relevant traffic:

# List available interfaces
tshark -D
 
# Start capture on eth0 with a capture filter to limit scope
tshark -i eth0 -f "host 10.10.5.23 and (port 80 or port 443 or port 445)" -w /tmp/capture.pcapng
 
# Capture with ring buffer to manage disk usage (10 files, 100MB each)
tshark -i eth0 -b filesize:102400 -b files:10 -w /tmp/rolling_capture.pcapng
 
# Capture on multiple interfaces simultaneously
tshark -i eth0 -i eth1 -w /tmp/multi_interface.pcapng

For Wireshark GUI, set capture filter in the Capture Options dialog before starting.

Step 2: Apply Display Filters for Targeted Analysis

# Filter HTTP traffic containing suspicious user agents
tshark -r capture.pcapng -Y "http.user_agent contains \"curl\" or http.user_agent contains \"Wget\""
 
# Find DNS queries to suspicious TLDs
tshark -r capture.pcapng -Y "dns.qry.name contains \".xyz\" or dns.qry.name contains \".top\" or dns.qry.name contains \".tk\""
 
# Identify TCP retransmissions indicating network issues
tshark -r capture.pcapng -Y "tcp.analysis.retransmission"
 
# Filter SMB traffic for lateral movement detection
tshark -r capture.pcapng -Y "smb2.cmd == 5 or smb2.cmd == 3" -T fields -e ip.src -e ip.dst -e smb2.filename
 
# Find cleartext credential transmission
tshark -r capture.pcapng -Y "ftp.request.command == \"PASS\" or http.authbasic"
 
# Detect beaconing patterns (regular interval connections)
tshark -r capture.pcapng -Y "ip.dst == 203.0.113.50" -T fields -e frame.time_relative -e ip.src -e tcp.dstport

Step 3: Protocol-Specific Deep Analysis

# Follow a TCP stream to reconstruct a conversation
tshark -r capture.pcapng -q -z follow,tcp,ascii,0
 
# Analyze HTTP request/response pairs
tshark -r capture.pcapng -Y "http" -T fields -e frame.time -e ip.src -e ip.dst -e http.request.method -e http.request.uri -e http.response.code
 
# Extract DNS query/response statistics
tshark -r capture.pcapng -q -z dns,tree
 
# Analyze TLS handshakes for weak cipher suites
tshark -r capture.pcapng -Y "tls.handshake.type == 2" -T fields -e ip.src -e ip.dst -e tls.handshake.ciphersuite
 
# SMB file access enumeration
tshark -r capture.pcapng -Y "smb2" -T fields -e frame.time -e ip.src -e ip.dst -e smb2.filename -e smb2.cmd

Step 4: Extract Artifacts and IOCs

# Export HTTP objects (files transferred over HTTP)
tshark -r capture.pcapng --export-objects http,/tmp/http_objects/
 
# Export SMB objects (files transferred over SMB)
tshark -r capture.pcapng --export-objects smb,/tmp/smb_objects/
 
# Extract all unique destination IPs for threat intelligence lookup
tshark -r capture.pcapng -T fields -e ip.dst | sort -u > unique_dest_ips.txt
 
# Extract SSL/TLS certificate information
tshark -r capture.pcapng -Y "tls.handshake.type == 11" -T fields -e x509sat.uTF8String -e x509ce.dNSName
 
# Extract all URLs accessed
tshark -r capture.pcapng -Y "http.request" -T fields -e http.host -e http.request.uri | sort -u > urls.txt
 
# Hash extracted files for IOC matching
find /tmp/http_objects/ -type f -exec sha256sum {} \; > extracted_file_hashes.txt

Step 5: Statistical Analysis and Anomaly Detection

# Protocol hierarchy statistics
tshark -r capture.pcapng -q -z io,phs
 
# Conversation statistics sorted by bytes
tshark -r capture.pcapng -q -z conv,tcp -z conv,udp
 
# Identify top talkers
tshark -r capture.pcapng -q -z endpoints,ip
 
# IO graph data (packets per second)
tshark -r capture.pcapng -q -z io,stat,1,"COUNT(frame) frame"
 
# Detect port scanning patterns
tshark -r capture.pcapng -Y "tcp.flags.syn == 1 and tcp.flags.ack == 0" -T fields -e ip.src -e tcp.dstport | sort | uniq -c | sort -rn | head -20

Step 6: Generate Reports and Export Evidence

# Export filtered packets to a new PCAP for evidence preservation
tshark -r capture.pcapng -Y "ip.addr == 10.10.5.23 and tcp.port == 4444" -w evidence_c2_traffic.pcapng
 
# Generate packet summary in CSV format
tshark -r capture.pcapng -T fields -E header=y -E separator=, -e frame.number -e frame.time -e ip.src -e ip.dst -e ip.proto -e tcp.srcport -e tcp.dstport -e frame.len > traffic_summary.csv
 
# Create PDML (XML) output for programmatic analysis
tshark -r capture.pcapng -T pdml > capture_analysis.xml
 
# Calculate capture file hash for chain of custody
sha256sum capture.pcapng > capture_hash.txt

Key Concepts

Term Definition
Capture Filter (BPF) Berkeley Packet Filter syntax applied at capture time to limit which packets are recorded, reducing file size and improving performance
Display Filter Wireshark-specific filter syntax applied to already-captured packets for focused analysis without altering the capture file
PCAPNG Next-generation packet capture format supporting multiple interfaces, name resolution, annotations, and metadata in a single file
TCP Stream Reassembled sequence of TCP segments representing a complete bidirectional conversation between two endpoints
Protocol Dissector Wireshark module that decodes a specific protocol's fields and structure, enabling deep inspection of packet contents
IO Graph Time-series visualization of packet or byte rates over the capture duration, useful for identifying traffic spikes or beaconing

Tools & Systems

  • Wireshark 4.0+: GUI-based packet analyzer with protocol dissectors for 3,000+ protocols, stream reassembly, and export capabilities
  • tshark: Command-line version of Wireshark for headless capture, batch processing, and scripted analysis pipelines
  • tcpdump: Lightweight packet capture tool for quick captures on remote systems without GUI dependencies
  • mergecap: Wireshark utility for combining multiple capture files into a single PCAP for unified analysis
  • editcap: Wireshark utility for splitting, filtering, and converting between capture file formats

Common Scenarios

Scenario: Investigating Suspected Data Exfiltration via DNS Tunneling

Context: The SOC team detected unusually high DNS query volumes from a workstation (10.10.3.45) to an external domain. The SIEM alert flagged DNS queries averaging 200 per minute compared to the baseline of 15. A packet capture was initiated from the network tap on the workstation's VLAN.

Approach:

  1. Capture traffic from the workstation's subnet using tshark -i eth2 -f "host 10.10.3.45 and port 53" -w dns_exfil_investigation.pcapng
  2. Analyze DNS query patterns: tshark -r dns_exfil_investigation.pcapng -Y "dns.qry.name contains \"suspect-domain.xyz\"" -T fields -e frame.time -e dns.qry.name
  3. Examine subdomain labels for encoded data (long base64-like subdomains indicate tunneling): tshark -r dns_exfil_investigation.pcapng -Y "dns.qry.type == 16" -T fields -e dns.qry.name -e dns.txt
  4. Calculate data volume by summing query name lengths to estimate exfiltration bandwidth
  5. Extract unique query names and decode base64 subdomains to recover exfiltrated content
  6. Export evidence packets to a separate PCAP and generate SHA-256 hash for chain of custody

Pitfalls:

  • Capturing unfiltered traffic on a busy network and running out of disk space before collecting relevant data
  • Using display filters instead of capture filters, resulting in massive files that are slow to process
  • Overlooking encrypted DNS (DoH/DoT) traffic that bypasses traditional DNS capture on port 53
  • Failing to establish packet capture hash and chain of custody documentation for forensic evidence

Output Format

## Traffic Analysis Report
 
**Case ID**: IR-2024-0847
**Capture File**: dns_exfil_investigation.pcapng
**SHA-256**: a3f2b8c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1
**Duration**: 2024-03-15 14:00:00 to 14:45:00 UTC
**Source Interface**: eth2 (VLAN 30 span port)
 
### Findings
 
**1. DNS Tunneling Confirmed**
- Source: 10.10.3.45
- Destination DNS: 8.8.8.8 (forwarded to ns1.suspect-domain.xyz)
- Query volume: 9,247 queries in 45 minutes (205/min vs 15/min baseline)
- Average subdomain label length: 63 characters (base64-encoded data)
- Estimated data exfiltrated: ~2.3 MB via TXT record responses
 
**2. Indicators of Compromise**
- Domain: suspect-domain.xyz (registered 3 days prior)
- Nameserver: ns1.suspect-domain.xyz (203.0.113.50)
- Query pattern: TXT record requests with base64-encoded subdomains
- Response pattern: TXT records containing base64-encoded payloads
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 1

api-reference.md2.9 KB

API Reference: Wireshark and tshark

Live Capture

tshark -i eth0                              # Capture on interface
tshark -i eth0 -w output.pcap              # Write to file
tshark -i eth0 -a duration:60              # Capture for 60 seconds
tshark -i eth0 -f "port 80"               # BPF capture filter
tshark -D                                   # List interfaces

Display Filters (Read Mode)

tshark -r capture.pcap -Y "<filter>"

Common Filters

Filter Purpose
ip.addr == 10.0.0.5 Traffic to/from IP
tcp.port == 443 Traffic on port 443
http.request HTTP requests only
dns.qr == 0 DNS queries only
tls.handshake.type == 1 TLS Client Hello
tcp.flags.syn == 1 && tcp.flags.ack == 0 SYN-only
frame.len > 1500 Large frames
tcp.analysis.retransmission Retransmissions
icmp ICMP traffic

Field Extraction

tshark -r capture.pcap -T fields \
  -e frame.time -e ip.src -e ip.dst -e tcp.dstport \
  -E separator="," -E header=y

Common Fields

Field Description
frame.time Packet timestamp
ip.src / ip.dst Source/destination IP
tcp.srcport / tcp.dstport TCP ports
http.request.method HTTP method
http.host HTTP Host header
http.request.uri Request URI
http.user_agent User-Agent
dns.qry.name DNS query name
tls.handshake.extensions_server_name TLS SNI
tls.handshake.ja3 JA3 fingerprint

Statistics

tshark -r capture.pcap -q -z conv,ip         # IP conversations
tshark -r capture.pcap -q -z endpoints,ip    # IP endpoints
tshark -r capture.pcap -q -z io,stat,60      # I/O per minute
tshark -r capture.pcap -q -z io,phs          # Protocol hierarchy
tshark -r capture.pcap -q -z http,tree       # HTTP stats
tshark -r capture.pcap -q -z dns,tree        # DNS stats
tshark -r capture.pcap -q -z expert          # Expert info

Object Export

tshark -r capture.pcap --export-objects "http,/output/dir"
tshark -r capture.pcap --export-objects "smb,/output/dir"
tshark -r capture.pcap --export-objects "tftp,/output/dir"
tshark -r capture.pcap --export-objects "imf,/output/dir"

Stream Following

tshark -r capture.pcap -z follow,tcp,ascii,0
tshark -r capture.pcap -z follow,http,ascii,0
tshark -r capture.pcap -z follow,tls,ascii,0

Wireshark GUI Shortcuts

Shortcut Action
Ctrl+F Find packet
Ctrl+G Go to packet
Ctrl+Shift+E Export objects
Ctrl+H Follow stream

editcap - PCAP Manipulation

editcap -A "2024-01-15 09:00" -B "2024-01-15 10:00" in.pcap out.pcap  # Time filter
editcap -c 1000 large.pcap split.pcap    # Split into 1000-packet files
editcap -F pcap in.pcapng out.pcap       # Convert format

mergecap - Merge PCAPs

mergecap -w merged.pcap file1.pcap file2.pcap

Scripts 1

agent.py7.3 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Wireshark/tshark packet analysis agent for network security investigations."""

import subprocess
import shlex
import os
import sys


def run_tshark(pcap_path, args):
    """Execute tshark with custom arguments."""
    cmd = ["tshark", "-r", pcap_path] + shlex.split(args)
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
    return result.stdout.strip(), result.stderr.strip(), result.returncode


def capture_live(interface, output_path, duration=60, capture_filter=None):
    """Start a live packet capture using tshark."""
    cmd = ["tshark", "-i", interface, "-w", output_path, "-a", f"duration:{duration}"]
    if capture_filter:
        cmd += ["-f", capture_filter]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=duration + 10)
    return result.returncode == 0


def get_capture_summary(pcap_path):
    """Get overall PCAP capture statistics."""
    stdout, _, _ = run_tshark(pcap_path, "-q -z io,stat,0")
    return stdout


def get_protocol_hierarchy(pcap_path):
    """Get protocol hierarchy statistics."""
    stdout, _, _ = run_tshark(pcap_path, "-q -z io,phs")
    return stdout


def get_conversations(pcap_path, conv_type="ip"):
    """Get conversation statistics (ip, tcp, udp, ethernet)."""
    stdout, _, _ = run_tshark(pcap_path, f"-q -z conv,{conv_type}")
    return stdout


def get_endpoints(pcap_path, endpoint_type="ip"):
    """Get endpoint statistics."""
    stdout, _, _ = run_tshark(pcap_path, f"-q -z endpoints,{endpoint_type}")
    return stdout


def extract_http_requests(pcap_path):
    """Extract HTTP requests with key fields."""
    stdout, _, _ = run_tshark(
        pcap_path,
        '-Y "http.request" -T fields -e frame.time -e ip.src -e ip.dst '
        '-e http.request.method -e http.host -e http.request.uri -e http.user_agent '
        '-E separator="|"'
    )
    requests = []
    for line in stdout.splitlines():
        parts = line.split("|")
        if len(parts) >= 6:
            requests.append({
                "time": parts[0],
                "src": parts[1],
                "dst": parts[2],
                "method": parts[3],
                "host": parts[4],
                "uri": parts[5],
                "user_agent": parts[6] if len(parts) > 6 else "",
            })
    return requests


def extract_dns_queries(pcap_path):
    """Extract DNS queries and responses."""
    stdout, _, _ = run_tshark(
        pcap_path,
        '-Y "dns" -T fields -e frame.time -e ip.src -e ip.dst '
        '-e dns.qry.name -e dns.qry.type -e dns.flags.response '
        '-E separator="|"'
    )
    queries = []
    for line in stdout.splitlines():
        parts = line.split("|")
        if len(parts) >= 5:
            queries.append({
                "time": parts[0],
                "src": parts[1],
                "dst": parts[2],
                "query": parts[3],
                "type": parts[4],
                "is_response": parts[5] if len(parts) > 5 else "0",
            })
    return queries


def extract_tls_info(pcap_path):
    """Extract TLS handshake information including JA3 fingerprints."""
    stdout, _, _ = run_tshark(
        pcap_path,
        '-Y "tls.handshake.type==1" -T fields -e ip.src -e ip.dst '
        '-e tls.handshake.extensions_server_name -e tls.handshake.ja3 '
        '-E separator="|"'
    )
    tls_sessions = []
    for line in stdout.splitlines():
        parts = line.split("|")
        if len(parts) >= 3:
            tls_sessions.append({
                "client": parts[0],
                "server": parts[1],
                "sni": parts[2],
                "ja3": parts[3] if len(parts) > 3 else "",
            })
    return tls_sessions


def detect_suspicious_traffic(pcap_path):
    """Detect common suspicious traffic patterns."""
    findings = []

    # Large ICMP packets (possible data exfiltration)
    stdout, _, rc = run_tshark(pcap_path, '-Y "icmp && frame.len > 100" -T fields -e ip.src -e ip.dst -e frame.len')
    if stdout:
        findings.append({
            "type": "Large ICMP",
            "description": "ICMP packets with large payloads detected",
            "count": len(stdout.splitlines()),
        })

    # DNS TXT queries (possible tunneling)
    stdout, _, rc = run_tshark(pcap_path, '-Y "dns.qry.type==16" -T fields -e ip.src -e dns.qry.name')
    if stdout:
        findings.append({
            "type": "DNS TXT Queries",
            "description": "DNS TXT record queries detected",
            "count": len(stdout.splitlines()),
        })

    # Non-standard HTTP ports
    stdout, _, rc = run_tshark(
        pcap_path,
        '-Y "http && tcp.port != 80 && tcp.port != 443 && tcp.port != 8080" '
        '-T fields -e ip.src -e ip.dst -e tcp.dstport'
    )
    if stdout:
        findings.append({
            "type": "HTTP on non-standard port",
            "description": "HTTP traffic on unusual ports",
            "count": len(stdout.splitlines()),
        })

    return findings


def export_http_objects(pcap_path, output_dir):
    """Export HTTP transferred objects."""
    os.makedirs(output_dir, exist_ok=True)
    _, _, rc = run_tshark(pcap_path, f'--export-objects "http,{output_dir}"')
    files = []
    for f in os.listdir(output_dir):
        fpath = os.path.join(output_dir, f)
        files.append({"name": f, "size": os.path.getsize(fpath)})
    return files


def apply_display_filter(pcap_path, display_filter, fields):
    """Apply a custom display filter and extract specified fields."""
    field_str = " ".join(f"-e {f}" for f in fields)
    stdout, _, _ = run_tshark(
        pcap_path, f'-Y "{display_filter}" -T fields {field_str} -E separator="|"'
    )
    results = []
    for line in stdout.splitlines():
        parts = line.split("|")
        results.append(dict(zip(fields, parts)))
    return results


if __name__ == "__main__":
    print("=" * 60)
    print("Wireshark/tshark Network Analysis Agent")
    print("Packet analysis, protocol stats, artifact extraction")
    print("=" * 60)

    pcap = sys.argv[1] if len(sys.argv) > 1 else None

    if pcap and os.path.exists(pcap):
        print(f"\n[*] Analyzing: {pcap}")

        print("\n--- Capture Summary ---")
        summary = get_capture_summary(pcap)
        print(summary[:500] if summary else "  No stats available")

        print("\n--- Protocol Hierarchy ---")
        hierarchy = get_protocol_hierarchy(pcap)
        print(hierarchy[:500] if hierarchy else "  No hierarchy available")

        print("\n--- HTTP Requests ---")
        http = extract_http_requests(pcap)
        for r in http[:10]:
            print(f"  {r['method']} {r['host']}{r['uri']}")

        print("\n--- DNS Queries ---")
        dns = extract_dns_queries(pcap)
        queries_only = [d for d in dns if d["is_response"] == "0"]
        print(f"  Total DNS queries: {len(queries_only)}")

        print("\n--- TLS Sessions ---")
        tls = extract_tls_info(pcap)
        for t in tls[:10]:
            print(f"  {t['client']} -> {t['sni']} (JA3={t['ja3'][:16]}...)" if t['ja3'] else
                  f"  {t['client']} -> {t['sni']}")

        print("\n--- Suspicious Traffic ---")
        suspicious = detect_suspicious_traffic(pcap)
        for s in suspicious:
            print(f"  [!] {s['type']}: {s['description']} ({s['count']} occurrences)")
    else:
        print(f"\n[DEMO] Usage: python agent.py <capture.pcap>")
Keep exploring