try new correlation af packet bridge mode
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 11s

This commit is contained in:
2026-04-12 18:27:41 +02:00
parent 4521b9d99e
commit 9c6eaaa7b2
8 changed files with 214 additions and 11 deletions

View File

@@ -149,6 +149,7 @@ function buildReducedMetadata(packet: PacketRow | null) {
dpi_metadata: dpi,
capture_metadata: packet.capture_metadata ?? null,
telemetry_metadata: packet.telemetry_metadata ?? null,
capture_observations: packet.capture_observations ?? null,
};
}
@@ -499,6 +500,7 @@ export default function PacketInspectModal({
const reducedMetadata = useMemo(() => buildReducedMetadata(packet), [packet]);
const fullPacketJson = useMemo(() => formatJson(packet), [packet]);
const decodedPayload = useMemo(() => getDecodedPayload(packet), [packet]);
const captureObservationCount = Array.isArray(packet?.capture_observations) ? packet.capture_observations.length : 0;
const downloadRaw = () => {
if (!packet?.raw_b64) return;
@@ -548,11 +550,20 @@ export default function PacketInspectModal({
<Descriptions.Item label="Application">{packet?.app_protocol ?? packet?.app_master_protocol ?? '-'}</Descriptions.Item>
<Descriptions.Item label="Host">{packet?.app_hostname ?? '-'}</Descriptions.Item>
<Descriptions.Item label="Verdict">{packet?.verdict ?? '-'}</Descriptions.Item>
<Descriptions.Item label="Observations">{captureObservationCount || '-'}</Descriptions.Item>
<Descriptions.Item label="Source">{packet?.src_ip ? `${packet.src_ip}${packet?.src_port ? `:${packet.src_port}` : ''}` : '-'}</Descriptions.Item>
<Descriptions.Item label="Destination">{packet?.dst_ip ? `${packet.dst_ip}${packet?.dst_port ? `:${packet.dst_port}` : ''}` : '-'}</Descriptions.Item>
<Descriptions.Item label="Path">{[packet?.ingress_if, packet?.egress_if].filter(Boolean).join(' -> ') || '-'}</Descriptions.Item>
<Descriptions.Item label="Capture Sources">{packet?.capture_sources?.join(', ') || '-'}</Descriptions.Item>
</Descriptions>
{captureObservationCount > 0 ? (
<div>
<Text strong>Capture observations</Text>
<pre style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word', fontSize: 12, marginTop: 8 }}>
{formatJson(packet?.capture_observations)}
</pre>
</div>
) : null}
<div>
<Text strong>Reduced metadata</Text>
<pre style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word', fontSize: 12, marginTop: 8 }}>{formatJson(reducedMetadata)}</pre>

View File

@@ -296,6 +296,23 @@ function getStringList(value: unknown): string[] {
.filter(Boolean);
}
function getObservationIfaces(packet: PacketRow): string[] {
const observations = Array.isArray(packet.capture_observations) ? packet.capture_observations : [];
const seen = new Set<string>();
for (const observation of observations) {
const iface = observation?.iface;
if (iface) seen.add(String(iface));
}
return Array.from(seen);
}
function getObservationSummary(packet: PacketRow) {
const observations = Array.isArray(packet.capture_observations) ? packet.capture_observations : [];
const captureCount = observations.filter((observation) => observation?.observation_type === 'capture').length;
const telemetryCount = observations.filter((observation) => observation?.observation_type === 'telemetry').length;
return { total: observations.length, captureCount, telemetryCount };
}
function isLikelyText(bytes: Uint8Array) {
if (bytes.length === 0) return false;
let printable = 0;
@@ -1181,9 +1198,9 @@ export default function PacketViewer(): ReactElement {
render: (val: any) => <Text>{formatTimestamp(val)}</Text>,
},
{
title: 'Path',
title: 'Path / Seen On',
key: 'path',
width: 150,
width: 190,
render: (_: any, rec: PacketRow) => (
<Space wrap size={[6, 6]}>
{[rec.ingress_if, rec.egress_if].filter(Boolean).length > 0 ? (
@@ -1204,7 +1221,24 @@ export default function PacketViewer(): ReactElement {
)}
</>
) : (
<Text type="secondary">-</Text>
(() => {
const observationIfaces = getObservationIfaces(rec);
const summary = getObservationSummary(rec);
return observationIfaces.length > 0 ? (
<>
{observationIfaces.map((iface) => (
<Tooltip key={iface} title={`observed on ${iface}`}>
<Tag style={{ ...colorForName(iface), borderRadius: 6 }}>{iface}</Tag>
</Tooltip>
))}
<Tooltip title={`${summary.captureCount} capture observation(s), ${summary.telemetryCount} telemetry observation(s)`}>
<Tag color="default">{summary.total} obs</Tag>
</Tooltip>
</>
) : (
<Text type="secondary">-</Text>
);
})()
)}
</Space>
),