Last active
April 20, 2025 13:14
-
-
Save Bryan2333/2b15adb8859440358a6e07edc14bd987 to your computer and use it in GitHub Desktop.
tproxy脚本
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
#!/bin/bash | |
if [[ "$EUID" -ne 0 ]] | |
then | |
echo "This script must be run as root!" | |
exit 1 | |
fi | |
SCRIPT_NAME="$(basename "$0")" | |
## 网卡 | |
INTERFACE=$(ip route show default | awk '/default/ {print $5}') | |
INTERFACE="${INTERFACE:-wlan0}" | |
## TProxy流量标记 | |
TPROXY_MARK="0x1" | |
## TProxy路由表ID | |
TPROXY_ROUTE_TABLE="200" | |
## 绕开的用户 | |
BYPASS_USERS=('sing-box' 'naiveproxy') | |
## sing-box的透明代理端口 | |
TPROXY_PORT="7894" | |
## 需要代理的协议类型 | |
TPROXY_L4PROTO="{tcp, udp}" | |
function wait_online() { | |
until ping -c 1 baidu.com &> /dev/null | |
do | |
sleep 1 | |
done | |
} | |
function start_singbox() { | |
systemctl is-active --quiet sing-box || systemctl start sing-box | |
} | |
function clear_firewall_rules() { | |
{ | |
ip rule del fwmark "$TPROXY_MARK" table "$TPROXY_ROUTE_TABLE" | |
ip route del local default dev "$INTERFACE" table "$TPROXY_ROUTE_TABLE" | |
ip -6 rule del fwmark "$TPROXY_MARK" table "$TPROXY_ROUTE_TABLE" | |
ip -6 route del local default dev "$INTERFACE" table "$TPROXY_ROUTE_TABLE" | |
nft delete table inet singbox | |
} > /dev/null 2>&1 | |
} | |
function wait_for_ipv6_async() { | |
( | |
local retries=5 | |
while ((retries-- > 0)) | |
do | |
mapfile -t PUBLIC_IPv6 < <(ip addr | awk '/inet6 / {print $2}' | cut -d '/' -f1 | grep -vE '^::1|^fe80::') | |
if (( ${#PUBLIC_IPv6[@]} > 0 )) | |
then | |
for ip in "${PUBLIC_IPv6[@]}" | |
do | |
nft add rule inet singbox tp_rule ip6 daddr \["$ip"\] meta l4proto "$TPROXY_L4PROTO" th dport != 53 accept comment \"绕开本机 IPv6 公网地址\" | |
done | |
break | |
fi | |
sleep 0.5 | |
done | |
) & | |
} | |
function set_firewall_rules() { | |
{ | |
ip rule add fwmark "$TPROXY_MARK" lookup "$TPROXY_ROUTE_TABLE" | |
ip route add local default dev "$INTERFACE" table "$TPROXY_ROUTE_TABLE" | |
ip -6 rule add fwmark "$TPROXY_MARK" lookup "$TPROXY_ROUTE_TABLE" | |
ip -6 route add local default dev "$INTERFACE" table "$TPROXY_ROUTE_TABLE" | |
} > /dev/null 2>&1 | |
nft -f - <<EOF | |
table inet singbox { | |
## 保留IPv4地址 | |
set BYPASS_IPv4 { | |
type ipv4_addr | |
flags interval | |
auto-merge | |
elements = { | |
0.0.0.0/8, | |
10.0.0.0/8, | |
100.64.0.0/10, | |
127.0.0.0/8, | |
169.254.0.0/16, | |
172.16.0.0/12, | |
192.168.0.0/16, | |
224.0.0.0/4, | |
240.0.0.0/4, | |
255.255.255.255 | |
} | |
} | |
## 保留IPv6地址 | |
set BYPASS_IPv6 { | |
type ipv6_addr | |
flags interval | |
auto-merge | |
elements = { | |
::/128, | |
::1/128, | |
64:ff9b::/96, | |
100::/64, | |
2001::/32, | |
2001:20::/28, | |
fe80::/10, | |
ff00::/8 | |
} | |
} | |
chain tp_rule { | |
ip daddr @BYPASS_IPv4 meta l4proto $TPROXY_L4PROTO th dport != 53 accept comment "绕开私有IP" | |
ip6 daddr @BYPASS_IPv6 meta l4proto $TPROXY_L4PROTO th dport != 53 accept comment "绕开私有IP" | |
udp dport 123 accept comment "绕开NTP流量" | |
udp dport { netbios-ns, netbios-dgm, netbios-ssn } accept comment "绕开NBNS流量" | |
udp dport mdns accept comment "绕开mdns流量" | |
udp dport { 443, 8443 } drop comment "屏蔽Quic" | |
} | |
chain tp_pre { | |
type filter hook prerouting priority filter; policy accept; | |
fib daddr type local meta l4proto $TPROXY_L4PROTO th dport $TPROXY_PORT reject with icmpx type host-unreachable comment "直接访问tproxy端口拒绝, 防止回环" | |
jump tp_rule | |
meta l4proto $TPROXY_L4PROTO socket transparent 1 mark set $TPROXY_MARK | |
socket transparent 0 socket wildcard 0 return comment "跳过已经由TProxy接管的流量" | |
meta l4proto $TPROXY_L4PROTO meta mark set $TPROXY_MARK tproxy ip to 127.0.0.1:$TPROXY_PORT accept comment "转发给sing-box" | |
meta l4proto $TPROXY_L4PROTO meta mark set $TPROXY_MARK tproxy ip6 to [::1]:$TPROXY_PORT accept comment "转发给sing-box" | |
} | |
chain tp_out { | |
type route hook output priority filter; policy accept; | |
meta skuid {$(id -u "${BYPASS_USERS[@]}" | paste -sd ',')} accept comment "绕开naive和sing-box发出的连接" | |
jump tp_rule | |
meta l4proto $TPROXY_L4PROTO meta mark set $TPROXY_MARK accept comment "重路由到prerouting" | |
} | |
} | |
EOF | |
wait_for_ipv6_async | |
} | |
function start_tproxy() { | |
clear_firewall_rules | |
wait_online | |
start_singbox | |
set_firewall_rules | |
} | |
function stop_tproxy() { | |
clear_firewall_rules | |
} | |
function main() { | |
case "$1" in | |
"start"|"restart") | |
start_tproxy | |
;; | |
"stop") | |
stop_tproxy | |
;; | |
*) | |
echo "Usage: singbox-tproxy [start|restart|stop]" | |
exit 1 | |
;; | |
esac | |
} | |
if [[ "$SCRIPT_NAME" == "singbox-tproxy" ]] | |
then | |
main "$@" | |
elif [[ "$SCRIPT_NAME" == "tproxy-dispatcher" ]] | |
then | |
case "$2" in | |
"up") main start ;; | |
"down") main stop ;; | |
esac | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment