8 Commits
Author SHA1 Message Date
mack-a 11da068e9a sync: update English installer implementation 2026-09-01 00:21:40 +08:00
mack-a 7b151c9623 fix(sing-box): 将配置迁移至 1.14
fix(sing-box): 移除不需要的 Reality 目标
fix(reality): 为 Reality XHTTP 启用 ML-DSA-65
fix(reality): 设置兼容的最低客户端版本
2026-08-31 23:58:56 +08:00
mack-a 89388ca675 Merge pull request #1331 from zetaloop/fix-geosite-name-quotes
fix(脚本): 修复geosite组名带引号时无法识别
2026-08-03 22:55:53 +08:00
zetaloop 8cf91bb313 fix(脚本): 修复geosite组名带引号时无法识别 2026-08-02 02:42:41 +08:00
mack-a 85a2e32188 Merge branch 'master' of another.github.com:mack-a/v2ray-agent 2026-06-07 21:45:46 +08:00
mack-a c959c40b32 feat(脚本): 修复xray核心下载问题 2026-06-07 21:45:41 +08:00
mack-a e33374a74d Merge pull request #1318 from LiebeLee/fix/dns-api-non-wildcard-public-suffix
fix(脚本): 修复 DNS API 申请非通配符证书时仍签发根域导致失败
2026-06-07 21:41:43 +08:00
LiebeLee e53655d573 fix(脚本): 修复 DNS API 申请非通配符证书时仍签发根域导致失败的问题
acmeInstallSSL 在用户回答"是否使用 *.xxx 申请通配符证书 [y/n]"
为 n 时,仍然会向 acme.sh 追加 -d ${dnsTLSDomain},相当于同时
申请子域 + 根域两个证书。这导致使用 dpdns.org、is-a.dev 等
Public Suffix 上的子域时,CF / 阿里云 API 因无权操作根域 zone
直接返回 invalid domain,整体签发失败。

修复:仅当用户选择通配符(y)时才追加根域 -d,n 分支只签发用户
输入的子域。cloudflare 与 aliyun 两个分支同步修复,standalone
分支本就只签单域名,不受影响。

复现:
  域名: abc.dpdns.org
  选择 DNS API -> cloudflare -> 输入 CF Token
  是否使用 *.dpdns.org 通配符 [y/n]: n
  日志报错: invalid domain  _acme-challenge.dpdns.org
2026-06-03 23:32:59 +08:00
5 changed files with 6040 additions and 4188 deletions
+7 -2
View File
@@ -4,6 +4,12 @@
"level": "info",
"timestamp": true
},
"http_clients": [
{
"tag": "rule_set_http",
"detour": "本地直连"
}
],
"experimental": {
"clash_api": {
"external_controller": "127.0.0.1:9090",
@@ -73,7 +79,6 @@
"server": "dns_proxy"
}
],
"independent_cache": true,
"strategy": "prefer_ipv4",
"final": "dns_direct"
},
@@ -210,6 +215,7 @@
}
],
"route": {
"default_http_client": "rule_set_http",
"default_domain_resolver": {
"server": "dns_resolver",
"strategy": "prefer_ipv4"
@@ -458,4 +464,3 @@
"auto_detect_interface": true
}
}
+70 -52
View File
@@ -476,6 +476,8 @@ readInstallProtocolType() {
xrayVLESSRealityXHTTPServerName=$(jq -r .inbounds[0].streamSettings.realitySettings.serverNames[0] "${row}.json")
currentRealityXHTTPPublicKey=$(jq -r .inbounds[0].streamSettings.realitySettings.publicKey "${row}.json")
currentRealityMldsa65Seed=$(jq -r '.inbounds[0].streamSettings.realitySettings.mldsa65Seed // empty' "${row}.json")
currentRealityMldsa65Verify=$(jq -r '.inbounds[0].streamSettings.realitySettings.mldsa65Verify // empty' "${row}.json")
# currentRealityXHTTPPrivateKey=$(jq -r .inbounds[0].streamSettings.realitySettings.privateKey "${row}.json")
# if [[ "${coreInstallType}" == "2" ]]; then
@@ -523,8 +525,8 @@ readInstallProtocolType() {
currentRealityPublicKey=$(jq -r .inbounds[1].streamSettings.realitySettings.publicKey "${row}.json")
currentRealityPrivateKey=$(jq -r .inbounds[1].streamSettings.realitySettings.privateKey "${row}.json")
currentRealityMldsa65Seed=$(jq -r .inbounds[1].streamSettings.realitySettings.mldsa65Seed "${row}.json")
currentRealityMldsa65Verify=$(jq -r .inbounds[1].streamSettings.realitySettings.mldsa65Verify "${row}.json")
currentRealityMldsa65Seed=$(jq -r '.inbounds[1].streamSettings.realitySettings.mldsa65Seed // empty' "${row}.json")
currentRealityMldsa65Verify=$(jq -r '.inbounds[1].streamSettings.realitySettings.mldsa65Verify // empty' "${row}.json")
frontingTypeReality=07_VLESS_vision_reality_inbounds
@@ -1876,16 +1878,21 @@ selectAcmeInstallSSL() {
# 安装SSL证书
acmeInstallSSL() {
local dnsAPIDomain="${tlsDomain}"
local dnsAPIExtraDomain="-d ${dnsTLSDomain}"
if [[ "${dnsAPIStatus}" == "y" ]]; then
dnsAPIDomain="*.${dnsTLSDomain}"
else
# 用户选择不使用通配符时,只为自己输入的子域申请证书,
# 避免脚本追加根域 -d ${dnsTLSDomain} 导致根域不属于自己(例如 dpdns.org 等公共后缀)时签发失败
dnsAPIExtraDomain=""
fi
if [[ "${dnsAPIType}" == "cloudflare" ]]; then
echoContent green " ---> DNS API 生成证书中"
sudo CF_Token="${cfAPIToken}" "$HOME/.acme.sh/acme.sh" --issue -d "${dnsAPIDomain}" -d "${dnsTLSDomain}" --dns dns_cf -k ec-256 --server "${sslType}" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null
sudo CF_Token="${cfAPIToken}" "$HOME/.acme.sh/acme.sh" --issue -d "${dnsAPIDomain}" ${dnsAPIExtraDomain} --dns dns_cf -k ec-256 --server "${sslType}" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null
elif [[ "${dnsAPIType}" == "aliyun" ]]; then
echoContent green " ---> DNS API 生成证书中"
sudo Ali_Key="${aliKey}" Ali_Secret="${aliSecret}" "$HOME/.acme.sh/acme.sh" --issue -d "${dnsAPIDomain}" -d "${dnsTLSDomain}" --dns dns_ali -k ec-256 --server "${sslType}" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null
sudo Ali_Key="${aliKey}" Ali_Secret="${aliSecret}" "$HOME/.acme.sh/acme.sh" --issue -d "${dnsAPIDomain}" ${dnsAPIExtraDomain} --dns dns_ali -k ec-256 --server "${sslType}" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null
else
echoContent green " ---> 生成证书中"
sudo "$HOME/.acme.sh/acme.sh" --issue -d "${tlsDomain}" --standalone -k ec-256 --server "${sslType}" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null
@@ -2502,10 +2509,15 @@ updateXray() {
readInstallType
if [[ -z "${coreInstallType}" || "${coreInstallType}" != "1" ]]; then
if [[ "${prereleaseStatus}" == "true" ]]; then
version=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1)
else
version=$(curl -s https://api.github.com/repos/XTLS/Xray-core/releases/latest | jq -r .tag_name)
fi
if [[ -n "$1" ]]; then
version=$1
else
version=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1)
fi
echoContent green " ---> Xray-core版本:${version}"
@@ -3280,43 +3292,6 @@ initTuicProtocol() {
#EOF
#}
# 初始化singbox route配置
initSingBoxRouteConfig() {
downloadSingBoxGeositeDB
local outboundTag=$1
if [[ ! -f "${singBoxConfigPath}${outboundTag}_route.json" ]]; then
cat <<EOF >"${singBoxConfigPath}${outboundTag}_route.json"
{
"route": {
"geosite": {
"path": "${singBoxConfigPath}geosite.db"
},
"rules": [
{
"domain": [
],
"geosite": [
],
"outbound": "${outboundTag}"
}
]
}
}
EOF
fi
}
# 下载sing-box geosite db
downloadSingBoxGeositeDB() {
if [[ ! -f "${singBoxConfigPath}geosite.db" ]]; then
if [[ "${release}" == "alpine" ]]; then
wget -q -P "${singBoxConfigPath}" https://github.com/Johnshall/sing-geosite/releases/latest/download/geosite.db
else
wget -q "${wgetShowProgressStatus}" -P "${singBoxConfigPath}" https://github.com/Johnshall/sing-geosite/releases/latest/download/geosite.db
fi
fi
}
# 添加sing-box路由规则
addSingBoxRouteRule() {
local outboundTag=$1
@@ -4033,6 +4008,9 @@ EOF
],
"privateKey": "${realityPrivateKey}",
"publicKey": "${realityPublicKey}",
"mldsa65Seed": "${realityMldsa65Seed}",
"mldsa65Verify": "${realityMldsa65Verify}",
"minClientVer": "1.8.2",
"maxTimeDiff": 70000,
"shortIds": [
"",
@@ -4201,6 +4179,7 @@ EOF
"publicKey": "${realityPublicKey}",
"mldsa65Seed": "${realityMldsa65Seed}",
"mldsa65Verify": "${realityMldsa65Verify}",
"minClientVer": "1.8.2",
"maxTimeDiff": 70000,
"shortIds": [
"",
@@ -4887,13 +4866,20 @@ EOF
elif [[ "${type}" == "vlessXHTTP" ]]; then
local xhttpMldsa65Param=
local xhttpMldsa65ParamEncoded=
if [[ -n "${currentRealityMldsa65Verify}" && "${currentRealityMldsa65Verify}" != "null" ]]; then
xhttpMldsa65Param="&pqv=${currentRealityMldsa65Verify}"
xhttpMldsa65ParamEncoded="%26pqv%3D${currentRealityMldsa65Verify}"
fi
echoContent yellow " ---> 通用格式(VLESS+reality+XHTTP)"
echoContent green " vless://${id}@${add}:${port}?encryption=none&security=reality&type=xhttp&sni=${xrayVLESSRealityXHTTPServerName}&host=${xrayVLESSRealityXHTTPServerName}&fp=chrome&path=${path}&pbk=${currentRealityXHTTPPublicKey}&sid=6ba85179e30d4fc2#${email}\n"
echoContent green " vless://${id}@${add}:${port}?encryption=none&security=reality${xhttpMldsa65Param}&type=xhttp&sni=${xrayVLESSRealityXHTTPServerName}&host=${xrayVLESSRealityXHTTPServerName}&fp=chrome&path=${path}&pbk=${currentRealityXHTTPPublicKey}&sid=6ba85179e30d4fc2#${email}\n"
echoContent yellow " ---> 格式化明文(VLESS+reality+XHTTP)"
echoContent green "协议类型:VLESS reality,地址:${add}publicKey:${currentRealityXHTTPPublicKey}shortId: 6ba85179e30d4fc2,serverNames${xrayVLESSRealityXHTTPServerName},端口:${port},路径:${path}SNI:${xrayVLESSRealityXHTTPServerName},伪装域名:${xrayVLESSRealityXHTTPServerName},用户ID:${id},传输方式:xhttp,账户名:${email}\n"
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
vless://${id}@${add}:${port}?encryption=none&security=reality&type=xhttp&sni=${xrayVLESSRealityXHTTPServerName}&fp=chrome&path=${path}&pbk=${currentRealityXHTTPPublicKey}&sid=6ba85179e30d4fc2#${email}
vless://${id}@${add}:${port}?encryption=none&security=reality${xhttpMldsa65Param}&type=xhttp&sni=${xrayVLESSRealityXHTTPServerName}&fp=chrome&path=${path}&pbk=${currentRealityXHTTPPublicKey}&sid=6ba85179e30d4fc2#${email}
EOF
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
@@ -4918,7 +4904,7 @@ EOF
EOF
echoContent yellow " ---> 二维码 VLESS(VLESS+reality+XHTTP)"
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${port}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dxhttp%26sni%3D${xrayVLESSRealityXHTTPServerName}%26fp%3Dchrome%26path%3D${path}%26host%3D${xrayVLESSRealityXHTTPServerName}%26pbk%3D${currentRealityXHTTPPublicKey}%26sid%3D6ba85179e30d4fc2%23${email}\n"
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${port}%3Fencryption%3Dnone%26security%3Dreality${xhttpMldsa65ParamEncoded}%26type%3Dxhttp%26sni%3D${xrayVLESSRealityXHTTPServerName}%26fp%3Dchrome%26path%3D${path}%26host%3D${xrayVLESSRealityXHTTPServerName}%26pbk%3D${currentRealityXHTTPPublicKey}%26sid%3D6ba85179e30d4fc2%23${email}\n"
elif
[[ "${type}" == "vlessgrpc" ]]
@@ -6891,7 +6877,7 @@ getDLCGeositeName() {
escapedInput=$(escapeDLCRegexPattern "${normalizedInput}")
local matchedLine=
matchedLine=$(grep -n -m1 -E "^[[:space:]]*-[[:space:]]*name:[[:space:]]*${escapedInput}[[:space:]]*$" "${dlcFilePath}")
matchedLine=$(grep -n -m1 -E "^[[:space:]]*-[[:space:]]*name:[[:space:]]*\"?${escapedInput}\"?[[:space:]]*$" "${dlcFilePath}")
if [[ -n "${matchedLine}" ]]; then
echo "${normalizedInput}"
fi
@@ -7095,7 +7081,7 @@ addSingBoxGeoIPRouteRule() {
"type": "remote",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-${geoipCode}.srs",
"download_detour": "01_direct_outbound"
"http_client": "rule_set_http"
}
]
}
@@ -7788,7 +7774,7 @@ initSingBoxRules() {
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\"}]")
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\",\"http_client\":\"rule_set_http\"}]")
else
domainRules=$(echo "${domainRules}" | jq -r --arg reg "^([a-zA-Z0-9_-]+\\.)*${normalizedLine//./\\.}" '. += [$reg]')
fi
@@ -7860,13 +7846,44 @@ setSocks5InboundRouting() {
# 设置sniff routing规则
setSniffRouting() {
local singBoxDNSConfigPath="/etc/v2ray-agent/sing-box/conf/config/dns.json"
if [[ -f "${singBoxDNSConfigPath}" ]]; then
jq '
.dns.servers = (.dns.servers // [])
| if any(.dns.servers[]?; .tag == "local") then .
elif any(.dns.servers[]?; .type == "local" and ((.tag // "") == "")) then
.dns.servers |= map(if .type == "local" and ((.tag // "") == "") then .tag = "local" else . end)
else
.dns.servers += [{"tag": "local", "type": "local"}]
end
' "${singBoxDNSConfigPath}" >"${singBoxDNSConfigPath}.tmp" && mv "${singBoxDNSConfigPath}.tmp" "${singBoxDNSConfigPath}"
else
cat <<EOF >"${singBoxDNSConfigPath}"
{
"dns": {
"servers": [
{
"tag": "local",
"type": "local"
}
]
}
}
EOF
fi
cat <<EOF >"/etc/v2ray-agent/sing-box/conf/config/sniff.json"
{
"route":{
"default_domain_resolver": "local",
"rules":[
{
"action": "sniff",
"timeout": "1s"
},
{
"protocol": "dns",
"action": "hijack-dns"
}
]
}
@@ -8316,6 +8333,7 @@ EOF
"dns": {
"servers":[
{
"tag":"local",
"type":"local"
}
]
@@ -9584,7 +9602,7 @@ initRealityMldsa65() {
length=$(/etc/v2ray-agent/xray/xray tls ping "${realityServerName}:${realityDomainPort}" | grep "Certificate chain's total length:" | awk '{print $5}' | head -1)
if [ "$length" -gt 3500 ]; then
if [[ -n "${currentRealityMldsa65}" && -z "${lastInstallationConfig}" ]]; then
if [[ -n "${currentRealityMldsa65Seed}" && -z "${lastInstallationConfig}" ]]; then
read -r -p "读取到上次安装记录,是否使用上次安装时的Seed/Verify [y/n]:" historyMldsa65Status
if [[ "${historyMldsa65Status}" == "y" ]]; then
realityMldsa65Seed=${currentRealityMldsa65Seed}
@@ -9635,7 +9653,7 @@ initRealityClientServersName() {
if [[ "${coreInstallType}" == "1" || "${selectCoreType}" == "1" ]]; then
realityDestDomainList="download-installer.cdn.mozilla.net,addons.mozilla.org,s0.awsstatic.com,d1.awsstatic.com,images-na.ssl-images-amazon.com,m.media-amazon.com,player.live-video.net,one-piece.com,lol.secure.dyn.riotcdn.net,www.lovelive-anime.jp,academy.nvidia.com,dl.google.com,www.google-analytics.com,www.caltech.edu,www.calstatela.edu,www.suny.edu,www.suffolk.edu,www.python.org,vuejs-jp.org,vuejs.org,zh-hk.vuejs.org,react.dev,www.java.com,www.oracle.com,www.mysql.com,www.mongodb.com,redis.io,cname.vercel-dns.com,vercel-dns.com,www.swift.com,academy.nvidia.com,www.swift.com,www.cisco.com,www.asus.com,www.samsung.com,www.amd.com,www.umcg.nl,www.fom-international.com,www.u-can.co.jp,github.io"
elif [[ "${coreInstallType}" == "2" || "${selectCoreType}" == "2" ]]; then
realityDestDomainList="download-installer.cdn.mozilla.net,addons.mozilla.org,s0.awsstatic.com,d1.awsstatic.com,images-na.ssl-images-amazon.com,m.media-amazon.com,player.live-video.net,one-piece.com,lol.secure.dyn.riotcdn.net,www.lovelive-anime.jp,academy.nvidia.com,dl.google.com,www.google-analytics.com,www.python.org,vuejs-jp.org,vuejs.org,zh-hk.vuejs.org,react.dev,www.java.com,www.oracle.com,www.mysql.com,www.mongodb.com,cname.vercel-dns.com,vercel-dns.com,www.swift.com,academy.nvidia.com,www.swift.com,www.cisco.com,www.asus.com,www.samsung.com,www.amd.com,www.fom-international.com,github.io"
realityDestDomainList="download-installer.cdn.mozilla.net,addons.mozilla.org,s0.awsstatic.com,d1.awsstatic.com,images-na.ssl-images-amazon.com,m.media-amazon.com,player.live-video.net,one-piece.com,www.lovelive-anime.jp,academy.nvidia.com,dl.google.com,www.google-analytics.com,www.python.org,vuejs-jp.org,vuejs.org,zh-hk.vuejs.org,react.dev,www.oracle.com,www.mysql.com,www.mongodb.com,cname.vercel-dns.com,vercel-dns.com,www.swift.com,academy.nvidia.com,www.swift.com,www.cisco.com,www.asus.com,www.samsung.com,www.amd.com,www.fom-international.com,github.io"
fi
if [[ -n "${realityServerName}" && -z "${lastInstallationConfig}" ]]; then
if echo ${realityDestDomainList} | grep -q "${realityServerName}"; then
@@ -9978,7 +9996,7 @@ menu() {
cd "$HOME" || exit
echoContent red "\n=============================================================="
echoContent green "作者:mack-a"
echoContent green "当前版本:v3.5.19"
echoContent green "当前版本:v3.5.21"
echoContent green "Githubhttps://github.com/mack-a/v2ray-agent"
echoContent green "描述:八合一共存脚本\c"
showInstallStatus
+2
View File
@@ -2049,6 +2049,7 @@ _buildVisionInbounds() {
"serverNames": ["$(jsonEscape "${sName}")"],
"privateKey": "$(jsonEscape "${privKey}")",
"publicKey": "$(jsonEscape "${pubKey}")",
"minClientVer": "1.8.2",
"maxTimeDiff": 70000,
"shortIds": ["", "6ba85179e30d4fc2"]
}
@@ -2095,6 +2096,7 @@ _buildXHTTPInbound() {
"serverNames": ["$(jsonEscape "${sName}")"],
"privateKey": "$(jsonEscape "${privKey}")",
"publicKey": "$(jsonEscape "${pubKey}")",
"minClientVer": "1.8.2",
"maxTimeDiff": 70000,
"shortIds": ["", "6ba85179e30d4fc2"]
},
+2
View File
@@ -2031,6 +2031,7 @@ _buildVisionInbounds() {
"serverNames": ["$(jsonEscape "${sName}")"],
"privateKey": "$(jsonEscape "${privKey}")",
"publicKey": "$(jsonEscape "${pubKey}")",
"minClientVer": "1.8.2",
"maxTimeDiff": 70000,
"shortIds": ["", "6ba85179e30d4fc2"]
}
@@ -2077,6 +2078,7 @@ _buildXHTTPInbound() {
"serverNames": ["$(jsonEscape "${sName}")"],
"privateKey": "$(jsonEscape "${privKey}")",
"publicKey": "$(jsonEscape "${pubKey}")",
"minClientVer": "1.8.2",
"maxTimeDiff": 70000,
"shortIds": ["", "6ba85179e30d4fc2"]
},
Regular → Executable
+5724 -3899
View File
File diff suppressed because it is too large Load Diff