Skip to content

Commit 2c6edf7

Browse files
EternalARKsangyishuje1123vernesong
authored
Enable eBPF support. (#3893)
* Prerequisits for eBPF settings * Add basic eBPF function support. But firewall rule should be investigated in order to reduce system load. * Disable firewall when using eBPF function. * Fix firewall settings. * chore: add translates * chore: fix error * Update openclash --------- Co-authored-by: sangyishuje1123 <[email protected]> Co-authored-by: vernesong <[email protected]>
1 parent 0212f55 commit 2c6edf7

File tree

7 files changed

+117
-28
lines changed

7 files changed

+117
-28
lines changed

luci-app-openclash/luasrc/model/cbi/openclash/config-overwrite.lua

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ bold_off = [[</strong>]]
1818
local op_mode = string.sub(luci.sys.exec('uci get openclash.config.operation_mode 2>/dev/null'),0,-2)
1919
if not op_mode then op_mode = "redir-host" end
2020
local lan_int_name = uci:get("openclash", "config", "lan_interface_name") or "0"
21+
22+
23+
24+
2125
local lan_ip
2226
if lan_int_name == "0" then
2327
lan_ip = SYS.exec("uci -q get network.lan.ipaddr |awk -F '/' '{print $1}' 2>/dev/null |tr -d '\n'")

luci-app-openclash/luasrc/model/cbi/openclash/settings.lua

+12
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,18 @@ o:value("direct", translate("Direct Proxy Mode"))
102102
o:value("script", translate("Script Proxy Mode (Tun Core Only)"))
103103
o.default = "rule"
104104

105+
-- eBPF support setting
106+
o = s:taboption("op_mode", ListValue, "ebpf_action_interface", translate("eBPF Action Interface"))
107+
o.description = translate("Select outbound interface for eBPF to apply traffic management").."<br>"..font_red..bold_on.."1."..translate("Warning! Highly experimental configs. Will disable default firewall traffic inbound").."<br>2."..translate("Needs kernel support for eBPF functionality. And it takes about 130MB memory to starts").."<br>3."..translate("Might improve direct connection performance").."<br>4."..translate("Only support redir-host-tun")..bold_off..font_off
108+
o:value("0", translate("Disable"))
109+
o.default = "0"
110+
local interfaces = SYS.exec("ls -l /sys/class/net/ 2>/dev/null |awk '{print $9}' 2>/dev/null")
111+
for interface in string.gmatch(interfaces, "%S+") do
112+
o:value(interface)
113+
end
114+
o:depends{en_mode = "redir-host-tun"}
115+
116+
105117
o = s:taboption("op_mode", Value, "delay_start", translate("Delay Start (s)"))
106118
o.description = translate("Delay Start On Boot")
107119
o.default = "0"

luci-app-openclash/po/zh-cn/openclash.zh-cn.po

+19-1
Original file line numberDiff line numberDiff line change
@@ -3556,4 +3556,22 @@ msgid "LAN Interface Name"
35563556
msgstr "LAN 接口名称"
35573557

35583558
msgid "Select LAN Interface Name"
3559-
msgstr "指定正确的 LAN 接口名称"
3559+
msgstr "指定正确的 LAN 接口名称"
3560+
3561+
msgid "Select outbound interface for eBPF to apply traffic management"
3562+
msgstr "为 eBPF 指定流量出站接口"
3563+
3564+
msgid "Warning! Highly experimental configs. Will disable default firewall traffic inbound"
3565+
msgstr "警告!高度实验性的配置。将禁用默认防火墙入站流量"
3566+
3567+
msgid "Needs kernel support for eBPF functionality. And it takes about 130MB memory to starts"
3568+
msgstr "需要内核支持 eBPF 功能。启动时需要大约 130MB 内存"
3569+
3570+
msgid "Might improve direct connection performance"
3571+
msgstr "可提高直连性能"
3572+
3573+
msgid "Only support redir-host-tun"
3574+
msgstr "仅支持 redir-host(TUN)模式"
3575+
3576+
msgid "eBPF Action Interface"
3577+
msgstr "eBPF 出站接口"

luci-app-openclash/root/etc/config/openclash

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ config openclash 'config'
2828
option servers_update '0'
2929
option log_level '0'
3030
option proxy_mode 'rule'
31+
option ebpf_action_interface '0'
3132
option intranet_allowed '1'
3233
option enable_udp_proxy '1'
3334
option disable_udp_quic '1'

luci-app-openclash/root/etc/init.d/openclash

+58-26
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ LOCK_FILE="/tmp/lock/openclash.lock"
2929
PROXY_FWMARK="0x162"
3030
PROXY_ROUTE_TABLE="0x162"
3131

32+
# Assume we have bpftool sets would set ebpf marker to 1
33+
KERNEL_EBPF_SUPPORT=$(bpftool version > /dev/null 2>&1 && echo '1' || echo '0')
34+
35+
if [[ "${KERNEL_EBPF_SUPPORT}" == "1" ]]; then
36+
# Enhanced capabilities
37+
capabilties="cap_sys_resource,cap_dac_override,cap_net_raw,cap_net_bind_service,cap_net_admin,cap_sys_ptrace,cap_sys_admin,CAP_PERFMON,cap_bpf"
38+
else
39+
# Regular capabilities
40+
capabilties="cap_sys_resource,cap_dac_override,cap_net_raw,cap_net_bind_service,cap_net_admin,cap_sys_ptrace,cap_sys_admin"
41+
fi
42+
43+
44+
3245
set_lock() {
3346
exec 888>"$LOCK_FILE" 2>/dev/null
3447
flock -x 888 2>/dev/null
@@ -793,7 +806,6 @@ start_run_core()
793806
chmod o+w /tmp/openclash.log 2>/dev/null
794807
chown nobody:nogroup /etc/openclash/core/* 2>/dev/null
795808
#使用nobody启动内核方便代理路由自身流量
796-
capabilties="cap_sys_resource,cap_dac_override,cap_net_raw,cap_net_bind_service,cap_net_admin,cap_sys_ptrace"
797809
capsh --caps="${capabilties}+eip" -- -c "capsh --user=nobody --addamb='${capabilties}' -- -c 'nohup $CLASH -d $CLASH_CONFIG -f \"$CONFIG_FILE\" >> $LOG_FILE 2>&1 &'" >> $LOG_FILE 2>&1
798810
fi
799811
uci -q set openclash.config.config_reload=1
@@ -1432,6 +1444,7 @@ if [ "$ipv6_enable" -eq 1 ]; then
14321444
esac
14331445
fi
14341446

1447+
if [[ "${ebpf_int_name}" == "0" ]]; then
14351448
#NFTABLES
14361449
if [ -n "$FW4" ]; then
14371450
LOG_OUT "Tip: Firewall4 was Detected, Use NFTABLE Rules..."
@@ -2060,10 +2073,7 @@ if [ -n "$FW4" ]; then
20602073
fi
20612074
nft add rule inet fw4 openclash_v6 meta nfproto {ipv6} tcp dport { 0-65535 } counter redirect to "$proxy_port"
20622075
nft 'add rule inet fw4 dstnat meta nfproto {ipv6} tcp dport { 0-65535 } counter jump openclash_v6'
2063-
fi
20642076

2065-
#tproxy not support output chain
2066-
if [ "$ipv6_mode" -eq 0 ] || [ "$ipv6_mode" -eq 1 ]; then
20672077
if [ "$router_self_proxy" = "1" ]; then
20682078
nft 'add chain inet fw4 openclash_output_v6'
20692079
nft 'flush chain inet fw4 openclash_output_v6'
@@ -2081,12 +2091,18 @@ if [ -n "$FW4" ]; then
20812091
nft 'add rule inet fw4 openclash_output_v6 skuid != 65534 ip6 daddr @china_ip6_route counter return'
20822092
fi
20832093
fi
2084-
nft add rule inet fw4 openclash_output_v6 meta nfproto {ipv6} skuid != 65534 tcp dport { 0-65535 } counter redirect to "$proxy_port"
2094+
2095+
if [ "$ipv6_mode" -eq 2 ]; then
2096+
nft add rule inet fw4 openclash_output_v6 meta nfproto {ipv6} skuid != 65534 tcp dport { 0-65535 } mark set "$PROXY_FWMARK" counter
2097+
elif [ "$ipv6_mode" -eq 0 ]; then
2098+
nft add rule inet fw4 openclash_output_v6 meta nfproto {ipv6} skuid != 65534 tcp dport { 0-65535 } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash TCP Tproxy\"
2099+
fi
2100+
20852101
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
2086-
nft 'add rule inet fw4 nat_output meta nfproto {ipv6} counter jump openclash_output_v6'
2102+
nft 'add rule inet fw4 nat_output meta nfproto {ipv6} ip protocol tcp counter jump openclash_output_v6'
20872103
fi
20882104
fi
2089-
2105+
20902106
if [ "$enable_v6_udp_proxy" -eq 1 ] || [ "$ipv6_mode" -eq 0 ] || [ "$ipv6_mode" -eq 2 ]; then
20912107
nft 'add chain inet fw4 openclash_mangle_v6'
20922108
nft 'flush chain inet fw4 openclash_mangle_v6'
@@ -2127,26 +2143,28 @@ if [ -n "$FW4" ]; then
21272143
fi
21282144

21292145
if [ "$router_self_proxy" = "1" ]; then
2130-
if [ "$ipv6_mode" -eq 2 ]; then
2131-
nft 'add chain inet fw4 openclash_mangle_output_v6'
2132-
nft 'flush chain inet fw4 openclash_mangle_output_v6'
2133-
nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 daddr @localnetwork6 counter return'
2134-
nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 saddr @localnetwork6 meta nfproto {ipv6} sport @lan_ac_black_ports counter return'
2135-
nft 'add rule inet fw4 openclash_mangle_output_v6 skuid != 65534 ip6 daddr @wan_ac_black_ipv6s counter return'
2136-
if [ "$en_mode" = "redir-host" ]; then
2137-
nft 'add rule inet fw4 openclash_mangle_output_v6 meta nfproto {ipv6} th dport != @common_ports skuid != 65534 counter return'
2138-
fi
2146+
nft 'add chain inet fw4 openclash_mangle_output_v6'
2147+
nft 'flush chain inet fw4 openclash_mangle_output_v6'
2148+
nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 daddr @localnetwork6 counter return'
2149+
nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 saddr @localnetwork6 meta nfproto {ipv6} sport @lan_ac_black_ports counter return'
2150+
nft 'add rule inet fw4 openclash_mangle_output_v6 skuid != 65534 ip6 daddr @wan_ac_black_ipv6s counter return'
2151+
if [ "$en_mode" = "redir-host" ]; then
2152+
nft 'add rule inet fw4 openclash_mangle_output_v6 meta nfproto {ipv6} th dport != @common_ports skuid != 65534 counter return'
2153+
fi
21392154

2140-
if [ "$china_ip6_route" = "1" ]; then
2141-
if [ "$enable_redirect_dns" != "2" ]; then
2142-
nft 'add rule inet fw4 openclash_mangle_output_v6 skuid != 65534 ip6 daddr @china_ip6_route ip6 daddr != @china_ip6_route_pass counter return'
2143-
else
2144-
nft 'add rule inet fw4 openclash_mangle_output_v6 skuid != 65534 ip6 daddr @china_ip6_route counter return'
2145-
fi
2155+
if [ "$china_ip6_route" = "1" ]; then
2156+
if [ "$enable_redirect_dns" != "2" ]; then
2157+
nft 'add rule inet fw4 openclash_mangle_output_v6 skuid != 65534 ip6 daddr @china_ip6_route ip6 daddr != @china_ip6_route_pass counter return'
2158+
else
2159+
nft 'add rule inet fw4 openclash_mangle_output_v6 skuid != 65534 ip6 daddr @china_ip6_route counter return'
21462160
fi
2161+
fi
2162+
if [ "$ipv6_mode" -eq 2 ]; then
21472163
nft add rule inet fw4 openclash_mangle_output_v6 meta nfproto {ipv6} skuid != 65534 tcp dport { 0-65535 } mark set "$PROXY_FWMARK" counter
2148-
nft 'add rule inet fw4 mangle_output meta nfproto {ipv6} counter jump openclash_mangle_output_v6'
2164+
elif [ "$ipv6_mode" -eq 0 ]; then
2165+
nft add rule inet fw4 openclash_mangle_output_v6 meta nfproto {ipv6} skuid != 65534 tcp dport { 0-65535 } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash TCP Tproxy\"
21492166
fi
2167+
nft 'add rule inet fw4 mangle_output meta nfproto {ipv6} counter jump openclash_mangle_output_v6'
21502168
fi
21512169
fi
21522170

@@ -2912,8 +2930,8 @@ if [ -z "$FW4" ]; then
29122930
ip6tables -t mangle -A openclash -p tcp -j MARK --set-mark "$PROXY_FWMARK"
29132931
fi
29142932

2915-
if [ "$router_self_proxy" = "1" ]; then
2916-
if [ "$ipv6_mode" -eq 2 ]; then
2933+
if [ "$ipv6_mode" -eq 2 ]; then
2934+
if [ "$router_self_proxy" = "1" ]; then
29172935
ip6tables -t mangle -N openclash_output
29182936
ip6tables -t mangle -F openclash_output
29192937
ip6tables -t mangle -A openclash_output -m set --match-set localnetwork6 dst -j RETURN
@@ -3021,6 +3039,10 @@ if [ -z "$FW4" ]; then
30213039
fi
30223040
fi
30233041
fi 2>/dev/null
3042+
else
3043+
LOG_OUT "Escaping firewall settings due to eBPF interface: ${ebpf_int_name}..."
3044+
3045+
fi
30243046

30253047
#端口转发
30263048
LOG_OUT "Tip: Start Add Port Bypassing Rules For Firewall Redirect and Firewall Rules..."
@@ -3148,11 +3170,21 @@ get_config()
31483170
fi
31493171
[ -z "$fakeip_range" ] && fakeip_range="198.18.0.1/16"
31503172
lan_interface_name=$(uci -q get openclash.config.lan_interface_name || echo "0")
3173+
31513174
if [ "$lan_interface_name" = "0" ]; then
31523175
lan_ip=$(uci -q get network.lan.ipaddr |awk -F '/' '{print $1}' 2>/dev/null || ip address show $(uci -q -p /tmp/state get network.lan.ifname || uci -q -p /tmp/state get network.lan.device) | grep -w "inet" 2>/dev/null |grep -Eo 'inet [0-9\.]+' | awk '{print $2}' || ip addr show 2>/dev/null | grep -w 'inet' | grep 'global' | grep 'brd' | grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -n 1)
31533176
else
31543177
lan_ip=$(ip address show $lan_interface_name | grep -w "inet" 2>/dev/null |grep -Eo 'inet [0-9\.]+' | awk '{print $2}')
31553178
fi
3179+
3180+
# eBPF configuration
3181+
3182+
if [[ "$en_mode" == "redir-host" && "$en_mode_tun" == "1" && "${KERNEL_EBPF_SUPPORT}" == "1" ]]; then
3183+
ebpf_int_name=$(uci -q get openclash.config.ebpf_action_interface || echo "0")
3184+
else
3185+
ebpf_int_name=$(echo "0")
3186+
fi
3187+
31563188
wan_ip4s=$(/usr/share/openclash/openclash_get_network.lua "wanip" 2>/dev/null)
31573189
wan_ip6s=$(ifconfig | grep 'inet6 addr' | awk '{print $3}' 2>/dev/null)
31583190
disable_masq_cache=$(uci -q get openclash.config.disable_masq_cache)
@@ -3220,7 +3252,7 @@ start()
32203252
if ! $quick_start; then
32213253
LOG_OUT "Step 3: Modify The Config File..."
32223254
config_check
3223-
/usr/share/openclash/yml_change.sh 2>/dev/null "$en_mode" "$da_password" "$cn_port" "$proxy_port" "$TMP_CONFIG_FILE" "$ipv6_enable" "$http_port" "$socks_port" "$log_level" "$proxy_mode" "$en_mode_tun" "$stack_type" "$dns_port" "$mixed_port" "$tproxy_port" "$ipv6_dns" "$store_fakeip" "$stream_domains_prefetch" "$enable_meta_core" "$enable_meta_sniffer" "$enable_geoip_dat" "$geodata_loader" "$enable_meta_sniffer_custom" "$interface_name" "$enable_tcp_concurrent" "$core_type" "$append_default_dns" "$enable_meta_sniffer_pure_ip" "$find_process_mode" "$fakeip_range" "$global_client_fingerprint" "$ipv6_mode" "$stack_type_v6" "$enable_unified_delay" "$keep_alive_interval" "$proxy_dns_group"
3255+
/usr/share/openclash/yml_change.sh 2>/dev/null "$en_mode" "$da_password" "$cn_port" "$proxy_port" "$TMP_CONFIG_FILE" "$ipv6_enable" "$http_port" "$socks_port" "$log_level" "$proxy_mode" "$en_mode_tun" "$stack_type" "$dns_port" "$mixed_port" "$tproxy_port" "$ipv6_dns" "$store_fakeip" "$stream_domains_prefetch" "$enable_meta_core" "$enable_meta_sniffer" "$enable_geoip_dat" "$geodata_loader" "$enable_meta_sniffer_custom" "$interface_name" "$enable_tcp_concurrent" "$core_type" "$append_default_dns" "$enable_meta_sniffer_pure_ip" "$find_process_mode" "$fakeip_range" "$global_client_fingerprint" "$ipv6_mode" "$stack_type_v6" "$enable_unified_delay" "$keep_alive_interval" "$proxy_dns_group" "$ebpf_int_name"
32243256
/usr/share/openclash/yml_rules_change.sh 2>/dev/null "$rule_source" "$enable_custom_clash_rules" "$TMP_CONFIG_FILE" "$enable_rule_proxy" "$CONFIG_NAME" "$router_self_proxy" "$lan_ip" "$proxy_port" "$tproxy_port" "$enable_meta_core" "$enable_redirect_dns" "$fakeip_range" "$en_mode"
32253257
/usr/share/openclash/openclash_custom_domain_dns.sh >/dev/null 2>&1
32263258
#Custom overwrite

luci-app-openclash/root/usr/share/openclash/openclash_watchdog.sh

+4-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ STREAM_DOMAINS_PREFETCH=1
3434
STREAM_AUTO_SELECT=1
3535
FW4=$(command -v fw4)
3636

37+
# Enhanced capbilities
38+
capabilties="cap_sys_resource,cap_dac_override,cap_net_raw,cap_net_bind_service,cap_net_admin,cap_sys_ptrace,CAP_PERFMON,cap_bpf,cap_sys_admin"
39+
3740

3841
check_dnsmasq() {
3942
if [ -z "$(echo "$en_mode" |grep "redir-host")" ] && [ "$china_ip_route" -eq 1 ] && [ "$enable_redirect_dns" != "2" ]; then
@@ -181,7 +184,7 @@ if [ "$enable" -eq 1 ]; then
181184
chmod o+w /tmp/openclash.log 2>/dev/null
182185
chmod o+w /etc/openclash/cache.db 2>/dev/null
183186
chown nobody:nogroup /etc/openclash/core/* 2>/dev/null
184-
capabilties="cap_sys_resource,cap_dac_override,cap_net_raw,cap_net_bind_service,cap_net_admin,cap_sys_ptrace"
187+
185188
capsh --caps="${capabilties}+eip" -- -c "capsh --user=nobody --addamb='${capabilties}' -- -c 'nohup $CLASH -d $CLASH_CONFIG -f \"$CONFIG_FILE\" >> $LOG_FILE 2>&1 &'" >> $LOG_FILE 2>&1
186189
sleep 3
187190
if [ "$core_type" == "TUN" ] || [ "$core_type" == "Meta" ]; then

luci-app-openclash/root/usr/share/openclash/yml_change.sh

+19
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ enable_meta_core=$(uci -q get openclash.config.enable_meta_core || echo 0)
1616
china_ip_route=$(uci -q get openclash.config.china_ip_route || echo 0)
1717
proxy_dns_group=${36}
1818

19+
ebpf_action_interface=${37}
20+
21+
KERNEL_EBPF_SUPPORT=$(bpftool version > /dev/null 2>&1 && echo '1' || echo '0')
22+
1923
lan_block_google_dns=$(uci -q get openclash.config.lan_block_google_dns_ips || uci -q get openclash.config.lan_block_google_dns_macs || echo 0)
2024

2125
if [ -n "$(ruby_read "$5" "['tun']")" ]; then
@@ -506,9 +510,24 @@ Thread.new{
506510
if ${17} == 1 then
507511
Value['profile']['store-fake-ip']=true;
508512
end;
513+
509514
if Value.key?('ebpf') then
510515
Value.delete('ebpf');
511516
end;
517+
518+
if ${en_mode_tun} == 1 and '${1}' == 'redir-host' and '${ebpf_action_interface}' != '0' then
519+
520+
if ${KERNEL_EBPF_SUPPORT} == 1 then
521+
Value_2={'redirect-to-tun'=>['${ebpf_action_interface}']};
522+
Value['ebpf']=Value_2;
523+
524+
else
525+
puts '${LOGTIME} : intend to enable ebpf interface ${ebpf_action_interface}, but no kernel support found. Ignoring...';
526+
end;
527+
end;
528+
529+
530+
512531
if Value.key?('routing-mark') then
513532
Value.delete('routing-mark');
514533
end;

0 commit comments

Comments
 (0)