feat!: universal redesign — drop Minecraft stack, single-crate architecture
- remove Java plugins (velocity/paper), dashboard, all MC-specific code
(handshake, death_code, varint, hostname-HMAC); available in history pre-v0.2
- merge crates/* into one package with src/bin/{rampart,rampart-manager,rampart-cli}
- ProtocolHandler trait + registry (no implementations yet), universal PoW kept
- XDP: universal L3/L4 filter (xdp/core/) + pluggable hook API (xdp/hooks/),
fix IPv6 saddr bug; clang build verified
- docs: bilingual knowledge base (docs/kb/: attacks x4, defense-levels,
practice x3), rewrite README/architecture for universal concept
- TODO.md v4.0: <=300-line module limit, competitor benchmark section (ref/)
- deploy/CI/docs cleanup: no MC references, new binary names
cargo build/clippy(-D warnings)/test green (55 tests)
This commit is contained in:
parent
0b53ed720b
commit
15f474486a
179 changed files with 5044 additions and 11519 deletions
121
xdp/hooks/hook_api.h
Normal file
121
xdp/hooks/hook_api.h
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
#ifndef RAMPART_HOOK_API_H
|
||||
#define RAMPART_HOOK_API_H
|
||||
|
||||
/*
|
||||
* ── Rampart protocol-hook contract ──
|
||||
*
|
||||
* The universal XDP filter is protocol-agnostic: it validates L2/L3/L4,
|
||||
* tracks the TCP handshake (SYN_RECEIVED → ESTABLISHED), applies
|
||||
* blacklist/whitelist/throttle policy — and then delegates deep payload
|
||||
* inspection to an optional protocol hook.
|
||||
*
|
||||
* ── WHAT THE HOOK SEES ──
|
||||
*
|
||||
* proto_hook() is called ONLY when:
|
||||
* - packet is TCP, destination port is inside the protected range;
|
||||
* - connection passed SYN throttle and completed the 3-way handshake
|
||||
* (state == STATE_ESTABLISHED);
|
||||
* - the segment carries a non-zero payload.
|
||||
*
|
||||
* Pure SYN / SYN-ACK / ACK (handshake segments) NEVER reach the hook:
|
||||
* the hook physically cannot block a clean TCP handshake.
|
||||
* Empty ACKs also never reach the hook (keep-alives pass untouched).
|
||||
*
|
||||
* struct cursor — bounds-checked window over the TCP payload:
|
||||
* pos = first payload byte, end = one past the last
|
||||
* byte of the packet (validated against data_end).
|
||||
* struct pkt_meta — read-only metadata: 4-tuple (ports in HOST byte
|
||||
* order), payload length, full TCP flags byte,
|
||||
* L3 family.
|
||||
*
|
||||
* ── VERDICTS ──
|
||||
*
|
||||
* XDP_PASS — accept the segment; filter advances expected_seq by
|
||||
* the consumed payload length and keeps conntrack entry.
|
||||
* XDP_DROP — drop the segment AND tear down the conntrack entry.
|
||||
* Anything else (XDP_ABORTED etc.) is treated as XDP_PASS; do not
|
||||
* return it.
|
||||
*
|
||||
* ── RULES FOR HOOK IMPLEMENTATIONS ──
|
||||
*
|
||||
* 1. Never block handshake traffic — guaranteed by design (see above),
|
||||
* do not try to work around it either.
|
||||
* 2. Bounded loops only: every loop must have a compile-time-constant
|
||||
* trip count (or be provably bounded for the verifier), keep total
|
||||
* complexity low — the program must still load with unrolled loops.
|
||||
* 3. Every cursor advance MUST be bounds-checked against c->end
|
||||
* (use cursor_take()); reading past c->end is forbidden even if it
|
||||
* seems in-bounds in the packet.
|
||||
* 4. Do not update conntrack/throttle/blacklist maps from the hook;
|
||||
* emit events via push_event() if needed (ringbuf, may fail silently).
|
||||
* 5. Keep the hook stateless per-call: all per-connection state lives
|
||||
* in conntrack_map, which belongs to the core filter.
|
||||
*
|
||||
* ── HOW TO ATTACH A HOOK ──
|
||||
*
|
||||
* 1. Create hooks/<proto>_hook.h containing ONLY your own includes
|
||||
* (common.h etc.) and a definition of proto_hook(). Do NOT include
|
||||
* hook_api.h from the hook header — the core includes it for you:
|
||||
*
|
||||
* // hooks/myproto_hook.h
|
||||
* #include "../core/common.h"
|
||||
* static __always_inline enum xdp_action
|
||||
* proto_hook(struct cursor *c, struct pkt_meta *m)
|
||||
* {
|
||||
* ... parse m, advance c ...
|
||||
* return XDP_PASS; // or XDP_DROP
|
||||
* }
|
||||
*
|
||||
* 2. Build the object with the macro pointing at your header:
|
||||
*
|
||||
* clang -O2 -g -target bpf \
|
||||
* -DRAMPART_PROTO_HOOK='"../hooks/myproto_hook.h"' \
|
||||
* -c xdp/core/universal_filter.c -o universal_filter.o
|
||||
*
|
||||
* Without RAMPART_PROTO_HOOK the default no-op stub below is used
|
||||
* and every established connection passes.
|
||||
*/
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include "../core/common.h"
|
||||
|
||||
// ── Bounds-checked cursor over the payload window ──
|
||||
struct cursor {
|
||||
__u8 *pos; // next unparsed byte
|
||||
__u8 *end; // one past last valid byte (== data_end)
|
||||
};
|
||||
|
||||
// Take n bytes from the cursor; returns pointer or NULL on overrun.
|
||||
static __always_inline __u8 *cursor_take(struct cursor *c, __u32 n)
|
||||
{
|
||||
if (c->pos + n > c->end)
|
||||
return NULL;
|
||||
barrier_var(c->pos);
|
||||
__u8 *p = c->pos;
|
||||
c->pos += n;
|
||||
return p;
|
||||
}
|
||||
|
||||
// ── Read-only packet metadata handed to the hook ──
|
||||
struct pkt_meta {
|
||||
__u32 src_ip; // IPv4 addr, or low 32 bits of IPv4-mapped IPv6
|
||||
__u32 dst_ip; // same convention as src_ip
|
||||
__u16 src_port; // host byte order
|
||||
__u16 dst_port; // host byte order
|
||||
__u16 payload_len; // TCP payload bytes in this segment
|
||||
__u8 tcp_flags; // full 13th-byte flags field
|
||||
__u8 is_ipv6; // 1 if L3 is IPv4-mapped IPv6
|
||||
};
|
||||
|
||||
#ifdef RAMPART_PROTO_HOOK
|
||||
#include RAMPART_PROTO_HOOK
|
||||
#else
|
||||
/* Default stub: no deep inspection, everything established passes. */
|
||||
static __always_inline enum xdp_action
|
||||
proto_hook(struct cursor *c, struct pkt_meta *m)
|
||||
{
|
||||
return XDP_PASS;
|
||||
}
|
||||
#endif /* RAMPART_PROTO_HOOK */
|
||||
|
||||
#endif /* RAMPART_HOOK_API_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue