mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-11-04 03:43:56 +08:00
update 2026-10-07 18:47:42
This commit is contained in:
1 parent
617f7ca2a6
commit
bd061545ed
4832 files changed
+1693456
No files matched your search
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"luci-app-ssr-plus": {
|
||||
"description": "Grant UCI access for luci-app-ssr-plus",
|
||||
"read": {
|
||||
"file": {
|
||||
"/etc/ssrplus/*": [ "read" ]
|
||||
},
|
||||
"uci": ["shadowsocksr"]
|
||||
},
|
||||
"write": {
|
||||
"file": {
|
||||
"/etc/ssrplus/*": [ "write" ]
|
||||
},
|
||||
"uci": ["shadowsocksr"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 215 KiB |
@@ -0,0 +1,65 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $IPKG_INSTROOT/etc/init.d/shadowsocksr
|
||||
|
||||
check_run_environment
|
||||
|
||||
# 设置 china_ip 变量并检查文件是否存在
|
||||
china_ip="${1:-${china_ip:-/etc/ssrplus/china_ssr.txt}}"
|
||||
[ -f "$china_ip" ] || exit 1
|
||||
|
||||
if [ "$2" = "6" ]; then
|
||||
[ "$USE_TABLES" = "nftables" ] || exit 0
|
||||
nft list set inet ss_spec china6 >/dev/null 2>&1 || exit 0
|
||||
{
|
||||
echo 'flush set inet ss_spec china6'
|
||||
echo 'add element inet ss_spec china6 {'
|
||||
sed -e 's/#.*//' -e '/^[[:space:]]*$/d' -e 's/$/,/' "$china_ip"
|
||||
echo '}'
|
||||
} | nft -f -
|
||||
exit $?
|
||||
fi
|
||||
|
||||
case "$USE_TABLES" in
|
||||
nftables)
|
||||
skip_inet="${SKIP_INET:-0}"
|
||||
|
||||
case "$skip_inet" in
|
||||
1)
|
||||
{
|
||||
# ss_spec / inet (仅在表和 set 存在时添加)
|
||||
if nft list set inet ss_spec china >/dev/null 2>&1; then
|
||||
echo "add element inet ss_spec china {"
|
||||
grep -vE '^\s*#|^\s*$' "$china_ip" | sed 's/^/ /;s/$/,/'
|
||||
echo "}"
|
||||
fi
|
||||
} | nft -f - || exit 1
|
||||
;;
|
||||
2)
|
||||
{
|
||||
# ss_spec_mangle / ip (仅在表和 set 存在时添加)
|
||||
if nft list set ip ss_spec_mangle china >/dev/null 2>&1; then
|
||||
echo "add element ip ss_spec_mangle china {"
|
||||
grep -vE '^\s*#|^\s*$' "$china_ip" | sed 's/^/ /;s/$/,/'
|
||||
echo "}"
|
||||
fi
|
||||
} | nft -f - || exit 1
|
||||
;;
|
||||
*)
|
||||
echolog "chinaipset: invalid SKIP_INET=$skip_inet"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
iptables)
|
||||
ipset -! flush china 2>/dev/null
|
||||
ipset -! -R <<-EOF || exit 1
|
||||
create china hash:net
|
||||
$(grep -vE '^\s*#|^\s*$' "$china_ip" | sed 's/^/add china /')
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
echolog "ERROR: No supported firewall backend detected"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
File diff suppressed because it is too large.
Load diff
+1305
File diff suppressed because it is too large.
Load diff
+149
@@ -0,0 +1,149 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $IPKG_INSTROOT/etc/init.d/shadowsocksr
|
||||
|
||||
check_run_environment
|
||||
|
||||
case "$USE_TABLES" in
|
||||
nftables)
|
||||
nft_support=1
|
||||
echolog "gfw2ipset: Using nftables"
|
||||
;;
|
||||
iptables)
|
||||
nft_support=0
|
||||
echolog "gfw2ipset: Using iptables"
|
||||
;;
|
||||
*)
|
||||
echolog "ERROR: No supported firewall backend detected"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
mkdir -p $TMP_DNSMASQ_PATH
|
||||
|
||||
run_mode=$(normalize_run_mode)
|
||||
gfw_set="4#inet#ss_spec#gfwlist"
|
||||
black_set="4#inet#ss_spec#blacklist"
|
||||
white_set="4#inet#ss_spec#whitelist_domain"
|
||||
if ipv6_enabled; then
|
||||
gfw_set="$gfw_set,6#inet#ss_spec#gfwlist6"
|
||||
black_set="$black_set,6#inet#ss_spec#blacklist6"
|
||||
white_set="$white_set,6#inet#ss_spec#whitelist_domain6"
|
||||
fi
|
||||
|
||||
cp -rf /etc/ssrplus/gfw_list.conf $TMP_DNSMASQ_PATH/
|
||||
cp -rf /etc/ssrplus/gfw_base.conf $TMP_DNSMASQ_PATH/
|
||||
|
||||
for conf_file in gfw_base.conf gfw_list.conf; do
|
||||
conf="$TMP_DNSMASQ_PATH/$conf_file"
|
||||
[ -f "$conf" ] || continue
|
||||
|
||||
if [ "$run_mode" = "gfw" ]; then
|
||||
if [ "$nft_support" = "1" ]; then
|
||||
# gfw + nft:ipset → nftset
|
||||
sed -i "s|^ipset=/\\([^/]*\\)/gfwlist$|nftset=/\\1/$gfw_set|" "$conf"
|
||||
fi
|
||||
else
|
||||
# 非 gfw:无条件清理所有分流引用
|
||||
sed -i '/^[[:space:]]*\(ipset=\|nftset=\)/d' "$conf"
|
||||
fi
|
||||
done
|
||||
|
||||
# 此处使用 for 方式读取 防止 /etc/ssrplus/ 目录下的 black.list white.list deny.list 等2个或多个文件一行中存在空格 比如:# abc.com 而丢失:server
|
||||
# Optimize: Batch filter using grep
|
||||
for list_file in /etc/ssrplus/black.list /etc/ssrplus/white.list /etc/ssrplus/deny.list; do
|
||||
if [ -s "$list_file" ]; then
|
||||
# 清理注释和空行
|
||||
grep -vE '^\s*#|^\s*$' "$list_file" | sed 's/\r//g' > "${list_file}.clean"
|
||||
if [ -s "${list_file}.clean" ]; then
|
||||
for target_file in "$TMP_DNSMASQ_PATH/gfw_list.conf" "$TMP_DNSMASQ_PATH/gfw_base.conf"; do
|
||||
[ -f "$target_file" ] || continue
|
||||
tmp_file="${target_file}.tmp"
|
||||
awk -v list="${list_file}.clean" '
|
||||
BEGIN {
|
||||
while ((getline line < list) > 0) {
|
||||
gsub(/\r/, "", line)
|
||||
if (line != "") {
|
||||
domain[line] = 1
|
||||
# 同时支持 *.domain
|
||||
domain["*." line] = 1
|
||||
}
|
||||
}
|
||||
close(list)
|
||||
}
|
||||
{
|
||||
# 提取 server=/domain/xxx
|
||||
if ($0 ~ /^server=\//) {
|
||||
split($0, m, "/")
|
||||
if (m[2] in domain) next
|
||||
}
|
||||
# 提取 ipset=/domain/xxx
|
||||
if ($0 ~ /^(ipset|nftset)=\//) {
|
||||
split($0, m, "/")
|
||||
if (m[2] in domain) next
|
||||
}
|
||||
print
|
||||
}
|
||||
' "$target_file" > "$tmp_file"
|
||||
mv "$tmp_file" "$target_file"
|
||||
done
|
||||
fi
|
||||
rm -f "${list_file}.clean"
|
||||
fi
|
||||
done
|
||||
|
||||
# 此处直接使用 cat 因为有 sed '/#/d' 删除了 数据
|
||||
if [ "$nft_support" = "1" ]; then
|
||||
sed -e 's/[[:space:]]*#.*$//' -e '/^[[:space:]]*$/d' -e "s/.*/server=\/&\/127.0.0.1#$dns_port\nnftset=\/&\/$black_set/" /etc/ssrplus/black.list > "$TMP_DNSMASQ_PATH/blacklist_forward.conf"
|
||||
sed -e 's/[[:space:]]*#.*$//' -e '/^[[:space:]]*$/d' -e "s/.*/nftset=\/&\/$white_set/" /etc/ssrplus/white.list > "$TMP_DNSMASQ_PATH/whitelist_forward.conf"
|
||||
elif [ "$nft_support" = "0" ]; then
|
||||
sed -e 's/[[:space:]]*#.*$//' -e '/^[[:space:]]*$/d' -e "s/.*/server=\/&\/127.0.0.1#$dns_port\nipset=\/&\/blacklist/" /etc/ssrplus/black.list > "$TMP_DNSMASQ_PATH/blacklist_forward.conf"
|
||||
sed -e 's/[[:space:]]*#.*$//' -e '/^[[:space:]]*$/d' -e "s/.*/ipset=\/&\/whitelist/" /etc/ssrplus/white.list > "$TMP_DNSMASQ_PATH/whitelist_forward.conf"
|
||||
fi
|
||||
|
||||
sed -e 's/[[:space:]]*#.*$//' -e '/^[[:space:]]*$/d' -e "s/.*/address=\/&\//" /etc/ssrplus/deny.list > "$TMP_DNSMASQ_PATH/denylist.conf"
|
||||
|
||||
if [ "$(uci_get_by_type global adblock 0)" == "1" ]; then
|
||||
cp -f /etc/ssrplus/ad.conf "$TMP_DNSMASQ_PATH/"
|
||||
if [ -f "$TMP_DNSMASQ_PATH/ad.conf" ]; then
|
||||
for list_file in /etc/ssrplus/black.list /etc/ssrplus/white.list /etc/ssrplus/deny.list; do
|
||||
if [ -s "$list_file" ]; then
|
||||
# 清理注释 & 空行
|
||||
grep -vE '^\s*#|^\s*$' "$list_file" | sed 's/\r//g' > "${list_file}.clean"
|
||||
if [ -s "${list_file}.clean" ]; then
|
||||
tmp_file="$TMP_DNSMASQ_PATH/ad.conf.tmp"
|
||||
awk -v list="${list_file}.clean" '
|
||||
BEGIN {
|
||||
while ((getline line < list) > 0) {
|
||||
gsub(/\r/, "", line)
|
||||
if (line != "") {
|
||||
domain[line] = 1
|
||||
# 支持泛域名
|
||||
domain["*." line] = 1
|
||||
}
|
||||
}
|
||||
close(list)
|
||||
}
|
||||
{
|
||||
keep = 1
|
||||
# 精确匹配 server=/domain/
|
||||
if ($0 ~ /^server=\//) {
|
||||
split($0, m, "/")
|
||||
if (m[2] in domain) keep = 0
|
||||
}
|
||||
# 精确匹配 ipset=/domain/
|
||||
if ($0 ~ /^(ipset|nftset)=\//) {
|
||||
split($0, m, "/")
|
||||
if (m[2] in domain) keep = 0
|
||||
}
|
||||
if (keep) print
|
||||
}
|
||||
' "$TMP_DNSMASQ_PATH/ad.conf" > "$tmp_file"
|
||||
mv "$tmp_file" "$TMP_DNSMASQ_PATH/ad.conf"
|
||||
fi
|
||||
rm -f "${list_file}.clean"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
else
|
||||
rm -f "$TMP_DNSMASQ_PATH/ad.conf"
|
||||
fi
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
#!/bin/sh
|
||||
# IPv6 nftables rules, sourced by ssr-rules. DNS sets are shared by TCP and UDP.
|
||||
|
||||
# br_netfilter can run inet prerouting before ipv6_rcv() orphans the skb,
|
||||
# losing the TPROXY socket on bridged LAN ingress. Routed fw4 filtering still
|
||||
# runs when this bridge-only compatibility hook is disabled.
|
||||
ipv6_bridge_nf() {
|
||||
local knob=/proc/sys/net/bridge/bridge-nf-call-ip6tables
|
||||
local saved=/var/run/ssrplus-ipv6-bridge-nf
|
||||
[ -f "$knob" ] || return 0
|
||||
if [ "$1" = "start" ]; then
|
||||
[ -f "$saved" ] || cat "$knob" > "$saved"
|
||||
echo 0 > "$knob"
|
||||
elif [ -f "$saved" ]; then
|
||||
[ "$(cat "$knob")" != "0" ] || cat "$saved" > "$knob"
|
||||
rm -f "$saved"
|
||||
fi
|
||||
}
|
||||
|
||||
ipv6_policy_route() {
|
||||
ipv6_bridge_nf start || return 1
|
||||
ip -6 rule show | grep -q "fwmark ${FWMARK}.*lookup 999" ||
|
||||
ip -6 rule add fwmark "$FWMARK" table 999 priority 999 || return 1
|
||||
ip -6 route replace local ::/0 dev lo table 999
|
||||
}
|
||||
|
||||
ipv6_policy_cleanup() {
|
||||
ipv6_bridge_nf stop
|
||||
while ip -6 rule del fwmark "$FWMARK" table 999 2>/dev/null; do :; done
|
||||
ip -6 route del local ::/0 dev lo table 999 2>/dev/null
|
||||
return 0
|
||||
}
|
||||
|
||||
ipv6_set_elements() {
|
||||
local setname="$1" address
|
||||
shift
|
||||
for address in "$@"; do
|
||||
case "$address" in
|
||||
*:*) printf 'add element inet ss_spec %s { %s }\n' "$setname" "$address" ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
ipv6_policy_rules() {
|
||||
local chain="$1" target="$2"
|
||||
cat <<-RULES
|
||||
add rule inet ss_spec $chain meta mark 255 return
|
||||
add rule inet ss_spec $chain fib daddr type local return
|
||||
add rule inet ss_spec $chain ip6 daddr @local6 return
|
||||
add rule inet ss_spec $chain ip6 daddr @servers6 return
|
||||
add rule inet ss_spec $chain ip6 daddr @blacklist6 goto $target
|
||||
add rule inet ss_spec $chain ip6 daddr @whitelist6 return
|
||||
add rule inet ss_spec $chain ip6 daddr @whitelist_domain6 return
|
||||
add rule inet ss_spec $chain ip6 saddr @fplan6 goto $target
|
||||
add rule inet ss_spec $chain ip6 saddr @bplan6 return
|
||||
RULES
|
||||
case "$RUNMODE" in
|
||||
gfw)
|
||||
echo "add rule inet ss_spec $chain ip6 daddr @china6 return"
|
||||
echo "add rule inet ss_spec $chain ip6 daddr @gfwlist6 goto $target"
|
||||
echo "add rule inet ss_spec $chain ip6 saddr @gmlan6 goto $target"
|
||||
;;
|
||||
router)
|
||||
echo "add rule inet ss_spec $chain ip6 daddr @china6 return"
|
||||
echo "add rule inet ss_spec $chain goto $target"
|
||||
;;
|
||||
all) echo "add rule inet ss_spec $chain goto $target" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
ipv6_lan_hook() {
|
||||
local chain="$1" proto="$2" target="$3" match="" name ifname
|
||||
case "${LAN_AC_IP%%${LAN_AC_IP#?}}" in
|
||||
w|W) match="ip6 saddr @lan_ac6" ;;
|
||||
b|B) match="ip6 saddr != @lan_ac6" ;;
|
||||
esac
|
||||
if [ -z "$Interface" ]; then
|
||||
echo "add rule inet ss_spec $chain meta nfproto ipv6 meta l4proto $proto $match jump $target"
|
||||
else
|
||||
for name in $Interface; do
|
||||
ifname=$(uci -P /var/state -q get "network.$name.ifname")
|
||||
[ -n "$ifname" ] || ifname=$(uci -P /var/state -q get "network.$name.device")
|
||||
[ -n "$ifname" ] || continue
|
||||
echo "add rule inet ss_spec $chain iifname \"$ifname\" meta nfproto ipv6 meta l4proto $proto $match jump $target"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
ipv6_rules_generate() {
|
||||
local setname sid host ports
|
||||
for setname in china6 whitelist6 blacklist6 fplan6 bplan6 gmlan6 lan_ac6 servers6; do
|
||||
echo "add set inet ss_spec $setname { type ipv6_addr; flags interval; auto-merge; }"
|
||||
done
|
||||
for setname in gfwlist6 whitelist_domain6; do
|
||||
echo "add set inet ss_spec $setname { type ipv6_addr; }"
|
||||
done
|
||||
cat <<-'RULES'
|
||||
add set inet ss_spec local6 { type ipv6_addr; flags interval; auto-merge; elements = { ::/128, ::1/128, ::ffff:0:0/96, 64:ff9b:1::/48, 100::/64, 2001:db8::/32, fc00::/7, fe80::/10, ff00::/8 }; }
|
||||
RULES
|
||||
if [ -s /etc/ssrplus/china6_ssr.txt ]; then
|
||||
echo 'add element inet ss_spec china6 {'
|
||||
sed -e 's/#.*//' -e '/^[[:space:]]*$/d' -e 's/$/,/' /etc/ssrplus/china6_ssr.txt
|
||||
echo '}'
|
||||
fi
|
||||
ipv6_set_elements whitelist6 $WAN_BP_IP
|
||||
ipv6_set_elements blacklist6 $WAN_FW_IP
|
||||
ipv6_set_elements fplan6 $LAN_FP_IP
|
||||
ipv6_set_elements bplan6 $LAN_BP_IP
|
||||
ipv6_set_elements gmlan6 $LAN_GM_IP
|
||||
ipv6_set_elements lan_ac6 ${LAN_AC_IP#?}
|
||||
for sid in "$(uci_get_by_type global global_server)" "$(uci_get_by_type global udp_relay_server)"; do
|
||||
host=$(uci_get_by_name "$sid" server)
|
||||
host="${host#\[}"
|
||||
host="${host%\]}"
|
||||
[ -n "$host" ] || continue
|
||||
case "$host" in
|
||||
*:*) ipv6_set_elements servers6 "$host" ;;
|
||||
*) ipv6_set_elements servers6 $(resolveip -6 -t 3 "$host" 2>/dev/null) ;;
|
||||
esac
|
||||
done
|
||||
ports=$(echo "$PROXY_PORTS" | sed 's/-m multiport --dports //; s/:/-/g')
|
||||
cat <<-'RULES'
|
||||
add chain inet ss_spec ss_spec6_tcp
|
||||
add chain inet ss_spec ss_spec6_redirect
|
||||
add chain inet ss_spec ss_spec6_prerouting { type nat hook prerouting priority -1; policy accept; }
|
||||
RULES
|
||||
[ -z "$ports" ] || echo "add rule inet ss_spec ss_spec6_redirect tcp dport != { $ports } return"
|
||||
echo "add rule inet ss_spec ss_spec6_redirect meta l4proto tcp counter redirect to :$local_port"
|
||||
ipv6_policy_rules ss_spec6_tcp ss_spec6_redirect
|
||||
ipv6_lan_hook ss_spec6_prerouting tcp ss_spec6_tcp
|
||||
if [ "$OUTPUT" = "1" ] || [ "$OUTPUT" = "2" ]; then
|
||||
echo 'add chain inet ss_spec ss_spec6_output { type nat hook output priority -1; policy accept; }'
|
||||
if [ "$OUTPUT" = "2" ]; then
|
||||
cat <<-'RULES'
|
||||
add rule inet ss_spec ss_spec6_output meta mark 255 return
|
||||
add rule inet ss_spec ss_spec6_output fib daddr type local return
|
||||
add rule inet ss_spec ss_spec6_output ip6 daddr @local6 return
|
||||
add rule inet ss_spec ss_spec6_output ip6 daddr @servers6 return
|
||||
add rule inet ss_spec ss_spec6_output meta nfproto ipv6 meta l4proto tcp jump ss_spec6_redirect
|
||||
RULES
|
||||
else
|
||||
echo 'add rule inet ss_spec ss_spec6_output meta nfproto ipv6 meta l4proto tcp jump ss_spec6_tcp'
|
||||
fi
|
||||
fi
|
||||
|
||||
[ "$DISABLE_UDP_RULES" = "1" ] && return 0
|
||||
cat <<-'RULES'
|
||||
add chain inet ss_spec ss_spec6_udp
|
||||
add chain inet ss_spec ss_spec6_udp_proxy
|
||||
add chain inet ss_spec ss_spec6_mangle { type filter hook prerouting priority mangle; policy accept; }
|
||||
add rule inet ss_spec ss_spec6_mangle udp dport 53 return
|
||||
RULES
|
||||
if [ -n "$TPROXY" ]; then
|
||||
[ -z "$ports" ] || echo "add rule inet ss_spec ss_spec6_udp_proxy udp dport != { $ports } return"
|
||||
echo "add rule inet ss_spec ss_spec6_udp_proxy meta l4proto udp counter meta mark set $FWMARK tproxy ip6 to :$LOCAL_PORT accept"
|
||||
echo "add rule inet ss_spec ss_spec6_mangle meta nfproto ipv6 meta l4proto udp meta mark $FWMARK jump ss_spec6_udp_proxy"
|
||||
else
|
||||
echo 'add rule inet ss_spec ss_spec6_udp_proxy udp dport 443 counter drop'
|
||||
fi
|
||||
ipv6_policy_rules ss_spec6_udp ss_spec6_udp_proxy
|
||||
ipv6_lan_hook ss_spec6_mangle udp ss_spec6_udp
|
||||
if [ -n "$TPROXY" ] && { [ "$OUTPUT" = "1" ] || [ "$OUTPUT" = "2" ]; }; then
|
||||
cat <<-'RULES'
|
||||
add chain inet ss_spec ss_spec6_udp_output { type route hook output priority mangle; policy accept; }
|
||||
add chain inet ss_spec ss_spec6_udp_mark
|
||||
add chain inet ss_spec ss_spec6_udp_local
|
||||
add rule inet ss_spec ss_spec6_udp_output udp dport 53 return
|
||||
add rule inet ss_spec ss_spec6_udp_output meta nfproto ipv6 meta l4proto udp jump ss_spec6_udp_local
|
||||
RULES
|
||||
[ -z "$ports" ] || echo "add rule inet ss_spec ss_spec6_udp_mark udp dport != { $ports } return"
|
||||
echo "add rule inet ss_spec ss_spec6_udp_mark counter meta mark set $FWMARK return"
|
||||
if [ "$OUTPUT" = "2" ]; then
|
||||
local RUNMODE=all
|
||||
fi
|
||||
ipv6_policy_rules ss_spec6_udp_local ss_spec6_udp_mark
|
||||
fi
|
||||
}
|
||||
|
||||
ipv6_rules_apply() {
|
||||
[ "$USE_NFT" = "1" ] && ipv6_enabled || return 0
|
||||
local rules_file
|
||||
rules_file=$(mktemp /tmp/ssr-ipv6.XXXXXX) || return 1
|
||||
if ! ipv6_rules_generate > "$rules_file" || ! $NFT -f "$rules_file"; then
|
||||
rm -f "$rules_file"
|
||||
loger 3 "Failed to install IPv6 proxy rules"
|
||||
return 1
|
||||
fi
|
||||
rm -f "$rules_file"
|
||||
if [ -n "$TPROXY" ] && [ "$DISABLE_UDP_RULES" != "1" ]; then
|
||||
ipv6_policy_route
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
config global
|
||||
option global_server 'nil'
|
||||
option threads '0'
|
||||
option run_mode 'router'
|
||||
option dports '2'
|
||||
option custom_ports '80,443'
|
||||
option pdnsd_enable '1'
|
||||
option filter_aaaa '1'
|
||||
option ipv6_support '0'
|
||||
option tunnel_forward '8.8.4.4:53'
|
||||
option monitor_enable '1'
|
||||
option enable_switch '1'
|
||||
option switch_time '667'
|
||||
option switch_timeout '5'
|
||||
option switch_try_count '3'
|
||||
option default_node_local_port '1234'
|
||||
option component_mirror 'direct'
|
||||
option gfwlist_url 'https://fastly.jsdelivr.net/gh/YW5vbnltb3Vz/domain-list-community@release/gfwlist.txt'
|
||||
option chnroute6_url 'https://raw.githubusercontent.com/1715173329/IPCIDR-CHINA/master/ipv6.txt'
|
||||
option chnroute_url 'https://ispip.clang.cn/all_cn.txt'
|
||||
option adblock_url 'https://anti-ad.net/anti-ad-for-dnsmasq.conf'
|
||||
|
||||
config server_subscribe
|
||||
option proxy '1'
|
||||
option auto_update '1'
|
||||
option config_auto_update_mode '0'
|
||||
option config_update_interval '60'
|
||||
option auto_update_week_time '*'
|
||||
option auto_update_day_time '2'
|
||||
option auto_update_min_time '0'
|
||||
option url_test_url 'https://www.google.com/generate_204'
|
||||
option user_agent 'v2rayN/9.99'
|
||||
option filter_words '过期/重置/套餐/剩余/网址/QQ群/官网/防失联/回国'
|
||||
|
||||
config access_control
|
||||
option lan_ac_mode '0'
|
||||
option router_proxy '1'
|
||||
list wan_fw_ips '149.154.160.0/20'
|
||||
list wan_fw_ips '67.198.55.0/24'
|
||||
list wan_fw_ips '91.108.4.0/22'
|
||||
list wan_fw_ips '91.108.56.0/22'
|
||||
list wan_fw_ips '109.239.140.0/24'
|
||||
list wan_fw_ips '8.8.8.8'
|
||||
list wan_fw_ips '1.1.1.1'
|
||||
list Interface 'lan'
|
||||
|
||||
config socks5_proxy
|
||||
option server 'nil'
|
||||
option local_port '1080'
|
||||
|
||||
config http_proxy
|
||||
option server 'nil'
|
||||
option local_port '3128'
|
||||
option http_auth 'none'
|
||||
|
||||
config server_global
|
||||
option enable_server '0'
|
||||
|
||||
config global_xray_fragment
|
||||
option fragment '0'
|
||||
option noise '0'
|
||||
|
||||
config clash_client_group
|
||||
option enabled '0'
|
||||
option remarks ''
|
||||
option ip_addr ''
|
||||
option client_mac ''
|
||||
option policy_group ''
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
LOCK_DIR="/var/run/ssrplusupdate.lock"
|
||||
LOOP_STAMP="/var/run/ssrplusupdate.loop"
|
||||
MODE="$(uci -q get shadowsocksr.@server_subscribe[0].config_auto_update_mode 2>/dev/null || echo 0)"
|
||||
|
||||
mkdir "$LOCK_DIR" 2>/dev/null || exit 0
|
||||
trap 'rmdir "$LOCK_DIR" 2>/dev/null' EXIT INT TERM
|
||||
|
||||
if [ "$1" = "loop" ]; then
|
||||
[ "$(uci -q get shadowsocksr.@server_subscribe[0].auto_update 2>/dev/null || echo 0)" = "1" ] || exit 0
|
||||
[ "$MODE" = "1" ] || exit 0
|
||||
|
||||
INTERVAL="$(uci -q get shadowsocksr.@server_subscribe[0].config_update_interval 2>/dev/null || echo 60)"
|
||||
case "$INTERVAL" in
|
||||
''|*[!0-9]*)
|
||||
INTERVAL=60
|
||||
;;
|
||||
esac
|
||||
[ "$INTERVAL" -gt 0 ] 2>/dev/null || INTERVAL=60
|
||||
|
||||
NOW="$(date +%s)"
|
||||
LAST_RUN=0
|
||||
[ -f "$LOOP_STAMP" ] && LAST_RUN="$(cat "$LOOP_STAMP" 2>/dev/null || echo 0)"
|
||||
case "$LAST_RUN" in
|
||||
''|*[!0-9]*)
|
||||
LAST_RUN=0
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $((NOW - LAST_RUN)) -lt $((INTERVAL * 60)) ]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
/usr/bin/lua /usr/share/shadowsocksr/update.lua
|
||||
sleep 2s
|
||||
/usr/share/shadowsocksr/chinaipset.sh /var/etc/ssrplus/china_ssr.txt
|
||||
sleep 2s
|
||||
/usr/bin/lua /usr/share/shadowsocksr/subscribe.lua
|
||||
|
||||
if [ "$1" = "loop" ]; then
|
||||
date +%s > "$LOOP_STAMP"
|
||||
fi
|
||||
+3035
File diff suppressed because it is too large.
Load diff
+305
@@ -0,0 +1,305 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
------------------------------------------------
|
||||
-- This file is part of the luci-app-ssr-plus update.lua
|
||||
-- By Mattraks
|
||||
------------------------------------------------
|
||||
require "luci.sys"
|
||||
require "luci.model.uci"
|
||||
local icount = 0
|
||||
local args = arg[1]
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
|
||||
-- 以下设置更新数据库至 DNSMASQ 配置路径
|
||||
-- 获取 DNSMASQ 配置 ID
|
||||
local DNSMASQ_UCI_CONFIG = uci:get_first("dhcp", "dnsmasq", ".name")
|
||||
|
||||
-- 获取 DNSMASQ 默认配置文件
|
||||
local DNSMASQ_CONF_PATH = "/tmp/etc/dnsmasq.conf." .. DNSMASQ_UCI_CONFIG
|
||||
|
||||
-- 检查 DNSMASQ 配置文件是否存在,如果存在则提取 conf-dir
|
||||
for line in io.lines(DNSMASQ_CONF_PATH) do
|
||||
local conf_dir = line:match("^conf%-dir=(.+)")
|
||||
if conf_dir then
|
||||
DNSMASQ_CONF_DIR = conf_dir:gsub("%s+", "") -- 去除空白字符
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- 设置 dnsmasq-ssrplus.d 目录路径,并去除路径末尾的斜杠
|
||||
local TMP_DNSMASQ_PATH = DNSMASQ_CONF_DIR:match("^(.-)/?$") .. "/dnsmasq-ssrplus.d"
|
||||
|
||||
local TMP_PATH = "/var/etc/ssrplus"
|
||||
-- match comments/title/whitelist/ip address/excluded_domain
|
||||
local comment_pattern = "^[!\\[@]+"
|
||||
local ip_pattern = "^%d+%.%d+%.%d+%.%d+"
|
||||
local domain_pattern = "([%w%-%_]+%.[%w%.%-%_]+)[%/%*]*"
|
||||
local excluded_domain = {
|
||||
"apple.com", "sina.cn", "sina.com.cn", "baidu.com", "byr.cn", "jlike.com",
|
||||
"weibo.com", "zhongsou.com", "youdao.com", "sogou.com", "so.com", "soso.com",
|
||||
"aliyun.com", "taobao.com", "jd.com", "qq.com"
|
||||
}
|
||||
-- gfwlist parameter
|
||||
local mydnsip = '127.0.0.1'
|
||||
local mydnsport = '5335'
|
||||
local ipsetname = 'gfwlist'
|
||||
local new_appledns = uci:get_first("shadowsocksr", "global", "apple_dns", "")
|
||||
local bc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||
-- base64decoding
|
||||
local function base64_dec(data)
|
||||
data = string.gsub(data, '[^' .. bc .. '=]', '')
|
||||
return (data:gsub('.', function(x)
|
||||
if (x == '=') then
|
||||
return ''
|
||||
end
|
||||
local r, f = '', (bc:find(x) - 1)
|
||||
for i = 6, 1, -1 do
|
||||
r = r .. (f % 2 ^ i - f % 2 ^ (i - 1) > 0 and '1' or '0')
|
||||
end
|
||||
return r;
|
||||
end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
|
||||
if (#x ~= 8) then
|
||||
return ''
|
||||
end
|
||||
local c = 0
|
||||
for i = 1, 8 do
|
||||
c = c + (x:sub(i, i) == '1' and 2 ^ (8 - i) or 0)
|
||||
end
|
||||
return string.char(c)
|
||||
end))
|
||||
end
|
||||
-- check if domain is excluded
|
||||
local function check_excluded_domain(value)
|
||||
for _, domain in ipairs(excluded_domain) do
|
||||
if value:find(domain) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
-- gfwlist转码至dnsmasq格式
|
||||
local function generate_gfwlist(type)
|
||||
local domains, domains_map = {}, {}
|
||||
local out = io.open("/tmp/ssr-update." .. type, "w")
|
||||
for line in io.lines("/tmp/ssr-update.tmp") do
|
||||
if not (string.find(line, comment_pattern) or string.find(line, ip_pattern) or check_excluded_domain(line)) then
|
||||
local start, finish, match = string.find(line, domain_pattern)
|
||||
if start and not domains_map[match] then
|
||||
domains_map[match] = true
|
||||
table.insert(domains, match)
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, domain in ipairs(domains) do
|
||||
out:write(string.format("server=/%s/%s#%s\n", domain, mydnsip, mydnsport))
|
||||
out:write(string.format("ipset=/%s/%s\n", domain, ipsetname))
|
||||
end
|
||||
out:close()
|
||||
os.remove("/tmp/ssr-update.tmp")
|
||||
end
|
||||
|
||||
-- 更换 Apple dns
|
||||
local function generate_apple(type)
|
||||
local domains, domains_map = {}, {}
|
||||
local out = io.open("/tmp/ssr-update." .. type, "w")
|
||||
for line in io.lines("/tmp/ssr-update.tmp") do
|
||||
if not (string.find(line, comment_pattern)) then
|
||||
local start, finish, match = string.find(line, domain_pattern)
|
||||
if start and not domains_map[match] then
|
||||
domains_map[match] = true
|
||||
match = string.gsub(match, "%s", "") --从域名中去除所有空白字符
|
||||
table.insert(domains, match)
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, domain in ipairs(domains) do
|
||||
out:write(string.format("server=/%s/%s\n", domain, new_appledns))
|
||||
end
|
||||
out:close()
|
||||
os.remove("/tmp/ssr-update.tmp")
|
||||
end
|
||||
|
||||
-- adblock转码至dnsmasq格式
|
||||
local function generate_adblock(type)
|
||||
local domains, domains_map = {}, {}
|
||||
local out = io.open("/tmp/ssr-update." .. type, "w")
|
||||
for line in io.lines("/tmp/ssr-update.tmp") do
|
||||
if not (string.find(line, comment_pattern)) then
|
||||
local start, finish, match = string.find(line, domain_pattern)
|
||||
if start and not domains_map[match] then
|
||||
domains_map[match] = true
|
||||
table.insert(domains, match)
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, domain in ipairs(domains) do
|
||||
out:write(string.format("address=/%s/\n", domain))
|
||||
end
|
||||
out:close()
|
||||
os.remove("/tmp/ssr-update.tmp")
|
||||
end
|
||||
|
||||
local log = function(...)
|
||||
if args then
|
||||
print("{ret=" .. table.concat({...}, ",retcount=") .. "}")
|
||||
else
|
||||
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({...}, " "))
|
||||
end
|
||||
end
|
||||
|
||||
local function update(url, file, type, file2)
|
||||
local Num = 1
|
||||
local refresh_cmd = "curl -sSL --insecure -o /tmp/ssr-update." .. type .. " " .. url
|
||||
local sret = luci.sys.call(refresh_cmd)
|
||||
if sret == 0 then
|
||||
if type == "ip6_data" then
|
||||
local ip = require "luci.ip"
|
||||
local entries = {}
|
||||
for line in io.lines("/tmp/ssr-update." .. type) do
|
||||
line = line:gsub("#.*$", ""):match("^%s*(.-)%s*$")
|
||||
if line ~= "" then
|
||||
if not ip.IPv6(line) then
|
||||
os.remove("/tmp/ssr-update." .. type)
|
||||
log(-1)
|
||||
return
|
||||
end
|
||||
table.insert(entries, line)
|
||||
end
|
||||
end
|
||||
if #entries == 0 then
|
||||
os.remove("/tmp/ssr-update." .. type)
|
||||
log(-1)
|
||||
return
|
||||
end
|
||||
local out = io.open("/tmp/ssr-update." .. type, "w")
|
||||
out:write(table.concat(entries, "\n"), "\n")
|
||||
out:close()
|
||||
end
|
||||
if type == "gfw_data" then
|
||||
local gfwlist = io.open("/tmp/ssr-update." .. type, "r")
|
||||
local decode = gfwlist:read("*a")
|
||||
if not decode:find("google") then
|
||||
decode = base64_dec(decode)
|
||||
end
|
||||
gfwlist:close()
|
||||
-- 写回gfwlist
|
||||
gfwlist = io.open("/tmp/ssr-update.tmp", "w")
|
||||
gfwlist:write(decode)
|
||||
gfwlist:close()
|
||||
generate_gfwlist(type)
|
||||
Num = 2
|
||||
end
|
||||
if type == "apple_data" then
|
||||
local apple = io.open("/tmp/ssr-update." .. type, "r")
|
||||
local decode = apple:read("*a")
|
||||
if not decode:find("apple") then
|
||||
decode = base64_dec(decode)
|
||||
end
|
||||
apple:close()
|
||||
-- 写回applechina
|
||||
apple = io.open("/tmp/ssr-update.tmp", "w")
|
||||
apple:write(decode)
|
||||
apple:close()
|
||||
if new_appledns and new_appledns ~= "" then
|
||||
generate_apple(type)
|
||||
else
|
||||
os.remove("/tmp/ssr-update.tmp")
|
||||
end
|
||||
end
|
||||
if type == "ad_data" then
|
||||
local adblock = io.open("/tmp/ssr-update." .. type, "r")
|
||||
local decode = adblock:read("*a")
|
||||
if decode:find("address=") then
|
||||
adblock:close()
|
||||
else
|
||||
adblock:close()
|
||||
-- 写回adblock
|
||||
adblock = io.open("/tmp/ssr-update.tmp", "w")
|
||||
adblock:write(decode)
|
||||
adblock:close()
|
||||
generate_adblock(type)
|
||||
end
|
||||
end
|
||||
local new_md5 = luci.sys.exec("echo -n $([ -f '/tmp/ssr-update." .. type .. "' ] && md5sum /tmp/ssr-update." .. type .. " | awk '{print $1}')")
|
||||
local old_md5 = luci.sys.exec("echo -n $([ -f '" .. file .. "' ] && md5sum " .. file .. " | awk '{print $1}')")
|
||||
if new_md5 == old_md5 then
|
||||
if args then
|
||||
log(1)
|
||||
else
|
||||
log("你已经是最新数据,无需更新!")
|
||||
end
|
||||
else
|
||||
icount = luci.sys.exec("cat /tmp/ssr-update." .. type .. " | wc -l")
|
||||
luci.sys.exec("cp -f /tmp/ssr-update." .. type .. " " .. file)
|
||||
if file2 then
|
||||
luci.sys.exec("cp -f /tmp/ssr-update." .. type .. " " .. file2)
|
||||
end
|
||||
if type == "ip6_data" then
|
||||
luci.sys.call("/usr/share/shadowsocksr/chinaipset.sh /etc/ssrplus/china6_ssr.txt 6")
|
||||
elseif type == "gfw_data" or type == "ad_data" then
|
||||
luci.sys.call("/usr/share/shadowsocksr/gfw2ipset.sh")
|
||||
else
|
||||
if luci.sys.call("command -v ipset >/dev/null 2>&1") == 0 then
|
||||
luci.sys.call("/usr/share/shadowsocksr/chinaipset.sh " .. TMP_PATH .. "/china_ssr.txt")
|
||||
end
|
||||
end
|
||||
if args then
|
||||
log(0, tonumber(icount) / Num)
|
||||
else
|
||||
log("更新成功! 新的总记录数:" .. tostring(tonumber(icount) / Num))
|
||||
end
|
||||
end
|
||||
else
|
||||
if args then
|
||||
log(-1)
|
||||
else
|
||||
log("更新失败!")
|
||||
end
|
||||
end
|
||||
os.remove("/tmp/ssr-update." .. type)
|
||||
end
|
||||
|
||||
local function update_ipv6()
|
||||
update(uci:get_first("shadowsocksr", "global", "chnroute6_url",
|
||||
"https://raw.githubusercontent.com/1715173329/IPCIDR-CHINA/master/ipv6.txt"),
|
||||
"/etc/ssrplus/china6_ssr.txt", "ip6_data")
|
||||
end
|
||||
|
||||
if args then
|
||||
if args == "ip6_data" then
|
||||
update_ipv6()
|
||||
os.exit(0)
|
||||
end
|
||||
if args == "gfw_data" then
|
||||
update(uci:get_first("shadowsocksr", "global", "gfwlist_url"), "/etc/ssrplus/gfw_list.conf", args, TMP_DNSMASQ_PATH .. "/gfw_list.conf")
|
||||
os.exit(0)
|
||||
end
|
||||
if args == "ip_data" then
|
||||
update(uci:get_first("shadowsocksr", "global", "chnroute_url"), "/etc/ssrplus/china_ssr.txt", args, TMP_PATH .. "/china_ssr.txt")
|
||||
os.exit(0)
|
||||
end
|
||||
if args == "apple_data" then
|
||||
update(uci:get_first("shadowsocksr", "global", "apple_url"), "/etc/ssrplus/applechina.conf", args, TMP_DNSMASQ_PATH .. "/applechina.conf")
|
||||
os.exit(0)
|
||||
end
|
||||
if args == "ad_data" then
|
||||
update(uci:get_first("shadowsocksr", "global", "adblock_url"), "/etc/ssrplus/ad.conf", args, TMP_DNSMASQ_PATH .. "/ad.conf")
|
||||
os.exit(0)
|
||||
end
|
||||
else
|
||||
log("正在更新【GFW列表】数据库")
|
||||
update(uci:get_first("shadowsocksr", "global", "gfwlist_url"), "/etc/ssrplus/gfw_list.conf", "gfw_data", TMP_DNSMASQ_PATH .. "/gfw_list.conf")
|
||||
if uci:get_first("shadowsocksr", "global", "ipv6_support", "0") == "1" then
|
||||
log("正在更新【国内IPv6段】数据库")
|
||||
update_ipv6()
|
||||
end
|
||||
log("正在更新【国内IP段】数据库")
|
||||
update(uci:get_first("shadowsocksr", "global", "chnroute_url"), "/etc/ssrplus/china_ssr.txt", "ip_data", TMP_PATH .. "/china_ssr.txt")
|
||||
if uci:get_first("shadowsocksr", "global", "apple_optimization", "0") == "1" then
|
||||
log("正在更新【Apple域名】数据库")
|
||||
update(uci:get_first("shadowsocksr", "global", "apple_url"), "/etc/ssrplus/applechina.conf", "apple_data", TMP_DNSMASQ_PATH .. "/applechina.conf")
|
||||
end
|
||||
if uci:get_first("shadowsocksr", "global", "adblock", "0") == "1" then
|
||||
log("正在更新【广告屏蔽】数据库")
|
||||
update(uci:get_first("shadowsocksr", "global", "adblock_url"), "/etc/ssrplus/ad.conf", "ad_data", TMP_DNSMASQ_PATH .. "/ad.conf")
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"config": "shadowsocksr",
|
||||
"init": "shadowsocksr"
|
||||
}
|
||||
Reference in new issue
Block a user