mirror of
https://github.com/mack-a/v2ray-agent.git
synced 2026-09-02 13:56:37 +00:00
10034 lines
384 KiB
Bash
Executable File
10034 lines
384 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# -------------------------------------------------------------
|
||
# Detection area
|
||
#------------------------------------------------ ----------
|
||
# Check system
|
||
export LANG=en_US.UTF-8
|
||
|
||
echoContent() {
|
||
case $1 in
|
||
# red
|
||
"red")
|
||
# shellcheck disable=SC2154
|
||
# shellcheck disable=SC2154
|
||
${echoType} "\033[31m${printN}$2 \033[0m"
|
||
;;
|
||
# sky blue
|
||
"skyBlue")
|
||
${echoType} "\033[1;36m${printN}$2 \033[0m"
|
||
;;
|
||
# green
|
||
"green")
|
||
${echoType} "\033[32m${printN}$2 \033[0m"
|
||
;;
|
||
# White
|
||
"white")
|
||
${echoType} "\033[37m${printN}$2 \033[0m"
|
||
;;
|
||
"magenta")
|
||
${echoType} "\033[31m${printN}$2 \033[0m"
|
||
;;
|
||
#yellow
|
||
"yellow")
|
||
${echoType} "\033[33m${printN}$2 \033[0m"
|
||
;;
|
||
esac
|
||
}
|
||
# Check SELinux status
|
||
checkCentosSELinux() {
|
||
if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce)" == "Enforcing" ]; then
|
||
echoContent yellow "# Notes"
|
||
echoContent yellow "It is detected that SELinux is turned on. Please turn it off manually. The tutorial is as follows"
|
||
echoContent yellow "https://www.v2ray-agent.com/archives/1684115970026#centos-%E5%85%B3%E9%97%ADselinux"
|
||
exit 0
|
||
fi
|
||
}
|
||
checkSystem() {
|
||
if [[ -n $(find /etc -name "redhat-release") ]] || grep </proc/version -q -i "centos"; then
|
||
mkdir -p /etc/yum.repos.d
|
||
|
||
if [[ -f "/etc/centos-release" ]]; then
|
||
centosVersion=$(rpm -q centos-release | awk -F "[-]" '{print $3}' | awk -F "[.]" '{print $1}')
|
||
|
||
if [[ -z "${centosVersion}" ]] && grep </etc/centos-release -q -i "release 8"; then
|
||
centosVersion=8
|
||
fi
|
||
fi
|
||
|
||
release="centos"
|
||
installType='yum -y install'
|
||
removeType='yum -y remove'
|
||
# upgrade="yum update -y --skip-broken"
|
||
checkCentosSELinux
|
||
elif { [[ -f "/etc/issue" ]] && grep -qi "Alpine" /etc/issue; } || { [[ -f "/proc/version" ]] && grep -qi "Alpine" /proc/version; }; then
|
||
release="alpine"
|
||
installType='apk add'
|
||
upgrade="apk update"
|
||
removeType='apk del'
|
||
nginxConfigPath=/etc/nginx/http.d/
|
||
elif { [[ -f "/etc/issue" ]] && grep -qi "debian" /etc/issue; } || { [[ -f "/proc/version" ]] && grep -qi "debian" /proc/version; } || { [[ -f "/etc/os-release" ]] && grep -qi "ID=debian" /etc/issue; }; then
|
||
release="debian"
|
||
installType='apt -y install'
|
||
upgrade="apt update"
|
||
updateReleaseInfoChange='apt-get --allow-releaseinfo-change update'
|
||
removeType='apt -y autoremove'
|
||
|
||
elif { [[ -f "/etc/issue" ]] && grep -qi "ubuntu" /etc/issue; } || { [[ -f "/proc/version" ]] && grep -qi "ubuntu" /proc/version; }; then
|
||
release="ubuntu"
|
||
installType='apt -y install'
|
||
upgrade="apt update"
|
||
updateReleaseInfoChange='apt-get --allow-releaseinfo-change update'
|
||
removeType='apt -y autoremove'
|
||
if grep </etc/issue -q -i "16."; then
|
||
release=
|
||
fi
|
||
fi
|
||
|
||
if [[ -z ${release} ]]; then
|
||
echoContent red "\nThis script does not support this system, please feedback the following log to the developer\n"
|
||
echoContent yellow "$(cat /etc/issue)"
|
||
echoContent yellow "$(cat /proc/version)"
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
# Check CPU provider
|
||
checkCPUVendor() {
|
||
if [[ -n $(which uname) ]]; then
|
||
if [[ "$(uname)" == "Linux" ]]; then
|
||
case "$(uname -m)" in
|
||
'amd64' | 'x86_64')
|
||
xrayCoreCPUVendor="Xray-linux-64"
|
||
# v2rayCoreCPUVendor="v2ray-linux-64"
|
||
warpRegCoreCPUVendor="main-linux-amd64"
|
||
singBoxCoreCPUVendor="-linux-amd64"
|
||
;;
|
||
'armv8' | 'aarch64')
|
||
cpuVendor="arm"
|
||
xrayCoreCPUVendor="Xray-linux-arm64-v8a"
|
||
# v2rayCoreCPUVendor="v2ray-linux-arm64-v8a"
|
||
warpRegCoreCPUVendor="main-linux-arm64"
|
||
singBoxCoreCPUVendor="-linux-arm64"
|
||
;;
|
||
*)
|
||
echo "This CPU architecture is not supported --->"
|
||
exit 1
|
||
;;
|
||
esac
|
||
fi
|
||
else
|
||
echoContent red "This CPU architecture cannot be recognized, the default is amd64, x86_64--->"
|
||
xrayCoreCPUVendor="Xray-linux-64"
|
||
# v2rayCoreCPUVendor="v2ray-linux-64"
|
||
fi
|
||
}
|
||
|
||
#Initialize global variables
|
||
initVar() {
|
||
installType='yum -y install'
|
||
removeType='yum -y remove'
|
||
upgrade="yum -y update"
|
||
echoType='echo -e'
|
||
# sudoCMD=""
|
||
|
||
#CPU version supported by the core
|
||
xrayCoreCPUVendor=""
|
||
warpRegCoreCPUVendor=""
|
||
cpuVendor=""
|
||
|
||
# domain name
|
||
domain=
|
||
# Total installation progress
|
||
totalProgress=1
|
||
|
||
#1.xray-core installation
|
||
#2.v2ray-core installation
|
||
#3.v2ray-core[xtls] installation
|
||
coreInstallType=
|
||
|
||
# coreInstallPath=
|
||
|
||
# v2ctl Path
|
||
# Core installation path
|
||
# coreInstallPath=
|
||
|
||
# v2ctl Path
|
||
ctlPath=
|
||
# v2rayAgentInstallType=
|
||
|
||
#1.Install all
|
||
#2.Personalized installation
|
||
# v2rayAgentInstallType=
|
||
|
||
# Current personalized installation method 01234
|
||
currentInstallProtocolType=
|
||
|
||
# The order of the current alpn
|
||
currentAlpn=
|
||
|
||
# Prefix type
|
||
frontingType=
|
||
|
||
# Selected personalized installation method
|
||
selectCustomInstallType=
|
||
|
||
# Path to v2ray-core, xray-core configuration files
|
||
configPath=
|
||
|
||
# xray-core reality state
|
||
realityStatus=
|
||
|
||
singBoxConfigPath=
|
||
|
||
|
||
singBoxVLESSVisionPort=
|
||
singBoxVLESSRealityVisionPort=
|
||
singBoxVLESSRealityGRPCPort=
|
||
singBoxHysteria2Port=
|
||
singBoxTrojanPort=
|
||
singBoxTuicPort=
|
||
singBoxNaivePort=
|
||
singBoxVMessWSPort=
|
||
singBoxVLESSWSPort=
|
||
singBoxVMessHTTPUpgradePort=
|
||
|
||
subscribePort=
|
||
|
||
subscribeType=
|
||
|
||
# sing-box reality serverName publicKey
|
||
singBoxVLESSRealityGRPCServerName=
|
||
singBoxVLESSRealityVisionServerName=
|
||
singBoxVLESSRealityPublicKey=
|
||
|
||
# xray-core reality serverName publicKey
|
||
xrayVLESSRealityServerName=
|
||
xrayVLESSRealityPort=
|
||
xrayVLESSRealityXHTTPServerName=
|
||
xrayVLESSRealityXHTTPort=
|
||
# xrayVLESSRealityPublicKey=
|
||
|
||
# interfaceName=
|
||
# interfaceName=
|
||
# Port hopping
|
||
portHoppingStart=
|
||
portHoppingEnd=
|
||
portHopping=
|
||
|
||
hysteria2PortHoppingStart=
|
||
hysteria2PortHoppingEnd=
|
||
hysteria2PortHopping=
|
||
|
||
# tuicPortHoppingStart=
|
||
# tuicPortHoppingEnd=
|
||
# tuicPortHopping=
|
||
|
||
# tuicConfigPath=
|
||
tuicAlgorithm=
|
||
tuicPort=
|
||
|
||
# Path to configuration file
|
||
currentPath=
|
||
|
||
#Configuration file host
|
||
currentHost=
|
||
|
||
#The core type selected during installation
|
||
selectCoreType=
|
||
|
||
# v2rayCoreVersion=
|
||
|
||
# Random path
|
||
customPath=
|
||
|
||
# centos version
|
||
# centos version
|
||
centosVersion=
|
||
|
||
# UUID
|
||
#UUID
|
||
currentUUID=
|
||
|
||
# clients
|
||
#clients
|
||
currentClients=
|
||
|
||
# previousClients
|
||
# previousClients=
|
||
|
||
localIP=
|
||
|
||
# Scheduled task execution task name RenewTLS-update certificate UpdateGeo-update geo file
|
||
cronName=$1
|
||
|
||
#Number of attempts after tls installation failure
|
||
installTLSCount=
|
||
|
||
# BTPanelStatus=
|
||
#BTPanel status
|
||
# BTPanelStatus=
|
||
# Pagoda domain name
|
||
btDomain=
|
||
# nginx configuration file path
|
||
nginxConfigPath=/etc/nginx/conf.d/
|
||
nginxStaticPath=/usr/share/nginx/html/
|
||
|
||
# Is it a preview version?
|
||
prereleaseStatus=false
|
||
|
||
# ssl type
|
||
sslType=
|
||
# SSL CF API Token
|
||
cfAPIToken=
|
||
|
||
#sslmail
|
||
sslEmail=
|
||
|
||
# Check the number of days
|
||
sslRenewalDays=90
|
||
|
||
# dnsSSLStatus=
|
||
|
||
# dns tls domain
|
||
# dns tls domain
|
||
dnsTLSDomain=
|
||
ipType=
|
||
|
||
# installDNSACMEStatus=
|
||
|
||
# Custom port
|
||
customPort=
|
||
|
||
#hysteriaport
|
||
hysteriaPort=
|
||
|
||
# hysteriaProtocol=
|
||
|
||
# hysteriaLag=
|
||
|
||
hysteria2ClientDownloadSpeed=
|
||
|
||
hysteria2ClientUploadSpeed=
|
||
|
||
# Reality
|
||
#Reality
|
||
realityPrivateKey=
|
||
realityServerName=
|
||
realityDestDomain=
|
||
|
||
# isPortOpen=
|
||
# wildcardDomainStatus=
|
||
# nginxIPort=
|
||
|
||
# wget show progress
|
||
#Port status
|
||
# isPortOpen=
|
||
# Wildcard domain name status
|
||
# wildcardDomainStatus=
|
||
# Port checked by nginx
|
||
#nginxIPort=
|
||
|
||
# wget show progress
|
||
wgetShowProgressStatus=
|
||
|
||
# warp
|
||
#warp
|
||
reservedWarpReg=
|
||
publicKeyWarpReg=
|
||
addressWarpReg=
|
||
secretKeyWarpReg=
|
||
|
||
lastInstallationConfig=
|
||
|
||
}
|
||
|
||
# Read tls certificate details
|
||
readAcmeTLS() {
|
||
local readAcmeDomain=
|
||
if [[ -n "${currentHost}" ]]; then
|
||
readAcmeDomain="${currentHost}"
|
||
fi
|
||
|
||
if [[ -n "${domain}" ]]; then
|
||
readAcmeDomain="${domain}"
|
||
fi
|
||
|
||
dnsTLSDomain=$(echo "${readAcmeDomain}" | awk -F "." '{$1="";print $0}' | sed 's/^[[:space:]]*//' | sed 's/ /./g')
|
||
if [[ -d "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc" && -f "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.key" && -f "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer" ]]; then
|
||
installedDNSAPIStatus=true
|
||
fi
|
||
}
|
||
|
||
# Read the default custom port
|
||
readCustomPort() {
|
||
if [[ -n "${configPath}" && -z "${realityStatus}" && "${coreInstallType}" == "1" ]]; then
|
||
local port=
|
||
port=$(jq -r .inbounds[0].port "${configPath}${frontingType}.json")
|
||
if [[ "${port}" != "443" ]]; then
|
||
customPort=${port}
|
||
fi
|
||
fi
|
||
}
|
||
|
||
readNginxSubscribe() {
|
||
subscribeType="https"
|
||
if [[ -f "${nginxConfigPath}subscribe.conf" ]]; then
|
||
if grep -q "sing-box" "${nginxConfigPath}subscribe.conf"; then
|
||
subscribePort=$(grep "listen" "${nginxConfigPath}subscribe.conf" | awk '{print $2}')
|
||
subscribeDomain=$(grep "server_name" "${nginxConfigPath}subscribe.conf" | awk '{print $2}')
|
||
subscribeDomain=${subscribeDomain//;/}
|
||
if [[ -n "${currentHost}" && "${subscribeDomain}" != "${currentHost}" ]]; then
|
||
subscribePort=
|
||
subscribeType=
|
||
else
|
||
if ! grep "listen" "${nginxConfigPath}subscribe.conf" | grep -q "ssl"; then
|
||
subscribeType="http"
|
||
fi
|
||
fi
|
||
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Detect installation method
|
||
readInstallType() {
|
||
coreInstallType=
|
||
configPath=
|
||
singBoxConfigPath=
|
||
|
||
#1.Detect the installation directory
|
||
if [[ -d "/etc/v2ray-agent" ]]; then
|
||
if [[ -f "/etc/v2ray-agent/xray/xray" ]]; then
|
||
if [[ -d "/etc/v2ray-agent/xray/conf" ]] && [[ -f "/etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json" || -f "/etc/v2ray-agent/xray/conf/02_trojan_TCP_inbounds.json" || -f "/etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json" || -f "/etc/v2ray-agent/xray/conf/12_VLESS_XHTTP_inbounds.json" ]]; then
|
||
# xray-core
|
||
#xray-core
|
||
configPath=/etc/v2ray-agent/xray/conf/
|
||
ctlPath=/etc/v2ray-agent/xray/xray
|
||
coreInstallType=1
|
||
|
||
if [[ -f "${configPath}07_VLESS_vision_reality_inbounds.json" ]]; then
|
||
realityStatus=7
|
||
fi
|
||
if [[ -f "${configPath}12_VLESS_XHTTP_inbounds.json" ]]; then
|
||
realityStatus=12
|
||
fi
|
||
if [[ -f "/etc/v2ray-agent/sing-box/sing-box" ]] && [[ -f "/etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json" || -f "/etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json" || -f "/etc/v2ray-agent/sing-box/conf/config/20_socks5_inbounds.json" ]]; then
|
||
singBoxConfigPath=/etc/v2ray-agent/sing-box/conf/config/
|
||
fi
|
||
fi
|
||
elif [[ -f "/etc/v2ray-agent/sing-box/sing-box" && -f "/etc/v2ray-agent/sing-box/conf/config.json" ]]; then
|
||
ctlPath=/etc/v2ray-agent/sing-box/sing-box
|
||
coreInstallType=2
|
||
configPath=/etc/v2ray-agent/sing-box/conf/config/
|
||
singBoxConfigPath=/etc/v2ray-agent/sing-box/conf/config/
|
||
fi
|
||
fi
|
||
}
|
||
|
||
#Read protocol type
|
||
readInstallProtocolType() {
|
||
currentInstallProtocolType=
|
||
frontingType=
|
||
|
||
xrayVLESSRealityPort=
|
||
xrayVLESSRealityServerName=
|
||
|
||
xrayVLESSRealityXHTTPort=
|
||
xrayVLESSRealityXHTTPServerName=
|
||
|
||
# currentRealityXHTTPPrivateKey=
|
||
currentRealityXHTTPPublicKey=
|
||
|
||
currentRealityPrivateKey=
|
||
currentRealityPublicKey=
|
||
|
||
currentRealityMldsa65Seed=
|
||
currentRealityMldsa65Verify=
|
||
|
||
singBoxVLESSVisionPort=
|
||
singBoxHysteria2Port=
|
||
singBoxTrojanPort=
|
||
|
||
frontingTypeReality=
|
||
singBoxVLESSRealityVisionPort=
|
||
singBoxVLESSRealityVisionServerName=
|
||
singBoxVLESSRealityGRPCPort=
|
||
singBoxVLESSRealityGRPCServerName=
|
||
singBoxAnyTLSPort=
|
||
singBoxTuicPort=
|
||
singBoxNaivePort=
|
||
singBoxVMessWSPort=
|
||
singBoxSocks5Port=
|
||
|
||
while read -r row; do
|
||
if echo "${row}" | grep -q VLESS_TCP_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}0,"
|
||
frontingType=02_VLESS_TCP_inbounds
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
singBoxVLESSVisionPort=$(jq .inbounds[0].listen_port "${row}.json")
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q VLESS_WS_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}1,"
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
frontingType=03_VLESS_WS_inbounds
|
||
singBoxVLESSWSPort=$(jq .inbounds[0].listen_port "${row}.json")
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q VLESS_XHTTP_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}12,"
|
||
xrayVLESSRealityXHTTPort=$(jq -r .inbounds[0].port "${row}.json")
|
||
|
||
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
|
||
# frontingType=03_VLESS_WS_inbounds
|
||
# singBoxVLESSWSPort=$(jq .inbounds[0].listen_port "${row}.json")
|
||
# fi
|
||
fi
|
||
|
||
if echo "${row}" | grep -q trojan_gRPC_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}2,"
|
||
fi
|
||
if echo "${row}" | grep -q VMess_WS_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}3,"
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
frontingType=05_VMess_WS_inbounds
|
||
singBoxVMessWSPort=$(jq .inbounds[0].listen_port "${row}.json")
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q trojan_TCP_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}4,"
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
frontingType=04_trojan_TCP_inbounds
|
||
singBoxTrojanPort=$(jq .inbounds[0].listen_port "${row}.json")
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q VLESS_gRPC_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}5,"
|
||
fi
|
||
if echo "${row}" | grep -q hysteria2_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}6,"
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
frontingType=06_hysteria2_inbounds
|
||
singBoxHysteria2Port=$(jq .inbounds[0].listen_port "${row}.json")
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q VLESS_vision_reality_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}7,"
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
xrayVLESSRealityServerName=$(jq -r .inbounds[1].streamSettings.realitySettings.serverNames[0] "${row}.json")
|
||
realityServerName=${xrayVLESSRealityServerName}
|
||
xrayVLESSRealityPort=$(jq -r .inbounds[0].port "${row}.json")
|
||
|
||
realityDomainPort=$(jq -r .inbounds[1].streamSettings.realitySettings.target "${row}.json" | awk -F '[:]' '{print $2}')
|
||
|
||
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 // empty' "${row}.json")
|
||
currentRealityMldsa65Verify=$(jq -r '.inbounds[1].streamSettings.realitySettings.mldsa65Verify // empty' "${row}.json")
|
||
|
||
frontingTypeReality=07_VLESS_vision_reality_inbounds
|
||
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
frontingTypeReality=07_VLESS_vision_reality_inbounds
|
||
singBoxVLESSRealityVisionPort=$(jq -r .inbounds[0].listen_port "${row}.json")
|
||
singBoxVLESSRealityVisionServerName=$(jq -r .inbounds[0].tls.server_name "${row}.json")
|
||
realityDomainPort=$(jq -r .inbounds[0].tls.reality.handshake.server_port "${row}.json")
|
||
|
||
realityServerName=${singBoxVLESSRealityVisionServerName}
|
||
if [[ -f "${configPath}reality_key" ]]; then
|
||
singBoxVLESSRealityPublicKey=$(grep "publicKey" <"${configPath}reality_key" | awk -F "[:]" '{print $2}')
|
||
|
||
currentRealityPrivateKey=$(jq -r .inbounds[0].tls.reality.private_key "${row}.json")
|
||
currentRealityPublicKey=$(grep "publicKey" <"${configPath}reality_key" | awk -F "[:]" '{print $2}')
|
||
fi
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q VLESS_vision_gRPC_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}8,"
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
frontingTypeReality=08_VLESS_vision_gRPC_inbounds
|
||
singBoxVLESSRealityGRPCPort=$(jq -r .inbounds[0].listen_port "${row}.json")
|
||
singBoxVLESSRealityGRPCServerName=$(jq -r .inbounds[0].tls.server_name "${row}.json")
|
||
if [[ -f "${configPath}reality_key" ]]; then
|
||
singBoxVLESSRealityPublicKey=$(grep "publicKey" <"${configPath}reality_key" | awk -F "[:]" '{print $2}')
|
||
fi
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q tuic_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}9,"
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
frontingType=09_tuic_inbounds
|
||
singBoxTuicPort=$(jq .inbounds[0].listen_port "${row}.json")
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q naive_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}10,"
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
frontingType=10_naive_inbounds
|
||
singBoxNaivePort=$(jq .inbounds[0].listen_port "${row}.json")
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q anytls_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}13,"
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
frontingType=13_anytls_inbounds
|
||
singBoxAnyTLSPort=$(jq .inbounds[0].listen_port "${row}.json")
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q VMess_HTTPUpgrade_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}11,"
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
frontingType=11_VMess_HTTPUpgrade_inbounds
|
||
singBoxVMessHTTPUpgradePort=$(grep 'listen' <${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf | awk '{print $2}')
|
||
fi
|
||
fi
|
||
if echo "${row}" | grep -q socks5_inbounds; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}20,"
|
||
singBoxSocks5Port=$(jq .inbounds[0].listen_port "${row}.json")
|
||
fi
|
||
|
||
done < <(find ${configPath} -name "*inbounds.json" | sort | awk -F "[.]" '{print $1}')
|
||
|
||
if [[ "${coreInstallType}" == "1" && -n "${singBoxConfigPath}" ]]; then
|
||
if [[ -f "${singBoxConfigPath}06_hysteria2_inbounds.json" ]]; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}6,"
|
||
singBoxHysteria2Port=$(jq .inbounds[0].listen_port "${singBoxConfigPath}06_hysteria2_inbounds.json")
|
||
fi
|
||
if [[ -f "${singBoxConfigPath}09_tuic_inbounds.json" ]]; then
|
||
currentInstallProtocolType="${currentInstallProtocolType}9,"
|
||
singBoxTuicPort=$(jq .inbounds[0].listen_port "${singBoxConfigPath}09_tuic_inbounds.json")
|
||
fi
|
||
fi
|
||
if [[ "${currentInstallProtocolType:0:1}" != "," ]]; then
|
||
currentInstallProtocolType=",${currentInstallProtocolType}"
|
||
fi
|
||
}
|
||
|
||
# Check whether pagoda is installed
|
||
checkBTPanel() {
|
||
if [[ -n $(pgrep -f "BT-Panel") ]]; then
|
||
# Read domain name
|
||
if [[ -d '/www/server/panel/vhost/cert/' && -n $(find /www/server/panel/vhost/cert/*/fullchain.pem) ]]; then
|
||
if [[ -z "${currentHost}" ]]; then
|
||
echoContent skyBlue "\nRead pagoda configuration\n"
|
||
|
||
find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F "[/]" '{print $7}' | awk '{print NR""":"$0}'
|
||
|
||
read -r -p "Please enter the number to select:" selectBTDomain
|
||
else
|
||
selectBTDomain=$(find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F "[/]" '{print $7}' | awk '{print NR""":"$0}' | grep "${currentHost}" | cut -d ":" -f 1)
|
||
fi
|
||
|
||
if [[ -n "${selectBTDomain}" ]]; then
|
||
btDomain=$(find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F "[/]" '{print $7}' | awk '{print NR""":"$0}' | grep -e "^${selectBTDomain}:" | cut -d ":" -f 2)
|
||
|
||
if [[ -z "${btDomain}" ]]; then
|
||
echoContent red " ---> Wrong selection, please select again"
|
||
checkBTPanel
|
||
else
|
||
domain=${btDomain}
|
||
if [[ ! -f "/etc/v2ray-agent/tls/${btDomain}.crt" && ! -f "/etc/v2ray-agent/tls/${btDomain}.key" ]]; then
|
||
ln -s "/www/server/panel/vhost/cert/${btDomain}/fullchain.pem" "/etc/v2ray-agent/tls/${btDomain}.crt"
|
||
ln -s "/www/server/panel/vhost/cert/${btDomain}/privkey.pem" "/etc/v2ray-agent/tls/${btDomain}.key"
|
||
fi
|
||
|
||
nginxStaticPath="/www/wwwroot/${btDomain}/html/"
|
||
|
||
mkdir -p "/www/wwwroot/${btDomain}/html/"
|
||
|
||
if [[ -f "/www/wwwroot/${btDomain}/.user.ini" ]]; then
|
||
chattr -i "/www/wwwroot/${btDomain}/.user.ini"
|
||
fi
|
||
nginxConfigPath="/www/server/panel/vhost/nginx/"
|
||
fi
|
||
else
|
||
echoContent red " ---> Wrong selection, please select again"
|
||
checkBTPanel
|
||
fi
|
||
fi
|
||
fi
|
||
}
|
||
check1Panel() {
|
||
if [[ -n $(pgrep -f "1panel") ]]; then
|
||
if [[ -d '/opt/1panel/apps/openresty/openresty/www/sites/' && -n $(find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem) ]]; then
|
||
if [[ -z "${currentHost}" ]]; then
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Installation tools"
|
||
|
||
find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem | awk -F "[/]" '{print $9}' | awk '{print NR""":"$0}'
|
||
|
||
read -r -p "Enter the number:" selectBTDomain
|
||
else
|
||
selectBTDomain=$(find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem | awk -F "[/]" '{print $9}' | awk '{print NR""":"$0}' | grep "${currentHost}" | cut -d ":" -f 1)
|
||
fi
|
||
|
||
if [[ -n "${selectBTDomain}" ]]; then
|
||
btDomain=$(find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem | awk -F "[/]" '{print $9}' | awk '{print NR""":"$0}' | grep "${selectBTDomain}:" | cut -d ":" -f 2)
|
||
|
||
if [[ -z "${btDomain}" ]]; then
|
||
echoContent red " ---> $1 port opening failed"
|
||
check1Panel
|
||
else
|
||
domain=${btDomain}
|
||
if [[ ! -f "/etc/v2ray-agent/tls/${btDomain}.crt" && ! -f "/etc/v2ray-agent/tls/${btDomain}.key" ]]; then
|
||
ln -s "/opt/1panel/apps/openresty/openresty/www/sites/${btDomain}/ssl/fullchain.pem" "/etc/v2ray-agent/tls/${btDomain}.crt"
|
||
ln -s "/opt/1panel/apps/openresty/openresty/www/sites/${btDomain}/ssl/privkey.pem" "/etc/v2ray-agent/tls/${btDomain}.key"
|
||
fi
|
||
|
||
nginxStaticPath="/opt/1panel/apps/openresty/openresty/www/sites/${btDomain}/index/"
|
||
fi
|
||
else
|
||
echoContent red " ---> $1 port opening failed"
|
||
check1Panel
|
||
fi
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Check firewall
|
||
allowPort() {
|
||
local type=$2
|
||
if [[ -z "${type}" ]]; then
|
||
type=tcp
|
||
fi
|
||
if command -v dpkg >/dev/null 2>&1 && dpkg -l | grep -q "^[[:space:]]*ii[[:space:]]\+ufw"; then
|
||
if ufw status | grep -q "Status: active"; then
|
||
if ! ufw status | grep -q "$1/${type}"; then
|
||
sudo ufw allow "$1/${type}"
|
||
checkUFWAllowPort "$1"
|
||
fi
|
||
fi
|
||
elif systemctl status firewalld 2>/dev/null | grep -q "active (running)"; then
|
||
local updateFirewalldStatus=
|
||
if ! firewall-cmd --list-ports --permanent | grep -qw "$1/${type}"; then
|
||
updateFirewalldStatus=true
|
||
local firewallPort=$1
|
||
if echo "${firewallPort}" | grep -q ":"; then
|
||
firewallPort=$(echo "${firewallPort}" | awk -F ":" '{print $1"-"$2}')
|
||
fi
|
||
firewall-cmd --zone=public --add-port="${firewallPort}/${type}" --permanent
|
||
checkFirewalldAllowPort "${firewallPort}"
|
||
fi
|
||
|
||
if echo "${updateFirewalldStatus}" | grep -q "true"; then
|
||
firewall-cmd --reload
|
||
fi
|
||
elif rc-update show 2>/dev/null | grep -q ufw; then
|
||
if ufw status | grep -q "Status: active"; then
|
||
if ! ufw status | grep -q "$1/${type}"; then
|
||
sudo ufw allow "$1/${type}"
|
||
checkUFWAllowPort "$1"
|
||
fi
|
||
fi
|
||
elif dpkg -l | grep -q "^[[:space:]]*ii[[:space:]]\+netfilter-persistent" && systemctl status netfilter-persistent 2>/dev/null | grep -q "active (exited)"; then
|
||
local updateFirewalldStatus=
|
||
if ! iptables -L | grep -q "$1/${type}(mack-a)"; then
|
||
updateFirewalldStatus=true
|
||
iptables -I INPUT -p "${type}" --dport "$1" -m comment --comment "allow $1/${type}(mack-a)" -j ACCEPT
|
||
fi
|
||
|
||
if echo "${updateFirewalldStatus}" | grep -q "true"; then
|
||
netfilter-persistent save
|
||
fi
|
||
fi
|
||
}
|
||
# Get public IP
|
||
getPublicIP() {
|
||
local type=4
|
||
if [[ -n "$1" ]]; then
|
||
type=$1
|
||
fi
|
||
if [[ -n "${currentHost}" && -z "$1" ]] && [[ "${singBoxVLESSRealityVisionServerName}" == "${currentHost}" || "${singBoxVLESSRealityGRPCServerName}" == "${currentHost}" || "${xrayVLESSRealityServerName}" == "${currentHost}" ]]; then
|
||
echo "${currentHost}"
|
||
else
|
||
local currentIP=
|
||
currentIP=$(curl -s "-${type}" http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | awk -F "[=]" '{print $2}')
|
||
if [[ -z "${currentIP}" && -z "$1" ]]; then
|
||
currentIP=$(curl -s "-6" http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | awk -F "[=]" '{print $2}')
|
||
fi
|
||
echo "${currentIP}"
|
||
fi
|
||
|
||
}
|
||
|
||
# Output ufw port open status
|
||
checkUFWAllowPort() {
|
||
if ufw status | grep -q "$1"; then
|
||
echoContent green " ---> $1 port opened successfully"
|
||
else
|
||
echoContent red "acme installation failed--->"
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
# Output firewall-cmd port open status
|
||
checkFirewalldAllowPort() {
|
||
if firewall-cmd --list-ports --permanent | grep -q "$1"; then
|
||
echoContent green " ---> $1 port opened successfully"
|
||
else
|
||
echoContent red "1.Failed to obtain Github files. Please wait for Github to recover and try again. The recovery progress can be viewed [https://www.githubstatus.com/]"
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
readSingBoxConfig() {
|
||
tuicPort=
|
||
hysteriaPort=
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
|
||
if [[ -f "${singBoxConfigPath}09_tuic_inbounds.json" ]]; then
|
||
tuicPort=$(jq -r '.inbounds[0].listen_port' "${singBoxConfigPath}09_tuic_inbounds.json")
|
||
tuicAlgorithm=$(jq -r '.inbounds[0].congestion_control' "${singBoxConfigPath}09_tuic_inbounds.json")
|
||
fi
|
||
if [[ -f "${singBoxConfigPath}06_hysteria2_inbounds.json" ]]; then
|
||
hysteriaPort=$(jq -r '.inbounds[0].listen_port' "${singBoxConfigPath}06_hysteria2_inbounds.json")
|
||
hysteria2ClientUploadSpeed=$(jq -r '.inbounds[0].down_mbps' "${singBoxConfigPath}06_hysteria2_inbounds.json")
|
||
hysteria2ClientDownloadSpeed=$(jq -r '.inbounds[0].up_mbps' "${singBoxConfigPath}06_hysteria2_inbounds.json")
|
||
fi
|
||
fi
|
||
}
|
||
|
||
readLastInstallationConfig() {
|
||
if [[ -n "${configPath}" ]]; then
|
||
read -r -p "Previous installation configuration found. Use it? [y/n]:" lastInstallationConfigStatus
|
||
if [[ "${lastInstallationConfigStatus}" == "y" ]]; then
|
||
lastInstallationConfig=true
|
||
fi
|
||
fi
|
||
}
|
||
unInstallSingBox() {
|
||
local type=$1
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
if grep -q 'tuic' </etc/v2ray-agent/sing-box/conf/config.json && [[ "${type}" == "tuic" ]]; then
|
||
rm "${singBoxConfigPath}09_tuic_inbounds.json"
|
||
echoContent green " ---> Check and install updates [The new machine will be very slow. If there is no response for a long time, please stop it manually and then execute it again]"
|
||
fi
|
||
|
||
if grep -q 'hysteria2' </etc/v2ray-agent/sing-box/conf/config.json && [[ "${type}" == "hysteria2" ]]; then
|
||
rm "${singBoxConfigPath}06_hysteria2_inbounds.json"
|
||
echoContent green " ---> Install wget"
|
||
fi
|
||
rm "${singBoxConfigPath}config.json"
|
||
fi
|
||
|
||
readInstallType
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
echoContent yellow "https://www.v2ray-agent.com/archives/1679931532764#heading-8 "
|
||
handleSingBox stop
|
||
handleSingBox start
|
||
else
|
||
handleSingBox stop
|
||
rm /etc/systemd/system/sing-box.service
|
||
rm -rf /etc/v2ray-agent/sing-box/*
|
||
echoContent green " ---> Install curl"
|
||
fi
|
||
}
|
||
|
||
# Check the file directory and path
|
||
readConfigHostPathUUID() {
|
||
currentPath=
|
||
currentDefaultPort=
|
||
currentUUID=
|
||
currentClients=
|
||
currentHost=
|
||
currentPort=
|
||
currentCDNAddress=
|
||
singBoxVMessWSPath=
|
||
singBoxVLESSWSPath=
|
||
singBoxVMessHTTPUpgradePath=
|
||
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
|
||
# Install
|
||
if [[ -n "${frontingType}" ]]; then
|
||
currentHost=$(jq -r .inbounds[0].streamSettings.tlsSettings.certificates[0].certificateFile ${configPath}${frontingType}.json | awk -F '[t][l][s][/]' '{print $2}' | awk -F '[.][c][r][t]' '{print $1}')
|
||
|
||
currentPort=$(jq .inbounds[0].port ${configPath}${frontingType}.json)
|
||
|
||
local defaultPortFile=
|
||
defaultPortFile=$(find ${configPath}* | grep "default")
|
||
|
||
if [[ -n "${defaultPortFile}" ]]; then
|
||
currentDefaultPort=$(echo "${defaultPortFile}" | awk -F [_] '{print $4}')
|
||
else
|
||
currentDefaultPort=$(jq -r .inbounds[0].port ${configPath}${frontingType}.json)
|
||
fi
|
||
currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}${frontingType}.json)
|
||
currentClients=$(jq -r .inbounds[0].settings.clients ${configPath}${frontingType}.json)
|
||
fi
|
||
|
||
# reality
|
||
if echo ${currentInstallProtocolType} | grep -q ",7,"; then
|
||
|
||
currentClients=$(jq -r .inbounds[1].settings.clients ${configPath}07_VLESS_vision_reality_inbounds.json)
|
||
currentUUID=$(jq -r .inbounds[1].settings.clients[0].id ${configPath}07_VLESS_vision_reality_inbounds.json)
|
||
xrayVLESSRealityVisionPort=$(jq -r .inbounds[0].port ${configPath}07_VLESS_vision_reality_inbounds.json)
|
||
if [[ "${currentPort}" == "${xrayVLESSRealityVisionPort}" ]]; then
|
||
xrayVLESSRealityVisionPort="${currentDefaultPort}"
|
||
fi
|
||
fi
|
||
# reality xhttp
|
||
if echo ${currentInstallProtocolType} | grep -q ",12,"; then
|
||
|
||
currentClients=$(jq -r .inbounds[0].settings.clients ${configPath}12_VLESS_XHTTP_inbounds.json)
|
||
currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}12_VLESS_XHTTP_inbounds.json)
|
||
xrayVLESSRealityXHTTPort=$(jq -r .inbounds[0].port ${configPath}12_VLESS_XHTTP_inbounds.json)
|
||
if [[ "${currentPort}" == "${xrayVLESSRealityXHTTPort}" ]]; then
|
||
xrayVLESSRealityXHTTPort="${currentDefaultPort}"
|
||
fi
|
||
currentPath=$(jq -r .inbounds[0].streamSettings.xhttpSettings.path ${configPath}12_VLESS_XHTTP_inbounds.json | awk -F "[/]" '{print $2}' | awk -F "[x][H][T][T][P]" '{print $1}')
|
||
fi
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
if [[ -n "${frontingType}" ]]; then
|
||
currentHost=$(jq -r .inbounds[0].tls.server_name ${configPath}${frontingType}.json)
|
||
if echo ${currentInstallProtocolType} | grep -q ",11," && [[ "${currentHost}" == "null" ]]; then
|
||
currentHost=$(grep 'server_name' <${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf | awk '{print $2}')
|
||
currentHost=${currentHost//;/}
|
||
fi
|
||
currentUUID=$(jq -r .inbounds[0].users[0].uuid ${configPath}${frontingType}.json)
|
||
currentClients=$(jq -r .inbounds[0].users ${configPath}${frontingType}.json)
|
||
else
|
||
currentUUID=$(jq -r .inbounds[0].users[0].uuid ${configPath}${frontingTypeReality}.json)
|
||
currentClients=$(jq -r .inbounds[0].users ${configPath}${frontingTypeReality}.json)
|
||
fi
|
||
fi
|
||
|
||
#Read path
|
||
if [[ -n "${configPath}" && -n "${frontingType}" ]]; then
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
local fallback
|
||
fallback=$(jq -r -c '.inbounds[0].settings.fallbacks[]|select(.path)' ${configPath}${frontingType}.json | head -1)
|
||
|
||
local path
|
||
path=$(echo "${fallback}" | jq -r .path | awk -F "[/]" '{print $2}')
|
||
|
||
if [[ $(echo "${fallback}" | jq -r .dest) == 31297 ]]; then
|
||
currentPath=$(echo "${path}" | awk -F "[w][s]" '{print $1}')
|
||
elif [[ $(echo "${fallback}" | jq -r .dest) == 31299 ]]; then
|
||
currentPath=$(echo "${path}" | awk -F "[v][w][s]" '{print $1}')
|
||
fi
|
||
|
||
# Try to read alpn h2 Path
|
||
if [[ -z "${currentPath}" ]]; then
|
||
dest=$(jq -r -c '.inbounds[0].settings.fallbacks[]|select(.alpn)|.dest' ${configPath}${frontingType}.json | head -1)
|
||
if [[ "${dest}" == "31302" || "${dest}" == "31304" ]]; then
|
||
# checkBTPanel
|
||
# check1Panel
|
||
if grep -q "trojangrpc {" <${nginxConfigPath}alone.conf; then
|
||
currentPath=$(grep "trojangrpc {" <${nginxConfigPath}alone.conf | awk -F "[/]" '{print $2}' | awk -F "[t][r][o][j][a][n]" '{print $1}')
|
||
elif grep -q "grpc {" <${nginxConfigPath}alone.conf; then
|
||
currentPath=$(grep "grpc {" <${nginxConfigPath}alone.conf | head -1 | awk -F "[/]" '{print $2}' | awk -F "[g][r][p][c]" '{print $1}')
|
||
fi
|
||
fi
|
||
fi
|
||
if [[ -z "${currentPath}" && -f "${configPath}12_VLESS_XHTTP_inbounds.json" ]]; then
|
||
currentPath=$(jq -r .inbounds[0].streamSettings.xhttpSettings.path "${configPath}12_VLESS_XHTTP_inbounds.json" | awk -F "[x][H][T][T][P]" '{print $1}' | awk -F "[/]" '{print $2}')
|
||
fi
|
||
elif [[ "${coreInstallType}" == "2" && -f "${singBoxConfigPath}05_VMess_WS_inbounds.json" ]]; then
|
||
singBoxVMessWSPath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}05_VMess_WS_inbounds.json")
|
||
currentPath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}05_VMess_WS_inbounds.json" | awk -F "[/]" '{print $2}')
|
||
fi
|
||
if [[ "${coreInstallType}" == "2" && -f "${singBoxConfigPath}03_VLESS_WS_inbounds.json" ]]; then
|
||
singBoxVLESSWSPath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}03_VLESS_WS_inbounds.json")
|
||
currentPath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}03_VLESS_WS_inbounds.json" | awk -F "[/]" '{print $2}')
|
||
currentPath=${currentPath::-2}
|
||
fi
|
||
if [[ "${coreInstallType}" == "2" && -f "${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json" ]]; then
|
||
singBoxVMessHTTPUpgradePath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json")
|
||
currentPath=$(jq -r .inbounds[0].transport.path "${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json" | awk -F "[/]" '{print $2}')
|
||
fi
|
||
fi
|
||
if [[ -f "/etc/v2ray-agent/cdn" ]] && [[ -n "$(head -1 /etc/v2ray-agent/cdn)" ]]; then
|
||
currentCDNAddress=$(head -1 /etc/v2ray-agent/cdn)
|
||
else
|
||
currentCDNAddress="${currentHost}"
|
||
fi
|
||
}
|
||
|
||
# Status display
|
||
showInstallStatus() {
|
||
if [[ -n "${coreInstallType}" ]]; then
|
||
if [[ "${coreInstallType}" == 1 ]]; then
|
||
if [[ -n $(pgrep -f "xray/xray") ]]; then
|
||
echoContent yellow "$(cat /etc/issue)"
|
||
else
|
||
echoContent yellow "$(cat /proc/version)"
|
||
fi
|
||
|
||
elif [[ "${coreInstallType}" == 2 ]]; then
|
||
if [[ -n $(pgrep -f "sing-box/sing-box") ]]; then
|
||
echoContent yellow "\nCore: Xray-core[Running]"
|
||
else
|
||
echoContent yellow "\nCore: Xray-core[not running]"
|
||
fi
|
||
fi
|
||
#Read protocol type
|
||
readInstallProtocolType
|
||
|
||
if [[ -n ${currentInstallProtocolType} ]]; then
|
||
echoContent yellow "\nCore: v2ray-core[Running]"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",0,"; then
|
||
echoContent yellow "VLESS+TCP[TLS_Vision] \c"
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",1,"; then
|
||
echoContent yellow "VLESS+WS[TLS] \c"
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",2,"; then
|
||
echoContent yellow "Trojan+gRPC[TLS] \c"
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",3,"; then
|
||
echoContent yellow "VMess+WS[TLS] \c"
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",4,"; then
|
||
echoContent yellow "Trojan+TCP[TLS] \c"
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",5,"; then
|
||
echoContent yellow "VLESS+gRPC[TLS] \c"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",6,"; then
|
||
echoContent yellow "Hysteria2 \c"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",7,"; then
|
||
echoContent yellow "VLESS+Reality+Vision \c"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",8,"; then
|
||
echoContent yellow "VLESS+Reality+gRPC \c"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",9,"; then
|
||
echoContent yellow "Tuic \c"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",10,"; then
|
||
echoContent yellow "Naive \c"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",11,"; then
|
||
echoContent yellow "VMess+TLS+HTTPUpgrade \c"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",12,"; then
|
||
echoContent yellow "VLESS+Reality+XHTTP \c"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",13,"; then
|
||
echoContent yellow "AnyTLS \c"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Clean up old residue
|
||
cleanUp() {
|
||
if [[ "$1" == "xrayDel" ]]; then
|
||
handleXray stop
|
||
rm -rf /etc/v2ray-agent/xray/*
|
||
elif [[ "$1" == "singBoxDel" ]]; then
|
||
handleSingBox stop
|
||
rm -rf /etc/v2ray-agent/sing-box/conf/config.json >/dev/null 2>&1
|
||
rm -rf /etc/v2ray-agent/sing-box/conf/config/* >/dev/null 2>&1
|
||
fi
|
||
}
|
||
initVar "$1"
|
||
checkSystem
|
||
checkCPUVendor
|
||
|
||
readInstallType
|
||
readInstallProtocolType
|
||
readConfigHostPathUUID
|
||
readCustomPort
|
||
readSingBoxConfig
|
||
# -------------------------------------------------------------
|
||
|
||
#------------------------------------------------ ----------
|
||
|
||
#Initialize the installation directory
|
||
mkdirTools() {
|
||
mkdir -p /etc/v2ray-agent/tls
|
||
mkdir -p /etc/v2ray-agent/subscribe_local/default
|
||
mkdir -p /etc/v2ray-agent/subscribe_local/clashMeta
|
||
|
||
mkdir -p /etc/v2ray-agent/subscribe_remote/default
|
||
mkdir -p /etc/v2ray-agent/subscribe_remote/clashMeta
|
||
|
||
mkdir -p /etc/v2ray-agent/subscribe/default
|
||
mkdir -p /etc/v2ray-agent/subscribe/clashMetaProfiles
|
||
mkdir -p /etc/v2ray-agent/subscribe/clashMeta
|
||
|
||
mkdir -p /etc/v2ray-agent/subscribe/sing-box
|
||
mkdir -p /etc/v2ray-agent/subscribe/sing-box_profiles
|
||
mkdir -p /etc/v2ray-agent/subscribe_local/sing-box
|
||
|
||
mkdir -p /etc/v2ray-agent/xray/conf
|
||
mkdir -p /etc/v2ray-agent/xray/reality_scan
|
||
mkdir -p /etc/v2ray-agent/xray/tmp
|
||
mkdir -p /etc/systemd/system/
|
||
mkdir -p /tmp/v2ray-agent-tls/
|
||
|
||
mkdir -p /etc/v2ray-agent/warp
|
||
|
||
mkdir -p /etc/v2ray-agent/sing-box/conf/config
|
||
|
||
mkdir -p /usr/share/nginx/html/
|
||
}
|
||
checkRoot() {
|
||
if [ "$(id -u)" -ne 0 ]; then
|
||
# sudoCMD="sudo"
|
||
echo "${currentHost}"
|
||
fi
|
||
}
|
||
# Install toolkit
|
||
installTools() {
|
||
echoContent skyBlue "sed -i \"1i\\\nameserver 2001:67c:2b0::4\\\nnameserver 2a00:1098:2c::1\" /etc/resolv.conf"
|
||
# Repair individual system problems in ubuntu
|
||
if [[ "${release}" == "ubuntu" ]]; then
|
||
dpkg --configure -a
|
||
fi
|
||
|
||
if [[ -n $(pgrep -f "apt") ]]; then
|
||
pgrep -f apt | xargs kill -9
|
||
fi
|
||
|
||
echoContent green " ---> install unzip"
|
||
|
||
if [[ "${release}" != "centos" ]]; then
|
||
${upgrade} >/etc/v2ray-agent/install.log 2>&1
|
||
fi
|
||
|
||
if grep <"/etc/v2ray-agent/install.log" -q "changed"; then
|
||
${updateReleaseInfoChange} >/dev/null 2>&1
|
||
fi
|
||
|
||
if [[ "${release}" == "centos" ]]; then
|
||
rm -rf /var/run/yum.pid
|
||
${installType} epel-release >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! sudo --version >/dev/null 2>&1; then
|
||
echoContent green " ---> Install socat"
|
||
${installType} sudo >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! wget --help >/dev/null 2>&1; then
|
||
echoContent green " ---> Install tar"
|
||
${installType} wget >/dev/null 2>&1
|
||
fi
|
||
|
||
# if ! command -v netfilter-persistent >/dev/null 2>&1; then
|
||
# if [[ "${release}" != "centos" ]]; then
|
||
# echo "iptables-persistent iptables-persistent/autosave_v4 boolean true" | sudo debconf-set-selections
|
||
# echo "iptables-persistent iptables-persistent/autosave_v6 boolean true" | sudo debconf-set-selections
|
||
# ${installType} iptables-persistent >/dev/null 2>&1
|
||
# fi
|
||
# fi
|
||
|
||
if ! curl --help >/dev/null 2>&1; then
|
||
echoContent green " ---> install crontabs"
|
||
${installType} curl >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! unzip >/dev/null 2>&1; then
|
||
echoContent green " ---> Install jq"
|
||
${installType} unzip >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! socat -h >/dev/null 2>&1; then
|
||
echoContent green " ---> Install binutils"
|
||
${installType} socat >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! tar --help >/dev/null 2>&1; then
|
||
echoContent green " ---> Install ping6"
|
||
${installType} tar >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! crontab -l >/dev/null 2>&1; then
|
||
echoContent green " ---> Install qrencode"
|
||
if [[ "${release}" == "ubuntu" || "${release}" == "debian" ]]; then
|
||
${installType} cron >/dev/null 2>&1
|
||
else
|
||
${installType} crontabs >/dev/null 2>&1
|
||
fi
|
||
fi
|
||
if ! jq --help >/dev/null 2>&1; then
|
||
echoContent green " ---> install sudo"
|
||
${installType} jq >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! command -v ld >/dev/null 2>&1; then
|
||
echoContent green " ---> install lsb-release"
|
||
${installType} binutils >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! openssl help >/dev/null 2>&1; then
|
||
echoContent green " ---> Install lsof"
|
||
${installType} openssl >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! ping6 --help >/dev/null 2>&1; then
|
||
echoContent green " ---> Install dig"
|
||
${installType} inetutils-ping >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! qrencode --help >/dev/null 2>&1; then
|
||
echoContent green " ---> Detected services that do not depend on Nginx, skip installation"
|
||
${installType} qrencode >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! command -v lsb_release >/dev/null 2>&1; then
|
||
if [[ "${release}" == "ubuntu" || "${release}" == "debian" ]]; then
|
||
${installType} lsb-release >/dev/null 2>&1
|
||
elif [[ "${release}" == "centos" ]]; then
|
||
${installType} redhat-lsb-core >/dev/null 2>&1
|
||
else
|
||
${installType} lsb-release >/dev/null 2>&1
|
||
fi
|
||
fi
|
||
|
||
if ! lsof -h >/dev/null 2>&1; then
|
||
echoContent green " ---> Install nginx"
|
||
${installType} lsof >/dev/null 2>&1
|
||
fi
|
||
|
||
if ! dig -h >/dev/null 2>&1; then
|
||
echoContent green " ---> Install nginx"
|
||
if echo "${installType}" | grep -qw "apt"; then
|
||
${installType} dnsutils >/dev/null 2>&1
|
||
elif echo "${installType}" | grep -qw "yum"; then
|
||
${installType} bind-utils >/dev/null 2>&1
|
||
elif echo "${installType}" | grep -qw "apk"; then
|
||
${installType} bind-tools >/dev/null 2>&1
|
||
fi
|
||
fi
|
||
|
||
if echo "${selectCustomInstallType}" | grep -qwE ",7,|,8,|,7,8,|,12,|,7,12,"; then
|
||
echoContent green " ---> Install semanage"
|
||
else
|
||
if ! nginx >/dev/null 2>&1; then
|
||
echoContent green " ---> Detected services that do not depend on certificates, skip installation"
|
||
installNginxTools
|
||
else
|
||
nginxVersion=$(nginx -v 2>&1)
|
||
nginxVersion=$(echo "${nginxVersion}" | awk -F "[n][g][i][n][x][/]" '{print $2}' | awk -F "[.]" '{print $2}')
|
||
if [[ ${nginxVersion} -lt 14 ]]; then
|
||
read -r -p "Read that the current Nginx version does not support gRPC, which will cause the installation to fail. Do you want to uninstall Nginx and reinstall it? [y/n]:" unInstallNginxStatus
|
||
if [[ "${unInstallNginxStatus}" == "y" ]]; then
|
||
${removeType} nginx >/dev/null 2>&1
|
||
echoContent yellow "\nCore: v2ray-core[not running]"
|
||
echoContent green " ---> Install acme.sh"
|
||
installNginxTools >/dev/null 2>&1
|
||
else
|
||
exit 0
|
||
fi
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
# if ! command -v semanage >/dev/null 2>&1 && [[ "${release}" == "centos" ]]; then
|
||
# if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce)" == "Enforcing" ]; then
|
||
# if [[ "${centosVersion}" == "7" ]]; then
|
||
# policyCoreUtils="policycoreutils-python"
|
||
# elif [[ "${centosVersion}" == "8" || "${centosVersion}" == "9" || "${centosVersion}" == "10" ]]; then
|
||
# policyCoreUtils="policycoreutils-python-utils"
|
||
# fi
|
||
#
|
||
# if [[ -n "${policyCoreUtils}" ]]; then
|
||
# ${installType} bash-completion >/dev/null 2>&1
|
||
# ${installType} ${policyCoreUtils} >/dev/null 2>&1
|
||
# fi
|
||
# if [[ -n $(which semanage) ]]; then
|
||
# semanage port -a -t http_port_t -p tcp 31300
|
||
# fi
|
||
# fi
|
||
# fi
|
||
|
||
# Detect nginx version and provide the option of uninstalling it
|
||
if [[ "${selectCustomInstallType}" == "7" ]]; then
|
||
echoContent green " ---> Install WARP"
|
||
else
|
||
if [[ ! -d "$HOME/.acme.sh" ]] || [[ -d "$HOME/.acme.sh" && -z $(find "$HOME/.acme.sh/acme.sh") ]]; then
|
||
echoContent green " ---> WARP started successfully"
|
||
curl -s https://get.acme.sh | sh >/etc/v2ray-agent/tls/acme.log 2>&1
|
||
|
||
if [[ ! -d "$HOME/.acme.sh" ]] || [[ -z $(find "$HOME/.acme.sh/acme.sh") ]]; then
|
||
echoContent red "2.There is a bug in the acme.sh script, please check [https://github.com/acmesh-official/acme.sh] issues"
|
||
tail -n 100 /etc/v2ray-agent/tls/acme.log
|
||
echoContent yellow "Installed protocol: \c"
|
||
echoContent red "3.For pure IPv6 machines, please set up NAT64.You can execute the following command. If it still does not work after adding the following command, please try to change to another NAT64"
|
||
echoContent red " ---> The official WARP client does not support ARM architecture"
|
||
echoContent red " ---> Failed to install WARP"
|
||
echoContent skyBlue " sed -i \"1i\\\nameserver 2a00:1098:2b::1\\\nnameserver 2a00:1098:2c::1\\\nnameserver 2a01:4f8:c2c:123f::1\\\nnameserver 2a01:4f9:c010:3f02::1\" /etc/resolv.conf"
|
||
exit 0
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
}
|
||
bootStartup() {
|
||
local serviceName=$1
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
rc-update add "${serviceName}" default
|
||
else
|
||
systemctl daemon-reload
|
||
systemctl enable "${serviceName}"
|
||
fi
|
||
}
|
||
# Install Nginx
|
||
installNginxTools() {
|
||
|
||
if [[ "${release}" == "debian" ]]; then
|
||
sudo apt install gnupg2 ca-certificates lsb-release -y >/dev/null 2>&1
|
||
echo "deb http://nginx.org/packages/mainline/debian $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list >/dev/null 2>&1
|
||
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | sudo tee /etc/apt/preferences.d/99nginx >/dev/null 2>&1
|
||
curl -o /tmp/nginx_signing.key https://nginx.org/keys/nginx_signing.key >/dev/null 2>&1
|
||
# gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key
|
||
# gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key
|
||
sudo mv /tmp/nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.asc
|
||
sudo apt update >/dev/null 2>&1
|
||
|
||
elif [[ "${release}" == "ubuntu" ]]; then
|
||
sudo apt install gnupg2 ca-certificates lsb-release -y >/dev/null 2>&1
|
||
echo "deb http://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list >/dev/null 2>&1
|
||
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | sudo tee /etc/apt/preferences.d/99nginx >/dev/null 2>&1
|
||
curl -o /tmp/nginx_signing.key https://nginx.org/keys/nginx_signing.key >/dev/null 2>&1
|
||
# gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key
|
||
# gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key
|
||
sudo mv /tmp/nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.asc
|
||
sudo apt update >/dev/null 2>&1
|
||
|
||
elif [[ "${release}" == "centos" ]]; then
|
||
${installType} yum-utils >/dev/null 2>&1
|
||
cat <<EOF >/etc/yum.repos.d/nginx.repo
|
||
[nginx-stable]
|
||
name=nginx stable repo
|
||
baseurl=http://nginx.org/packages/centos/\$releasever/\$basearch/
|
||
gpgcheck=1
|
||
enabled=1
|
||
gpgkey=https://nginx.org/keys/nginx_signing.key
|
||
module_hotfixes=true
|
||
|
||
[nginx-mainline]
|
||
name=nginx mainline repo
|
||
baseurl=http://nginx.org/packages/mainline/centos/\$releasever/\$basearch/
|
||
gpgcheck=1
|
||
enabled=0
|
||
gpgkey=https://nginx.org/keys/nginx_signing.key
|
||
module_hotfixes=true
|
||
EOF
|
||
sudo yum-config-manager --enable nginx-mainline >/dev/null 2>&1
|
||
elif [[ "${release}" == "alpine" ]]; then
|
||
rm "${nginxConfigPath}default.conf"
|
||
fi
|
||
${installType} nginx >/dev/null 2>&1
|
||
bootStartup nginx
|
||
}
|
||
|
||
# Install warp
|
||
installWarp() {
|
||
if [[ "${cpuVendor}" == "arm" ]]; then
|
||
echoContent red " ---> Unable to obtain domain name IPv4 address through DNS"
|
||
exit 0
|
||
fi
|
||
|
||
${installType} gnupg2 -y >/dev/null 2>&1
|
||
if [[ "${release}" == "debian" ]]; then
|
||
curl -s https://pkg.cloudflareclient.com/pubkey.gpg | sudo apt-key add - >/dev/null 2>&1
|
||
echo "deb http://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list >/dev/null 2>&1
|
||
sudo apt update >/dev/null 2>&1
|
||
|
||
elif [[ "${release}" == "ubuntu" ]]; then
|
||
curl -s https://pkg.cloudflareclient.com/pubkey.gpg | sudo apt-key add - >/dev/null 2>&1
|
||
echo "deb http://pkg.cloudflareclient.com/ focal main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list >/dev/null 2>&1
|
||
sudo apt update >/dev/null 2>&1
|
||
|
||
elif [[ "${release}" == "centos" ]]; then
|
||
${installType} yum-utils >/dev/null 2>&1
|
||
sudo rpm -ivh "http://pkg.cloudflareclient.com/cloudflare-release-el${centosVersion}.rpm" >/dev/null 2>&1
|
||
fi
|
||
|
||
echoContent green " ---> Try to check the domain name IPv6 address"
|
||
${installType} cloudflare-warp >/dev/null 2>&1
|
||
if [[ -z $(which warp-cli) ]]; then
|
||
echoContent red " ---> Unable to obtain domain name IPv6 address through DNS, exit installation"
|
||
exit 0
|
||
fi
|
||
systemctl enable warp-svc
|
||
warp-cli --accept-tos register
|
||
warp-cli --accept-tos set-mode proxy
|
||
warp-cli --accept-tos set-proxy-port 31303
|
||
warp-cli --accept-tos connect
|
||
warp-cli --accept-tos enable-always-on
|
||
|
||
local warpStatus=
|
||
warpStatus=$(curl -s --socks5 127.0.0.1:31303 https://www.cloudflare.com/cdn-cgi/trace | grep "warp" | cut -d "=" -f 2)
|
||
|
||
if [[ "${warpStatus}" == "on" ]]; then
|
||
echoContent green " ---> Current VPS IP: ${publicIP}"
|
||
fi
|
||
}
|
||
|
||
# Check the IP of the domain name through dns
|
||
checkDNSIP() {
|
||
local domain=$1
|
||
local dnsIP=
|
||
ipType=4
|
||
dnsIP=$(dig @1.1.1.1 +time=2 +short "${domain}" | grep -E "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")
|
||
if [[ -z "${dnsIP}" ]]; then
|
||
dnsIP=$(dig @8.8.8.8 +time=2 +short "${domain}" | grep -E "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")
|
||
fi
|
||
if echo "${dnsIP}" | grep -q "timed out" || [[ -z "${dnsIP}" ]]; then
|
||
echo
|
||
echoContent red " ---> The domain name resolution IP is inconsistent with the current server IP\n"
|
||
echoContent green " ---> DNS resolution IP: ${dnsIP}"
|
||
dnsIP=$(dig @2606:4700:4700::1111 +time=2 aaaa +short "${domain}")
|
||
ipType=6
|
||
if echo "${dnsIP}" | grep -q "network unreachable" || [[ -z "${dnsIP}" ]]; then
|
||
echoContent red " ---> Please check if there is a web firewall, such as Oracle and other cloud service providers"
|
||
exit 0
|
||
fi
|
||
fi
|
||
local publicIP=
|
||
|
||
publicIP=$(getPublicIP "${ipType}")
|
||
if [[ "${publicIP}" != "${dnsIP}" ]]; then
|
||
echoContent red " ---> Check whether you have installed nginx and there are configuration conflicts. You can try DD pure system and try again"
|
||
echoContent yellow "VLESS+TCP[TLS] \c"
|
||
echoContent green " ---> Domain name IP verification passed"
|
||
echoContent green " ---> Detected that ${port} port is open"
|
||
exit 0
|
||
else
|
||
echoContent green " ---> No open ${port} port detected, exit installation"
|
||
fi
|
||
}
|
||
# Check the actual open status of the port
|
||
checkPortOpen() {
|
||
handleSingBox stop >/dev/null 2>&1
|
||
handleXray stop >/dev/null 2>&1
|
||
|
||
local port=$1
|
||
local domain=$2
|
||
local checkPortOpenResult=
|
||
# open port
|
||
allowPort "${port}"
|
||
|
||
if [[ -z "${btDomain}" ]]; then
|
||
|
||
# Change setting
|
||
handleNginx stop
|
||
#Initialize nginx configuration
|
||
touch ${nginxConfigPath}checkPortOpen.conf
|
||
local listenIPv6PortConfig=
|
||
|
||
if [[ -n $(curl -s -6 -m 4 http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2) ]]; then
|
||
listenIPv6PortConfig="listen [::]:${port};"
|
||
fi
|
||
cat <<EOF >${nginxConfigPath}checkPortOpen.conf
|
||
server {
|
||
listen ${port};
|
||
${listenIPv6PortConfig}
|
||
server_name ${domain};
|
||
location /checkPort {
|
||
return 200 'fjkvymb6len';
|
||
}
|
||
location /ip {
|
||
proxy_set_header Host \$host;
|
||
proxy_set_header X-Real-IP \$remote_addr;
|
||
proxy_set_header REMOTE-HOST \$remote_addr;
|
||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||
default_type text/plain;
|
||
return 200 \$proxy_add_x_forwarded_for;
|
||
}
|
||
}
|
||
EOF
|
||
handleNginx start
|
||
checkPortOpenResult=$(curl -s -m 10 "http://${domain}:${port}/checkPort")
|
||
localIP=$(curl -s -m 10 "http://${domain}:${port}/ip")
|
||
rm "${nginxConfigPath}checkPortOpen.conf"
|
||
handleNginx stop
|
||
if [[ "${checkPortOpenResult}" == "fjkvymb6len" ]]; then
|
||
echoContent green " ---> Delete Nginx default configuration"
|
||
else
|
||
echoContent green " ---> Check that the current domain name IP is correct"
|
||
if echo "${checkPortOpenResult}" | grep -q "cloudflare"; then
|
||
echoContent yellow "VLESS+TCP[TLS_Vision] \c"
|
||
else
|
||
if [[ -z "${checkPortOpenResult}" ]]; then
|
||
echoContent red " ---> Error log: ${checkPortOpenResult}, please submit feedback on this error log through issues"
|
||
echoContent red "Domain name cannot be empty--->"
|
||
else
|
||
echoContent red "\n ---> The ip of the current domain name was not detected"
|
||
fi
|
||
fi
|
||
exit 0
|
||
fi
|
||
checkIP "${localIP}"
|
||
fi
|
||
}
|
||
|
||
# Initialize Nginx application certificate configuration
|
||
initTLSNginxConfig() {
|
||
handleNginx stop
|
||
echoContent skyBlue "\nProgress $1/${totalProgress}: Initializing Nginx application certificate configuration"
|
||
if [[ -n "${currentHost}" && -z "${lastInstallationConfig}" ]]; then
|
||
echo
|
||
read -r -p "Read the last installation record. Do you want to use the domain name from the last installation? [y/n]:" historyDomainStatus
|
||
if [[ "${historyDomainStatus}" == "y" ]]; then
|
||
domain=${currentHost}
|
||
echoContent yellow "Trojan+TCP[TLS_Vision] \c"
|
||
else
|
||
echo
|
||
echoContent yellow "VLESS+WS[TLS] \c"
|
||
read -r -p "domain name:" domain
|
||
fi
|
||
elif [[ -n "${currentHost}" && -n "${lastInstallationConfig}" ]]; then
|
||
domain=${currentHost}
|
||
else
|
||
echo
|
||
echoContent yellow "Trojan+gRPC[TLS] \c"
|
||
read -r -p "domain name:" domain
|
||
fi
|
||
|
||
if [[ -z ${domain} ]]; then
|
||
echoContent red " ---> Exception result: ${localIP}"
|
||
# Apply for tls
|
||
initTLSNginxConfig 3
|
||
else
|
||
dnsTLSDomain=$(echo "${domain}" | awk -F "." '{$1="";print $0}' | sed 's/^[[:space:]]*//' | sed 's/ /./g')
|
||
if [[ "${selectCoreType}" == "1" ]]; then
|
||
customPortFunction
|
||
fi
|
||
handleNginx stop
|
||
fi
|
||
}
|
||
|
||
# Delete nginx default configuration
|
||
removeNginxDefaultConf() {
|
||
if [[ -f ${nginxConfigPath}default.conf ]]; then
|
||
if [[ "$(grep -c "server_name" <${nginxConfigPath}default.conf)" == "1" ]] && [[ "$(grep -c "server_name localhost;" <${nginxConfigPath}default.conf)" == "1" ]]; then
|
||
echoContent green " ---> Added successfully"
|
||
rm -rf ${nginxConfigPath}default.conf >/dev/null 2>&1
|
||
fi
|
||
fi
|
||
}
|
||
# Modify nginx redirection configuration
|
||
updateRedirectNginxConf() {
|
||
local redirectDomain=
|
||
redirectDomain=${domain}:${port}
|
||
|
||
local nginxH2Conf=
|
||
nginxH2Conf="listen 127.0.0.1:31302 http2 so_keepalive=on proxy_protocol;"
|
||
nginxVersion=$(nginx -v 2>&1)
|
||
|
||
if echo "${nginxVersion}" | grep -q "1.25" && [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $3}') -gt 0 ]] || [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $2}') -gt 25 ]]; then
|
||
nginxH2Conf="listen 127.0.0.1:31302 so_keepalive=on proxy_protocol;http2 on;"
|
||
fi
|
||
|
||
cat <<EOF >${nginxConfigPath}alone.conf
|
||
server {
|
||
listen 127.0.0.1:31300;
|
||
server_name _;
|
||
return 403;
|
||
}
|
||
EOF
|
||
|
||
if echo "${selectCustomInstallType}" | grep -qE ",2,|,5," || [[ -z "${selectCustomInstallType}" ]]; then
|
||
|
||
cat <<EOF >>${nginxConfigPath}alone.conf
|
||
server {
|
||
${nginxH2Conf}
|
||
server_name ${domain};
|
||
root ${nginxStaticPath};
|
||
|
||
set_real_ip_from 127.0.0.1;
|
||
real_ip_header proxy_protocol;
|
||
|
||
client_header_timeout 1071906480m;
|
||
keepalive_timeout 1071906480m;
|
||
|
||
location /${currentPath}grpc {
|
||
if (\$content_type !~ "application/grpc") {
|
||
return 404;
|
||
}
|
||
client_max_body_size 0;
|
||
grpc_set_header X-Real-IP \$proxy_add_x_forwarded_for;
|
||
client_body_timeout 1071906480m;
|
||
grpc_read_timeout 1071906480m;
|
||
grpc_pass grpc://127.0.0.1:31301;
|
||
}
|
||
|
||
location /${currentPath}trojangrpc {
|
||
if (\$content_type !~ "application/grpc") {
|
||
return 404;
|
||
}
|
||
client_max_body_size 0;
|
||
grpc_set_header X-Real-IP \$proxy_add_x_forwarded_for;
|
||
client_body_timeout 1071906480m;
|
||
grpc_read_timeout 1071906480m;
|
||
grpc_pass grpc://127.0.0.1:31304;
|
||
}
|
||
location / {
|
||
}
|
||
}
|
||
EOF
|
||
elif echo "${selectCustomInstallType}" | grep -q ",5," || [[ -z "${selectCustomInstallType}" ]]; then
|
||
cat <<EOF >>${nginxConfigPath}alone.conf
|
||
server {
|
||
${nginxH2Conf}
|
||
|
||
set_real_ip_from 127.0.0.1;
|
||
real_ip_header proxy_protocol;
|
||
|
||
server_name ${domain};
|
||
root ${nginxStaticPath};
|
||
|
||
location /${currentPath}grpc {
|
||
client_max_body_size 0;
|
||
# keepalive_time 1071906480m;
|
||
keepalive_requests 4294967296;
|
||
client_body_timeout 1071906480m;
|
||
send_timeout 1071906480m;
|
||
lingering_close always;
|
||
grpc_read_timeout 1071906480m;
|
||
grpc_send_timeout 1071906480m;
|
||
grpc_pass grpc://127.0.0.1:31301;
|
||
}
|
||
location / {
|
||
}
|
||
}
|
||
EOF
|
||
|
||
elif echo "${selectCustomInstallType}" | grep -q ",2," || [[ -z "${selectCustomInstallType}" ]]; then
|
||
cat <<EOF >>${nginxConfigPath}alone.conf
|
||
server {
|
||
${nginxH2Conf}
|
||
|
||
set_real_ip_from 127.0.0.1;
|
||
real_ip_header proxy_protocol;
|
||
|
||
server_name ${domain};
|
||
root ${nginxStaticPath};
|
||
|
||
location /${currentPath}trojangrpc {
|
||
client_max_body_size 0;
|
||
# keepalive_time 1071906480m;
|
||
# keepalive_time 1071906480m;
|
||
keepalive_requests 4294967296;
|
||
client_body_timeout 1071906480m;
|
||
send_timeout 1071906480m;
|
||
lingering_close always;
|
||
grpc_read_timeout 1071906480m;
|
||
grpc_send_timeout 1071906480m;
|
||
grpc_pass grpc://127.0.0.1:31301;
|
||
}
|
||
location / {
|
||
}
|
||
}
|
||
EOF
|
||
else
|
||
|
||
cat <<EOF >>${nginxConfigPath}alone.conf
|
||
server {
|
||
${nginxH2Conf}
|
||
|
||
set_real_ip_from 127.0.0.1;
|
||
real_ip_header proxy_protocol;
|
||
|
||
server_name ${domain};
|
||
root ${nginxStaticPath};
|
||
|
||
location / {
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
cat <<EOF >>${nginxConfigPath}alone.conf
|
||
server {
|
||
listen 127.0.0.1:31300 proxy_protocol;
|
||
server_name ${domain};
|
||
|
||
set_real_ip_from 127.0.0.1;
|
||
real_ip_header proxy_protocol;
|
||
|
||
root ${nginxStaticPath};
|
||
location / {
|
||
}
|
||
}
|
||
EOF
|
||
handleNginx stop
|
||
}
|
||
# singbox Nginx config
|
||
singBoxNginxConfig() {
|
||
local type=$1
|
||
local port=$2
|
||
|
||
local nginxH2Conf=
|
||
nginxH2Conf="listen ${port} http2 so_keepalive=on ssl;"
|
||
nginxVersion=$(nginx -v 2>&1)
|
||
|
||
local singBoxNginxSSL=
|
||
singBoxNginxSSL="ssl_certificate /etc/v2ray-agent/tls/${domain}.crt;ssl_certificate_key /etc/v2ray-agent/tls/${domain}.key;"
|
||
|
||
if echo "${nginxVersion}" | grep -q "1.25" && [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $3}') -gt 0 ]] || [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $2}') -gt 25 ]]; then
|
||
nginxH2Conf="listen ${port} so_keepalive=on ssl;http2 on;"
|
||
fi
|
||
|
||
if echo "${selectCustomInstallType}" | grep -q ",11," || [[ "$1" == "all" ]]; then
|
||
cat <<EOF >>${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf
|
||
server {
|
||
${nginxH2Conf}
|
||
|
||
server_name ${domain};
|
||
root ${nginxStaticPath};
|
||
${singBoxNginxSSL}
|
||
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
ssl_ciphers TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;
|
||
ssl_prefer_server_ciphers on;
|
||
|
||
resolver 1.1.1.1 valid=60s;
|
||
resolver_timeout 2s;
|
||
client_max_body_size 100m;
|
||
|
||
location /${currentPath} {
|
||
if (\$http_upgrade != "websocket") {
|
||
return 444;
|
||
}
|
||
|
||
proxy_pass http://127.0.0.1:31306;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade \$http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
proxy_set_header X-Real-IP \$remote_addr;
|
||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||
proxy_set_header Host \$host;
|
||
proxy_redirect off;
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
}
|
||
|
||
# check ip
|
||
checkIP() {
|
||
echoContent skyBlue "\n ---> Check the domain name ip"
|
||
local localIP=$1
|
||
|
||
if [[ -z ${localIP} ]] || ! echo "${localIP}" | sed '1{s/[^(]*(//;s/).*//;q}' | grep -q '\.' && ! echo "${localIP}" | sed '1{s/[^(]*(//;s/).*//;q}' | grep -q ':'; then
|
||
echoContent red "\n ---> Multiple IPs were detected, please confirm whether to turn off cloudflare"
|
||
echoContent skyBlue " ---> Please perform the following checks in order"
|
||
echoContent yellow "VMess+WS[TLS] \c"
|
||
echoContent yellow "Trojan+TCP[TLS] \c"
|
||
echoContent yellow "VLESS+gRPC[TLS] \c"
|
||
echoContent yellow "VLESS+Reality+Vision \c"
|
||
echo
|
||
echoContent skyBlue " ---> If the above settings are correct, please reinstall a pure system and try again"
|
||
|
||
if [[ -n ${localIP} ]]; then
|
||
echoContent yellow "VLESS+Reality+gRPC \c"
|
||
echoContent red "\n=============================================================="
|
||
fi
|
||
exit 0
|
||
else
|
||
if echo "${localIP}" | awk -F "[,]" '{print $2}' | grep -q "." || echo "${localIP}" | awk -F "[,]" '{print $2}' | grep -q ":"; then
|
||
echoContent red "================================================== ==============="
|
||
echoContent yellow " ---> nginx uninstall completed"
|
||
echoContent yellow "Error troubleshooting:"
|
||
exit 0
|
||
fi
|
||
echoContent green " ---> Please add DNS TXT record manually"
|
||
fi
|
||
}
|
||
# Custom email
|
||
customSSLEmail() {
|
||
if echo "$1" | grep -q "validate email"; then
|
||
read -r -p "Whether to re-enter the email address [y/n]:" sslEmailStatus
|
||
if [[ "${sslEmailStatus}" == "y" ]]; then
|
||
sed '/ACCOUNT_EMAIL/d' /root/.acme.sh/account.conf >/root/.acme.sh/account.conf_tmp && mv /root/.acme.sh/account.conf_tmp /root/.acme.sh/account.conf
|
||
else
|
||
exit 0
|
||
fi
|
||
fi
|
||
|
||
if [[ -d "/root/.acme.sh" && -f "/root/.acme.sh/account.conf" ]]; then
|
||
if ! grep -q "ACCOUNT_EMAIL" <"/root/.acme.sh/account.conf" && ! echo "${sslType}" | grep -q "letsencrypt"; then
|
||
read -r -p "Please enter your email address:" sslEmail
|
||
if echo "${sslEmail}" | grep -q "@"; then
|
||
echo "ACCOUNT_EMAIL='${sslEmail}'" >>/root/.acme.sh/account.conf
|
||
echoContent green " ---> name: _acme-challenge"
|
||
else
|
||
echoContent yellow " ---> Please check whether the domain name resolution is valid and correct"
|
||
customSSLEmail
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
}
|
||
switchDNSAPI() {
|
||
read -r -p "Use DNS API to issue the certificate [NAT supported]? [y/n]:" dnsAPIStatus
|
||
if [[ "${dnsAPIStatus}" == "y" ]]; then
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow " ---> Please close the cloud and wait three minutes to try again"
|
||
echoContent yellow "2.aliyun"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Select [Enter for default]:" selectDNSAPIType
|
||
case ${selectDNSAPIType} in
|
||
1)
|
||
dnsAPIType="cloudflare"
|
||
;;
|
||
2)
|
||
dnsAPIType="aliyun"
|
||
;;
|
||
*)
|
||
dnsAPIType="cloudflare"
|
||
;;
|
||
esac
|
||
initDNSAPIConfig "${dnsAPIType}"
|
||
fi
|
||
}
|
||
initDNSAPIConfig() {
|
||
if [[ "$1" == "cloudflare" ]]; then
|
||
echoContent yellow "\n ---> Domain name: ${domain}"
|
||
read -r -p "Enter API Token:" cfAPIToken
|
||
if [[ -z "${cfAPIToken}" ]]; then
|
||
echoContent red " ---> buypass does not support free wildcard certificates"
|
||
initDNSAPIConfig "$1"
|
||
else
|
||
echo
|
||
if ! echo "${dnsTLSDomain}" | grep -q "\." || [[ -z $(echo "${dnsTLSDomain}" | awk -F "[.]" '{print $1}') ]]; then
|
||
echoContent green " ---> value: ${txtValue}"
|
||
exit 0
|
||
fi
|
||
read -r -p "Use *.${dnsTLSDomain} to request a wildcard certificate via API? [y/n]:" dnsAPIStatus
|
||
fi
|
||
elif [[ "$1" == "aliyun" ]]; then
|
||
read -r -p "Enter Ali Key:" aliKey
|
||
read -r -p "Enter Ali Secret:" aliSecret
|
||
if [[ -z "${aliKey}" || -z "${aliSecret}" ]]; then
|
||
echoContent red " ---> Verification failed, please wait 1-2 minutes and try again"
|
||
initDNSAPIConfig "$1"
|
||
else
|
||
echo
|
||
if ! echo "${dnsTLSDomain}" | grep -q "\." || [[ -z $(echo "${dnsTLSDomain}" | awk -F "[.]" '{print $1}') ]]; then
|
||
echoContent green " ---> TXT record verification passed"
|
||
exit 0
|
||
fi
|
||
read -r -p "Use *.${dnsTLSDomain} to request a wildcard certificate via API? [y/n]:" dnsAPIStatus
|
||
fi
|
||
fi
|
||
}
|
||
#Select ssl installation type
|
||
switchSSLType() {
|
||
if [[ -z "${sslType}" ]]; then
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "Please enter the domain name to be configured: www.v2ray-agent.com --->"
|
||
echoContent yellow "2.zerossl"
|
||
echoContent yellow "Please enter the domain name to be configured: www.v2ray-agent.com --->"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select [Enter] to use the default:" selectSSLType
|
||
case ${selectSSLType} in
|
||
1)
|
||
sslType="letsencrypt"
|
||
;;
|
||
2)
|
||
sslType="zerossl"
|
||
;;
|
||
3)
|
||
sslType="buypass"
|
||
;;
|
||
*)
|
||
sslType="letsencrypt"
|
||
;;
|
||
esac
|
||
if [[ -n "${dnsAPIType}" && "${sslType}" == "buypass" ]]; then
|
||
echoContent red " ---> Give up"
|
||
exit 0
|
||
fi
|
||
echo "${sslType}" >/etc/v2ray-agent/tls/ssl_type
|
||
fi
|
||
}
|
||
|
||
#Select acme installation certificate method
|
||
selectAcmeInstallSSL() {
|
||
# local sslIPv6=
|
||
# local currentIPType=
|
||
if [[ "${ipType}" == "6" ]]; then
|
||
sslIPv6="--listen-v6"
|
||
fi
|
||
# currentIPType=$(curl -s "-${ipType}" http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2)
|
||
|
||
# if [[ -z "${currentIPType}" ]]; then
|
||
# currentIPType=$(curl -s -6 http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2)
|
||
# if [[ -n "${currentIPType}" ]]; then
|
||
# sslIPv6="--listen-v6"
|
||
# fi
|
||
# fi
|
||
|
||
acmeInstallSSL
|
||
|
||
readAcmeTLS
|
||
}
|
||
|
||
# Install SSL certificate
|
||
acmeInstallSSL() {
|
||
local dnsAPIDomain="${tlsDomain}"
|
||
local dnsAPIExtraDomain="-d ${dnsTLSDomain}"
|
||
if [[ "${dnsAPIStatus}" == "y" ]]; then
|
||
dnsAPIDomain="*.${dnsTLSDomain}"
|
||
else
|
||
dnsAPIExtraDomain=""
|
||
fi
|
||
|
||
if [[ "${dnsAPIType}" == "cloudflare" ]]; then
|
||
echoContent green " ---> Generating certificate"
|
||
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 " ---> Generating certificate"
|
||
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 " ---> Certificate detected"
|
||
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
|
||
fi
|
||
}
|
||
# Custom port
|
||
customPortFunction() {
|
||
local historyCustomPortStatus=
|
||
if [[ -n "${customPort}" || -n "${currentPort}" ]]; then
|
||
echo
|
||
if [[ -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Read the port from the last installation. Do you want to use the port from the last installation? [y/n]:" historyCustomPortStatus
|
||
if [[ "${historyCustomPortStatus}" == "y" ]]; then
|
||
port=${currentPort}
|
||
echoContent yellow " --->1.Check whether the domain name is written correctly"
|
||
fi
|
||
elif [[ -n "${lastInstallationConfig}" ]]; then
|
||
port=${currentPort}
|
||
fi
|
||
fi
|
||
if [[ -z "${currentPort}" ]] || [[ "${historyCustomPortStatus}" == "n" ]]; then
|
||
echo
|
||
|
||
if [[ -n "${btDomain}" ]]; then
|
||
echoContent yellow " --->2.Check whether the domain name dns resolution is correct"
|
||
read -r -p "port:" port
|
||
if [[ -z "${port}" ]]; then
|
||
port=$((RANDOM % 20001 + 10000))
|
||
fi
|
||
else
|
||
echo
|
||
echoContent yellow " --->3.If the parsing is correct, please wait for the dns to take effect, which is expected to take effect within three minutes"
|
||
read -r -p "port:" port
|
||
if [[ -z "${port}" ]]; then
|
||
port=443
|
||
fi
|
||
if [[ "${port}" == "${xrayVLESSRealityPort}" ]]; then
|
||
handleXray stop
|
||
fi
|
||
fi
|
||
|
||
if [[ -n "${port}" ]]; then
|
||
if ((port >= 1 && port <= 65535)); then
|
||
allowPort "${port}"
|
||
echoContent yellow " --->4.If you report Nginx startup problems, please start nginx manually to check the errors. If you cannot handle it yourself, please submit issues"
|
||
if [[ -z "${btDomain}" ]]; then
|
||
checkDNSIP "${domain}"
|
||
removeNginxDefaultConf
|
||
checkPortOpen "${port}" "${domain}"
|
||
fi
|
||
else
|
||
echoContent red " ---> Port input error"
|
||
exit 0
|
||
fi
|
||
else
|
||
echoContent red " ---> Port cannot be empty"
|
||
exit 0
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Check whether the port is occupied
|
||
checkPort() {
|
||
if [[ -n "$1" ]] && lsof -i "tcp:$1" | grep -q LISTEN; then
|
||
echoContent red "\n ---> $1 port is occupied, please close it manually and install\n"
|
||
lsof -i "tcp:$1" | grep LISTEN
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
# Install TLS
|
||
installTLS() {
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Apply for TLS certificate\n"
|
||
readAcmeTLS
|
||
local tlsDomain=${domain}
|
||
|
||
if [[ -f "/etc/v2ray-agent/tls/${tlsDomain}.crt" && -f "/etc/v2ray-agent/tls/${tlsDomain}.key" && -n $(cat "/etc/v2ray-agent/tls/${tlsDomain}.crt") ]] || [[ -d "$HOME/.acme.sh/${tlsDomain}_ecc" && -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key" && -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer" ]] || [[ "${installedDNSAPIStatus}" == "true" ]]; then
|
||
echoContent green " ---> Install TLS certificate, need to rely on port 80"
|
||
# checkTLStatus
|
||
renewalTLS
|
||
|
||
if [[ -z $(find /etc/v2ray-agent/tls/ -name "${tlsDomain}.crt") ]] || [[ -z $(find /etc/v2ray-agent/tls/ -name "${tlsDomain}.key") ]] || [[ -z $(cat "/etc/v2ray-agent/tls/${tlsDomain}.crt") ]]; then
|
||
if [[ "${installedDNSAPIStatus}" == "true" ]]; then
|
||
sudo "$HOME/.acme.sh/acme.sh" --installcert -d "*.${dnsTLSDomain}" --fullchainpath "/etc/v2ray-agent/tls/${tlsDomain}.crt" --keypath "/etc/v2ray-agent/tls/${tlsDomain}.key" --ecc >/dev/null
|
||
else
|
||
sudo "$HOME/.acme.sh/acme.sh" --installcert -d "${tlsDomain}" --fullchainpath "/etc/v2ray-agent/tls/${tlsDomain}.crt" --keypath "/etc/v2ray-agent/tls/${tlsDomain}.key" --ecc >/dev/null
|
||
fi
|
||
|
||
else
|
||
if [[ -d "$HOME/.acme.sh/${tlsDomain}_ecc" && -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key" && -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer" ]] || [[ "${installedDNSAPIStatus}" == "true" ]]; then
|
||
if [[ -z "${lastInstallationConfig}" ]]; then
|
||
echoContent yellow " ---> Detection of abnormal return value, it is recommended to manually uninstall nginx and re-execute the script"
|
||
read -r -p "Reinstall? [y/n]:" reInstallStatus
|
||
if [[ "${reInstallStatus}" == "y" ]]; then
|
||
rm -rf /etc/v2ray-agent/tls/*
|
||
installTLS "$1"
|
||
fi
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
elif [[ -d "$HOME/.acme.sh" ]] && [[ ! -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer" || ! -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key" ]]; then
|
||
switchDNSAPI
|
||
if [[ -z "${dnsAPIType}" ]]; then
|
||
echoContent yellow " ---> Wait three minutes after closing the cloud and try again"
|
||
echoContent green " ---> TLS generated successfully"
|
||
allowPort 80
|
||
fi
|
||
|
||
switchSSLType
|
||
customSSLEmail
|
||
selectAcmeInstallSSL
|
||
|
||
if [[ "${installedDNSAPIStatus}" == "true" ]]; then
|
||
sudo "$HOME/.acme.sh/acme.sh" --installcert -d "*.${dnsTLSDomain}" --fullchainpath "/etc/v2ray-agent/tls/${tlsDomain}.crt" --keypath "/etc/v2ray-agent/tls/${tlsDomain}.key" --ecc >/dev/null
|
||
else
|
||
sudo "$HOME/.acme.sh/acme.sh" --installcert -d "${tlsDomain}" --fullchainpath "/etc/v2ray-agent/tls/${tlsDomain}.crt" --keypath "/etc/v2ray-agent/tls/${tlsDomain}.key" --ecc >/dev/null
|
||
fi
|
||
|
||
if [[ ! -f "/etc/v2ray-agent/tls/${tlsDomain}.crt" || ! -f "/etc/v2ray-agent/tls/${tlsDomain}.key" ]] || [[ -z $(cat "/etc/v2ray-agent/tls/${tlsDomain}.key") || -z $(cat "/etc/v2ray-agent/tls/${tlsDomain}.crt") ]]; then
|
||
tail -n 10 /etc/v2ray-agent/tls/acme.log
|
||
if [[ ${installTLSCount} == "1" ]]; then
|
||
echoContent red " ---> TLS installation failed, please check the acme log"
|
||
exit 0
|
||
fi
|
||
|
||
installTLSCount=1
|
||
echo
|
||
|
||
if tail -n 10 /etc/v2ray-agent/tls/acme.log | grep -q "Could not validate email address as valid"; then
|
||
echoContent red " ---> The email cannot pass SSL vendor verification, please re-enter"
|
||
echo
|
||
customSSLEmail "validate email"
|
||
installTLS "$1"
|
||
else
|
||
installTLS "$1"
|
||
fi
|
||
fi
|
||
|
||
echoContent green " ---> Used successfully\n"
|
||
else
|
||
echoContent yellow " ---> The detected IP is as follows: [${localIP}]"
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
#Initialize random string
|
||
initRandomPath() {
|
||
local chars="abcdefghijklmnopqrtuxyz"
|
||
local initCustomPath=
|
||
for i in {1..4}; do
|
||
echo "${i}" >/dev/null
|
||
initCustomPath+="${chars:RANDOM%${#chars}:1}"
|
||
done
|
||
customPath=${initCustomPath}
|
||
}
|
||
|
||
# Custom/random path
|
||
randomPathFunction() {
|
||
if [[ -n $1 ]]; then
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Generate random path"
|
||
else
|
||
echoContent skyBlue "\n----------------------------"
|
||
fi
|
||
|
||
if [[ -n "${currentPath}" && -z "${lastInstallationConfig}" ]]; then
|
||
echo
|
||
read -r -p "Read the last installation record. Do you want to use the path from the last installation? [y/n]:" historyPathStatus
|
||
echo
|
||
elif [[ -n "${currentPath}" && -n "${lastInstallationConfig}" ]]; then
|
||
historyPathStatus="y"
|
||
fi
|
||
|
||
if [[ "${historyPathStatus}" == "y" ]]; then
|
||
customPath=${currentPath}
|
||
echoContent green " ---> Added fake site successfully"
|
||
else
|
||
echoContent yellow "Please re-enter the correct email format [Example: username@example.com]"
|
||
read -r -p 'path:' customPath
|
||
if [[ -z "${customPath}" ]]; then
|
||
initRandomPath
|
||
currentPath=${customPath}
|
||
else
|
||
if [[ "${customPath: -2}" == "ws" ]]; then
|
||
echo
|
||
echoContent red " ---> The custom path cannot end with ws, otherwise the splitting path cannot be distinguished"
|
||
randomPathFunction "$1"
|
||
else
|
||
currentPath=${customPath}
|
||
fi
|
||
fi
|
||
fi
|
||
echoContent yellow "\n path:${currentPath}"
|
||
echoContent skyBlue "\n----------------------------"
|
||
}
|
||
randomNum() {
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
local ranNum=
|
||
ranNum="$(shuf -i "$1"-"$2" -n 1)"
|
||
echo "${ranNum}"
|
||
else
|
||
echo $((RANDOM % $2 + $1))
|
||
fi
|
||
}
|
||
# Nginx disguise blog
|
||
nginxBlog() {
|
||
if [[ -n "$1" ]]; then
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Add fake site"
|
||
else
|
||
echoContent yellow "1.letsencrypt[default]"
|
||
fi
|
||
|
||
if [[ -d "${nginxStaticPath}" && -f "${nginxStaticPath}/check" ]]; then
|
||
echo
|
||
if [[ -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Detected installation of fake site, do you need to reinstall [y/n]:" nginxBlogInstallStatus
|
||
else
|
||
nginxBlogInstallStatus="n"
|
||
fi
|
||
|
||
if [[ "${nginxBlogInstallStatus}" == "y" ]]; then
|
||
rm -rf "${nginxStaticPath}*"
|
||
# randomNum=$((RANDOM % 6 + 1))
|
||
randomNum=$(randomNum 1 9)
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
wget -q -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip"
|
||
else
|
||
wget -q "${wgetShowProgressStatus}" -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip"
|
||
fi
|
||
|
||
unzip -o "${nginxStaticPath}html${randomNum}.zip" -d "${nginxStaticPath}" >/dev/null
|
||
rm -f "${nginxStaticPath}html${randomNum}.zip*"
|
||
echoContent green " ---> Added fake site successfully"
|
||
fi
|
||
else
|
||
randomNum=$(randomNum 1 9)
|
||
# randomNum=$((RANDOM % 6 + 1))
|
||
rm -rf "${nginxStaticPath}*"
|
||
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
wget -q -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip"
|
||
else
|
||
wget -q "${wgetShowProgressStatus}" -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip"
|
||
fi
|
||
|
||
unzip -o "${nginxStaticPath}html${randomNum}.zip" -d "${nginxStaticPath}" >/dev/null
|
||
rm -f "${nginxStaticPath}html${randomNum}.zip*"
|
||
echoContent green " ---> http_port_t 31300 port opened successfully"
|
||
fi
|
||
|
||
}
|
||
|
||
# Modify http_port_t port
|
||
updateSELinuxHTTPPortT() {
|
||
|
||
$(find /usr/bin /usr/sbin | grep -w journalctl) -xe >/etc/v2ray-agent/nginx_error.log 2>&1
|
||
|
||
if find /usr/bin /usr/sbin | grep -q -w semanage && find /usr/bin /usr/sbin | grep -q -w getenforce && grep -E "31300|31302" </etc/v2ray-agent/nginx_error.log | grep -q "Permission denied"; then
|
||
echoContent red " ---> Check if the SELinux port is open"
|
||
if ! $(find /usr/bin /usr/sbin | grep -w semanage) port -l | grep http_port | grep -q 31300; then
|
||
$(find /usr/bin /usr/sbin | grep -w semanage) port -a -t http_port_t -p tcp 31300
|
||
echoContent green " ---> http_port_t 31302 port opened successfully"
|
||
fi
|
||
|
||
if ! $(find /usr/bin /usr/sbin | grep -w semanage) port -l | grep http_port | grep -q 31302; then
|
||
$(find /usr/bin /usr/sbin | grep -w semanage) port -a -t http_port_t -p tcp 31302
|
||
echoContent green " ---> Nginx started successfully"
|
||
fi
|
||
handleNginx start
|
||
|
||
else
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
#Operation Nginx
|
||
handleNginx() {
|
||
|
||
if ! echo "${selectCustomInstallType}" | grep -qwE ",7,|,8,|,7,8," && [[ -z $(pgrep -f "nginx") ]] && [[ "$1" == "start" ]]; then
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
rc-service nginx start 2>/etc/v2ray-agent/nginx_error.log
|
||
else
|
||
systemctl start nginx 2>/etc/v2ray-agent/nginx_error.log
|
||
fi
|
||
|
||
sleep 0.5
|
||
|
||
if [[ -z $(pgrep -f "nginx") ]]; then
|
||
echoContent red " ---> Nginx failed to start"
|
||
echoContent red " ---> Please try to install nginx manually and execute the script again"
|
||
nginx
|
||
if grep -q "journalctl -xe" </etc/v2ray-agent/nginx_error.log; then
|
||
updateSELinuxHTTPPortT
|
||
fi
|
||
else
|
||
echoContent green " ---> Nginx closed successfully"
|
||
fi
|
||
|
||
elif [[ -n $(pgrep -f "nginx") ]] && [[ "$1" == "stop" ]]; then
|
||
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
rc-service nginx stop
|
||
else
|
||
systemctl stop nginx
|
||
fi
|
||
sleep 0.5
|
||
|
||
if [[ -z ${btDomain} && -n $(pgrep -f "nginx") ]]; then
|
||
pgrep -f "nginx" | xargs kill -9
|
||
fi
|
||
echoContent green "\n ---> Add scheduled maintenance certificate successfully"
|
||
fi
|
||
}
|
||
|
||
# Scheduled task to update tls certificate
|
||
installCronTLS() {
|
||
if [[ -z "${btDomain}" ]]; then
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Add scheduled maintenance certificate"
|
||
crontab -l >/etc/v2ray-agent/backup_crontab.cron
|
||
local historyCrontab
|
||
historyCrontab=$(sed '/v2ray-agent/d;/acme.sh/d' /etc/v2ray-agent/backup_crontab.cron)
|
||
echo "${historyCrontab}" >/etc/v2ray-agent/backup_crontab.cron
|
||
echo "30 1 * * * /bin/bash /etc/v2ray-agent/install.sh RenewTLS >> /etc/v2ray-agent/crontab_tls.log 2>&1" >>/etc/v2ray-agent/backup_crontab.cron
|
||
crontab /etc/v2ray-agent/backup_crontab.cron
|
||
echoContent green "\n ---> Adding scheduled update geo file successfully"
|
||
fi
|
||
}
|
||
# Scheduled tasks update geo files
|
||
installCronUpdateGeo() {
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
if crontab -l | grep -q "UpdateGeo"; then
|
||
echoContent red "\n ---> The automatic update scheduled task has been added, please do not add it repeatedly"
|
||
exit 0
|
||
fi
|
||
echoContent skyBlue "\nProgress 1/1: Add regularly updated geo files"
|
||
crontab -l >/etc/v2ray-agent/backup_crontab.cron
|
||
echo "35 1 * * * /bin/bash /etc/v2ray-agent/install.sh UpdateGeo >> /etc/v2ray-agent/crontab_tls.log 2>&1" >>/etc/v2ray-agent/backup_crontab.cron
|
||
crontab /etc/v2ray-agent/backup_crontab.cron
|
||
echoContent green " ---> The certificate is valid"
|
||
fi
|
||
}
|
||
|
||
# Update certificate
|
||
renewalTLS() {
|
||
|
||
if [[ -n $1 ]]; then
|
||
echoContent skyBlue "\nProgress$1/1: Update certificate"
|
||
fi
|
||
readAcmeTLS
|
||
local domain=${currentHost}
|
||
if [[ -z "${currentHost}" && -n "${tlsDomain}" ]]; then
|
||
domain=${tlsDomain}
|
||
fi
|
||
|
||
if [[ -f "/etc/v2ray-agent/tls/ssl_type" ]]; then
|
||
if grep -q "buypass" <"/etc/v2ray-agent/tls/ssl_type"; then
|
||
sslRenewalDays=180
|
||
fi
|
||
fi
|
||
if [[ -d "$HOME/.acme.sh/${domain}_ecc" && -f "$HOME/.acme.sh/${domain}_ecc/${domain}.key" && -f "$HOME/.acme.sh/${domain}_ecc/${domain}.cer" ]] || [[ "${installedDNSAPIStatus}" == "true" ]]; then
|
||
modifyTime=
|
||
|
||
if [[ "${installedDNSAPIStatus}" == "true" ]]; then
|
||
modifyTime=$(stat --format=%z "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer")
|
||
else
|
||
modifyTime=$(stat --format=%z "$HOME/.acme.sh/${domain}_ecc/${domain}.cer")
|
||
fi
|
||
|
||
modifyTime=$(date +%s -d "${modifyTime}")
|
||
currentTime=$(date +%s)
|
||
((stampDiff = currentTime - modifyTime))
|
||
((days = stampDiff / 86400))
|
||
((remainingDays = sslRenewalDays - days))
|
||
|
||
tlsStatus=${remainingDays}
|
||
if [[ ${remainingDays} -le 0 ]]; then
|
||
tlsStatus="Expired"
|
||
fi
|
||
|
||
echoContent skyBlue " ---> Certificate check date:$(date "+%F %H:%M:%S")"
|
||
echoContent skyBlue " ---> Certificate generation date: $(date -d @"${modifyTime}" +"%F %H:%M:%S")"
|
||
echoContent skyBlue " ---> Certificate generation days: ${days}"
|
||
echoContent skyBlue " ---> Number of days remaining on the certificate: "${tlsStatus}
|
||
echoContent skyBlue " ---> The certificate will be automatically updated on the last day before it expires. If the update fails, please update manually"
|
||
|
||
if [[ ${remainingDays} -le 1 ]]; then
|
||
echoContent yellow "2.zerossl"
|
||
handleNginx stop
|
||
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
handleXray stop
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
handleSingBox stop
|
||
fi
|
||
|
||
sudo "$HOME/.acme.sh/acme.sh" --cron --home "$HOME/.acme.sh"
|
||
sudo "$HOME/.acme.sh/acme.sh" --installcert -d "${domain}" --fullchainpath /etc/v2ray-agent/tls/"${domain}.crt" --keypath /etc/v2ray-agent/tls/"${domain}.key" --ecc
|
||
reloadCore
|
||
handleNginx start
|
||
else
|
||
echoContent green " ---> v2ray-core version:${version}"
|
||
fi
|
||
elif [[ -f "/etc/v2ray-agent/tls/${tlsDomain}.crt" && -f "/etc/v2ray-agent/tls/${tlsDomain}.key" && -n $(cat "/etc/v2ray-agent/tls/${tlsDomain}.crt") ]]; then
|
||
echoContent yellow "3.buypass[Does not support DNS application]"
|
||
else
|
||
echoContent red " ---> not installed"
|
||
fi
|
||
}
|
||
|
||
installSingBox() {
|
||
readInstallType
|
||
echoContent skyBlue " ---> Certificate generation days: ${days}"
|
||
|
||
if [[ ! -f "/etc/v2ray-agent/sing-box/sing-box" ]]; then
|
||
|
||
if [[ "${prereleaseStatus}" == "true" ]]; then
|
||
version=$(curl -s "https://api.github.com/repos/SagerNet/sing-box/releases?per_page=20" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1)
|
||
else
|
||
version=$(curl -s https://api.github.com/repos/SagerNet/sing-box/releases/latest | jq -r .tag_name)
|
||
fi
|
||
|
||
echoContent green " ---> Lock v2ray-core version to v4.32.1"
|
||
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
wget -c -q -P /etc/v2ray-agent/sing-box/ "https://github.com/SagerNet/sing-box/releases/download/${version}/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz"
|
||
else
|
||
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/sing-box/ "https://github.com/SagerNet/sing-box/releases/download/${version}/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz"
|
||
fi
|
||
|
||
if [[ ! -f "/etc/v2ray-agent/sing-box/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz" ]]; then
|
||
read -r -p "Core download failed. Retry installation? [y/n]" downloadStatus
|
||
if [[ "${downloadStatus}" == "y" ]]; then
|
||
installSingBox "$1"
|
||
fi
|
||
else
|
||
|
||
tar zxvf "/etc/v2ray-agent/sing-box/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz" -C "/etc/v2ray-agent/sing-box/" >/dev/null 2>&1
|
||
|
||
mv "/etc/v2ray-agent/sing-box/sing-box-${version/v/}${singBoxCoreCPUVendor}/sing-box" /etc/v2ray-agent/sing-box/sing-box
|
||
rm -rf /etc/v2ray-agent/sing-box/sing-box-*
|
||
chmod 655 /etc/v2ray-agent/sing-box/sing-box
|
||
fi
|
||
else
|
||
echoContent green " ---> Current version:v$(/etc/v2ray-agent/sing-box/sing-box version | grep "sing-box version" | awk '{print $3}')"
|
||
|
||
if [[ "${prereleaseStatus}" == "true" ]]; then
|
||
version=$(curl -s "https://api.github.com/repos/SagerNet/sing-box/releases?per_page=20" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1)
|
||
else
|
||
version=$(curl -s https://api.github.com/repos/SagerNet/sing-box/releases/latest | jq -r .tag_name)
|
||
fi
|
||
|
||
echoContent green " ---> v2ray-core version:$(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)"
|
||
|
||
if [[ -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Update or upgrade? [y/n]:" reInstallSingBoxStatus
|
||
if [[ "${reInstallSingBoxStatus}" == "y" ]]; then
|
||
rm -f /etc/v2ray-agent/sing-box/sing-box
|
||
installSingBox "$1"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
}
|
||
|
||
# Check wget showProgress
|
||
checkWgetShowProgress() {
|
||
if [[ "${release}" != "alpine" ]]; then
|
||
if find /usr/bin /usr/sbin | grep -q "/wget" && wget --help | grep -q show-progress; then
|
||
wgetShowProgressStatus="--show-progress"
|
||
fi
|
||
fi
|
||
}
|
||
# Install xray
|
||
installXray() {
|
||
readInstallType
|
||
local prereleaseStatus=false
|
||
if [[ "$2" == "true" ]]; then
|
||
prereleaseStatus=true
|
||
fi
|
||
|
||
echoContent skyBlue " ---> Number of days remaining on the certificate:${tlsStatus}"
|
||
|
||
if [[ ! -f "/etc/v2ray-agent/xray/xray" ]]; 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
|
||
|
||
echoContent green " ---> Hysteria version:${version}"
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
wget -c -q -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip"
|
||
else
|
||
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip"
|
||
fi
|
||
|
||
if [[ ! -f "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" ]]; then
|
||
read -r -p "Core download failed. Retry installation? [y/n]" downloadStatus
|
||
if [[ "${downloadStatus}" == "y" ]]; then
|
||
installXray "$1"
|
||
fi
|
||
else
|
||
unzip -o "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" -d /etc/v2ray-agent/xray >/dev/null
|
||
rm -rf "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip"
|
||
|
||
version=$(curl -s https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases?per_page=1 | jq -r '.[]|.tag_name')
|
||
echoContent skyBlue "------------------------Version-------------------------------"
|
||
echo "version:${version}"
|
||
rm /etc/v2ray-agent/xray/geo* >/dev/null 2>&1
|
||
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
wget -c -q -P /etc/v2ray-agent/xray/ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat"
|
||
wget -c -q -P /etc/v2ray-agent/xray/ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat"
|
||
else
|
||
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/xray/ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat"
|
||
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/xray/ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat"
|
||
fi
|
||
|
||
chmod 655 /etc/v2ray-agent/xray/xray
|
||
fi
|
||
else
|
||
if [[ -z "${lastInstallationConfig}" ]]; then
|
||
echoContent green " ---> Hysteria version:$(/etc/v2ray-agent/hysteria/hysteria --version | awk '{print $3}')"
|
||
read -r -p "Would you like to update or upgrade? [y/n]:" reInstallXrayStatus
|
||
if [[ "${reInstallXrayStatus}" == "y" ]]; then
|
||
rm -f /etc/v2ray-agent/xray/xray
|
||
installXray "$1" "$2"
|
||
fi
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# xray version management
|
||
xrayVersionManageMenu() {
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Install V2Ray"
|
||
if [[ "${coreInstallType}" != "1" ]]; then
|
||
echoContent red " ---> Core download failed, please try installation again"
|
||
exit 0
|
||
fi
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow " ---> Please refer to this tutorial for adding method, https://github.com/mack-a/v2ray-agent/blob/master/documents/dns_txt.md"
|
||
echoContent yellow " ---> Just like installing wildcard certificates on multiple machines with the same domain name, please add multiple TXT records. There is no need to modify the previously added TXT records."
|
||
echoContent yellow " ---> Please wait 1-2 minutes after the addition is completed"
|
||
echoContent yellow "\n ---> Port: ${port}"
|
||
echoContent yellow "Please enter the port [cannot be the same as the BT Panel port, press Enter to be random]"
|
||
echoContent yellow "Please enter the port [default: 443], you can customize the port [press Enter to use the default]"
|
||
echoContent yellow "\n ---> Port: ${port}"
|
||
echoContent yellow " ---> If the certificate has not expired or is customized, please select [n]\n"
|
||
echoContent yellow " ---> acme.sh is not installed"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" selectXrayType
|
||
if [[ "${selectXrayType}" == "1" ]]; then
|
||
prereleaseStatus=false
|
||
updateXray
|
||
elif [[ "${selectXrayType}" == "2" ]]; then
|
||
prereleaseStatus=true
|
||
updateXray
|
||
elif [[ "${selectXrayType}" == "3" ]]; then
|
||
echoContent yellow "Please enter a custom path [eg: alone], no slash required, [Enter] random path"
|
||
echoContent yellow "\n path:${currentPath}"
|
||
echoContent yellow " ---> Regenerate certificate"
|
||
echoContent skyBlue "------------------------Version-------------------------------"
|
||
curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5" | jq -r ".[]|select (.prerelease==false)|.tag_name" | awk '{print ""NR""":"$0}'
|
||
echoContent skyBlue "--------------------------------------------------------------"
|
||
read -r -p "Please enter the version you want to roll back:" selectXrayVersionType
|
||
version=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5" | jq -r ".[]|select (.prerelease==false)|.tag_name" | awk '{print ""NR""":"$0}' | grep "${selectXrayVersionType}:" | awk -F "[:]" '{print $2}')
|
||
if [[ -n "${version}" ]]; then
|
||
updateXray "${version}"
|
||
else
|
||
echoContent red " ---> The installation directory is not detected, please execute the script to install the content"
|
||
xrayVersionManageMenu 1
|
||
fi
|
||
elif [[ "${selectXrayType}" == "4" ]]; then
|
||
handleXray stop
|
||
elif [[ "${selectXrayType}" == "5" ]]; then
|
||
# start up
|
||
handleXray start
|
||
elif [[ "${selectXrayType}" == "6" ]]; then
|
||
reloadCore
|
||
elif [[ "${selectXrayType}" == "7" ]]; then
|
||
updateGeoSite
|
||
elif [[ "${selectXrayType}" == "8" ]]; then
|
||
installCronUpdateGeo
|
||
elif [[ "${selectXrayType}" == "9" ]]; then
|
||
checkLog 1
|
||
fi
|
||
}
|
||
|
||
# Update geosite
|
||
updateGeoSite() {
|
||
echoContent yellow "1.Upgrade v2ray-core"
|
||
|
||
version=$(curl -s https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases?per_page=1 | jq -r '.[]|.tag_name')
|
||
echoContent skyBlue "------------------------Version-------------------------------"
|
||
echo "version:${version}"
|
||
rm ${configPath}../geo* >/dev/null
|
||
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
wget -c -q -P ${configPath}../ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat"
|
||
wget -c -q -P ${configPath}../ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat"
|
||
else
|
||
wget -c -q "${wgetShowProgressStatus}" -P ${configPath}../ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat"
|
||
wget -c -q "${wgetShowProgressStatus}" -P ${configPath}../ "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat"
|
||
fi
|
||
|
||
reloadCore
|
||
echoContent green " ---> Tuic version:${version}"
|
||
|
||
}
|
||
|
||
# Update Xray
|
||
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
|
||
fi
|
||
|
||
echoContent green " ---> Tuic version:$(/etc/v2ray-agent/tuic/tuic -v)"
|
||
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
wget -c -q -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip"
|
||
else
|
||
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip"
|
||
fi
|
||
|
||
unzip -o "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" -d /etc/v2ray-agent/xray >/dev/null
|
||
rm -rf "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip"
|
||
chmod 655 /etc/v2ray-agent/xray/xray
|
||
handleXray stop
|
||
handleXray start
|
||
else
|
||
echoContent green " ---> Xray-core version:${version}"
|
||
|
||
if [[ "${prereleaseStatus}" == "true" ]]; then
|
||
remoteVersion=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1)
|
||
else
|
||
remoteVersion=$(curl -s https://api.github.com/repos/XTLS/Xray-core/releases/latest | jq -r .tag_name)
|
||
fi
|
||
|
||
echoContent green " ---> Xray-core version:$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)"
|
||
|
||
if [[ -n "$1" ]]; then
|
||
version=$1
|
||
else
|
||
version=${remoteVersion}
|
||
fi
|
||
|
||
if [[ -n "$1" ]]; then
|
||
read -r -p "The rollback version is ${version}, do you want to continue? [y/n]:" rollbackXrayStatus
|
||
if [[ "${rollbackXrayStatus}" == "y" ]]; then
|
||
echoContent green " ---> Update completed"
|
||
|
||
handleXray stop
|
||
rm -f /etc/v2ray-agent/xray/xray
|
||
updateXray "${version}"
|
||
else
|
||
echoContent green " ---> v2ray-core version:${version}"
|
||
fi
|
||
elif [[ "${version}" == "v$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)" ]]; then
|
||
read -r -p "The current version is the same as the latest version. Do you want to reinstall? [y/n]:" reInstallXrayStatus
|
||
if [[ "${reInstallXrayStatus}" == "y" ]]; then
|
||
handleXray stop
|
||
rm -f /etc/v2ray-agent/xray/xray
|
||
updateXray
|
||
else
|
||
echoContent green " ---> Current v2ray-core version: $(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)"
|
||
fi
|
||
else
|
||
read -r -p "The latest version is: ${version}, is it updated? [y/n]:" installXrayStatus
|
||
if [[ "${installXrayStatus}" == "y" ]]; then
|
||
rm /etc/v2ray-agent/xray/xray
|
||
updateXray
|
||
else
|
||
echoContent green " ---> Current v2ray-core version: $(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)"
|
||
fi
|
||
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Verify that the entire service is available
|
||
checkGFWStatue() {
|
||
readInstallType
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Installing Hysteria"
|
||
if [[ "${coreInstallType}" == "1" ]] && [[ -n $(pgrep -f "xray/xray") ]]; then
|
||
echoContent green " ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)"
|
||
elif [[ "${coreInstallType}" == "2" ]] && [[ -n $(pgrep -f "sing-box/sing-box") ]]; then
|
||
echoContent green " ---> Abandon the rollback version"
|
||
else
|
||
echoContent red "\n================================================ ================="
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
installAlpineStartup() {
|
||
local serviceName=$1
|
||
if [[ "${serviceName}" == "sing-box" ]]; then
|
||
cat <<EOF >"/etc/init.d/${serviceName}"
|
||
#!/sbin/openrc-run
|
||
|
||
description="sing-box service"
|
||
command="/etc/v2ray-agent/sing-box/sing-box"
|
||
command_args="run -c /etc/v2ray-agent/sing-box/conf/config.json"
|
||
command_background=true
|
||
pidfile="/var/run/sing-box.pid"
|
||
EOF
|
||
elif [[ "${serviceName}" == "xray" ]]; then
|
||
cat <<EOF >"/etc/init.d/${serviceName}"
|
||
#!/sbin/openrc-run
|
||
|
||
description="xray service"
|
||
command="/etc/v2ray-agent/xray/xray"
|
||
command_args="run -confdir /etc/v2ray-agent/xray/conf"
|
||
command_background=true
|
||
pidfile="/var/run/xray.pid"
|
||
EOF
|
||
fi
|
||
|
||
chmod +x "/etc/init.d/${serviceName}"
|
||
}
|
||
|
||
installSingBoxService() {
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Install Tuic"
|
||
execStart='/etc/v2ray-agent/sing-box/sing-box run -c /etc/v2ray-agent/sing-box/conf/config.json'
|
||
|
||
if [[ -n $(find /bin /usr/bin -name "systemctl") && "${release}" != "alpine" ]]; then
|
||
rm -rf /etc/systemd/system/sing-box.service
|
||
touch /etc/systemd/system/sing-box.service
|
||
cat <<EOF >/etc/systemd/system/sing-box.service
|
||
[Unit]
|
||
Description=Sing-Box Service
|
||
Documentation=https://sing-box.sagernet.org
|
||
After=network.target nss-lookup.target
|
||
|
||
[Service]
|
||
User=root
|
||
WorkingDirectory=/root
|
||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||
ExecStart=${execStart}
|
||
ExecReload=/bin/kill -HUP $MAINPID
|
||
Restart=on-failure
|
||
RestartSec=10
|
||
LimitNPROC=infinity
|
||
LimitNOFILE=infinity
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
bootStartup "sing-box.service"
|
||
elif [[ "${release}" == "alpine" ]]; then
|
||
installAlpineStartup "sing-box"
|
||
bootStartup "sing-box"
|
||
fi
|
||
|
||
echoContent green " ---> Give up and reinstall"
|
||
}
|
||
|
||
# Xray starts automatically after booting
|
||
installXrayService() {
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Install Xray"
|
||
execStart='/etc/v2ray-agent/xray/xray run -confdir /etc/v2ray-agent/xray/conf'
|
||
if [[ -n $(find /bin /usr/bin -name "systemctl") ]]; then
|
||
rm -rf /etc/systemd/system/xray.service
|
||
touch /etc/systemd/system/xray.service
|
||
cat <<EOF >/etc/systemd/system/xray.service
|
||
[Unit]
|
||
Description=Xray Service
|
||
Documentation=https://github.com/xtls
|
||
After=network.target nss-lookup.target
|
||
[Service]
|
||
User=root
|
||
ExecStart=${execStart}
|
||
Restart=on-failure
|
||
RestartPreventExitStatus=23
|
||
LimitNPROC=infinity
|
||
LimitNOFILE=infinity
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
bootStartup "xray.service"
|
||
echoContent green " ---> Abort update"
|
||
elif [[ "${release}" == "alpine" ]]; then
|
||
installAlpineStartup "xray"
|
||
bootStartup "xray"
|
||
fi
|
||
}
|
||
|
||
# Operation Hysteria
|
||
handleHysteria() {
|
||
# shellcheck disable=SC2010
|
||
# shellcheck disable=SC2010
|
||
if find /bin /usr/bin | grep -q systemctl && ls /etc/systemd/system/ | grep -q hysteria.service; then
|
||
if [[ -z $(pgrep -f "hysteria/hysteria") ]] && [[ "$1" == "start" ]]; then
|
||
systemctl start hysteria.service
|
||
elif [[ -n $(pgrep -f "hysteria/hysteria") ]] && [[ "$1" == "stop" ]]; then
|
||
systemctl stop hysteria.service
|
||
fi
|
||
fi
|
||
sleep 0.8
|
||
|
||
if [[ "$1" == "start" ]]; then
|
||
if [[ -n $(pgrep -f "hysteria/hysteria") ]]; then
|
||
echoContent green " ---> Xray-core version:${version}"
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
echoContent red "\n ---> Incorrect input, please re-enter"
|
||
exit 0
|
||
fi
|
||
elif [[ "$1" == "stop" ]]; then
|
||
if [[ -z $(pgrep -f "hysteria/hysteria") ]]; then
|
||
echoContent green " ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)"
|
||
else
|
||
echoContent red " ---> The installation directory is not detected, please execute the script to install the content"
|
||
echoContent red "\n================================================ ================="
|
||
exit 0
|
||
fi
|
||
fi
|
||
}
|
||
|
||
handleSingBox() {
|
||
if [[ -f "/etc/systemd/system/sing-box.service" ]]; then
|
||
if [[ -z $(pgrep -f "sing-box") ]] && [[ "$1" == "start" ]]; then
|
||
singBoxMergeConfig
|
||
systemctl start sing-box.service
|
||
elif [[ -n $(pgrep -f "sing-box") ]] && [[ "$1" == "stop" ]]; then
|
||
systemctl stop sing-box.service
|
||
fi
|
||
elif [[ -f "/etc/init.d/sing-box" ]]; then
|
||
if [[ -z $(pgrep -f "sing-box") ]] && [[ "$1" == "start" ]]; then
|
||
singBoxMergeConfig
|
||
rc-service sing-box start
|
||
elif [[ -n $(pgrep -f "sing-box") ]] && [[ "$1" == "stop" ]]; then
|
||
rc-service sing-box stop
|
||
fi
|
||
fi
|
||
sleep 1
|
||
|
||
if [[ "$1" == "start" ]]; then
|
||
if [[ -n $(pgrep -f "sing-box") ]]; then
|
||
echoContent green " ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)"
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
echoContent yellow "2.Fallback v2ray-core"
|
||
echo
|
||
echoContent yellow "3.Close v2ray-core"
|
||
exit 0
|
||
fi
|
||
elif [[ "$1" == "stop" ]]; then
|
||
if [[ -z $(pgrep -f "sing-box") ]]; then
|
||
echoContent green " ---> Abandon the rollback version"
|
||
else
|
||
echoContent red "\n ---> Incorrect input, please re-enter"
|
||
echoContent red " ---> Service startup failed, please check if there are logs printed in the terminal"
|
||
exit 0
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Manipulate xray
|
||
handleXray() {
|
||
if [[ -n $(find /bin /usr/bin -name "systemctl") ]] && [[ -n $(find /etc/systemd/system/ -name "xray.service") ]]; then
|
||
if [[ -z $(pgrep -f "xray/xray") ]] && [[ "$1" == "start" ]]; then
|
||
systemctl start xray.service
|
||
elif [[ -n $(pgrep -f "xray/xray") ]] && [[ "$1" == "stop" ]]; then
|
||
systemctl stop xray.service
|
||
fi
|
||
elif [[ -f "/etc/init.d/xray" ]]; then
|
||
if [[ -z $(pgrep -f "xray/xray") ]] && [[ "$1" == "start" ]]; then
|
||
rc-service xray start
|
||
elif [[ -n $(pgrep -f "xray/xray") ]] && [[ "$1" == "stop" ]]; then
|
||
rc-service xray stop
|
||
fi
|
||
fi
|
||
|
||
sleep 0.8
|
||
|
||
if [[ "$1" == "start" ]]; then
|
||
if [[ -n $(pgrep -f "xray/xray") ]]; then
|
||
echoContent green " ---> Give up and reinstall"
|
||
else
|
||
echoContent red "V2Ray failed to start"
|
||
echoContent red "Please manually execute [/etc/v2ray-agent/v2ray/v2ray -confdir /etc/v2ray-agent/v2ray/conf] and check the error log"
|
||
exit 0
|
||
fi
|
||
elif [[ "$1" == "stop" ]]; then
|
||
if [[ -z $(pgrep -f "xray/xray") ]]; then
|
||
echoContent green " ---> Abort update"
|
||
else
|
||
echoContent red "V2Ray failed to close"
|
||
echoContent red "Please execute manually [ps -ef|grep -v grep|grep v2ray|awk '{print \$2}'|xargs kill -9]"
|
||
exit 0
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Read user data and initialize
|
||
initXrayClients() {
|
||
local type=",$1,"
|
||
local newUUID=$2
|
||
local newEmail=$3
|
||
if [[ -n "${newUUID}" ]]; then
|
||
local newUser=
|
||
newUser="{\"id\":\"${uuid}\",\"flow\":\"xtls-rprx-vision\",\"email\":\"${newEmail}-VLESS_TCP/TLS_Vision\"}"
|
||
currentClients=$(echo "${currentClients}" | jq -r ". +=[${newUser}]")
|
||
fi
|
||
local users=
|
||
users=[]
|
||
while read -r user; do
|
||
uuid=$(echo "${user}" | jq -r .id//.uuid)
|
||
email=$(echo "${user}" | jq -r .email//.name | awk -F "[-]" '{print $1}')
|
||
currentUser=
|
||
if echo "${type}" | grep -q "0"; then
|
||
currentUser="{\"id\":\"${uuid}\",\"flow\":\"xtls-rprx-vision\",\"email\":\"${email}-VLESS_TCP/TLS_Vision\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# VLESS WS
|
||
if echo "${type}" | grep -q ",1,"; then
|
||
currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-VLESS_WS\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
# VLESS XHTTP
|
||
if echo "${type}" | grep -q ",12,"; then
|
||
currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-VLESS_Reality_XHTTP\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
# trojan grpc
|
||
if echo "${type}" | grep -q ",2,"; then
|
||
currentUser="{\"password\":\"${uuid}\",\"email\":\"${email}-Trojan_gRPC\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
# VMess WS
|
||
if echo "${type}" | grep -q ",3,"; then
|
||
currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-VMess_WS\",\"alterId\": 0}"
|
||
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# trojan tcp
|
||
if echo "${type}" | grep -q ",4,"; then
|
||
currentUser="{\"password\":\"${uuid}\",\"email\":\"${email}-trojan_tcp\"}"
|
||
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# vless grpc
|
||
if echo "${type}" | grep -q ",5,"; then
|
||
currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-vless_grpc\"}"
|
||
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# hysteria
|
||
if echo "${type}" | grep -q ",6,"; then
|
||
currentUser="{\"password\":\"${uuid}\",\"name\":\"${email}-singbox_hysteria2\"}"
|
||
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# vless reality vision
|
||
if echo "${type}" | grep -q ",7,"; then
|
||
currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-vless_reality_vision\",\"flow\":\"xtls-rprx-vision\"}"
|
||
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# vless reality grpc
|
||
if echo "${type}" | grep -q ",8,"; then
|
||
currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-vless_reality_grpc\",\"flow\":\"\"}"
|
||
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
# tuic
|
||
if echo "${type}" | grep -q ",9,"; then
|
||
currentUser="{\"uuid\":\"${uuid}\",\"password\":\"${uuid}\",\"name\":\"${email}-singbox_tuic\"}"
|
||
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
done < <(echo "${currentClients}" | jq -c '.[]')
|
||
echo "${users}"
|
||
}
|
||
initSingBoxClients() {
|
||
local type=",$1,"
|
||
local newUUID=$2
|
||
local newName=$3
|
||
|
||
if [[ -n "${newUUID}" ]]; then
|
||
local newUser=
|
||
newUser="{\"uuid\":\"${newUUID}\",\"flow\":\"xtls-rprx-vision\",\"name\":\"${newName}-VLESS_TCP/TLS_Vision\"}"
|
||
currentClients=$(echo "${currentClients}" | jq -r ". +=[${newUser}]")
|
||
fi
|
||
local users=
|
||
users=[]
|
||
while read -r user; do
|
||
uuid=$(echo "${user}" | jq -r .uuid//.id//.password)
|
||
name=$(echo "${user}" | jq -r .name//.email//.username | awk -F "[-]" '{print $1}')
|
||
currentUser=
|
||
# VLESS Vision
|
||
if echo "${type}" | grep -q ",0,"; then
|
||
currentUser="{\"uuid\":\"${uuid}\",\"flow\":\"xtls-rprx-vision\",\"name\":\"${name}-VLESS_TCP/TLS_Vision\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
# VLESS WS
|
||
if echo "${type}" | grep -q ",1,"; then
|
||
currentUser="{\"uuid\":\"${uuid}\",\"name\":\"${name}-VLESS_WS\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
# VMess ws
|
||
if echo "${type}" | grep -q ",3,"; then
|
||
currentUser="{\"uuid\":\"${uuid}\",\"name\":\"${name}-VMess_WS\",\"alterId\": 0}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# trojan
|
||
if echo "${type}" | grep -q ",4,"; then
|
||
currentUser="{\"password\":\"${uuid}\",\"name\":\"${name}-Trojan_TCP\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# VLESS Reality Vision
|
||
if echo "${type}" | grep -q ",7,"; then
|
||
currentUser="{\"uuid\":\"${uuid}\",\"flow\":\"xtls-rprx-vision\",\"name\":\"${name}-VLESS_Reality_Vision\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
# VLESS Reality gRPC
|
||
if echo "${type}" | grep -q ",8,"; then
|
||
currentUser="{\"uuid\":\"${uuid}\",\"name\":\"${name}-VLESS_Reality_gPRC\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# hysteria2
|
||
if echo "${type}" | grep -q ",6,"; then
|
||
currentUser="{\"password\":\"${uuid}\",\"name\":\"${name}-singbox_hysteria2\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# tuic
|
||
if echo "${type}" | grep -q ",9,"; then
|
||
currentUser="{\"uuid\":\"${uuid}\",\"password\":\"${uuid}\",\"name\":\"${name}-singbox_tuic\"}"
|
||
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
# naive
|
||
if echo "${type}" | grep -q ",10,"; then
|
||
currentUser="{\"password\":\"${uuid}\",\"username\":\"${name}-singbox_naive\"}"
|
||
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
# VMess HTTPUpgrade
|
||
if echo "${type}" | grep -q ",11,"; then
|
||
currentUser="{\"uuid\":\"${uuid}\",\"name\":\"${name}-VMess_HTTPUpgrade\",\"alterId\": 0}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
# anytls
|
||
if echo "${type}" | grep -q ",13,"; then
|
||
currentUser="{\"password\":\"${uuid}\",\"name\":\"${name}-anytls\"}"
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
if echo "${type}" | grep -q ",20,"; then
|
||
currentUser="{\"username\":\"${uuid}\",\"password\":\"${uuid}\"}"
|
||
|
||
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
|
||
fi
|
||
|
||
done < <(echo "${currentClients}" | jq -c '.[]')
|
||
echo "${users}"
|
||
}
|
||
|
||
#Initialize hysteria port
|
||
initHysteriaPort() {
|
||
readSingBoxConfig
|
||
if [[ -n "${hysteriaPort}" ]]; then
|
||
read -r -p "Read the port from the last installation. Do you want to use the port from the last installation? [y/n]:" historyHysteriaPortStatus
|
||
if [[ "${historyHysteriaPortStatus}" == "y" ]]; then
|
||
echoContent yellow "4.Open v2ray-core"
|
||
else
|
||
hysteriaPort=
|
||
fi
|
||
fi
|
||
|
||
if [[ -z "${hysteriaPort}" ]]; then
|
||
echoContent yellow "5.Restart v2ray-core"
|
||
read -r -p "Port:" hysteriaPort
|
||
if [[ -z "${hysteriaPort}" ]]; then
|
||
hysteriaPort=$((RANDOM % 20001 + 10000))
|
||
fi
|
||
fi
|
||
if [[ -z ${hysteriaPort} ]]; then
|
||
echoContent red "Hysteria startup failed"
|
||
initHysteriaPort "$2"
|
||
elif ((hysteriaPort < 1 || hysteriaPort > 65535)); then
|
||
echoContent red "Please manually execute [/etc/v2ray-agent/hysteria/hysteria --log-level debug -c /etc/v2ray-agent/hysteria/conf/config.json server] to view the error log"
|
||
initHysteriaPort "$2"
|
||
fi
|
||
allowPort "${hysteriaPort}"
|
||
allowPort "${hysteriaPort}" "udp"
|
||
}
|
||
|
||
initHysteria2Network() {
|
||
|
||
echoContent yellow "6.Update geosite, geoip"
|
||
read -r -p "Download speed:" hysteria2ClientDownloadSpeed
|
||
if [[ -z "${hysteria2ClientDownloadSpeed}" ]]; then
|
||
hysteria2ClientDownloadSpeed=100
|
||
echoContent green " ---> Service started successfully"
|
||
fi
|
||
|
||
echoContent yellow "7.Set up automatic update of geo files [updated every morning]"
|
||
read -r -p "Upload speed:" hysteria2ClientUploadSpeed
|
||
if [[ -z "${hysteria2ClientUploadSpeed}" ]]; then
|
||
hysteria2ClientUploadSpeed=50
|
||
echoContent green " ---> Service started successfully"
|
||
fi
|
||
}
|
||
|
||
addFirewalldPortHopping() {
|
||
|
||
local start=$1
|
||
local end=$2
|
||
local targetPort=$3
|
||
for port in $(seq "$start" "$end"); do
|
||
sudo firewall-cmd --permanent --add-forward-port=port="${port}":proto=udp:toport="${targetPort}"
|
||
done
|
||
sudo firewall-cmd --reload
|
||
}
|
||
|
||
addPortHopping() {
|
||
local type=$1
|
||
local targetPort=$2
|
||
if [[ -n "${portHoppingStart}" || -n "${portHoppingEnd}" ]]; then
|
||
echoContent red "Hysteria shutdown failed"
|
||
exit 0
|
||
fi
|
||
if [[ "${release}" == "centos" ]]; then
|
||
if ! systemctl status firewalld 2>/dev/null | grep -q "active (running)"; then
|
||
echoContent red "Please execute manually [ps -ef|grep -v grep|grep hysteria|awk '{print \$2}'|xargs kill -9]"
|
||
exit 0
|
||
fi
|
||
fi
|
||
|
||
echoContent skyBlue "------------------------Version-------------------------------"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "\n1.Only the last five versions can be rolled back"
|
||
echoContent yellow "2.There is no guarantee that it will be able to be used normally after the rollback"
|
||
echoContent yellow "3.If the rolled-back version does not support the current config, it will be unable to connect, so operate with caution"
|
||
echoContent yellow "1.Upgrade Xray-core"
|
||
echoContent yellow "2.Upgrade Xray-core preview version"
|
||
echoContent yellow "3.Fallback Xray-core"
|
||
echoContent yellow "4.Close Xray-core"
|
||
|
||
echoContent yellow "5.Open Xray-core"
|
||
|
||
read -r -p "Range:" portHoppingRange
|
||
if [[ -z "${portHoppingRange}" ]]; then
|
||
echoContent red "Tuic startup failed"
|
||
addPortHopping "${type}" "${targetPort}"
|
||
elif echo "${portHoppingRange}" | grep -q "-"; then
|
||
|
||
local portStart=
|
||
local portEnd=
|
||
portStart=$(echo "${portHoppingRange}" | awk -F '-' '{print $1}')
|
||
portEnd=$(echo "${portHoppingRange}" | awk -F '-' '{print $2}')
|
||
|
||
if [[ -z "${portStart}" || -z "${portEnd}" ]]; then
|
||
echoContent red "Please manually execute [/etc/v2ray-agent/tuic/tuic -c /etc/v2ray-agent/tuic/conf/config.json] and check the error log"
|
||
addPortHopping "${type}" "${targetPort}"
|
||
elif ((portStart < 30000 || portStart > 40000 || portEnd < 30000 || portEnd > 40000 || portEnd < portStart)); then
|
||
echoContent red "Tuic failed to close"
|
||
addPortHopping "${type}" "${targetPort}"
|
||
else
|
||
echoContent green " ---> Configure V2Ray to start automatically at boot"
|
||
if [[ "${release}" == "centos" ]]; then
|
||
sudo firewall-cmd --permanent --add-masquerade
|
||
sudo firewall-cmd --reload
|
||
addFirewalldPortHopping "${portStart}" "${portEnd}" "${targetPort}"
|
||
if ! sudo firewall-cmd --list-forward-ports | grep -q "toport=${targetPort}"; then
|
||
echoContent red "Please execute manually [ps -ef|grep -v grep|grep tuic|awk '{print \$2}'|xargs kill -9]"
|
||
exit 0
|
||
fi
|
||
else
|
||
iptables -t nat -A PREROUTING -p udp --dport "${portStart}:${portEnd}" -m comment --comment "mack-a_${type}_portHopping" -j DNAT --to-destination ":${targetPort}"
|
||
sudo netfilter-persistent save
|
||
if ! iptables-save | grep -q "mack-a_${type}_portHopping"; then
|
||
echoContent red "Xray startup failed"
|
||
exit 0
|
||
fi
|
||
fi
|
||
allowPort "${portStart}:${portEnd}" udp
|
||
echoContent green " ---> Configure Hysteria to start automatically at boot"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
readPortHopping() {
|
||
local type=$1
|
||
local targetPort=$2
|
||
local portHoppingStart=
|
||
local portHoppingEnd=
|
||
|
||
if [[ "${release}" == "centos" ]]; then
|
||
portHoppingStart=$(sudo firewall-cmd --list-forward-ports | grep "toport=${targetPort}" | head -1 | cut -d ":" -f 1 | cut -d "=" -f 2)
|
||
portHoppingEnd=$(sudo firewall-cmd --list-forward-ports | grep "toport=${targetPort}" | tail -n 1 | cut -d ":" -f 1 | cut -d "=" -f 2)
|
||
else
|
||
if iptables-save | grep -q "mack-a_${type}_portHopping"; then
|
||
local portHopping=
|
||
portHopping=$(iptables-save | grep "mack-a_${type}_portHopping" | cut -d " " -f 8)
|
||
|
||
portHoppingStart=$(echo "${portHopping}" | cut -d ":" -f 1)
|
||
portHoppingEnd=$(echo "${portHopping}" | cut -d ":" -f 2)
|
||
fi
|
||
fi
|
||
if [[ "${type}" == "hysteria2" ]]; then
|
||
hysteria2PortHoppingStart="${portHoppingStart}"
|
||
hysteria2PortHoppingEnd=${portHoppingEnd}
|
||
hysteria2PortHopping="${portHoppingStart}-${portHoppingEnd}"
|
||
elif [[ "${type}" == "tuic" ]]; then
|
||
tuicPortHoppingStart="${portHoppingStart}"
|
||
tuicPortHoppingEnd="${portHoppingEnd}"
|
||
# tuicPortHopping="${portHoppingStart}-${portHoppingEnd}"
|
||
fi
|
||
}
|
||
deletePortHoppingRules() {
|
||
local type=$1
|
||
local start=$2
|
||
local end=$3
|
||
local targetPort=$4
|
||
|
||
if [[ "${release}" == "centos" ]]; then
|
||
for port in $(seq "${start}" "${end}"); do
|
||
sudo firewall-cmd --permanent --remove-forward-port=port="${port}":proto=udp:toport="${targetPort}"
|
||
done
|
||
sudo firewall-cmd --reload
|
||
else
|
||
iptables -t nat -L PREROUTING --line-numbers | grep "mack-a_${type}_portHopping" | awk '{print $1}' | while read -r line; do
|
||
iptables -t nat -D PREROUTING 1
|
||
sudo netfilter-persistent save
|
||
done
|
||
fi
|
||
}
|
||
|
||
portHoppingMenu() {
|
||
local type=$1
|
||
# Determine whether iptables exists
|
||
if ! find /usr/bin /usr/sbin | grep -q -w iptables; then
|
||
echoContent red "Please manually execute the following command [/etc/v2ray-agent/xray/xray -confdir /etc/v2ray-agent/xray/conf] and feedback the error log"
|
||
exit 0
|
||
fi
|
||
|
||
local targetPort=
|
||
local portHoppingStart=
|
||
local portHoppingEnd=
|
||
|
||
if [[ "${type}" == "hysteria2" ]]; then
|
||
readPortHopping "${type}" "${singBoxHysteria2Port}"
|
||
targetPort=${singBoxHysteria2Port}
|
||
portHoppingStart=${hysteria2PortHoppingStart}
|
||
portHoppingEnd=${hysteria2PortHoppingEnd}
|
||
elif [[ "${type}" == "tuic" ]]; then
|
||
readPortHopping "${type}" "${singBoxTuicPort}"
|
||
targetPort=${singBoxTuicPort}
|
||
portHoppingStart=${tuicPortHoppingStart}
|
||
portHoppingEnd=${tuicPortHoppingEnd}
|
||
fi
|
||
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: V2Ray version management"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "6.Restart Xray-core"
|
||
echoContent yellow "7.Update geosite, geoip"
|
||
echoContent yellow "8.Set up automatic update of geo files [updated every morning]"
|
||
read -r -p "range:" selectPortHoppingStatus
|
||
if [[ "${selectPortHoppingStatus}" == "1" ]]; then
|
||
addPortHopping "${type}" "${targetPort}"
|
||
elif [[ "${selectPortHoppingStatus}" == "2" ]]; then
|
||
deletePortHoppingRules "${type}" "${portHoppingStart}" "${portHoppingEnd}" "${targetPort}"
|
||
echoContent green " ---> Configuring Tuic to start automatically at boot"
|
||
elif [[ "${selectPortHoppingStatus}" == "3" ]]; then
|
||
if [[ -n "${portHoppingStart}" && -n "${portHoppingEnd}" ]]; then
|
||
echoContent green " ---> Configure Xray to start automatically at boot"
|
||
else
|
||
echoContent yellow "\n1.Only the last five versions can be rolled back"
|
||
fi
|
||
else
|
||
portHoppingMenu
|
||
fi
|
||
}
|
||
|
||
#Initialize tuic port
|
||
initTuicPort() {
|
||
readSingBoxConfig
|
||
if [[ -n "${tuicPort}" ]]; then
|
||
read -r -p "Read the port from the last installation. Do you want to use the port from the last installation? [y/n]:" historyTuicPortStatus
|
||
if [[ "${historyTuicPortStatus}" == "y" ]]; then
|
||
echoContent yellow "2.There is no guarantee that it will be able to be used normally after the rollback"
|
||
else
|
||
tuicPort=
|
||
fi
|
||
fi
|
||
|
||
if [[ -z "${tuicPort}" ]]; then
|
||
echoContent yellow "3.If the rolled-back version does not support the current config, it will be unable to connect, so operate with caution"
|
||
read -r -p "Port:" tuicPort
|
||
if [[ -z "${tuicPort}" ]]; then
|
||
tuicPort=$((RANDOM % 20001 + 10000))
|
||
fi
|
||
fi
|
||
if [[ -z ${tuicPort} ]]; then
|
||
echoContent red "xray failed to close"
|
||
initTuicPort "$2"
|
||
elif ((tuicPort < 1 || tuicPort > 65535)); then
|
||
echoContent red "Please execute manually [ps -ef|grep -v grep|grep xray|awk '{print \$2}'|xargs kill -9]"
|
||
initTuicPort "$2"
|
||
fi
|
||
echoContent green " ---> V2Ray started successfully"
|
||
allowPort "${tuicPort}"
|
||
allowPort "${tuicPort}" "udp"
|
||
}
|
||
|
||
# Initialize tuic protocol
|
||
initTuicProtocol() {
|
||
if [[ -n "${tuicAlgorithm}" && -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Previous algorithm found. Use it? [y/n]:" historyTuicAlgorithm
|
||
if [[ "${historyTuicAlgorithm}" != "y" ]]; then
|
||
tuicAlgorithm=
|
||
else
|
||
echoContent yellow "\nSource https://github.com/Loyalsoldier/v2ray-rules-dat"
|
||
fi
|
||
elif [[ -n "${tuicAlgorithm}" && -n "${lastInstallationConfig}" ]]; then
|
||
echoContent yellow "The configuration file last installed for this protocol [${protocol}] was not read, and the first uuid of the configuration file was used"
|
||
fi
|
||
|
||
if [[ -z "${tuicAlgorithm}" ]]; then
|
||
|
||
echoContent skyBlue "------------------------Version-------------------------------"
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "\n ---> Port: ${hysteriaPort}"
|
||
echoContent yellow "2.cubic"
|
||
echoContent yellow "3.new_reno"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" selectTuicAlgorithm
|
||
case ${selectTuicAlgorithm} in
|
||
1)
|
||
tuicAlgorithm="bbr"
|
||
;;
|
||
2)
|
||
tuicAlgorithm="cubic"
|
||
;;
|
||
3)
|
||
tuicAlgorithm="new_reno"
|
||
;;
|
||
*)
|
||
tuicAlgorithm="bbr"
|
||
;;
|
||
esac
|
||
echoContent yellow "Please enter the Hysteria port [enter random 10000-30000], cannot be repeated with other services"
|
||
fi
|
||
}
|
||
|
||
#initTuicConfig() {
|
||
#
|
||
# initTuicPort
|
||
# initTuicProtocol
|
||
# cat <<EOF >/etc/v2ray-agent/tuic/conf/config.json
|
||
#{
|
||
# "server": "[::]:${tuicPort}",
|
||
# "users": $(initXrayClients 9),
|
||
# "certificate": "/etc/v2ray-agent/tls/${currentHost}.crt",
|
||
# "private_key": "/etc/v2ray-agent/tls/${currentHost}.key",
|
||
# "congestion_control":"${tuicAlgorithm}",
|
||
# "alpn": ["h3"],
|
||
# "log_level": "warn"
|
||
#}
|
||
#EOF
|
||
#}
|
||
|
||
addSingBoxRouteRule() {
|
||
local outboundTag=$1
|
||
local domainList=$2
|
||
local routingName=$3
|
||
if [[ -f "${singBoxConfigPath}${routingName}.json" ]]; then
|
||
read -r -p "Previous configuration found. Keep it? [y/n]:" historyRouteStatus
|
||
if [[ "${historyRouteStatus}" == "y" ]]; then
|
||
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')"
|
||
fi
|
||
|
||
fi
|
||
local rules=
|
||
rules=$(initSingBoxRules "${domainList}" "${routingName}")
|
||
local domainRules=
|
||
domainRules=$(echo "${rules}" | jq .domainRules)
|
||
|
||
local ruleSet=
|
||
ruleSet=$(echo "${rules}" | jq .ruleSet)
|
||
|
||
local ruleSetTag=[]
|
||
if [[ "$(echo "${ruleSet}" | jq '.|length')" != "0" ]]; then
|
||
ruleSetTag=$(echo "${ruleSet}" | jq '.|map(.tag)')
|
||
fi
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
cat <<EOF >"${singBoxConfigPath}${routingName}.json"
|
||
{
|
||
"route": {
|
||
"rules": [
|
||
{
|
||
"rule_set":${ruleSetTag},
|
||
"domain_regex":${domainRules},
|
||
"outbound": "${outboundTag}"
|
||
}
|
||
],
|
||
"rule_set":${ruleSet}
|
||
}
|
||
}
|
||
EOF
|
||
jq 'if .route.rule_set == [] then del(.route.rule_set) else . end' "${singBoxConfigPath}${routingName}.json" >"${singBoxConfigPath}${routingName}_tmp.json" && mv "${singBoxConfigPath}${routingName}_tmp.json" "${singBoxConfigPath}${routingName}.json"
|
||
fi
|
||
|
||
}
|
||
|
||
removeSingBoxRouteRule() {
|
||
local outboundTag=$1
|
||
local delRules
|
||
if [[ -f "${singBoxConfigPath}${outboundTag}_route.json" ]]; then
|
||
delRules=$(jq -r 'del(.route.rules[]|select(.outbound=="'"${outboundTag}"'"))' "${singBoxConfigPath}${outboundTag}_route.json")
|
||
echo "${delRules}" >"${singBoxConfigPath}${outboundTag}_route.json"
|
||
fi
|
||
}
|
||
|
||
addSingBoxOutbound() {
|
||
local tag=$1
|
||
local type="ipv4"
|
||
local detour=$2
|
||
if echo "${tag}" | grep -q "IPv6"; then
|
||
type=ipv6
|
||
fi
|
||
if [[ -n "${detour}" ]]; then
|
||
cat <<EOF >"${singBoxConfigPath}${tag}.json"
|
||
{
|
||
"outbounds": [
|
||
{
|
||
"type": "direct",
|
||
"tag": "${tag}",
|
||
"detour": "${detour}",
|
||
"domain_strategy": "${type}_only"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif echo "${tag}" | grep -q "direct"; then
|
||
|
||
cat <<EOF >"${singBoxConfigPath}${tag}.json"
|
||
{
|
||
"outbounds": [
|
||
{
|
||
"type": "direct",
|
||
"tag": "${tag}"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif echo "${tag}" | grep -q "block"; then
|
||
|
||
cat <<EOF >"${singBoxConfigPath}${tag}.json"
|
||
{
|
||
"outbounds": [
|
||
{
|
||
"type": "block",
|
||
"tag": "${tag}"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
else
|
||
cat <<EOF >"${singBoxConfigPath}${tag}.json"
|
||
{
|
||
"outbounds": [
|
||
{
|
||
"type": "direct",
|
||
"tag": "${tag}",
|
||
"domain_strategy": "${type}_only"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
}
|
||
|
||
addXrayOutbound() {
|
||
local tag=$1
|
||
local domainStrategy=
|
||
|
||
if echo "${tag}" | grep -q "IPv4"; then
|
||
domainStrategy="ForceIPv4"
|
||
elif echo "${tag}" | grep -q "IPv6"; then
|
||
domainStrategy="ForceIPv6"
|
||
fi
|
||
|
||
if [[ -n "${domainStrategy}" ]]; then
|
||
cat <<EOF >"/etc/v2ray-agent/xray/conf/${tag}.json"
|
||
{
|
||
"outbounds":[
|
||
{
|
||
"protocol":"freedom",
|
||
"settings":{
|
||
"domainStrategy":"${domainStrategy}"
|
||
},
|
||
"tag":"${tag}"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
# direct
|
||
if echo "${tag}" | grep -q "direct"; then
|
||
cat <<EOF >"/etc/v2ray-agent/xray/conf/${tag}.json"
|
||
{
|
||
"outbounds":[
|
||
{
|
||
"protocol":"freedom",
|
||
"settings": {
|
||
"domainStrategy":"UseIP"
|
||
},
|
||
"tag":"${tag}"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
# blackhole
|
||
if echo "${tag}" | grep -q "blackhole"; then
|
||
cat <<EOF >"/etc/v2ray-agent/xray/conf/${tag}.json"
|
||
{
|
||
"outbounds":[
|
||
{
|
||
"protocol":"blackhole",
|
||
"tag":"${tag}"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
# socks5 outbound
|
||
if echo "${tag}" | grep -q "socks5"; then
|
||
cat <<EOF >"/etc/v2ray-agent/xray/conf/${tag}.json"
|
||
{
|
||
"outbounds": [
|
||
{
|
||
"protocol": "socks",
|
||
"tag": "${tag}",
|
||
"settings": {
|
||
"servers": [
|
||
{
|
||
"address": "${socks5RoutingOutboundIP}",
|
||
"port": ${socks5RoutingOutboundPort},
|
||
"users": [
|
||
{
|
||
"user": "${socks5RoutingOutboundUserName}",
|
||
"pass": "${socks5RoutingOutboundPassword}"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
if echo "${tag}" | grep -q "wireguard_out_IPv4"; then
|
||
cat <<EOF >"/etc/v2ray-agent/xray/conf/${tag}.json"
|
||
{
|
||
"outbounds": [
|
||
{
|
||
"protocol": "wireguard",
|
||
"settings": {
|
||
"secretKey": "${secretKeyWarpReg}",
|
||
"address": [
|
||
"${address}"
|
||
],
|
||
"peers": [
|
||
{
|
||
"publicKey": "${publicKeyWarpReg}",
|
||
"allowedIPs": [
|
||
"0.0.0.0/0",
|
||
"::/0"
|
||
],
|
||
"endpoint": "162.159.192.1:2408"
|
||
}
|
||
],
|
||
"reserved": ${reservedWarpReg},
|
||
"mtu": 1280
|
||
},
|
||
"tag": "${tag}"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
if echo "${tag}" | grep -q "wireguard_out_IPv6"; then
|
||
cat <<EOF >"/etc/v2ray-agent/xray/conf/${tag}.json"
|
||
{
|
||
"outbounds": [
|
||
{
|
||
"protocol": "wireguard",
|
||
"settings": {
|
||
"secretKey": "${secretKeyWarpReg}",
|
||
"address": [
|
||
"${address}"
|
||
],
|
||
"peers": [
|
||
{
|
||
"publicKey": "${publicKeyWarpReg}",
|
||
"allowedIPs": [
|
||
"0.0.0.0/0",
|
||
"::/0"
|
||
],
|
||
"endpoint": "162.159.192.1:2408"
|
||
}
|
||
],
|
||
"reserved": ${reservedWarpReg},
|
||
"mtu": 1280
|
||
},
|
||
"tag": "${tag}"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
if echo "${tag}" | grep -q "vmess-out"; then
|
||
cat <<EOF >"/etc/v2ray-agent/xray/conf/${tag}.json"
|
||
{
|
||
"outbounds": [
|
||
{
|
||
"tag": "${tag}",
|
||
"protocol": "vmess",
|
||
"streamSettings": {
|
||
"network": "ws",
|
||
"security": "tls",
|
||
"tlsSettings": {},
|
||
"wsSettings": {
|
||
"path": "${setVMessWSTLSPath}"
|
||
}
|
||
},
|
||
"mux": {
|
||
"enabled": true,
|
||
"concurrency": 8
|
||
},
|
||
"settings": {
|
||
"vnext": [
|
||
{
|
||
"address": "${setVMessWSTLSAddress}",
|
||
"port": "${setVMessWSTLSPort}",
|
||
"users": [
|
||
{
|
||
"id": "${setVMessWSTLSUUID}",
|
||
"security": "auto",
|
||
"alterId": 0
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
}
|
||
|
||
removeXrayOutbound() {
|
||
local tag=$1
|
||
if [[ -f "/etc/v2ray-agent/xray/conf/${tag}.json" ]]; then
|
||
rm "/etc/v2ray-agent/xray/conf/${tag}.json" >/dev/null 2>&1
|
||
fi
|
||
}
|
||
removeSingBoxConfig() {
|
||
|
||
local tag=$1
|
||
if [[ -f "${singBoxConfigPath}${tag}.json" ]]; then
|
||
rm "${singBoxConfigPath}${tag}.json"
|
||
fi
|
||
}
|
||
|
||
addSingBoxWireGuardEndpoints() {
|
||
local type=$1
|
||
|
||
readConfigWarpReg
|
||
|
||
cat <<EOF >"${singBoxConfigPath}wireguard_endpoints_${type}.json"
|
||
{
|
||
"endpoints": [
|
||
{
|
||
"type": "wireguard",
|
||
"tag": "wireguard_endpoints_${type}",
|
||
"address": [
|
||
"${address}"
|
||
],
|
||
"private_key": "${secretKeyWarpReg}",
|
||
"peers": [
|
||
{
|
||
"address": "162.159.192.1",
|
||
"port": 2408,
|
||
"public_key": "${publicKeyWarpReg}",
|
||
"reserved":${reservedWarpReg},
|
||
"allowed_ips": ["0.0.0.0/0","::/0"]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
}
|
||
|
||
initSingBoxHysteria2Config() {
|
||
echoContent skyBlue "------------------------------------------------- ---------------"
|
||
|
||
initHysteriaPort
|
||
initHysteria2Network
|
||
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/hysteria2.json
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"type": "hysteria2",
|
||
"listen": "::",
|
||
"listen_port": ${hysteriaPort},
|
||
"users": $(initXrayClients 6),
|
||
"up_mbps":${hysteria2ClientDownloadSpeed},
|
||
"down_mbps":${hysteria2ClientUploadSpeed},
|
||
"tls": {
|
||
"enabled": true,
|
||
"server_name":"${currentHost}",
|
||
"alpn": [
|
||
"h3"
|
||
],
|
||
"certificate_path": "/etc/v2ray-agent/tls/${currentHost}.crt",
|
||
"key_path": "/etc/v2ray-agent/tls/${currentHost}.key"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
}
|
||
|
||
singBoxTuicInstall() {
|
||
if ! echo "${currentInstallProtocolType}" | grep -qE ",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,"; then
|
||
echoContent red " ---> Port cannot be empty"
|
||
exit 0
|
||
fi
|
||
|
||
totalProgress=5
|
||
installSingBox 1
|
||
selectCustomInstallType=",9,"
|
||
initSingBoxConfig custom 2 true
|
||
installSingBoxService 3
|
||
reloadCore
|
||
showAccounts 4
|
||
}
|
||
|
||
singBoxHysteria2Install() {
|
||
if ! echo "${currentInstallProtocolType}" | grep -qE ",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,"; then
|
||
echoContent red " ---> The port is illegal"
|
||
exit 0
|
||
fi
|
||
|
||
totalProgress=5
|
||
installSingBox 1
|
||
selectCustomInstallType=",6,"
|
||
initSingBoxConfig custom 2 true
|
||
installSingBoxService 3
|
||
reloadCore
|
||
showAccounts 4
|
||
}
|
||
|
||
singBoxMergeConfig() {
|
||
rm /etc/v2ray-agent/sing-box/conf/config.json >/dev/null 2>&1
|
||
/etc/v2ray-agent/sing-box/sing-box merge config.json -C /etc/v2ray-agent/sing-box/conf/config/ -D /etc/v2ray-agent/sing-box/conf/ >/dev/null 2>&1
|
||
}
|
||
|
||
#initXrayFrontingConfig() {
|
||
# if [[ -z "${configPath}" ]]; then
|
||
# menu
|
||
# exit 0
|
||
# fi
|
||
# if [[ "${coreInstallType}" != "1" ]]; then
|
||
# fi
|
||
# local xtlsType=
|
||
# if echo ${currentInstallProtocolType} | grep -q trojan; then
|
||
# xtlsType=VLESS
|
||
# else
|
||
# xtlsType=Trojan
|
||
# fi
|
||
#
|
||
# echoContent red "\n=============================================================="
|
||
#
|
||
# echoContent red "=============================================================="
|
||
# if [[ "${selectType}" == "1" ]]; then
|
||
#
|
||
# if [[ "${xtlsType}" == "Trojan" ]]; then
|
||
#
|
||
# local VLESSConfig
|
||
# VLESSConfig=$(cat ${configPath}${frontingType}.json)
|
||
# VLESSConfig=${VLESSConfig//"id"/"password"}
|
||
# VLESSConfig=${VLESSConfig//VLESSTCP/TrojanTCPXTLS}
|
||
# VLESSConfig=${VLESSConfig//VLESS/Trojan}
|
||
# VLESSConfig=${VLESSConfig//"vless"/"trojan"}
|
||
# VLESSConfig=${VLESSConfig//"id"/"password"}
|
||
#
|
||
# echo "${VLESSConfig}" | jq . >${configPath}02_trojan_TCP_inbounds.json
|
||
# rm ${configPath}${frontingType}.json
|
||
# elif [[ "${xtlsType}" == "VLESS" ]]; then
|
||
#
|
||
# local VLESSConfig
|
||
# VLESSConfig=$(cat ${configPath}02_trojan_TCP_inbounds.json)
|
||
# VLESSConfig=${VLESSConfig//"password"/"id"}
|
||
# VLESSConfig=${VLESSConfig//TrojanTCPXTLS/VLESSTCP}
|
||
# VLESSConfig=${VLESSConfig//Trojan/VLESS}
|
||
# VLESSConfig=${VLESSConfig//"trojan"/"vless"}
|
||
# VLESSConfig=${VLESSConfig//"password"/"id"}
|
||
#
|
||
# echo "${VLESSConfig}" | jq . >${configPath}02_VLESS_TCP_inbounds.json
|
||
# rm ${configPath}02_trojan_TCP_inbounds.json
|
||
# fi
|
||
# reloadCore
|
||
# fi
|
||
#
|
||
# exit 0
|
||
#}
|
||
|
||
initSingBoxPort() {
|
||
local port=$1
|
||
if [[ -n "${port}" && -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Previous port found. Use it? [y/n]:" historyPort
|
||
if [[ "${historyPort}" != "y" ]]; then
|
||
port=
|
||
else
|
||
echo "${port}"
|
||
fi
|
||
elif [[ -n "${port}" && -n "${lastInstallationConfig}" ]]; then
|
||
echo "${port}"
|
||
fi
|
||
if [[ -z "${port}" ]]; then
|
||
read -r -p 'Enter a custom port [must be valid and unique; Enter for random]:' port
|
||
if [[ -z "${port}" ]]; then
|
||
port=$((RANDOM % 50001 + 10000))
|
||
fi
|
||
if ((port >= 1 && port <= 65535)); then
|
||
allowPort "${port}"
|
||
allowPort "${port}" "udp"
|
||
echo "${port}"
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
exit 0
|
||
fi
|
||
fi
|
||
}
|
||
|
||
#Initialize Xray configuration file
|
||
initXrayConfig() {
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Xray version management"
|
||
echo
|
||
local uuid=
|
||
local addClientsStatus=
|
||
if [[ -n "${currentUUID}" && -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Read the last installation record. Do you want to use the UUID from the last installation? [y/n]:" historyUUIDStatus
|
||
if [[ "${historyUUIDStatus}" == "y" ]]; then
|
||
addClientsStatus=true
|
||
echoContent green " ---> V2Ray closed successfully"
|
||
fi
|
||
elif [[ -n "${currentUUID}" && -n "${lastInstallationConfig}" ]]; then
|
||
addClientsStatus=true
|
||
fi
|
||
|
||
if [[ -z "${addClientsStatus}" ]]; then
|
||
echoContent yellow "1.udp(QUIC)(default)"
|
||
read -r -p 'UUID:' customUUID
|
||
|
||
if [[ -n ${customUUID} ]]; then
|
||
uuid=${customUUID}
|
||
else
|
||
uuid=$(/etc/v2ray-agent/xray/xray uuid)
|
||
fi
|
||
|
||
echoContent yellow "2.faketcp"
|
||
read -r -p 'Username:' customEmail
|
||
if [[ -z ${customEmail} ]]; then
|
||
customEmail="$(echo "${uuid}" | cut -d "-" -f 1)-VLESS_TCP/TLS_Vision"
|
||
fi
|
||
fi
|
||
|
||
if [[ -z "${addClientsStatus}" && -z "${uuid}" ]]; then
|
||
addClientsStatus=
|
||
echoContent red "================================================== ==============="
|
||
uuid=$(/etc/v2ray-agent/xray/xray uuid)
|
||
fi
|
||
|
||
if [[ -n "${uuid}" ]]; then
|
||
currentClients='[{"id":"'${uuid}'","add":"'${add}'","flow":"xtls-rprx-vision","email":"'${customEmail}'"}]'
|
||
echoContent green "\n ${customEmail}:${uuid}"
|
||
echo
|
||
fi
|
||
|
||
# log
|
||
#log
|
||
if [[ ! -f "/etc/v2ray-agent/xray/conf/00_log.json" ]]; then
|
||
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/00_log.json
|
||
{
|
||
"log": {
|
||
"error": "/etc/v2ray-agent/xray/error.log",
|
||
"loglevel": "warning",
|
||
"dnsLog": false
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
if [[ ! -f "/etc/v2ray-agent/xray/conf/12_policy.json" ]]; then
|
||
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/12_policy.json
|
||
{
|
||
"policy": {
|
||
"levels": {
|
||
"0": {
|
||
"handshake": $((1 + RANDOM % 4)),
|
||
"connIdle": $((250 + RANDOM % 51))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
addXrayOutbound "z_direct_outbound"
|
||
# dns
|
||
# dns
|
||
if [[ ! -f "/etc/v2ray-agent/xray/conf/11_dns.json" ]]; then
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/11_dns.json
|
||
{
|
||
"dns": {
|
||
"servers": [
|
||
"localhost"
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
# routing
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/09_routing.json
|
||
{
|
||
"routing": {
|
||
"rules": [
|
||
{
|
||
"type": "field",
|
||
"domain": [
|
||
"domain:gstatic.com",
|
||
"domain:googleapis.com",
|
||
"domain:googleapis.cn"
|
||
],
|
||
"outboundTag": "z_direct_outbound"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
# VLESS_TCP_TLS_Vision
|
||
local fallbacksList='{"dest":31300,"xver":1},{"alpn":"h2","dest":31302,"xver":1}'
|
||
|
||
# trojan
|
||
if echo "${selectCustomInstallType}" | grep -q ",4," || [[ "$1" == "all" ]]; then
|
||
fallbacksList='{"dest":31296,"xver":1},{"alpn":"h2","dest":31302,"xver":1}'
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/04_trojan_TCP_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"port": 31296,
|
||
"listen": "127.0.0.1",
|
||
"protocol": "trojan",
|
||
"tag":"trojanTCP",
|
||
"settings": {
|
||
"clients": $(initXrayClients 4),
|
||
"fallbacks":[
|
||
{
|
||
"dest":"31300",
|
||
"xver":1
|
||
}
|
||
]
|
||
},
|
||
"streamSettings": {
|
||
"network": "tcp",
|
||
"security": "none",
|
||
"tcpSettings": {
|
||
"acceptProxyProtocol": true
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/xray/conf/04_trojan_TCP_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
# VLESS_WS_TLS
|
||
if echo "${selectCustomInstallType}" | grep -q ",1," || [[ "$1" == "all" ]]; then
|
||
fallbacksList=${fallbacksList}',{"path":"/'${customPath}'ws","dest":31297,"xver":1}'
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/03_VLESS_WS_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"port": 31297,
|
||
"listen": "127.0.0.1",
|
||
"protocol": "vless",
|
||
"tag":"VLESSWS",
|
||
"settings": {
|
||
"clients": $(initXrayClients 1),
|
||
"decryption": "none"
|
||
},
|
||
"streamSettings": {
|
||
"network": "ws",
|
||
"security": "none",
|
||
"wsSettings": {
|
||
"acceptProxyProtocol": true,
|
||
"path": "/${customPath}ws"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/xray/conf/03_VLESS_WS_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
# VLESS_Reality_XHTTP_TLS
|
||
if echo "${selectCustomInstallType}" | grep -q ",12," || [[ "$1" == "all" ]]; then
|
||
initXrayXHTTPort
|
||
initRealityClientServersName
|
||
initRealityKey
|
||
initRealityMldsa65
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/12_VLESS_XHTTP_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"port": ${xHTTPort},
|
||
"listen": "0.0.0.0",
|
||
"protocol": "vless",
|
||
"tag":"VLESSRealityXHTTP",
|
||
"settings": {
|
||
"clients": $(initXrayClients 12),
|
||
"decryption": "none"
|
||
},
|
||
"streamSettings": {
|
||
"network": "xhttp",
|
||
"security": "reality",
|
||
"realitySettings": {
|
||
"show": false,
|
||
"target": "${realityServerName}:${realityDomainPort}",
|
||
"xver": 0,
|
||
"serverNames": [
|
||
"${realityServerName}"
|
||
],
|
||
"privateKey": "${realityPrivateKey}",
|
||
"publicKey": "${realityPublicKey}",
|
||
"mldsa65Seed": "${realityMldsa65Seed}",
|
||
"mldsa65Verify": "${realityMldsa65Verify}",
|
||
"minClientVer": "1.8.2",
|
||
"maxTimeDiff": 70000,
|
||
"shortIds": [
|
||
"",
|
||
"6ba85179e30d4fc2"
|
||
]
|
||
},
|
||
"xhttpSettings": {
|
||
"host": "${realityServerName}",
|
||
"path": "/${customPath}xHTTP",
|
||
"mode": "auto"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/xray/conf/12_VLESS_XHTTP_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
if echo "${selectCustomInstallType}" | grep -q ",3," || [[ "$1" == "all" ]]; then
|
||
fallbacksList=${fallbacksList}',{"path":"/'${customPath}'vws","dest":31299,"xver":1}'
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/05_VMess_WS_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"listen": "127.0.0.1",
|
||
"port": 31299,
|
||
"protocol": "vmess",
|
||
"tag":"VMessWS",
|
||
"settings": {
|
||
"clients": $(initXrayClients 3)
|
||
},
|
||
"streamSettings": {
|
||
"network": "ws",
|
||
"security": "none",
|
||
"wsSettings": {
|
||
"acceptProxyProtocol": true,
|
||
"path": "/${customPath}vws"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/xray/conf/05_VMess_WS_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
# VLESS_gRPC
|
||
# if echo "${selectCustomInstallType}" | grep -q ",5," || [[ "$1" == "all" ]]; then
|
||
# cat <<EOF >/etc/v2ray-agent/xray/conf/06_VLESS_gRPC_inbounds.json
|
||
#{
|
||
# "inbounds":[
|
||
# {
|
||
# "port": 31301,
|
||
# "listen": "127.0.0.1",
|
||
# "protocol": "vless",
|
||
# "tag":"VLESSGRPC",
|
||
# "settings": {
|
||
# "clients": $(initXrayClients 5),
|
||
# "decryption": "none"
|
||
# },
|
||
# "streamSettings": {
|
||
# "network": "grpc",
|
||
# "grpcSettings": {
|
||
# "serviceName": "${customPath}grpc"
|
||
# }
|
||
# }
|
||
# }
|
||
# ]
|
||
#}
|
||
#EOF
|
||
# elif [[ -z "$3" ]]; then
|
||
# rm /etc/v2ray-agent/xray/conf/06_VLESS_gRPC_inbounds.json >/dev/null 2>&1
|
||
# fi
|
||
|
||
# VLESS Vision
|
||
if echo "${selectCustomInstallType}" | grep -q ",0," || [[ "$1" == "all" ]]; then
|
||
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"port": ${port},
|
||
"protocol": "vless",
|
||
"tag":"VLESSTCP",
|
||
"settings": {
|
||
"clients":$(initXrayClients 0),
|
||
"decryption": "none",
|
||
"fallbacks": [
|
||
${fallbacksList}
|
||
]
|
||
},
|
||
"add": "${add}",
|
||
"streamSettings": {
|
||
"network": "tcp",
|
||
"security": "tls",
|
||
"tlsSettings": {
|
||
"rejectUnknownSni": true,
|
||
"minVersion": "1.2",
|
||
"certificates": [
|
||
{
|
||
"certificateFile": "/etc/v2ray-agent/tls/${domain}.crt",
|
||
"keyFile": "/etc/v2ray-agent/tls/${domain}.key",
|
||
"ocspStapling": 3600
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
# VLESS_TCP/reality
|
||
if echo "${selectCustomInstallType}" | grep -q ",7," || [[ "$1" == "all" ]]; then
|
||
echoContent skyBlue "------------------------Version-------------------------------"
|
||
|
||
initXrayRealityPort
|
||
initRealityClientServersName
|
||
initRealityKey
|
||
initRealityMldsa65
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"tag": "dokodemo-in-VLESSReality",
|
||
"port": ${realityPort},
|
||
"protocol": "dokodemo-door",
|
||
"settings": {
|
||
"address": "127.0.0.1",
|
||
"port": 45987,
|
||
"network": "tcp"
|
||
},
|
||
"sniffing": {
|
||
"enabled": true,
|
||
"destOverride": [
|
||
"tls"
|
||
],
|
||
"routeOnly": true
|
||
}
|
||
},
|
||
{
|
||
"listen": "127.0.0.1",
|
||
"port": 45987,
|
||
"protocol": "vless",
|
||
"settings": {
|
||
"clients": $(initXrayClients 7),
|
||
"decryption": "none",
|
||
"fallbacks":[
|
||
]
|
||
},
|
||
"streamSettings": {
|
||
"network": "tcp",
|
||
"security": "reality",
|
||
"realitySettings": {
|
||
"show": false,
|
||
"target": "${realityServerName}:${realityDomainPort}",
|
||
"xver": 0,
|
||
"serverNames": [
|
||
"${realityServerName}"
|
||
],
|
||
"privateKey": "${realityPrivateKey}",
|
||
"publicKey": "${realityPublicKey}",
|
||
"mldsa65Seed": "${realityMldsa65Seed}",
|
||
"mldsa65Verify": "${realityMldsa65Verify}",
|
||
"minClientVer": "1.8.2",
|
||
"maxTimeDiff": 70000,
|
||
"shortIds": [
|
||
"",
|
||
"6ba85179e30d4fc2"
|
||
]
|
||
}
|
||
},
|
||
"sniffing": {
|
||
"enabled": true,
|
||
"destOverride": [
|
||
"http",
|
||
"tls",
|
||
"quic"
|
||
],
|
||
"routeOnly": true
|
||
}
|
||
}
|
||
],
|
||
"routing": {
|
||
"rules": [
|
||
{
|
||
"inboundTag": [
|
||
"dokodemo-in"
|
||
],
|
||
"domain": [
|
||
"${realityServerName}"
|
||
],
|
||
"outboundTag": "z_direct_outbound"
|
||
},
|
||
{
|
||
"inboundTag": [
|
||
"dokodemo-in"
|
||
],
|
||
"outboundTag": "blackhole_out"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
# cat <<EOF >/etc/v2ray-agent/xray/conf/08_VLESS_vision_gRPC_inbounds.json
|
||
#{
|
||
# "inbounds": [
|
||
# {
|
||
# "port": 31305,
|
||
# "listen": "127.0.0.1",
|
||
# "protocol": "vless",
|
||
# "tag": "VLESSRealityGRPC",
|
||
# "settings": {
|
||
# "clients": $(initXrayClients 8),
|
||
# "decryption": "none"
|
||
# },
|
||
# "streamSettings": {
|
||
# "network": "grpc",
|
||
# "grpcSettings": {
|
||
# "serviceName": "grpc",
|
||
# "multiMode": true
|
||
# },
|
||
# "sockopt": {
|
||
# "acceptProxyProtocol": true
|
||
# }
|
||
# }
|
||
# }
|
||
# ]
|
||
#}
|
||
#EOF
|
||
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json >/dev/null 2>&1
|
||
rm /etc/v2ray-agent/xray/conf/08_VLESS_vision_gRPC_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
installSniffing
|
||
if [[ -z "$3" ]]; then
|
||
removeXrayOutbound wireguard_out_IPv4_route
|
||
removeXrayOutbound wireguard_out_IPv6_route
|
||
removeXrayOutbound wireguard_outbound
|
||
removeXrayOutbound IPv4_out
|
||
removeXrayOutbound IPv6_out
|
||
removeXrayOutbound socks5_outbound
|
||
removeXrayOutbound blackhole_out
|
||
removeXrayOutbound wireguard_out_IPv6
|
||
removeXrayOutbound wireguard_out_IPv4
|
||
addXrayOutbound z_direct_outbound
|
||
addXrayOutbound blackhole_out
|
||
fi
|
||
}
|
||
|
||
initTCPBrutal() {
|
||
echoContent skyBlue "------------------------------------------------- ---------------"
|
||
read -r -p "Use TCP_Brutal? [y/n]:" tcpBrutalStatus
|
||
if [[ "${tcpBrutalStatus}" == "y" ]]; then
|
||
read -r -p "Enter local peak download speed (default: 100 Mbps):" tcpBrutalClientDownloadSpeed
|
||
if [[ -z "${tcpBrutalClientDownloadSpeed}" ]]; then
|
||
tcpBrutalClientDownloadSpeed=100
|
||
fi
|
||
|
||
read -r -p "Enter local peak upload speed (default: 50 Mbps):" tcpBrutalClientUploadSpeed
|
||
if [[ -z "${tcpBrutalClientUploadSpeed}" ]]; then
|
||
tcpBrutalClientUploadSpeed=50
|
||
fi
|
||
fi
|
||
}
|
||
initSingBoxConfig() {
|
||
echoContent skyBlue "------------------------Version-------------------------------"
|
||
|
||
echo
|
||
local uuid=
|
||
local addClientsStatus=
|
||
local sslDomain=
|
||
if [[ -n "${domain}" ]]; then
|
||
sslDomain="${domain}"
|
||
elif [[ -n "${currentHost}" ]]; then
|
||
sslDomain="${currentHost}"
|
||
fi
|
||
if [[ -n "${currentUUID}" && -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Read the last user configuration. Do you want to use the last installed configuration? [y/n]:" historyUUIDStatus
|
||
if [[ "${historyUUIDStatus}" == "y" ]]; then
|
||
addClientsStatus=true
|
||
echoContent green " ---> Hysteria started successfully"
|
||
fi
|
||
elif [[ -n "${currentUUID}" && -n "${lastInstallationConfig}" ]]; then
|
||
addClientsStatus=true
|
||
fi
|
||
|
||
if [[ -z "${addClientsStatus}" ]]; then
|
||
echoContent yellow "3.wechat-video"
|
||
read -r -p 'UUID:' customUUID
|
||
|
||
if [[ -n ${customUUID} ]]; then
|
||
uuid=${customUUID}
|
||
else
|
||
uuid=$(/etc/v2ray-agent/sing-box/sing-box generate uuid)
|
||
fi
|
||
|
||
echoContent yellow "\n ---> Protocol: ${hysteriaProtocol}\n"
|
||
read -r -p 'Username:' customEmail
|
||
if [[ -z ${customEmail} ]]; then
|
||
customEmail="$(echo "${uuid}" | cut -d "-" -f 1)-VLESS_TCP/TLS_Vision"
|
||
fi
|
||
fi
|
||
|
||
if [[ -z "${addClientsStatus}" && -z "${uuid}" ]]; then
|
||
addClientsStatus=
|
||
echoContent red " ---> Already added, cannot be added repeatedly, can be deleted and re-added"
|
||
uuid=$(/etc/v2ray-agent/sing-box/sing-box generate uuid)
|
||
fi
|
||
|
||
if [[ -n "${uuid}" ]]; then
|
||
currentClients='[{"uuid":"'${uuid}'","flow":"xtls-rprx-vision","name":"'${customEmail}'"}]'
|
||
echoContent yellow "\n ${customEmail}:${uuid}"
|
||
fi
|
||
|
||
# VLESS Vision
|
||
if echo "${selectCustomInstallType}" | grep -q ",0," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "Please enter the average delay from local to server, please fill it in according to the actual situation (default: 180, unit: ms)"
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Verify service startup status"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxVLESSVisionPort}")
|
||
echoContent green " ---> Hysteria closed successfully"
|
||
|
||
checkDNSIP "${domain}"
|
||
removeNginxDefaultConf
|
||
handleSingBox stop
|
||
|
||
checkPortOpen "${result[-1]}" "${domain}"
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/02_VLESS_TCP_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"type": "vless",
|
||
"listen":"::",
|
||
"listen_port":${result[-1]},
|
||
"tag":"VLESSTCP",
|
||
"users":$(initSingBoxClients 0),
|
||
"tls":{
|
||
"server_name": "${sslDomain}",
|
||
"enabled": true,
|
||
"certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt",
|
||
"key_path": "/etc/v2ray-agent/tls/${sslDomain}.key"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/02_VLESS_TCP_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
if echo "${selectCustomInstallType}" | grep -q ",1," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "\n ---> Delay: ${hysteriaLag}\n"
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Configure V2Ray to start automatically at boot"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxVLESSWSPort}")
|
||
echoContent green " ---> Tuic started successfully"
|
||
|
||
checkDNSIP "${domain}"
|
||
removeNginxDefaultConf
|
||
handleSingBox stop
|
||
randomPathFunction
|
||
checkPortOpen "${result[-1]}" "${domain}"
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/03_VLESS_WS_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"type": "vless",
|
||
"listen":"::",
|
||
"listen_port":${result[-1]},
|
||
"tag":"VLESSWS",
|
||
"users":$(initSingBoxClients 1),
|
||
"tls":{
|
||
"server_name": "${sslDomain}",
|
||
"enabled": true,
|
||
"certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt",
|
||
"key_path": "/etc/v2ray-agent/tls/${sslDomain}.key"
|
||
},
|
||
"transport": {
|
||
"type": "ws",
|
||
"path": "/${currentPath}ws",
|
||
"max_early_data": 2048,
|
||
"early_data_header_name": "Sec-WebSocket-Protocol"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/03_VLESS_WS_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
if echo "${selectCustomInstallType}" | grep -q ",3," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "Please enter the local bandwidth peak downstream speed (default: 100, unit: Mbps)"
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Configure Hysteria to start automatically at boot"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxVMessWSPort}")
|
||
echoContent green " ---> Tuic closed successfully"
|
||
|
||
checkDNSIP "${domain}"
|
||
removeNginxDefaultConf
|
||
handleSingBox stop
|
||
randomPathFunction
|
||
checkPortOpen "${result[-1]}" "${domain}"
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/05_VMess_WS_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"type": "vmess",
|
||
"listen":"::",
|
||
"listen_port":${result[-1]},
|
||
"tag":"VMessWS",
|
||
"users":$(initSingBoxClients 3),
|
||
"tls":{
|
||
"server_name": "${sslDomain}",
|
||
"enabled": true,
|
||
"certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt",
|
||
"key_path": "/etc/v2ray-agent/tls/${sslDomain}.key"
|
||
},
|
||
"transport": {
|
||
"type": "ws",
|
||
"path": "/${currentPath}",
|
||
"max_early_data": 2048,
|
||
"early_data_header_name": "Sec-WebSocket-Protocol"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/05_VMess_WS_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
# VLESS_Reality_Vision
|
||
if echo "${selectCustomInstallType}" | grep -q ",7," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "\n --->Download speed: ${hysteriaClientDownloadSpeed}\n"
|
||
initRealityClientServersName
|
||
initRealityKey
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Configure Tuic to start automatically at boot"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxVLESSRealityVisionPort}")
|
||
echoContent green " ---> Xray started successfully"
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/07_VLESS_vision_reality_inbounds.json
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"type": "vless",
|
||
"listen":"::",
|
||
"listen_port":${result[-1]},
|
||
"tag": "VLESSReality",
|
||
"users":$(initSingBoxClients 7),
|
||
"tls": {
|
||
"enabled": true,
|
||
"server_name": "${realityServerName}",
|
||
"reality": {
|
||
"enabled": true,
|
||
"handshake":{
|
||
"server": "${realityServerName}",
|
||
"server_port":${realityDomainPort}
|
||
},
|
||
"private_key": "${realityPrivateKey}",
|
||
"short_id": [
|
||
"",
|
||
"6ba85179e30d4fc2"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/07_VLESS_vision_reality_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
if echo "${selectCustomInstallType}" | grep -q ",8," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "Please enter the local bandwidth peak uplink speed (default: 50, unit: Mbps)"
|
||
initRealityClientServersName
|
||
initRealityKey
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Configure Xray to start automatically at boot"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxVLESSRealityGRPCPort}")
|
||
echoContent green " ---> Xray closed successfully"
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/08_VLESS_vision_gRPC_inbounds.json
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"type": "vless",
|
||
"listen":"::",
|
||
"listen_port":${result[-1]},
|
||
"users":$(initSingBoxClients 8),
|
||
"tag": "VLESSRealityGRPC",
|
||
"tls": {
|
||
"enabled": true,
|
||
"server_name": "${realityServerName}",
|
||
"reality": {
|
||
"enabled": true,
|
||
"handshake":{
|
||
"server":"${realityServerName}",
|
||
"server_port":${realityDomainPort}
|
||
},
|
||
"private_key": "${realityPrivateKey}",
|
||
"short_id": [
|
||
"",
|
||
"6ba85179e30d4fc2"
|
||
]
|
||
}
|
||
},
|
||
"transport": {
|
||
"type": "grpc",
|
||
"service_name": "grpc"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/08_VLESS_vision_gRPC_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
if echo "${selectCustomInstallType}" | grep -q ",6," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "\n ---> Upload speed: ${hysteriaClientUploadSpeed}\n"
|
||
echoContent skyBlue "\nPlease select the protocol type"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxHysteria2Port}")
|
||
echoContent green "\nPort range: ${hysteriaPortHoppingRange}\n"
|
||
initHysteria2Network
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"type": "hysteria2",
|
||
"listen": "::",
|
||
"listen_port": ${result[-1]},
|
||
"users": $(initSingBoxClients 6),
|
||
"up_mbps":${hysteria2ClientDownloadSpeed},
|
||
"down_mbps":${hysteria2ClientUploadSpeed},
|
||
"tls": {
|
||
"enabled": true,
|
||
"server_name":"${sslDomain}",
|
||
"alpn": [
|
||
"h3"
|
||
],
|
||
"certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt",
|
||
"key_path": "/etc/v2ray-agent/tls/${sslDomain}.key"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
if echo "${selectCustomInstallType}" | grep -q ",4," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "# Notes\n"
|
||
echoContent skyBlue "\nProgress 1/1: Port jump"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxTrojanPort}")
|
||
echoContent green " ---> Port hopping added successfully"
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/04_trojan_TCP_inbounds.json
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"type": "trojan",
|
||
"listen": "::",
|
||
"listen_port": ${result[-1]},
|
||
"users": $(initSingBoxClients 4),
|
||
"tls": {
|
||
"enabled": true,
|
||
"server_name":"${sslDomain}",
|
||
"certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt",
|
||
"key_path": "/etc/v2ray-agent/tls/${sslDomain}.key"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/04_trojan_TCP_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
if echo "${selectCustomInstallType}" | grep -q ",9," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "Only supports UDP"
|
||
echoContent skyBlue "\nProgress 1/1: Port jump"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxTuicPort}")
|
||
echoContent green " ---> Deletion successful"
|
||
initTuicProtocol
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"type": "tuic",
|
||
"listen": "::",
|
||
"tag": "singbox-tuic-in",
|
||
"listen_port": ${result[-1]},
|
||
"users": $(initSingBoxClients 9),
|
||
"congestion_control": "${tuicAlgorithm}",
|
||
"tls": {
|
||
"enabled": true,
|
||
"server_name":"${sslDomain}",
|
||
"alpn": [
|
||
"h3"
|
||
],
|
||
"certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt",
|
||
"key_path": "/etc/v2ray-agent/tls/${sslDomain}.key"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
if echo "${selectCustomInstallType}" | grep -q ",10," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "The starting position of port jumping is 30000"
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Initializing Hysteria configuration"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxNaivePort}")
|
||
echoContent green " ---> The current port hopping range is: ${portHoppingStart}-${portHoppingEnd}"
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/10_naive_inbounds.json
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"type": "naive",
|
||
"listen": "::",
|
||
"tag": "singbox-naive-in",
|
||
"listen_port": ${result[-1]},
|
||
"users": $(initSingBoxClients 10),
|
||
"tls": {
|
||
"enabled": true,
|
||
"server_name":"${sslDomain}",
|
||
"certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt",
|
||
"key_path": "/etc/v2ray-agent/tls/${sslDomain}.key"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/10_naive_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
if echo "${selectCustomInstallType}" | grep -q ",11," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "The end position of port jumping is 60000"
|
||
echoContent skyBlue "\nPlease select the algorithm type"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxVMessHTTPUpgradePort}")
|
||
echoContent green "\n ---> Port: ${tuicPort}"
|
||
|
||
checkDNSIP "${domain}"
|
||
removeNginxDefaultConf
|
||
handleSingBox stop
|
||
randomPathFunction
|
||
rm -rf "${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf" >/dev/null 2>&1
|
||
checkPortOpen "${result[-1]}" "${domain}"
|
||
singBoxNginxConfig "$1" "${result[-1]}"
|
||
bootStartup nginx
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/11_VMess_HTTPUpgrade_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"type": "vmess",
|
||
"listen":"127.0.0.1",
|
||
"listen_port":31306,
|
||
"tag":"VMessHTTPUpgrade",
|
||
"users":$(initSingBoxClients 11),
|
||
"transport": {
|
||
"type": "httpupgrade",
|
||
"path": "/${currentPath}"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/11_VMess_HTTPUpgrade_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
if echo "${selectCustomInstallType}" | grep -q ",13," || [[ "$1" == "all" ]]; then
|
||
echoContent yellow "You can choose a segment in the range of 30000-60000"
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Initializing Tuic configuration"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxAnyTLSPort}")
|
||
echoContent green "\n ---> Used successfully"
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/13_anytls_inbounds.json
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"type": "anytls",
|
||
"listen": "::",
|
||
"tag":"anytls",
|
||
"listen_port": ${result[-1]},
|
||
"users": $(initSingBoxClients 13),
|
||
"tls": {
|
||
"enabled": true,
|
||
"server_name":"${sslDomain}",
|
||
"certificate_path": "/etc/v2ray-agent/tls/${sslDomain}.crt",
|
||
"key_path": "/etc/v2ray-agent/tls/${sslDomain}.key"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
elif [[ -z "$3" ]]; then
|
||
rm /etc/v2ray-agent/sing-box/conf/config/13_anytls_inbounds.json >/dev/null 2>&1
|
||
fi
|
||
|
||
if [[ -z "$3" ]]; then
|
||
removeSingBoxConfig wireguard_endpoints_IPv4_route
|
||
removeSingBoxConfig wireguard_endpoints_IPv6_route
|
||
removeSingBoxConfig wireguard_endpoints_IPv4
|
||
removeSingBoxConfig wireguard_endpoints_IPv6
|
||
|
||
removeSingBoxConfig IPv4_out
|
||
removeSingBoxConfig IPv6_out
|
||
removeSingBoxConfig IPv6_route
|
||
removeSingBoxConfig block
|
||
removeSingBoxConfig cn_block_outbound
|
||
removeSingBoxConfig cn_block_route
|
||
removeSingBoxConfig 01_direct_outbound
|
||
removeSingBoxConfig socks5_outbound.json
|
||
removeSingBoxConfig block_domain_outbound
|
||
removeSingBoxConfig dns
|
||
fi
|
||
|
||
setSniffRouting
|
||
}
|
||
initSubscribeLocalConfig() {
|
||
rm -rf /etc/v2ray-agent/subscribe_local/sing-box/*
|
||
}
|
||
# General
|
||
defaultBase64Code() {
|
||
local type=$1
|
||
local port=$2
|
||
local email=$3
|
||
local id=$4
|
||
local add=$5
|
||
local path=$6
|
||
local user=
|
||
user=$(echo "${email}" | awk -F "[-]" '{print $1}')
|
||
if [[ ! -f "/etc/v2ray-agent/subscribe_local/sing-box/${user}" ]]; then
|
||
echo [] >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
fi
|
||
local singBoxSubscribeLocalConfig=
|
||
if [[ "${type}" == "vlesstcp" ]]; then
|
||
|
||
echoContent yellow "Recommend about 1000"
|
||
echoContent green " vless://${id}@${currentHost}:${port}?encryption=none&security=tls&fp=chrome&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}\n"
|
||
|
||
echoContent yellow "Please enter the port jumping range, for example [30000-31000]"
|
||
echoContent green " vless://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=tls&fp=chrome&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx- vision#${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
vless://${id}@${currentHost}:${port}?encryption=none&security=tls&type=tcp&host=${currentHost}&fp=chrome&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}
|
||
EOF
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
type: vless
|
||
server: ${currentHost}
|
||
port: ${port}
|
||
uuid: ${id}
|
||
network: tcp
|
||
tls: true
|
||
udp: true
|
||
flow: xtls-rprx-vision
|
||
client-fingerprint: chrome
|
||
EOF
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vless\",\"server\":\"${currentHost}\",\"server_port\":${port},\"uuid\":\"${id}\",\"flow\":\"xtls-rprx-vision\",\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}},\"packet_encoding\":\"xudp\"}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent yellow "1.Add port hopping"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${currentHost}%3A${port}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26type%3Dtcp%26${currentHost}%3D${currentHost}%26headerType%3Dnone%26sni%3D${currentHost}%26flow%3Dxtls-rprx-vision%23${email}\n"
|
||
|
||
elif [[ "${type}" == "vmessws" ]]; then
|
||
qrCodeBase64Default=$(echo -n "{\"port\":${port},\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${currentHost}\",\"type\":\"none\",\"path\":\"${path}\",\"net\":\"ws\",\"add\":\"${add}\",\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}" | base64 -w 0)
|
||
qrCodeBase64Default="${qrCodeBase64Default// /}"
|
||
|
||
echoContent yellow "2.Delete port hopping"
|
||
echoContent green " {\"port\":${port},\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${currentHost}\",\"type\":\"none\",\"path\":\"${path}\",\"net\":\"ws\",\"add\":\"${add}\",\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}\n"
|
||
echoContent yellow "3.Check port jumping"
|
||
echoContent green " vmess://${qrCodeBase64Default}\n"
|
||
echoContent yellow "\n ---> Port: ${tuicPort}"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
vmess://${qrCodeBase64Default}
|
||
EOF
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
type: vmess
|
||
server: ${add}
|
||
port: ${port}
|
||
uuid: ${id}
|
||
alterId: 0
|
||
cipher: none
|
||
udp: true
|
||
tls: true
|
||
client-fingerprint: chrome
|
||
servername: ${currentHost}
|
||
network: ws
|
||
ws-opts:
|
||
path: ${path}
|
||
headers:
|
||
Host: ${currentHost}
|
||
EOF
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vmess\",\"server\":\"${add}\",\"server_port\":${port},\"uuid\":\"${id}\",\"alter_id\":0,\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}},\"packet_encoding\":\"packetaddr\",\"transport\":{\"type\":\"ws\",\"path\":\"${path}\",\"max_early_data\":2048,\"early_data_header_name\":\"Sec-WebSocket-Protocol\"}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\n"
|
||
|
||
elif [[ "${type}" == "vlessws" ]]; then
|
||
|
||
echoContent yellow "Please enter the Tuic port [enter random 10000-30000], cannot be repeated with other services"
|
||
echoContent green " vless://${id}@${add}:${port}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=${path}#${email}\n"
|
||
|
||
echoContent yellow "1.bbr(default)"
|
||
echoContent green "Protocol type: VLESS, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, client-fingerprint: chrome, transmission method: tcp, flow: xtls-rprx -vision, account name:${email}\n"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
vless://${id}@${add}:${port}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=${path}#${email}
|
||
EOF
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
type: vless
|
||
server: ${add}
|
||
port: ${port}
|
||
uuid: ${id}
|
||
udp: true
|
||
tls: true
|
||
network: ws
|
||
client-fingerprint: chrome
|
||
servername: ${currentHost}
|
||
ws-opts:
|
||
path: ${path}
|
||
headers:
|
||
Host: ${currentHost}
|
||
EOF
|
||
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vless\",\"server\":\"${add}\",\"server_port\":${port},\"uuid\":\"${id}\",\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}},\"multiplex\":{\"enabled\":false,\"protocol\":\"smux\",\"max_streams\":32},\"packet_encoding\":\"xudp\",\"transport\":{\"type\":\"ws\",\"path\":\"${path}\",\"headers\":{\"Host\":\"${currentHost}\"}}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent yellow "2.cubic"
|
||
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%3Dtls%26type%3Dws%26host%3D${currentHost}%26fp%3Dchrome%26sni%3D${currentHost}%26path%3D${path}%23${email}"
|
||
|
||
elif [[ "${type}" == "vlessXHTTP" ]]; then
|
||
|
||
local xhttpMldsa65Param=
|
||
local xhttpMldsa65ParamEncoded=
|
||
if [[ -n "${currentRealityMldsa65Verify}" && "${currentRealityMldsa65Verify}" != "null" ]]; then
|
||
xhttpMldsa65Param="&pqv=${currentRealityMldsa65Verify}"
|
||
xhttpMldsa65ParamEncoded="%26pqv%3D${currentRealityMldsa65Verify}"
|
||
fi
|
||
|
||
echoContent yellow "3.new_reno"
|
||
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 "\n ---> Algorithm: ${tuicAlgorithm}\n"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${currentHost}%3A${currentDefaultPort}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26type%3Dtcp%26${currentHost}%3D${currentHost}%26headerType%3Dnone%26sni%3D${currentHost}%26flow%3Dxtls-rprx-vision%23${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
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}"
|
||
- name: "${email}"
|
||
type: vless
|
||
server: ${add}
|
||
port: ${port}
|
||
uuid: ${id}
|
||
udp: true
|
||
tls: true
|
||
network: xhttp
|
||
client-fingerprint: chrome
|
||
alpn:
|
||
- h2
|
||
servername: ${xrayVLESSRealityXHTTPServerName}
|
||
xhttp-opts:
|
||
path: ${path}
|
||
host: ${xrayVLESSRealityXHTTPServerName}
|
||
reality-opts:
|
||
public-key: ${currentRealityXHTTPPublicKey}
|
||
short-id: 6ba85179e30d4fc2
|
||
EOF
|
||
|
||
echoContent yellow "# Notes\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" ]]
|
||
then
|
||
|
||
echoContent yellow "will replace the prefix with ${xtlsType}"
|
||
echoContent green " vless://${id}@${add}:${port}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&fp=chrome&serviceName=${currentPath}grpc&alpn=h2&sni=${currentHost}#${email}\n"
|
||
|
||
echoContent yellow "If the prefix is Trojan, two Trojan protocol nodes will appear when viewing the account, and one of them is unavailable xtls"
|
||
echoContent green " vless://${id}@${currentHost}:${currentDefaultPort}?security=tls&encryption=none&host=${currentHost}&fp=chrome&headerType=none&type=tcp#${email}\n"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
vless://${id}@${add}:${port}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&serviceName=${currentPath}grpc&fp=chrome&alpn=h2&sni=${currentHost}#${email}
|
||
EOF
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
type: vless
|
||
server: ${add}
|
||
port: ${port}
|
||
uuid: ${id}
|
||
udp: true
|
||
tls: true
|
||
network: grpc
|
||
client-fingerprint: chrome
|
||
servername: ${currentHost}
|
||
grpc-opts:
|
||
grpc-service-name: ${currentPath}grpc
|
||
EOF
|
||
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\": \"vless\",\"server\": \"${add}\",\"server_port\": ${port},\"uuid\": \"${id}\",\"tls\": { \"enabled\": true, \"server_name\": \"${currentHost}\", \"utls\": { \"enabled\": true, \"fingerprint\": \"chrome\" }},\"packet_encoding\": \"xudp\",\"transport\": { \"type\": \"grpc\", \"service_name\": \"${currentPath}grpc\"}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent yellow "Execute again to switch to the last prefix\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%3Dtls%26type%3Dgrpc%26host%3D${currentHost}%26serviceName%3D${currentPath}grpc%26fp%3Dchrome%26path%3D${currentPath}grpc%26sni%3D${currentHost}%26alpn%3Dh2%23${email}"
|
||
|
||
elif [[ "${type}" == "trojan" ]]; then
|
||
# URLEncode
|
||
# URLEncode
|
||
echoContent yellow " ---> Trojan(TLS)"
|
||
echoContent green " trojan://${id}@${currentHost}:${port}?peer=${currentHost}&fp=chrome&sni=${currentHost}&alpn=http/1.1#${currentHost}_Trojan\n"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
trojan://${id}@${currentHost}:${port}?peer=${currentHost}&fp=chrome&sni=${currentHost}&alpn=http/1.1#${email}_Trojan
|
||
EOF
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
type: trojan
|
||
server: ${currentHost}
|
||
port: ${port}
|
||
password: ${id}
|
||
client-fingerprint: chrome
|
||
udp: true
|
||
sni: ${currentHost}
|
||
EOF
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"trojan\",\"server\":\"${currentHost}\",\"server_port\":${port},\"password\":\"${id}\",\"tls\":{\"alpn\":[\"http/1.1\"],\"enabled\":true,\"server_name\":\"${currentHost}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent yellow "1.Switch to ${xtlsType}"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${currentHost}%3a${port}%3fpeer%3d${currentHost}%26fp%3Dchrome%26sni%3d${currentHost}%26alpn%3Dhttp/1.1%23${email}\n"
|
||
|
||
elif [[ "${type}" == "trojangrpc" ]]; then
|
||
# URLEncode
|
||
|
||
# URLEncode
|
||
|
||
echoContent yellow " ---> Trojan gRPC(TLS)"
|
||
echoContent green " trojan://${id}@${add}:${port}?encryption=none&peer=${currentHost}&fp=chrome&security=tls&type=grpc&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
trojan://${id}@${add}:${port}?encryption=none&peer=${currentHost}&security=tls&type=grpc&fp=chrome&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}
|
||
EOF
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
server: ${add}
|
||
port: ${port}
|
||
type: trojan
|
||
password: ${id}
|
||
network: grpc
|
||
sni: ${currentHost}
|
||
udp: true
|
||
grpc-opts:
|
||
grpc-service-name: ${currentPath}trojangrpc
|
||
EOF
|
||
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"trojan\",\"server\":\"${add}\",\"server_port\":${port},\"password\":\"${id}\",\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"insecure\":true,\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}},\"transport\":{\"type\":\"grpc\",\"service_name\":\"${currentPath}trojangrpc\",\"idle_timeout\":\"15s\",\"ping_timeout\":\"15s\",\"permit_without_stream\":false},\"multiplex\":{\"enabled\":false,\"protocol\":\"smux\",\"max_streams\":32}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent yellow "Please enter custom UUID [need to be legal], [Enter] random UUID"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${add}%3a${port}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26peer%3d${currentHost}%26type%3Dgrpc%26sni%3d${currentHost}%26path%3D${currentPath}trojangrpc%26alpn%3Dh2%26serviceName%3D${currentPath}trojangrpc%23${email}\n"
|
||
|
||
elif [[ "${type}" == "hysteria" ]]; then
|
||
echoContent yellow " ---> Hysteria(TLS)"
|
||
local clashMetaPortContent="port: ${port}"
|
||
local multiPort=
|
||
local multiPortEncode
|
||
if echo "${port}" | grep -q "-"; then
|
||
clashMetaPortContent="ports: ${port}"
|
||
multiPort="mport=${port}&"
|
||
multiPortEncode="mport%3D${port}%26"
|
||
fi
|
||
|
||
echoContent green " hysteria2://${id}@${currentHost}:${singBoxHysteria2Port}?${multiPort}peer=${currentHost}&insecure=0&sni=${currentHost}&alpn=h3#${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
hysteria2://${id}@${currentHost}:${singBoxHysteria2Port}?${multiPort}peer=${currentHost}&insecure=0&sni=${currentHost}&alpn=h3#${email}
|
||
EOF
|
||
echoContent yellow " ---> v2rayN(hysteria+TLS)"
|
||
echo "{\"server\": \"${currentHost}:${port}\",\"socks5\": { \"listen\": \"127.0.0.1:7798\", \"timeout\": 300},\"auth\":\"${id}\",\"tls\":{\"sni\":\"${currentHost}\"}}" | jq
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
type: hysteria2
|
||
server: ${currentHost}
|
||
${clashMetaPortContent}
|
||
password: ${id}
|
||
alpn:
|
||
- h3
|
||
sni: ${currentHost}
|
||
up: "${hysteria2ClientUploadSpeed} Mbps"
|
||
down: "${hysteria2ClientDownloadSpeed} Mbps"
|
||
EOF
|
||
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"hysteria2\",\"server\":\"${currentHost}\",\"server_port\":${singBoxHysteria2Port},\"up_mbps\":${hysteria2ClientUploadSpeed},\"down_mbps\":${hysteria2ClientDownloadSpeed},\"password\":\"${id}\",\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"alpn\":[\"h3\"]}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent yellow "\n ${uuid}"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=hysteria2%3A%2F%2F${id}%40${currentHost}%3A${singBoxHysteria2Port}%3F${multiPortEncode}peer%3D${currentHost}%26insecure%3D0%26sni%3D${currentHost}%26alpn%3Dh3%23${email}\n"
|
||
|
||
elif [[ "${type}" == "vlessReality" ]]; then
|
||
local realityServerName=${xrayVLESSRealityServerName}
|
||
local publicKey=${currentRealityPublicKey}
|
||
local realityMldsa65Verify=${currentRealityMldsa65Verify}
|
||
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
realityServerName=${singBoxVLESSRealityVisionServerName}
|
||
publicKey=${singBoxVLESSRealityPublicKey}
|
||
fi
|
||
echoContent yellow "# Notes"
|
||
echoContent green " vless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&pqv=${realityMldsa65Verify}&type=tcp&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email}\n"
|
||
|
||
echoContent yellow "\nTutorial address:"
|
||
echoContent green "Protocol type: VLESS, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, client-fingerprint: chrome, transmission method: tcp, account name: ${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
vless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&pqv=${realityMldsa65Verify}&type=tcp&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email}
|
||
EOF
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
type: vless
|
||
server: $(getPublicIP)
|
||
port: ${port}
|
||
uuid: ${id}
|
||
network: tcp
|
||
tls: true
|
||
udp: true
|
||
flow: xtls-rprx-vision
|
||
servername: ${realityServerName}
|
||
reality-opts:
|
||
public-key: ${publicKey}
|
||
short-id: 6ba85179e30d4fc2
|
||
client-fingerprint: chrome
|
||
EOF
|
||
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vless\",\"server\":\"$(getPublicIP)\",\"server_port\":${port},\"uuid\":\"${id}\",\"flow\":\"xtls-rprx-vision\",\"tls\":{\"enabled\":true,\"server_name\":\"${realityServerName}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"},\"reality\":{\"enabled\":true,\"public_key\":\"${publicKey}\",\"short_id\":\"6ba85179e30d4fc2\"}},\"packet_encoding\":\"xudp\"}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent yellow "\n1.CNAME www.digitalocean.com"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${port}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dtcp%26sni%3D${realityServerName}%26fp%3Dchrome%26pbk%3D${publicKey}%26sid%3D6ba85179e30d4fc2%26flow%3Dxtls-rprx-vision%23${email}\n"
|
||
|
||
elif [[ "${type}" == "vlessRealityGRPC" ]]; then
|
||
local realityServerName=${xrayVLESSRealityServerName}
|
||
local publicKey=${currentRealityPublicKey}
|
||
local realityMldsa65Verify=${currentRealityMldsa65Verify}
|
||
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
realityServerName=${singBoxVLESSRealityGRPCServerName}
|
||
publicKey=${singBoxVLESSRealityPublicKey}
|
||
fi
|
||
|
||
echoContent yellow "2.CNAME who.int"
|
||
# pqv=${realityMldsa65Verify}&
|
||
echoContent green " vless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&type=grpc&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email}\n"
|
||
|
||
echoContent yellow "3.CNAME blog.hostmonit.com"
|
||
# pqv=${realityMldsa65Verify},
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3a%2f%2f${id}%40${currentHost}%3a${currentDefaultPort}%3fsecurity%3dtls%26encryption%3dnone%26fp%3Dchrome%26host%3d${currentHost}%26headerType%3dnone%26type%3dtcp%23${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
vless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&pqv=${realityMldsa65Verify}&type=grpc&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email}
|
||
EOF
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
type: vless
|
||
server: $(getPublicIP)
|
||
port: ${port}
|
||
uuid: ${id}
|
||
network: grpc
|
||
tls: true
|
||
udp: true
|
||
servername: ${realityServerName}
|
||
reality-opts:
|
||
public-key: ${publicKey}
|
||
short-id: 6ba85179e30d4fc2
|
||
grpc-opts:
|
||
grpc-service-name: "grpc"
|
||
client-fingerprint: chrome
|
||
EOF
|
||
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vless\",\"server\":\"$(getPublicIP)\",\"server_port\":${port},\"uuid\":\"${id}\",\"tls\":{\"enabled\":true,\"server_name\":\"${realityServerName}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"},\"reality\":{\"enabled\":true,\"public_key\":\"${publicKey}\",\"short_id\":\"6ba85179e30d4fc2\"}},\"packet_encoding\":\"xudp\",\"transport\":{\"type\":\"grpc\",\"service_name\":\"grpc\"}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent yellow "\n ---> Not used"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${port}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dgrpc%26sni%3D${realityServerName}%26fp%3Dchrome%26pbk%3D${publicKey}%26sid%3D6ba85179e30d4fc2%26path%3Dgrpc%26serviceName%3Dgrpc%23${email}\n"
|
||
elif [[ "${type}" == "tuic" ]]; then
|
||
local tuicUUID=
|
||
tuicUUID=$(echo "${id}" | awk -F "[_]" '{print $1}')
|
||
|
||
local tuicPassword=
|
||
tuicPassword=$(echo "${id}" | awk -F "[_]" '{print $2}')
|
||
|
||
if [[ -z "${email}" ]]; then
|
||
echoContent red "\n================================================ ================="
|
||
exit 0
|
||
fi
|
||
|
||
echoContent yellow " ---> Universal format (VLESS+TCP+TLS_Vision)"
|
||
echoContent green " trojan://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}\n"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
tuic://${tuicUUID}:${tuicPassword}@${currentHost}:${port}?congestion_control=${tuicAlgorithm}&alpn=h3&sni=${currentHost}&udp_relay_mode=quic&allow_insecure=0#${email}
|
||
EOF
|
||
echoContent yellow " ---> v2rayN(Tuic+TLS)"
|
||
echo "{\"relay\": {\"server\": \"${currentHost}:${port}\",\"uuid\": \"${tuicUUID}\",\"password\": \"${tuicPassword}\",\"ip\": \"${currentHost}\",\"congestion_control\": \"${tuicAlgorithm}\",\"alpn\": [\"h3\"]},\"local\": {\"server\": \"127.0.0.1:7798\"},\"log_level\": \"warn\"}" | jq
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
server: ${currentHost}
|
||
type: tuic
|
||
port: ${port}
|
||
uuid: ${tuicUUID}
|
||
password: ${tuicPassword}
|
||
alpn:
|
||
- h3
|
||
congestion-controller: ${tuicAlgorithm}
|
||
disable-sni: true
|
||
reduce-rtt: true
|
||
sni: ${email}
|
||
EOF
|
||
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\": \"tuic\",\"server\": \"${currentHost}\",\"server_port\": ${port},\"uuid\": \"${tuicUUID}\",\"password\": \"${tuicPassword}\",\"congestion_control\": \"${tuicAlgorithm}\",\"tls\": {\"enabled\": true,\"server_name\": \"${currentHost}\",\"alpn\": [\"h3\"]}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent yellow " ---> Formatted plain text (VLESS+TCP+TLS_Vision)"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=tuic%3A%2F%2F${tuicUUID}%3A${tuicPassword}%40${currentHost}%3A${tuicPort}%3Fcongestion_control%3D${tuicAlgorithm}%26alpn%3Dh3%26sni%3D${currentHost}%26udp_relay_mode%3Dquic%26allow_insecure%3D0%23${email}\n"
|
||
elif [[ "${type}" == "naive" ]]; then
|
||
echoContent yellow " ---> Naive(TLS)"
|
||
|
||
echoContent green " naive+https://${email}:${id}@${currentHost}:${port}?padding=true#${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
naive+https://${email}:${id}@${currentHost}:${port}?padding=true#${email}
|
||
EOF
|
||
echoContent yellow " ---> QR code VLESS(VLESS+TCP+TLS_Vision)"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=naive%2Bhttps%3A%2F%2F${email}%3A${id}%40${currentHost}%3A${port}%3Fpadding%3Dtrue%23${email}\n"
|
||
elif [[ "${type}" == "vmessHTTPUpgrade" ]]; then
|
||
qrCodeBase64Default=$(echo -n "{\"port\":${port},\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${currentHost}\",\"type\":\"none\",\"path\":\"${path}\",\"net\":\"httpupgrade\",\"add\":\"${add}\",\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}" | base64 -w 0)
|
||
qrCodeBase64Default="${qrCodeBase64Default// /}"
|
||
|
||
echoContent yellow " ---> Universal format (VLESS+TCP+TLS)"
|
||
echoContent green " {\"port\":${port},\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${currentHost}\",\"type\":\"none\",\"path\":\"${path}\",\"net\":\"httpupgrade\",\"add\":\"${add}\",\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}\n"
|
||
echoContent yellow " ---> Formatted plain text (VLESS+TCP+TLS)"
|
||
echoContent green " vmess://${qrCodeBase64Default}\n"
|
||
echoContent yellow " ---> QR code VLESS(VLESS+TCP+TLS)"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
vmess://${qrCodeBase64Default}
|
||
EOF
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
type: vmess
|
||
server: ${add}
|
||
port: ${port}
|
||
uuid: ${id}
|
||
alterId: 0
|
||
cipher: auto
|
||
udp: true
|
||
tls: true
|
||
client-fingerprint: chrome
|
||
servername: ${currentHost}
|
||
network: ws
|
||
ws-opts:
|
||
path: ${path}
|
||
headers:
|
||
Host: ${currentHost}
|
||
v2ray-http-upgrade: true
|
||
EOF
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"vmess\",\"server\":\"${add}\",\"server_port\":${port},\"uuid\":\"${id}\",\"security\":\"auto\",\"alter_id\":0,\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\",\"utls\":{\"enabled\":true,\"fingerprint\":\"chrome\"}},\"packet_encoding\":\"packetaddr\",\"transport\":{\"type\":\"httpupgrade\",\"path\":\"${path}\"}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\n"
|
||
|
||
elif [[ "${type}" == "anytls" ]]; then
|
||
echoContent yellow " ---> AnyTLS"
|
||
|
||
echoContent yellow " ---> Common format (Trojan+TCP+TLS_Vision)"
|
||
echoContent green "Protocol type: Trojan, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: xtls, transmission method: tcp, flow: xtls-rprx-vision, account name: ${email}\n"
|
||
|
||
echoContent green " anytls://${id}@${currentHost}:${singBoxAnyTLSPort}?peer=${currentHost}&insecure=0&sni=${currentHost}#${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
|
||
anytls://${id}@${currentHost}:${singBoxAnyTLSPort}?peer=${currentHost}&insecure=0&sni=${currentHost}#${email}
|
||
EOF
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
|
||
- name: "${email}"
|
||
type: anytls
|
||
port: ${singBoxAnyTLSPort}
|
||
server: ${currentHost}
|
||
password: ${id}
|
||
client-fingerprint: chrome
|
||
udp: true
|
||
sni: ${currentHost}
|
||
alpn:
|
||
- h2
|
||
- http/1.1
|
||
EOF
|
||
|
||
singBoxSubscribeLocalConfig=$(jq -r ". += [{\"tag\":\"${email}\",\"type\":\"anytls\",\"server\":\"${currentHost}\",\"server_port\":${singBoxAnyTLSPort},\"password\":\"${id}\",\"tls\":{\"enabled\":true,\"server_name\":\"${currentHost}\"}}]" "/etc/v2ray-agent/subscribe_local/sing-box/${user}")
|
||
echo "${singBoxSubscribeLocalConfig}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${user}"
|
||
|
||
echoContent yellow " ---> Formatted plain text (Trojan+TCP+TLS_Vision)"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=anytls%3A%2F%2F${id}%40${currentHost}%3A${singBoxAnyTLSPort}%3Fpeer%3D${currentHost}%26insecure%3D0%26sni%3D${currentHost}%23${email}\n"
|
||
fi
|
||
|
||
}
|
||
|
||
# account
|
||
showAccounts() {
|
||
readInstallType
|
||
readInstallProtocolType
|
||
readConfigHostPathUUID
|
||
readSingBoxConfig
|
||
|
||
echo
|
||
echoContent skyBlue "\nProgress$2/${totalProgress}: Initializing V2Ray configuration"
|
||
|
||
initSubscribeLocalConfig
|
||
# VLESS TCP
|
||
if echo ${currentInstallProtocolType} | grep -q ",0,"; then
|
||
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: Switch to ${xtlsType}"
|
||
jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}02_VLESS_TCP_inbounds.json | jq -c '.[]' | while read -r user; do
|
||
local email=
|
||
email=$(echo "${user}" | jq -r .email//.name)
|
||
|
||
echoContent skyBlue "\nProgress$2/${totalProgress}: Initializing Xray configuration"
|
||
echo
|
||
defaultBase64Code vlesstcp "${currentDefaultPort}${singBoxVLESSVisionPort}" "${email}" "$(echo "${user}" | jq -r .id//.uuid)"
|
||
done
|
||
fi
|
||
|
||
# VLESS WS
|
||
if echo ${currentInstallProtocolType} | grep -q ",1,"; then
|
||
echoContent skyBlue "\n===================== Configure VLESS+Reality ==================== =\n"
|
||
|
||
jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}03_VLESS_WS_inbounds.json | jq -c '.[]' | while read -r user; do
|
||
local email=
|
||
email=$(echo "${user}" | jq -r .email//.name)
|
||
|
||
local vlessWSPort=${currentDefaultPort}
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
vlessWSPort="${singBoxVLESSWSPort}"
|
||
fi
|
||
echo
|
||
local path="${currentPath}ws"
|
||
|
||
if [[ ${coreInstallType} == "1" ]]; then
|
||
path="/${currentPath}ws"
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
path="${singBoxVLESSWSPath}"
|
||
fi
|
||
|
||
local count=
|
||
while read -r line; do
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Add cloudflare custom CNAME"
|
||
if [[ -n "${line}" ]]; then
|
||
defaultBase64Code vlessws "${vlessWSPort}" "${email}${count}" "$(echo "${user}" | jq -r .id//.uuid)" "${line}" "${path}"
|
||
count=$((count + 1))
|
||
echo
|
||
fi
|
||
done < <(echo "${currentCDNAddress}" | tr ',' '\n')
|
||
done
|
||
fi
|
||
# trojan grpc
|
||
if echo ${currentInstallProtocolType} | grep -q ",2,"; then
|
||
echoContent skyBlue "https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip"
|
||
jq .inbounds[0].settings.clients ${configPath}04_trojan_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do
|
||
local email=
|
||
email=$(echo "${user}" | jq -r .email)
|
||
local count=
|
||
while read -r line; do
|
||
echoContent skyBlue "----------------------------"
|
||
echo
|
||
if [[ -n "${line}" ]]; then
|
||
defaultBase64Code trojangrpc "${currentDefaultPort}" "${email}${count}" "$(echo "${user}" | jq -r .password)" "${line}"
|
||
count=$((count + 1))
|
||
fi
|
||
done < <(echo "${currentCDNAddress}" | tr ',' '\n')
|
||
|
||
done
|
||
fi
|
||
# VMess WS
|
||
if echo ${currentInstallProtocolType} | grep -q ",3,"; then
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: account"
|
||
local path="${currentPath}vws"
|
||
if [[ ${coreInstallType} == "1" ]]; then
|
||
path="/${currentPath}vws"
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
path="${singBoxVMessWSPath}"
|
||
fi
|
||
jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}05_VMess_WS_inbounds.json | jq -c '.[]' | while read -r user; do
|
||
local email=
|
||
email=$(echo "${user}" | jq -r .email//.name)
|
||
|
||
local vmessPort=${currentDefaultPort}
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
vmessPort="${singBoxVMessWSPort}"
|
||
fi
|
||
|
||
local count=
|
||
while read -r line; do
|
||
echoContent skyBlue "===================== Trojan TCP TLS_Vision ======================\n"
|
||
echo
|
||
if [[ -n "${line}" ]]; then
|
||
defaultBase64Code vmessws "${vmessPort}" "${email}${count}" "$(echo "${user}" | jq -r .id//.uuid)" "${line}" "${path}"
|
||
count=$((count + 1))
|
||
fi
|
||
done < <(echo "${currentCDNAddress}" | tr ',' '\n')
|
||
done
|
||
fi
|
||
|
||
# trojan tcp
|
||
if echo ${currentInstallProtocolType} | grep -q ",4,"; then
|
||
echoContent skyBlue "\n --->Account:${email}"
|
||
jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}04_trojan_TCP_inbounds.json | jq -c '.[]' | while read -r user; do
|
||
local email=
|
||
email=$(echo "${user}" | jq -r .email//.name)
|
||
echoContent skyBlue "============================= VLESS TCP TLS_Vision ==============================\n"
|
||
|
||
defaultBase64Code trojan "${currentDefaultPort}${singBoxTrojanPort}" "${email}" "$(echo "${user}" | jq -r .password)"
|
||
done
|
||
fi
|
||
# VLESS grpc
|
||
if echo ${currentInstallProtocolType} | grep -q ",5,"; then
|
||
echoContent skyBlue "\n --->Account:${email}"
|
||
jq .inbounds[0].settings.clients ${configPath}06_VLESS_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do
|
||
|
||
local email=
|
||
email=$(echo "${user}" | jq -r .email)
|
||
|
||
local count=
|
||
while read -r line; do
|
||
echoContent skyBlue "\n================================ VLESS WS TLS CDN ================================\n"
|
||
echo
|
||
if [[ -n "${line}" ]]; then
|
||
defaultBase64Code vlessgrpc "${currentDefaultPort}" "${email}${count}" "$(echo "${user}" | jq -r .id)" "${line}"
|
||
count=$((count + 1))
|
||
fi
|
||
done < <(echo "${currentCDNAddress}" | tr ',' '\n')
|
||
|
||
done
|
||
fi
|
||
# hysteria2
|
||
if echo ${currentInstallProtocolType} | grep -q ",6," || [[ -n "${hysteriaPort}" ]]; then
|
||
readPortHopping "hysteria2" "${singBoxHysteria2Port}"
|
||
echoContent skyBlue "\n --->Account:${email}"
|
||
local path="${configPath}"
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
path="${singBoxConfigPath}"
|
||
fi
|
||
local hysteria2DefaultPort=
|
||
if [[ -n "${hysteria2PortHoppingStart}" && -n "${hysteria2PortHoppingEnd}" ]]; then
|
||
hysteria2DefaultPort="${hysteria2PortHopping}"
|
||
else
|
||
hysteria2DefaultPort=${singBoxHysteria2Port}
|
||
fi
|
||
|
||
jq -r -c '.inbounds[]|.users[]' "${path}06_hysteria2_inbounds.json" | while read -r user; do
|
||
echoContent skyBlue "\n ---> Account:$(echo "${user}" | jq -r .name)"
|
||
echo
|
||
defaultBase64Code hysteria "${hysteria2DefaultPort}" "$(echo "${user}" | jq -r .name)" "$(echo "${user}" | jq -r .password)"
|
||
done
|
||
|
||
fi
|
||
|
||
# VLESS reality vision
|
||
if echo ${currentInstallProtocolType} | grep -q ",7,"; then
|
||
echoContent skyBlue "\n=============================== VLESS gRPC TLS CDN ===============================\n"
|
||
jq .inbounds[1].settings.clients//.inbounds[0].users ${configPath}07_VLESS_vision_reality_inbounds.json | jq -c '.[]' | while read -r user; do
|
||
local email=
|
||
email=$(echo "${user}" | jq -r .email//.name)
|
||
|
||
echoContent skyBlue "\n --->Account:${email}"
|
||
echo
|
||
defaultBase64Code vlessReality "${xrayVLESSRealityVisionPort}${singBoxVLESSRealityVisionPort}" "${email}" "$(echo "${user}" | jq -r .id//.uuid)"
|
||
done
|
||
fi
|
||
# VLESS reality gRPC
|
||
if echo ${currentInstallProtocolType} | grep -q ",8,"; then
|
||
echoContent skyBlue "\n================================ VMess WS TLS CDN ================================\n"
|
||
jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}08_VLESS_vision_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do
|
||
local email=
|
||
email=$(echo "${user}" | jq -r .email//.name)
|
||
|
||
echoContent skyBlue "\n --->Account:${email}"
|
||
echo
|
||
defaultBase64Code vlessRealityGRPC "${xrayVLESSRealityVisionPort}${singBoxVLESSRealityGRPCPort}" "${email}" "$(echo "${user}" | jq -r .id//.uuid)"
|
||
done
|
||
fi
|
||
# tuic
|
||
if echo ${currentInstallProtocolType} | grep -q ",9," || [[ -n "${tuicPort}" ]]; then
|
||
echoContent skyBlue "\n================================== Trojan TLS ==================================\n"
|
||
local path="${configPath}"
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
path="${singBoxConfigPath}"
|
||
fi
|
||
jq -r -c '.inbounds[].users[]' "${path}09_tuic_inbounds.json" | while read -r user; do
|
||
echoContent skyBlue "\n ---> Account:$(echo "${user}" | jq -r .name)"
|
||
echo
|
||
defaultBase64Code tuic "${singBoxTuicPort}" "$(echo "${user}" | jq -r .name)" "$(echo "${user}" | jq -r .uuid)_$(echo "${user}" | jq -r .password)"
|
||
done
|
||
|
||
fi
|
||
# naive
|
||
if echo ${currentInstallProtocolType} | grep -q ",10," || [[ -n "${singBoxNaivePort}" ]]; then
|
||
echoContent skyBlue "\n --->Account:${email}"
|
||
|
||
jq -r -c '.inbounds[]|.users[]' "${configPath}10_naive_inbounds.json" | while read -r user; do
|
||
echoContent skyBlue "\n ---> Account:$(echo "${user}" | jq -r .username)"
|
||
echo
|
||
defaultBase64Code naive "${singBoxNaivePort}" "$(echo "${user}" | jq -r .username)" "$(echo "${user}" | jq -r .password)"
|
||
done
|
||
|
||
fi
|
||
# VMess HTTPUpgrade
|
||
if echo ${currentInstallProtocolType} | grep -q ",11,"; then
|
||
echoContent skyBlue "\n================================ Trojan gRPC TLS ================================\n"
|
||
local path="${currentPath}vws"
|
||
if [[ ${coreInstallType} == "1" ]]; then
|
||
path="/${currentPath}vws"
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
path="${singBoxVMessHTTPUpgradePath}"
|
||
fi
|
||
jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}11_VMess_HTTPUpgrade_inbounds.json | jq -c '.[]' | while read -r user; do
|
||
local email=
|
||
email=$(echo "${user}" | jq -r .email//.name)
|
||
|
||
local vmessHTTPUpgradePort=${currentDefaultPort}
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
vmessHTTPUpgradePort="${singBoxVMessHTTPUpgradePort}"
|
||
fi
|
||
|
||
local count=
|
||
while read -r line; do
|
||
echoContent skyBlue "\n --->Account:${email}"
|
||
echo
|
||
if [[ -n "${line}" ]]; then
|
||
defaultBase64Code vmessHTTPUpgrade "${vmessHTTPUpgradePort}" "${email}${count}" "$(echo "${user}" | jq -r .id//.uuid)" "${line}" "${path}"
|
||
count=$((count + 1))
|
||
fi
|
||
done < <(echo "${currentCDNAddress}" | tr ',' '\n')
|
||
done
|
||
fi
|
||
# VLESS Reality XHTTP
|
||
if echo ${currentInstallProtocolType} | grep -q ",12,"; then
|
||
echoContent skyBlue "\n================================ Hysteria TLS ================================\n"
|
||
|
||
jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}12_VLESS_XHTTP_inbounds.json | jq -c '.[]' | while read -r user; do
|
||
local email=
|
||
email=$(echo "${user}" | jq -r .email//.name)
|
||
echo
|
||
local path="${currentPath}xHTTP"
|
||
|
||
local count=
|
||
while read -r line; do
|
||
echoContent skyBlue "============================= VLESS reality_vision ==============================\n"
|
||
if [[ -z "${line}" ]]; then
|
||
line=$(getPublicIP)
|
||
fi
|
||
if [[ -n "${line}" ]]; then
|
||
defaultBase64Code vlessXHTTP "${xrayVLESSRealityXHTTPort}" "${email}${count}" "$(echo "${user}" | jq -r .id//.uuid)" "${line}" "${path}"
|
||
count=$((count + 1))
|
||
echo
|
||
fi
|
||
done < <(echo "${currentCDNAddress}" | tr ',' '\n')
|
||
done
|
||
fi
|
||
# AnyTLS
|
||
if echo ${currentInstallProtocolType} | grep -q ",13,"; then
|
||
echoContent skyBlue "\n================================ AnyTLS ================================\n"
|
||
|
||
jq -r -c '.inbounds[]|.users[]' "${configPath}13_anytls_inbounds.json" | while read -r user; do
|
||
echoContent skyBlue "\n ---> Account:$(echo "${user}" | jq -r .name)"
|
||
echo
|
||
defaultBase64Code anytls "${singBoxAnyTLSPort}" "$(echo "${user}" | jq -r .name)" "$(echo "${user}" | jq -r .password)"
|
||
done
|
||
|
||
fi
|
||
}
|
||
# Remove nginx302 configuration
|
||
removeNginx302() {
|
||
local count=
|
||
grep -n "return 302" <"${nginxConfigPath}alone.conf" | while read -r line; do
|
||
|
||
if ! echo "${line}" | grep -q "request_uri"; then
|
||
local removeIndex=
|
||
removeIndex=$(echo "${line}" | awk -F "[:]" '{print $1}')
|
||
removeIndex=$((removeIndex + count))
|
||
sed -i "${removeIndex}d" ${nginxConfigPath}alone.conf
|
||
count=$((count - 1))
|
||
fi
|
||
done
|
||
}
|
||
|
||
# Check if 302 is successful
|
||
checkNginx302() {
|
||
local domain302Status=
|
||
domain302Status=$(curl -s "https://${currentHost}:${currentPort}")
|
||
if echo "${domain302Status}" | grep -q "302"; then
|
||
# local domain302Result=
|
||
# domain302Result=$(curl -L -s "https://${currentHost}:${currentPort}")
|
||
# if [[ -n "${domain302Result}" ]]; then
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3A%2F%2F${id}%40${currentHost}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dxtls%26type%3Dtcp%26${currentHost}%3D${currentHost}%26headerType%3Dnone%26sni%3D${currentHost}%26flow%3Dxtls-rprx-vision%23${email}\n"
|
||
exit 0
|
||
# fi
|
||
fi
|
||
echoContent red " ---> Range cannot be empty"
|
||
backupNginxConfig restoreBackup
|
||
}
|
||
|
||
# Backup and restore nginx files
|
||
backupNginxConfig() {
|
||
if [[ "$1" == "backup" ]]; then
|
||
cp ${nginxConfigPath}alone.conf /etc/v2ray-agent/alone_backup.conf
|
||
echoContent green " {\"port\":${currentDefaultPort},\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${currentHost}\",\"type\":\"none\",\"path\":\"/${currentPath}vws\",\"net\":\"ws\",\"add\":\"${add}\",\"allowInsecure\":0,\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}\n"
|
||
fi
|
||
|
||
if [[ "$1" == "restoreBackup" ]] && [[ -f "/etc/v2ray-agent/alone_backup.conf" ]]; then
|
||
cp /etc/v2ray-agent/alone_backup.conf ${nginxConfigPath}alone.conf
|
||
echoContent green " vmess://${qrCodeBase64Default}\n"
|
||
rm /etc/v2ray-agent/alone_backup.conf
|
||
fi
|
||
|
||
}
|
||
# Add 302 configuration
|
||
addNginx302() {
|
||
|
||
# local line302Result=
|
||
# line302Result=$(| tail -n 1)
|
||
local count=1
|
||
grep -n "location / {" <"${nginxConfigPath}alone.conf" | while read -r line; do
|
||
if [[ -n "${line}" ]]; then
|
||
local insertIndex=
|
||
insertIndex="$(echo "${line}" | awk -F "[:]" '{print $1}')"
|
||
insertIndex=$((insertIndex + count))
|
||
sed "${insertIndex}i return 302 '$1';" ${nginxConfigPath}alone.conf >${nginxConfigPath}tmpfile && mv ${nginxConfigPath}tmpfile ${nginxConfigPath}alone.conf
|
||
count=$((count + 1))
|
||
else
|
||
echoContent red " ---> The range is illegal"
|
||
backupNginxConfig restoreBackup
|
||
fi
|
||
|
||
done
|
||
}
|
||
|
||
# Update camouflage station
|
||
updateNginxBlog() {
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
echoContent red " ---> The range is illegal"
|
||
exit 0
|
||
fi
|
||
|
||
echoContent skyBlue "\n --->Account:${email}"
|
||
|
||
if ! echo "${currentInstallProtocolType}" | grep -q ",0," || [[ -z "${coreInstallType}" ]]; then
|
||
echoContent red " ---> Failed to add port hopping"
|
||
exit 0
|
||
fi
|
||
echoContent red "=============================================================="
|
||
echoContent yellow " ---> QR code Trojan(Trojan+TCP+TLS_Vision)"
|
||
echoContent yellow " ---> Universal json(VMess+WS+TLS)"
|
||
echoContent yellow " ---> Universal vmess (VMess+WS+TLS) link"
|
||
echoContent yellow " ---> QR code vmess(VMess+WS+TLS)"
|
||
echoContent yellow " ---> Universal format (VLESS+WS+TLS)"
|
||
echoContent yellow " ---> Formatted plain text (VLESS+WS+TLS)"
|
||
echoContent yellow "6.mikutap[https://github.com/HFIProgramming/mikutap]"
|
||
echoContent yellow " ---> QR code VLESS(VLESS+WS+TLS)"
|
||
echoContent yellow " ---> Universal format (VLESS+gRPC+TLS)"
|
||
echoContent yellow " ---> Formatted plain text (VLESS+gRPC+TLS)"
|
||
echoContent yellow " ---> QR code VLESS(VLESS+gRPC+TLS)"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" selectInstallNginxBlogType
|
||
|
||
if [[ "${selectInstallNginxBlogType}" == "10" ]]; then
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
echoContent red " ---> Unable to recognize iptables tool, unable to use port jump, exit installation"
|
||
exit 0
|
||
fi
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow " ---> Trojan(TLS)"
|
||
echoContent yellow " ---> QR code Trojan(TLS)"
|
||
echoContent yellow " ---> Trojan gRPC(TLS)"
|
||
echoContent yellow " ---> QR code Trojan gRPC(TLS)"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" redirectStatus
|
||
|
||
if [[ "${redirectStatus}" == "1" ]]; then
|
||
backupNginxConfig backup
|
||
read -r -p "Please enter the domain name to be redirected, for example https://www.baidu.com:" redirectDomain
|
||
removeNginx302
|
||
addNginx302 "${redirectDomain}"
|
||
handleNginx stop
|
||
handleNginx start
|
||
if [[ -z $(pgrep -f "nginx") ]]; then
|
||
backupNginxConfig restoreBackup
|
||
handleNginx start
|
||
exit 0
|
||
fi
|
||
checkNginx302
|
||
exit 0
|
||
fi
|
||
if [[ "${redirectStatus}" == "2" ]]; then
|
||
removeNginx302
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\n"
|
||
exit 0
|
||
fi
|
||
fi
|
||
if [[ "${selectInstallNginxBlogType}" =~ ^[1-9]$ ]]; then
|
||
rm -rf "${nginxStaticPath}*"
|
||
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
wget -q -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${selectInstallNginxBlogType}.zip"
|
||
else
|
||
wget -q "${wgetShowProgressStatus}" -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${selectInstallNginxBlogType}.zip"
|
||
fi
|
||
|
||
unzip -o "${nginxStaticPath}html${selectInstallNginxBlogType}.zip" -d "${nginxStaticPath}" >/dev/null
|
||
rm -f "${nginxStaticPath}html${selectInstallNginxBlogType}.zip*"
|
||
echoContent green " vless://${id}@${add}:${currentDefaultPort}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=/${currentPath}ws #${email}\n"
|
||
else
|
||
echoContent red "\n================================================ ================="
|
||
updateNginxBlog
|
||
fi
|
||
}
|
||
|
||
#Add new port
|
||
addCorePort() {
|
||
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
echoContent red " ---> Port cannot be empty"
|
||
exit 0
|
||
fi
|
||
|
||
echoContent skyBlue "============================== VLESS reality_gRPC ===============================\n"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow " ---> Hysteria(TLS)"
|
||
echoContent yellow " ---> v2rayN(hysteria+TLS)"
|
||
echoContent yellow " ---> QR code Hysteria(TLS)"
|
||
echoContent yellow " ---> Universal format (VLESS+reality+uTLS+Vision)"
|
||
echoContent yellow " ---> Formatted plain text (VLESS+reality+uTLS+Vision)"
|
||
echoContent yellow " ---> QR code VLESS(VLESS+reality+uTLS+Vision)"
|
||
echoContent yellow " ---> Universal format (VLESS+reality+uTLS+gRPC)"
|
||
|
||
echoContent yellow " ---> Formatted plain text (VLESS+reality+uTLS+gRPC)"
|
||
echoContent yellow " ---> QR code VLESS(VLESS+reality+uTLS+gRPC)"
|
||
echoContent yellow " ---> Formatted plain text (Tuic+TLS)"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" selectNewPortType
|
||
if [[ "${selectNewPortType}" == "1" ]]; then
|
||
find ${configPath} -name "*dokodemodoor*" | grep -v "hysteria" | awk -F "[c][o][n][f][/]" '{print $2}' | awk -F "[_]" '{print $4}' | awk -F "[.]" '{print ""NR""":"$1}'
|
||
exit 0
|
||
elif [[ "${selectNewPortType}" == "2" ]]; then
|
||
read -r -p "Please enter the port number:" newPort
|
||
read -r -p "Please enter the default port number. The subscription port and node port will be changed at the same time. [Enter] Default 443:" defaultPort
|
||
|
||
if [[ -n "${defaultPort}" ]]; then
|
||
rm -rf "$(find ${configPath}* | grep "default")"
|
||
fi
|
||
|
||
if [[ -n "${newPort}" ]]; then
|
||
|
||
while read -r port; do
|
||
rm -rf "$(find ${configPath}* | grep "${port}")"
|
||
|
||
local fileName=
|
||
local hysteriaFileName=
|
||
if [[ -n "${defaultPort}" && "${port}" == "${defaultPort}" ]]; then
|
||
fileName="${configPath}02_dokodemodoor_inbounds_${port}_default.json"
|
||
else
|
||
fileName="${configPath}02_dokodemodoor_inbounds_${port}.json"
|
||
fi
|
||
|
||
if [[ -n ${hysteriaPort} ]]; then
|
||
hysteriaFileName="${configPath}02_dokodemodoor_inbounds_hysteria_${port}.json"
|
||
fi
|
||
|
||
allowPort "${port}"
|
||
allowPort "${port}" "udp"
|
||
|
||
local settingsPort=443
|
||
if [[ -n "${customPort}" ]]; then
|
||
settingsPort=${customPort}
|
||
fi
|
||
|
||
if [[ -n ${hysteriaFileName} ]]; then
|
||
cat <<EOF >"${hysteriaFileName}"
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"listen": "0.0.0.0",
|
||
"port": ${port},
|
||
"protocol": "dokodemo-door",
|
||
"settings": {
|
||
"address": "127.0.0.1",
|
||
"port": ${hysteriaPort},
|
||
"network": "udp",
|
||
"followRedirect": false
|
||
},
|
||
"tag": "dokodemo-door-newPort-hysteria-${port}"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
cat <<EOF >"${fileName}"
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"listen": "0.0.0.0",
|
||
"port": ${port},
|
||
"protocol": "dokodemo-door",
|
||
"settings": {
|
||
"address": "127.0.0.1",
|
||
"port": ${settingsPort},
|
||
"network": "tcp",
|
||
"followRedirect": false
|
||
},
|
||
"tag": "dokodemo-door-newPort-${port}"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
done < <(echo "${newPort}" | tr ',' '\n')
|
||
|
||
echoContent green "Protocol type: VLESS, address: ${add}, disguised domain name/SNI: ${currentHost}, port: ${currentDefaultPort}, client-fingerprint: chrome, user ID: ${id}, security: tls, Transmission method: ws, path: /${currentPath}ws, account name: ${email}\n"
|
||
reloadCore
|
||
addCorePort
|
||
fi
|
||
elif [[ "${selectNewPortType}" == "3" ]]; then
|
||
find ${configPath} -name "*dokodemodoor*" | grep -v "hysteria" | awk -F "[c][o][n][f][/]" '{print $2}' | awk -F "[_]" '{print $4}' | awk -F "[.]" '{print ""NR""":"$1}'
|
||
read -r -p "Please enter the port number to be deleted:" portIndex
|
||
local dokoConfig
|
||
dokoConfig=$(find ${configPath} -name "*dokodemodoor*" | grep -v "hysteria" | awk -F "[c][o][n][f][/]" '{print $2}' | awk -F "[_]" '{print $4}' | awk -F "[.]" '{print ""NR""":"$1}' | grep "${portIndex}:")
|
||
if [[ -n "${dokoConfig}" ]]; then
|
||
rm "${configPath}02_dokodemodoor_inbounds_$(echo "${dokoConfig}" | awk -F "[:]" '{print $2}').json"
|
||
local hysteriaDokodemodoorFilePath=
|
||
|
||
hysteriaDokodemodoorFilePath="${configPath}02_dokodemodoor_inbounds_hysteria_$(echo "${dokoConfig}" | awk -F "[:]" '{print $2}').json"
|
||
if [[ -f "${hysteriaDokodemodoorFilePath}" ]]; then
|
||
rm "${hysteriaDokodemodoorFilePath}"
|
||
fi
|
||
|
||
reloadCore
|
||
addCorePort
|
||
else
|
||
echoContent yellow " ---> v2rayN(Tuic+TLS)"
|
||
addCorePort
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Uninstall script
|
||
unInstall() {
|
||
read -r -p "Are you sure you want to uninstall the installation content? [y/n]:" unInstallStatus
|
||
if [[ "${unInstallStatus}" != "y" ]]; then
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dws%26host%3D${currentHost}%26fp%3Dchrome%26sni%3D${currentHost}%26path%3D%252f${currentPath}ws%23${email}"
|
||
menu
|
||
exit 0
|
||
fi
|
||
# checkBTPanel
|
||
echoContent yellow "\n --->Tuic will be warmer and may have a smoother user experience than Hysteria."
|
||
handleNginx stop
|
||
if [[ -z $(pgrep -f "nginx") ]]; then
|
||
echoContent green " vless://${id}@${add}:${currentDefaultPort}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&fp=chrome&serviceName=${currentPath}grpc&alpn=h2&sni=${currentHost}#${email}\n"
|
||
fi
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
handleXray stop
|
||
rc-update del xray default
|
||
rm -rf /etc/init.d/xray
|
||
echoContent green "Protocol type: VLESS, address: ${add}, disguised domain name/SNI: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, transmission method: gRPC, alpn :h2, client-fingerprint: chrome, serviceName: ${currentPath}grpc, account name: ${email}\n"
|
||
fi
|
||
if [[ "${coreInstallType}" == "2" || -n "${singBoxConfigPath}" ]]; then
|
||
handleSingBox stop
|
||
rc-update del sing-box default
|
||
rm -rf /etc/init.d/sing-box
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dgrpc%26host%3D${currentHost}%26serviceName%3D${currentPath}grpc%26fp%3Dchrome%26path%3D${currentPath}grpc%26sni%3D${currentHost}%26alpn%3Dh2%23${email}"
|
||
fi
|
||
else
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
handleXray stop
|
||
rm -rf /etc/systemd/system/xray.service
|
||
echoContent green " trojan://${id}@${currentHost}:${currentDefaultPort}?peer=${currentHost}&fp=chrome&sni=${currentHost}&alpn=http/1.1#${currentHost}_Trojan\n"
|
||
fi
|
||
if [[ "${coreInstallType}" == "2" || -n "${singBoxConfigPath}" ]]; then
|
||
handleSingBox stop
|
||
rm -rf /etc/systemd/system/sing-box.service
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${currentHost}%3a${port}%3fpeer%3d${currentHost}%26fp%3Dchrome%26sni%3d${currentHost}%26alpn%3Dhttp/1.1%23${email}\n"
|
||
fi
|
||
fi
|
||
|
||
# if [[ -f "/root/.acme.sh/acme.sh.env" ]] && grep -q 'acme.sh.env' </root/.bashrc; then
|
||
# sed -i 's/. "\/root\/.acme.sh\/acme.sh.env"//g' "$(grep '. "/root/.acme.sh/acme.sh.env "' -rl /root/.bashrc)"
|
||
#fi
|
||
# rm -rf /root/.acme.sh
|
||
|
||
#rm -rf /tmp/v2ray-agent-tls/*
|
||
# if [[ -d "/etc/v2ray-agent/tls" ]] && [[ -n $(find /etc/v2ray-agent/tls/ -name "*.key") ]] && [[ -n $(find /etc/v2ray-agent/tls/ -name "*.crt") ]]; then
|
||
# mv /etc/v2ray-agent/tls /tmp/v2ray-agent-tls
|
||
# if [[ -n $(find /tmp/v2ray-agent-tls -name '*.key') ]]; then
|
||
# echoContent yellow " ---> Backup certificate successful, please save it. [/tmp/v2ray-agent-tls]"
|
||
#fi
|
||
#fi
|
||
|
||
rm -rf /etc/v2ray-agent
|
||
rm -rf ${nginxConfigPath}alone.conf
|
||
rm -rf ${nginxConfigPath}checkPortOpen.conf >/dev/null 2>&1
|
||
rm -rf "${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf" >/dev/null 2>&1
|
||
rm -rf ${nginxConfigPath}checkPortOpen.conf >/dev/null 2>&1
|
||
|
||
unInstallSubscribe
|
||
|
||
if [[ -d "${nginxStaticPath}" && -f "${nginxStaticPath}/check" ]]; then
|
||
rm -rf "${nginxStaticPath}"
|
||
echoContent green " trojan://${id}@${add}:${currentDefaultPort}?encryption=none&peer=${currentHost}&fp=chrome&security=tls&type=grpc&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}\n"
|
||
fi
|
||
|
||
rm -rf /usr/bin/vasma
|
||
rm -rf /usr/sbin/vasma
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${add}%3a${currentDefaultPort}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26peer%3d${currentHost}%26type%3Dgrpc%26sni%3d${currentHost}%26path%3D${currentPath}trojangrpc%26alpn%3Dh2%26serviceName%3D${currentPath}trojangrpc%23${email}\n"
|
||
echoContent green " hysteria://${currentHost}:${hysteriaPort}?${mport}protocol=${hysteriaProtocol}&auth=${id}&peer=${currentHost}&insecure=0&alpn=h3&upmbps=${hysteriaClientUploadSpeed}&downmbps=${hysteriaClientDownloadSpeed}#${hysteriaEmail}\n"
|
||
}
|
||
|
||
manageCDN() {
|
||
echoContent skyBlue "\n --->Account:${email}"
|
||
local setCDNDomain=
|
||
|
||
if echo "${currentInstallProtocolType}" | grep -qE ",1,|,2,|,3,|,5,|,11,"; then
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "# If you need to customize, please manually copy the template file to ${nginxStaticPath} \n"
|
||
echoContent yellow "1.Newbie guide"
|
||
echoContent skyBlue "https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip"
|
||
echoContent red " ---> The port is illegal"
|
||
|
||
echoContent yellow "1.CNAME www.digitalocean.com"
|
||
echoContent yellow "2.CNAME who.int"
|
||
echoContent yellow "3.CNAME blog.hostmonit.com"
|
||
echoContent yellow "4.CNAME www.visa.com.hk"
|
||
echoContent yellow "2.Game website"
|
||
echoContent yellow "3.Personal blog 01"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" selectCDNType
|
||
case ${selectCDNType} in
|
||
1)
|
||
setCDNDomain="www.digitalocean.com"
|
||
;;
|
||
2)
|
||
setCDNDomain="who.int"
|
||
;;
|
||
3)
|
||
setCDNDomain="blog.hostmonit.com"
|
||
;;
|
||
4)
|
||
setCDNDomain="www.visa.com.hk"
|
||
;;
|
||
5)
|
||
read -r -p "Enter the custom CDN IP or domain:" setCDNDomain
|
||
;;
|
||
6)
|
||
echo >/etc/v2ray-agent/cdn
|
||
echoContent green "${v2rayNConf}\n"
|
||
exit 0
|
||
;;
|
||
esac
|
||
|
||
if [[ -n "${setCDNDomain}" ]]; then
|
||
echo >/etc/v2ray-agent/cdn
|
||
echo "${setCDNDomain}" >"/etc/v2ray-agent/cdn"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=hysteria%3A%2F%2F${currentHost}%3A${hysteriaPort}%3F${mport}protocol%3D${hysteriaProtocol}%26auth%3D${id}%26peer%3D${currentHost}%26insecure%3D0%26alpn%3Dh3%26upmbps%3D${hysteriaClientUploadSpeed}%26downmbps%3D${hysteriaClientDownloadSpeed}%23${hysteriaEmail}\n"
|
||
subscribe false false
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
manageCDN 1
|
||
fi
|
||
else
|
||
echoContent yellow "4.Enterprise Station"
|
||
echoContent skyBlue "https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip\n"
|
||
echoContent red "================================================== =========== ===="
|
||
fi
|
||
}
|
||
# Custom uuid
|
||
customUUID() {
|
||
read -r -p "Please enter a valid UUID:" currentCustomUUID
|
||
echo
|
||
if [[ -z "${currentCustomUUID}" ]]; then
|
||
if [[ "${selectInstallType}" == "1" || "${coreInstallType}" == "1" ]]; then
|
||
currentCustomUUID=$(${ctlPath} uuid)
|
||
elif [[ "${selectInstallType}" == "2" || "${coreInstallType}" == "2" ]]; then
|
||
currentCustomUUID=$(${ctlPath} generate uuid)
|
||
fi
|
||
|
||
echoContent yellow "uuid:${currentCustomUUID}\n"
|
||
|
||
else
|
||
local checkUUID=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
checkUUID=$(jq -r --arg currentUUID "$currentCustomUUID" "(.inbounds[0].settings.clients // .inbounds[1].settings.clients)[]? | select(.id == \$currentUUID) | .email" ${configPath}${frontingType:-$frontingTypeReality}.json)
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
checkUUID=$(jq -r --arg currentUUID "$currentCustomUUID" ".inbounds[0].users[] | select(.uuid == \$currentUUID) | .name//.username" ${configPath}${frontingType}.json)
|
||
fi
|
||
|
||
if [[ -n "${checkUUID}" ]]; then
|
||
echoContent red "\n ---> Due to environmental dependencies, if you install Tuic, please install Xray-core's VLESS_TCP_TLS_Vision first"
|
||
exit 0
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Custom email
|
||
customUserEmail() {
|
||
read -r -p "Please enter a valid email, [Enter] random email:" currentCustomEmail
|
||
echo
|
||
if [[ -z "${currentCustomEmail}" ]]; then
|
||
currentCustomEmail="${currentCustomUUID}"
|
||
echoContent yellow "email: ${currentCustomEmail}\n"
|
||
else
|
||
local checkEmail=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
local frontingTypeConfig="${frontingType}"
|
||
if [[ "${currentInstallProtocolType}" == ",7,8," ]]; then
|
||
frontingTypeConfig="07_VLESS_vision_reality_inbounds"
|
||
fi
|
||
|
||
checkEmail=$(jq -r --arg currentEmail "$currentCustomEmail" "(.inbounds[0].settings.clients // .inbounds[1].settings.clients)[]? | select(.email == \$currentEmail) | .email" ${configPath}${frontingTypeConfig:-$frontingTypeReality}.json)
|
||
elif
|
||
[[ "${coreInstallType}" == "2" ]]
|
||
then
|
||
checkEmail=$(jq -r --arg currentEmail "$currentCustomEmail" ".inbounds[0].users[] | select(.name == \$currentEmail) | .name" ${configPath}${frontingType}.json)
|
||
fi
|
||
|
||
if [[ -n "${checkEmail}" ]]; then
|
||
echoContent red "\n ---> uuid reading error, regenerate"
|
||
exit 0
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Add user
|
||
addUser() {
|
||
read -r -p "Please enter the number of users to add:" userNum
|
||
echo
|
||
if [[ -z ${userNum} || ${userNum} -le 0 ]]; then
|
||
echoContent red " ---> Trojan does not currently support xtls-rprx-vision"
|
||
exit 0
|
||
fi
|
||
local userConfig=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
userConfig=".inbounds[0].settings.clients"
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
userConfig=".inbounds[0].users"
|
||
fi
|
||
|
||
while [[ ${userNum} -gt 0 ]]; do
|
||
readConfigHostPathUUID
|
||
local users=
|
||
((userNum--)) || true
|
||
|
||
customUUID
|
||
customUserEmail
|
||
|
||
uuid=${currentCustomUUID}
|
||
email=${currentCustomEmail}
|
||
|
||
# VLESS TCP
|
||
if echo "${currentInstallProtocolType}" | grep -q ",0,"; then
|
||
local clients=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 0 "${uuid}" "${email}")
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
clients=$(initSingBoxClients 0 "${uuid}" "${email}")
|
||
fi
|
||
clients=$(jq -r "${userConfig} = ${clients}" ${configPath}02_VLESS_TCP_inbounds.json)
|
||
echo "${clients}" | jq . >${configPath}02_VLESS_TCP_inbounds.json
|
||
fi
|
||
|
||
# VLESS WS
|
||
if echo "${currentInstallProtocolType}" | grep -q ",1,"; then
|
||
local clients=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 1 "${uuid}" "${email}")
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
clients=$(initSingBoxClients 1 "${uuid}" "${email}")
|
||
fi
|
||
|
||
clients=$(jq -r "${userConfig} = ${clients}" ${configPath}03_VLESS_WS_inbounds.json)
|
||
echo "${clients}" | jq . >${configPath}03_VLESS_WS_inbounds.json
|
||
fi
|
||
|
||
# trojan grpc
|
||
if echo "${currentInstallProtocolType}" | grep -q ",2,"; then
|
||
local clients=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 2 "${uuid}" "${email}")
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
clients=$(initSingBoxClients 2 "${uuid}" "${email}")
|
||
fi
|
||
|
||
clients=$(jq -r "${userConfig} = ${clients}" ${configPath}04_trojan_gRPC_inbounds.json)
|
||
echo "${clients}" | jq . >${configPath}04_trojan_gRPC_inbounds.json
|
||
fi
|
||
# VMess WS
|
||
if echo "${currentInstallProtocolType}" | grep -q ",3,"; then
|
||
local clients=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 3 "${uuid}" "${email}")
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
clients=$(initSingBoxClients 3 "${uuid}" "${email}")
|
||
fi
|
||
|
||
clients=$(jq -r "${userConfig} = ${clients}" ${configPath}05_VMess_WS_inbounds.json)
|
||
echo "${clients}" | jq . >${configPath}05_VMess_WS_inbounds.json
|
||
fi
|
||
# trojan tcp
|
||
if echo "${currentInstallProtocolType}" | grep -q ",4,"; then
|
||
local clients=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 4 "${uuid}" "${email}")
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
clients=$(initSingBoxClients 4 "${uuid}" "${email}")
|
||
fi
|
||
clients=$(jq -r "${userConfig} = ${clients}" ${configPath}04_trojan_TCP_inbounds.json)
|
||
echo "${clients}" | jq . >${configPath}04_trojan_TCP_inbounds.json
|
||
fi
|
||
|
||
# vless grpc
|
||
if echo "${currentInstallProtocolType}" | grep -q ",5,"; then
|
||
local clients=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 5 "${uuid}" "${email}")
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
clients=$(initSingBoxClients 5 "${uuid}" "${email}")
|
||
fi
|
||
clients=$(jq -r "${userConfig} = ${clients}" ${configPath}06_VLESS_gRPC_inbounds.json)
|
||
echo "${clients}" | jq . >${configPath}06_VLESS_gRPC_inbounds.json
|
||
fi
|
||
|
||
# vless reality vision
|
||
if echo "${currentInstallProtocolType}" | grep -q ",7,"; then
|
||
local clients=
|
||
local realityUserConfig=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 7 "${uuid}" "${email}")
|
||
realityUserConfig=".inbounds[1].settings.clients"
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
clients=$(initSingBoxClients 7 "${uuid}" "${email}")
|
||
realityUserConfig=".inbounds[0].users"
|
||
fi
|
||
clients=$(jq -r "${realityUserConfig} = ${clients}" ${configPath}07_VLESS_vision_reality_inbounds.json)
|
||
echo "${clients}" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json
|
||
fi
|
||
|
||
# vless reality grpc
|
||
if echo "${currentInstallProtocolType}" | grep -q ",8,"; then
|
||
local clients=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 8 "${uuid}" "${email}")
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
clients=$(initSingBoxClients 8 "${uuid}" "${email}")
|
||
fi
|
||
clients=$(jq -r "${userConfig} = ${clients}" ${configPath}08_VLESS_vision_gRPC_inbounds.json)
|
||
echo "${clients}" | jq . >${configPath}08_VLESS_vision_gRPC_inbounds.json
|
||
fi
|
||
|
||
# hysteria2
|
||
if echo ${currentInstallProtocolType} | grep -q ",6,"; then
|
||
local clients=
|
||
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 6 "${uuid}" "${email}")
|
||
elif [[ -n "${singBoxConfigPath}" ]]; then
|
||
clients=$(initSingBoxClients 6 "${uuid}" "${email}")
|
||
fi
|
||
|
||
clients=$(jq -r ".inbounds[0].users = ${clients}" "${singBoxConfigPath}06_hysteria2_inbounds.json")
|
||
echo "${clients}" | jq . >"${singBoxConfigPath}06_hysteria2_inbounds.json"
|
||
fi
|
||
|
||
# tuic
|
||
if echo ${currentInstallProtocolType} | grep -q ",9,"; then
|
||
local clients=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 9 "${uuid}" "${email}")
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
clients=$(initSingBoxClients 9 "${uuid}" "${email}")
|
||
fi
|
||
|
||
clients=$(jq -r ".inbounds[0].users = ${clients}" "${singBoxConfigPath}09_tuic_inbounds.json")
|
||
|
||
echo "${clients}" | jq . >"${singBoxConfigPath}09_tuic_inbounds.json"
|
||
fi
|
||
# naive
|
||
if echo ${currentInstallProtocolType} | grep -q ",10,"; then
|
||
local clients=
|
||
clients=$(initSingBoxClients 10 "${uuid}" "${email}")
|
||
clients=$(jq -r ".inbounds[0].users = ${clients}" "${singBoxConfigPath}10_naive_inbounds.json")
|
||
|
||
echo "${clients}" | jq . >"${singBoxConfigPath}10_naive_inbounds.json"
|
||
fi
|
||
# VMess WS
|
||
if echo "${currentInstallProtocolType}" | grep -q ",11,"; then
|
||
local clients=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
clients=$(initXrayClients 11 "${uuid}" "${email}")
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
clients=$(initSingBoxClients 11 "${uuid}" "${email}")
|
||
fi
|
||
|
||
clients=$(jq -r "${userConfig} = ${clients}" ${configPath}11_VMess_HTTPUpgrade_inbounds.json)
|
||
echo "${clients}" | jq . >${configPath}11_VMess_HTTPUpgrade_inbounds.json
|
||
fi
|
||
# anytls
|
||
if echo "${currentInstallProtocolType}" | grep -q ",13,"; then
|
||
local clients=
|
||
clients=$(initSingBoxClients 13 "${uuid}" "${email}")
|
||
|
||
clients=$(jq -r "${userConfig} = ${clients}" ${configPath}13_anytls_inbounds.json)
|
||
echo "${clients}" | jq . >${configPath}13_anytls_inbounds.json
|
||
fi
|
||
done
|
||
reloadCore
|
||
echoContent green " vless://${id}@$(getPublicIP):${currentRealityPort}?encryption=none&security=reality&type=tcp&sni=${currentRealityServerNames}&fp=chrome&pbk=${currentRealityPublicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email}\n"
|
||
readNginxSubscribe
|
||
if [[ -n "${subscribePort}" ]]; then
|
||
subscribe false
|
||
fi
|
||
manageAccount 1
|
||
}
|
||
# Remove user
|
||
removeUser() {
|
||
|
||
local uuid=
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
jq -r -c '(.inbounds[0].settings.clients // .inbounds[1].settings.clients)[]?|.email' ${configPath}${frontingType:-$frontingTypeReality}.json | awk '{print NR""":"$0}'
|
||
read -r -p "Please select the user number to delete [only supports single deletion]:" delUserIndex
|
||
if [[ $(jq -r '(.inbounds[0].settings.clients // .inbounds[1].settings.clients)?|length' ${configPath}${frontingType:-$frontingTypeReality}.json) -lt ${delUserIndex} ]]; then
|
||
echoContent red " ---> Not installed, please use script to install"
|
||
else
|
||
delUserIndex=$((delUserIndex - 1))
|
||
fi
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
jq -r -c .inbounds[0].users[].name//.inbounds[0].users[].username ${configPath}${frontingType:-$frontingTypeReality}.json | awk '{print NR""":"$0}'
|
||
read -r -p "Please select the user number to delete [only supports single deletion]:" delUserIndex
|
||
if [[ $(jq -r '.inbounds[0].users|length' ${configPath}${frontingType:-$frontingTypeReality}.json) -lt ${delUserIndex} ]]; then
|
||
echoContent red " ---> Available types are not installed"
|
||
else
|
||
delUserIndex=$((delUserIndex - 1))
|
||
fi
|
||
fi
|
||
|
||
if [[ -n "${delUserIndex}" ]]; then
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",0,"; then
|
||
local vlessVision
|
||
vlessVision=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}02_VLESS_TCP_inbounds.json)
|
||
echo "${vlessVision}" | jq . >${configPath}02_VLESS_TCP_inbounds.json
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",1,"; then
|
||
local vlessWSResult
|
||
vlessWSResult=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}03_VLESS_WS_inbounds.json)
|
||
echo "${vlessWSResult}" | jq . >${configPath}03_VLESS_WS_inbounds.json
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",2,"; then
|
||
local trojangRPCUsers
|
||
trojangRPCUsers=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"')' ${configPath}04_trojan_gRPC_inbounds.json)
|
||
echo "${trojangRPCUsers}" | jq . >${configPath}04_trojan_gRPC_inbounds.json
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",3,"; then
|
||
local vmessWSResult
|
||
vmessWSResult=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}05_VMess_WS_inbounds.json)
|
||
echo "${vmessWSResult}" | jq . >${configPath}05_VMess_WS_inbounds.json
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",5,"; then
|
||
local vlessGRPCResult
|
||
vlessGRPCResult=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}06_VLESS_gRPC_inbounds.json)
|
||
echo "${vlessGRPCResult}" | jq . >${configPath}06_VLESS_gRPC_inbounds.json
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",4,"; then
|
||
local trojanTCPResult
|
||
trojanTCPResult=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}04_trojan_TCP_inbounds.json)
|
||
echo "${trojanTCPResult}" | jq . >${configPath}04_trojan_TCP_inbounds.json
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",6,"; then
|
||
local hysteriaResult
|
||
hysteriaResult=$(jq -r 'del(.inbounds[0].users['"${delUserIndex}"'])' "${singBoxConfigPath}06_hysteria2_inbounds.json")
|
||
echo "${hysteriaResult}" | jq . >"${singBoxConfigPath}06_hysteria2_inbounds.json"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",7,"; then
|
||
local vlessRealityResult
|
||
vlessRealityResult=$(jq -r 'del(.inbounds[1].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}07_VLESS_vision_reality_inbounds.json)
|
||
echo "${vlessRealityResult}" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",8,"; then
|
||
local vlessRealityGRPCResult
|
||
vlessRealityGRPCResult=$(jq -r 'del(.inbounds[0].settings.clients['"${delUserIndex}"']//.inbounds[0].users['"${delUserIndex}"'])' ${configPath}08_VLESS_vision_gRPC_inbounds.json)
|
||
echo "${vlessRealityGRPCResult}" | jq . >${configPath}08_VLESS_vision_gRPC_inbounds.json
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q ",9,"; then
|
||
local tuicResult
|
||
tuicResult=$(jq -r 'del(.inbounds[0].users['"${delUserIndex}"'])' "${singBoxConfigPath}09_tuic_inbounds.json")
|
||
echo "${tuicResult}" | jq . >"${singBoxConfigPath}09_tuic_inbounds.json"
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q ",10,"; then
|
||
local naiveResult
|
||
naiveResult=$(jq -r 'del(.inbounds[0].users['"${delUserIndex}"'])' "${singBoxConfigPath}10_naive_inbounds.json")
|
||
echo "${naiveResult}" | jq . >"${singBoxConfigPath}10_naive_inbounds.json"
|
||
fi
|
||
# VMess HTTPUpgrade
|
||
if echo ${currentInstallProtocolType} | grep -q ",11,"; then
|
||
local vmessHTTPUpgradeResult
|
||
vmessHTTPUpgradeResult=$(jq -r 'del(.inbounds[0].users['"${delUserIndex}"'])' "${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json")
|
||
echo "${vmessHTTPUpgradeResult}" | jq . >"${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json"
|
||
echo "${vmessHTTPUpgradeResult}" | jq . >${configPath}11_VMess_HTTPUpgrade_inbounds.json
|
||
fi
|
||
# AnyTLS
|
||
if echo ${currentInstallProtocolType} | grep -q ",13,"; then
|
||
local anyTLSResult
|
||
anyTLSResult=$(jq -r 'del(.inbounds[0].users['"${delUserIndex}"'])' "${singBoxConfigPath}13_anytls_inbounds.json")
|
||
echo "${anyTLSResult}" | jq . >"${singBoxConfigPath}13_anytls_inbounds.json"
|
||
fi
|
||
reloadCore
|
||
readNginxSubscribe
|
||
if [[ -n "${subscribePort}" ]]; then
|
||
subscribe false
|
||
fi
|
||
fi
|
||
manageAccount 1
|
||
}
|
||
# update script
|
||
updateV2RayAgent() {
|
||
echoContent skyBlue "\n================================ Tuic TLS ================================\n"
|
||
rm -rf /etc/v2ray-agent/install.sh
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
wget -c -q -P /etc/v2ray-agent/ -N --no-check-certificate "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh"
|
||
else
|
||
# if wget --help | grep -q show-progress; then
|
||
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/ -N --no-check-certificate "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh"
|
||
fi
|
||
|
||
#else
|
||
# wget -c -q -P /etc/v2ray-agent/ -N --no-check-certificate "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh"
|
||
#fi
|
||
|
||
sudo chmod 700 /etc/v2ray-agent/install.sh
|
||
local version
|
||
version=$(grep 'Current version: v' "/etc/v2ray-agent/install.sh" | awk -F "[v]" '{print $2}' | tail -n +2 | head -n 1 | awk -F "[\"]" '{print $1}')
|
||
|
||
echoContent green "Protocol type: VLESS reality, address: $(getPublicIP), publicKey: ${currentRealityPublicKey}, shortId: 6ba85179e30d4fc2, serverNames: ${currentRealityServerNames}, port: ${currentRealityPort}, user ID: ${id}, transmission Method: tcp, account name: ${email}\n"
|
||
echoContent yellow "5.Unlock encrypted music file template [https://github.com/ix64/unlock-music]"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${currentRealityPort}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dtcp%26sni%3D${currentRealityServerNames}%26fp%3Dchrome%26pbk%3D${currentRealityPublicKey}%26pbk%3D6ba85179e30d4fc2%26flow%3Dxtls-rprx-vision%23${email}\n"
|
||
echoContent yellow "6.mikutap[https://github.com/HFIProgramming/mikutap]"
|
||
echoContent skyBlue "wget -P /root -N --no-check-certificate https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh && chmod 700 /root/install.sh && /root/install.sh"
|
||
echo
|
||
exit 0
|
||
}
|
||
|
||
# firewall
|
||
handleFirewall() {
|
||
if systemctl status ufw 2>/dev/null | grep -q "active (exited)" && [[ "$1" == "stop" ]]; then
|
||
systemctl stop ufw >/dev/null 2>&1
|
||
systemctl disable ufw >/dev/null 2>&1
|
||
echoContent green " vless://${id}@$(getPublicIP):${currentRealityPort}?encryption=none&security=reality&type=grpc&sni=${currentRealityServerNames}&fp=chrome&pbk=${currentRealityPublicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email}\n"
|
||
|
||
fi
|
||
|
||
if systemctl status firewalld 2>/dev/null | grep -q "active (running)" && [[ "$1" == "stop" ]]; then
|
||
systemctl stop firewalld >/dev/null 2>&1
|
||
systemctl disable firewalld >/dev/null 2>&1
|
||
echoContent green "Protocol type: VLESS reality, serviceName: grpc, address: $(getPublicIP), publicKey: ${currentRealityPublicKey}, shortId: 6ba85179e30d4fc2, serverNames: ${currentRealityServerNames}, port: ${currentRealityPort}, user ID: ${id}, transmission method: gRPC, client-fingerprint: chrome, account name: ${email}\n"
|
||
fi
|
||
}
|
||
|
||
# Install BBR
|
||
bbrInstall() {
|
||
echoContent red "\n=============================================================="
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${currentRealityPort}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dgrpc%26sni%3D${currentRealityServerNames}%26fp%3Dchrome%26pbk%3D${currentRealityPublicKey}%26pbk%3D6ba85179e30d4fc2%26path%3Dgrpc%26serviceName%3Dgrpc%23${email}\n"
|
||
echoContent yellow "7.Enterprise Station 02"
|
||
echoContent yellow "8.Personal blog 02"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" installBBRStatus
|
||
if [[ "${installBBRStatus}" == "1" ]]; then
|
||
wget -O tcpx.sh "https://github.com/ylx2016/Linux-NetSpeed/raw/master/tcpx.sh" && chmod +x tcpx.sh && ./tcpx.sh
|
||
else
|
||
menu
|
||
fi
|
||
}
|
||
|
||
# View and check logs
|
||
checkLog() {
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
echoContent red "\n================================================ ================="
|
||
exit 0
|
||
fi
|
||
if [[ -z "${configPath}" && -z "${realityStatus}" ]]; then
|
||
echoContent red "================================================== ==============="
|
||
exit 0
|
||
fi
|
||
local realityLogShow=
|
||
local logStatus=false
|
||
if grep -q "access" ${configPath}00_log.json; then
|
||
logStatus=true
|
||
fi
|
||
|
||
echoContent skyBlue "\n --->Account:${tuicEmail}_tuic"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "9.404 automatically jumps to baidu"
|
||
|
||
if [[ "${logStatus}" == "false" ]]; then
|
||
echoContent yellow "10.302 redirect website"
|
||
else
|
||
echoContent yellow "Redirect has a higher priority. If you change the camouflage site after configuring 302, the camouflage site under the root route will not work."
|
||
fi
|
||
|
||
echoContent yellow "If you want to disguise the site to achieve the function, you need to delete the 302 redirect configuration\n"
|
||
echoContent yellow "1.Add"
|
||
echoContent yellow "2.Delete"
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "Support batch addition"
|
||
echoContent red "=============================================================="
|
||
|
||
read -r -p "Please select:" selectAccessLogType
|
||
local configPathLog=${configPath//conf\//}
|
||
|
||
case ${selectAccessLogType} in
|
||
1)
|
||
if [[ "${logStatus}" == "false" ]]; then
|
||
realityLogShow=true
|
||
cat <<EOF >${configPath}00_log.json
|
||
{
|
||
"log": {
|
||
"access":"${configPathLog}access.log",
|
||
"error": "${configPathLog}error.log",
|
||
"loglevel": "debug"
|
||
}
|
||
}
|
||
EOF
|
||
elif [[ "${logStatus}" == "true" ]]; then
|
||
realityLogShow=false
|
||
cat <<EOF >${configPath}00_log.json
|
||
{
|
||
"log": {
|
||
"error": "${configPathLog}error.log",
|
||
"loglevel": "warning"
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
if [[ ${realityStatus} == "7" ]]; then
|
||
local vlessVisionRealityInbounds
|
||
vlessVisionRealityInbounds=$(jq -r ".inbounds[0].streamSettings.realitySettings.show=${realityLogShow}" ${configPath}07_VLESS_vision_reality_inbounds.json)
|
||
echo "${vlessVisionRealityInbounds}" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json
|
||
fi
|
||
if [[ ${realityStatus} == "12" ]]; then
|
||
local vlessVisionRealityXHTTPInbounds
|
||
vlessVisionRealityXHTTPInbounds=$(jq -r ".inbounds[0].streamSettings.realitySettings.show=${realityLogShow}" ${configPath}12_VLESS_XHTTP_inbounds.json)
|
||
echo "${vlessVisionRealityXHTTPInbounds}" | jq . >${configPath}12_VLESS_XHTTP_inbounds.json
|
||
fi
|
||
reloadCore
|
||
checkLog 1
|
||
;;
|
||
2)
|
||
tail -f "${configPathLog}access.log"
|
||
;;
|
||
3)
|
||
tail -f "${configPathLog}error.log"
|
||
;;
|
||
4)
|
||
if [[ ! -f "/etc/v2ray-agent/crontab_tls.log" ]]; then
|
||
touch /etc/v2ray-agent/crontab_tls.log
|
||
fi
|
||
tail -n 100 /etc/v2ray-agent/crontab_tls.log
|
||
;;
|
||
5)
|
||
tail -n 100 /etc/v2ray-agent/tls/acme.log
|
||
;;
|
||
6)
|
||
echo >"${configPathLog}access.log"
|
||
echo >"${configPathLog}error.log"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# Script shortcut
|
||
aliasInstall() {
|
||
|
||
if [[ -f "$HOME/install.sh" ]] && [[ -d "/etc/v2ray-agent" ]] && grep <"$HOME/install.sh" -q "作者:mack-a"; then
|
||
mv "$HOME/install.sh" /etc/v2ray-agent/install.sh
|
||
local vasmaType=
|
||
if [[ -d "/usr/bin/" ]]; then
|
||
if [[ ! -f "/usr/bin/vasma" ]]; then
|
||
ln -s /etc/v2ray-agent/install.sh /usr/bin/vasma
|
||
chmod 700 /usr/bin/vasma
|
||
vasmaType=true
|
||
fi
|
||
|
||
rm -rf "$HOME/install.sh"
|
||
elif [[ -d "/usr/sbin" ]]; then
|
||
if [[ ! -f "/usr/sbin/vasma" ]]; then
|
||
ln -s /etc/v2ray-agent/install.sh /usr/sbin/vasma
|
||
chmod 700 /usr/sbin/vasma
|
||
vasmaType=true
|
||
fi
|
||
rm -rf "$HOME/install.sh"
|
||
fi
|
||
if [[ "${vasmaType}" == "true" ]]; then
|
||
echoContent green "Protocol type: Tuic, address: ${currentHost}, port: ${tuicPort}, uuid: ${id}, password: ${id}, congestion-controller:${tuicAlgorithm}, alpn: h3, account Name:${email}_tuic\n"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Check ipv6, ipv4
|
||
checkIPv6() {
|
||
currentIPv6IP=$(curl -s -6 -m 4 http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2)
|
||
|
||
if [[ -z "${currentIPv6IP}" ]]; then
|
||
echoContent red "\n ---> uuid reading error, randomly generated"
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
# ipv6 offload
|
||
ipv6Routing() {
|
||
if [[ -z "${configPath}" ]]; then
|
||
echoContent red "\n================================================ ================="
|
||
menu
|
||
exit 0
|
||
fi
|
||
|
||
checkIPv6
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Change disguise site"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "Does not affect the use of the default port"
|
||
echoContent yellow "When viewing accounts, only accounts with default ports will be displayed"
|
||
echoContent yellow "No special characters allowed, pay attention to the comma format"
|
||
echoContent yellow "If hysteria is already installed, a new hysteria port will be installed at the same time"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" ipv6Status
|
||
if [[ "${ipv6Status}" == "1" ]]; then
|
||
showIPv6Routing
|
||
exit 0
|
||
elif [[ "${ipv6Status}" == "2" ]]; then
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "Input example:2053,2083,2087\n"
|
||
echoContent yellow "1.Check the added port"
|
||
echoContent yellow "2.Add port"
|
||
|
||
read -r -p "Please enter the domain name according to the above example:" domainList
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
addXrayRouting IPv6_out outboundTag "${domainList}"
|
||
addXrayOutbound IPv6_out
|
||
fi
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
addSingBoxRouteRule "IPv6_out" "${domainList}" "IPv6_route"
|
||
addSingBoxOutbound 01_direct_outbound
|
||
addSingBoxOutbound IPv6_out
|
||
addSingBoxOutbound IPv4_out
|
||
fi
|
||
|
||
echoContent green "${v2rayNConf}"
|
||
|
||
elif [[ "${ipv6Status}" == "3" ]]; then
|
||
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "3.Delete port"
|
||
echoContent yellow "\n ---> The number entered is wrong, please choose again"
|
||
echoContent yellow " ---> The script will not delete acme related configurations. To delete, please execute manually [rm -rf /root/.acme.sh]"
|
||
read -r -p "Confirm settings? [y/n]:" IPv6OutStatus
|
||
|
||
if [[ "${IPv6OutStatus}" == "y" ]]; then
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
addXrayOutbound IPv6_out
|
||
removeXrayOutbound IPv4_out
|
||
removeXrayOutbound z_direct_outbound
|
||
removeXrayOutbound blackhole_out
|
||
removeXrayOutbound wireguard_out_IPv4
|
||
removeXrayOutbound wireguard_out_IPv6
|
||
removeXrayOutbound socks5_outbound
|
||
|
||
rm ${configPath}09_routing.json >/dev/null 2>&1
|
||
fi
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
|
||
removeSingBoxConfig IPv4_out
|
||
|
||
removeSingBoxConfig wireguard_endpoints_IPv4_route
|
||
removeSingBoxConfig wireguard_endpoints_IPv6_route
|
||
removeSingBoxConfig wireguard_endpoints_IPv4
|
||
removeSingBoxConfig wireguard_endpoints_IPv6
|
||
|
||
removeSingBoxConfig socks5_02_inbound_route
|
||
|
||
removeSingBoxConfig IPv6_route
|
||
|
||
removeSingBoxConfig 01_direct_outbound
|
||
|
||
addSingBoxOutbound IPv6_out
|
||
|
||
fi
|
||
|
||
echoContent green " ---> 302 redirection set up successfully"
|
||
else
|
||
|
||
echoContent green " ---> nginx configuration file backup successful"
|
||
exit 0
|
||
fi
|
||
|
||
elif [[ "${ipv6Status}" == "4" ]]; then
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
unInstallRouting IPv6_out outboundTag
|
||
|
||
removeXrayOutbound IPv6_out
|
||
addXrayOutbound "z_direct_outbound"
|
||
fi
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
removeSingBoxConfig IPv6_out
|
||
removeSingBoxConfig "IPv6_route"
|
||
addSingBoxOutbound "01_direct_outbound"
|
||
fi
|
||
|
||
echoContent green " ---> nginx configuration file restoration backup successful"
|
||
else
|
||
echoContent red "\nIf you don't understand Cloudflare optimization, please do not use it"
|
||
exit 0
|
||
fi
|
||
|
||
reloadCore
|
||
}
|
||
|
||
showIPv6Routing() {
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
echoContent yellow "Xray-core:"
|
||
jq -r -c '.routing.rules[]|select (.outboundTag=="IPv6_out")|.domain' ${configPath}09_routing.json | jq -r
|
||
elif [[ ! -f "${configPath}09_routing.json" && -f "${configPath}IPv6_out.json" ]]; then
|
||
echoContent yellow "Xray-core"
|
||
echoContent green " ---> Removed 302 redirect successfully"
|
||
else
|
||
echoContent yellow "1.CNAME www.digitalocean.com"
|
||
fi
|
||
|
||
fi
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
if [[ -f "${singBoxConfigPath}IPv6_route.json" ]]; then
|
||
echoContent yellow "sing-box"
|
||
jq -r -c '.route.rules[]|select (.outbound=="IPv6_out")' "${singBoxConfigPath}IPv6_route.json" | jq -r
|
||
elif [[ ! -f "${singBoxConfigPath}IPv6_route.json" && -f "${singBoxConfigPath}IPv6_out.json" ]]; then
|
||
echoContent yellow "sing-box"
|
||
echoContent green " ---> Pseudo site replaced successfully"
|
||
else
|
||
echoContent yellow "2.CNAME who.int"
|
||
fi
|
||
fi
|
||
}
|
||
# bt download management
|
||
btTools() {
|
||
if [[ "${coreInstallType}" == "2" ]]; then
|
||
echoContent red " ---> Failed to read configuration, please reinstall"
|
||
exit 0
|
||
fi
|
||
if [[ -z "${configPath}" ]]; then
|
||
echoContent red "\n --->Hysteria speed depends on the local network environment. If it is used by QoS, the experience will be very poor. IDC may also consider it an attack, please use it with caution"
|
||
menu
|
||
exit 0
|
||
fi
|
||
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: Add new port"
|
||
echoContent red "\n=============================================================="
|
||
|
||
if [[ -f ${configPath}09_routing.json ]] && grep -q bittorrent <${configPath}09_routing.json; then
|
||
echoContent yellow "3.CNAME blog.hostmonit.com"
|
||
else
|
||
echoContent yellow "4.Manual input [can enter multiple, such as:1.1.1.1,1.1.2.2, cloudflare.com separated by commas]"
|
||
fi
|
||
|
||
echoContent yellow "5.Remove CDN node"
|
||
echoContent yellow "1.Add user"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" btStatus
|
||
if [[ "${btStatus}" == "1" ]]; then
|
||
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
|
||
unInstallRouting blackhole_out outboundTag bittorrent
|
||
|
||
routing=$(jq -r '.routing.rules += [{"type":"field","outboundTag":"blackhole_out","protocol":["bittorrent"]}]' ${configPath}09_routing.json)
|
||
|
||
echo "${routing}" | jq . >${configPath}09_routing.json
|
||
|
||
else
|
||
cat <<EOF >${configPath}09_routing.json
|
||
{
|
||
"routing":{
|
||
"domainStrategy": "IPOnDemand",
|
||
"rules": [
|
||
{
|
||
"type": "field",
|
||
"outboundTag": "blackhole_out",
|
||
"protocol": [ "bittorrent" ]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
installSniffing
|
||
removeXrayOutbound blackhole_out
|
||
addXrayOutbound blackhole_out
|
||
|
||
echoContent green " ---> Added successfully"
|
||
|
||
elif [[ "${btStatus}" == "2" ]]; then
|
||
|
||
unInstallSniffing
|
||
|
||
unInstallRouting blackhole_out outboundTag bittorrent
|
||
|
||
echoContent green " ---> Give up uninstalling"
|
||
else
|
||
echoContent red " ---> not installed"
|
||
exit 0
|
||
fi
|
||
|
||
reloadCore
|
||
}
|
||
|
||
# Domain name blacklist
|
||
blacklist() {
|
||
if [[ -z "${configPath}" ]]; then
|
||
echoContent red " ---> 302 redirection setting failed, please double check whether it is the same as the example"
|
||
menu
|
||
exit 0
|
||
fi
|
||
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Modify CDN node"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "2.Delete user"
|
||
echoContent yellow "uuid:${currentCustomUUID}\n"
|
||
echoContent yellow "email: ${currentCustomEmail}\n"
|
||
echoContent yellow "After adding a new user, you need to check the subscription again"
|
||
echoContent yellow " ---> Please manually execute [vasma] to open the script"
|
||
echoContent yellow "If the update fails, please manually execute the following command\n"
|
||
echoContent red "=============================================================="
|
||
|
||
read -r -p "Please select:" blacklistStatus
|
||
if [[ "${blacklistStatus}" == "1" ]]; then
|
||
jq -r -c '.routing.rules[]|select (.outboundTag=="blackhole_out")|.domain' ${configPath}09_routing.json | jq -r
|
||
exit 0
|
||
elif [[ "${blacklistStatus}" == "2" ]]; then
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "1.Installation script [recommended original BBR+FQ]"
|
||
echoContent yellow "2.Return to the home directory"
|
||
echoContent yellow "# It is recommended to only open the access log during debugging\n"
|
||
echoContent yellow "1.Open access log"
|
||
echoContent yellow "1.Close access log"
|
||
echoContent yellow "2.Monitor access log"
|
||
read -r -p "Please enter the domain name according to the above example:" domainList
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
addXrayRouting blackhole_out outboundTag "${domainList}"
|
||
addXrayOutbound blackhole_out
|
||
fi
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
addSingBoxRouteRule "block_domain_outbound" "${domainList}" "block_domain_route"
|
||
addSingBoxOutbound "block_domain_outbound"
|
||
addSingBoxOutbound "01_direct_outbound"
|
||
fi
|
||
echoContent green " ---> Stop Nginx successfully"
|
||
|
||
elif [[ "${blacklistStatus}" == "3" ]]; then
|
||
local allowDomainList="googleplay.com,play.google.com,play.googleapis.com,play-lh.googleusercontent.com,play-games.googleusercontent.com,play-fe.googleapis.com,dl.google.com,apple.com,apple-pki,apple-tvplus,apple-update,itunes,icloud,beats,bing.com,microsoft.com,gstatic,xn--ngstr-lra8j.com,googleapis.com,googleapis.cn"
|
||
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
unInstallRouting blackhole_out outboundTag
|
||
unInstallRouting blackhole_ip_out outboundTag
|
||
|
||
addXrayRouting blackhole_out outboundTag "cn"
|
||
addXrayIPRouting blackhole_ip_out outboundTag "cn"
|
||
addXrayRouting allow_domain_direct_outbound outboundTag "${allowDomainList}" "top"
|
||
|
||
addXrayOutbound blackhole_out
|
||
addXrayOutbound blackhole_ip_out
|
||
addXrayOutbound allow_domain_direct_outbound
|
||
fi
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
|
||
addSingBoxRouteRule "cn_block_outbound" "cn" "cn_block_route"
|
||
addSingBoxGeoIPRouteRule "block_ip_outbound" "cn" "cn_block_ip_route"
|
||
addSingBoxRouteRule "01_direct_outbound" "${allowDomainList}" "00_allow_domain_route"
|
||
|
||
addSingBoxOutbound "cn_block_outbound"
|
||
addSingBoxOutbound "block_ip_outbound"
|
||
addSingBoxOutbound "01_direct_outbound"
|
||
fi
|
||
|
||
echoContent green " ---> Delete Xray and it will start automatically after booting"
|
||
|
||
elif [[ "${blacklistStatus}" == "4" ]]; then
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
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
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
removeSingBoxConfig "cn_block_route"
|
||
removeSingBoxConfig "cn_block_outbound"
|
||
removeSingBoxConfig "cn_block_ip_route"
|
||
removeSingBoxConfig "block_ip_route"
|
||
removeSingBoxConfig "block_ip_outbound"
|
||
|
||
removeSingBoxConfig "cn_01_google_play_route"
|
||
removeSingBoxConfig "00_allow_domain_route"
|
||
|
||
removeSingBoxConfig "block_domain_route"
|
||
removeSingBoxConfig "block_domain_outbound"
|
||
fi
|
||
echoContent green " ---> Delete V2Ray and it will start automatically after booting"
|
||
elif [[ "${blacklistStatus}" == "5" ]]; then
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "3.Monitor error log"
|
||
read -r -p "Please enter the blocked IP list:" ipList
|
||
if [[ -z "${ipList}" ]]; then
|
||
echoContent red " ---> 302 Add failed"
|
||
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 " ---> Delete Hysteria and it will start automatically after booting"
|
||
elif [[ "${blacklistStatus}" == "6" ]]; then
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "4.View certificate scheduled task log"
|
||
read -r -p "Please enter whitelist domains:" allowDomainList
|
||
if [[ -z "${allowDomainList}" ]]; then
|
||
echoContent red "\n ---> Due to environmental dependencies, please install Xray-core's VLESS_TCP_TLS_Vision first"
|
||
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 " ---> Delete Tuic and start automatically after booting"
|
||
else
|
||
echoContent red "================================================== =========== ===="
|
||
exit 0
|
||
fi
|
||
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 -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
|
||
}
|
||
|
||
# Escape grep/regex pattern meta characters
|
||
escapeDLCRegexPattern() {
|
||
# shellcheck disable=SC2016
|
||
# shellcheck disable=SC2001
|
||
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
|
||
}
|
||
|
||
addXrayRouting() {
|
||
|
||
local tag=$1 # warp-socks
|
||
local type=$2 # outboundTag/inboundTag
|
||
local domain=$3 # domain
|
||
local rulePosition=$4
|
||
|
||
if [[ -z "${tag}" || -z "${type}" || -z "${domain}" ]]; then
|
||
echoContent red "================================================== ==============="
|
||
exit 0
|
||
fi
|
||
|
||
local routingRule=
|
||
if [[ ! -f "${configPath}09_routing.json" ]]; then
|
||
cat <<EOF >${configPath}09_routing.json
|
||
{
|
||
"routing":{
|
||
"type": "field",
|
||
"rules": [
|
||
{
|
||
"type": "field",
|
||
"domain": [
|
||
],
|
||
"outboundTag": "${tag}"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
local routingRule=
|
||
routingRule=$(jq -r ".routing.rules[]|select(.outboundTag==\"${tag}\" and (.protocol == null))" ${configPath}09_routing.json)
|
||
|
||
if [[ -z "${routingRule}" ]]; then
|
||
routingRule="{\"type\": \"field\",\"domain\": [],\"outboundTag\": \"${tag}\"}"
|
||
fi
|
||
|
||
while read -r line; do
|
||
if echo "${routingRule}" | grep -q "${line}"; then
|
||
echoContent yellow "5.View certificate installation log"
|
||
else
|
||
local matchedRuleValue
|
||
matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray")
|
||
routingRule=$(echo "${routingRule}" | jq -r --arg rule "${matchedRuleValue}" '.domain += [$rule]')
|
||
fi
|
||
done < <(echo "${domain}" | tr ',' '\n')
|
||
|
||
unInstallRouting "${tag}" "${type}"
|
||
if ! grep -q "gstatic.com" ${configPath}09_routing.json && [[ "${tag}" == "blackhole_out" ]]; then
|
||
local routing=
|
||
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
|
||
addXrayOutbound allow_domain_direct_outbound
|
||
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
|
||
}
|
||
|
||
addXrayIPRouting() {
|
||
|
||
local tag=$1
|
||
local type=$2
|
||
local ipList=$3
|
||
|
||
if [[ -z "${tag}" || -z "${type}" || -z "${ipList}" ]]; then
|
||
echoContent red "\n================================================ ================="
|
||
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 "6.Clear the log"
|
||
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)
|
||
echo "${routing}" | jq . >${configPath}09_routing.json
|
||
}
|
||
|
||
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
|
||
}
|
||
|
||
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",
|
||
"http_client": "rule_set_http"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
}
|
||
# Uninstall Routing based on tag
|
||
unInstallRouting() {
|
||
local tag=$1
|
||
local type=$2
|
||
local protocol=$3
|
||
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
local routing=
|
||
if [[ -n "${protocol}" ]]; then
|
||
routing=$(jq -r "del(.routing.rules[] | select(.${type} == \"${tag}\" and (.protocol | index(\"${protocol}\"))))" ${configPath}09_routing.json)
|
||
echo "${routing}" | jq . >${configPath}09_routing.json
|
||
else
|
||
routing=$(jq -r "del(.routing.rules[] | select(.${type} == \"${tag}\" and (.protocol == null )))" ${configPath}09_routing.json)
|
||
echo "${routing}" | jq . >${configPath}09_routing.json
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Uninstall sniffing
|
||
unInstallSniffing() {
|
||
|
||
find ${configPath} -name "*inbounds.json*" | awk -F "[c][o][n][f][/]" '{print $2}' | while read -r inbound; do
|
||
if grep -q "destOverride" <"${configPath}${inbound}"; then
|
||
sniffing=$(jq -r 'del(.inbounds[0].sniffing)' "${configPath}${inbound}")
|
||
echo "${sniffing}" | jq . >"${configPath}${inbound}"
|
||
fi
|
||
done
|
||
|
||
}
|
||
|
||
# Install sniffing
|
||
installSniffing() {
|
||
readInstallType
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
if [[ -f "${configPath}02_VLESS_TCP_inbounds.json" ]]; then
|
||
if ! grep -q "destOverride" <"${configPath}02_VLESS_TCP_inbounds.json"; then
|
||
sniffing=$(jq -r '.inbounds[0].sniffing = {"enabled":true,"destOverride":["http","tls","quic"]}' "${configPath}02_VLESS_TCP_inbounds.json")
|
||
echo "${sniffing}" | jq . >"${configPath}02_VLESS_TCP_inbounds.json"
|
||
fi
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Read third-party warp configuration
|
||
readConfigWarpReg() {
|
||
if [[ ! -f "/etc/v2ray-agent/warp/config" ]]; then
|
||
/etc/v2ray-agent/warp/warp-reg >/etc/v2ray-agent/warp/config
|
||
fi
|
||
|
||
secretKeyWarpReg=$(grep <"/etc/v2ray-agent/warp/config" private_key | awk '{print $2}')
|
||
|
||
addressWarpReg=$(grep <"/etc/v2ray-agent/warp/config" v6 | awk '{print $2}')
|
||
|
||
publicKeyWarpReg=$(grep <"/etc/v2ray-agent/warp/config" public_key | awk '{print $2}')
|
||
|
||
reservedWarpReg=$(grep <"/etc/v2ray-agent/warp/config" reserved | awk -F "[:]" '{print $2}')
|
||
|
||
}
|
||
installWarpReg() {
|
||
if [[ ! -f "/etc/v2ray-agent/warp/warp-reg" ]]; then
|
||
echo
|
||
echoContent yellow "1.View the diverted domain name"
|
||
echoContent yellow "2.Add domain name"
|
||
echoContent yellow "3.Set IPv6 global"
|
||
|
||
read -r -p "warp-reg is not installed, do you want to install it? [y/n]:" installWarpRegStatus
|
||
|
||
if [[ "${installWarpRegStatus}" == "y" ]]; then
|
||
|
||
curl -sLo /etc/v2ray-agent/warp/warp-reg "https://github.com/badafans/warp-reg/releases/download/v1.0/${warpRegCoreCPUVendor}"
|
||
chmod 655 /etc/v2ray-agent/warp/warp-reg
|
||
|
||
else
|
||
echoContent yellow "4.Uninstall IPv6 offloading"
|
||
exit 0
|
||
fi
|
||
fi
|
||
}
|
||
|
||
showWireGuardDomain() {
|
||
local type=$1
|
||
# xray
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
echoContent yellow "Xray-core"
|
||
jq -r -c '.routing.rules[]|select (.outboundTag=="wireguard_out_'"${type}"'")|.domain' ${configPath}09_routing.json | jq -r
|
||
elif [[ ! -f "${configPath}09_routing.json" && -f "${configPath}wireguard_out_${type}.json" ]]; then
|
||
echoContent yellow "Xray-core"
|
||
echoContent green " ---> Deletion of fake website completed"
|
||
else
|
||
echoContent yellow "# Notes\n"
|
||
fi
|
||
fi
|
||
|
||
# sing-box
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
if [[ -f "${singBoxConfigPath}wireguard_endpoints_${type}_route.json" ]]; then
|
||
echoContent yellow "sing-box"
|
||
jq -r -c '.route.rules[]' "${singBoxConfigPath}wireguard_endpoints_${type}_route.json" | jq -r
|
||
elif [[ ! -f "${singBoxConfigPath}wireguard_endpoints_${type}_route.json" && -f "${singBoxConfigPath}wireguard_endpoints_${type}.json" ]]; then
|
||
echoContent yellow "sing-box"
|
||
echoContent green " ---> Uninstallation of shortcut completed"
|
||
else
|
||
echoContent yellow "# Notes"
|
||
fi
|
||
fi
|
||
|
||
}
|
||
|
||
addWireGuardRoute() {
|
||
local type=$1
|
||
local tag=$2
|
||
local domainList=$3
|
||
# xray
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
|
||
addXrayRouting "wireguard_out_${type}" "${tag}" "${domainList}"
|
||
addXrayOutbound "wireguard_out_${type}"
|
||
fi
|
||
# sing-box
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
|
||
# rule
|
||
addSingBoxRouteRule "wireguard_endpoints_${type}" "${domainList}" "wireguard_endpoints_${type}_route"
|
||
# addSingBoxOutbound "wireguard_out_${type}" "wireguard_out"
|
||
if [[ -n "${domainList}" ]]; then
|
||
addSingBoxOutbound "01_direct_outbound"
|
||
fi
|
||
|
||
# outbound
|
||
addSingBoxWireGuardEndpoints "${type}"
|
||
fi
|
||
}
|
||
|
||
unInstallWireGuard() {
|
||
local type=$1
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
|
||
if [[ "${type}" == "IPv4" ]]; then
|
||
if [[ ! -f "${configPath}wireguard_out_IPv6.json" ]]; then
|
||
rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1
|
||
fi
|
||
elif [[ "${type}" == "IPv6" ]]; then
|
||
if [[ ! -f "${configPath}wireguard_out_IPv4.json" ]]; then
|
||
rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
if [[ ! -f "${singBoxConfigPath}wireguard_endpoints_IPv6_route.json" && ! -f "${singBoxConfigPath}wireguard_endpoints_IPv4_route.json" ]]; then
|
||
rm "${singBoxConfigPath}wireguard_outbound.json" >/dev/null 2>&1
|
||
rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1
|
||
fi
|
||
fi
|
||
}
|
||
removeWireGuardRoute() {
|
||
local type=$1
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
|
||
unInstallRouting wireguard_out_"${type}" outboundTag
|
||
|
||
removeXrayOutbound "wireguard_out_${type}"
|
||
if [[ ! -f "${configPath}IPv4_out.json" ]]; then
|
||
addXrayOutbound IPv4_out
|
||
fi
|
||
fi
|
||
|
||
# sing-box
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
removeSingBoxRouteRule "wireguard_endpoints_${type}"
|
||
fi
|
||
|
||
unInstallWireGuard "${type}"
|
||
}
|
||
# warp offload-third-party IPv4
|
||
warpRoutingReg() {
|
||
local type=$2
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Multi-user management"
|
||
echoContent red "=============================================================="
|
||
|
||
echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n"
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "1.All diversion rules set will be deleted"
|
||
echoContent yellow "2.All outbound rules except IPv6 will be deleted"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" warpStatus
|
||
installWarpReg
|
||
readConfigWarpReg
|
||
local address=
|
||
if [[ ${type} == "IPv4" ]]; then
|
||
address="172.16.0.2/32"
|
||
elif [[ ${type} == "IPv6" ]]; then
|
||
address="${addressWarpReg}/128"
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
fi
|
||
|
||
if [[ "${warpStatus}" == "1" ]]; then
|
||
showWireGuardDomain "${type}"
|
||
exit 0
|
||
elif [[ "${warpStatus}" == "2" ]]; then
|
||
echoContent yellow "Current status: disabled"
|
||
echoContent yellow "Current status: not disabled"
|
||
echoContent yellow "1.Disable"
|
||
|
||
read -r -p "Please enter the domain name according to the above example:" domainList
|
||
addWireGuardRoute "${type}" outboundTag "${domainList}"
|
||
echoContent green " ---> Uninstall v2ray-agent script completed"
|
||
|
||
elif [[ "${warpStatus}" == "3" ]]; then
|
||
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "2.Open"
|
||
echoContent yellow "1.View blocked domain names"
|
||
echoContent yellow "2.Add domain name"
|
||
read -r -p "Confirm settings? [y/n]:" warpOutStatus
|
||
|
||
if [[ "${warpOutStatus}" == "y" ]]; then
|
||
readConfigWarpReg
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
addXrayOutbound "wireguard_out_${type}"
|
||
if [[ "${type}" == "IPv4" ]]; then
|
||
removeXrayOutbound "wireguard_out_IPv6"
|
||
elif [[ "${type}" == "IPv6" ]]; then
|
||
removeXrayOutbound "wireguard_out_IPv4"
|
||
fi
|
||
|
||
removeXrayOutbound IPv4_out
|
||
removeXrayOutbound IPv6_out
|
||
removeXrayOutbound z_direct_outbound
|
||
removeXrayOutbound blackhole_out
|
||
removeXrayOutbound socks5_outbound
|
||
|
||
rm ${configPath}09_routing.json >/dev/null 2>&1
|
||
fi
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
|
||
removeSingBoxConfig IPv4_out
|
||
removeSingBoxConfig IPv6_out
|
||
removeSingBoxConfig 01_direct_outbound
|
||
|
||
removeSingBoxConfig wireguard_endpoints_IPv4_route
|
||
removeSingBoxConfig wireguard_endpoints_IPv6_route
|
||
|
||
removeSingBoxConfig IPv6_route
|
||
removeSingBoxConfig socks5_02_inbound_route
|
||
|
||
addSingBoxWireGuardEndpoints "${type}"
|
||
addWireGuardRoute "${type}" outboundTag ""
|
||
if [[ "${type}" == "IPv4" ]]; then
|
||
removeSingBoxConfig wireguard_endpoints_IPv6
|
||
else
|
||
removeSingBoxConfig wireguard_endpoints_IPv4
|
||
fi
|
||
|
||
# outbound
|
||
# addSingBoxOutbound "wireguard_out_${type}" "wireguard_out"
|
||
|
||
fi
|
||
|
||
echoContent green " ---> CDN modified successfully"
|
||
else
|
||
echoContent green " ---> Adding completed"
|
||
exit 0
|
||
fi
|
||
|
||
elif [[ "${warpStatus}" == "4" ]]; then
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
unInstallRouting "wireguard_out_${type}" outboundTag
|
||
|
||
removeXrayOutbound "wireguard_out_${type}"
|
||
addXrayOutbound "z_direct_outbound"
|
||
fi
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
removeSingBoxConfig "wireguard_endpoints_${type}_route"
|
||
|
||
removeSingBoxConfig "wireguard_endpoints_${type}"
|
||
addSingBoxOutbound "01_direct_outbound"
|
||
fi
|
||
|
||
echoContent green " ---> Adding completed"
|
||
else
|
||
|
||
echoContent red " ---> Wrong selection, please select again"
|
||
exit 0
|
||
fi
|
||
reloadCore
|
||
}
|
||
|
||
# Diversion tool
|
||
routingToolsMenu() {
|
||
echoContent skyBlue "------------------------------------------------- ------"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "3.Block domestic domain names + IP"
|
||
echoContent yellow "4.Delete blacklist/whitelist"
|
||
|
||
echoContent yellow "5.Add blocked IP"
|
||
echoContent yellow "6.Add domain whitelist"
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "1.Rules support predefined domain name list [https://github.com/v2fly/domain-list-community]"
|
||
echoContent yellow "2.Rules support custom domain names"
|
||
echoContent yellow "3.Input example: speedtest, facebook, cn, example.com"
|
||
|
||
read -r -p "Please select:" selectType
|
||
|
||
case ${selectType} in
|
||
1)
|
||
warpRoutingReg 1 IPv4
|
||
;;
|
||
2)
|
||
warpRoutingReg 1 IPv6
|
||
;;
|
||
3)
|
||
ipv6Routing 1
|
||
;;
|
||
4)
|
||
socks5Routing
|
||
;;
|
||
5)
|
||
dnsRouting 1
|
||
;;
|
||
# 6)
|
||
# if [[ -n "${singBoxConfigPath}" ]]; then
|
||
# fi
|
||
# vmessWSRouting 1
|
||
# ;;
|
||
7)
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
echoContent red "\n================================================ ================="
|
||
fi
|
||
sniRouting 1
|
||
;;
|
||
esac
|
||
|
||
}
|
||
|
||
# VMess+WS+TLS offload
|
||
vmessWSRouting() {
|
||
echoContent skyBlue "------------------------------------------------- ------"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "4.If the domain name exists in the predefined domain name list, use geosite:xx. If it does not exist, the entered domain name will be used by default."
|
||
echoContent yellow "5.Add rules as incremental configuration and will not delete previously set content\n"
|
||
|
||
echoContent yellow "Input example:1.1.1.1,8.8.8.8,1.1.1.0/24,2400:3200::/32\n"
|
||
echoContent yellow "Input example:speedtest,openai,google.com\n"
|
||
read -r -p "Please select:" selectType
|
||
|
||
case ${selectType} in
|
||
1)
|
||
setVMessWSRoutingOutbounds
|
||
;;
|
||
2)
|
||
removeVMessWSRouting
|
||
;;
|
||
esac
|
||
}
|
||
socks5Routing() {
|
||
if [[ -z "${coreInstallType}" ]]; then
|
||
echoContent red "================================================== ==============="
|
||
exit 0
|
||
fi
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Update v2ray-agent script"
|
||
echoContent red "\n=============================================================="
|
||
echoContent red "================================================== ==============="
|
||
echoContent yellow " ---> ${line} already exists, skip"
|
||
|
||
echoContent yellow " ---> ${ipRuleValue} already exists, skip"
|
||
echoContent yellow " ---> Abort installation"
|
||
|
||
echoContent yellow "1.View the diverted domain name"
|
||
echoContent yellow "2.Add domain name"
|
||
echoContent yellow "3.Set WARP global"
|
||
read -r -p "Please select:" selectType
|
||
|
||
case ${selectType} in
|
||
1)
|
||
socks5OutboundRoutingMenu
|
||
;;
|
||
2)
|
||
socks5InboundRoutingMenu
|
||
;;
|
||
3)
|
||
removeSocks5Routing
|
||
;;
|
||
esac
|
||
}
|
||
socks5InboundRoutingMenu() {
|
||
readInstallType
|
||
echoContent skyBlue "wget -P /root -N --no-check-certificate https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh && chmod 700 /root/install.sh && /root/install.sh"
|
||
echoContent red "\n=============================================================="
|
||
|
||
echoContent yellow "4.Uninstall WARP distribution"
|
||
echoContent yellow "# Notes"
|
||
echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n"
|
||
echoContent yellow "# Notes\n"
|
||
read -r -p "Please select:" selectType
|
||
case ${selectType} in
|
||
1)
|
||
totalProgress=1
|
||
installSingBox 1
|
||
installSingBoxService 1
|
||
setSocks5Inbound
|
||
setSocks5InboundRouting
|
||
reloadCore
|
||
socks5InboundRoutingMenu
|
||
;;
|
||
2)
|
||
showSingBoxRoutingRules socks5_02_inbound_route
|
||
socks5InboundRoutingMenu
|
||
;;
|
||
3)
|
||
setSocks5InboundRouting addRules
|
||
reloadCore
|
||
socks5InboundRoutingMenu
|
||
;;
|
||
4)
|
||
if [[ -f "${singBoxConfigPath}20_socks5_inbounds.json" ]]; then
|
||
echoContent yellow "1.All diversion rules set will be deleted"
|
||
echoContent green "\n ---> Update completed"
|
||
echoContent green " ---> Current version: ${version}\n"
|
||
echoContent green " ---> ufw closed successfully"
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
socks5InboundRoutingMenu
|
||
fi
|
||
;;
|
||
esac
|
||
|
||
}
|
||
|
||
socks5OutboundRoutingMenu() {
|
||
echoContent skyBlue "\nFunction$1/${totalProgress}: View log"
|
||
echoContent red "\n=============================================================="
|
||
|
||
echoContent yellow "2.All outbound rules except WARP will be deleted"
|
||
echoContent yellow "# Notes"
|
||
echoContent yellow "# relies on third-party programs, please be aware of the risks"
|
||
echoContent yellow "# Project address: https://github.com/badafans/warp-reg \n"
|
||
read -r -p "Please select:" selectType
|
||
case ${selectType} in
|
||
1)
|
||
setSocks5Outbound
|
||
setSocks5OutboundRouting
|
||
reloadCore
|
||
socks5OutboundRoutingMenu
|
||
;;
|
||
2)
|
||
setSocks5Outbound
|
||
setSocks5OutboundRoutingAll
|
||
reloadCore
|
||
socks5OutboundRoutingMenu
|
||
;;
|
||
3)
|
||
showSingBoxRoutingRules socks5_01_outbound_route
|
||
showXrayRoutingRules socks5_outbound
|
||
socks5OutboundRoutingMenu
|
||
;;
|
||
4)
|
||
setSocks5OutboundRouting addRules
|
||
reloadCore
|
||
socks5OutboundRoutingMenu
|
||
;;
|
||
esac
|
||
|
||
}
|
||
|
||
setSocks5OutboundRoutingAll() {
|
||
|
||
echoContent red "=============================================================="
|
||
echoContent yellow " ---> Abort installation"
|
||
echoContent yellow "1.View the diverted domain name"
|
||
echoContent yellow "2.Add domain name"
|
||
read -r -p "Confirm this setting? [y/n]:" socksOutStatus
|
||
|
||
if [[ "${socksOutStatus}" == "y" ]]; then
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
removeXrayOutbound IPv4_out
|
||
removeXrayOutbound IPv6_out
|
||
removeXrayOutbound z_direct_outbound
|
||
removeXrayOutbound blackhole_out
|
||
removeXrayOutbound wireguard_out_IPv4
|
||
removeXrayOutbound wireguard_out_IPv6
|
||
|
||
rm ${configPath}09_routing.json >/dev/null 2>&1
|
||
fi
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
|
||
removeSingBoxConfig IPv4_out
|
||
removeSingBoxConfig IPv6_out
|
||
|
||
removeSingBoxConfig wireguard_endpoints_IPv4_route
|
||
removeSingBoxConfig wireguard_endpoints_IPv6_route
|
||
removeSingBoxConfig wireguard_endpoints_IPv4
|
||
removeSingBoxConfig wireguard_endpoints_IPv6
|
||
|
||
removeSingBoxConfig socks5_01_outbound_route
|
||
removeSingBoxConfig 01_direct_outbound
|
||
fi
|
||
|
||
echoContent green " ---> firewalld closed successfully"
|
||
fi
|
||
}
|
||
showSingBoxRoutingRules() {
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
if [[ -f "${singBoxConfigPath}$1.json" ]]; then
|
||
jq .route.rules "${singBoxConfigPath}$1.json"
|
||
elif [[ "$1" == "socks5_01_outbound_route" && -f "${singBoxConfigPath}socks5_outbound.json" ]]; then
|
||
echoContent yellow "3.Set WARP global"
|
||
echoContent yellow "4.Uninstall WARP distribution"
|
||
echoContent skyBlue "$(jq .outbounds[0] ${singBoxConfigPath}socks5_outbound.json)"
|
||
elif [[ "$1" == "socks5_02_inbound_route" && -f "${singBoxConfigPath}20_socks5_inbounds.json" ]]; then
|
||
echoContent yellow "# Notes"
|
||
echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n"
|
||
echoContent skyBlue "$(jq .outbounds[0] ${singBoxConfigPath}socks5_outbound.json)"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
showXrayRoutingRules() {
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
jq ".routing.rules[]|select(.outboundTag==\"$1\")" "${configPath}09_routing.json"
|
||
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "1.All diversion rules set will be deleted"
|
||
echoContent skyBlue "$(jq .outbounds[0].settings.servers[0] ${configPath}socks5_outbound.json)"
|
||
|
||
elif [[ "$1" == "socks5_outbound" && -f "${configPath}socks5_outbound.json" ]]; then
|
||
echoContent yellow "2.All outbound rules except WARP [third party] will be deleted"
|
||
echoContent yellow "1.WARP diversion [Third-party IPv4]"
|
||
echoContent skyBlue "$(jq .outbounds[0].settings.servers[0] ${configPath}socks5_outbound.json)"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
removeSocks5Routing() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: IPv6 offload"
|
||
echoContent red "\n=============================================================="
|
||
|
||
echoContent yellow "2.WARP diversion [Third-party IPv6]"
|
||
echoContent yellow "3.IPv6 offload"
|
||
echoContent yellow "4.Any door diversion"
|
||
read -r -p "Select:" unInstallSocks5RoutingStatus
|
||
if [[ "${unInstallSocks5RoutingStatus}" == "1" ]]; then
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
removeXrayOutbound socks5_outbound
|
||
unInstallRouting socks5_outbound outboundTag
|
||
|
||
addXrayOutbound z_direct_outbound
|
||
fi
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
removeSingBoxConfig socks5_outbound
|
||
removeSingBoxConfig socks5_01_outbound_route
|
||
addSingBoxOutbound 01_direct_outbound
|
||
fi
|
||
|
||
elif [[ "${unInstallSocks5RoutingStatus}" == "2" ]]; then
|
||
|
||
removeSingBoxConfig 20_socks5_inbounds
|
||
removeSingBoxConfig socks5_02_inbound_route
|
||
removeSingBoxConfig sniff_socks5_inbound
|
||
removeSingBoxConfig "strategy_ipv4_only_socks5_inbound"
|
||
removeSingBoxConfig "strategy_ipv6_only_socks5_inbound"
|
||
|
||
handleSingBox stop
|
||
elif [[ "${unInstallSocks5RoutingStatus}" == "3" ]]; then
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
removeXrayOutbound socks5_outbound
|
||
unInstallRouting socks5_outbound outboundTag
|
||
addXrayOutbound z_direct_outbound
|
||
fi
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
removeSingBoxConfig socks5_outbound
|
||
removeSingBoxConfig socks5_01_outbound_route
|
||
removeSingBoxConfig 20_socks5_inbounds
|
||
removeSingBoxConfig socks5_02_inbound_route
|
||
removeSingBoxConfig sniff_socks5_inbound
|
||
removeSingBoxConfig "strategy_ipv4_only_socks5_inbound"
|
||
removeSingBoxConfig "strategy_ipv6_only_socks5_inbound"
|
||
|
||
addSingBoxOutbound 01_direct_outbound
|
||
fi
|
||
|
||
handleSingBox stop
|
||
else
|
||
echoContent red " ---> Available types are not installed"
|
||
exit 0
|
||
fi
|
||
echoContent green "The mature works of [ylx2016] used for BBR and DD scripts, the address [https://github.com/ylx2016/Linux-NetSpeed], please be familiar with it"
|
||
reloadCore
|
||
}
|
||
setSocks5Inbound() {
|
||
|
||
echoContent yellow "5.DNS divert"
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: bt download management"
|
||
echo
|
||
mapfile -t result < <(initSingBoxPort "${singBoxSocks5Port}")
|
||
echoContent green "The shortcut is created successfully, you can execute [vasma] to reopen the script"
|
||
echoContent green " ---> Added successfully"
|
||
|
||
echoContent yellow "6.VMess+WS+TLS offload"
|
||
read -r -p 'UUID:' socks5RoutingUUID
|
||
if [[ -z "${socks5RoutingUUID}" ]]; then
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
socks5RoutingUUID=$(/etc/v2ray-agent/xray/xray uuid)
|
||
elif [[ -n "${singBoxConfigPath}" ]]; then
|
||
socks5RoutingUUID=$(/etc/v2ray-agent/sing-box/sing-box generate uuid)
|
||
fi
|
||
fi
|
||
echo
|
||
echoContent green " ---> IPv6 global outbound setting successful"
|
||
echoContent green " ---> Abandon settings"
|
||
|
||
echoContent yellow "7.SNI reverse proxy offload"
|
||
echoContent yellow "1.Any door floor machine unlocks streaming media"
|
||
echoContent yellow "2.DNS unlock streaming media"
|
||
echoContent yellow "2.IPv6"
|
||
|
||
read -r -p 'IP type:' socks5InboundDomainStrategyStatus
|
||
local domainStrategy=
|
||
if [[ -z "${socks5InboundDomainStrategyStatus}" || "${socks5InboundDomainStrategyStatus}" == "1" ]]; then
|
||
domainStrategy="ipv4_only"
|
||
elif [[ "${socks5InboundDomainStrategyStatus}" == "2" ]]; then
|
||
domainStrategy="ipv6_only"
|
||
else
|
||
echoContent red " ---> Wrong selection"
|
||
exit 0
|
||
fi
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/20_socks5_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"type": "socks",
|
||
"listen":"::",
|
||
"listen_port":${result[-1]},
|
||
"tag":"socks5_inbound",
|
||
"users":[
|
||
{
|
||
"username": "${socks5RoutingUUID}",
|
||
"password": "${socks5RoutingUUID}"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
setStrategyRouting socks5_inbound "${domainStrategy}"
|
||
}
|
||
|
||
initSingBoxRules() {
|
||
local domainRules=[]
|
||
local ruleSet=[]
|
||
while read -r line; do
|
||
local normalizedLine=
|
||
normalizedLine=$(echo "${line}" | tr '[:upper:]' '[:lower:]' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||
if isDomainFormat "${normalizedLine}"; then
|
||
local escapedDomain=
|
||
escapedDomain=${normalizedLine//./\\.}
|
||
domainRules=$(echo "${domainRules}" | jq -r --arg reg ".*${escapedDomain}.*" '. += [$reg]')
|
||
else
|
||
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\",\"http_client\":\"rule_set_http\"}]")
|
||
else
|
||
domainRules=$(echo "${domainRules}" | jq -r --arg reg "^([a-zA-Z0-9_-]+\\.)*${normalizedLine//./\\.}" '. += [$reg]')
|
||
fi
|
||
fi
|
||
done < <(echo "$1" | tr ',' '\n' | grep -v '^$' | sort -n | uniq | paste -sd ',' | tr ',' '\n')
|
||
echo "{ \"domainRules\":${domainRules},\"ruleSet\":${ruleSet}}"
|
||
}
|
||
|
||
setSocks5InboundRouting() {
|
||
|
||
singBoxConfigPath=/etc/v2ray-agent/sing-box/conf/config/
|
||
|
||
if [[ "$1" == "addRules" && ! -f "${singBoxConfigPath}socks5_02_inbound_route.json" && ! -f "${configPath}09_routing.json" ]]; then
|
||
echoContent red " ---> UUID cannot be repeated"
|
||
echoContent red " ---> email cannot be repeated"
|
||
exit 0
|
||
fi
|
||
local socks5InboundRoutingIPs=
|
||
if [[ "$1" == "addRules" ]]; then
|
||
socks5InboundRoutingIPs=$(jq .route.rules[0].source_ip_cidr "${singBoxConfigPath}socks5_02_inbound_route.json")
|
||
else
|
||
echoContent red "=============================================================="
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Domain name blacklist"
|
||
read -r -p "IP:" socks5InboundRoutingIPs
|
||
|
||
if [[ -z "${socks5InboundRoutingIPs}" ]]; then
|
||
echoContent red " ---> Incorrect input, please re-enter"
|
||
exit 0
|
||
fi
|
||
socks5InboundRoutingIPs=$(echo "\"${socks5InboundRoutingIPs}"\" | jq -c '.|split(",")')
|
||
fi
|
||
|
||
echoContent red "=============================================================="
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: WARP offload"
|
||
echoContent yellow "3.VMess+WS+TLS to unlock streaming media"
|
||
echoContent yellow "# Notes"
|
||
echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n"
|
||
echoContent yellow "1.Add outbound"
|
||
|
||
read -r -p "Allow all websites? Select [y/n]:" socks5InboundRoutingDomainStatus
|
||
if [[ "${socks5InboundRoutingDomainStatus}" == "y" ]]; then
|
||
addSingBoxRouteRule "01_direct_outbound" "" "socks5_02_inbound_route"
|
||
local route=
|
||
route=$(jq ".route.rules[0].inbound = [\"socks5_inbound\"]" "${singBoxConfigPath}socks5_02_inbound_route.json")
|
||
route=$(echo "${route}" | jq ".route.rules[0].source_ip_cidr=${socks5InboundRoutingIPs}")
|
||
echo "${route}" | jq . >"${singBoxConfigPath}socks5_02_inbound_route.json"
|
||
|
||
addSingBoxOutbound block
|
||
addSingBoxOutbound "01_direct_outbound"
|
||
else
|
||
echoContent yellow "2.Add inbound"
|
||
read -r -p "Domain:" socks5InboundRoutingDomain
|
||
if [[ -z "${socks5InboundRoutingDomain}" ]]; then
|
||
echoContent red " ---> Incorrect input, please re-enter"
|
||
exit 0
|
||
fi
|
||
addSingBoxRouteRule "01_direct_outbound" "${socks5InboundRoutingDomain}" "socks5_02_inbound_route"
|
||
local route=
|
||
route=$(jq ".route.rules[0].inbound = [\"socks5_inbound\"]" "${singBoxConfigPath}socks5_02_inbound_route.json")
|
||
route=$(echo "${route}" | jq ".route.rules[0].source_ip_cidr=${socks5InboundRoutingIPs}")
|
||
echo "${route}" | jq . >"${singBoxConfigPath}socks5_02_inbound_route.json"
|
||
|
||
addSingBoxOutbound block
|
||
addSingBoxOutbound "01_direct_outbound"
|
||
fi
|
||
|
||
}
|
||
|
||
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"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
}
|
||
|
||
setStrategyRouting() {
|
||
local tag=$1
|
||
local strategy=$2
|
||
cat <<EOF >"/etc/v2ray-agent/sing-box/conf/config/strategy_${strategy}_${tag}.json"
|
||
{
|
||
"route":{
|
||
"rules":[
|
||
{
|
||
"inbound": "${tag}",
|
||
"action": "resolve",
|
||
"strategy": "${strategy}"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
}
|
||
setSocks5Outbound() {
|
||
|
||
echoContent yellow "3.Uninstall"
|
||
echo
|
||
read -r -p "Enter the landing server IP address:" socks5RoutingOutboundIP
|
||
if [[ -z "${socks5RoutingOutboundIP}" ]]; then
|
||
echoContent red " ---> Wrong selection"
|
||
exit 0
|
||
fi
|
||
echo
|
||
read -r -p "Enter the landing server port:" socks5RoutingOutboundPort
|
||
if [[ -z "${socks5RoutingOutboundPort}" ]]; then
|
||
echoContent red " ---> Wrong selection"
|
||
exit 0
|
||
fi
|
||
echo
|
||
read -r -p "Enter username:" socks5RoutingOutboundUserName
|
||
if [[ -z "${socks5RoutingOutboundUserName}" ]]; then
|
||
echoContent red "\n================================================ ================="
|
||
exit 0
|
||
fi
|
||
echo
|
||
read -r -p "Enter password:" socks5RoutingOutboundPassword
|
||
if [[ -z "${socks5RoutingOutboundPassword}" ]]; then
|
||
echoContent red "================================================== ==============="
|
||
exit 0
|
||
fi
|
||
echo
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
cat <<EOF >"${singBoxConfigPath}socks5_outbound.json"
|
||
{
|
||
"outbounds":[
|
||
{
|
||
"type": "socks",
|
||
"tag":"socks5_outbound",
|
||
"server": "${socks5RoutingOutboundIP}",
|
||
"server_port": ${socks5RoutingOutboundPort},
|
||
"version": "5",
|
||
"username":"${socks5RoutingOutboundUserName}",
|
||
"password":"${socks5RoutingOutboundPassword}"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
addXrayOutbound socks5_outbound
|
||
fi
|
||
}
|
||
|
||
setSocks5OutboundRouting() {
|
||
|
||
if [[ "$1" == "addRules" && ! -f "${singBoxConfigPath}socks5_01_outbound_route.json" && ! -f "${configPath}09_routing.json" ]]; then
|
||
echoContent red " ---> The installation directory is not detected, please execute the script to install the content"
|
||
exit 0
|
||
fi
|
||
|
||
echoContent red "=============================================================="
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: WARP offload [third party]"
|
||
echoContent yellow "# Notes"
|
||
echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n"
|
||
echoContent yellow "1.Add outbound"
|
||
echoContent yellow "2.Uninstall"
|
||
echoContent yellow "Input example:netflix,openai\n"
|
||
read -r -p "Domain:" socks5RoutingOutboundDomain
|
||
if [[ -z "${socks5RoutingOutboundDomain}" ]]; then
|
||
echoContent red "\n================================================ ================="
|
||
exit 0
|
||
fi
|
||
addSingBoxRouteRule "socks5_outbound" "${socks5RoutingOutboundDomain}" "socks5_01_outbound_route"
|
||
addSingBoxOutbound "01_direct_outbound"
|
||
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
|
||
unInstallRouting "socks5_outbound" "outboundTag"
|
||
local domainRules=[]
|
||
while read -r line; do
|
||
if echo "${routingRule}" | grep -q "${line}"; then
|
||
echoContent yellow "Input example:netflix,openai\n"
|
||
else
|
||
local matchedRuleValue
|
||
matchedRuleValue=$(getDLCMatchedRuleValue "${line}" "/etc/v2ray-agent/xray")
|
||
domainRules=$(echo "${domainRules}" | jq -r --arg rule "${matchedRuleValue}" '. += [$rule]')
|
||
fi
|
||
done < <(echo "${socks5RoutingOutboundDomain}" | tr ',' '\n')
|
||
if [[ ! -f "${configPath}09_routing.json" ]]; then
|
||
cat <<EOF >${configPath}09_routing.json
|
||
{
|
||
"routing":{
|
||
"rules": []
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
routing=$(jq -r ".routing.rules += [{\"type\": \"field\",\"domain\": ${domainRules},\"outboundTag\": \"socks5_outbound\"}]" ${configPath}09_routing.json)
|
||
echo "${routing}" | jq . >${configPath}09_routing.json
|
||
fi
|
||
}
|
||
|
||
# Set VMess+WS+TLS [outbound only]
|
||
setVMessWSRoutingOutbounds() {
|
||
read -r -p "Please enter the address of VMess+WS+TLS:" setVMessWSTLSAddress
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "ip entry example:1.1.1.1,1.1.1.2"
|
||
read -r -p "Please enter the domain name according to the above example:" domainList
|
||
|
||
if [[ -z ${domainList} ]]; then
|
||
echoContent red "================================================== ==============="
|
||
setVMessWSRoutingOutbounds
|
||
fi
|
||
|
||
if [[ -n "${setVMessWSTLSAddress}" ]]; then
|
||
removeXrayOutbound VMess-out
|
||
|
||
echo
|
||
read -r -p "Please enter the port of VMess+WS+TLS:" setVMessWSTLSPort
|
||
echo
|
||
if [[ -z "${setVMessWSTLSPort}" ]]; then
|
||
echoContent red " ---> does not support ipv6"
|
||
fi
|
||
|
||
read -r -p "Please enter the UUID of VMess+WS+TLS:" setVMessWSTLSUUID
|
||
echo
|
||
if [[ -z "${setVMessWSTLSUUID}" ]]; then
|
||
echoContent red " ---> Not installed, please use script to install"
|
||
fi
|
||
|
||
read -r -p "Please enter the Path of VMess+WS+TLS:" setVMessWSTLSPath
|
||
echo
|
||
if [[ -z "${setVMessWSTLSPath}" ]]; then
|
||
echoContent red "\n================================================ ============ ====="
|
||
elif ! echo "${setVMessWSTLSPath}" | grep -q "/"; then
|
||
setVMessWSTLSPath="/${setVMessWSTLSPath}"
|
||
fi
|
||
addXrayOutbound "VMess-out"
|
||
addXrayRouting VMess-out outboundTag "${domainList}"
|
||
reloadCore
|
||
echoContent green " ---> IPv6 offload uninstall successful"
|
||
exit 0
|
||
fi
|
||
echoContent red "================================================== ==============="
|
||
setVMessWSRoutingOutbounds
|
||
}
|
||
|
||
# Remove VMess+WS+TLS shunt
|
||
removeVMessWSRouting() {
|
||
|
||
removeXrayOutbound VMess-out
|
||
unInstallRouting VMess-out outboundTag
|
||
|
||
reloadCore
|
||
echoContent green " ---> BT download disabled successfully"
|
||
}
|
||
|
||
# Restart core
|
||
reloadCore() {
|
||
readInstallType
|
||
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
handleXray stop
|
||
handleXray start
|
||
fi
|
||
if echo "${currentInstallProtocolType}" | grep -q ",20," || [[ "${coreInstallType}" == "2" || -n "${singBoxConfigPath}" ]]; then
|
||
handleSingBox stop
|
||
handleSingBox start
|
||
fi
|
||
}
|
||
|
||
# dns divert
|
||
dnsRouting() {
|
||
|
||
if [[ -z "${configPath}" ]]; then
|
||
echoContent red "================================================== ==============="
|
||
menu
|
||
exit 0
|
||
fi
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: Diversion tool"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "The domain name below must be consistent with the outbound vps"
|
||
echoContent yellow "Example of domain name entry: netflix,openai\n"
|
||
|
||
echoContent yellow "# Notes"
|
||
echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n"
|
||
read -r -p "Please select:" selectType
|
||
|
||
case ${selectType} in
|
||
1)
|
||
setUnlockDNS
|
||
;;
|
||
2)
|
||
removeUnlockDNS
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# SNI reverse proxy offload
|
||
sniRouting() {
|
||
|
||
if [[ -z "${configPath}" ]]; then
|
||
echoContent red "================================================== ==============="
|
||
menu
|
||
exit 0
|
||
fi
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: Streaming Media Toolbox"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "1.Add"
|
||
echoContent yellow "2.Uninstall"
|
||
echoContent yellow "# Notes"
|
||
|
||
echoContent yellow "# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \n"
|
||
echoContent yellow "1.Add"
|
||
read -r -p "Please select:" selectType
|
||
|
||
case ${selectType} in
|
||
1)
|
||
setUnlockSNI
|
||
;;
|
||
2)
|
||
removeUnlockSNI
|
||
;;
|
||
esac
|
||
}
|
||
# Set up SNI offloading
|
||
setUnlockSNI() {
|
||
read -r -p "Please enter the SNI IP of the offload:" setSNIP
|
||
if [[ -n ${setSNIP} ]]; then
|
||
echoContent red "=============================================================="
|
||
|
||
if [[ "${coreInstallType}" == 1 ]]; then
|
||
echoContent yellow "2.Uninstall"
|
||
read -r -p "Enter domains using the example above:" xrayDomainList
|
||
local hosts={}
|
||
while read -r domain; do
|
||
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')
|
||
cat <<EOF >${configPath}11_dns.json
|
||
{
|
||
"dns": {
|
||
"hosts":${hosts},
|
||
"servers": [
|
||
"8.8.8.8",
|
||
"1.1.1.1"
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
echoContent yellow "Input example: netflix, disney, hulu"
|
||
read -r -p "Enter domains using the example above:" singboxDomainList
|
||
addSingBoxDNSConfig "${setSNIP}" "${singboxDomainList}" "predefined"
|
||
fi
|
||
echoContent yellow "Input example: netflix, disney, hulu"
|
||
reloadCore
|
||
else
|
||
echoContent red " ---> Wrong selection"
|
||
fi
|
||
exit 0
|
||
}
|
||
|
||
addXrayDNSConfig() {
|
||
local ip=$1
|
||
local domainList=$2
|
||
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')
|
||
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
|
||
cat <<EOF >${configPath}11_dns.json
|
||
{
|
||
"dns": {
|
||
"servers": [
|
||
{
|
||
"address": "${ip}",
|
||
"port": 53,
|
||
"domains": ${domains}
|
||
},
|
||
"localhost"
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
}
|
||
|
||
addSingBoxDNSConfig() {
|
||
local ip=$1
|
||
local domainList=$2
|
||
local actionType=$3
|
||
|
||
local rules=
|
||
rules=$(initSingBoxRules "${domainList}" "dns")
|
||
local domainRules=
|
||
domainRules=$(echo "${rules}" | jq .domainRules)
|
||
|
||
local ruleSet=
|
||
ruleSet=$(echo "${rules}" | jq .ruleSet)
|
||
|
||
local ruleSetTag=[]
|
||
if [[ "$(echo "${ruleSet}" | jq '.|length')" != "0" ]]; then
|
||
ruleSetTag=$(echo "${ruleSet}" | jq '.|map(.tag)')
|
||
fi
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
if [[ "${actionType}" == "predefined" ]]; then
|
||
local predefined={}
|
||
while read -r line; do
|
||
predefined=$(echo "${predefined}" | jq ".\"${line}\"=\"${ip}\"")
|
||
done < <(echo "${domainList}" | tr ',' '\n' | grep -v '^$' | sort -n | uniq | paste -sd ',' | tr ',' '\n')
|
||
|
||
cat <<EOF >"${singBoxConfigPath}dns.json"
|
||
{
|
||
"dns": {
|
||
"servers": [
|
||
{
|
||
"tag": "local",
|
||
"type": "local"
|
||
},
|
||
{
|
||
"tag": "hosts",
|
||
"type": "hosts",
|
||
"predefined": ${predefined}
|
||
}
|
||
],
|
||
"rules": [
|
||
{
|
||
"domain_regex":${domainRules},
|
||
"server":"hosts"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
else
|
||
cat <<EOF >"${singBoxConfigPath}dns.json"
|
||
{
|
||
"dns": {
|
||
"servers": [
|
||
{
|
||
"tag": "local",
|
||
"type": "local"
|
||
},
|
||
{
|
||
"tag": "dnsRouting",
|
||
"type": "udp",
|
||
"server": "${ip}"
|
||
}
|
||
],
|
||
"rules": [
|
||
{
|
||
"rule_set": ${ruleSetTag},
|
||
"domain_regex": ${domainRules},
|
||
"server":"dnsRouting"
|
||
}
|
||
]
|
||
},
|
||
"route":{
|
||
"rule_set":${ruleSet}
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
fi
|
||
}
|
||
# Set dns
|
||
setUnlockDNS() {
|
||
read -r -p "Please enter the diverted DNS:" setDNS
|
||
if [[ -n ${setDNS} ]]; then
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "Please enter 1 for the default scheme. The default scheme includes the following content"
|
||
read -r -p "Please enter the domain name according to the above example:" domainList
|
||
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
addXrayDNSConfig "${setDNS}" "${domainList}"
|
||
fi
|
||
|
||
if [[ -n "${singBoxConfigPath}" ]]; then
|
||
addSingBoxOutbound 01_direct_outbound
|
||
addSingBoxDNSConfig "${setDNS}" "${domainList}"
|
||
fi
|
||
|
||
reloadCore
|
||
|
||
echoContent yellow "netflix,bahamut,hulu,hbo,disney,bbc,4chan,fox,abema,dmm,niconico,pixiv,bilibili,viu"
|
||
echoContent yellow "\n ---> If you still can't watch, you can try the following two solutions"
|
||
echoContent yellow "1.Restart vps"
|
||
else
|
||
echoContent red " ---> Not installed, please use script to install"
|
||
fi
|
||
exit 0
|
||
}
|
||
|
||
# Remove DNS offloading
|
||
removeUnlockDNS() {
|
||
if [[ "${coreInstallType}" == "1" && -f "${configPath}11_dns.json" ]]; then
|
||
cat <<EOF >${configPath}11_dns.json
|
||
{
|
||
"dns": {
|
||
"servers": [
|
||
"localhost"
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
if [[ "${coreInstallType}" == "2" && -f "${singBoxConfigPath}dns.json" ]]; then
|
||
cat <<EOF >${singBoxConfigPath}dns.json
|
||
{
|
||
"dns": {
|
||
"servers":[
|
||
{
|
||
"tag":"local",
|
||
"type":"local"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
reloadCore
|
||
|
||
echoContent green " ---> BT download opened successfully"
|
||
|
||
exit 0
|
||
}
|
||
|
||
# Remove SNI shunt
|
||
removeUnlockSNI() {
|
||
if [[ "${coreInstallType}" == 1 ]]; then
|
||
cat <<EOF >${configPath}11_dns.json
|
||
{
|
||
"dns": {
|
||
"servers": [
|
||
"localhost"
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
if [[ "${coreInstallType}" == "2" && -f "${singBoxConfigPath}dns.json" ]]; then
|
||
cat <<EOF >${singBoxConfigPath}dns.json
|
||
{
|
||
"dns": {
|
||
"servers":[
|
||
{
|
||
"type":"local"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
reloadCore
|
||
echoContent green " ---> Added successfully"
|
||
|
||
exit 0
|
||
}
|
||
|
||
customSingBoxInstall() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: any door diversion"
|
||
echoContent yellow "0.VLESS+Vision+TCP"
|
||
echoContent yellow "2.After uninstalling dns unlocking, modify the local [/etc/resolv.conf] DNS settings and restart vps\n"
|
||
echoContent yellow "VLESS is prefixed and 0 is installed by default. If you only need to install 0, just select 0"
|
||
echoContent yellow "0.VLESS+TLS_Vision+TCP"
|
||
echoContent yellow "6.Hysteria2"
|
||
echoContent yellow "7.VLESS+Reality+Vision"
|
||
echoContent yellow "8.VLESS+Reality+gRPC"
|
||
echoContent yellow "9.Tuic"
|
||
echoContent yellow "10.Naive"
|
||
echoContent yellow "11.VMess+TLS+HTTPUpgrade"
|
||
echoContent yellow "13.anytls"
|
||
|
||
read -r -p "Please select [multiple selection], [for example: 123]:" selectCustomInstallType
|
||
echoContent skyBlue "--------------------------------------------------------------"
|
||
if echo "${selectCustomInstallType}" | grep -q ","; then
|
||
echoContent red "\n================================================ ================="
|
||
exit 0
|
||
fi
|
||
if [[ "${selectCustomInstallType}" != "10" ]] && [[ "${selectCustomInstallType}" != "11" ]] && [[ "${selectCustomInstallType}" != "13" ]] && ((${#selectCustomInstallType} >= 2)) && ! echo "${selectCustomInstallType}" | grep -q ","; then
|
||
echoContent red "================================================== ==============="
|
||
exit 0
|
||
fi
|
||
if [[ "${selectCustomInstallType: -1}" != "," ]]; then
|
||
selectCustomInstallType="${selectCustomInstallType},"
|
||
fi
|
||
if [[ "${selectCustomInstallType:0:1}" != "," ]]; then
|
||
selectCustomInstallType=",${selectCustomInstallType},"
|
||
fi
|
||
|
||
if [[ "${selectCustomInstallType//,/}" =~ ^[0-9]+$ ]]; then
|
||
readLastInstallationConfig
|
||
unInstallSubscribe
|
||
totalProgress=9
|
||
installTools 1
|
||
if echo "${selectCustomInstallType}" | grep -q -E ",0,|,1,|,3,|,4,|,6,|,9,|,10,|,11,|,13,"; then
|
||
# Apply for tls
|
||
initTLSNginxConfig 2
|
||
# handleNginx start
|
||
installTLS 3
|
||
handleNginx stop
|
||
fi
|
||
|
||
installSingBox 4
|
||
installSingBoxService 5
|
||
initSingBoxConfig custom 6
|
||
cleanUp xrayDel
|
||
installCronTLS 7
|
||
handleSingBox stop
|
||
handleSingBox start
|
||
handleNginx stop
|
||
handleNginx start
|
||
checkGFWStatue 8
|
||
showAccounts 9
|
||
else
|
||
echoContent red " ---> Wrong selection"
|
||
customSingBoxInstall
|
||
fi
|
||
}
|
||
|
||
installXrayReality() {
|
||
selectCustomInstallType=",7,"
|
||
readLastInstallationConfig
|
||
unInstallSubscribe
|
||
totalProgress=6
|
||
installTools 1
|
||
|
||
handleNginx stop
|
||
|
||
installXray 2 false
|
||
installXrayService 3
|
||
initXrayConfig custom 4
|
||
cleanUp singBoxDel
|
||
|
||
handleXray stop
|
||
handleXray start
|
||
checkGFWStatue 5
|
||
showAccounts 6
|
||
}
|
||
installSingBoxReality() {
|
||
|
||
selectCustomInstallType=",7,"
|
||
readLastInstallationConfig
|
||
unInstallSubscribe
|
||
totalProgress=6
|
||
installTools 1
|
||
|
||
installSingBox 2
|
||
installSingBoxService 3
|
||
initSingBoxConfig custom 4
|
||
cleanUp xrayDel
|
||
handleSingBox stop
|
||
handleSingBox start
|
||
checkGFWStatue 5
|
||
showAccounts 6
|
||
}
|
||
# Xray-core personalized installation
|
||
customXrayInstall() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: VMess+WS+TLS offload"
|
||
echoContent yellow "1.VLESS+TLS+WS[CDN]"
|
||
echoContent yellow "2.Trojan+TLS+gRPC[CDN]"
|
||
echoContent yellow "3.VMess+TLS+WS[CDN]"
|
||
echoContent yellow "4.Trojan+TLS"
|
||
echoContent yellow "5.VLESS+TLS+gRPC[CDN]"
|
||
echoContent yellow "VLESS is prefixed and 0 is installed by default. If you only need to install 0, just select 0"
|
||
# echoContent yellow "8.VLESS+Reality+gRPC"
|
||
echoContent yellow "0.VLESS+TLS_Vision+TCP[recommended]"
|
||
read -r -p "Please select [multiple selection], [for example: 123]:" selectCustomInstallType
|
||
echoContent skyBlue "--------------------------------------------------------------"
|
||
if echo "${selectCustomInstallType}" | grep -q ","; then
|
||
echoContent red " ---> Not installed, please use script to install"
|
||
exit 0
|
||
fi
|
||
if [[ "${selectCustomInstallType}" != "12" ]] && ((${#selectCustomInstallType} >= 2)) && ! echo "${selectCustomInstallType}" | grep -q ","; then
|
||
echoContent red "\n================================================ ================="
|
||
exit 0
|
||
fi
|
||
if echo "${selectCustomInstallType}" | grep -qE '^(7|7,12|12)$'; then
|
||
selectCustomInstallType=",${selectCustomInstallType},"
|
||
else
|
||
if ! echo "${selectCustomInstallType}" | grep -q "0,"; then
|
||
selectCustomInstallType=",0,${selectCustomInstallType},"
|
||
else
|
||
selectCustomInstallType=",${selectCustomInstallType},"
|
||
fi
|
||
fi
|
||
if [[ "${selectCustomInstallType:0:1}" != "," ]]; then
|
||
selectCustomInstallType=",${selectCustomInstallType},"
|
||
fi
|
||
if [[ "${selectCustomInstallType//,/}" =~ ^[0-7]+$ ]]; then
|
||
readLastInstallationConfig
|
||
unInstallSubscribe
|
||
# checkBTPanel
|
||
# check1Panel
|
||
totalProgress=12
|
||
installTools 1
|
||
if [[ -n "${btDomain}" ]]; then
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: Add inbound at any door"
|
||
handleXray stop
|
||
if [[ "${selectCustomInstallType}" != ",7," ]]; then
|
||
customPortFunction
|
||
fi
|
||
else
|
||
if ! echo "${selectCustomInstallType}" | grep -qE '^(,7,|,7,12,|,12,)$'; then
|
||
# Apply for tls
|
||
initTLSNginxConfig 2
|
||
handleXray stop
|
||
installTLS 3
|
||
else
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: DNS offloading"
|
||
fi
|
||
fi
|
||
|
||
handleNginx stop
|
||
if echo "${selectCustomInstallType}" | grep -qE ",1,|,2,|,3,|,5,|,12,"; then
|
||
randomPathFunction 4
|
||
fi
|
||
if [[ -n "${btDomain}" ]]; then
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: SNI reverse proxy offload"
|
||
else
|
||
nginxBlog 6
|
||
fi
|
||
if ! echo "${selectCustomInstallType}" | grep -qE '^(,7,|,7,12,|,12,)$'; then
|
||
updateRedirectNginxConf
|
||
handleNginx start
|
||
fi
|
||
|
||
# Install Xray
|
||
installXray 7 false
|
||
installXrayService 8
|
||
initXrayConfig custom 9
|
||
cleanUp singBoxDel
|
||
if ! echo "${selectCustomInstallType}" | grep -qE '^(,7,|,7,12,|,12,)$'; then
|
||
installCronTLS 10
|
||
fi
|
||
|
||
handleXray stop
|
||
handleXray start
|
||
# Generate account
|
||
checkGFWStatue 11
|
||
showAccounts 12
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
customXrayInstall
|
||
fi
|
||
}
|
||
|
||
# Select core installation---v2ray-core, xray-core
|
||
selectCoreInstall() {
|
||
echoContent skyBlue "\n========================Personalized installation================== =========="
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "1.Xray-core"
|
||
echoContent yellow "2.sing-box"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" selectCoreType
|
||
case ${selectCoreType} in
|
||
1)
|
||
if [[ "${selectInstallType}" == "1" ]]; then
|
||
xrayCoreInstall
|
||
elif [[ "${selectInstallType}" == "2" ]]; then
|
||
customXrayInstall
|
||
elif [[ "${selectInstallType}" == "3" ]]; then
|
||
installXrayReality
|
||
fi
|
||
;;
|
||
2)
|
||
if [[ "${selectInstallType}" == "1" ]]; then
|
||
singBoxInstall
|
||
elif [[ "${selectInstallType}" == "2" ]]; then
|
||
customSingBoxInstall
|
||
elif [[ "${selectInstallType}" == "3" ]]; then
|
||
installSingBoxReality
|
||
fi
|
||
;;
|
||
*)
|
||
echoContent red "================================================== ==============="
|
||
selectCoreInstall
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# xray-core installation
|
||
xrayCoreInstall() {
|
||
readLastInstallationConfig
|
||
unInstallSubscribe
|
||
# checkBTPanel
|
||
# check1Panel
|
||
selectCustomInstallType=
|
||
totalProgress=12
|
||
installTools 2
|
||
if [[ -n "${btDomain}" ]]; then
|
||
echoContent skyBlue "------------------------------------------------- ---------------"
|
||
handleXray stop
|
||
customPortFunction
|
||
else
|
||
# Apply for tls
|
||
initTLSNginxConfig 3
|
||
handleXray stop
|
||
# handleNginx start
|
||
|
||
installTLS 4
|
||
fi
|
||
|
||
handleNginx stop
|
||
randomPathFunction 5
|
||
|
||
# Install Xray
|
||
installXray 6 false
|
||
installXrayService 7
|
||
initXrayConfig all 8
|
||
cleanUp singBoxDel
|
||
installCronTLS 9
|
||
if [[ -n "${btDomain}" ]]; then
|
||
echoContent skyBlue "\n========================Personalized installation================== =========="
|
||
else
|
||
nginxBlog 10
|
||
fi
|
||
updateRedirectNginxConf
|
||
handleXray stop
|
||
sleep 2
|
||
handleXray start
|
||
|
||
handleNginx start
|
||
checkGFWStatue 11
|
||
showAccounts 12
|
||
}
|
||
|
||
singBoxInstall() {
|
||
readLastInstallationConfig
|
||
unInstallSubscribe
|
||
# checkBTPanel
|
||
# check1Panel
|
||
selectCustomInstallType=
|
||
totalProgress=8
|
||
installTools 2
|
||
|
||
if [[ -n "${btDomain}" ]]; then
|
||
echoContent skyBlue "------------------------------------------------- --------- ------"
|
||
handleXray stop
|
||
customPortFunction
|
||
else
|
||
initTLSNginxConfig 3
|
||
handleXray stop
|
||
installTLS 4
|
||
fi
|
||
|
||
handleNginx stop
|
||
|
||
installSingBox 5
|
||
installSingBoxService 6
|
||
initSingBoxConfig all 7
|
||
|
||
cleanUp xrayDel
|
||
installCronTLS 8
|
||
|
||
handleSingBox stop
|
||
handleSingBox start
|
||
handleNginx stop
|
||
handleNginx start
|
||
showAccounts 9
|
||
}
|
||
|
||
# Core Management
|
||
coreVersionManageMenu() {
|
||
|
||
if [[ -z "${coreInstallType}" ]]; then
|
||
echoContent red " ---> ip cannot be empty"
|
||
menu
|
||
exit 0
|
||
fi
|
||
echoContent skyBlue "\nProgress 3/${totalProgress}: Pagoda panel detected, skip applying for TLS"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "1.Xray-core"
|
||
echoContent yellow "2.sing-box"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Enter selection:" selectCore
|
||
|
||
if [[ "${selectCore}" == "1" ]]; then
|
||
xrayVersionManageMenu 1
|
||
elif [[ "${selectCore}" == "2" ]]; then
|
||
singBoxVersionManageMenu 1
|
||
fi
|
||
}
|
||
# Scheduled task check
|
||
cronFunction() {
|
||
if [[ "${cronName}" == "RenewTLS" ]]; then
|
||
renewalTLS
|
||
exit 0
|
||
elif [[ "${cronName}" == "UpdateGeo" ]]; then
|
||
updateGeoSite >>/etc/v2ray-agent/crontab_updateGeoSite.log
|
||
echoContent green " ---> geo update date: $(date "+%F %H:%M:%S")" >>/etc/v2ray-agent/crontab_updateGeoSite.log
|
||
exit 0
|
||
fi
|
||
}
|
||
#Account management
|
||
manageAccount() {
|
||
echoContent skyBlue "\nProgress 6/${totalProgress}: Pagoda panel detected, skipping disguised website"
|
||
if [[ -z "${configPath}" ]]; then
|
||
echoContent red " ---> domain cannot be empty"
|
||
exit 0
|
||
fi
|
||
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "1.VLESS+TLS+WS[CDN]"
|
||
echoContent yellow "2.Trojan+TLS+gRPC[CDN]"
|
||
echoContent yellow "3.VMess+TLS+WS[CDN]"
|
||
echoContent yellow "4.Trojan+TLS"
|
||
echoContent yellow "5.VLESS+TLS+gRPC[CDN]"
|
||
echoContent yellow "7.VLESS+Reality+uTLS+Vision[recommended]"
|
||
echoContent yellow "1.Xray-core"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please enter:" manageAccountStatus
|
||
if [[ "${manageAccountStatus}" == "1" ]]; then
|
||
showAccounts 1
|
||
elif [[ "${manageAccountStatus}" == "2" ]]; then
|
||
subscribe
|
||
elif [[ "${manageAccountStatus}" == "3" ]]; then
|
||
addSubscribeMenu 1
|
||
elif [[ "${manageAccountStatus}" == "4" ]]; then
|
||
addUser
|
||
elif [[ "${manageAccountStatus}" == "5" ]]; then
|
||
removeUser
|
||
else
|
||
echoContent red " ---> Wrong selection"
|
||
fi
|
||
}
|
||
|
||
installSubscribe() {
|
||
readNginxSubscribe
|
||
local nginxSubscribeListen=
|
||
local nginxSubscribeSSL=
|
||
local serverName=
|
||
local SSLType=
|
||
local listenIPv6=
|
||
if [[ -z "${subscribePort}" ]]; then
|
||
|
||
nginxVersion=$(nginx -v 2>&1)
|
||
|
||
if echo "${nginxVersion}" | grep -q "not found" || [[ -z "${nginxVersion}" ]]; then
|
||
echoContent yellow "2.v2ray-core"
|
||
read -r -p "Install [y/n]?" installNginxStatus
|
||
if [[ "${installNginxStatus}" == "y" ]]; then
|
||
installNginxTools
|
||
else
|
||
echoContent red " ---> Parameter error"
|
||
exit 0
|
||
fi
|
||
fi
|
||
echoContent yellow "# Only delete VLESS Reality related configurations, other content will not be deleted."
|
||
|
||
mapfile -t result < <(initSingBoxPort "${subscribePort}")
|
||
echo
|
||
echoContent yellow "# If you need to uninstall other content, please uninstall the script function"
|
||
nginxBlog
|
||
echo
|
||
local httpSubscribeStatus=
|
||
|
||
if ! echo "${selectCustomInstallType}" | grep -qE ",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,|,11,|,13," && ! echo "${currentInstallProtocolType}" | grep -qE ",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,|,11,|,13," && [[ -z "${domain}" ]]; then
|
||
httpSubscribeStatus=true
|
||
fi
|
||
|
||
if [[ "${httpSubscribeStatus}" == "true" ]]; then
|
||
|
||
echoContent yellow "# You can customize email and uuid when adding a single user"
|
||
echo
|
||
read -r -p "Use HTTP subscription [y/n]?" addNginxSubscribeStatus
|
||
echo
|
||
if [[ "${addNginxSubscribeStatus}" != "y" ]]; then
|
||
echoContent yellow "# If Hysteria or Tuic is installed, the account will be added to the corresponding type at the same time\n"
|
||
exit
|
||
fi
|
||
else
|
||
local subscribeServerName=
|
||
if [[ -n "${currentHost}" ]]; then
|
||
subscribeServerName="${currentHost}"
|
||
else
|
||
subscribeServerName="${domain}"
|
||
fi
|
||
|
||
SSLType="ssl"
|
||
serverName="server_name ${subscribeServerName};"
|
||
nginxSubscribeSSL="ssl_certificate /etc/v2ray-agent/tls/${subscribeServerName}.crt;ssl_certificate_key /etc/v2ray-agent/tls/${subscribeServerName}.key;"
|
||
fi
|
||
if [[ -n "$(curl --connect-timeout 2 -s -6 http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2)" ]]; then
|
||
listenIPv6="listen [::]:${result[-1]} ${SSLType};"
|
||
fi
|
||
if echo "${nginxVersion}" | grep -q "1.25" && [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $3}') -gt 0 ]] || [[ $(echo "${nginxVersion}" | awk -F "[.]" '{print $2}') -gt 25 ]]; then
|
||
nginxSubscribeListen="listen ${result[-1]} ${SSLType} so_keepalive=on;http2 on;${listenIPv6}"
|
||
else
|
||
nginxSubscribeListen="listen ${result[-1]} ${SSLType} so_keepalive=on;${listenIPv6}"
|
||
fi
|
||
|
||
cat <<EOF >${nginxConfigPath}subscribe.conf
|
||
server {
|
||
${nginxSubscribeListen}
|
||
${serverName}
|
||
${nginxSubscribeSSL}
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
ssl_ciphers TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;
|
||
ssl_prefer_server_ciphers on;
|
||
|
||
resolver 1.1.1.1 valid=60s;
|
||
resolver_timeout 2s;
|
||
client_max_body_size 100m;
|
||
root ${nginxStaticPath};
|
||
location ~ ^/s/(clashMeta|default|clashMetaProfiles|sing-box|sing-box_profiles)/(.*) {
|
||
default_type 'text/plain; charset=utf-8';
|
||
alias /etc/v2ray-agent/subscribe/\$1/\$2;
|
||
}
|
||
location / {
|
||
}
|
||
}
|
||
EOF
|
||
bootStartup nginx
|
||
handleNginx stop
|
||
handleNginx start
|
||
fi
|
||
if [[ -z $(pgrep -f "nginx") ]]; then
|
||
handleNginx start
|
||
fi
|
||
}
|
||
unInstallSubscribe() {
|
||
rm -rf ${nginxConfigPath}subscribe.conf >/dev/null 2>&1
|
||
}
|
||
|
||
#Add subscription
|
||
addSubscribeMenu() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: Select core installation"
|
||
echoContent yellow "1.Check account"
|
||
echoContent yellow "2.View subscription"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" addSubscribeStatus
|
||
if [[ "${addSubscribeStatus}" == "1" ]]; then
|
||
addOtherSubscribe
|
||
elif [[ "${addSubscribeStatus}" == "2" ]]; then
|
||
if [[ ! -f "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" ]]; then
|
||
echoContent green " ---> Domestic domain name + IP blocked successfully"
|
||
exit 0
|
||
fi
|
||
grep -v '^$' "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" | awk '{print NR""":"$0}'
|
||
read -r -p "Select the subscription number to delete [single selection only]:" delSubscribeIndex
|
||
if [[ -z "${delSubscribeIndex}" ]]; then
|
||
echoContent green " ---> Domain blacklist/whitelist deleted successfully"
|
||
exit 0
|
||
fi
|
||
|
||
sed -i "$((delSubscribeIndex))d" "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" >/dev/null 2>&1
|
||
|
||
echoContent green " ---> Blocked IP added successfully"
|
||
subscribe
|
||
fi
|
||
}
|
||
# Add other machines to clashMeta subscription
|
||
addOtherSubscribe() {
|
||
echoContent yellow "3.Add subscription"
|
||
echoContent yellow "4.Add user"
|
||
echoContent skyBlue "\nProgress 3/${totalProgress}: Pagoda panel detected, skip applying for TLS"
|
||
read -r -p "Please enter the domain name, port and machine alias:" remoteSubscribeUrl
|
||
if [[ -z "${remoteSubscribeUrl}" ]]; then
|
||
echoContent red " ---> Parameter error"
|
||
addOtherSubscribe
|
||
elif ! echo "${remoteSubscribeUrl}" | grep -q ":"; then
|
||
echoContent red "=============================================================="
|
||
else
|
||
|
||
if [[ -f "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" ]] && grep -q "${remoteSubscribeUrl}" /etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl; then
|
||
echoContent red "\n================================================ ================="
|
||
exit 0
|
||
fi
|
||
echo
|
||
read -r -p "Is this an HTTP subscription? [y/n]" httpSubscribeStatus
|
||
if [[ "${httpSubscribeStatus}" == "y" ]]; then
|
||
remoteSubscribeUrl="${remoteSubscribeUrl}:http"
|
||
fi
|
||
echo "${remoteSubscribeUrl}" >>/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl
|
||
subscribe
|
||
fi
|
||
}
|
||
# clashMeta configuration file
|
||
clashMetaConfig() {
|
||
local url=$1
|
||
local id=$2
|
||
cat <<EOF >"/etc/v2ray-agent/subscribe/clashMetaProfiles/${id}"
|
||
log-level: debug
|
||
mode: rule
|
||
ipv6: true
|
||
mixed-port: 7890
|
||
allow-lan: true
|
||
bind-address: "*"
|
||
lan-allowed-ips:
|
||
- 0.0.0.0/0
|
||
- ::/0
|
||
find-process-mode: strict
|
||
external-controller: 0.0.0.0:9090
|
||
|
||
geox-url:
|
||
geoip: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat"
|
||
geosite: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat"
|
||
mmdb: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.metadb"
|
||
geo-auto-update: true
|
||
geo-update-interval: 24
|
||
|
||
external-controller-cors:
|
||
allow-private-network: true
|
||
|
||
global-client-fingerprint: chrome
|
||
|
||
profile:
|
||
store-selected: true
|
||
store-fake-ip: true
|
||
|
||
sniffer:
|
||
enable: true
|
||
override-destination: false
|
||
sniff:
|
||
QUIC:
|
||
ports: [ 443 ]
|
||
TLS:
|
||
ports: [ 443 ]
|
||
HTTP:
|
||
ports: [80]
|
||
|
||
|
||
dns:
|
||
enable: true
|
||
prefer-h3: false
|
||
listen: 0.0.0.0:1053
|
||
ipv6: true
|
||
enhanced-mode: fake-ip
|
||
fake-ip-range: 198.18.0.1/16
|
||
fake-ip-filter:
|
||
- '*.lan'
|
||
- '*.local'
|
||
- 'dns.google'
|
||
- "localhost.ptlogin2.qq.com"
|
||
use-hosts: true
|
||
nameserver:
|
||
- https://1.1.1.1/dns-query
|
||
- https://8.8.8.8/dns-query
|
||
- 1.1.1.1
|
||
- 8.8.8.8
|
||
proxy-server-nameserver:
|
||
- https://223.5.5.5/dns-query
|
||
- https://1.12.12.12/dns-query
|
||
nameserver-policy:
|
||
"geosite:cn,private":
|
||
- https://doh.pub/dns-query
|
||
- https://dns.alidns.com/dns-query
|
||
|
||
proxy-providers:
|
||
${subscribeSalt}_provider:
|
||
type: http
|
||
path: ./${subscribeSalt}_provider.yaml
|
||
url: ${url}
|
||
interval: 3600
|
||
proxy: DIRECT
|
||
health-check:
|
||
enable: true
|
||
url: https://cp.cloudflare.com/generate_204
|
||
interval: 300
|
||
|
||
proxy-groups:
|
||
- name: 手动切换
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies: null
|
||
- name: 自动选择
|
||
type: url-test
|
||
url: http://www.gstatic.com/generate_204
|
||
interval: 36000
|
||
tolerance: 50
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies: null
|
||
|
||
- name: 全球代理
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 手动切换
|
||
- 自动选择
|
||
|
||
- name: 流媒体
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 手动切换
|
||
- 自动选择
|
||
- DIRECT
|
||
- name: DNS_Proxy
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 自动选择
|
||
- 手动切换
|
||
- DIRECT
|
||
|
||
- name: Telegram
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 手动切换
|
||
- 自动选择
|
||
- name: Google
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 手动切换
|
||
- 自动选择
|
||
- DIRECT
|
||
- name: YouTube
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 手动切换
|
||
- 自动选择
|
||
- name: Netflix
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 流媒体
|
||
- 手动切换
|
||
- 自动选择
|
||
- name: Spotify
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 流媒体
|
||
- 手动切换
|
||
- 自动选择
|
||
- DIRECT
|
||
- name: HBO
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 流媒体
|
||
- 手动切换
|
||
- 自动选择
|
||
- name: Bing
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 手动切换
|
||
- 自动选择
|
||
|
||
|
||
- name: OpenAI
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 手动切换
|
||
- 自动选择
|
||
|
||
- name: ClaudeAI
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 手动切换
|
||
- 自动选择
|
||
|
||
- name: Disney
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 流媒体
|
||
- 手动切换
|
||
- 自动选择
|
||
- name: GitHub
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- 手动切换
|
||
- 自动选择
|
||
- DIRECT
|
||
|
||
- name: 国内媒体
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- DIRECT
|
||
- name: 本地直连
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- DIRECT
|
||
- 自动选择
|
||
- name: 漏网之鱼
|
||
type: select
|
||
use:
|
||
- ${subscribeSalt}_provider
|
||
proxies:
|
||
- DIRECT
|
||
- 手动切换
|
||
- 自动选择
|
||
rule-providers:
|
||
lan:
|
||
type: http
|
||
behavior: classical
|
||
interval: 86400
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Lan/Lan.yaml
|
||
path: ./Rules/lan.yaml
|
||
reject:
|
||
type: http
|
||
behavior: domain
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/reject.txt
|
||
path: ./ruleset/reject.yaml
|
||
interval: 86400
|
||
proxy:
|
||
type: http
|
||
behavior: domain
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/proxy.txt
|
||
path: ./ruleset/proxy.yaml
|
||
interval: 86400
|
||
direct:
|
||
type: http
|
||
behavior: domain
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/direct.txt
|
||
path: ./ruleset/direct.yaml
|
||
interval: 86400
|
||
private:
|
||
type: http
|
||
behavior: domain
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/private.txt
|
||
path: ./ruleset/private.yaml
|
||
interval: 86400
|
||
gfw:
|
||
type: http
|
||
behavior: domain
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/gfw.txt
|
||
path: ./ruleset/gfw.yaml
|
||
interval: 86400
|
||
greatfire:
|
||
type: http
|
||
behavior: domain
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/greatfire.txt
|
||
path: ./ruleset/greatfire.yaml
|
||
interval: 86400
|
||
tld-not-cn:
|
||
type: http
|
||
behavior: domain
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/tld-not-cn.txt
|
||
path: ./ruleset/tld-not-cn.yaml
|
||
interval: 86400
|
||
telegramcidr:
|
||
type: http
|
||
behavior: ipcidr
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/telegramcidr.txt
|
||
path: ./ruleset/telegramcidr.yaml
|
||
interval: 86400
|
||
applications:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/applications.txt
|
||
path: ./ruleset/applications.yaml
|
||
interval: 86400
|
||
Disney:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Disney/Disney.yaml
|
||
path: ./ruleset/disney.yaml
|
||
interval: 86400
|
||
Netflix:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Netflix/Netflix.yaml
|
||
path: ./ruleset/netflix.yaml
|
||
interval: 86400
|
||
YouTube:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/YouTube/YouTube.yaml
|
||
path: ./ruleset/youtube.yaml
|
||
interval: 86400
|
||
HBO:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/HBO/HBO.yaml
|
||
path: ./ruleset/hbo.yaml
|
||
interval: 86400
|
||
OpenAI:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/OpenAI/OpenAI.yaml
|
||
path: ./ruleset/openai.yaml
|
||
interval: 86400
|
||
ClaudeAI:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Claude/Claude.yaml
|
||
path: ./ruleset/claudeai.yaml
|
||
interval: 86400
|
||
Bing:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Bing/Bing.yaml
|
||
path: ./ruleset/bing.yaml
|
||
interval: 86400
|
||
Google:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Google/Google.yaml
|
||
path: ./ruleset/google.yaml
|
||
interval: 86400
|
||
GitHub:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/GitHub/GitHub.yaml
|
||
path: ./ruleset/github.yaml
|
||
interval: 86400
|
||
Spotify:
|
||
type: http
|
||
behavior: classical
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Spotify/Spotify.yaml
|
||
path: ./ruleset/spotify.yaml
|
||
interval: 86400
|
||
ChinaMaxDomain:
|
||
type: http
|
||
behavior: domain
|
||
interval: 86400
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/ChinaMax/ChinaMax_Domain.yaml
|
||
path: ./Rules/ChinaMaxDomain.yaml
|
||
ChinaMaxIPNoIPv6:
|
||
type: http
|
||
behavior: ipcidr
|
||
interval: 86400
|
||
url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/ChinaMax/ChinaMax_IP_No_IPv6.yaml
|
||
path: ./Rules/ChinaMaxIPNoIPv6.yaml
|
||
rules:
|
||
- RULE-SET,YouTube,YouTube,no-resolve
|
||
- RULE-SET,Google,Google,no-resolve
|
||
- RULE-SET,GitHub,GitHub
|
||
- RULE-SET,telegramcidr,Telegram,no-resolve
|
||
- RULE-SET,Spotify,Spotify,no-resolve
|
||
- RULE-SET,Netflix,Netflix
|
||
- RULE-SET,HBO,HBO
|
||
- RULE-SET,Bing,Bing
|
||
- RULE-SET,OpenAI,OpenAI
|
||
- RULE-SET,ClaudeAI,ClaudeAI
|
||
- RULE-SET,Disney,Disney
|
||
- RULE-SET,proxy,全球代理
|
||
- RULE-SET,gfw,全球代理
|
||
- RULE-SET,applications,本地直连
|
||
- RULE-SET,ChinaMaxDomain,本地直连
|
||
- RULE-SET,ChinaMaxIPNoIPv6,本地直连,no-resolve
|
||
- RULE-SET,lan,本地直连,no-resolve
|
||
- GEOIP,CN,本地直连
|
||
- MATCH,漏网之鱼
|
||
EOF
|
||
|
||
}
|
||
# Random salt
|
||
initRandomSalt() {
|
||
local chars="abcdefghijklmnopqrtuxyz"
|
||
local initCustomPath=
|
||
for i in {1..10}; do
|
||
echo "${i}" >/dev/null
|
||
initCustomPath+="${chars:RANDOM%${#chars}:1}"
|
||
done
|
||
echo "${initCustomPath}"
|
||
}
|
||
# Subscribe
|
||
subscribe() {
|
||
readInstallProtocolType
|
||
installSubscribe
|
||
|
||
readNginxSubscribe
|
||
local renewSalt=$1
|
||
local showStatus=$2
|
||
if [[ "${coreInstallType}" == "1" || "${coreInstallType}" == "2" ]]; then
|
||
|
||
echoContent skyBlue "\nProgress 11/${totalProgress}: Pagoda panel detected, skipping disguised website"
|
||
echoContent yellow "5.Delete user"
|
||
echoContent red "================================================== ==============="
|
||
echoContent yellow "1.Add"
|
||
|
||
if [[ -f "/etc/v2ray-agent/subscribe_local/subscribeSalt" && -n $(cat "/etc/v2ray-agent/subscribe_local/subscribeSalt") ]]; then
|
||
if [[ -z "${renewSalt}" ]]; then
|
||
read -r -p "Read the Salt set by the last installation. Do you want to use the Salt generated last time? [y/n]:" historySaltStatus
|
||
if [[ "${historySaltStatus}" == "y" ]]; then
|
||
subscribeSalt=$(cat /etc/v2ray-agent/subscribe_local/subscribeSalt)
|
||
else
|
||
read -r -p "Please enter the salt value, [Enter] use random:" subscribeSalt
|
||
fi
|
||
else
|
||
subscribeSalt=$(cat /etc/v2ray-agent/subscribe_local/subscribeSalt)
|
||
fi
|
||
else
|
||
read -r -p "Please enter the salt value, [Enter] use random:" subscribeSalt
|
||
showStatus=
|
||
fi
|
||
|
||
if [[ -z "${subscribeSalt}" ]]; then
|
||
subscribeSalt=$(initRandomSalt)
|
||
fi
|
||
echoContent yellow "\n ---> Salt: ${subscribeSalt}"
|
||
|
||
echo "${subscribeSalt}" >/etc/v2ray-agent/subscribe_local/subscribeSalt
|
||
|
||
rm -rf /etc/v2ray-agent/subscribe/default/*
|
||
rm -rf /etc/v2ray-agent/subscribe/clashMeta/*
|
||
rm -rf /etc/v2ray-agent/subscribe_local/default/*
|
||
rm -rf /etc/v2ray-agent/subscribe_local/clashMeta/*
|
||
rm -rf /etc/v2ray-agent/subscribe_local/sing-box/*
|
||
showAccounts >/dev/null
|
||
if [[ -n $(ls /etc/v2ray-agent/subscribe_local/default/) ]]; then
|
||
if [[ -f "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" && -n $(cat "/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl") ]]; then
|
||
if [[ -z "${renewSalt}" ]]; then
|
||
read -r -p "Other subscriptions found. Update them? [y/n]" updateOtherSubscribeStatus
|
||
else
|
||
updateOtherSubscribeStatus=y
|
||
fi
|
||
fi
|
||
local subscribePortLocal="${subscribePort}"
|
||
find /etc/v2ray-agent/subscribe_local/default/* | while read -r email; do
|
||
email=$(echo "${email}" | awk -F "[d][e][f][a][u][l][t][/]" '{print $2}')
|
||
|
||
# md5 encryption
|
||
local emailMd5=
|
||
emailMd5=$(echo -n "${email}${subscribeSalt}"$'\n' | md5sum | awk '{print $1}')
|
||
|
||
cat "/etc/v2ray-agent/subscribe_local/default/${email}" >>"/etc/v2ray-agent/subscribe/default/${emailMd5}"
|
||
if [[ "${updateOtherSubscribeStatus}" == "y" ]]; then
|
||
updateRemoteSubscribe "${emailMd5}" "${email}"
|
||
fi
|
||
local base64Result
|
||
base64Result=$(base64 -w 0 "/etc/v2ray-agent/subscribe/default/${emailMd5}")
|
||
echo "${base64Result}" >"/etc/v2ray-agent/subscribe/default/${emailMd5}"
|
||
echoContent yellow "--------------------------------------------------------------"
|
||
local currentDomain=${currentHost}
|
||
|
||
if [[ -n "${currentDefaultPort}" && "${currentDefaultPort}" != "443" ]]; then
|
||
currentDomain="${currentHost}:${currentDefaultPort}"
|
||
fi
|
||
if [[ -n "${subscribePortLocal}" ]]; then
|
||
if [[ "${subscribeType}" == "http" ]]; then
|
||
currentDomain="$(getPublicIP):${subscribePort}"
|
||
else
|
||
currentDomain="${currentHost}:${subscribePort}"
|
||
fi
|
||
fi
|
||
if [[ -z "${showStatus}" ]]; then
|
||
echoContent skyBlue "\nFunction 1/1: reality uninstall"
|
||
echoContent green "email:${email}\n"
|
||
echoContent yellow "url:${subscribeType}://${currentDomain}/s/default/${emailMd5}\n"
|
||
echoContent yellow "2.Remove"
|
||
if [[ "${release}" != "alpine" ]]; then
|
||
echo "${subscribeType}://${currentDomain}/s/default/${emailMd5}" | qrencode -s 10 -m 1 -t UTF8
|
||
fi
|
||
|
||
# clashMeta
|
||
#clashMeta
|
||
if [[ -f "/etc/v2ray-agent/subscribe_local/clashMeta/${email}" ]]; then
|
||
|
||
cat "/etc/v2ray-agent/subscribe_local/clashMeta/${email}" >>"/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}"
|
||
|
||
sed -i '1i\proxies:' "/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}"
|
||
|
||
local clashProxyUrl="${subscribeType}://${currentDomain}/s/clashMeta/${emailMd5}"
|
||
clashMetaConfig "${clashProxyUrl}" "${emailMd5}"
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: Account Management"
|
||
echoContent yellow "url:${subscribeType}://${currentDomain}/s/clashMetaProfiles/${emailMd5}\n"
|
||
echoContent yellow "#Notes:"
|
||
if [[ "${release}" != "alpine" ]]; then
|
||
echo "${subscribeType}://${currentDomain}/s/clashMetaProfiles/${emailMd5}" | qrencode -s 10 -m 1 -t UTF8
|
||
fi
|
||
|
||
fi
|
||
# sing-box
|
||
if [[ -f "/etc/v2ray-agent/subscribe_local/sing-box/${email}" ]]; then
|
||
cp "/etc/v2ray-agent/subscribe_local/sing-box/${email}" "/etc/v2ray-agent/subscribe/sing-box_profiles/${emailMd5}"
|
||
|
||
echoContent skyBlue "\n====================== Add other machine subscriptions==================== ==="
|
||
if [[ "${release}" == "alpine" ]]; then
|
||
wget -O "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}" -q "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/documents/sing-box.json"
|
||
else
|
||
wget -O "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}" -q "${wgetShowProgressStatus}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/documents/sing-box.json"
|
||
fi
|
||
|
||
jq ".outbounds=$(jq ".outbounds|map(if has(\"outbounds\") then .outbounds += $(jq ".|map(.tag)" "/etc/v2ray-agent/subscribe_local/sing-box/${email}") else . end)" "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}")" "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}" >"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp" && mv "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp" "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}"
|
||
jq ".outbounds += $(jq '.' "/etc/v2ray-agent/subscribe_local/sing-box/${email}")" "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}" >"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp" && mv "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp" "/etc/v2ray-agent/subscribe/sing-box/${emailMd5}"
|
||
|
||
echoContent skyBlue "Input example: www.v2ray-agent.com:443:vps1\n"
|
||
echoContent yellow "url:${subscribeType}://${currentDomain}/s/sing-box/${emailMd5}\n"
|
||
echoContent yellow "Please read the following article carefully: https://www.v2ray-agent.com/archives/1681804748677"
|
||
if [[ "${release}" != "alpine" ]]; then
|
||
echo "${subscribeType}://${currentDomain}/s/sing-box/${emailMd5}" | qrencode -s 10 -m 1 -t UTF8
|
||
fi
|
||
|
||
fi
|
||
|
||
echoContent skyBlue "--------------------------------------------------------------"
|
||
else
|
||
echoContent green " ---> Domain whitelist added successfully"
|
||
fi
|
||
|
||
done
|
||
fi
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
fi
|
||
}
|
||
|
||
# Update remote subscription
|
||
updateRemoteSubscribe() {
|
||
|
||
local emailMD5=$1
|
||
local email=$2
|
||
while read -r line; do
|
||
local subscribeType=
|
||
subscribeType="https"
|
||
|
||
local serverAlias=
|
||
serverAlias=$(echo "${line}" | awk -F "[:]" '{print $3}')
|
||
|
||
local remoteUrl=
|
||
remoteUrl=$(echo "${line}" | awk -F "[:]" '{print $1":"$2}')
|
||
|
||
local subscribeTypeRemote=
|
||
subscribeTypeRemote=$(echo "${line}" | awk -F "[:]" '{print $4}')
|
||
|
||
if [[ -n "${subscribeTypeRemote}" ]]; then
|
||
subscribeType="${subscribeTypeRemote}"
|
||
fi
|
||
local clashMetaProxies=
|
||
|
||
clashMetaProxies=$(curl -s "${subscribeType}://${remoteUrl}/s/clashMeta/${emailMD5}" | sed '/proxies:/d' | sed "s/\"${email}/\"${email}_${serverAlias}/g")
|
||
|
||
if ! echo "${clashMetaProxies}" | grep -q "nginx" && [[ -n "${clashMetaProxies}" ]]; then
|
||
echo "${clashMetaProxies}" >>"/etc/v2ray-agent/subscribe/clashMeta/${emailMD5}"
|
||
echoContent green " ---> Added successfully"
|
||
else
|
||
echoContent red " ---> Wrong selection"
|
||
fi
|
||
|
||
local default=
|
||
default=$(curl -s "${subscribeType}://${remoteUrl}/s/default/${emailMD5}")
|
||
|
||
if ! echo "${default}" | grep -q "nginx" && [[ -n "${default}" ]]; then
|
||
default=$(echo "${default}" | base64 -d | sed "s/#${email}/#${email}_${serverAlias}/g")
|
||
echo "${default}" >>"/etc/v2ray-agent/subscribe/default/${emailMD5}"
|
||
|
||
echoContent green " ---> WARP global outbound setting successful"
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
fi
|
||
|
||
local singBoxSubscribe=
|
||
singBoxSubscribe=$(curl -s "${subscribeType}://${remoteUrl}/s/sing-box_profiles/${emailMD5}")
|
||
|
||
if ! echo "${singBoxSubscribe}" | grep -q "nginx" && [[ -n "${singBoxSubscribe}" ]]; then
|
||
singBoxSubscribe=${singBoxSubscribe//tag\": \"${email}/tag\": \"${email}_${serverAlias}}
|
||
singBoxSubscribe=$(jq ". +=${singBoxSubscribe}" "/etc/v2ray-agent/subscribe_local/sing-box/${email}")
|
||
echo "${singBoxSubscribe}" | jq . >"/etc/v2ray-agent/subscribe_local/sing-box/${email}"
|
||
|
||
echoContent green " ---> Abandon settings"
|
||
else
|
||
echoContent red "\n================================================ ================="
|
||
fi
|
||
|
||
done < <(grep -v '^$' <"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl")
|
||
}
|
||
|
||
# switch alpn
|
||
switchAlpn() {
|
||
echoContent skyBlue "-------------------------Remarks--------------------- ----------"
|
||
if [[ -z ${currentAlpn} ]]; then
|
||
echoContent red "================================================== ==============="
|
||
exit 0
|
||
fi
|
||
|
||
echoContent red "\n=============================================================="
|
||
echoContent green " ---> WARP offload uninstall successful"
|
||
echoContent yellow "# Viewing subscriptions will regenerate local account subscriptions"
|
||
echoContent yellow "# When adding an account or modifying an account, you need to re-check the subscription before the subscription content for external access will be regenerated"
|
||
echoContent yellow "# Does not affect the content of added remote subscriptions\n"
|
||
echoContent red "=============================================================="
|
||
|
||
if [[ "${currentAlpn}" == "http/1.1" ]]; then
|
||
echoContent yellow "\n ---> Salt: ${subscribeSalt}"
|
||
elif [[ "${currentAlpn}" == "h2" ]]; then
|
||
echoContent yellow "--------------------------------------------------------------"
|
||
else
|
||
echoContent red " ---> IP acquisition failed, exit installation"
|
||
fi
|
||
|
||
echoContent red "=============================================================="
|
||
|
||
read -r -p "Please select:" selectSwitchAlpnType
|
||
if [[ "${selectSwitchAlpnType}" == "1" && "${currentAlpn}" == "http/1.1" ]]; then
|
||
|
||
local frontingTypeJSON
|
||
frontingTypeJSON=$(jq -r ".inbounds[0].streamSettings.tlsSettings.alpn = [\"h2\",\"http/1.1\"]" ${configPath}${frontingType}.json)
|
||
echo "${frontingTypeJSON}" | jq . >${configPath}${frontingType}.json
|
||
|
||
elif [[ "${selectSwitchAlpnType}" == "1" && "${currentAlpn}" == "h2" ]]; then
|
||
local frontingTypeJSON
|
||
frontingTypeJSON=$(jq -r ".inbounds[0].streamSettings.tlsSettings.alpn =[\"http/1.1\",\"h2\"]" ${configPath}${frontingType}.json)
|
||
echo "${frontingTypeJSON}" | jq . >${configPath}${frontingType}.json
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
exit 0
|
||
fi
|
||
reloadCore
|
||
}
|
||
|
||
#Initialize realityKey
|
||
initRealityKey() {
|
||
echoContent skyBlue "\n----------Default subscription----------\n"
|
||
if [[ -n "${currentRealityPublicKey}" && -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Read the last installation record. Do you want to use the PublicKey/PrivateKey from the last installation? [y/n]:" historyKeyStatus
|
||
if [[ "${historyKeyStatus}" == "y" ]]; then
|
||
realityPrivateKey=${currentRealityPrivateKey}
|
||
realityPublicKey=${currentRealityPublicKey}
|
||
fi
|
||
elif [[ -n "${currentRealityPublicKey}" && -n "${lastInstallationConfig}" ]]; then
|
||
realityPrivateKey=${currentRealityPrivateKey}
|
||
realityPublicKey=${currentRealityPublicKey}
|
||
fi
|
||
if [[ -z "${realityPrivateKey}" ]]; then
|
||
if [[ "${selectCoreType}" == "2" || "${coreInstallType}" == "2" ]]; then
|
||
realityX25519Key=$(/etc/v2ray-agent/sing-box/sing-box generate reality-keypair)
|
||
realityPrivateKey=$(echo "${realityX25519Key}" | head -1 | awk '{print $2}')
|
||
realityPublicKey=$(echo "${realityX25519Key}" | tail -n 1 | awk '{print $2}')
|
||
echo "publicKey:${realityPublicKey}" >/etc/v2ray-agent/sing-box/conf/config/reality_key
|
||
else
|
||
read -r -p "Enter Private Key [Enter to generate automatically]:" historyPrivateKey
|
||
if [[ -n "${historyPrivateKey}" ]]; then
|
||
realityX25519Key=$(/etc/v2ray-agent/xray/xray x25519 -i "${historyPrivateKey}")
|
||
else
|
||
realityX25519Key=$(/etc/v2ray-agent/xray/xray x25519)
|
||
fi
|
||
realityPrivateKey=$(echo "${realityX25519Key}" | grep "PrivateKey" | awk '{print $2}')
|
||
realityPublicKey=$(echo "${realityX25519Key}" | grep "Password" | awk '{print $3}')
|
||
if [[ -z "${realityPrivateKey}" ]]; then
|
||
echoContent red " ---> Wrong selection"
|
||
initRealityKey
|
||
else
|
||
echoContent green "\n privateKey:${realityPrivateKey}"
|
||
echoContent green "\n publicKey:${realityPublicKey}"
|
||
fi
|
||
fi
|
||
fi
|
||
}
|
||
initRealityMldsa65() {
|
||
echoContent skyBlue "\n----------clashMeta subscription----------\n"
|
||
if /etc/v2ray-agent/xray/xray tls ping "${realityServerName}:${realityDomainPort}" 2>/dev/null | grep -q "X25519MLKEM768"; then
|
||
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 "${currentRealityMldsa65Seed}" && -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Previous Seed/Verify values found. Use them? [y/n]:" historyMldsa65Status
|
||
if [[ "${historyMldsa65Status}" == "y" ]]; then
|
||
realityMldsa65Seed=${currentRealityMldsa65Seed}
|
||
realityMldsa65Verify=${currentRealityMldsa65Verify}
|
||
fi
|
||
elif [[ -n "${currentRealityMldsa65Seed}" && -n "${lastInstallationConfig}" ]]; then
|
||
realityMldsa65Seed=${currentRealityMldsa65Seed}
|
||
realityMldsa65Verify=${currentRealityMldsa65Verify}
|
||
fi
|
||
if [[ -z "${realityMldsa65Seed}" ]]; then
|
||
# if [[ "${selectCoreType}" == "2" || "${coreInstallType}" == "2" ]]; then
|
||
# realityX25519Key=$(/etc/v2ray-agent/sing-box/sing-box generate reality-keypair)
|
||
# realityPrivateKey=$(echo "${realityX25519Key}" | head -1 | awk '{print $2}')
|
||
# realityPublicKey=$(echo "${realityX25519Key}" | tail -n 1 | awk '{print $2}')
|
||
# echo "publicKey:${realityPublicKey}" >/etc/v2ray-agent/sing-box/conf/config/reality_key
|
||
# else
|
||
realityMldsa65=$(/etc/v2ray-agent/xray/xray mldsa65)
|
||
realityMldsa65Seed=$(echo "${realityMldsa65}" | head -1 | awk '{print $2}')
|
||
realityMldsa65Verify=$(echo "${realityMldsa65}" | tail -n 1 | awk '{print $2}')
|
||
# fi
|
||
fi
|
||
# echoContent green "\n Seed:${realityMldsa65Seed}"
|
||
# echoContent green "\n Verify:${realityMldsa65Verify}"
|
||
else
|
||
echoContent green " ---> Added successfully"
|
||
fi
|
||
else
|
||
echoContent green " ---> WARP global outbound setting successful"
|
||
fi
|
||
}
|
||
# Check whether the reality domain name matches
|
||
checkRealityDest() {
|
||
local traceResult=
|
||
traceResult=$(curl -s "https://$(echo "${realityDestDomain}" | cut -d ':' -f 1)/cdn-cgi/trace" | grep "visit_scheme=https")
|
||
if [[ -n "${traceResult}" ]]; then
|
||
echoContent red "\n================================================ ================="
|
||
read -r -p "Continue? [y/n]" setRealityDestStatus
|
||
if [[ "${setRealityDestStatus}" != 'y' ]]; then
|
||
exit 0
|
||
fi
|
||
echoContent yellow "url:https://${currentDomain}/s/default/${emailMd5}\n"
|
||
fi
|
||
}
|
||
|
||
# Initialize the ServersName available to the client
|
||
initRealityClientServersName() {
|
||
local realityDestDomainList=
|
||
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,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
|
||
read -r -p "Previous Reality server name found. Use it? [y/n]:" realityServerNameStatus
|
||
if [[ "${realityServerNameStatus}" != "y" ]]; then
|
||
realityServerName=
|
||
realityDomainPort=
|
||
fi
|
||
else
|
||
realityServerName=
|
||
realityDomainPort=
|
||
fi
|
||
elif [[ -n "${realityServerName}" && -z "${lastInstallationConfig}" ]]; then
|
||
realityServerName=
|
||
realityDomainPort=
|
||
fi
|
||
|
||
if [[ -z "${realityServerName}" ]]; then
|
||
if [[ -n "${domain}" ]]; then
|
||
echo
|
||
read -r -p "Use ${domain} as the Reality target domain? [y/n]:" realityServerNameCurrentDomainStatus
|
||
if [[ "${realityServerNameCurrentDomainStatus}" == "y" ]]; then
|
||
realityServerName="${domain}"
|
||
if [[ "${selectCoreType}" == "1" ]]; then
|
||
if [[ -z "${subscribePort}" ]]; then
|
||
echo
|
||
installSubscribe
|
||
readNginxSubscribe
|
||
realityDomainPort="${subscribePort}"
|
||
else
|
||
realityDomainPort="${subscribePort}"
|
||
fi
|
||
fi
|
||
if [[ "${selectCoreType}" == "2" ]]; then
|
||
if [[ -z "${subscribePort}" ]]; then
|
||
echo
|
||
installSubscribe
|
||
readNginxSubscribe
|
||
realityDomainPort="${subscribePort}"
|
||
else
|
||
realityDomainPort="${subscribePort}"
|
||
fi
|
||
fi
|
||
fi
|
||
fi
|
||
if [[ -z "${realityServerName}" ]]; then
|
||
realityDomainPort=443
|
||
echoContent skyBlue "------------------------------------------------- ---------------"
|
||
echoContent yellow "Online QR code: https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=https://${currentDomain}/s/default/${emailMd5}\n "
|
||
echoContent green " ---> Abandon settings"
|
||
echoContent yellow "url:https://${currentDomain}/s/clashMetaProfiles/${emailMd5}\n"
|
||
read -r -p "Enter target domain [Enter for random; default port 443]:" realityServerName
|
||
if [[ -z "${realityServerName}" ]]; then
|
||
count=$(echo ${realityDestDomainList} | awk -F',' '{print NF}')
|
||
randomNum=$(randomNum 1 "${count}")
|
||
|
||
realityServerName=$(echo "${realityDestDomainList}" | awk -F ',' -v randomNum="$randomNum" '{print $randomNum}')
|
||
fi
|
||
if echo "${realityServerName}" | grep -q ":"; then
|
||
realityDomainPort=$(echo "${realityServerName}" | awk -F "[:]" '{print $2}')
|
||
realityServerName=$(echo "${realityServerName}" | awk -F "[:]" '{print $1}')
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
echoContent yellow "Online QR code: https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=https://${currentDomain}/s/clashMetaProfiles/${emailMd5}\n "
|
||
}
|
||
initXrayRealityPort() {
|
||
if [[ -n "${xrayVLESSRealityPort}" && -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Read the last installation record. Do you want to use the port from the last installation? [y/n]:" historyRealityPortStatus
|
||
if [[ "${historyRealityPortStatus}" == "y" ]]; then
|
||
realityPort=${xrayVLESSRealityPort}
|
||
fi
|
||
elif [[ -n "${xrayVLESSRealityPort}" && -n "${lastInstallationConfig}" ]]; then
|
||
realityPort=${xrayVLESSRealityPort}
|
||
fi
|
||
|
||
# todo Read the VLESS_TLS_Vision port and prompt whether to use it. There may be ambiguity here
|
||
if [[ -z "${realityPort}" ]]; then
|
||
# if [[ -n "${port}" ]]; then
|
||
# if [[ "${realityPortTLSVisionStatus}" == "y" ]]; then
|
||
# realityPort=${port}
|
||
# fi
|
||
# fi
|
||
# if [[ -z "${realityPort}" ]]; then
|
||
echoContent yellow "1.When http/1.1 is the first, trojan is available, and some gRPC clients are available [the client supports manual selection of alpn]"
|
||
|
||
read -r -p "port:" realityPort
|
||
if [[ -z "${realityPort}" ]]; then
|
||
realityPort=$((RANDOM % 20001 + 10000))
|
||
fi
|
||
# fi
|
||
if [[ -n "${realityPort}" && "${xrayVLESSRealityPort}" == "${realityPort}" ]]; then
|
||
handleXray stop
|
||
else
|
||
checkPort "${realityPort}"
|
||
fi
|
||
fi
|
||
if [[ -z "${realityPort}" ]]; then
|
||
initXrayRealityPort
|
||
else
|
||
allowPort "${realityPort}"
|
||
echoContent yellow "2.When h2 is the first, gRPC is available, and some trojan clients are available [the client supports manual selection of alpn]"
|
||
fi
|
||
|
||
}
|
||
initXrayXHTTPort() {
|
||
if [[ -n "${xrayVLESSRealityXHTTPort}" && -z "${lastInstallationConfig}" ]]; then
|
||
read -r -p "Previous installation port found. Use it? [y/n]:" historyXHTTPortStatus
|
||
if [[ "${historyXHTTPortStatus}" == "y" ]]; then
|
||
xHTTPort=${xrayVLESSRealityXHTTPort}
|
||
fi
|
||
elif [[ -n "${xrayVLESSRealityXHTTPort}" && -n "${lastInstallationConfig}" ]]; then
|
||
xHTTPort=${xrayVLESSRealityXHTTPort}
|
||
fi
|
||
|
||
if [[ -z "${xHTTPort}" ]]; then
|
||
|
||
echoContent yellow "3.If the client does not support manual alpn replacement, it is recommended to use this function to change the server alpn order to use the corresponding protocol"
|
||
read -r -p "Port:" xHTTPort
|
||
if [[ -z "${xHTTPort}" ]]; then
|
||
xHTTPort=$((RANDOM % 20001 + 10000))
|
||
fi
|
||
if [[ -n "${xHTTPort}" && "${xrayVLESSRealityXHTTPort}" == "${xHTTPort}" ]]; then
|
||
handleXray stop
|
||
else
|
||
checkPort "${xHTTPort}"
|
||
fi
|
||
fi
|
||
if [[ -z "${xHTTPort}" ]]; then
|
||
initXrayXHTTPort
|
||
else
|
||
allowPort "${xHTTPort}"
|
||
allowPort "${xHTTPort}" "udp"
|
||
echoContent yellow "1.Switch alpn h2 first"
|
||
fi
|
||
}
|
||
|
||
#realitymanagement
|
||
manageReality() {
|
||
readInstallProtocolType
|
||
readConfigHostPathUUID
|
||
readCustomPort
|
||
readSingBoxConfig
|
||
|
||
if ! echo "${currentInstallProtocolType}" | grep -q -E "7,|8," || [[ -z "${coreInstallType}" ]]; then
|
||
echoContent red "\n================================================ ============ ====="
|
||
exit 0
|
||
fi
|
||
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
selectCustomInstallType=",7,"
|
||
initXrayConfig custom 1 true
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
if echo "${currentInstallProtocolType}" | grep -q ",7,"; then
|
||
selectCustomInstallType=",7,"
|
||
fi
|
||
if echo "${currentInstallProtocolType}" | grep -q ",8,"; then
|
||
selectCustomInstallType="${selectCustomInstallType},8,"
|
||
fi
|
||
initSingBoxConfig custom 1 true
|
||
fi
|
||
|
||
reloadCore
|
||
subscribe false
|
||
}
|
||
|
||
installRealityScanner() {
|
||
if [[ ! -f "/etc/v2ray-agent/xray/reality_scan/RealiTLScanner-linux-64" ]]; then
|
||
version=$(curl -s https://api.github.com/repos/XTLS/RealiTLScanner/releases?per_page=1 | jq -r '.[]|.tag_name')
|
||
wget -c -q -P /etc/v2ray-agent/xray/reality_scan/ "https://github.com/XTLS/RealiTLScanner/releases/download/${version}/RealiTLScanner-linux-64"
|
||
chmod 655 /etc/v2ray-agent/xray/reality_scan/RealiTLScanner-linux-64
|
||
fi
|
||
}
|
||
# reality scanner
|
||
realityScanner() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress}: switch alpn"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "1.Switch alpn http/1.1 first"
|
||
echoContent yellow "\n --->Ignore the risks and continue using"
|
||
echoContent red "\n================================================ ================="
|
||
echoContent yellow "\n ---> Fallback domain name: ${realityDestDomain}"
|
||
echoContent yellow "#Notes"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Select:" realityScannerStatus
|
||
local type=
|
||
if [[ "${realityScannerStatus}" == "1" ]]; then
|
||
type=4
|
||
elif [[ "${realityScannerStatus}" == "2" ]]; then
|
||
type=6
|
||
fi
|
||
|
||
read -r -p "Some providers disallow scanning (for example Bandwagon). Continue at your own risk? [y/n]:" scanStatus
|
||
|
||
if [[ "${scanStatus}" != "y" ]]; then
|
||
exit 0
|
||
fi
|
||
|
||
publicIP=$(getPublicIP "${type}")
|
||
echoContent yellow "IP:${publicIP}"
|
||
if [[ -z "${publicIP}" ]]; then
|
||
echoContent red "\n================================================ ================="
|
||
exit 0
|
||
fi
|
||
|
||
read -r -p "Is the IP address correct? [y/n]:" ipStatus
|
||
if [[ "${ipStatus}" == "y" ]]; then
|
||
echoContent yellow "Input example: addons.mozilla.org\n"
|
||
/etc/v2ray-agent/xray/reality_scan/RealiTLScanner-linux-64 -addr "${publicIP}" | tee /etc/v2ray-agent/xray/reality_scan/result.log
|
||
else
|
||
echoContent red "================================================== ==============="
|
||
fi
|
||
}
|
||
# hysteriaadmin
|
||
manageHysteria() {
|
||
echoContent skyBlue "\n========================== Generate key ================= =========\n"
|
||
echoContent red "\n=============================================================="
|
||
local hysteria2Status=
|
||
if [[ -n "${singBoxConfigPath}" ]] && [[ -f "/etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json" ]]; then
|
||
echoContent yellow "\n ---> Available client domain names: ${realityServerNames}\n"
|
||
echoContent yellow "Please enter the port [Enter random 10000-30000]"
|
||
echoContent yellow "\n ---> Port: ${realityPort}"
|
||
echoContent yellow "1.Reinstall"
|
||
hysteria2Status=true
|
||
else
|
||
echoContent yellow "2.Uninstall"
|
||
echoContent yellow "3.Change configuration"
|
||
fi
|
||
|
||
echoContent red "=============================================================="
|
||
read -r -p "Select:" installHysteria2Status
|
||
if [[ "${installHysteria2Status}" == "1" ]]; then
|
||
singBoxHysteria2Install
|
||
elif [[ "${installHysteria2Status}" == "2" && "${hysteria2Status}" == "true" ]]; then
|
||
unInstallSingBox hysteria2
|
||
elif [[ "${installHysteria2Status}" == "3" && "${hysteria2Status}" == "true" ]]; then
|
||
portHoppingMenu hysteria2
|
||
fi
|
||
}
|
||
|
||
#tuicadmin
|
||
manageTuic() {
|
||
echoContent skyBlue "\n====== Generate a domain name with fallback configuration , for example : [addons.mozilla.org:443] ======\n"
|
||
echoContent red "\n=============================================================="
|
||
local tuicStatus=
|
||
if [[ -n "${singBoxConfigPath}" ]] && [[ -f "/etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json" ]]; then
|
||
echoContent yellow "1.Installation"
|
||
echoContent yellow "1.Reinstall"
|
||
echoContent yellow "2.Uninstall"
|
||
echoContent yellow "3.Port jump management"
|
||
tuicStatus=true
|
||
else
|
||
echoContent yellow "4.core management"
|
||
echoContent yellow "5.View log"
|
||
fi
|
||
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" installTuicStatus
|
||
if [[ "${installTuicStatus}" == "1" ]]; then
|
||
singBoxTuicInstall
|
||
elif [[ "${installTuicStatus}" == "2" && "${tuicStatus}" == "true" ]]; then
|
||
unInstallSingBox tuic
|
||
elif [[ "${installTuicStatus}" == "3" && "${tuicStatus}" == "true" ]]; then
|
||
portHoppingMenu tuic
|
||
fi
|
||
}
|
||
singBoxLog() {
|
||
cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/log.json
|
||
{
|
||
"log": {
|
||
"disabled": $1,
|
||
"level": "debug",
|
||
"output": "/etc/v2ray-agent/sing-box/conf/box.log",
|
||
"timestamp": true
|
||
}
|
||
}
|
||
EOF
|
||
|
||
handleSingBox stop
|
||
handleSingBox start
|
||
}
|
||
|
||
singBoxVersionManageMenu() {
|
||
echoContent skyBlue "\n================ Configure serverNames available to the client ================\n"
|
||
if [[ -z "${singBoxConfigPath}" ]]; then
|
||
echoContent red " ---> Domain name cannot be empty"
|
||
menu
|
||
exit 0
|
||
fi
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "1.Installation"
|
||
echoContent yellow "1.Reinstall"
|
||
echoContent yellow "2.Uninstall"
|
||
echoContent yellow "3.core management"
|
||
echoContent yellow "=============================================================="
|
||
local logStatus=
|
||
if [[ -n "${singBoxConfigPath}" && -f "${singBoxConfigPath}log.json" && "$(jq -r .log.disabled "${singBoxConfigPath}log.json")" == "false" ]]; then
|
||
echoContent yellow "4.View log"
|
||
logStatus=true
|
||
else
|
||
echoContent yellow "1.Installation"
|
||
logStatus=false
|
||
fi
|
||
|
||
echoContent yellow "1.Upgrade Hysteria"
|
||
echoContent red "=============================================================="
|
||
|
||
read -r -p "Select:" selectSingBoxType
|
||
if [[ ! -f "${singBoxConfigPath}../box.log" ]]; then
|
||
touch "${singBoxConfigPath}../box.log" >/dev/null 2>&1
|
||
fi
|
||
if [[ "${selectSingBoxType}" == "1" ]]; then
|
||
installSingBox 1
|
||
handleSingBox stop
|
||
handleSingBox start
|
||
elif [[ "${selectSingBoxType}" == "2" ]]; then
|
||
handleSingBox stop
|
||
elif [[ "${selectSingBoxType}" == "3" ]]; then
|
||
handleSingBox start
|
||
elif [[ "${selectSingBoxType}" == "4" ]]; then
|
||
handleSingBox stop
|
||
handleSingBox start
|
||
elif [[ "${selectSingBoxType}" == "5" ]]; then
|
||
singBoxLog ${logStatus}
|
||
if [[ "${logStatus}" == "false" ]]; then
|
||
tail -f "${singBoxConfigPath}../box.log"
|
||
fi
|
||
elif [[ "${selectSingBoxType}" == "6" ]]; then
|
||
tail -f "${singBoxConfigPath}../box.log"
|
||
fi
|
||
}
|
||
|
||
# main menu
|
||
menu() {
|
||
cd "$HOME" || exit
|
||
echoContent red "\n=============================================================="
|
||
echoContent green " ---> WARP offload uninstall successful"
|
||
echoContent green " ---> Added shunt successfully"
|
||
echoContent green "Github:https://github.com/mack-a/v2ray-agent"
|
||
echoContent green " ---> Add any door to divert successfully"
|
||
showInstallStatus
|
||
checkWgetShowProgress
|
||
echoContent red " ---> Port cannot be empty"
|
||
echoContent red " "
|
||
echoContent yellow "2.Close Hysteria"
|
||
echoContent green "https://www.v2ray-agent.com/archives/1679975663984"
|
||
echoContent yellow "3.Open Hysteria"
|
||
echoContent green "https://www.v2ray-agent.com/archives/racknerdtao-can-zheng-li-nian-fu-10mei-yuan"
|
||
echoContent yellow "4.Restart Hysteria"
|
||
echoContent green "https://www.v2ray-agent.com/archives/186cee7b-9459-4e57-b9b2-b07a4f36931c"
|
||
echoContent yellow "1.Upgrade Tuic"
|
||
echoContent red " "
|
||
echoContent red "=============================================================="
|
||
if [[ -n "${coreInstallType}" ]]; then
|
||
echoContent yellow "2.Close Tuic"
|
||
else
|
||
echoContent yellow "3.Open Tuic"
|
||
fi
|
||
|
||
echoContent yellow "4.Restart Tuic"
|
||
echoContent yellow "1.Reinstall"
|
||
echoContent yellow "1.Installation"
|
||
echoContent yellow "2.Install in any combination"
|
||
echoContent yellow "3.Switch VLESS[XTLS]"
|
||
|
||
echoContent skyBlue "\nProgress$1/${totalProgress}: Initializing Xray-core reality configuration"
|
||
echoContent yellow "3.Switch Trojan[XTLS]"
|
||
echoContent yellow "4.Hysteria Management"
|
||
echoContent yellow "5.REALITY Management"
|
||
echoContent yellow "6.Tuic Management"
|
||
echoContent yellow "7.Account management"
|
||
echoContent yellow "8.Change the camouflage station"
|
||
echoContent yellow "9.Update certificate"
|
||
echoContent yellow "10.Change CDN node"
|
||
echoContent skyBlue "\nProgress 1/1: reality management"
|
||
echoContent yellow "11.Diversion tool"
|
||
echoContent yellow "12.Add new port"
|
||
echoContent yellow "13.BT download management"
|
||
echoContent skyBlue "\nProgress 1/1: Hysteria Management"
|
||
echoContent yellow "14.Switch alpn"
|
||
echoContent red "=============================================================="
|
||
mkdirTools
|
||
aliasInstall
|
||
read -r -p "Please select:" selectInstallType
|
||
case ${selectInstallType} in
|
||
1)
|
||
selectCoreInstall
|
||
;;
|
||
2)
|
||
selectCoreInstall
|
||
;;
|
||
3)
|
||
selectCoreInstall
|
||
;;
|
||
4)
|
||
manageHysteria
|
||
;;
|
||
5)
|
||
manageReality 1
|
||
;;
|
||
6)
|
||
manageTuic
|
||
;;
|
||
7)
|
||
manageAccount 1
|
||
;;
|
||
8)
|
||
updateNginxBlog 1
|
||
;;
|
||
9)
|
||
renewalTLS 1
|
||
;;
|
||
10)
|
||
manageCDN 1
|
||
;;
|
||
11)
|
||
routingToolsMenu 1
|
||
;;
|
||
12)
|
||
addCorePort 1
|
||
;;
|
||
13)
|
||
btTools 1
|
||
;;
|
||
14)
|
||
switchAlpn 1
|
||
;;
|
||
15)
|
||
blacklist 1
|
||
;;
|
||
16)
|
||
coreVersionManageMenu 1
|
||
;;
|
||
17)
|
||
updateV2RayAgent 1
|
||
;;
|
||
18)
|
||
bbrInstall
|
||
;;
|
||
20)
|
||
unInstall 1
|
||
;;
|
||
esac
|
||
}
|
||
cronFunction
|
||
menu
|