Packet captures save packets collected at a specific observation point over a period of time. tcpdump is suitable for conditional collection and offline inspection, while Wireshark/TShark is suitable for protocol field, reassembly, and timing analysis. Reliable conclusions come from the consistency of "collection scope, protocol facts, and inference boundaries," rather than a single line being highlighted in red.
Question to answer first
Impact on collection
Which part of the connection failed
Client, proxy ingress, and proxy egress may require different collection points
TCP or UDP?
Capturing only TCP 443 will miss QUIC
Is DNS involved?
Capturing only by destination IP may miss preceding resolution failures
Do you want to check handshakes or content?
Determines whether to start early, and whether full snaplen and decryption materials are needed
Can it be saved completely?
Determines filtering scope, buffering, file rotation, and stop conditions
Observation position determines what you can prove
Linux host, container network namespace, veth, bridge, physical NIC, and loopback are not the same perspective. -i any covers interfaces available for capture in the current namespace and does not automatically enter all containers. Linux's any typically uses a cooked capture link type; do not assume each packet starts with a standard Ethernet header.
After NAT, addresses and ports may change; after a reverse proxy, it is usually another TCP connection, so you cannot use the same tcp.stream or five-tuple to find the backend. Cross-file association requires combining time, request ID, payload characteristics, and proxy logs; stream numbers in each file are just indices in this analysis result.
Capturing at both ends simultaneously can narrow down where the loss occurred, but if clocks are not synchronized, directly subtracting timestamps will produce incorrect one-way latency. Microsecond or nanosecond precision timestamps do not guarantee measurement accuracy at the same level.
Where do capture filters and display filters take effect?
Attribute
Capture filter
Display filter
Common usage
tcpdump expressions, TShark -f
Wireshark filter bar, TShark -Y
Target
Pre-collection filtering or offline read filtering
Fields after existing packets have been parsed
Example
tcp port 443
tcp.port == 443
Unmatched data
Usually not written to the capture file during real-time collection
Original file is still retained, allowing re-analysis with different conditions
Capability boundaries
Depends on link type, offsets, and compiler support
Depends on dissector, reassembly, and visible plaintext
In real-time collection, libpcap can hand the filtering program to the kernel on supported platforms, reducing packets sent to user space; when reading offline files, the same expressions can be used, but it is not true that "all BPF filtering always happens in the kernel." Without given traffic, match ratios, and decoding overhead, one cannot claim it is fixed by several orders of magnitude. tcpdump manual source
Common capture conditions
# The following are filter expressions, passed to tcpdump as a single quoted argument.# Bidirectional involving destination, covering TCP and UDP 443:tcpdump -nn -r capture.pcap 'host 192.0.2.10 and port 443'# Only IPv4 with SYN set and ACK not set; allows other coexistence flags to exist simultaneously:tcpdump -nn -r capture.pcap 'ip and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn'# One of two destinations, and TCP 443:tcpdump -nn -r capture.pcap '(host 192.0.2.10 or host 192.0.2.20) and tcp port 443'
tcp[tcpflags] == tcp-syn is strict equality of the flag byte, which may exclude SYN packets that also have other coexistence flags; bitwise masking accurately expresses "has SYN, no ACK." Raw transport header offset expressions have additional limitations in scenarios like IPv6 extension headers, so IPv4 is explicitly limited here and cannot be treated as a universal connection establishment statistic for all protocols.
Port conditions do not equal application identification: 443 can carry different protocols, and encrypted DNS traffic is not always on port 53. Non-first IP fragments do not have original transport layer ports; overly narrow port filtering may cause missing fragments during reassembly. VLAN and tunnel encapsulation also affect offsets and match ranges. pcap-filter syntax source
Can changing the display filter recover packets that weren't captured?
Using strict equality for collection first, then displaying all, will only show one packet. You must re-collect using masking to save both SYN types. Changing the collection dropdown itself does not rewrite the already saved file; you must explicitly execute a new collection.
Preparing the visual
Can changing the display filter recover packets that weren't captured?
Display filtering can only filter within the saved set. Strict SYN equality will miss SYN packets with ECE/CWR set simultaneously; displaying all afterwards cannot recover them.
{"id":"capture-filter-evidence","title":"Can changing the display filter recover packets that weren't captured?","summary":"Display filtering can only filter within the saved set. Strict SYN equality will miss SYN packets with ECE/CWR set simultaneously; displaying all afterwards cannot recover them.","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><label class=\"form-field\"><span data-i18n=\"capture\"></span><select id=\"capture\"><option value=\"exact\">flags == 0x02</option><option value=\"mask\">(flags & 0x12) == 0x02</option><option value=\"all\">TCP443: all</option></select></label><div class=\"actions\"><button id=\"record\" data-i18n=\"record\"></button><button id=\"reset\" data-i18n=\"reset\"></button></div><label class=\"form-field\"><span data-i18n=\"display\"></span><select id=\"display\"><option value=\"all\">All saved packets</option><option value=\"syn\">SYN bit set</option></select></label><section class=\"panel\"><h3 data-i18n=\"sets\"></h3><div id=\"sets\"></div></section><div class=\"metrics\"><div><span data-i18n=\"saved\"></span><strong id=\"saved\"></strong></div><div><span data-i18n=\"shown\"></span><strong id=\"shown\"></strong></div></div><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:500;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:500 20px var(--viz-font-ui)}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:var(--viz-font-mono);font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px var(--viz-font-ui);background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n/* Action labels must remain readable across locales and narrow embeds. */\n.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.actions button{overflow-wrap:anywhere;white-space:normal;min-height:58px;padding:8px}\nbutton{overflow-wrap:anywhere}\n@media(min-width:640px){.actions{grid-template-columns:repeat(3,minmax(0,1fr))}}\n\n.metrics span{overflow-wrap:anywhere}\n.panel{border:1px solid var(--rule);border-radius:9px;padding:12px;margin:14px 0;min-width:0}.panel h3{font-size:13px;margin:0 0 10px;color:var(--muted)}.source{font:13px/1.8 var(--viz-font-mono);white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0}.source mark{background:var(--accent-soft);color:var(--ink);border-bottom:2px solid var(--accent)}.source .fault{background:var(--second-soft);border-color:var(--second)}.diagram{display:block;width:100%;height:auto;max-height:320px;margin:14px 0;overflow:visible}.diagram text{fill:var(--ink);font:12px var(--viz-font-ui)}.diagram .edge{stroke:var(--muted);stroke-width:1.5;fill:none}.diagram .edge.on{stroke:var(--accent);stroke-width:3}.diagram .node{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.diagram .node.on{fill:var(--accent-soft);stroke:var(--accent)}.diagram .node.gold{fill:var(--second-soft);stroke:var(--second)}.log{font:12px/1.8 var(--viz-font-mono);white-space:pre-line;overflow-wrap:anywhere;min-height:7.2em}.table{display:grid;gap:5px;margin:14px 0}.table .tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px}.table .tr>*{padding:8px 5px;background:var(--surface);border-radius:4px;min-width:0;overflow-wrap:anywhere;font-size:12px}.table .tr .on{background:var(--accent-soft)}.table .tr .gold{background:var(--second-soft)}.choices button{min-height:44px}.metrics strong{min-height:1.6em}.code-line{display:block}.code-line.on{background:var(--accent-soft);border-left:2px solid var(--accent);padding-left:6px}.status-badge{font-size:12px;color:var(--accent)}.tile-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.tile-grid .cell{min-height:40px}.actions button{min-height:48px}.form-field{display:grid;gap:8px;margin:14px 0;font-size:13px}.form-field input{width:100%;font-family:var(--viz-font-ui)}.metrics.three{grid-template-columns:repeat(3,minmax(0,1fr))}.formula{min-height:3.2em}.presets{flex-wrap:wrap}.presets button{flex-basis:25%;min-height:44px}\n\n.budget{display:flex;height:28px;margin:16px 0;background:var(--surface);border-radius:5px;overflow:hidden}.budget i{display:block;background:var(--accent);transition:width .2s}.budget i.gold{background:var(--second)}.intervals{margin:16px 0}.interval{position:relative;height:36px;background:var(--surface);margin:6px 0;border-radius:4px;overflow:hidden}.interval i{position:absolute;height:100%;background:var(--accent-soft);border-left:2px solid var(--accent)}.interval i.gold{background:var(--second-soft);border-color:var(--second)}.interval span{position:relative;z-index:1;font:12px/36px var(--viz-font-ui);padding-left:7px}.table .tr>*{min-height:4.8em}.formula{white-space:pre-line;min-height:7.2em}.actions:has(>button:only-child){grid-template-columns:1fr}.metrics strong{min-height:3.2em}.rangegrid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:3px;margin:14px 0}.rangegrid .cell{min-height:30px;padding:3px 1px;font-size:10px}.message{min-height:7.2em;white-space:pre-line;font:13px/1.8 var(--viz-font-ui);overflow-wrap:anywhere}\n/* Allow CJK hanging punctuation without overflowing a metric's border box. */\n.metrics>div{padding-right:4px}.metrics span{line-break:anywhere}\n\n#sets .tr>*{min-height:3.6em}","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).classList.add('table');$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function band(id,parts,total){$('#'+id).replaceChildren(...parts.map((p,i)=>{const e=document.createElement('i');e.style.width=(100*p.value/total)+'%';e.className=i%2?'gold':'on';e.title=p.name+': '+p.value;return e}));}function intervals(id,items,total){$('#'+id).replaceChildren(...items.map(p=>{const row=document.createElement('div');row.className='interval';const bar=document.createElement('i');bar.style.left=(100*p.start/total)+'%';bar.style.width=(100*(p.end-p.start)/total)+'%';bar.className=p.cls||'';const label=document.createElement('span');label.textContent=p.label;row.append(bar,label);return row;}));}const flags=[2,194,16];let saved=[];function draw(){const shown=saved.filter(i=>$('#display').value==='all'||flags[i]&2);table('sets',[['flags','saved','displayed'],...flags.map((n,i)=>['0x'+n.toString(16).padStart(2,'0'),saved.includes(i)?'✓':'∅',shown.includes(i)?'✓':'∅'])]);set('saved',saved.length);set('shown',shown.length);$('#sets').dataset.snapshot=JSON.stringify({saved,shown});}$('#record').onclick=()=>{const mode=$('#capture').value;saved=[0,1,2].filter(i=>mode==='all'||(mode==='exact'?flags[i]===2:(flags[i]&18)===2));draw()};$('#display').onchange=draw;$('#reset').onclick=()=>{saved=[];draw()};draw();","audio":false,"strings":{"capture":"Collection condition","display":"Display condition","heading":"Can changing the display filter recover packets that weren't captured?","intro":"Select collection conditions and save once, then change display conditions. The two sets are kept separate.","record":"Capture according to current condition","reset":"Reset","saved":"Saved packet count","scope":"Three fixed Ethernet/IPv4/TCP packets, flags02/c2/10, all involving 443. The model calculates filtering bitwise, without actual packet capture; full pcap and tcpdump offline verification are retained in the main text.","scopeLabel":"Model scope and conventions","sets":"Candidates, saved, displayed","shown":"Displayed packet count"}}
Collect controllably, then analyze offline
The following are commands adjusted for the environment during actual troubleshooting. NIC names and target addresses need to be replaced; file locations must be writable; capturing interfaces usually require corresponding permissions, while reading saved files generally does not.
# Process at most 5000 matching packets; -c limits packet count, not wait time.tcpdump -i eth0 -nn -s 0 -B 4096 -c 5000 \
-w capture.pcap 'host 192.0.2.10 and port 443'# Rotate saving 5 files by size, -C 100 base unit is decimal megabytes.tcpdump -i eth0 -nn -s 0 -C 100 -W 5 \
-w trace.pcap 'host 192.0.2.10'# Read-only, do not start capturing.tcpdump -nn -tttt -r capture.pcap
-s 0 uses the tool-defined maximum/default snaplen, not mathematically infinite length; check the captured length and original length inside the file to know if a packet was truncated. -B unit is KiB. -C rotation may slightly exceed the threshold and cannot be treated as an exact disk limit; combined with -W, it will loop and overwrite old files. Time-based -G and counting options have different interactions; do not directly copy size rotation logic.
At the end, record captured, received by filter, and dropped by kernel. The latter two depend on the operating system; dropped by kernel indicates buffer drops by the capture mechanism, not equal to the actual business network packet loss count. Even if it shows 0, it does not guarantee that the mirror port, driver, or other locations did not miss captures.
A rough storage budget: average 20,000 packets per second, average retained 800 B, classic pcap has an additional 16 B header per record, 60 seconds is approximately 20,000 × 816 × 60 = 979,200,000 B, which is 979.2 MB. This estimate does not account for filesystem overhead and is not applicable for directly calculating all block structures in pcapng.
Locate the stream first, then look at reassembly and direction
# TCP conversation summary; -q reduces per-packet output.tshark -r capture.pcap -q -z conv,tcp# Select stream 3 from the same capture file and export key fields.tshark -r capture.pcap -Y'tcp.stream == 3' -T fields \
-e frame.number -e frame.time_relative -e ip.src -e tcp.srcport \
-e tcp.seq -e tcp.ack -e tcp.len -e tcp.window_size# Find candidate anomalies, then return to the full stream context.tshark -r capture.pcap \
-Y'tcp.analysis.retransmission || tcp.analysis.zero_window'
IPv6 analysis should simultaneously select fields like ipv6.src. Without a handshake, negotiation information like window scaling may be unknown; blank fields may also be because the packet does not contain that layer, rather than the value being 0. TShark manual
ip.addr == A matches the address in either direction. To exclude all packets involving A, use !(ip.addr == A) to explicitly express it, avoiding intuitive derivation of inequality semantics on multi-value fields. Display filters do not re-add bytes dropped during collection. Display filters
HTTP headers may span TCP segments, and after compression or encryption, they may not be directly searchable text. tcpdump -A | grep Host: can only find visible fragments in some single packets, not a reliable HTTP request parser. Use protocol reassembly and Follow Stream, and explicitly capture whether it starts from the connection beginning.
"Retransmission" hints are analysis based on visible packets
Hint or phenomenon
Interpret first as
Continue to verify
Previous segment not captured
Gap before current visible sequence number
Did capture start midway, miss packets, or filter too narrowly?
Retransmission / Out-of-order
Visible sequence number has duplicate or out-of-order relationship with existing stream state
Bidirectional ACK, timing, repeated capture, and analysis settings
ZeroWindow
This packet sender advertises zero receive window
Application read and receive buffer status on this end
Bad checksum
Current sampled byte calculation mismatch or insufficient verification conditions
Host-side send offloading, truncation, and capture location
"Packet" larger than usual MTU
Host observed a larger processing unit
Is TSO/GSO/GRO/LRO involved?
Wireshark's TCP analysis depends on the order and visible history of captured packets; its classifications can be ambiguous, and not every hint should be treated as a fact directly reported by the peer TCP implementation. TCP Analysis
Sender-side capture may occur before the NIC adds checksums or segments; receiver-side may also observe aggregated data. In this case, erroneous checksums or "large packets" do not necessarily appear on the wire. To confirm the true online form, compare receiver-side or external observation points; turning off offloading changes performance and behavior and should not be the default first step after seeing hints. Wireshark Offloading
TLS decryption requires correct session secrets, not just filling in a variable name
SSLKEYLOGFILE is a key logging interface supported by some clients and TLS libraries, not a universal switch that forces the OS to output secrets for all programs. The program must actually support it, read the configuration at startup, and produce logs matching the captured session.
Specify the log file in Wireshark's TLS protocol settings, or use offline:
The decrypted protocol is not necessarily HTTP/1; HTTP/2 etc. require corresponding filters. Having only the server certificate private key cannot decrypt ECDHE sessions with forward secure exchange or typical TLS 1.3 sessions; historical RSA key exchange private key decryption has strict applicability conditions. Missing handshakes, records, or logs will also hinder reassembly and decryption. Wireshark TLS
Key logs combined with corresponding captures will expose the session content; manage access and retention scope according to the contained session data. Visible content after decryption still depends on whether the application has independent end-to-end encryption.
Offline verification of filter semantics: two SYNs and one ACK
Below generates a temporary Ethernet/IPv4/TCP pcap, reads and filters it with the installed tcpdump, without connecting to an interface or sending packets. The three packets are SYN, SYN+ECE+CWR, ACK; exact match to SYN will only match one, while the mask condition should match two.
importipaddressimportstructimportsubprocessimporttempfilefrompathlibimportPathdefchecksum(data):iflen(data)%2:data+=b'\0'total=sum(struct.unpack('>'+'H'*(len(data)//2),data))whiletotal>>16:total=(total&0xffff)+(total>>16)return(~total)&0xffffsrc=ipaddress.ip_address('192.0.2.1').packeddst=ipaddress.ip_address('192.0.2.10').packedpackets=[]forflagsin[0x02,0xc2,0x10]:tcp=struct.pack('>HHIIBBHHH',40000,443,1000,0,0x50,flags,65535,0,0)pseudo=src+dst+struct.pack('>BBH',0,6,len(tcp))tcp=tcp[:16]+struct.pack('>H',checksum(pseudo+tcp))+tcp[18:]ip=struct.pack('>BBHHHBBH4s4s',0x45,0,40,1,0,64,6,0,src,dst)ip=ip[:10]+struct.pack('>H',checksum(ip))+ip[12:]ethernet=bytes.fromhex('0200000000020200000000010800')packets.append(ethernet+ip+tcp)withtempfile.TemporaryDirectory()asfolder:path=Path(folder)/'flags.pcap'output=struct.pack('<IHHIIII',0xa1b2c3d4,2,4,0,0,65535,1)fori,packetinenumerate(packets):output+=struct.pack('<IIII',1700000000+i,0,len(packet),len(packet))output+=packetpath.write_bytes(output)filters=[('ip and tcp[tcpflags] == tcp-syn',1),('ip and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn',2),('tcp port 443',3),]forexpression,expectedinfilters:result=subprocess.run(['tcpdump','-nn','-r',str(path),expression],text=True,capture_output=True,check=True)assertlen(result.stdout.strip().splitlines())==expectedprint('Offline pcap: strict SYN 1, mask SYN 2, 443 total 3')
This verifies the match between capture expressions and packet encoding, not performance testing, and does not simulate a complete TCP session. Real troubleshooting should record the original file, capture command, tool version, capture count, and key frame numbers together, so conclusions can be audited.