feat: skip XSK redirect for non-TCP/UDP and malformed packets and add Zeek-style server port heuristic for flow direction (#17)

This commit is contained in:
ParrotXray 2026-05-28 18:52:00 +08:00 committed by GitHub
parent 22d0384c69
commit 890406a4da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 135 additions and 8 deletions

View File

@ -24,21 +24,25 @@ static INGRESS_XSKS_MAP: XskMap = XskMap::pinned(64, 0);
#[xdp]
pub fn mantis(ctx: XdpContext) -> u32 {
unsafe {
let _ = packet_intake(&ctx);
let _ = PROGRAM_ARRAY.tail_call(&ctx, TRANSMISSION);
xdp_action::XDP_PASS
match packet_intake(&ctx) {
Err(_) => xdp_action::XDP_PASS,
Ok(_) => {
let _ = PROGRAM_ARRAY.tail_call(&ctx, TRANSMISSION);
xdp_action::XDP_PASS
}
}
}
}
#[inline(always)]
unsafe fn packet_intake(ctx: &XdpContext) -> Result<u32, ()> {
unsafe fn packet_intake(ctx: &XdpContext) -> Result<(), ()> {
unsafe {
let start = ctx.data();
let end = ctx.data_end();
let ptr = PARSED_PACKET.get_ptr_mut(0).ok_or(())?;
parsing::parse_packet(start, end, ptr)?;
let _ = PROGRAM_ARRAY.tail_call(ctx, ACCESS_CONTROL);
Err(())
Ok(())
}
}
@ -124,4 +128,4 @@ pub fn transmission(ctx: XdpContext) -> u32 {
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe { core::hint::unreachable_unchecked() }
}
}

View File

@ -6,6 +6,8 @@ use common::model::event::Event;
use crate::model::direction::Direction;
use crate::model::ml_detection::{BulkState, FlowKey, PacketData};
use super::server_ports;
#[derive(Debug, Clone)]
pub struct FlowData {
pub flow_key: FlowKey,
@ -280,7 +282,13 @@ impl FlowTracker {
match detect_initiator(payload, packet_key.protocol, packet_key.src_port, packet_key.dst_port) {
Some(true) => (packet_key, true),
Some(false) => (reversed_key, false),
None => (packet_key, true),
None => {
if server_ports::is_server_port(packet_key.src_port, packet_key.protocol) {
(reversed_key, false)
} else {
(packet_key, true)
}
}
}
}
};
@ -366,4 +374,4 @@ fn detect_initiator(payload: &[u8], protocol: u8, src_port: u16, dst_port: u16)
}
None
}
}

View File

@ -6,3 +6,4 @@ pub mod flow_tracker;
pub mod inference;
pub mod model_loader;
pub mod traffic_logger;
pub mod server_ports;

View File

@ -0,0 +1,114 @@
// Well-known server-side ports derived from Zeek's likely_server_ports set,
// IANA well-known port assignments, and common production services.
//
// If a packet's src_port is in this list, the packet originated from the server
// (responder), so the flow key should be flipped to put the client as initiator.
//
// Source: Zeek protocol analyzers + IANA well-known ports (0-1023) + common practice.
// Arrays must remain sorted for binary_search to work correctly.
const TCP: &[u16] = &[
20, // FTP data
21, // FTP control
22, // SSH
23, // Telnet
25, // SMTP
53, // DNS
80, // HTTP
81, // HTTP alt
88, // Kerberos
110, // POP3
119, // NNTP
135, // MS RPC
139, // NetBIOS / SMB
143, // IMAP
179, // BGP
389, // LDAP
443, // HTTPS
445, // SMB/CIFS
465, // SMTPS
502, // Modbus
514, // Syslog
563, // NNTPS
585, // IMAP4+SSL (legacy)
587, // SMTP submission
614, // SSLshell
631, // IPP (CUPS)
636, // LDAPS
989, // FTPS data
990, // FTPS control
992, // Telnet/SSL
993, // IMAPS
995, // POP3S
1080, // SOCKS
1194, // OpenVPN
1433, // Microsoft SQL Server
1434, // MSSQL monitor
1521, // Oracle DB
1883, // MQTT
2049, // NFS
2811, // FTP alt
3128, // HTTP proxy
3268, // LDAP Global Catalog
3306, // MySQL / MariaDB
3389, // RDP
3690, // SVN
5222, // XMPP client
5223, // XMPP/Apple Push over SSL
5269, // XMPP server
5432, // PostgreSQL
5900, // VNC
6379, // Redis
6443, // Kubernetes API
6666, // IRC
6667, // IRC
6668, // IRC
6669, // IRC
7001, // Oracle WebLogic
8000, // HTTP dev/alt
8080, // HTTP alt
8443, // HTTPS alt
8883, // MQTT over TLS
8888, // HTTP alt
9092, // Kafka broker
9200, // Elasticsearch HTTP
9300, // Elasticsearch cluster
20000, // DNP3
27017, // MongoDB
27018, // MongoDB shard
];
const UDP: &[u16] = &[
53, // DNS
67, // DHCP server
69, // TFTP
88, // Kerberos
123, // NTP
137, // NetBIOS Name Service
161, // SNMP
162, // SNMP traps
389, // LDAP
443, // QUIC / HTTP3
500, // IKE / IPsec
514, // Syslog
520, // RIP
1194, // OpenVPN
1812, // RADIUS authentication
1813, // RADIUS accounting
3389, // RDP over UDP
4011, // PXE / ProxyDHCP
4500, // IPsec NAT-T
5060, // SIP
5353, // mDNS
5355, // LLMNR
20000, // DNP3
51820, // WireGuard
];
pub fn is_server_port(port: u16, protocol: u8) -> bool {
match protocol {
6 => TCP.binary_search(&port).is_ok(),
17 => UDP.binary_search(&port).is_ok(),
_ => false,
}
}