パケットキャプチャは、特定の観測点および特定の期間中に収集されたパケットを保存したものです。tcpdump は条件に基づく収集やオフライン検査に適しており、Wireshark/TShark はプロトコルフィールドの再構成や時系列分析に適しています。信頼できる結論は、「収集範囲」「プロトコルの事実」「推論の境界」の三者が一致することから導き出されるものであり、単に某行が赤色で強調されているからではありません。
最初に答えるべき質問 収集への影響
どの接続が失敗したか クライアント、プロキシのエントリポイント、プロキシの出口では、異なる収集ポイントが必要になる場合があります
TCP か UDP か TCP 443 だけをキャプチャすると、QUIC を見逃す可能性があります
DNS が関与するか 宛先 IP のみでフィルタリングすると、その前の名前解決の失敗が見えない場合があります
ハンドシェイクかコンテンツか 収集をいつ開始するか、完全な snaplen と復号化素材が必要かどうかを決定します
完全に保存できるか フィルタリングの範囲、バッファリング、ファイルのローテーション、停止条件を決定します
観測位置が証明できる内容を決定する
同じアクセスでも、異なる観測点では異なる接続とパケットの形態が見える
クライアント
アプリケーション / ソケット
プロキシまたは NAT
接続の終了またはアドレスの書き換え
バックエンドサービス
別の接続セグメント
ホストでのキャプチャは、オフロード前に行われる可能性があります
プロキシ後の5タプルは変化する可能性があります
インターフェース、ネームスペース、方向、時間基準を最初に記録する
パケットが見えないのは、この場所で収集されなかったことを示すだけです。経路の違い、フィルタリング、切り捨て、キャプチャのドロップを除外する必要があります。
Linux ホスト、コンテナネットワークのネームスペース、veth、ブリッジ、物理 NIC、ループバックは、それぞれ異なる視点を提供します。-i any は、現在のネームスペースでキャプチャ可能なインターフェースをカバーしますが、すべてのコンテナに自動的に進入するわけではありません。Linux の any は通常、cooked capture リンクタイプを使用するため、すべてのパケットが標準のイーサネットヘッダーから解析されるとは限りません。
NAT を通過するとアドレスとポートが変更される可能性があります。リバースプロキシを通過すると、通常は別の TCP 接続となっており、同じ tcp.stream や5タプルを使用してバックエンドを見つけることはできません。ファイル間の関連付けには、時間、リクエスト ID、ペイロードの特徴、およびプロキシログを組み合わせる必要があります。各ファイルのストリーム番号は、今回の分析結果におけるインデックスに過ぎません。
両端で同時にキャプチャすると、欠落が発生した位置を絞り込むことができますが、時計が同期されていない場合、タイムスタンプを単純に減算すると、誤った片方向レイテンシが生じます。マイクロ秒またはナノ秒単位の精度のタイムスタンプでも、同等の測定精度が保証されるわけではありません。
キャプチャフィルタと表示フィルタはそれぞれどこで有効になるか
属性 キャプチャフィルタ 表示フィルタ
一般的な使用箇所 tcpdump 式、TShark -f Wireshark のフィルターバー、TShark -Y
作用対象 収集前のフィルタリング、またはオフライン読み取り時のフィルタリング 解析済みの既存パケットのフィールド
例 tcp port 443tcp.port == 443
非マッチデータ リアルタイム収集時は通常、キャプチャファイルに書き込まれない 元のファイルは保持され、条件を変更して再分析可能
能力の限界 リンクタイプ、オフセット、コンパイラのサポートに依存 ディセクター、再構成、可視な平文に依存
リアルタイム収集では、libpcap はサポートされているプラットフォームでフィルタプログラムをカーネルに渡し、ユーザーモードに渡されるパケットを減らすことができます。オフラインファイルを読み取る際にも同じ式を使用できますが、「すべての BPF フィルタリングが常にカーネルで発生する」わけではありません。トラフィック、マッチング比率、デコードオーバーヘッドが与えられていない場合、固定された桁数で高速であるとは主張できません。tcpdump マニュアルソース
一般的なキャプチャ条件
tcpdump - nn - r capture.pcap ' host 192.0.2.10 and port 443'
tcpdump - nn - r capture.pcap ' ip and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn'
tcpdump - nn - r capture.pcap ' (host 192.0.2.10 or host 192.0.2.20) and tcp port 443'
tcp[tcpflags] == tcp-syn はフラグバイトの厳密な一致であり、他の協働フラグも同時に含んでいる SYN を除外する可能性があります。ビットマスクを使用することで、「SYN があり、ACK がない」を正確に表現できます。生トランスポートヘッダーのオフセット式は、IPv6 拡張ヘッダーなどのシナリオで追加の制限があるため、ここでは明示的に IPv4 を限定しており、全プロトコル共通の接続統計として扱うことはできません。
ポート条件はアプリケーションの識別には等しくありません。443 は異なるプロトコルを運ぶことができ、DNS 暗号化トラフィックがすべて 53 番ポートにあるわけではありません。最初のフラグメント以外の IP フラグメントには、生トランスポート層ポートがないため、狭すぎるポートフィルタリングは再構成の欠片を引き起こす可能性があります。VLAN およびトンネルカプセル化も、オフセットとマッチング範囲に影響を与えます。pcap-filter 構文ソース
表示フィルタを変更しても、キャプチャしなかったパケットは戻ってきますか?
厳密な等値で収集し、その後すべてを表示しても、1つのパケットしか見えません。マスクを使用して再収集すると、2種類の SYN が保存されます。キャプチャドロップダウンボックス自体を変更しても、すでに保存されたファイルは書き換えられないため、新しい収集を明示的に実行する必要があります。
図を準備しています 再読み込み
表示フィルタを変更しても、キャプチャしなかったパケットは戻ってきますか? 表示フィルタは、すでに保存された集合内でのみフィルタリングできます。厳密な SYN 等値は、ECE/CWR も同時にセットしている SYN を見逃すため、事後にすべてを表示しても補完できません。
{"id":"capture-filter-evidence","title":"表示フィルタを変更しても、キャプチャしなかったパケットは戻ってきますか?","summary":"表示フィルタは、すでに保存された集合内でのみフィルタリングできます。厳密な SYN 等値は、ECE/CWR も同時にセットしている SYN を見逃すため、事後にすべてを表示しても補完できません。","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":"収集条件","display":"表示条件","heading":"表示フィルタを変更しても、キャプチャしなかったパケットは戻ってきますか?","intro":"まず収集条件を選択して保存し、その後表示条件を変更します。2つの集合は分離して保持されます。","record":"現在の条件で収集","reset":"リセット","saved":"保存されたパケット数","scope":"3つの固定された Ethernet/IPv4/TCP パケット、flags02/c2/10、すべて 443 に関連。モデルはビット演算でフィルタリングを計算し、キャプチャは実行しません。完全な pcap と tcpdump のオフライン検証は本文に保持されます。","scopeLabel":"モデルの範囲と規約","sets":"候補、保存済み、表示済み","shown":"表示されたパケット数"}}
制御された収集を行い、その後オフラインで分析する
以下は、実際のトラブルシューティング時に環境に応じて調整するコマンドです。NIC 名と宛先アドレスは置き換えてください。ファイルの場所は書き込み可能であることを確認してください。キャプチャインターフェースには通常、適切な権限が必要です。保存されたファイルの読み取りには通常、権限は必要ありません。
tcpdump - i eth0 - nn - s 0 - B 4096 - c 5000 \
- w capture.pcap ' host 192.0.2.10 and port 443'
tcpdump - i eth0 - nn - s 0 - C 100 - W 5 \
- w trace.pcap ' host 192.0.2.10'
tcpdump - nn - tttt - r capture.pcap
-s 0 は、ツールが定義する最大/デフォルトの snaplen を使用しますが、数学的な無限長ではありません。ファイル内の captured length と original length を確認して、パケットが切り捨てられているかどうかを判断する必要があります。-B の単位は KiB です。-C のローテーションは閾値を少し超える可能性があるため、正確なディスク上限として扱うことはできません。-W と組み合わさると、古いファイルを循環して上書きします。時間ベースの -G とカウントオプションは異なる相互作用を持つため、容量ベースのローテーションロジックをそのままコピーしてはいけません。
終了時に、captured(キャプチャ数)、received by filter(フィルタ通過数)、dropped by kernel(カーネルドロップ数)を記録します。後2つの口径はオペレーティングシステムに依存します。dropped by kernel は、キャプチャメカニズムのバッファドロップを示し、ビジネスネットワークの実際のドロップ数とは異なります。0 と表示されていても、ミラーポート、ドライバ、または他の場所でキャプチャが漏れていないことを保証するものではありません。
大まかなストレージ予算:平均して秒間 20,000 パケット、平均 800 B を保持する場合、古典的な pcap ではレコードごとに 16 B のヘッダーがあり、60秒で約 20,000 × 816 × 60 = 979,200,000 B、つまり 979.2 MB となります。この見積もりにはファイルシステムオーバーヘッドは含まれておらず、pcapng のすべてのブロック構造に直接適用できるものではありません。
まずストリームを特定し、その後再構成と方向を見る
tshark - r capture.pcap - q - z conv,tcp
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
tshark - r capture.pcap \
- Y ' tcp.analysis.retransmission || tcp.analysis.zero_window'
IPv6 分析では、ipv6.src などのフィールドも同時に選択する必要があります。ハンドシェイクがない場合、ウィンドウスケーリングなどのネゴシエーション情報は不明である可能性があります。フィールドが空白なのは、そのパケットにそのレイヤーが含まれていないためであり、数値が 0 であるためではありません。TShark マニュアル
ip.addr == A は、どちらの方向のアドレスにも一致します。A に関連するすべてのパケットを除外したい場合は、!(ip.addr == A) を明示的に使用し、多値フィールドで直感的に不等演算のセマンティクスを推測しないようにしてください。表示フィルタは、収集時に失われたバイトを再構築しません。表示フィルタ
HTTP ヘッダーは TCP セグメントにまたがる可能性があり、圧縮または暗号化された後でも、検索可能なテキストになるとは限りません。tcpdump -A | grep Host: は、特定のパケット内の可視な断片しか見つからないため、信頼できる HTTP リクエストパーサーではありません。プロトコル再構成とストリームの追跡を使用し、収集が接続の開始から行われたかどうかを明確にしてください。
「再送」のヒントは、可視なパケットに基づく分析である
シーケンス番号のギャップ:パスのドロップとキャプチャの欠落をまず区別する
送信側
キャプチャポイント
受信側
seq=1001、len=1000
seq=2001、len=1000(この地点ではキャプチャされなかった)
ACK=3001
受信側は 3001 まで確認した。中間のキャプチャギャップだけで、送信漏れと断定することはできない
これは教育用の仮定です。実際の判断には、完全な双方向ストリーム、重複キャプチャ、シーケンス番号のラップアラウンド、および分析設定の確認が必要です。
ヒントまたは現象 まず何と解釈するか 継続的な確認
Previous segment not captured 現在可視のシーケンス番号の前にギャップがある キャプチャの中途開始、キャプチャ漏れ、またはフィルタリングが狭すぎた
Retransmission / Out-of-order 可視のシーケンス番号と既存のストリーム状態の間に重複または順序入れ替えの関係がある 双方向 ACK、タイムスタンプ、重複キャプチャ、および分析設定
ZeroWindow このパケットの送信者が受信ウィンドウをゼロとして通知している この側のアプリケーションの読み取りと受信バッファの状態
Bad checksum 現在のサンプリングバイトの計算結果が一致しない、または検証条件が不十分 送信側のオフロード、切り捨て、およびキャプチャ位置
通常の MTU より大きい「パケット」 ホストがより大きな処理単位を観測した TSO/GSO/GRO/LRO が関与しているかどうか
Wireshark の TCP 分析は、キャプチャパケットの順序と可視な履歴に依存しており、その分類には曖昧さがある可能性があります。各ヒントを、相手側の TCP 実装が直接報告した事実として扱うことはできません。TCP 分析
送信側でのキャプチャは、NIC によるチェックサム補完やセグメンテーションの前で行われる可能性があります。受信側では、集約されたデータを観測する場合があります。この場合、誤ったチェックサムや「大きなパケット」が必ずしも回線上に現れるわけではありません。実際の回線上の形態を確認するには、受信側または外部の観測点と比較する必要があります。オフロードを無効にするとパフォーマンスと動作が変化するため、ヒントを見つけた後のデフォルトの最初のステップとして行うべきではありません。Wireshark オフロード
TLS 復号化には、正しいセッションシークレットが必要であり、変数名を1つ記入するだけでは不十分です
SSLKEYLOGFILE は、一部のクライアントおよび TLS ライブラリがサポートするキーログインターフェースであり、オペレーティングシステムがすべてのプログラムに秘密の出力を強制する汎用スイッチではありません。プログラムは実際にサポートしており、起動時に設定を読み取り、キャプチャセッションと一致するログを生成する必要があります。
Wireshark の TLS プロトコル設定でログファイルを指定するか、オフラインで使用します:
tshark - r capture.pcap - o tls.keylog_file:session.keys - Y http
復号化されたプロトコルが必ずしも HTTP/1 であるとは限りません。HTTP/2 などは、対応するフィルタが必要です。サーバー証明書プライベートキーのみでは、前方秘匿性を持つ ECDHE セッションや通常の TLS 1.3 セッションを復号できません。歴史的な RSA キー交換のプライベートキーによる復号には、厳格な適用条件があります。ハンドシェイク、レコード、またはログの欠如も、再構成と復号化を妨げます。Wireshark TLS
キーログと対応するキャプチャを組み合わせると、そのセッションの内容が露出するため、含まれるセッションデータに応じてアクセスと保持範囲を管理する必要があります。復号化された可視内容は、アプリケーションが独自のエンドツーエンド暗号化を持っているかどうかにも依存します。
フィルタセマンティクスのオフライン検証:SYN が2つと ACK が1つ
以下は、インストール済みの tcpdump を使用して、一時的な Ethernet/IPv4/TCP pcap を生成し、読み取りおよびフィルタリングするものです。インターフェースに接続せず、パケットを送信しません。3つのパケットは、SYN、SYN+ECE+CWR、ACK です。SYN と厳密に一致するのは1つのみですが、マスク条件は2つに一致する必要があります。
import ipaddress
import struct
import subprocess
import tempfile
from pathlib import Path
def checksum ( data ) :
if len ( data ) % 2 : data += b ' \0 '
total = sum ( struct . unpack ( ' >' + ' H' * ( len ( data ) / / 2 ) , data ) )
while total > > 16 : total = ( total & 0x ffff) + ( total > > 16 )
return ( ~ total ) & 0x ffff
src = ipaddress . ip_address ( ' 192.0.2.1' ) . packed
dst = ipaddress . ip_address ( ' 192.0.2.10' ) . packed
packets = [ ]
for flags in [ 0x 02, 0x c2, 0x 10] :
tcp = struct . pack ( ' >HHIIBBHHH' , 40000 , 443 , 1000 , 0 , 0x 50, 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' , 0x 45, 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 )
with tempfile . TemporaryDirectory ( ) as folder :
path = Path ( folder ) / ' flags.pcap'
output = struct . pack ( ' <IHHIIII' , 0x a1b2c3d4, 2 , 4 , 0 , 0 , 65535 , 1 )
for i , packet in enumerate ( packets ) :
output += struct . pack ( ' <IIII' , 1700000000 + i , 0 , len ( packet ) , len ( packet ) )
output += packet
filters = [
( ' ip and tcp[tcpflags] == tcp-syn' , 1 ) ,
( ' ip and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn' , 2 ) ,
( ' tcp port 443' , 3 ) ,
]
for expression , expected in filters :
result = subprocess . run ( [ ' tcpdump' , ' -nn' , ' -r' , str ( path ) , expression ] ,
text = True , capture_output = True , check = True )
assert len ( result . stdout . strip ( ) . splitlines ( ) ) == expected
print ( ' オフライン pcap:厳密な SYN 1個、マスク SYN 2個、443 合計 3個' )
これは、キャプチャ式とパケットエンコーディングのマッチングを検証するものであり、パフォーマンステストではなく、完全な TCP セッションをシミュレートしたものではありません。実際のトラブルシューティングでは、元のファイル、収集コマンド、ツールバージョン、収集カウント、および重要なフレーム番号を一緒に記録し、結論を検証可能にする必要があります。