Conversation
feat: implement asymmetric syn_udp transport and add multi-inbound su…
add web panel
set workflows for panel
chore: update Zig installation path to user home directory in CI work…
refactor: migrate to pure Go SQLite driver to enable static cross-com…
New Core architecture, v3.0.0
fix: ensure tester results exist and optimize rendering by memoizing …
feat: replace download link and apply action with a client-side file …
feat: add support for dynamic web path prefixing to all frontend rout…
Added a donation section to the README file.
back runner to ubuntu22
feat: add file path support for IP lists, implement tunnel auto-start and update version to 3.0.2
feat: add TCP destination port filtering support for receiver mode
…ceive ## Architecture Restructure Rust workspace into three crates: - spoof-transport: existing raw socket transport (moved from rust/src/) - xdp-ebpf: eBPF program compiled for bpfel-unknown-none target - xdp-loader: userspace loader using aya for XDP program management ## XDP eBPF Program (rust/xdp-ebpf/) - Parses Ethernet/IPv4 headers using fixed constant offsets (14+20) to satisfy the BPF verifier's strict bounds checking - Filters packets by protocol, peer spoof IP, and destination port via BPF HashMap config map - Uses bpf_xdp_load_bytes() kernel helper for payload copy into ring buffer, avoiding the verifier's variable-offset packet pointer access restrictions - Inline asm (asm_experimental_arch) to emit AND/OR instructions that the BPF verifier can track for argument bounds - Returns XDP_DROP for matched packets (zero-copy to userspace) - Returns XDP_PASS for non-matching traffic (normal stack) ## XDP Loader (rust/xdp-loader/) - Embeds compiled eBPF ELF at compile time via include_bytes!() - build.rs tracks eBPF binary for proper change detection - Aligned copy mechanism for ELF data (8-byte alignment required) - Configures BPF maps: CONFIG (filter params), PAYLOADS (ring buf), PKT_COUNT (statistics) - Ring buffer consumer thread delivers packets to Go via FFI - Graceful XDP detach on close ## Go Integration - New XDPReceiver type in internal/transport/xdp_receiver.go - Factory pattern: --xdp-interface flag triggers XDP-first with automatic fallback to raw socket on failure - CGo FFI via spoof_transport.h for XDP lifecycle management - Config support: xdp_interface field in JSON config ## Build System - xdp-ebpf excluded from Cargo workspace (separate nightly toolchain) - Makefile updated for two-phase Rust build (eBPF then workspace) - .gitignore updated for xdp-ebpf build artifacts ## Key BPF Verifier Solutions - Fixed header offsets (no variable IHL/doff) for packet access - bpf_xdp_load_bytes() instead of manual byte-copy loop - Inline asm for payload_len masking (LLVM optimizes away Rust masks) - Ring buffer entry sized to accommodate masked max (2064 bytes)
Add build-ebpf job to both test.yml and release.yml: - Uses nightly Rust toolchain with rust-src component - Compiles xdp-ebpf crate for bpfel-unknown-none target - Passes eBPF binary to downstream jobs via upload-artifact Update Rust build jobs: - Install libelf-dev (required by aya for ELF object parsing) - Download eBPF binary artifact before building Rust workspace - Use -p spoof-transport flag in test workflow for targeted build Job dependency graph: build-ebpf → test-rust build-ebpf → test-go (test.yml) build-ebpf → test-rust → build-tunnel (release.yml) The eBPF program is architecture-independent (bpfel-unknown-none) so it only needs to be built once and shared across amd64/arm64 jobs.
…ection
## Root cause: | 1 bug causing ~50% packet loss
The previous asm block used 'r0 |= 1' to ensure the verifier saw
min=1. This corrupted the actual value:
- payload_len=100 (even) → safe_len=101 → bpf_xdp_load_bytes
tried to read 101 bytes from a 100-byte payload → FAIL
- Failed entries were discarded → ~50% of packets dropped
- Surviving packets had length off-by-one → garbled data
## Fix: single asm block with inline conditional branch
Use a single asm block that:
1. Masks: r2 = payload_len & 0x7FF (verifier: [0, 2047])
2. Branch: if r2 == 0 goto skip (verifier narrowing)
3. Sets args and calls bpf_xdp_load_bytes#189 directly
4. On zero path: returns -1 to signal skip
The verifier can follow the conditional branch and knows that on
the fall-through path r2 (the length arg) is in [1, 2047].
This completely avoids the 'zero-sized read' verifier error.
The zero case never triggers at runtime since payload_len >= 1
is checked earlier, but the verifier needs the proof.
## Also removes unused import
bpf_xdp_load_bytes is now called via raw asm 'call 189' so
the aya_ebpf_bindings import is no longer needed.
The asm block was not setting r2 (offset argument) correctly. r2 contained the masked payload_len instead of payload_offset, causing bpf_xdp_load_bytes to read from the wrong location in the packet (e.g. offset 10 in IP header instead of offset 54 where TCP payload starts). This resulted in IP/TCP header bytes being returned as payload data, causing garbled output on the receiving end. Fix: add payload_offset as input register r8 and set r2 = r8 before the call. Also fix the goto offset from +5 to +6 since the call setup now uses 4 instructions instead of 3. Args to bpf_xdp_load_bytes (helper #189): r1 = xdp_md context r2 = offset in packet ← was wrong (payload_len), now correct r3 = destination buffer r4 = length to copy
When the TCP sender fragments packets (payload + TCP overhead > MTU), the XDP program was DROPping the first fragment (which has the TCP header) while PASSing subsequent fragments (no TCP header → bounds check fail). The kernel couldn't reassemble because the first fragment was missing, causing 0 throughput at higher WireGuard MTUs. Fix: check IP flags/fragment-offset field (bytes 6-7 of IP header). If MF (More Fragments) bit is set OR fragment offset > 0, return XDP_PASS to let the kernel handle reassembly via the raw socket receiver fallback. This restores correct behavior for WireGuard MTU 1280+ while keeping the XDP fast path for non-fragmented packets.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.