RepoPilotOpen in app →

daeuniverse/dae

eBPF-based Linux high-performance transparent proxy solution.

Healthy

Healthy across the board

weakest axis
Use as dependencyConcerns

copyleft license (AGPL-3.0) — review compatibility

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 2d ago
  • 37+ active contributors
  • Distributed ownership (top contributor 12% of recent commits)
Show all 7 evidence items →
  • AGPL-3.0 licensed
  • CI configured
  • Tests present
  • AGPL-3.0 is copyleft — check downstream compatibility
What would change the summary?
  • Use as dependency ConcernsMixed if: relicense under MIT/Apache-2.0 (rare for established libs)

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/daeuniverse/dae)](https://repopilot.app/r/daeuniverse/dae)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/daeuniverse/dae on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: daeuniverse/dae

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/daeuniverse/dae shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 2d ago
  • 37+ active contributors
  • Distributed ownership (top contributor 12% of recent commits)
  • AGPL-3.0 licensed
  • CI configured
  • Tests present
  • ⚠ AGPL-3.0 is copyleft — check downstream compatibility

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live daeuniverse/dae repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/daeuniverse/dae.

What it runs against: a local clone of daeuniverse/dae — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in daeuniverse/dae | Confirms the artifact applies here, not a fork | | 2 | License is still AGPL-3.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 32 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>daeuniverse/dae</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of daeuniverse/dae. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/daeuniverse/dae.git
#   cd dae
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of daeuniverse/dae and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "daeuniverse/dae(\\.git)?\\b" \\
  && ok "origin remote is daeuniverse/dae" \\
  || miss "origin remote is not daeuniverse/dae (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(AGPL-3\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"AGPL-3\\.0\"" package.json 2>/dev/null) \\
  && ok "license is AGPL-3.0" \\
  || miss "license drift — was AGPL-3.0 at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "cmd/run.go" \\
  && ok "cmd/run.go" \\
  || miss "missing critical file: cmd/run.go"
test -f "common/consts/ebpf.go" \\
  && ok "common/consts/ebpf.go" \\
  || miss "missing critical file: common/consts/ebpf.go"
test -f "component/dns/routing_program.go" \\
  && ok "component/dns/routing_program.go" \\
  || miss "missing critical file: component/dns/routing_program.go"
test -f "cmd/runner.go" \\
  && ok "cmd/runner.go" \\
  || miss "missing critical file: cmd/runner.go"
test -f "component/daedns/router.go" \\
  && ok "component/daedns/router.go" \\
  || miss "missing critical file: component/daedns/router.go"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 32 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~2d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/daeuniverse/dae"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

dae is a Linux transparent proxy built on eBPF that routes traffic by splitting it at the kernel level, bypassing the userspace proxy entirely for direct flows. It implements 'Real Direct' traffic with minimal performance loss by leveraging eBPF to intercept and classify packets (by process name, MAC address, or invert-match rules), then forwards only proxied traffic through the proxy app while letting direct traffic pass natively. Monorepo split into three layers: cmd/ contains the CLI entry points (cmd.go, run.go, reload.go), ebpf/ (inferred from workflow references) holds eBPF C programs, and the Go core under the root module implements traffic classification, DNS resolution, and protocol handling. The Makefile orchestrates eBPF compilation (likely via clang via .clang-format presence), Go builds, and test suites.

👥Who it's for

Linux system administrators and power users who need high-performance traffic splitting and selective proxying (by process, host, or subnet) with support for advanced DNS resolution, automatic node failover testing, and proxy protocols like Shadowsocks, Trojan, and SOCKS5—especially those running transparent proxy setups on VPS or LAN gateways.

🌱Maturity & risk

Actively developed with comprehensive CI (11 GitHub workflows including kernel-test, ebpf-audit, go-test, bpf-test). The large Go codebase (2.3M lines) and well-structured eBPF C components (194K lines) suggest production maturity. Populated issue templates and change logs indicate active maintenance, though the successor status to v2rayA suggests ongoing evolution rather than stabilization.

Kernel-level eBPF code is inherently risky (bugs can crash the kernel or leak memory), and the 38+ Go dependencies introduce supply-chain exposure. No obvious single-maintainer risk given the daeuniverse org, but eBPF requires Linux 5.10+ and specific kernel configurations—mismatches silently fail. Heavy reliance on cilium/ebpf (v0.20.0) and custom outbound libraries means upstream changes could break the proxy protocol stack.

Active areas of work

Active development with workflows for daily builds, prerelease automation, downstream flake syncing, and eBPF auditing. The presence of cmd/generators/gen_ebpf_sync suggests ongoing code generation for eBPF-Go sync, and the ebpf-audit.yml workflow indicates security/correctness hardening work.

🚀Get running

git clone https://github.com/daeuniverse/dae.git
cd dae
make  # compiles eBPF and Go
sudo ./dae run  # requires root for eBPF and iptables setup

Daily commands:

make  # builds dae binary and eBPF bytecode
sudo ./dae run --config /etc/dae/config.dae  # or see dae run --help

Requires: Linux kernel 5.10+, CAP_SYS_ADMIN, eBPF JIT enabled (echo 1 > /proc/sys/net/core/bpf_jit_enable).

🗺️Map of the codebase

  • cmd/run.go — Entry point for dae daemon execution; all core initialization, lifecycle management, and signal handling flows through here.
  • common/consts/ebpf.go — eBPF constant definitions and kernel-userspace contract; critical for understanding eBPF program communication.
  • component/dns/routing_program.go — DNS request/response routing logic compilation; core traffic split decision logic leveraging eBPF.
  • cmd/runner.go — Manages eBPF program loading, attachment, and reload orchestration; bridges userspace and kernel-space.
  • component/daedns/router.go — DNS query routing and upstream selection logic; implements distributed DNS resolution policy.
  • common/netutils/netproxy_udp.go — UDP proxy handling for transparent traffic interception; handles non-TCP transparent proxy mechanics.
  • component/dns/upstream.go — DNS upstream server abstraction and management; critical for multi-upstream DNS failover logic.

🛠️How to make changes

Add a new DNS upstream provider

  1. Define upstream configuration structure in component/dns/upstream.go (component/dns/upstream.go)
  2. Implement DNS resolution logic for the new provider in component/daedns/client.go (component/daedns/client.go)
  3. Register upstream selector in component/daedns/router.go routing dispatch (component/daedns/router.go)
  4. Add configuration parsing rules in component/dns/routing_program.go (component/dns/routing_program.go)

Add a new routing policy function

  1. Define function signature and behavior in component/dns/function_parser.go (component/dns/function_parser.go)
  2. Implement request-phase logic in component/dns/request_routing.go (component/dns/request_routing.go)
  3. Implement response-phase logic if needed in component/dns/response_routing.go (component/dns/response_routing.go)
  4. Add test cases in component/dns/routing_program_test.go (component/dns/routing_program_test.go)

Add a new CLI command

  1. Create command handler following pattern in cmd/run.go (cmd/cmd.go)
  2. Register command in main dispatcher in cmd/cmd.go (cmd/cmd.go)
  3. Add command-specific logic file following naming convention (e.g., cmd/mycommand.go) (cmd/validate.go)
  4. Wire runner/eBPF interactions through cmd/runner.go if kernel communication needed (cmd/runner.go)

Add support for a new network protocol

  1. Add protocol constants and packet structures in common/consts/net.go (common/consts/net.go)
  2. Implement protocol parsing utilities in common/netutils/ directory (common/netutils/dns.go)
  3. Add transparent proxy handling in common/netutils/netproxy_udp.go or new file (common/netutils/netproxy_udp.go)
  4. Register protocol routing in component/dns/routing_program.go or appropriate component (component/dns/routing_program.go)

🔧Why these technologies

  • eBPF (Extended Berkeley Packet Filter) — Enables kernel-space traffic interception and splitting with minimal overhead; allows direct traffic bypass without userspace forwarding
  • Go — High-level language for userspace daemon, config parsing, and eBPF program orchestration; strong concurrency support
  • Cilium ebpf library (github.com/cilium/ebpf) — Abstracts eBPF program loading, map management, and kernel communication; handles portability across kernel versions
  • Linux transparent proxy (SO_REUSEADDR, IP_TRANSPARENT) — Allows dae to transparently intercept traffic without application modification
  • ANTLR4 (github.com/antlr/antlr4) — Parses DNS routing policy domain-specific language (DSL) into executable routing programs
  • miekg/dns library — Pure Go DNS packet parsing and protocol handling; integrates with routing logic

⚖️Trade-offs already made

  • eBPF for kernel-space traffic splitting vs. userspace-only proxy

    • Why: Maximize throughput and minimize latency by keeping hot path in kernel
    • Consequence: Increased complexity, kernel version dependencies, and debugging difficulty; requires root/CAP_BPF
  • Transparent proxy (redirect iptables rules) vs. explicit proxy (CONNECT/SOCKS)

    • Why: Support existing applications without modification; true direct-to-destination traffic
    • Consequence: Linux-only, must manage netfilter rules, kernel permissions required, harder to audit flows
  • DNS routing DSL compiled to eBPF programs vs. userspace-only DNS routing

    • Why: Push routing decisions into kernel for consistent, zero-copy traffic steering
    • Consequence: DSL compilation complexity, eBPF memory limits, harder to update rules dynamically (requires reload)
  • Reload entire eBPF programs on config change vs. hot-update kernel maps

    • Why: Simpler implementation, guaranteed consistency; avoids race conditions during updates
    • Consequence: Brief traffic interruption during reload, higher latency during updates

🚫Non-goals (don't propose these)

  • Does not handle authentication or access control (relies on system-level permissions)
  • Not a general-purpose load balancer; focused on single-host transparent proxying
  • Does not support Windows or macOS; Linux kernel eBPF is fundamental requirement
  • Does not provide GUI or web dashboard (CLI-only control interface)
  • Does not handle HTTPS/TLS decryption (transparent proxy limitation)
  • Not a VPN client; focuses on traffic routing within local network interface

🪤Traps & gotchas

  1. eBPF code generation: gen_ebpf_sync generates Go↔eBPF bindings; editing eBPF headers requires regeneration via make. 2. Linux kernel version: eBPF features vary by kernel version; tail calls, BPF_MAP_TYPE_RINGBUF, and XDP require 5.10+; missing features silently degrade. 3. Namespace isolation: netns (vishvananda/netns) operations require CAP_SYS_ADMIN; missing in unprivileged containers. 4. Config parsing: uses ANTLR4 grammar (embedded in dae-config-dist Go module), so config syntax changes require syncing the external grammar repo. 5. UDP state tracking: README warns that UDP statefulness is fragile—all outgoing UDP is proxied unless explicitly marked must_direct.

🏗️Architecture

💡Concepts to learn

  • v2rayA/v2rayA — Direct predecessor; dae abandoned v2ray-core in favor of native eBPF to solve the same transparent proxy problem with better performance.
  • daeuniverse/outbound — Companion library imported directly; implements proxy protocol encoding/decoding (Shadowsocks, Trojan, SOCKS5) that dae depends on.
  • daeuniverse/dae-config-dist — Separate repo holding ANTLR4 grammar and generated Go config bindings; schema changes require updates here first.
  • cilium/ebpf — Core dependency providing the Go eBPF loader and BPF syscall bindings; version v0.20.0 must be compatible with Linux kernel features used.
  • vishvananda/netlink — Used for netlink-based namespace and route management; critical for setting up per-netns routing rules and eBPF program attachment.

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for common/bitlist/bitlist.go

The bitlist package is a core utility used throughout the codebase (particularly for bitmask operations in eBPF contexts), but only has a single _test.go file. Given its criticality in a high-performance transparent proxy, edge cases around bit manipulation, boundary conditions, and performance characteristics need thorough testing. This would improve reliability and catch regressions early.

  • [ ] Review existing common/bitlist/bitlist_test.go to identify coverage gaps
  • [ ] Add tests for edge cases: empty bitlists, single-bit operations, overflow scenarios, concurrent access patterns
  • [ ] Add benchmark tests (BenchmarkBitlist*) to track performance regressions
  • [ ] Test integration with eBPF constant generation in common/consts/ebpf.go
  • [ ] Ensure tests run in the go-test.yml workflow without requiring kernel access

Add integration tests for cmd/dae-ebpf-audit/main.go in bpf-test.yml workflow

The dae-ebpf-audit tool is a critical debugging utility for eBPF programs, but there's no dedicated test coverage visible in the bpf-test.yml workflow. Adding integration tests would verify that eBPF audit functionality correctly validates eBPF code generation, which is essential given the complexity of eBPF-based traffic splitting.

  • [ ] Create cmd/dae-ebpf-audit/audit_test.go with test fixtures for common eBPF validation scenarios
  • [ ] Add test cases for: detecting invalid eBPF instructions, validating program maps, checking kernel compatibility
  • [ ] Extend .github/workflows/bpf-test.yml to run dae-ebpf-audit tests with mock eBPF programs
  • [ ] Ensure tests work with ebpf-audit's output parsing to catch regressions in audit report format

Add missing linter rule configurations for eBPF C code in .clang-format and create ebpf/Makefile lint target

The repo has comprehensive Go linting (.golangci.yml) and formatting rules (.clang-format, .editorconfig), but no visible dedicated linting workflow for eBPF C source files (referenced by cilium/ebpf v0.20.0). Given that eBPF correctness is security-critical and the codebase uses kernel-level code, systematic C code analysis is essential. This would complement the existing ebpf-audit.yml workflow.

  • [ ] Identify all eBPF C source files in the repository (likely in an ebpf/ or bpf/ directory referenced by cmd/generators/gen_ebpf_sync)
  • [ ] Configure .clang-format with stricter rules for eBPF code (pointer safety, bounds checking style)
  • [ ] Create or enhance .github/workflows/ebpf-audit.yml to run clang-tidy on all .c/.h eBPF files
  • [ ] Add Makefile target for local eBPF linting (e.g., make lint-ebpf) for contributor convenience
  • [ ] Document eBPF code standards in CONTRIBUTING.md (if it exists) or README.md

🌿Good first issues

  • Add unit tests for cmd/reload_progress_test.go coverage gaps—the file exists but likely has untested edge cases in config rollback or partial reload scenarios.
  • Document the eBPF map schemas (ringbuf format, BPF_HASH keys/values) in a new docs/ebpf-maps.md—currently inferred only from C code and workflows.
  • Implement missing shell completion for new CLI flags added since cmd/completion.go was written—check dae run --help against completion logic.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • c7e0296 — fix(bpf): fallback to bpf_get_current_comm when bpf_get_current_task is unavailable (#995) (QiuSimons)
  • 0a4de9d — ci: build for GORISCV64 variants (#994) (Xeonacid)
  • 320a9e5 — fix(bpf): restore cmdline parsing for accurate process name (#991) (TnZzZHlp)
  • ddee330 — fix(docker): update Go version to 1.26 in Dockerfile (#989) (KagurazakaNyaa)
  • bc62085 — fix(ebpf): fix "bad CO-RE relocation" on GCC 15 by disabling unnecessary UAPI CO-RE (#986) (KongQBin)
  • 8b52a2a — docs: add official repository installation guide for Arch Linux (#981) (Integral-Tech)
  • e239c3b — ci(release): draft release v2.0.0rc1 (#978) (dae-prow[bot])
  • 654c7eb — ci(release): draft release v1.1.0 (#976) (dae-prow[bot])
  • 85a1fc3 — ci/docs/optimize/feature: Enhance control plane features and improve CI workflows by olicesx (#970) (MarksonHon)
  • 39831d5 — feat(control): add runtime traffic metrics and node latency probing (#968) (ksong008)

🔒Security observations

  • High · Insecure Dockerfile - Running as Root — Dockerfile. The Dockerfile does not specify a USER directive, meaning the container runs as root by default. This violates the principle of least privilege and increases the attack surface if the application is compromised. Fix: Add a non-root user and switch to it before the CMD/ENTRYPOINT. Example: RUN useradd -m -u 1000 dae && USER dae
  • High · Insecure File Permissions in Docker — Dockerfile. The configuration file /etc/dae/config.dae is set to 0600 (read/write by owner only), but since the container runs as root, this does not prevent privilege escalation. Additionally, the file could contain sensitive information. Fix: Run the container as a non-root user and ensure proper permission management. Store sensitive configuration in secrets management systems rather than volume mounts.
  • High · Privileged Docker Container Mode — docker-compose.yml. The docker-compose.yml runs the container with privileged: true, network_mode: host, and pid: host. This grants excessive capabilities and bypasses container isolation, significantly increasing security risk. Fix: Remove or minimize privileged mode. Use specific capability flags (--cap-add) instead of privileged=true. Consider using network namespaces instead of host mode where possible.
  • High · Unsafe External Network Requests in Docker Build — Dockerfile. The Dockerfile uses wget to download geoip.dat and geosite.dat from the internet during build without signature verification. This is vulnerable to man-in-the-middle attacks and supply chain attacks. Fix: Verify downloaded files using checksums/signatures. Consider using a build-time package cache. Use HTTPS exclusively and validate certificates. Store these files in a private registry.
  • High · eBPF Programs - Potential Privilege Escalation — cmd/dae-ebpf-audit, eBPF modules. As an eBPF-based transparent proxy running with elevated privileges, there is inherent risk of kernel vulnerability exploitation. eBPF programs have access to kernel memory and networking structures. Fix: Regularly audit eBPF bytecode for security issues. Keep kernel version updated to patch eBPF vulnerabilities. Use eBPF verifier features where possible. Implement capability restrictions.
  • Medium · Outdated Go Version — go.mod. The go.mod specifies go 1.26.0, which appears to be a future version. Ensure this is intentional and not a typo (should likely be 1.21.x or 1.22.x range for current stable releases). Fix: Verify the Go version is correct and supported. Use an actively maintained Go version.
  • Medium · Dependency on Custom Outbound Package — go.mod. The github.com/daeuniverse/outbound dependency uses a 'sticky-ip' fork with a specific commit hash. Version pinning to specific commits reduces auditability and makes security updates harder to track. Fix: Use semantic versioning for dependencies where possible. If using commit hashes, maintain a changelog of why specific commits are pinned and regularly audit for security updates.
  • Medium · Volume Mount of /sys Directory — docker-compose.yml. The docker-compose.yml mounts /sys:/sys which provides access to kernel interfaces. Combined with privileged mode, this significantly increases the attack surface. Fix: Restrict /sys mounts to specific subdirectories if possible. Minimize the scope of mount points. Audit what /sys interfaces are actually required by the application.
  • Medium · No HEALTHCHECK in Dockerfile — Dockerfile. The Dockerfile lacks a HEALTHCHECK instruction, making it difficult to detect if the proxy is functioning correctly, potentially allowing silent failures. Fix: Add a HEALTHCHECK instruction that validates the proxy is functional. Example: HEALTHCHECK --interval=30s --timeout=10s CMD dae status
  • Medium · Unverified Git Submodules — undefined. The Makefile includes Fix: undefined

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · daeuniverse/dae — RepoPilot