feat(脚本): 完善黑名单机制

This commit is contained in:
mack-a
2026-04-13 20:48:55 +08:00
parent d64843bbdd
commit 77a39bd624
2 changed files with 592 additions and 97 deletions
+338 -40
View File
@@ -3309,6 +3309,7 @@ addSingBoxRouteRule() {
domainList="${domainList},$(jq -rc .route.rules[0].rule_set[] "${singBoxConfigPath}${routingName}.json" | awk -F "[_]" '{print $1}' | paste -sd ',')" domainList="${domainList},$(jq -rc .route.rules[0].rule_set[] "${singBoxConfigPath}${routingName}.json" | awk -F "[_]" '{print $1}' | paste -sd ',')"
domainList="${domainList},$(jq -rc .route.rules[0].domain_regex[] "${singBoxConfigPath}${routingName}.json" | awk -F "[*]" '{print $2}' | paste -sd ',' | sed 's/\\//g')" domainList="${domainList},$(jq -rc .route.rules[0].domain_regex[] "${singBoxConfigPath}${routingName}.json" | awk -F "[*]" '{print $2}' | paste -sd ',' | sed 's/\\//g')"
fi fi
fi fi
local rules= local rules=
rules=$(initSingBoxRules "${domainList}" "${routingName}") rules=$(initSingBoxRules "${domainList}" "${routingName}")
@@ -3326,7 +3327,6 @@ addSingBoxRouteRule() {
ruleSetTag=$(echo "${ruleSet}" | jq '.|map(.tag)') ruleSetTag=$(echo "${ruleSet}" | jq '.|map(.tag)')
fi fi
if [[ -n "${singBoxConfigPath}" ]]; then if [[ -n "${singBoxConfigPath}" ]]; then
cat <<EOF >"${singBoxConfigPath}${routingName}.json" cat <<EOF >"${singBoxConfigPath}${routingName}.json"
{ {
"route": { "route": {
@@ -6637,8 +6637,10 @@ blacklist() {
echoContent red "\n==============================================================" echoContent red "\n=============================================================="
echoContent yellow "1.查看已屏蔽域名" echoContent yellow "1.查看已屏蔽域名"
echoContent yellow "2.添加域名" echoContent yellow "2.添加域名"
echoContent yellow "3.屏蔽大陆域名" echoContent yellow "3.屏蔽大陆域名+IP"
echoContent yellow "4.卸载黑名单" echoContent yellow "4.卸载黑/白名单"
echoContent yellow "5.添加IP"
echoContent yellow "6.添加域名白名单"
echoContent red "==============================================================" echoContent red "=============================================================="
read -r -p "请选择:" blacklistStatus read -r -p "请选择:" blacklistStatus
@@ -6667,54 +6669,231 @@ blacklist() {
echoContent green " ---> 添加完毕" echoContent green " ---> 添加完毕"
elif [[ "${blacklistStatus}" == "3" ]]; then elif [[ "${blacklistStatus}" == "3" ]]; then
local allowDomainList="dl.google.com,apple.com,bing.com,microsoft.com,gstatic,xn--ngstr-lra8j.com,googleapis.com,googleapis.cn"
if [[ "${coreInstallType}" == "1" ]]; then if [[ "${coreInstallType}" == "1" ]]; then
unInstallRouting blackhole_out outboundTag unInstallRouting blackhole_out outboundTag
unInstallRouting blackhole_ip_out outboundTag
addXrayRouting blackhole_out outboundTag "cn" addXrayRouting blackhole_out outboundTag "cn"
addXrayIPRouting blackhole_ip_out outboundTag "cn"
addXrayRouting allow_domain_direct_outbound outboundTag "${allowDomainList}" "top"
addXrayOutbound blackhole_out addXrayOutbound blackhole_out
addXrayOutbound blackhole_ip_out
addXrayOutbound allow_domain_direct_outbound
fi fi
if [[ -n "${singBoxConfigPath}" ]]; then if [[ -n "${singBoxConfigPath}" ]]; then
addSingBoxRouteRule "cn_block_outbound" "cn" "cn_block_route" addSingBoxRouteRule "cn_block_outbound" "cn" "cn_block_route"
addSingBoxGeoIPRouteRule "block_ip_outbound" "cn" "cn_block_ip_route"
addSingBoxRouteRule "01_direct_outbound" "googleapis.com,googleapis.cn,xn--ngstr-lra8j.com,gstatic.com" "cn_01_google_play_route" addSingBoxRouteRule "01_direct_outbound" "${allowDomainList}" "00_allow_domain_route"
addSingBoxOutbound "cn_block_outbound" addSingBoxOutbound "cn_block_outbound"
addSingBoxOutbound "block_ip_outbound"
addSingBoxOutbound "01_direct_outbound" addSingBoxOutbound "01_direct_outbound"
fi fi
echoContent green " ---> 屏蔽大陆域名完毕" echoContent green " ---> 屏蔽大陆域名+IP完毕"
elif [[ "${blacklistStatus}" == "4" ]]; then elif [[ "${blacklistStatus}" == "4" ]]; then
if [[ "${coreInstallType}" == "1" ]]; then if [[ "${coreInstallType}" == "1" ]]; then
unInstallRouting blackhole_out outboundTag unInstallRouting blackhole_out outboundTag
unInstallRouting blackhole_ip_out outboundTag
unInstallRouting allow_domain_direct_outbound outboundTag
removeXrayOutbound blackhole_ip_out
removeXrayOutbound allow_domain_direct_outbound
fi fi
if [[ -n "${singBoxConfigPath}" ]]; then if [[ -n "${singBoxConfigPath}" ]]; then
removeSingBoxConfig "cn_block_route" removeSingBoxConfig "cn_block_route"
removeSingBoxConfig "cn_block_outbound" removeSingBoxConfig "cn_block_outbound"
removeSingBoxConfig "cn_block_ip_route"
removeSingBoxConfig "block_ip_route"
removeSingBoxConfig "block_ip_outbound"
removeSingBoxConfig "cn_01_google_play_route" removeSingBoxConfig "cn_01_google_play_route"
removeSingBoxConfig "00_allow_domain_route"
removeSingBoxConfig "block_domain_route" removeSingBoxConfig "block_domain_route"
removeSingBoxConfig "block_domain_outbound" removeSingBoxConfig "block_domain_outbound"
fi fi
echoContent green " ---> 域名黑名单删除完毕" echoContent green " ---> 域名黑名单/白名单删除完毕"
elif [[ "${blacklistStatus}" == "5" ]]; then
echoContent red "=============================================================="
echoContent yellow "录入示例:1.1.1.1,8.8.8.8,1.1.1.0/24,2400:3200::/32\n"
read -r -p "请按照上面示例录入IP:" ipList
if [[ -z "${ipList}" ]]; then
echoContent red " ---> IP不可为空"
exit 0
fi
if [[ "${coreInstallType}" == "1" ]]; then
addXrayIPRouting blackhole_ip_out outboundTag "${ipList}"
addXrayOutbound blackhole_ip_out
fi
if [[ -n "${singBoxConfigPath}" ]]; then
addSingBoxIPRouteRule "block_ip_outbound" "${ipList}" "block_ip_route"
addSingBoxOutbound "block_ip_outbound"
fi
echoContent green " ---> 添加IP完毕"
elif [[ "${blacklistStatus}" == "6" ]]; then
echoContent red "=============================================================="
echoContent yellow "录入示例:speedtest,openai,google.com\n"
read -r -p "请按照上面示例录入域名:" allowDomainList
if [[ -z "${allowDomainList}" ]]; then
echoContent red " ---> 域名不可为空"
exit 0
fi
if [[ "${coreInstallType}" == "1" ]]; then
addXrayRouting allow_domain_direct_outbound outboundTag "${allowDomainList}" "top"
addXrayOutbound allow_domain_direct_outbound
fi
if [[ -n "${singBoxConfigPath}" ]]; then
addSingBoxRouteRule "01_direct_outbound" "${allowDomainList}" "00_allow_domain_route"
addSingBoxOutbound "01_direct_outbound"
fi
echoContent green " ---> 添加域名白名单完毕"
else else
echoContent red " ---> 选择错误" echoContent red " ---> 选择错误"
exit 0 exit 0
fi fi
reloadCore reloadCore
} }
# 下载 dlc.dat_plain.yml 到核心目录
downloadDLCPlainYAML() {
local corePath=$1
local dlcFilePath="${corePath}/dlc.dat_plain.yml"
local tmpFilePath="${dlcFilePath}.tmp"
if [[ -z "${corePath}" ]]; then
return 1
fi
mkdir -p "${corePath}" >/dev/null 2>&1
if [[ -s "${dlcFilePath}" ]]; then
return 0
fi
local dlcDownloadURL="https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat_plain.yml"
if [[ "${release}" == "alpine" ]]; then
wget -c -O "${tmpFilePath}" "${dlcDownloadURL}" >/dev/null 2>&1
else
wget -c "${wgetShowProgressStatus}" -O "${tmpFilePath}" "${dlcDownloadURL}" >/dev/null 2>&1
fi
# shellcheck disable=SC2181
if [[ "$?" -ne 0 || ! -s "${tmpFilePath}" ]]; then
rm -f "${tmpFilePath}" >/dev/null 2>&1
return 1
fi
mv "${tmpFilePath}" "${dlcFilePath}" >/dev/null 2>&1
}
# 转义grep/regex匹配字符
escapeDLCRegexPattern() {
# shellcheck disable=SC2016
# shellcheck disable=SC2001
echo "$1" | sed -e 's/[.[\*^$()+?{|]/\\&/g'
}
# 根据规则行号向上回溯对应name
getDLCNameByRuleLine() {
local ruleLine=$1
local dlcFilePath=$2
awk -v targetLine="${ruleLine}" '
/^[[:space:]]*-[[:space:]]*name:[[:space:]]*/ {
line = $0
sub(/^[[:space:]]*-[[:space:]]*name:[[:space:]]*/, "", line)
currentName = line
}
NR == targetLine {
print currentName
exit
}' "${dlcFilePath}"
}
isDomainFormat() {
local target=$1
[[ "${target}" =~ ^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z0-9-]{2,63}$ ]]
}
# 根据输入域名匹配 dlc.dat_plain.yml 对应 geosite name
getDLCGeositeName() {
local inputRule=$1
local corePath=$2
local dlcFilePath="${corePath}/dlc.dat_plain.yml"
if [[ -z "${inputRule}" || -z "${corePath}" ]]; then
echo ""
return
fi
local normalizedInput
normalizedInput=$(echo "${inputRule}" | tr '[:upper:]' '[:lower:]' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
normalizedInput=${normalizedInput#domain:}
normalizedInput=${normalizedInput#full:}
normalizedInput=${normalizedInput#keyword:}
if [[ -z "${normalizedInput}" ]]; then
echo ""
return
fi
if isDomainFormat "${normalizedInput}"; then
return
fi
if ! downloadDLCPlainYAML "${corePath}"; then
echo ""
return
fi
local escapedInput=
escapedInput=$(escapeDLCRegexPattern "${normalizedInput}")
local matchedLine=
matchedLine=$(grep -n -m1 -E "^[[:space:]]*-[[:space:]]*name:[[:space:]]*${escapedInput}[[:space:]]*$" "${dlcFilePath}")
if [[ -n "${matchedLine}" ]]; then
echo "${normalizedInput}"
fi
}
# 获取规则匹配结果,优先geosite,失败回退domain
getDLCMatchedRuleValue() {
local inputRule=$1
local corePath=$2
local normalizedInput=
normalizedInput=$(echo "${inputRule}" | tr '[:upper:]' '[:lower:]' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if isDomainFormat "${normalizedInput}"; then
local escapedDomain=
escapedDomain=$(escapeDLCRegexPattern "${normalizedInput}")
echo "regexp:.*${escapedDomain}.*"
return
fi
local matchedRuleName=
matchedRuleName=$(getDLCGeositeName "${normalizedInput}" "${corePath}")
if [[ -n "${matchedRuleName}" ]]; then
echo "geosite:${matchedRuleName}"
else
echo "domain:${normalizedInput}"
fi
}
# 添加routing配置 # 添加routing配置
addXrayRouting() { addXrayRouting() {
local tag=$1 # warp-socks local tag=$1 # warp-socks
local type=$2 # outboundTag/inboundTag local type=$2 # outboundTag/inboundTag
local domain=$3 # 域名 local domain=$3 # 域名
local rulePosition=$4
if [[ -z "${tag}" || -z "${type}" || -z "${domain}" ]]; then if [[ -z "${tag}" || -z "${type}" || -z "${domain}" ]]; then
echoContent red " ---> 参数错误" echoContent red " ---> 参数错误"
@@ -6750,27 +6929,146 @@ EOF
if echo "${routingRule}" | grep -q "${line}"; then if echo "${routingRule}" | grep -q "${line}"; then
echoContent yellow " ---> ${line}已存在,跳过" echoContent yellow " ---> ${line}已存在,跳过"
else else
local geositeStatus local matchedRuleValue
geositeStatus=$(curl -s "https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}" | jq .message) matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray")
routingRule=$(echo "${routingRule}" | jq -r --arg rule "${matchedRuleValue}" '.domain += [$rule]')
if [[ "${geositeStatus}" == "null" ]]; then
routingRule=$(echo "${routingRule}" | jq -r '.domain += ["geosite:'"${line}"'"]')
else
routingRule=$(echo "${routingRule}" | jq -r '.domain += ["domain:'"${line}"'"]')
fi
fi fi
done < <(echo "${domain}" | tr ',' '\n') done < <(echo "${domain}" | tr ',' '\n')
unInstallRouting "${tag}" "${type}" unInstallRouting "${tag}" "${type}"
if ! grep -q "gstatic.com" ${configPath}09_routing.json && [[ "${tag}" == "blackhole_out" ]]; then if ! grep -q "gstatic.com" ${configPath}09_routing.json && [[ "${tag}" == "blackhole_out" ]]; then
local routing= local routing=
routing=$(jq -r ".routing.rules += [{\"type\": \"field\",\"domain\": [\"gstatic.com\"],\"outboundTag\": \"direct\"}]" ${configPath}09_routing.json) routing=$(jq -r ".routing.rules += [{\"type\": \"field\",\"domain\": [\"domain:gstatic.com\"],\"outboundTag\": \"allow_domain_direct_outbound\"}]" ${configPath}09_routing.json)
echo "${routing}" | jq . >${configPath}09_routing.json echo "${routing}" | jq . >${configPath}09_routing.json
addXrayOutbound allow_domain_direct_outbound
fi fi
if [[ "${rulePosition}" == "top" ]]; then
routing=$(jq -r ".routing.rules = [${routingRule}] + .routing.rules" ${configPath}09_routing.json)
else
routing=$(jq -r ".routing.rules += [${routingRule}]" ${configPath}09_routing.json)
fi
echo "${routing}" | jq . >${configPath}09_routing.json
}
# 添加 Xray IP 屏蔽路由规则
# 支持 geoip:cn 与自定义 IPv4/IPv6/CIDR
addXrayIPRouting() {
local tag=$1
local type=$2
local ipList=$3
if [[ -z "${tag}" || -z "${type}" || -z "${ipList}" ]]; then
echoContent red " ---> 参数错误"
exit 0
fi
if [[ ! -f "${configPath}09_routing.json" ]]; then
cat <<EOF >${configPath}09_routing.json
{
"routing":{
"type": "field",
"rules": []
}
}
EOF
fi
local routingRule=
routingRule=$(jq -r ".routing.rules[]|select(.outboundTag==\"${tag}\" and (.protocol == null) and (.ip != null))" ${configPath}09_routing.json)
if [[ -z "${routingRule}" ]]; then
routingRule="{\"type\": \"field\",\"ip\": [],\"outboundTag\": \"${tag}\"}"
fi
while read -r line; do
line=$(echo "${line}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [[ -z "${line}" ]]; then
continue
fi
local ipRuleValue=${line}
if [[ "${line}" == "cn" ]]; then
ipRuleValue="geoip:cn"
fi
if echo "${routingRule}" | grep -q "${ipRuleValue}"; then
echoContent yellow " ---> ${ipRuleValue}已存在,跳过"
else
routingRule=$(echo "${routingRule}" | jq -r '.ip += ["'"${ipRuleValue}"'"]')
fi
done < <(echo "${ipList}" | tr ',' '\n')
unInstallRouting "${tag}" "${type}"
local routing=
routing=$(jq -r ".routing.rules += [${routingRule}]" ${configPath}09_routing.json) routing=$(jq -r ".routing.rules += [${routingRule}]" ${configPath}09_routing.json)
echo "${routing}" | jq . >${configPath}09_routing.json echo "${routing}" | jq . >${configPath}09_routing.json
} }
# 添加 sing-box IP 屏蔽路由规则
# 支持增量合并历史 ip_cidr
addSingBoxIPRouteRule() {
local outboundTag=$1
local ipList=$2
local routingName=$3
local historyIPs=
if [[ -f "${singBoxConfigPath}${routingName}.json" ]]; then
historyIPs=$(jq -r '.route.rules[0].ip_cidr[]?' "${singBoxConfigPath}${routingName}.json" | paste -sd ',')
fi
if [[ -n "${historyIPs}" ]]; then
ipList="${ipList},${historyIPs}"
fi
local ipCIDR=[]
ipCIDR=$(echo "${ipList}" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep -v '^$' | sort -n | uniq | jq -R . | jq -s .)
cat <<EOF >"${singBoxConfigPath}${routingName}.json"
{
"route": {
"rules": [
{
"ip_cidr": ${ipCIDR},
"outbound": "${outboundTag}"
}
]
}
}
EOF
}
# 添加 sing-box GeoIP 远程规则
# 用于大陆 IP 自动屏蔽场景
addSingBoxGeoIPRouteRule() {
local outboundTag=$1
local geoipCode=$2
local routingName=$3
cat <<EOF >"${singBoxConfigPath}${routingName}.json"
{
"route": {
"rules": [
{
"rule_set": [
"geoip_${geoipCode}_${routingName}"
],
"outbound": "${outboundTag}"
}
],
"rule_set": [
{
"tag": "geoip_${geoipCode}_${routingName}",
"type": "remote",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-${geoipCode}.srs",
"download_detour": "01_direct_outbound"
}
]
}
}
EOF
}
# 根据tag卸载Routing # 根据tag卸载Routing
unInstallRouting() { unInstallRouting() {
local tag=$1 local tag=$1
@@ -7446,13 +7744,21 @@ initSingBoxRules() {
local domainRules=[] local domainRules=[]
local ruleSet=[] local ruleSet=[]
while read -r line; do while read -r line; do
local geositeStatus local normalizedLine=
geositeStatus=$(curl -s "https://api.github.com/repos/SagerNet/sing-geosite/contents/geosite-${line}.srs?ref=rule-set" | jq .message) normalizedLine=$(echo "${line}" | tr '[:upper:]' '[:lower:]' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if isDomainFormat "${normalizedLine}"; then
if [[ "${geositeStatus}" == "null" ]]; then local escapedDomain=
ruleSet=$(echo "${ruleSet}" | jq -r ". += [{\"tag\":\"${line}_$2\",\"type\":\"remote\",\"format\":\"binary\",\"url\":\"https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-${line}.srs\",\"download_detour\":\"01_direct_outbound\"}]") escapedDomain=${normalizedLine//./\\.}
domainRules=$(echo "${domainRules}" | jq -r --arg reg ".*${escapedDomain}.*" '. += [$reg]')
else else
domainRules=$(echo "${domainRules}" | jq -r ". += [\"^([a-zA-Z0-9_-]+\\\.)*${line//./\\\\.}\"]") local matchedRuleName
matchedRuleName=$(getDLCGeositeName "${normalizedLine}" "/etc/v2ray-agent/sing-box")
if [[ -n "${matchedRuleName}" ]]; then
ruleSet=$(echo "${ruleSet}" | jq -r ". += [{\"tag\":\"${matchedRuleName}_$2\",\"type\":\"remote\",\"format\":\"binary\",\"url\":\"https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-${matchedRuleName}.srs\",\"download_detour\":\"01_direct_outbound\"}]")
else
domainRules=$(echo "${domainRules}" | jq -r --arg reg "^([a-zA-Z0-9_-]+\\.)*${normalizedLine//./\\.}" '. += [$reg]')
fi
fi fi
done < <(echo "$1" | tr ',' '\n' | grep -v '^$' | sort -n | uniq | paste -sd ',' | tr ',' '\n') done < <(echo "$1" | tr ',' '\n' | grep -v '^$' | sort -n | uniq | paste -sd ',' | tr ',' '\n')
echo "{ \"domainRules\":${domainRules},\"ruleSet\":${ruleSet}}" echo "{ \"domainRules\":${domainRules},\"ruleSet\":${ruleSet}}"
@@ -7635,14 +7941,9 @@ setSocks5OutboundRouting() {
if echo "${routingRule}" | grep -q "${line}"; then if echo "${routingRule}" | grep -q "${line}"; then
echoContent yellow " ---> ${line}已存在,跳过" echoContent yellow " ---> ${line}已存在,跳过"
else else
local geositeStatus local matchedRuleValue
geositeStatus=$(curl -s "https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}" | jq .message) matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray")
domainRules=$(echo "${domainRules}" | jq -r --arg rule "${matchedRuleValue}" '. += [$rule]')
if [[ "${geositeStatus}" == "null" ]]; then
domainRules=$(echo "${domainRules}" | jq -r ". += [\"geosite:${line}\"]")
else
domainRules=$(echo "${domainRules}" | jq -r ". += [\"domain:${line}\"]")
fi
fi fi
done < <(echo "${socks5RoutingOutboundDomain}" | tr ',' '\n') done < <(echo "${socks5RoutingOutboundDomain}" | tr ',' '\n')
if [[ ! -f "${configPath}09_routing.json" ]]; then if [[ ! -f "${configPath}09_routing.json" ]]; then
@@ -7793,7 +8094,9 @@ setUnlockSNI() {
read -r -p "请按照上面示例录入域名:" xrayDomainList read -r -p "请按照上面示例录入域名:" xrayDomainList
local hosts={} local hosts={}
while read -r domain; do while read -r domain; do
hosts=$(echo "${hosts}" | jq -r ".\"geosite:${domain}\"=\"${setSNIP}\"") local matchedRuleValue
matchedRuleValue=$(getDLCMatchedRuleValue "${domain}" "/etc/v2ray-agent/xray")
hosts=$(echo "${hosts}" | jq -r --arg key "${matchedRuleValue}" --arg value "${setSNIP}" '. + {($key):$value}')
done < <(echo "${xrayDomainList}" | tr ',' '\n') done < <(echo "${xrayDomainList}" | tr ',' '\n')
cat <<EOF >${configPath}11_dns.json cat <<EOF >${configPath}11_dns.json
{ {
@@ -7826,14 +8129,9 @@ addXrayDNSConfig() {
local domainList=$2 local domainList=$2
local domains=[] local domains=[]
while read -r line; do while read -r line; do
local geositeStatus local matchedRuleValue
geositeStatus=$(curl -s "https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}" | jq .message) matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray")
domains=$(echo "${domains}" | jq -r --arg rule "${matchedRuleValue}" '. += [$rule]')
if [[ "${geositeStatus}" == "null" ]]; then
domains=$(echo "${domains}" | jq -r '. += ["geosite:'"${line}"'"]')
else
domains=$(echo "${domains}" | jq -r '. += ["domain:'"${line}"'"]')
fi
done < <(echo "${domainList}" | tr ',' '\n') done < <(echo "${domainList}" | tr ',' '\n')
if [[ "${coreInstallType}" == "1" ]]; then if [[ "${coreInstallType}" == "1" ]]; then
@@ -9649,7 +9947,7 @@ menu() {
cd "$HOME" || exit cd "$HOME" || exit
echoContent red "\n==============================================================" echoContent red "\n=============================================================="
echoContent green "作者:mack-a" echoContent green "作者:mack-a"
echoContent green "当前版本:v3.5.12" echoContent green "当前版本:v3.5.13"
echoContent green "Githubhttps://github.com/mack-a/v2ray-agent" echoContent green "Githubhttps://github.com/mack-a/v2ray-agent"
echoContent green "描述:八合一共存脚本\c" echoContent green "描述:八合一共存脚本\c"
showInstallStatus showInstallStatus
+254 -57
View File
@@ -5545,8 +5545,10 @@ blacklist() {
echoContent red "\n================================================ =================" echoContent red "\n================================================ ================="
echoContent yellow "1.View blocked domain names" echoContent yellow "1.View blocked domain names"
echoContent yellow "2.Add domain name" echoContent yellow "2.Add domain name"
echoContent yellow "3.Block domestic domain names" echoContent yellow "3.Block domestic domain names + IP"
echoContent yellow "4.Delete blacklist" echoContent yellow "4.Delete blacklist/whitelist"
echoContent yellow "5.Add blocked IP"
echoContent yellow "6.Add domain whitelist"
echoContent red "================================================== ===============" echoContent red "================================================== ==============="
read -r -p "Please select:" blacklistStatus read -r -p "Please select:" blacklistStatus
@@ -5575,33 +5577,194 @@ blacklist() {
echoContent green " ---> Added successfully" echoContent green " ---> Added successfully"
elif [[ "${blacklistStatus}" == "3" ]]; then elif [[ "${blacklistStatus}" == "3" ]]; then
local autoAllowDomainList="dl.google.com,apple.com,bing.com,microsoft.com,gstatic.cn"
unInstallRouting blackhole-out outboundTag
unInstallRouting blackhole-ip-out outboundTag
addInstallRouting blackhole-out outboundTag "cn" addInstallRouting blackhole-out outboundTag "cn"
addInstallIPRouting blackhole-ip-out outboundTag "cn"
addInstallRouting allow-domain-direct-out outboundTag "${autoAllowDomainList}" "top"
unInstallOutbounds blackhole-out unInstallOutbounds blackhole-out
unInstallOutbounds blackhole-ip-out
unInstallOutbounds allow-domain-direct-out
outbounds=$(jq -r '.outbounds += [{"protocol":"blackhole","tag":"blackhole-out"}]' ${configPath}10_ipv4_outbounds.json) outbounds=$(jq -r '.outbounds += [{"protocol":"blackhole","tag":"blackhole-out"},{"protocol":"blackhole","tag":"blackhole-ip-out"},{"protocol":"freedom","tag":"allow-domain-direct-out","settings":{"domainStrategy":"UseIP"}}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
echoContent green " ---> Domestic domain name blocked successfully" echoContent green " ---> Domestic domain name + IP blocked successfully"
elif [[ "${blacklistStatus}" == "4" ]]; then elif [[ "${blacklistStatus}" == "4" ]]; then
unInstallRouting blackhole-out outboundTag unInstallRouting blackhole-out outboundTag
unInstallRouting blackhole-ip-out outboundTag
unInstallRouting allow-domain-direct-out outboundTag
echoContent green " ---> Domain name blacklist deleted successfully" unInstallOutbounds blackhole-ip-out
unInstallOutbounds allow-domain-direct-out
echoContent green " ---> Domain blacklist/whitelist deleted successfully"
elif [[ "${blacklistStatus}" == "5" ]]; then
echoContent yellow "Input example:1.1.1.1,8.8.8.8,1.1.1.0/24,2400:3200::/32\n"
read -r -p "Please enter the blocked IP list:" ipList
if [[ -z "${ipList}" ]]; then
echoContent red " ---> ip cannot be empty"
exit 0
fi
addInstallIPRouting blackhole-ip-out outboundTag "${ipList}"
unInstallOutbounds blackhole-ip-out
outbounds=$(jq -r '.outbounds += [{"protocol":"blackhole","tag":"blackhole-ip-out"}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
echoContent green " ---> Blocked IP added successfully"
elif [[ "${blacklistStatus}" == "6" ]]; then
echoContent yellow "Input example:speedtest,openai,google.com\n"
read -r -p "Please enter whitelist domains:" allowDomainList
if [[ -z "${allowDomainList}" ]]; then
echoContent red " ---> domain cannot be empty"
exit 0
fi
addInstallRouting allow-domain-direct-out outboundTag "${allowDomainList}" "top"
unInstallOutbounds allow-domain-direct-out
outbounds=$(jq -r '.outbounds += [{"protocol":"freedom","tag":"allow-domain-direct-out","settings":{"domainStrategy":"UseIP"}}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
echoContent green " ---> Domain whitelist added successfully"
else else
echoContent red " ---> Wrong selection" echoContent red " ---> Wrong selection"
exit 0 exit 0
fi fi
reloadCore reloadCore
} }
# Download dlc.dat_plain.yml into core directory
downloadDLCPlainYAML() {
local corePath=$1
local dlcFilePath="${corePath}/dlc.dat_plain.yml"
local tmpFilePath="${dlcFilePath}.tmp"
if [[ -z "${corePath}" ]]; then
return 1
fi
mkdir -p "${corePath}" >/dev/null 2>&1
if [[ -s "${dlcFilePath}" ]]; then
return 0
fi
local dlcDownloadURL="https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat_plain.yml"
if [[ "${release}" == "alpine" ]]; then
wget -c -q -O "${tmpFilePath}" "${dlcDownloadURL}" >/dev/null 2>&1
else
wget -c -q "${wgetShowProgressStatus}" -O "${tmpFilePath}" "${dlcDownloadURL}" >/dev/null 2>&1
fi
if [[ $? -ne 0 || ! -s "${tmpFilePath}" ]]; then
rm -f "${tmpFilePath}" >/dev/null 2>&1
return 1
fi
mv "${tmpFilePath}" "${dlcFilePath}" >/dev/null 2>&1
}
# Escape grep/regex pattern meta characters
escapeDLCRegexPattern() {
echo "$1" | sed -e 's/[.[\\*^$()+?{|]/\\\\&/g'
}
# Resolve nearest upper name by matched rule line
getDLCNameByRuleLine() {
local ruleLine=$1
local dlcFilePath=$2
awk -v targetLine="${ruleLine}" '
/^[[:space:]]*-[[:space:]]*name:[[:space:]]*/ {
line = $0
sub(/^[[:space:]]*-[[:space:]]*name:[[:space:]]*/, "", line)
currentName = line
}
NR == targetLine {
print currentName
exit
}' "${dlcFilePath}"
}
isDomainFormat() {
local target=$1
[[ "${target}" =~ ^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z0-9-]{2,63}$ ]]
}
# Resolve geosite name from dlc.dat_plain.yml by input domain
getDLCGeositeName() {
local inputRule=$1
local corePath=$2
local dlcFilePath="${corePath}/dlc.dat_plain.yml"
if [[ -z "${inputRule}" || -z "${corePath}" ]]; then
echo ""
return
fi
local normalizedInput
normalizedInput=$(echo "${inputRule}" | tr '[:upper:]' '[:lower:]' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
normalizedInput=${normalizedInput#domain:}
normalizedInput=${normalizedInput#full:}
normalizedInput=${normalizedInput#keyword:}
if [[ -z "${normalizedInput}" ]]; then
echo ""
return
fi
if isDomainFormat "${normalizedInput}"; then
return
fi
if ! downloadDLCPlainYAML "${corePath}"; then
echo ""
return
fi
local escapedInput=
escapedInput=$(escapeDLCRegexPattern "${normalizedInput}")
local matchedLine=
matchedLine=$(grep -n -m1 -E "^[[:space:]]*-[[:space:]]*name:[[:space:]]*${escapedInput}[[:space:]]*$" "${dlcFilePath}")
if [[ -n "${matchedLine}" ]]; then
echo "${normalizedInput}"
fi
}
# Build final rule value: prefer geosite, fallback to domain
getDLCMatchedRuleValue() {
local inputRule=$1
local corePath=$2
local normalizedInput=
normalizedInput=$(echo "${inputRule}" | tr '[:upper:]' '[:lower:]' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if isDomainFormat "${normalizedInput}"; then
local escapedDomain=
escapedDomain=$(escapeDLCRegexPattern "${normalizedInput}")
echo "regexp:.*${escapedDomain}.*"
return
fi
local matchedRuleName=
matchedRuleName=$(getDLCGeositeName "${normalizedInput}" "${corePath}")
if [[ -n "${matchedRuleName}" ]]; then
echo "geosite:${matchedRuleName}"
else
echo "domain:${normalizedInput}"
fi
}
#Add routing configuration #Add routing configuration
addInstallRouting() { addInstallRouting() {
local tag=$1 # warp-socks local tag=$1 # warp-socks
local type=$2 # outboundTag/inboundTag local type=$2 # outboundTag/inboundTag
local domain=$3 # Domain name local domain=$3 # Domain name
local rulePosition=$4
if [[ -z "${tag}" || -z "${type}" || -z "${domain}" ]]; then if [[ -z "${tag}" || -z "${type}" || -z "${domain}" ]]; then
echoContent red " ---> Parameter error" echoContent red " ---> Parameter error"
@@ -5642,24 +5805,83 @@ EOF
if echo "${routingRule}" | grep -q "${line}"; then if echo "${routingRule}" | grep -q "${line}"; then
echoContent yellow " ---> ${line} already exists, skip" echoContent yellow " ---> ${line} already exists, skip"
else else
local geositeStatus local matchedRuleValue
geositeStatus=$(curl -s "https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}" | jq .message) matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray")
routingRule=$(echo "${routingRule}" | jq -r --arg rule "${matchedRuleValue}" '.domain += [$rule]')
if [[ "${geositeStatus}" == "null" ]]; then
routingRule=$(echo "${routingRule}" | jq -r '.domain += ["geosite:'"${line}"'"]')
else
routingRule=$(echo "${routingRule}" | jq -r '.domain += ["domain:'"${line}"'"]')
fi
fi fi
done < <(echo "${domain}" | tr ',' '\n') done < <(echo "${domain}" | tr ',' '\n')
unInstallRouting "${tag}" "${type}" unInstallRouting "${tag}" "${type}"
if ! grep -q "gstatic.com" ${configPath}09_routing.json && [[ "${tag}" == "blackhole-out" ]]; then if ! grep -q "gstatic.com" ${configPath}09_routing.json && [[ "${tag}" == "blackhole-out" ]]; then
local routing= local routing=
routing=$(jq -r ".routing.rules += [{\"type\": \"field\",\"domain\": [\"gstatic.com\"],\"outboundTag\": \"direct\"}]" ${configPath}09_routing.json) routing=$(jq -r ".routing.rules += [{\"type\": \"field\",\"domain\": [\"domain:gstatic.com\"],\"outboundTag\": \"allow-domain-direct-out\"}]" ${configPath}09_routing.json)
echo "${routing}" | jq . >${configPath}09_routing.json echo "${routing}" | jq . >${configPath}09_routing.json
if [[ -f "${configPath}10_ipv4_outbounds.json" ]] && ! grep -q '"allow-domain-direct-out"' "${configPath}10_ipv4_outbounds.json"; then
local outbounds=
outbounds=$(jq -r '.outbounds += [{"protocol":"freedom","tag":"allow-domain-direct-out","settings":{"domainStrategy":"UseIP"}}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
fi
fi fi
if [[ "${rulePosition}" == "top" ]]; then
routing=$(jq -r ".routing.rules = [${routingRule}] + .routing.rules" ${configPath}09_routing.json)
else
routing=$(jq -r ".routing.rules += [${routingRule}]" ${configPath}09_routing.json)
fi
echo "${routing}" | jq . >${configPath}09_routing.json
}
# Add Xray IP block routing
# Supports geoip:cn and custom IPv4/IPv6/CIDR input
addInstallIPRouting() {
local tag=$1
local type=$2
local ipList=$3
if [[ -z "${tag}" || -z "${type}" || -z "${ipList}" ]]; then
echoContent red " ---> Parameter error"
exit 0
fi
if [[ ! -f "${configPath}09_routing.json" ]]; then
cat <<EOF >${configPath}09_routing.json
{
"routing":{
"type": "field",
"rules": []
}
}
EOF
fi
local routingRule=
routingRule=$(jq -r ".routing.rules[]|select(.outboundTag==\"${tag}\" and (.protocol == null) and (.ip != null))" ${configPath}09_routing.json)
if [[ -z "${routingRule}" ]]; then
routingRule="{\"type\": \"field\",\"ip\": [],\"outboundTag\": \"${tag}\"}"
fi
while read -r line; do
line=$(echo "${line}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [[ -z "${line}" ]]; then
continue
fi
local ipRuleValue=${line}
if [[ "${line}" == "cn" ]]; then
ipRuleValue="geoip:cn"
fi
if echo "${routingRule}" | grep -q "${ipRuleValue}"; then
echoContent yellow " ---> ${ipRuleValue} already exists, skip"
else
routingRule=$(echo "${routingRule}" | jq -r '.ip += ["'"${ipRuleValue}"'"]')
fi
done < <(echo "${ipList}" | tr ',' '\n')
unInstallRouting "${tag}" "${type}"
local routing=
routing=$(jq -r ".routing.rules += [${routingRule}]" ${configPath}09_routing.json) routing=$(jq -r ".routing.rules += [${routingRule}]" ${configPath}09_routing.json)
echo "${routing}" | jq . >${configPath}09_routing.json echo "${routing}" | jq . >${configPath}09_routing.json
} }
@@ -6254,14 +6476,9 @@ EOF
local domains= local domains=
domains=[] domains=[]
while read -r line; do while read -r line; do
local geositeStatus local matchedRuleValue
geositeStatus=$(curl -s "https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}" | jq .message) matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray")
domains=$(echo "${domains}" | jq -r --arg rule "${matchedRuleValue}" '. += [$rule]')
if [[ "${geositeStatus}" == "null" ]]; then
domains=$(echo "${domains}" | jq -r '. += ["geosite:'"${line}"'"]')
else
domains=$(echo "${domains}" | jq -r '. += ["domain:'"${line}"'"]')
fi
done < <(echo "${domainList}" | tr ',' '\n') done < <(echo "${domainList}" | tr ',' '\n')
if [[ -f "${configPath}09_routing.json" ]]; then if [[ -f "${configPath}09_routing.json" ]]; then
@@ -6427,7 +6644,9 @@ setUnlockSNI() {
if [[ -n "${domainList}" ]]; then if [[ -n "${domainList}" ]]; then
local hosts={} local hosts={}
while read -r domain; do while read -r domain; do
hosts=$(echo "${hosts}" | jq -r ".\"geosite:${domain}\"=\"${setSNIP}\"") local matchedRuleValue
matchedRuleValue=$(getDLCMatchedRuleValue "${domain}" "/etc/v2ray-agent/xray")
hosts=$(echo "${hosts}" | jq -r --arg key "${matchedRuleValue}" --arg value "${setSNIP}" '. + {($key):$value}')
done < <(echo "${domainList}" | tr ',' '\n') done < <(echo "${domainList}" | tr ',' '\n')
cat <<EOF >${configPath}11_dns.json cat <<EOF >${configPath}11_dns.json
{ {
@@ -6462,6 +6681,16 @@ setUnlockDNS() {
echoContent yellow "netflix,bahamut,hulu,hbo,disney,bbc,4chan,fox,abema,dmm,niconico,pixiv,bilibili,viu" echoContent yellow "netflix,bahamut,hulu,hbo,disney,bbc,4chan,fox,abema,dmm,niconico,pixiv,bilibili,viu"
read -r -p "Please enter the domain name according to the above example:" domainList read -r -p "Please enter the domain name according to the above example:" domainList
if [[ "${domainList}" == "1" ]]; then if [[ "${domainList}" == "1" ]]; then
domainList="netflix,bahamut,hulu,hbo,disney,bbc,4chan,fox,abema,dmm,niconico,pixiv,bilibili,viu"
fi
if [[ -n "${domainList}" ]]; then
local domains=[]
while read -r line; do
local matchedRuleValue
matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray")
domains=$(echo "${domains}" | jq -r --arg rule "${matchedRuleValue}" '. += [$rule]')
done < <(echo "${domainList}" | tr ',' '\n')
cat <<EOF >${configPath}11_dns.json cat <<EOF >${configPath}11_dns.json
{ {
"dns": { "dns": {
@@ -6469,39 +6698,7 @@ setUnlockDNS() {
{ {
"address": "${setDNS}", "address": "${setDNS}",
"port": 53, "port": 53,
"domains": [ "domains": ${domains}
"geosite:netflix",
"geosite:bahamut",
"geosite:hulu",
"geosite:hbo",
"geosite:disney",
"geosite:bbc",
"geosite:4chan",
"geosite:fox",
"geosite:abema",
"geosite:dmm",
"geosite:niconico",
"geosite:pixiv",
"geosite:bilibili",
"geosite:viu"
]
},
"localhost"
]
}
}
EOF
elif [[ -n "${domainList}" ]]; then
cat <<EOF >${configPath}11_dns.json
{
"dns": {
"servers": [
{
"address": "${setDNS}",
"port": 53,
"domains": [
"geosite:${domainList//,/\",\"geosite:}"
]
}, },
"localhost" "localhost"
] ]
@@ -7896,7 +8093,7 @@ menu() {
cd "$HOME" || exit cd "$HOME" || exit
echoContent red "\n================================================ =================" echoContent red "\n================================================ ================="
echoContent green "Author: mack-a" echoContent green "Author: mack-a"
echoContent green "Current version: v2.10.20" echoContent green "Current version: v3.5.13"
echoContent green "Github: https://github.com/mack-a/v2ray-agent" echoContent green "Github: https://github.com/mack-a/v2ray-agent"
echoContent green "Description: 8-in-1 coexistence script\c" echoContent green "Description: 8-in-1 coexistence script\c"
showInstallStatus showInstallStatus