dae: an eBPF transparent proxy that keeps direct traffic out of userspace
eBPF-based Linux high-performance transparent proxy solution.
At a glance
- What is it?
- dae splits traffic inside the Linux kernel with eBPF so that only proxied flows reach the proxy process. Here is what the repository documents about installing it, writing routing rules, and where the design stops being the right choice.
- Who is it for?
- dae fits engineers running a Linux router or VPS who want per-process, per-MAC and per-domain routing with direct traffic bypassing userspace, and who are comfortable editing a .dae config and running a privileged daemon. Skip it if you need a GUI-first client, a non-Linux host, or a proxy stack you cannot run with host networking and privileged mode.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem dae targets: proxying without paying for direct traffic
Most Linux proxy clients intercept every packet, hand it to a userspace process, decide what to do with it, and send it back out. Direct traffic pays that cost even though it never needed a proxy. dae, named after the Chinese word for goose, takes the opposite route. The README states that it "employs the transparent proxy and traffic split suite within the Linux kernel using eBPF," so that direct traffic bypasses the proxy application's forwarding entirely. The stated result is minimal performance loss and negligible extra resource consumption for flows that are not proxied.
The audience is narrower than a desktop VPN app. dae is a Linux daemon aimed at people who run a router, a home gateway or a VPS and want routing decisions made per process, per MAC address or per domain. The README lists process-name splitting on the local host and MAC-address splitting across a LAN as first-class features, which points at gateway deployments rather than single laptops. It is also positioned as a successor to v2rayA, and the README says the project abandoned v2ray-core "to meet the needs of users more freely." That is a deliberate break from the v2ray configuration model, not an incremental fork.
How the eBPF datapath and the routing rules fit together
The kernel side does the splitting. Go code loads eBPF programs that classify packets against the routing rules, so a flow that matches a direct rule never enters the proxy process at all. A flow that matches a proxy rule is redirected to the daemon, which then speaks whatever outbound protocol the configuration selects. The repository keeps the outbound implementations in a separate module, github.com/daeuniverse/outbound, and the README points at docs/en/proxy-protocols.md for the protocol list rather than enumerating it inline.
Rules are written in a small expression language, and the repository ships example.dae at the top level as a reference config. The README's own examples show the shape: a rule can match on l4proto, sport, and a domain set, and terminate in an action such as must_direct. The README also documents invert match rules and automatic node switching, where dae tests independent TCP, UDP, IPv4 and IPv6 latencies and then picks the best node per the user's policy. DNS is handled through what the README calls an advanced DNS resolution process, with domain routing separate from traffic routing.
Two operational details in the README matter more than the feature list. First, because UDP state is hard to maintain, all outgoing UDP packets can potentially be proxied depending on your routing, so a UDP server running on the same public machine needs an explicit rule of the form l4proto(udp) && sport(your server ports) -> must_direct to keep client traffic and DNS from looping back through the proxy. Second, DNS routing interacts with first-connection latency: the README warns that a domestic domain handled by a foreign DNS upstream can stall TLS handshakes, and cites ocsp.digicert.cn appearing in geosite:geolocation-!cn as an example.
Installing dae and writing a first config
The README does not carry install commands. It points to the Quick Start Guide at docs/en/README.md and says to refer to it to start using dae right away, so that file is the place to check for the current install path for your distribution. What the repository does show directly is the container route. The Dockerfile builds the daemon with a Go builder image, installs clang-15 and llvm-15 for the eBPF objects, and then copies the binary plus install/empty.dae into /etc/dae/config.dae in an Alpine runtime image. The compose file at the repository root shows the privileges that setup expects:
version: "3"
services:
dae:
privileged: true
network_mode: host
pid: host
build:
context: .
volumes:
- /sys:/sys
- /etc/dae:/etc/daePrivileged mode, host networking and host PID are not incidental. The kernel datapath needs /sys mounted to attach its eBPF programs, and it needs to see the host's network namespace and processes to classify traffic by process name. If your platform will not grant those, the container path is closed.
The image also pins its geo data. The Dockerfile downloads geoip.dat and geosite.dat from v2fly release tags, checks each against a sha256 value embedded as a build argument, and fails the build if the checksum does not match. Those ARG defaults are asserted against scripts/fetch-geo-data.sh by scripts/check-build-env.sh, which the Dockerfile comment calls the single owner of the pins. For a first run, start from the config the repository already ships rather than an empty document; the Dockerfile copies install/empty.dae into place as /etc/dae/config.dae, and example.dae at the repository root is the worked reference. The README's UDP warning translates into a rule you should have in place before the daemon handles real traffic on a VPS that also serves UDP:
l4proto(udp) && sport(your server ports) -> must_directSubstitute your actual server port range. The point is not the specific number; it is that the rule must exist before you start routing, because the failure mode is a loop rather than an error message.
Where dae is the wrong tool
The kernel datapath is also the constraint. Everything dae does depends on eBPF features available in your kernel, so an old kernel, a locked-down kernel, or a virtualized environment that restricts BPF program loading removes the mechanism the project is built on. There is no userspace fallback documented in the README.
Privilege is the second boundary. The compose file runs the container privileged with host networking and host PID, and the daemon attaches programs that affect all traffic on the machine. On a shared host, or anywhere you cannot grant that access, dae is not a candidate. The same applies to macOS and Windows: the README describes a Linux kernel solution, and nothing in the repository suggests a non-Linux datapath.
The third case is operational rather than technical. dae is a daemon with a text configuration file and no documented GUI. The README's TODO list includes "Add quick-start guide" as an unchecked item, and the Getting Started section defers to a separate document. If your team needs a point-and-click client, or needs configuration managed by something other than a file on disk, the project's current shape will fight you. The README's own note about foreign DNS breaking first-screen latency on domestic Chinese sites is a good illustration of the class of problem here: the misconfiguration is silent, the symptom is slow TLS handshakes, and finding it requires reading your DNS routing rules carefully rather than waiting for a log line.
How dae differs from a v2ray-core based client
The obvious comparison is v2rayA, which the README names as the project dae succeeds. The difference is architectural, not cosmetic. A v2ray-core based setup routes traffic through a userspace process that makes the proxy-or-direct decision after the packet has already left the kernel path; dae moves that decision into eBPF programs attached in the kernel, so direct flows are never handed to the daemon. That is the entire justification for the project's existence, and it is why the README frames the v2ray-core removal as freeing the project from that model.
The practical consequence is that dae's configuration language is its own. You are not writing v2ray JSON or reusing an existing subscription-to-config pipeline; you are writing rules in the expression syntax shown in example.dae, with actions like must_direct and match conditions on protocol, port, domain set and process. Node selection is also handled differently: instead of a fixed outbound, dae can measure TCP, UDP, IPv4 and IPv6 latency per node and switch according to policy. If your existing tooling generates v2ray configs and your operators know that format, moving to dae means rewriting both the configs and the mental model. If your pain is that direct traffic is being dragged through userspace, the rewrite is the point.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-09-20. Release cadence in the recent history is roughly one minor release per quarter, with v1.1.0 on 2026-04-23, v2.0.0 on 2026-07-08 and v2.1.1 on 2026-09-18. The jump from 1.x to 2.x within that window is worth noting if you are pinning versions: a major bump in a proxy daemon usually means config or behaviour changes, and the README does not document a rollback procedure for a bad upgrade. Check CHANGELOGS.md before moving between majors.
The licence is AGPL-3.0, and the README states it as "AGPL-3.0 (C) daeuniverse." That is a copyleft licence with a network-use clause. If you run a modified dae as part of a service other people interact with over a network, the licence's terms are likely to reach your modifications. This is not legal advice and the specifics depend on your situation, but the practical check is whether you intend to modify and redistribute or network-serve the daemon. If you only run it unmodified on your own gateway, the obligation is lighter than if you ship a product built on it. Note also that the package.json in the repository declares "Apache" for the npm tooling used by the docs lint scripts; that file covers markdown linting dependencies, not the daemon, whose LICENSE file is AGPL-3.0.
Editorial conclusion
dae fits engineers running a Linux router or VPS who want per-process, per-MAC and per-domain routing with direct traffic bypassing userspace, and who are comfortable editing a .dae config and running a privileged daemon. Skip it if you need a GUI-first client, a non-Linux host, or a proxy stack you cannot run with host networking and privileged mode. Verify first that your kernel exposes the eBPF features the build needs, that ipforward is enabled if you want Real Direct, and that every UDP service on the same machine has an explicit must_direct rule before you route production traffic through it.
Frequently asked questions
What is daeuniverse/dae and what does it do?
It is an eBPF-based transparent proxy solution for Linux. The README states that it uses the transparent proxy and traffic split suite in the Linux kernel so direct traffic bypasses the proxy application's forwarding, and it is described as a successor to v2rayA that abandoned v2ray-core.
How do I install dae on Linux?
The README does not give install commands; it points to the Quick Start Guide at docs/en/README.md. The repository does include a Dockerfile and docker-compose.yml, and the compose service runs privileged with network_mode host and pid host, mounting /sys and /etc/dae.
Why does dae need privileged mode and host networking?
The datapath is eBPF programs attached in the Linux kernel, and the compose file mounts /sys so they can be loaded, while host networking and host PID let the daemon see host traffic and classify it by process name. Without those permissions the kernel-side splitting cannot work.
What should I watch out for with UDP when running dae on a VPS?
The README warns that because UDP states are hard to maintain, all outgoing UDP packets can potentially be proxied depending on your routing, including traffic to a UDP server on the same machine. It recommends adding a rule such as l4proto(udp) && sport(your server ports) -> must_direct for that port.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/daeuniverse-dae)