eBPF
Changes in sing-box 1.14.0
eBPF inbound is experimental and only available in Linux and Android builds
with the with_ebpf build tag.
The eBPF inbound transparently intercepts selected local or downstream TCP and UDP traffic. Intercepted connections enter the normal sing-box routing pipeline. Required system network state is installed and removed automatically.
The eBPF inbound does not use Listen Fields.
Structure
{
"type": "ebpf",
"tag": "ebpf-in",
"network": ["tcp", "udp"],
"udp_timeout": "5m",
"tc_priority": 1,
"bypass_rule_set": [],
"local": {
"enabled": true,
"data_plane": "cgroup",
"dns_mode": "respect_policy",
"ipv6": true,
"bypass_private_address": true,
"include_uid": [],
"include_uid_range": [],
"exclude_uid": [],
"exclude_uid_range": [],
"include_android_user": [],
"include_package": [],
"exclude_package": [],
"bypass_port": [],
"bypass_port_range": []
},
"shared": {
"enabled": true,
"data_plane": "packet_rewrite",
"dns_mode": "respect_policy",
"interface": ["wlan1"],
"ipv6": true,
"bypass_private_address": true,
"include_source_cidr": [],
"exclude_source_cidr": [],
"include_mac_address": [],
"exclude_mac_address": [],
"bypass_port": [],
"bypass_port_range": []
}
}
Fields
network
Enabled transport protocols, tcp and/or udp. Both are enabled by default.
udp_timeout
UDP session timeout. Default is 5m.
tc_priority
TC filter priority in the range 1 through 65535. Default is 1. Change it only
when coordinating with other TC filters on the same interfaces.
When left at the default, TCX links are used when supported; a custom priority
keeps the traditional clsact attachment so its numeric ordering remains effective.
bypass_rule_set
Traffic to destination IP CIDRs contained in these rule sets bypasses this inbound. Non-IP rules are ignored.
local
local.enabled
Enable interception of traffic generated on this host. When either path uses
the new enabled field, an omitted enabled field on the other path means
false. At least one path must be enabled.
The default cgroup data plane intercepts sockets in the visible cgroup v2 hierarchy and does not follow a network interface. The optional TC data plane follows the current system default network interface and moves when it changes. During a short handoff, the previous attachment remains active until the replacement is ready.
local.data_plane
Selects the local interception backend. cgroup is the default and intercepts
sockets in the visible cgroup v2 hierarchy. Set tc explicitly to intercept
traffic on the current default interface instead.
local.cgroup_path
Limits data_plane: cgroup interception to the specified absolute cgroup v2
subtree. When omitted, the visible cgroup v2 root and all its descendants are
intercepted. This is not the path of the sing-box service unless only that
service subtree should be intercepted.
local.dns_mode
| Value | Behavior |
|---|---|
hijack |
Intercept enabled TCP/UDP traffic to destination port 53. |
respect_policy |
Apply local UID and package selection before intercepting destination port 53. |
off |
Do not intercept destination port 53. |
Default is respect_policy. This setting applies only to enabled TCP/UDP
protocols and does not identify DoH or DoT traffic.
local.ipv6
Enable local IPv6 interception. Default is true. When disabled, local IPv6
traffic bypasses this inbound.
local.bypass_private_address
Bypass private and special-use destinations. Default is true.
local.include_uid
UIDs to intercept. Once an include UID, range, or package is configured, other UIDs bypass by default.
local.include_uid_range
UID ranges to intercept, in start:end format.
local.exclude_uid
UIDs to bypass. Exclude policy takes precedence over include policy.
local.exclude_uid_range
UID ranges to bypass, in start:end format.
local.include_android_user
Android user IDs to intercept. Android only.
local.include_package
Android package names to intercept. Android only.
local.exclude_package
Android package names to bypass. Android only. Packages sharing one UID cannot be distinguished.
local.bypass_port
Destination ports to bypass local interception. This option is supported by
both local data planes (tc and cgroup) and applies independently to TCP and
UDP when those protocols are enabled by network. It matches the destination
port only. FakeIP always forces interception. DNS handling also has precedence:
hijack always intercepts port 53, respect_policy applies UID policy before
DNS interception, and off already bypasses DNS. sing-box emits a startup
warning when port 53 is listed.
local.bypass_port_range
Destination port ranges to bypass, in start:end format. The range is
inclusive.
shared
shared.enabled
Enable interception of traffic arriving from the configured downstream interfaces.
shared.data_plane
| Value | Behavior |
|---|---|
socket_assign |
Assign selected traffic directly to the internal transparent listener. |
packet_rewrite |
Rewrite selected traffic to an internal token address and restore reply packets on the downstream interface. This is the default. |
packet_rewrite requires Ethernet-framed downstream interfaces and does not
use the policy routing required by socket_assign. Neither shared data plane
creates the delivery veth used by local TC. Local and shared data planes are
selected independently.
shared.dns_mode
Uses the same values as local.dns_mode. In respect_policy mode, source CIDR
and MAC selection is applied before destination port 53 is intercepted.
shared.interface
Required when shared interception is enabled
Downstream interfaces where client traffic enters the host. The default
packet_rewrite data plane requires Ethernet framing. Set socket_assign
explicitly for Ethernet/IPoE, raw-IP (including Android rmnet), PPP/PPPoE, or
IPIP/SIT/GRE tunnel interfaces.
Multiple interfaces may be specified; interfaces that are temporarily absent
are retried after network updates. An interface is temporarily excluded from
shared interception while it is the current default upstream, then restored
when it becomes downstream again. Loopback is not accepted.
shared.ipv6
Enable shared IPv6 interception. Default is true. When disabled, IPv6 traffic
on shared interfaces bypasses this inbound.
shared.bypass_private_address
Bypass private and special-use destinations. Default is true.
shared.include_source_cidr
Client source CIDRs to intercept. When non-empty, non-matching sources bypass.
shared.exclude_source_cidr
Client source CIDRs to bypass. Exclude policy takes precedence over include policy.
shared.include_mac_address
48-bit client source MAC addresses to intercept.
This option is available only on Ethernet-framed shared interfaces.
shared.exclude_mac_address
48-bit client source MAC addresses to bypass. Exclude policy takes precedence over include policy.
This option is available only on Ethernet-framed shared interfaces.
shared.bypass_port
Destination ports to bypass shared interception. This option is supported by
both shared data planes (socket_assign and packet_rewrite) and applies
independently to TCP and UDP when those protocols are enabled by network. It
matches the destination port only. FakeIP and DNS handling have the same
precedence described for local.bypass_port; listing port 53 in this mode is
therefore warned about at startup.
shared.bypass_port_range
Destination port ranges to bypass, in start:end format. The range is
inclusive.
Note
Shared mode does not enable IP forwarding or provide NAT, DHCP, IPv6 router advertisements, or hotspot management. Configure these functions in Android, Linux, or the router operating system. Multiple downstream interfaces may be configured for Wi-Fi, USB tethering, and similar links.
Limitations
- A sing-box instance may contain only one eBPF inbound with local interception enabled. Additional eBPF inbounds must be shared-only.
- Fragmented IPv4 and IPv6 datagrams bypass interception. IPv6 atomic fragments are processed as ordinary IPv6 packets.
- Interception state is restored automatically after network changes.
See eBPF kernel requirements before enabling this inbound on vendor or Android kernels.