Networking Design & TCP Reassembly: Aegis Packet Engine
1. Zero-Copy Protocol Parsing
Aegis decodes network protocol headers sequentially by reading directly from the raw memory buffer. The parser does not copy fields; instead, it casts memory segments to struct pointers or references.
Raw Packet Buffer:
[ Ethernet Header (14B) ][ IPv4 Header (20B) ][ TCP Header (20B) ][ Payload (Variable) ]
^ ^ ^ ^
| | | |
+-- eth_offset +-- ip_offset +-- tcp_offset +-- payload_offset
Parser Casts:
- Ethernet:
const EthernetHeader* eth = reinterpret_cast<const EthernetHeader*>(data); - IPv4:
const IPv4Header* ip = reinterpret_cast<const IPv4Header*>(data + eth_offset); - TCP:
const TCPHeader* tcp = reinterpret_cast<const TCPHeader*>(data + ip_offset + (ip->version_ihl & 0x0F) * 4);
All byte order adjustments (Big-Endian to Host-Endian) are performed in-place using fast macros or compiler builtins (e.g. __builtin_bswap16, __builtin_bswap32 or ntohs/ntohl).
2. Stateful TCP Flow State Machine
Aegis tracks the standard TCP lifecycle to correctly handle flow creation, payload inspection, and reclamation.
[NEW] (SYN Packet)
│
▼
[ESTABLISHED] (SYN-ACK / ACK)
│
├───────────────────────────┐
▼ ▼
[INSPECT PAYLOAD] [TERMINATING] (FIN / RST Packet)
│ │
▼ ▼
[CLASSIFIED] (SNI Found) [CLOSED]
Flow Lifetime Rules:
- Creation: A new connection entry is created when a
SYNpacket is detected. - Promotion: Promoted to
ESTABLISHEDonce the handshake completes (SYN-ACK or payload seen). - Classification: Promoted to
CLASSIFIEDonce the application type (HTTP, TLS, DNS) is identified. - Cleanup: Closed when a
FINorRSTis processed, or when the inactivity timer expires (default: 300 seconds).
3. TCP Segment Reassembly for Handshake Detection
Sometimes, the TLS Client Hello or HTTP request is split across multiple TCP segments due to TCP window fragmentation or path MTU limitations. If the engine inspects only individual packets, it will fail to classify these flows.
In-Buffer Reassembly Mechanism:
- Connection Reassembly Buffer: Each
Flowentry has a small pre-allocated scratch buffer (e.g. 4096 bytes). - Out-of-Order Queue: A fixed-size array inside the
Flowtracks segments out of sequence. - Process:
- If a packet contains a portion of the TLS handshake but not the complete extensions block, the payload is appended to the scratch buffer.
- The parser tracks the expected sequence number (
expected_seq). - If the next segment matches
expected_seq, it is appended. - Once the buffer contains enough contiguous bytes to parse the TLS Client Hello (e.g., matching the TLS length field in the TLS record header), the
SNIExtractorparses the combined scratch buffer. - Once classified, the scratch buffer is cleared to save memory.