v2ray-agent/shell/install_en.sh

8012 lines
293 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env bash
# Detection area
#------------------------------------------------ ----------
# Check system
export LANG=en_US.UTF-8
echoContent() {
case $1 in
# red
"red")
# 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 [[ -f "/etc/selinux/config" ]] && ! grep -q "SELINUX=disabled" <"/etc/selinux/config"; 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/1679931532764#heading-8 "
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 </etc/issue -q -i "debian" || [[ -f "/proc/version" ]] && grep </etc/issue -q -i "debian" || [[ -f "/etc/os-release" ]] && grep </etc/os-release -q -i "ID=debian"; 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 </etc/issue -q -i "ubuntu" || [[ -f "/proc/version" ]] && grep </etc/issue -q -i "ubuntu"; 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"
hysteriaCoreCPUVendor="hysteria-linux-amd64"
tuicCoreCPUVendor="-x86_64-unknown-linux-musl"
warpRegCoreCPUVendor="main-linux-amd64"
;;
'armv8' | 'aarch64')
cpuVendor="arm"
xrayCoreCPUVendor="Xray-linux-arm64-v8a"
v2rayCoreCPUVendor="v2ray-linux-arm64-v8a"
hysteriaCoreCPUVendor="hysteria-linux-arm64"
tuicCoreCPUVendor="-aarch64-unknown-linux-musl"
warpRegCoreCPUVendor="main-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'
#CPU version supported by the core
xrayCoreCPUVendor=""
v2rayCoreCPUVendor=""
hysteriaCoreCPUVendor=""
warpRegCoreCPUVendor=""
cpuVendor=""
# domain name
domain=
#Address of CDN node
add=
# Total installation progress
totalProgress=1
#1.xray-core installation
#2.v2ray-core installation
#3.v2ray-core[xtls] installation
coreInstallType=
# Core installation path
# coreInstallPath=
# v2ctl Path
ctlPath=
#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=
# Path to hysteria configuration file
hysteriaConfigPath=
# interfaceName=
# Port hopping
portHoppingStart=
portHoppingEnd=
portHopping=
# tuic configuration file path
tuicConfigPath=
tuicAlgorithm=
tuicPort=
# Path to configuration file
currentPath=
#Configuration file host
currentHost=
#The core type selected during installation
selectCoreType=
#Default core version
v2rayCoreVersion=
# Random path
customPath=
# centos version
centosVersion=
#UUID
currentUUID=
#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=
#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=
#sslmail
sslEmail=
# Check the number of days
sslRenewalDays=90
# dns ssl status
dnsSSLStatus=
# dns tls domain
dnsTLSDomain=
# Whether the domain name installs a wildcard certificate through dns
installDNSACMEStatus=
# Custom port
customPort=
#hysteriaport
hysteriaPort=
#hysteriaprotocol
hysteriaProtocol=
#hysteriadelay
hysteriaLag=
# hysteriadownload speed
hysteriaClientDownloadSpeed=
# hysteria uplink speed
hysteriaClientUploadSpeed=
#Reality
realityPrivateKey=
realityServerNames=
realityDestDomain=
#Port status
# isPortOpen=
# Wildcard domain name status
# wildcardDomainStatus=
# Port checked by nginx
#nginxIPort=
# wget show progress
wgetShowProgressStatus=
#warp
reservedWarpReg=
publicKeyWarpReg=
addressWarpReg=
secretKeyWarpReg=
}
# Read tls certificate details
readAcmeTLS() {
if [[ -n "${currentHost}" ]]; then
dnsTLSDomain=$(echo "${currentHost}" | awk -F "[.]" '{print $(NF-1)"."$NF}')
fi
if [[ -d "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc" && -f "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.key" && -f "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer" ]]; then
installDNSACMEStatus=true
fi
}
# Read the default custom port
readCustomPort() {
if [[ -n "${configPath}" && -z "${realityStatus}" ]]; then
local port=
port=$(jq -r .inbounds[0].port "${configPath}${frontingType}.json")
if [[ "${port}" != "443" ]]; then
customPort=${port}
fi
fi
}
# Detect installation method
readInstallType() {
coreInstallType=
configPath=
hysteriaConfigPath=
#1.Detect the installation directory
if [[ -d "/etc/v2ray-agent" ]]; then
# Detect installation method v2ray-core
if [[ -d "/etc/v2ray-agent/v2ray" && -f "/etc/v2ray-agent/v2ray/v2ray" && -f "/etc/v2ray-agent/v2ray/v2ctl" ]]; then
if [[ -d "/etc/v2ray-agent/v2ray/conf" && -f "/etc/v2ray-agent/v2ray/conf/02_VLESS_TCP_inbounds.json" ]]; then
configPath=/etc/v2ray-agent/v2ray/conf/
if grep </etc/v2ray-agent/v2ray/conf/02_VLESS_TCP_inbounds.json -q '"security": "tls"'; then
coreInstallType=2
ctlPath=/etc/v2ray-agent/v2ray/v2ctl
fi
fi
fi
if [[ -d "/etc/v2ray-agent/xray" && -f "/etc/v2ray-agent/xray/xray" ]]; then
# Detect xray-core here
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" ]]; then
#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=1
fi
fi
fi
if [[ -d "/etc/v2ray-agent/hysteria" && -f "/etc/v2ray-agent/hysteria/hysteria" ]]; then
# Detect hysteria here
if [[ -d "/etc/v2ray-agent/hysteria/conf" ]] && [[ -f "/etc/v2ray-agent/hysteria/conf/config.json" ]] && [[ -f "/etc/v2ray-agent/hysteria/conf/client_network.json" ]]; then
hysteriaConfigPath=/etc/v2ray-agent/hysteria/conf/
fi
fi
if [[ -d "/etc/v2ray-agent/tuic" && -f "/etc/v2ray-agent/tuic/tuic" ]]; then
if [[ -d "/etc/v2ray-agent/tuic/conf" ]] && [[ -f "/etc/v2ray-agent/tuic/conf/config.json" ]]; then
tuicConfigPath=/etc/v2ray-agent/tuic/conf/
fi
fi
fi
}
#Read protocol type
readInstallProtocolType() {
currentInstallProtocolType=
frontingType=
while read -r row; do
if echo "${row}" | grep -q 02_trojan_TCP_inbounds; then
currentInstallProtocolType=${currentInstallProtocolType}'trojan'
frontingType=02_trojan_TCP_inbounds
fi
if echo "${row}" | grep -q VLESS_TCP_inbounds; then
currentInstallProtocolType=${currentInstallProtocolType}'0'
frontingType=02_VLESS_TCP_inbounds
fi
if echo "${row}" | grep -q VLESS_WS_inbounds; then
currentInstallProtocolType=${currentInstallProtocolType}'1'
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'
fi
if echo "${row}" | grep -q 04_trojan_TCP_inbounds; then
currentInstallProtocolType=${currentInstallProtocolType}'4'
fi
if echo "${row}" | grep -q VLESS_gRPC_inbounds; then
currentInstallProtocolType=${currentInstallProtocolType}'5'
fi
if echo "${row}" | grep -q VLESS_vision_reality_inbounds; then
currentInstallProtocolType=${currentInstallProtocolType}'7'
fi
if echo "${row}" | grep -q VLESS_reality_fallback_grpc_inbounds; then
currentInstallProtocolType=${currentInstallProtocolType}'8'
fi
done < <(find ${configPath} -name "*inbounds.json" | awk -F "[.]" '{print $1}')
if [[ -n "${hysteriaConfigPath}" ]]; then
currentInstallProtocolType=${currentInstallProtocolType}'6'
fi
if [[ -n "${tuicConfigPath}" ]]; then
currentInstallProtocolType=${currentInstallProtocolType}'9'
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 "${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}/"
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
}
# Read the current alpn order
readInstallAlpn() {
if [[ -n "${currentInstallProtocolType}" && -z "${realityStatus}" ]]; then
local alpn
alpn=$(jq -r .inbounds[0].streamSettings.tlsSettings.alpn[0] ${configPath}${frontingType}.json)
if [[ -n ${alpn} ]]; then
currentAlpn=${alpn}
fi
fi
}
# Check firewall
allowPort() {
local type=$2
if [[ -z "${type}" ]]; then
type=tcp
fi
# If the firewall is enabled, add the corresponding open port
if 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
elif systemctl status ufw 2>/dev/null | grep -q "active (exited)"; 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 ":"; 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
fi
}
# Get public IP
getPublicIP() {
local type=4
if [[ -n "$1" ]]; then
type=$1
fi
if [[ -n "${currentHost}" && -n "${currentRealityServerNames}" && "${currentRealityServerNames}" == "${currentHost}" && -z "$1" ]]; 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 " ---> $1 port opening 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 port opening failed"
exit 0
fi
}
# Read hysteria network environment
readHysteriaConfig() {
if [[ -n "${hysteriaConfigPath}" ]]; then
hysteriaLag=$(jq -r .hysteriaLag <"${hysteriaConfigPath}client_network.json")
hysteriaClientDownloadSpeed=$(jq -r .hysteriaClientDownloadSpeed <"${hysteriaConfigPath}client_network.json")
hysteriaClientUploadSpeed=$(jq -r .hysteriaClientUploadSpeed <"${hysteriaConfigPath}client_network.json")
hysteriaPort=$(jq -r .listen <"${hysteriaConfigPath}config.json" | awk -F "[:]" '{print $2}')
hysteriaProtocol=$(jq -r .protocol <"${hysteriaConfigPath}config.json")
fi
}
# Read Tuic configuration
readTuicConfig() {
if [[ -n "${tuicConfigPath}" ]]; then
tuicPort=$(jq -r .server <"${tuicConfigPath}config.json" | cut -d ':' -f 4)
tuicAlgorithm=$(jq -r .congestion_control <"${tuicConfigPath}config.json")
fi
}
# Read xray reality configuration
readXrayCoreRealityConfig() {
currentRealityServerNames=
currentRealityPublicKey=
currentRealityPrivateKey=
currentRealityPort=
if [[ -n "${realityStatus}" ]]; then
currentRealityServerNames=$(jq -r .inbounds[0].streamSettings.realitySettings.serverNames[0] "${configPath}07_VLESS_vision_reality_inbounds.json")
currentRealityPublicKey=$(jq -r .inbounds[0].streamSettings.realitySettings.publicKey "${configPath}07_VLESS_vision_reality_inbounds.json")
currentRealityPrivateKey=$(jq -r .inbounds[0].streamSettings.realitySettings.privateKey "${configPath}07_VLESS_vision_reality_inbounds.json")
currentRealityPort=$(jq -r .inbounds[0].port "${configPath}07_VLESS_vision_reality_inbounds.json")
fi
}
# Check the file directory and path
readConfigHostPathUUID() {
currentPath=
currentDefaultPort=
currentUUID=
currentClients=
currentHost=
currentPort=
currentAdd=
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}')
currentAdd=$(jq -r .inbounds[0].add ${configPath}${frontingType}.json)
if [[ "${currentAdd}" == "null" ]]; then
currentAdd=${currentHost}
fi
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 [[ -n "${realityStatus}" && -z "${currentClients}" ]]; then
currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}07_VLESS_vision_reality_inbounds.json)
currentClients=$(jq -r .inbounds[0].settings.clients ${configPath}07_VLESS_vision_reality_inbounds.json)
fi
elif [[ "${coreInstallType}" == "2" ]]; 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}')
currentAdd=$(jq -r .inbounds[0].settings.clients[0].add ${configPath}${frontingType}.json)
if [[ "${currentAdd}" == "null" ]]; then
currentAdd=${currentHost}
fi
currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}${frontingType}.json)
currentPort=$(jq .inbounds[0].port ${configPath}${frontingType}.json)
fi
#Read path
if [[ -n "${configPath}" && -n "${frontingType}" ]]; 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
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
fi
}
# Status display
showInstallStatus() {
if [[ -n "${coreInstallType}" ]]; then
if [[ "${coreInstallType}" == 1 ]]; then
if [[ -n $(pgrep -f "xray/xray") ]]; then
echoContent yellow "\nCore: Xray-core[Running]"
else
echoContent yellow "\nCore: Xray-core[not running]"
fi
elif [[ "${coreInstallType}" == 2 || "${coreInstallType}" == 3 ]]; then
if [[ -n $(pgrep -f "v2ray/v2ray") ]]; then
echoContent yellow "\nCore: v2ray-core[Running]"
else
echoContent yellow "\nCore: v2ray-core[not running]"
fi
fi
#Read protocol type
readInstallProtocolType
if [[ -n ${currentInstallProtocolType} ]]; then
echoContent yellow "Installed protocol: \c"
fi
if echo ${currentInstallProtocolType} | grep -q 0; then
if [[ "${coreInstallType}" == 2 ]]; then
echoContent yellow "VLESS+TCP[TLS] \c"
else
echoContent yellow "VLESS+TCP[TLS_Vision] \c"
fi
fi
if echo ${currentInstallProtocolType} | grep -q trojan; then
if [[ "${coreInstallType}" == 1 ]]; then
echoContent yellow "Trojan+TCP[TLS_Vision] \c"
fi
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 7; then
echoContent yellow "VLESS+Reality+Vision \c"
fi
if echo ${currentInstallProtocolType} | grep -q 8; then
echoContent yellow "VLESS+Reality+gRPC \c"
fi
fi
}
# Clean up old residue
cleanUp() {
if [[ "$1" == "v2rayClean" ]]; then
rm -rf "$(find /etc/v2ray-agent/v2ray/* | grep -E '(config_full.json|conf)')"
handleV2Ray stop >/dev/null
rm -f /etc/systemd/system/v2ray.service
elif [[ "$1" == "xrayClean" ]]; then
rm -rf "$(find /etc/v2ray-agent/xray/* | grep -E '(config_full.json|conf)')"
handleXray stop >/dev/null
rm -f /etc/systemd/system/xray.service
elif [[ "$1" == "v2rayDel" ]]; then
rm -rf /etc/v2ray-agent/v2ray/*
elif [[ "$1" == "xrayDel" ]]; then
rm -rf /etc/v2ray-agent/xray/*
fi
}
initVar "$1"
checkSystem
checkCPUVendor
readInstallType
readInstallProtocolType
readConfigHostPathUUID
readInstallAlpn
readCustomPort
readXrayCoreRealityConfig
#------------------------------------------------ ----------
#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/v2ray/conf
mkdir -p /etc/v2ray-agent/v2ray/tmp
mkdir -p /etc/v2ray-agent/xray/conf
mkdir -p /etc/v2ray-agent/xray/tmp
mkdir -p /etc/v2ray-agent/hysteria/conf
mkdir -p /etc/systemd/system/
mkdir -p /tmp/v2ray-agent-tls/
mkdir -p /etc/v2ray-agent/warp
mkdir -p /etc/v2ray-agent/tuic/conf
}
# Install toolkit
installTools() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Installation tools"
# 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 " ---> 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]"
${upgrade} >/etc/v2ray-agent/install.log 2>&1
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
# [[ -z `find /usr/bin /usr/sbin |grep -v grep|grep -w curl` ]]
if ! find /usr/bin /usr/sbin | grep -q -w wget; then
echoContent green " ---> Install wget"
${installType} wget >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w curl; then
echoContent green " ---> Install curl"
${installType} curl >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w unzip; then
echoContent green " ---> install unzip"
${installType} unzip >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w socat; then
echoContent green " ---> Install socat"
${installType} socat >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w tar; then
echoContent green " ---> Install tar"
${installType} tar >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w cron; then
echoContent green " ---> install crontabs"
if [[ "${release}" == "ubuntu" ]] || [[ "${release}" == "debian" ]]; then
${installType} cron >/dev/null 2>&1
else
${installType} crontabs >/dev/null 2>&1
fi
fi
if ! find /usr/bin /usr/sbin | grep -q -w jq; then
echoContent green " ---> Install jq"
${installType} jq >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w binutils; then
echoContent green " ---> Install binutils"
${installType} binutils >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w ping6; then
echoContent green " ---> Install ping6"
${installType} inetutils-ping >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w qrencode; then
echoContent green " ---> Install qrencode"
${installType} qrencode >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w sudo; then
echoContent green " ---> install sudo"
${installType} sudo >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w lsb-release; then
echoContent green " ---> install lsb-release"
${installType} lsb-release >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w lsof; then
echoContent green " ---> Install lsof"
${installType} lsof >/dev/null 2>&1
fi
if ! find /usr/bin /usr/sbin | grep -q -w dig; then
echoContent green " ---> Install dig"
if echo "${installType} " | grep -q -w "apt"; then
${installType} dnsutils >/dev/null 2>&1
elif echo "${installType} " | grep -q -w "yum"; then
${installType} bind-utils >/dev/null 2>&1
fi
fi
# Detect nginx version and provide the option of uninstalling it
if [[ "${selectCustomInstallType}" == "7" ]]; then
echoContent green " ---> Detected services that do not depend on Nginx, skip installation"
else
if ! find /usr/bin /usr/sbin | grep -q -w nginx; then
echoContent green " ---> Install nginx"
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 " ---> nginx uninstall completed"
echoContent green " ---> Install nginx"
installNginxTools >/dev/null 2>&1
else
exit 0
fi
fi
fi
fi
if ! find /usr/bin /usr/sbin | grep -q -w semanage; then
echoContent green " ---> Install semanage"
${installType} bash-completion >/dev/null 2>&1
if [[ "${centosVersion}" == "7" ]]; then
policyCoreUtils="policycoreutils-python.x86_64"
elif [[ "${centosVersion}" == "8" ]]; then
policyCoreUtils="policycoreutils-python-utils-2.9-9.el8.noarch"
fi
if [[ -n "${policyCoreUtils}" ]]; then
${installType} ${policyCoreUtils} >/dev/null 2>&1
fi
if [[ -n $(which semanage) ]]; then
semanage port -a -t http_port_t -p tcp 31300
fi
fi
if [[ "${selectCustomInstallType}" == "7" ]]; then
echoContent green " ---> Detected services that do not depend on certificates, skip installation"
else
if [[ ! -d "$HOME/.acme.sh" ]] || [[ -d "$HOME/.acme.sh" && -z $(find "$HOME/.acme.sh/acme.sh") ]]; then
echoContent green " ---> Install acme.sh"
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 "acme installation failed--->"
tail -n 100 /etc/v2ray-agent/tls/acme.log
echoContent yellow "Error troubleshooting:"
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/]"
echoContent red "2.There is a bug in the acme.sh script, please check [https://github.com/acmesh-official/acme.sh] issues"
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 skyBlue " echo -e \"nameserver 2001:67c:2b0::4\\\nnameserver 2a00:1098:2c::1\" >> /etc/resolv.conf"
echoContent skyBlue "sed -i \"1i\\\nameserver 2001:67c:2b0::4\\\nnameserver 2a00:1098:2c::1\" /etc/resolv.conf"
exit 0
fi
fi
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
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
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
fi
${installType} nginx >/dev/null 2>&1
systemctl daemon-reload
systemctl enable nginx
}
# Install warp
installWarp() {
if [[ "${cpuVendor}" == "arm" ]]; then
echoContent red " ---> The official WARP client does not support ARM architecture"
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 " ---> Install WARP"
${installType} cloudflare-warp >/dev/null 2>&1
if [[ -z $(which warp-cli) ]]; then
echoContent red " ---> Failed to install WARP"
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 " ---> WARP started successfully"
fi
}
# Check the IP of the domain name through dns
checkDNSIP() {
local domain=$1
local dnsIP=
local type=4
dnsIP=$(dig @1.1.1.1 +time=1 +short "${domain}")
if [[ -z "${dnsIP}" ]]; then
dnsIP=$(dig @8.8.8.8 +time=1 +short "${domain}")
fi
if echo "${dnsIP}" | grep -q "timed out" || [[ -z "${dnsIP}" ]]; then
echo
echoContent red " ---> Unable to obtain domain name IPv4 address through DNS"
echoContent green " ---> Try to check the domain name IPv6 address"
dnsIP=$(dig @2606:4700:4700::1111 +time=1 aaaa +short "${domain}")
type=6
if echo "${dnsIP}" | grep -q "network unreachable" || [[ -z "${dnsIP}" ]]; then
echoContent red " ---> Unable to obtain domain name IPv6 address through DNS, exit installation"
exit 0
fi
fi
local publicIP=
publicIP=$(getPublicIP "${type}")
if [[ "${publicIP}" != "${dnsIP}" ]]; then
echoContent red " ---> The domain name resolution IP is inconsistent with the current server IP\n"
echoContent yellow " ---> Please check whether the domain name resolution is valid and correct"
echoContent green " ---> Current VPS IP: ${publicIP}"
echoContent green " ---> DNS resolution IP: ${dnsIP}"
exit 0
else
echoContent green " ---> Domain name IP verification passed"
fi
}
# Check the actual open status of the port
checkPortOpen() {
local port=$1
local domain=$2
local checkPortOpenResult=
allowPort "${port}"
#Initialize nginx configuration
touch ${nginxConfigPath}checkPortOpen.conf
cat <<EOF >${nginxConfigPath}checkPortOpen.conf
server {
listen ${port};
listen [::]:${port};
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
# Check domain name + port opening
checkPortOpenResult=$(curl -s -m 2 "http://${domain}:${port}/checkPort")
localIP=$(curl -s -m 2 "http://${domain}:${port}/ip")
rm "${nginxConfigPath}checkPortOpen.conf"
handleNginx stop
if [[ "${checkPortOpenResult}" == "fjkvymb6len" ]]; then
echoContent green " ---> Detected that ${port} port is open"
else
echoContent green " ---> No open ${port} port detected, exit installation"
if echo "${checkPortOpenResult}" | grep -q "cloudflare"; then
echoContent yellow " ---> Please close the cloud and wait three minutes to try again"
else
if [[ -z "${checkPortOpenResult}" ]]; then
echoContent red " ---> Please check if there is a web firewall, such as Oracle and other cloud service providers"
echoContent red " ---> Check whether you have installed nginx and there are configuration conflicts. You can try DD pure system and try again"
else
echoContent red " ---> Error log: ${checkPortOpenResult}, please submit feedback on this error log through issues"
fi
fi
exit 0
fi
checkIP "${localIP}"
}
# Initialize Nginx application certificate configuration
initTLSNginxConfig() {
handleNginx stop
echoContent skyBlue "\nProgress $1/${totalProgress}: Initializing Nginx application certificate configuration"
if [[ -n "${currentHost}" ]]; 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 "\n ---> Domain name: ${domain}"
else
echo
echoContent yellow "Please enter the domain name to be configured: www.v2ray-agent.com --->"
read -r -p "domain name:" domain
fi
else
echo
echoContent yellow "Please enter the domain name to be configured: www.v2ray-agent.com --->"
read -r -p "domain name:" domain
fi
if [[ -z ${domain} ]]; then
echoContent red "Domain name cannot be empty--->"
initTLSNginxConfig 3
else
dnsTLSDomain=$(echo "${domain}" | awk -F "[.]" '{print $(NF-1)"."$NF}')
customPortFunction
# Change setting
handleNginx stop
# touch ${nginxConfigPath}alone.conf
# nginxIPort=80
# if [[ "${wildcardDomainStatus}" == "true" ]]; then
# nginxIPort=${port}
# fi
#
# cat <<EOF >${nginxConfigPath}alone.conf
#server {
# listen ${port};
# listen [::]:${port};
# server_name ${domain};
# location /test {
# 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
fi
# readAcmeTLS
# handleNginx start
}
# 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 " ---> Delete Nginx default configuration"
rm -rf ${nginxConfigPath}default.conf
fi
fi
}
# Modify nginx redirection configuration
updateRedirectNginxConf() {
local redirectDomain=
redirectDomain=${domain}:${port}
cat <<EOF >${nginxConfigPath}alone.conf
server {
listen 127.0.0.1:31300;
server_name _;
return 403;
}
EOF
if echo "${selectCustomInstallType}" | grep -q 2 && echo "${selectCustomInstallType}" | grep -q 5 || [[ -z "${selectCustomInstallType}" ]]; then
local nginxH2Conf=
nginxH2Conf="listen 127.0.0.1:31302 http2 so_keepalive=on;"
nginxVersion=$(nginx -v 2>&1)
if echo "${nginxVersion}" | grep -q "1.25"; then
nginxH2Conf="listen 127.0.0.1:31302 so_keepalive=on;http2 on;"
fi
cat <<EOF >>${nginxConfigPath}alone.conf
server {
${nginxH2Conf}
server_name ${domain};
root ${nginxStaticPath};
client_header_timeout 1071906480m;
keepalive_timeout 1071906480m;
location ~ ^/s/(clashMeta|default|clashMetaProfiles)/(.*) {
default_type 'text/plain; charset=utf-8';
alias /etc/v2ray-agent/subscribe/\$1/\$2;
}
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 / {
add_header Strict-Transport-Security "max-age=15552000; preload" always;
}
}
EOF
elif echo "${selectCustomInstallType}" | grep -q 5 || [[ -z "${selectCustomInstallType}" ]]; then
cat <<EOF >>${nginxConfigPath}alone.conf
server {
listen 127.0.0.1:31302 http2;
server_name ${domain};
root ${nginxStaticPath};
location ~ ^/s/(clashMeta|default|clashMetaProfiles)/(.*) {
default_type 'text/plain; charset=utf-8';
alias /etc/v2ray-agent/subscribe/\$1/\$2;
}
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;
}
}
EOF
elif echo "${selectCustomInstallType}" | grep -q 2 || [[ -z "${selectCustomInstallType}" ]]; then
cat <<EOF >>${nginxConfigPath}alone.conf
server {
listen 127.0.0.1:31302 http2;
server_name ${domain};
root ${nginxStaticPath};
location ~ ^/s/(clashMeta|default|clashMetaProfiles)/(.*) {
default_type 'text/plain; charset=utf-8';
alias /etc/v2ray-agent/subscribe/\$1/\$2;
}
location /${currentPath}trojangrpc {
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;
}
}
EOF
else
cat <<EOF >>${nginxConfigPath}alone.conf
server {
listen 127.0.0.1:31302 http2;
server_name ${domain};
root ${nginxStaticPath};
location ~ ^/s/(clashMeta|default|clashMetaProfiles)/(.*) {
default_type 'text/plain; charset=utf-8';
alias /etc/v2ray-agent/subscribe/\$1/\$2;
}
location / {
}
}
EOF
fi
cat <<EOF >>${nginxConfigPath}alone.conf
server {
listen 127.0.0.1:31300;
server_name ${domain};
root ${nginxStaticPath};
location ~ ^/s/(clashMeta|default|clashMetaProfiles)/(.*) {
default_type 'text/plain; charset=utf-8';
alias /etc/v2ray-agent/subscribe/\$1/\$2;
}
location / {
add_header Strict-Transport-Security "max-age=15552000; preload" always;
}
}
EOF
handleNginx stop
}
# 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 ---> The ip of the current domain name was not detected"
echoContent skyBlue " ---> Please perform the following checks in order"
echoContent yellow " --->1.Check whether the domain name is written correctly"
echoContent yellow " --->2.Check whether the domain name dns resolution is correct"
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"
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"
echo
echoContent skyBlue " ---> If the above settings are correct, please reinstall a pure system and try again"
if [[ -n ${localIP} ]]; then
echoContent yellow " ---> Detection of abnormal return value, it is recommended to manually uninstall nginx and re-execute the script"
echoContent red " ---> Exception result: ${localIP}"
fi
exit 0
else
if echo "${localIP}" | awk -F "[,]" '{print $2}' | grep -q "." || echo "${localIP}" | awk -F "[,]" '{ print $2}' | grep -q ":"; then
echoContent red "\n ---> Multiple IPs were detected, please confirm whether to turn off cloudflare"
echoContent yellow " ---> Wait three minutes after closing the cloud and try again"
echoContent yellow " ---> The detected IP is as follows: [${localIP}]"
exit 0
fi
# echoContent green " ---> The current domain name ip is: [${localIP}]"
echoContent green " ---> Check that the current domain name IP is correct"
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 " ---> Added successfully"
else
echoContent yellow "Please re-enter the correct email format [Example: username@example.com]"
customSSLEmail
fi
fi
fi
}
#Select ssl installation type
switchSSLType() {
if [[ -z "${sslType}" ]]; then
echoContent red "\n=============================================================="
echoContent yellow "1.letsencrypt[default]"
echoContent yellow "2.zerossl"
echoContent yellow "3.buypass[Does not support DNS application]"
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
echo "${sslType}" >/etc/v2ray-agent/tls/ssl_type
fi
}
#Select acme installation certificate method
selectAcmeInstallSSL() {
local installSSLIPv6=
if echo "${localIP}" | grep -q ":"; then
installSSLIPv6="--listen-v6"
fi
echo
if [[ -n "${customPort}" ]]; then
if [[ "${selectSSLType}" == "3" ]]; then
echoContent red " ---> buypass does not support free wildcard certificates"
echo
exit
fi
dnsSSLStatus=true
#else
# if [[ -z "${dnsSSLStatus}" ]]; then
# read -r -p "Whether to use DNS to apply for a certificate? If you do not know how to use DNS to apply for a certificate, please enter n[y/n]:" installSSLDNStatus
#
# if [[ ${installSSLDNStatus} == 'y' ]]; then
# dnsSSLStatus=true
#else
#dnsSSLStatus=false
#fi
# fi
fi
acmeInstallSSL
readAcmeTLS
}
# Install SSL certificate
acmeInstallSSL() {
if [[ "${dnsSSLStatus}" == "true" ]]; then
sudo "$HOME/.acme.sh/acme.sh" --issue -d "*.${dnsTLSDomain}" -d "${dnsTLSDomain}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please -k ec-256 --server "${sslType}" ${installSSLIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null
local txtValue=
txtValue=$(tail -n 10 /etc/v2ray-agent/tls/acme.log | grep "TXT value" | awk -F "'" '{print $2}')
if [[ -n "${txtValue}" ]]; then
echoContent green " ---> Please add DNS TXT record manually"
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 green " ---> name: _acme-challenge"
echoContent green " ---> value: ${txtValue}"
echoContent yellow " ---> Please wait 1-2 minutes after the addition is completed"
echo
read -r -p "Whether the addition is completed [y/n]:" addDNSTXTRecordStatus
if [[ "${addDNSTXTRecordStatus}" == "y" ]]; then
local txtAnswer=
txtAnswer=$(dig @1.1.1.1 +nocmd "_acme-challenge.${dnsTLSDomain}" txt +noall +answer | awk -F "[\"]" '{print $2}')
if echo "${txtAnswer}" | grep -q "^${txtValue}"; then
echoContent green " ---> TXT record verification passed"
echoContent green " ---> Generating certificate"
if [[ -n "${installSSLIPv6}" ]]; then
sudo "$HOME/.acme.sh/acme.sh" --renew -d "*.${dnsTLSDomain}" -d "${dnsTLSDomain}" --yes-I-know-dns-manual-mode-enough-go-ahead-please --ecc --server "${sslType}" ${installSSLIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null
else
sudo "$HOME/.acme.sh/acme.sh" --renew -d "*.${dnsTLSDomain}" -d "${dnsTLSDomain}" --yes-I-know-dns-manual-mode-enough-go-ahead-please --ecc --server "${sslType}" 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null
fi
else
echoContent red " ---> Verification failed, please wait 1-2 minutes and try again"
acmeInstallSSL
fi
else
echoContent red " ---> Give up"
exit 0
fi
fi
else
echoContent green " ---> Generating certificate"
sudo "$HOME/.acme.sh/acme.sh" --issue -d "${tlsDomain}" --standalone -k ec-256 --server "${sslType}" ${installSSLIPv6} 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
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 "\n ---> Port: ${port}"
fi
fi
if [[ -z "${currentPort}" ]] || [[ "${historyCustomPortStatus}" == "n" ]]; then
echo
if [[ -n "${btDomain}" ]]; then
echoContent yellow "Please enter the port [cannot be the same as the BT Panel port, press Enter to be random]"
read -r -p "port:" port
if [[ -z "${port}" ]]; then
port=$((RANDOM % 20001 + 10000))
fi
else
echo
echoContent yellow "Please enter the port [default: 443], you can customize the port [press Enter to use the default]"
read -r -p "port:" port
if [[ -z "${port}" ]]; then
port=443
fi
if [[ "${port}" == "${currentRealityPort}" ]]; then
handleXray stop
fi
# todo dns api
fi
if [[ -n "${port}" ]]; then
if ((port >= 1 && port <= 65535)); then
allowPort "${port}"
echoContent yellow "\n ---> Port: ${port}"
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"
local tlsDomain=${domain}
# Install tls
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" ]]; then
echoContent green " ---> Certificate detected"
# 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
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
else
echoContent yellow " ---> If the certificate has not expired or is customized, please select [n]\n"
read -r -p "Reinstall? [y/n]:" reInstallStatus
if [[ "${reInstallStatus}" == "y" ]]; then
rm -rf /etc/v2ray-agent/tls/*
installTLS "$1"
fi
fi
elif [[ -d "$HOME/.acme.sh" ]] && [[ ! -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer" || ! -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key" ]]; then
echoContent green " ---> Install TLS certificate, need to rely on port 80"
allowPort 80
if [[ "${installDNSACMEStatus}" != "true" ]]; then
switchSSLType
customSSLEmail
selectAcmeInstallSSL
#else
# echoContent green " ---> A wildcard certificate has been detected and is being automatically generated"
fi
# if [[ "${installDNSACMEStatus}" == "true" ]]; then
# echo
# if [[ -d "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc" && -f "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}. key" && -f "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer" ]]; 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
# fi
#
# el
if [[ -d "$HOME/.acme.sh/${tlsDomain}_ecc" && -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key" && -f "$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer" ]]; then
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 " ---> TLS generated successfully"
else
echoContent yellow " ---> acme.sh is not installed"
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() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Generate random path"
if [[ -n "${currentPath}" ]]; 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
fi
if [[ "${historyPathStatus}" == "y" ]]; then
customPath=${currentPath}
echoContent green " ---> Used successfully\n"
else
echoContent yellow "Please enter a custom path [eg: alone], no slash required, [Enter] random path"
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----------------------------"
}
# Nginx disguise blog
nginxBlog() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Add fake site"
if [[ -d "${nginxStaticPath}" && -f "${nginxStaticPath}/check" ]]; then
echo
read -r -p "Detected installation of fake site, do you need to reinstall [y/n]:" nginxBlogInstallStatus
if [[ "${nginxBlogInstallStatus}" == "y" ]]; then
rm -rf "${nginxStaticPath}"
randomNum=$((RANDOM % 6 + 1))
wget -q -P "${nginxStaticPath}" https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip >/dev/null
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=$((RANDOM % 6 + 1))
rm -rf "${nginxStaticPath}"
wget -q -P "${nginxStaticPath}" https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip >/dev/null
unzip -o "${nginxStaticPath}html${randomNum}.zip" -d "${nginxStaticPath}" >/dev/null
rm -f "${nginxStaticPath}html${randomNum}.zip*"
echoContent green " ---> Added fake site 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 31300 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 " ---> http_port_t 31302 port opened successfully"
fi
handleNginx start
else
exit 0
fi
}
#Operation Nginx
handleNginx() {
if [[ -z $(pgrep -f "nginx") ]] && [[ "$1" == "start" ]]; then
systemctl start nginx 2>/etc/v2ray-agent/nginx_error.log
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"
if grep -q "journalctl -xe" </etc/v2ray-agent/nginx_error.log; then
updateSELinuxHTTPPortT
fi
# exit 0
else
echoContent green " ---> Nginx started successfully"
fi
elif [[ -n $(pgrep -f "nginx") ]] && [[ "$1" == "stop" ]]; then
systemctl stop nginx
sleep 0.5
if [[ -n $(pgrep -f "nginx") ]]; then
pgrep -f "nginx" | xargs kill -9
fi
echoContent green " ---> Nginx closed 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 ---> Add scheduled maintenance certificate successfully"
fi
}
# Scheduled tasks update geo files
installCronUpdateGeo() {
if [[ -n "${configPath}" ]]; 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 "\n ---> Adding scheduled update geo file successfully"
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" ]] || [[ "${installDNSACMEStatus}" == "true" ]]; then
modifyTime=
if [[ "${installDNSACMEStatus}" == "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 " ---> Regenerate certificate"
handleNginx stop
if [[ "${coreInstallType}" == "1" ]]; then
handleXray stop
elif [[ "${coreInstallType}" == "2" ]]; then
handleV2Ray 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 " ---> The certificate is valid"
fi
else
echoContent red " ---> not installed"
fi
}
# Check the status of TLS certificate
checkTLStatus() {
if [[ -d "$HOME/.acme.sh/${currentHost}_ecc" ]] && [[ -f "$HOME/.acme.sh/${currentHost}_ecc/${currentHost}.key" ]] && [[ -f "$HOME/.acme.sh/${currentHost}_ecc/${currentHost}.cer" ]]; then
modifyTime=$(stat "$HOME/.acme.sh/${currentHost}_ecc/${currentHost}.cer" | sed -n '7,6p' | awk '{print $2" "$3" "$4" "$5}')
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 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}"
fi
}
#Install V2Ray, specified version
installV2Ray() {
readInstallType
echoContent skyBlue "\nProgress$1/${totalProgress}: Install V2Ray"
if [[ "${coreInstallType}" != "2" && "${coreInstallType}" != "3" ]]; then
if [[ "${selectCoreType}" == "2" ]]; then
version=$(curl -s https://api.github.com/repos/v2fly/v2ray-core/releases?per_page=10 | jq -r '.[]|select (.prerelease==false)|.tag_name' | grep -v 'v5' | head -1)
else
version=${v2rayCoreVersion}
fi
echoContent green " ---> v2ray-core version:${version}"
# if wget --help | grep -q show-progress; then
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/v2ray/ "https://github.com/v2fly/v2ray-core/releases/download/${version}/${v2rayCoreCPUVendor}.zip"
#else
# wget -c -P /etc/v2ray-agent/v2ray/ "https://github.com/v2fly/v2ray-core/releases/download/${version}/${v2rayCoreCPUVendor}.zip" >/dev/ null 2>&1
# fi
unzip -o "/etc/v2ray-agent/v2ray/${v2rayCoreCPUVendor}.zip" -d /etc/v2ray-agent/v2ray >/dev/null
rm -rf "/etc/v2ray-agent/v2ray/${v2rayCoreCPUVendor}.zip"
else
if [[ "${selectCoreType}" == "3" ]]; then
echoContent green " ---> Lock v2ray-core version to v4.32.1"
rm -f /etc/v2ray-agent/v2ray/v2ray
rm -f /etc/v2ray-agent/v2ray/v2ctl
installV2Ray "$1"
else
echoContent green " ---> v2ray-core version:$(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)"
read -r -p "Update or upgrade? [y/n]:" reInstallV2RayStatus
if [[ "${reInstallV2RayStatus}" == "y" ]]; then
rm -f /etc/v2ray-agent/v2ray/v2ray
rm -f /etc/v2ray-agent/v2ray/v2ctl
installV2Ray "$1"
fi
fi
fi
}
# Install hysteria
installHysteria() {
readInstallType
echoContent skyBlue "\nProgress$1/${totalProgress}: Installing Hysteria"
if [[ -z "${hysteriaConfigPath}" ]]; then
version=$(curl -s "https://api.github.com/repos/apernet/hysteria/releases?per_page=10" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | grep -v "app/v2" | head -1)
echoContent green " ---> Hysteria version:${version}"
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/hysteria/ "https://github.com/apernet/hysteria/releases/download/${version}/${hysteriaCoreCPUVendor}"
mv "/etc/v2ray-agent/hysteria/${hysteriaCoreCPUVendor}" /etc/v2ray-agent/hysteria/hysteria
chmod 655 /etc/v2ray-agent/hysteria/hysteria
else
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]:" reInstallHysteriaStatus
if [[ "${reInstallHysteriaStatus}" == "y" ]]; then
rm -f /etc/v2ray-agent/hysteria/hysteria
installHysteria "$1"
fi
fi
}
# Install tuic
installTuic() {
readInstallType
echoContent skyBlue "\nProgress$1/${totalProgress}: Install Tuic"
if [[ -z "${tuicConfigPath}" ]]; then
version=$(curl -s "https://api.github.com/repos/EAimTY/tuic/releases?per_page=1" | jq -r '.[]|select (.prerelease==false)|.tag_name')
echoContent green " ---> Tuic version:${version}"
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/tuic/ "https://github.com/EAimTY/tuic/releases/download/${version}/${version}${tuicCoreCPUVendor}"
mv "/etc/v2ray-agent/tuic/${version}${tuicCoreCPUVendor}" /etc/v2ray-agent/tuic/tuic
chmod 655 /etc/v2ray-agent/tuic/tuic
else
echoContent green " ---> Tuic version:$(/etc/v2ray-agent/tuic/tuic -v)"
read -r -p "Would you like to update or upgrade? [y/n]:" reInstallTuicStatus
if [[ "${reInstallTuicStatus}" == "y" ]]; then
rm -f /etc/v2ray-agent/tuic/tuic
tuicConfigPath=
installTuic "$1"
fi
fi
}
# Check wget showProgress
checkWgetShowProgress() {
if find /usr/bin /usr/sbin | grep -q -w wget && wget --help | grep -q show-progress; then
wgetShowProgressStatus="--show-progress"
fi
}
# Install xray
installXray() {
readInstallType
local prereleaseStatus=false
if [[ "$2" == "true" ]]; then
prereleaseStatus=true
fi
echoContent skyBlue "\nProgress$1/${totalProgress}: Install Xray"
if [[ "${coreInstallType}" != "1" ]]; then
version=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=1" | jq -r ".[].tag_name")
echoContent green " ---> Xray-core version:${version}"
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip"
if [[ ! -f "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" ]]; then
echoContent red " ---> Core download failed, please try installation again"
exit 0
fi
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
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"
chmod 655 /etc/v2ray-agent/xray/xray
else
echoContent green " ---> Xray-core version:$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)"
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
}
# v2ray version management
v2rayVersionManageMenu() {
echoContent skyBlue "\nProgress$1/${totalProgress}: V2Ray version management"
if [[ ! -d "/etc/v2ray-agent/v2ray/" ]]; then
echoContent red " ---> The installation directory is not detected, please execute the script to install the content"
menu
exit 0
fi
echoContent red "\n================================================ ================="
echoContent yellow "1.Upgrade v2ray-core"
echoContent yellow "2.Fallback v2ray-core"
echoContent yellow "3.Close v2ray-core"
echoContent yellow "4.Open v2ray-core"
echoContent yellow "5.Restart v2ray-core"
echoContent yellow "6.Update geosite, geoip"
echoContent yellow "7.Set up automatic update of geo files [updated every morning]"
echoContent red "================================================== ==============="
read -r -p "Please select:" selectV2RayType
if [[ "${selectV2RayType}" == "1" ]]; then
updateV2Ray
elif [[ "${selectV2RayType}" == "2" ]]; then
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 skyBlue "------------------------Version-------------------------------"
curl -s https://api.github.com/repos/v2fly/v2ray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | grep -v 'v5' | head -5 | awk '{print ""NR""":"$0}'
echoContent skyBlue "------------------------------------------------- ---------------"
read -r -p "Please enter the version to be rolled back:" selectV2rayVersionType
version=$(curl -s https://api.github.com/repos/v2fly/v2ray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | grep -v 'v5' | head -5 | awk '{print ""NR""":"$0}' | grep "${selectV2rayVersionType}:" | awk -F "[:]" '{print $2}')
if [[ -n "${version}" ]]; then
updateV2Ray "${version}"
else
echoContent red "\n ---> Incorrect input, please re-enter"
v2rayVersionManageMenu 1
fi
elif [[ "${selectV2RayType}" == "3" ]]; then
handleV2Ray stop
elif [[ "${selectV2RayType}" == "4" ]]; then
handleV2Ray start
elif [[ "${selectV2RayType}" == "5" ]]; then
reloadCore
elif [[ "${selectXrayType}" == "6" ]]; then
updateGeoSite
elif [[ "${selectXrayType}" == "7" ]]; then
installCronUpdateGeo
fi
}
# xray version management
xrayVersionManageMenu() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Xray version management"
if [[ ! -d "/etc/v2ray-agent/xray/" ]]; then
echoContent red " ---> The installation directory is not detected, please execute the script to install the content"
menu
exit 0
fi
echoContent red "\n================================================ ================="
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"
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]"
echoContent red "================================================== ==============="
read -r -p "Please select:" selectXrayType
if [[ "${selectXrayType}" == "1" ]]; then
updateXray
elif [[ "${selectXrayType}" == "2" ]]; then
prereleaseStatus=true
updateXray
elif [[ "${selectXrayType}" == "3" ]]; then
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 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 "\n ---> Incorrect input, please re-enter"
xrayVersionManageMenu 1
fi
elif [[ "${selectXrayType}" == "4" ]]; then
handleXray stop
elif [[ "${selectXrayType}" == "5" ]]; then
handleXray start
elif [[ "${selectXrayType}" == "6" ]]; then
reloadCore
elif [[ "${selectXrayType}" == "7" ]]; then
updateGeoSite
elif [[ "${selectXrayType}" == "8" ]]; then
installCronUpdateGeo
fi
}
# Update geosite
updateGeoSite() {
echoContent yellow "\nSource https://github.com/Loyalsoldier/v2ray-rules-dat"
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
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"
reloadCore
echoContent green " ---> Update completed"
}
# Update V2Ray
updateV2Ray() {
readInstallType
if [[ -z "${coreInstallType}" ]]; then
if [[ -n "$1" ]]; then
version=$1
else
version=$(curl -s https://api.github.com/repos/v2fly/v2ray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | grep -v 'v5' | head -1)
fi
# Use locked version
if [[ -n "${v2rayCoreVersion}" ]]; then
version=${v2rayCoreVersion}
fi
echoContent green " ---> v2ray-core version:${version}"
# if wget --help | grep -q show-progress; then
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/v2ray/ "https://github.com/v2fly/v2ray-core/releases/download/${version}/${v2rayCoreCPUVendor}.zip"
#else
# wget -c -P "/etc/v2ray-agent/v2ray/ https://github.com/v2fly/v2ray-core/releases/download/${version}/${v2rayCoreCPUVendor}.zip" >/dev/ null 2>&1
#fi
unzip -o "/etc/v2ray-agent/v2ray/${v2rayCoreCPUVendor}.zip" -d /etc/v2ray-agent/v2ray >/dev/null
rm -rf "/etc/v2ray-agent/v2ray/${v2rayCoreCPUVendor}.zip"
handleV2Ray stop
handleV2Ray start
else
echoContent green " ---> Current v2ray-core version: $(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)"
if [[ -n "$1" ]]; then
version=$1
else
version=$(curl -s https://api.github.com/repos/v2fly/v2ray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | grep -v 'v5' | head -1)
fi
if [[ -n "${v2rayCoreVersion}" ]]; then
version=${v2rayCoreVersion}
fi
if [[ -n "$1" ]]; then
read -r -p "The rollback version is ${version}, do you want to continue? [y/n]:" rollbackV2RayStatus
if [[ "${rollbackV2RayStatus}" == "y" ]]; then
if [[ "${coreInstallType}" == "2" ]]; then
echoContent green " ---> Current v2ray-core version: $(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)"
elif [[ "${coreInstallType}" == "1" ]]; then
echoContent green " ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)"
fi
handleV2Ray stop
rm -f /etc/v2ray-agent/v2ray/v2ray
rm -f /etc/v2ray-agent/v2ray/v2ctl
updateV2Ray "${version}"
else
echoContent green " ---> Abandon the rollback version"
fi
elif [[ "${version}" == "v$(/etc/v2ray-agent/v2ray/v2ray --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]:" reInstallV2RayStatus
if [[ "${reInstallV2RayStatus}" == "y" ]]; then
handleV2Ray stop
rm -f /etc/v2ray-agent/v2ray/v2ray
rm -f /etc/v2ray-agent/v2ray/v2ctl
updateV2Ray
else
echoContent green " ---> Give up and reinstall"
fi
else
read -r -p "The latest version is: ${version}, do you want to update? [y/n]:" installV2RayStatus
if [[ "${installV2RayStatus}" == "y" ]]; then
rm -f /etc/v2ray-agent/v2ray/v2ray
rm -f /etc/v2ray-agent/v2ray/v2ctl
updateV2Ray
else
echoContent green " ---> Abort update"
fi
fi
fi
}
# Update Xray
updateXray() {
readInstallType
if [[ -z "${coreInstallType}" ]]; then
if [[ -n "$1" ]]; then
version=$1
else
version=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=1" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name")
fi
echoContent green " ---> Xray-core version:${version}"
wget -c -q "${wgetShowProgressStatus}" -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip"
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 " ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)"
if [[ -n "$1" ]]; then
version=$1
else
version=$(curl -s "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=1" | jq -r ".[].tag_name")
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 " ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)"
handleXray stop
rm -f /etc/v2ray-agent/xray/xray
updateXray "${version}"
else
echoContent green " ---> Abandon the rollback 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
rm -f /etc/v2ray-agent/xray/xray
updateXray
else
echoContent green " ---> Give up and reinstall"
fi
else
read -r -p "The latest version is: ${version}, is it updated? [y/n]:" installXrayStatus
if [[ "${installXrayStatus}" == "y" ]]; then
rm -f /etc/v2ray-agent/xray/xray
updateXray
else
echoContent green " ---> Abort update"
fi
fi
fi
}
# Verify that the entire service is available
checkGFWStatue() {
readInstallType
echoContent skyBlue "\nProgress$1/${totalProgress}: Verify service startup status"
if [[ "${coreInstallType}" == "1" ]] && [[ -n $(pgrep -f "xray/xray") ]]; then
echoContent green " ---> Service started successfully"
elif [[ "${coreInstallType}" == "2" ]] && [[ -n $(pgrep -f "v2ray/v2ray") ]]; then
echoContent green " ---> Service started successfully"
else
echoContent red " ---> Service startup failed, please check if there are logs printed in the terminal"
exit 0
fi
}
# V2Ray starts automatically after booting
installV2RayService() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Configure V2Ray to start automatically at boot"
if [[ -n $(find /bin /usr/bin -name "systemctl") ]]; then
rm -rf /etc/systemd/system/v2ray.service
touch /etc/systemd/system/v2ray.service
execStart='/etc/v2ray-agent/v2ray/v2ray -confdir /etc/v2ray-agent/v2ray/conf'
cat <<EOF >/etc/systemd/system/v2ray.service
[Unit]
Description=V2Ray - A unified platform for anti-censorship
Documentation=https://v2ray.com https://guide.v2fly.org
After=network.target nss-lookup.target
Wants=network-online.target
[Service]
Type=simple
User=root
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_RAW
NoNewPrivileges=yes
ExecStart=${execStart}
Restart=on-failure
RestartPreventExitStatus=23
LimitNPROC=10000
LimitNOFILE=1000000
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable v2ray.service
echoContent green " ---> Configure V2Ray to start automatically at boot"
fi
}
# Install hysteria to start automatically at boot
installHysteriaService() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Configure Hysteria to start automatically at boot"
if [[ -n $(find /bin /usr/bin -name "systemctl") ]]; then
rm -rf /etc/systemd/system/hysteria.service
touch /etc/systemd/system/hysteria.service
execStart='/etc/v2ray-agent/hysteria/hysteria --log-level info -c /etc/v2ray-agent/hysteria/conf/config.json server'
cat <<EOF >/etc/systemd/system/hysteria.service
[Unit]
Description=Hysteria Service
Documentation=https://github.com/apernet
After=network.target nss-lookup.target
[Service]
User=root
ExecStart=${execStart}
Restart=on-failure
RestartPreventExitStatus=23
LimitNPROC=10000
LimitNOFILE=1000000
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable hysteria.service
echoContent green " ---> Configure Hysteria to start automatically at boot"
fi
}
# Install Tuic to start automatically at boot
installTuicService() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Configure Tuic to start automatically at boot"
if [[ -n $(find /bin /usr/bin -name "systemctl") ]]; then
rm -rf /etc/systemd/system/tuic.service
touch /etc/systemd/system/tuic.service
execStart='/etc/v2ray-agent/tuic/tuic -c /etc/v2ray-agent/tuic/conf/config.json'
cat <<EOF >/etc/systemd/system/tuic.service
[Unit]
Description=Tuic Service
Documentation=https://github.com/EAimTY
After=network.target nss-lookup.target
[Service]
User=root
ExecStart=${execStart}
Restart=on-failure
RestartPreventExitStatus=23
LimitNPROC=10000
LimitNOFILE=1000000
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable tuic.service
echoContent green " ---> Configuring Tuic to start automatically at boot"
fi
}
# Xray starts automatically after booting
installXrayService() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Configure Xray to start automatically at boot"
if [[ -n $(find /bin /usr/bin -name "systemctl") ]]; then
rm -rf /etc/systemd/system/xray.service
touch /etc/systemd/system/xray.service
execStart='/etc/v2ray-agent/xray/xray run -confdir /etc/v2ray-agent/xray/conf'
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=10000
LimitNOFILE=1000000
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable xray.service
echoContent green " ---> Configure Xray to start automatically at boot"
fi
}
#Operation V2Ray
handleV2Ray() {
# shellcheck disable=SC2010
if find /bin /usr/bin | grep -q systemctl && ls /etc/systemd/system/ | grep -q v2ray.service; then
if [[ -z $(pgrep -f "v2ray/v2ray") ]] && [[ "$1" == "start" ]]; then
systemctl start v2ray.service
elif [[ -n $(pgrep -f "v2ray/v2ray") ]] && [[ "$1" == "stop" ]]; then
systemctl stop v2ray.service
fi
fi
sleep 0.8
if [[ "$1" == "start" ]]; then
if [[ -n $(pgrep -f "v2ray/v2ray") ]]; then
echoContent green " ---> V2Ray started successfully"
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 "v2ray/v2ray") ]]; then
echoContent green " ---> V2Ray closed successfully"
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
}
# Operation Hysteria
handleHysteria() {
# 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 " ---> Hysteria started successfully"
else
echoContent red "Hysteria startup failed"
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"
exit 0
fi
elif [[ "$1" == "stop" ]]; then
if [[ -z $(pgrep -f "hysteria/hysteria") ]]; then
echoContent green " ---> Hysteria closed successfully"
else
echoContent red "Hysteria shutdown failed"
echoContent red "Please execute manually [ps -ef|grep -v grep|grep hysteria|awk '{print \$2}'|xargs kill -9]"
exit 0
fi
fi
}
# Operate Tuic
handleTuic() {
# shellcheck disable=SC2010
if find /bin /usr/bin | grep -q systemctl && ls /etc/systemd/system/ | grep -q tuic.service; then
if [[ -z $(pgrep -f "tuic/tuic") ]] && [[ "$1" == "start" ]]; then
systemctl start tuic.service
elif [[ -n $(pgrep -f "tuic/tuic") ]] && [[ "$1" == "stop" ]]; then
systemctl stop tuic.service
fi
fi
sleep 0.8
if [[ "$1" == "start" ]]; then
if [[ -n $(pgrep -f "tuic/tuic") ]]; then
echoContent green " ---> Tuic started successfully"
else
echoContent red "Tuic startup failed"
echoContent red "Please manually execute [/etc/v2ray-agent/tuic/tuic -c /etc/v2ray-agent/tuic/conf/config.json] and check the error log"
exit 0
fi
elif [[ "$1" == "stop" ]]; then
if [[ -z $(pgrep -f "tuic/tuic") ]]; then
echoContent green " ---> Tuic closed successfully"
else
echoContent red "Tuic failed to close"
echoContent red "Please execute manually [ps -ef|grep -v grep|grep tuic|awk '{print \$2}'|xargs kill -9]"
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
fi
sleep 0.8
if [[ "$1" == "start" ]]; then
if [[ -n $(pgrep -f "xray/xray") ]]; then
echoContent green " ---> Xray started successfully"
else
echoContent red "Xray startup failed"
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
elif [[ "$1" == "stop" ]]; then
if [[ -z $(pgrep -f "xray/xray") ]]; then
echoContent green " ---> Xray closed successfully"
else
echoContent red "xray failed to close"
echoContent red "Please execute manually [ps -ef|grep -v grep|grep xray|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=
if [[ "${type}" == "9" ]]; then
users={}
else
users=[]
fi
while read -r user; do
uuid=$(echo "${user}" | jq -r .id)
email=$(echo "${user}" | jq -r .email | 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
#VLESSWS
if echo "${type}" | grep -q "1"; then
currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-VLESS_WS\"}"
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
#VMessWS
if echo "${type}" | grep -q "3"; then
currentUser="{\"id\":\"${uuid}\",\"email\":\"${email}-VMess_WS\",\"alterId\": 0}"
users=$(echo "${users}" | jq -r ". +=[${currentUser}]")
fi
#trojantcp
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
users=$(echo "${users}" | jq -r ". +=[\"${uuid}\"]")
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
users=$(echo "${users}" | jq -r ".\"${uuid}\"=\"${uuid}\"")
fi
done < <(echo "${currentClients}" | jq -c '.[]')
echo "${users}"
}
getClients() {
local path=$1
local addClientsStatus=$2
previousClients=
if [[ ${addClientsStatus} == "true" ]]; then
if [[ ! -f "${path}" ]]; then
echo
local protocol
protocol=$(echo "${path}" | awk -F "[_]" '{print $2 $3}')
echoContent yellow "The configuration file last installed for this protocol [${protocol}] was not read, and the first uuid of the configuration file was used"
else
previousClients=$(jq -r ".inbounds[0].settings.clients" "${path}")
fi
fi
}
#Add client configuration
addClients() {
local path=$1
local addClientsStatus=$2
if [[ ${addClientsStatus} == "true" && -n "${previousClients}" ]]; then
config=$(jq -r ".inbounds[0].settings.clients = ${previousClients}" "${path}")
echo "${config}" | jq . >"${path}"
fi
}
# Add hysteria configuration
addClientsHysteria() {
local path=$1
local addClientsStatus=$2
if [[ ${addClientsStatus} == "true" && -n "${previousClients}" ]]; then
local uuids=
uuids=$(echo "${previousClients}" | jq -r [.[].id])
if [[ "${frontingType}" == "02_trojan_TCP_inbounds" ]]; then
uuids=$(echo "${previousClients}" | jq -r [.[].password])
fi
config=$(jq -r ".auth.config = ${uuids}" "${path}")
echo "${config}" | jq . >"${path}"
fi
}
#Initialize hysteria port
initHysteriaPort() {
readHysteriaConfig
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 "\n ---> Port: ${hysteriaPort}"
else
hysteriaPort=
fi
fi
if [[ -z "${hysteriaPort}" ]]; then
echoContent yellow "Please enter the Hysteria port [enter random 10000-30000], cannot be repeated with other services"
read -r -p "Port:" hysteriaPort
if [[ -z "${hysteriaPort}" ]]; then
hysteriaPort=$((RANDOM % 20001 + 10000))
fi
fi
if [[ -z ${hysteriaPort} ]]; then
echoContent red " ---> Port cannot be empty"
initHysteriaPort "$2"
elif ((hysteriaPort < 1 || hysteriaPort > 65535)); then
echoContent red " ---> The port is illegal"
initHysteriaPort "$2"
fi
allowPort "${hysteriaPort}"
allowPort "${hysteriaPort}" "udp"
}
# Initialize hysteria protocol
initHysteriaProtocol() {
echoContent skyBlue "\nPlease select the protocol type"
echoContent red "================================================== ==============="
echoContent yellow "1.udp(QUIC)(default)"
echoContent yellow "2.faketcp"
echoContent yellow "3.wechat-video"
echoContent red "================================================== ==============="
read -r -p "Please select:" selectHysteriaProtocol
case ${selectHysteriaProtocol} in
1)
hysteriaProtocol="udp"
;;
2)
hysteriaProtocol="faketcp"
;;
3)
hysteriaProtocol="wechat-video"
;;
*)
hysteriaProtocol="udp"
;;
esac
echoContent yellow "\n ---> Protocol: ${hysteriaProtocol}\n"
}
# Initialize hysteria network information
initHysteriaNetwork() {
echoContent yellow "Please enter the average delay from local to server, please fill it in according to the actual situation (default: 180, unit: ms)"
read -r -p "Delay:" hysteriaLag
if [[ -z "${hysteriaLag}" ]]; then
hysteriaLag=180
echoContent yellow "\n ---> Delay: ${hysteriaLag}\n"
fi
echoContent yellow "Please enter the local bandwidth peak downstream speed (default: 100, unit: Mbps)"
read -r -p "Download speed:" hysteriaClientDownloadSpeed
if [[ -z "${hysteriaClientDownloadSpeed}" ]]; then
hysteriaClientDownloadSpeed=100
echoContent yellow "\n --->Download speed: ${hysteriaClientDownloadSpeed}\n"
fi
echoContent yellow "Please enter the local bandwidth peak uplink speed (default: 50, unit: Mbps)"
read -r -p "upload speed:" hysteriaClientUploadSpeed
if [[ -z "${hysteriaClientUploadSpeed}" ]]; then
hysteriaClientUploadSpeed=50
echoContent yellow "\n ---> Upload speed: ${hysteriaClientUploadSpeed}\n"
fi
cat <<EOF >/etc/v2ray-agent/hysteria/conf/client_network.json
{
"hysteriaLag":"${hysteriaLag}",
"hysteriaClientUploadSpeed":"${hysteriaClientUploadSpeed}",
"hysteriaClientDownloadSpeed":"${hysteriaClientDownloadSpeed}"
}
EOF
}
# hy port jump
hysteriaPortHopping() {
if [[ -n "${portHoppingStart}" || -n "${portHoppingEnd}" ]]; then
echoContent red " ---> Already added, cannot be added repeatedly, can be deleted and re-added"
exit 0
fi
echoContent skyBlue "\nProgress 1/1: Port jump"
echoContent red "\n================================================ ================="
echoContent yellow "# Notes\n"
echoContent yellow "Only supports UDP"
echoContent yellow "The starting position of port jumping is 30000"
echoContent yellow "The end position of port jumping is 60000"
echoContent yellow "You can choose a segment in the range of 30000-60000"
echoContent yellow "Recommend about 1000"
echoContent yellow "Please enter the port jumping range, for example [30000-31000]"
read -r -p "Range:" hysteriaPortHoppingRange
if [[ -z "${hysteriaPortHoppingRange}" ]]; then
echoContent red " ---> Range cannot be empty"
hysteriaPort Hopping
elif echo "${hysteriaPortHoppingRange}" | grep -q "-"; then
local portStart=
local portEnd=
portStart=$(echo "${hysteriaPortHoppingRange}" | awk -F '-' '{print $1}')
portEnd=$(echo "${hysteriaPortHoppingRange}" | awk -F '-' '{print $2}')
if [[ -z "${portStart}" || -z "${portEnd}" ]]; then
echoContent red " ---> The range is illegal"
hysteriaPort Hopping
elif ((portStart < 30000 || portStart > 60000 || portEnd < 30000 || portEnd > 60000 || portEnd < portStart)); then
echoContent red " ---> The range is illegal"
hysteriaPort Hopping
else
echoContent green "\nPort range: ${hysteriaPortHoppingRange}\n"
# ip -4 addr show | awk '/inet /{print $NF ":" $2}' | awk '{print ""NR""":"$0}'
# read -r -p "Please select the corresponding network card:" selectInterface
# if ! ip -4 addr show | awk '/inet /{print $NF ":" $2}' | awk '{print ""NR""":"$0}' | grep -q "${selectInterface}: "; then
# echoContent red " ---> Wrong selection"
# hysteriaPortHopping
#else
iptables -t nat -A PREROUTING -p udp --dport "${portStart}:${portEnd}" -m comment --comment "mack-a_portHopping" -j DNAT --to-destination :${hysteriaPort}
if iptables-save | grep -q "mack-a_portHopping"; then
allowPort "${portStart}:${portEnd}" udp
echoContent green " ---> Port hopping added successfully"
else
echoContent red " ---> Failed to add port hopping"
fi
# fi
fi
fi
}
# Read port hopping configuration
readHysteriaPortHopping() {
if [[ -n "${hysteriaPort}" ]]; then
# interfaceName=$(ip -4 addr show | awk '/inet /{print $NF ":" $2}' | awk '{print ""NR""":"$0}' | grep "${selectInterface}:" | awk -F "[:]" '{print $2}')
if iptables-save | grep -q "mack-a_portHopping"; then
portHopping=
portHopping=$(iptables-save | grep "mack-a_portHopping" | cut -d " " -f 8)
portHoppingStart=$(echo "${portHopping}" | cut -d ":" -f 1)
portHoppingEnd=$(echo "${portHopping}" | cut -d ":" -f 2)
fi
fi
}
# Delete hysteria port treaty iptables rules
deleteHysteriaPortHoppingRules() {
iptables -t nat -L PREROUTING --line-numbers | grep "mack-a_portHopping" | awk '{print $1}' | while read -r line; do
iptables -t nat -D PREROUTING 1
done
}
hysteriaPortHoppingMenu() {
# Determine whether iptables exists
if ! find /usr/bin /usr/sbin | grep -q -w iptables; then
echoContent red " ---> Unable to recognize iptables tool, unable to use port jump, exit installation"
exit 0
fi
readHysteriaConfig
readHysteriaPortHopping
echoContent skyBlue "\nProgress 1/1: Port jump"
echoContent red "\n================================================ ================="
echoContent yellow "1.Add port hopping"
echoContent yellow "2.Delete port hopping"
echoContent yellow "3.Check port jumping"
read -r -p "range:" selectPortHoppingStatus
if [[ "${selectPortHoppingStatus}" == "1" ]]; then
hysteriaPort Hopping
elif [[ "${selectPortHoppingStatus}" == "2" ]]; then
if [[ -n "${portHopping}" ]]; then
deleteHysteriaPortHoppingRules
echoContent green " ---> Deletion successful"
fi
elif [[ "${selectPortHoppingStatus}" == "3" ]]; then
echoContent green " ---> The current port hopping range is: ${portHoppingStart}-${portHoppingEnd}"
else
hysteriaPortHoppingMenu
fi
}
#Initialize Hysteria configuration
initHysteriaConfig() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Initializing Hysteria configuration"
initHysteriaPort
initHysteriaProtocol
initHysteriaNetwork
local uuid=
uuid=$(${ctlPath} uuid)
getClients "${configPath}${frontingType}.json" true
cat <<EOF >/etc/v2ray-agent/hysteria/conf/config.json
{
"listen": ":${hysteriaPort}",
"protocol": "${hysteriaProtocol}",
"disable_udp": false,
"cert": "/etc/v2ray-agent/tls/${currentHost}.crt",
"key": "/etc/v2ray-agent/tls/${currentHost}.key",
"auth": {
"mode": "passwords",
"config": []
},
"socks5_outbound":{
"server":"127.0.0.1:31295",
"user":"hysteria_socks5_outbound",
"password":"${uuid}"
},
"alpn": "h3",
"recv_window_conn": 15728640,
"recv_window_client": 67108864,
"max_conn_client": 4096,
"disable_mtu_discovery": true,
"resolve_preference": "46",
"resolver": "https://8.8.8.8:443/dns-query"
}
EOF
addClientsHysteria "/etc/v2ray-agent/hysteria/conf/config.json" true
# Add socks inbound
cat <<EOF >${configPath}/02_socks_inbounds_hysteria.json
{
"inbounds": [
{
"listen": "127.0.0.1",
"port": 31295,
"protocol": "Socks",
"tag": "socksHysteriaOutbound",
"settings": {
"auth": "password",
"accounts": [
{
"user": "hysteria_socks5_outbound",
"pass": "${uuid}"
}
],
"udp": true,
"ip": "127.0.0.1"
}
}
]
}
EOF
}
#Initialize tuic port
initTuicPort() {
readTuicConfig
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 "\n ---> Port: ${tuicPort}"
else
tuicPort=
fi
fi
if [[ -z "${tuicPort}" ]]; then
echoContent yellow "Please enter the Tuic port [enter random 10000-30000], cannot be repeated with other services"
read -r -p "Port:" tuicPort
if [[ -z "${tuicPort}" ]]; then
tuicPort=$((RANDOM % 20001 + 10000))
fi
fi
if [[ -z ${tuicPort} ]]; then
echoContent red " ---> Port cannot be empty"
initTuicPort "$2"
elif ((tuicPort < 1 || tuicPort > 65535)); then
echoContent red " ---> The port is illegal"
initTuicPort "$2"
fi
echoContent green "\n ---> Port: ${tuicPort}"
allowPort "${tuicPort}"
allowPort "${tuicPort}" "udp"
}
# Initialize tuic protocol
initTuicProtocol() {
echoContent skyBlue "\nPlease select the algorithm type"
echoContent red "================================================== ==============="
echoContent yellow "1.bbr(default)"
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 "\n ---> Algorithm: ${tuicAlgorithm}\n"
}
# Initialize tuic configuration
initTuicConfig() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Initializing Tuic configuration"
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
}
# Tuic installation
tuicCoreInstall() {
if ! echo "${currentInstallProtocolType}" | grep -q "0" || [[ -z "${coreInstallType}" ]]; 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
totalProgress=5
installTuic 1
initTuicConfig 2
installTuicService 3
reloadCore
showAccounts 4
}
#Initialize V2Ray configuration file
initV2RayConfig() {
echoContent skyBlue "\nProgress$2/${totalProgress}: Initializing V2Ray configuration"
echo
read -r -p "Do you want to customize the UUID? [y/n]:" customUUIDStatus
echo
if [[ "${customUUIDStatus}" == "y" ]]; then
read -r -p "Please enter a valid UUID:" currentCustomUUID
if [[ -n "${currentCustomUUID}" ]]; then
uuid=${currentCustomUUID}
fi
fi
local addClientsStatus=
if [[ -n "${currentUUID}" && -z "${uuid}" ]]; 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
uuid=${currentUUID}
addClientsStatus=true
else
uuid=$(/etc/v2ray-agent/v2ray/v2ctl uuid)
fi
elif [[ -z "${uuid}" ]]; then
uuid=$(/etc/v2ray-agent/v2ray/v2ctl uuid)
fi
if [[ -z "${uuid}" ]]; then
addClientsStatus=
echoContent red "\n ---> uuid reading error, regenerate"
uuid=$(/etc/v2ray-agent/v2ray/v2ctl uuid)
fi
movePreviousConfig
# log
cat <<EOF >/etc/v2ray-agent/v2ray/conf/00_log.json
{
"log": {
"error": "/etc/v2ray-agent/v2ray/error.log",
"loglevel": "warning"
}
}
EOF
# outbounds
if [[ -n "${pingIPv6}" ]]; then
cat <<EOF >/etc/v2ray-agent/v2ray/conf/10_ipv6_outbounds.json
{
"outbounds": [
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
}
]
}
EOF
else
cat <<EOF >/etc/v2ray-agent/v2ray/conf/10_ipv4_outbounds.json
{
"outbounds":[
{
"protocol":"freedom",
"settings":{
"domainStrategy":"UseIPv4"
},
"tag":"IPv4-out"
},
{
"protocol":"freedom",
"settings":{
"domainStrategy":"UseIPv6"
},
"tag":"IPv6-out"
},
{
"protocol":"blackhole",
"tag":"blackhole-out"
}
]
}
EOF
fi
# dns
cat <<EOF >/etc/v2ray-agent/v2ray/conf/11_dns.json
{
"dns": {
"servers": [
"localhost"
]
}
}
EOF
# VLESS_TCP_TLS
# Fall back nginx
local fallbacksList='{"dest":31300,"xver":0},{"alpn":"h2","dest":31302,"xver":0}'
#trojan
if echo "${selectCustomInstallType}" | grep -q 4 || [[ "$1" == "all" ]]; then
fallbacksList='{"dest":31296,"xver":1},{"alpn":"h2","dest":31302,"xver":0}'
getClients "${configPath}../tmp/04_trojan_TCP_inbounds.json" "${addClientsStatus}"
cat <<EOF >/etc/v2ray-agent/v2ray/conf/04_trojan_TCP_inbounds.json
{
"inbounds":[
{
"port": 31296,
"listen": "127.0.0.1",
"protocol": "trojan",
"tag":"trojanTCP",
"settings": {
"clients": [
{
"password": "${uuid}",
"email": "default_Trojan_TCP"
}
],
"fallbacks":[
{"dest":"31300"}
]
},
"streamSettings": {
"network": "tcp",
"security": "none",
"tcpSettings": {
"acceptProxyProtocol": true
}
}
}
]
}
EOF
addClients "/etc/v2ray-agent/v2ray/conf/04_trojan_TCP_inbounds.json" "${addClientsStatus}"
fi
# VLESS_WS_TLS
if echo "${selectCustomInstallType}" | grep -q 1 || [[ "$1" == "all" ]]; then
fallbacksList=${fallbacksList}',{"path":"/'${customPath}'ws","dest":31297,"xver":1}'
getClients "${configPath}../tmp/03_VLESS_WS_inbounds.json" "${addClientsStatus}"
cat <<EOF >/etc/v2ray-agent/v2ray/conf/03_VLESS_WS_inbounds.json
{
"inbounds":[
{
"port": 31297,
"listen": "127.0.0.1",
"protocol": "vless",
"tag":"VLESSWS",
"settings": {
"clients": [
{
"id": "${uuid}",
"email": "default_VLESS_WS"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "ws",
"security": "none",
"wsSettings": {
"acceptProxyProtocol": true,
"path": "/${customPath}ws"
}
}
}
]
}
EOF
addClients "/etc/v2ray-agent/v2ray/conf/03_VLESS_WS_inbounds.json" "${addClientsStatus}"
fi
# trojan_grpc
if echo "${selectCustomInstallType}" | grep -q 2 || [[ "$1" == "all" ]]; then
if ! echo "${selectCustomInstallType}" | grep -q 5 && [[ -n ${selectCustomInstallType} ]]; then
fallbacksList=${fallbacksList//31302/31304}
fi
getClients "${configPath}../tmp/04_trojan_gRPC_inbounds.json" "${addClientsStatus}"
cat <<EOF >/etc/v2ray-agent/v2ray/conf/04_trojan_gRPC_inbounds.json
{
"inbounds": [
{
"port": 31304,
"listen": "127.0.0.1",
"protocol": "trojan",
"tag": "trojangRPCTCP",
"settings": {
"clients": [
{
"password": "${uuid}",
"email": "default_Trojan_gRPC"
}
],
"fallbacks": [
{
"dest": "31300"
}
]
},
"streamSettings": {
"network": "grpc",
"grpcSettings": {
"serviceName": "${customPath}trojangrpc"
}
}
}
]
}
EOF
addClients "/etc/v2ray-agent/v2ray/conf/04_trojan_gRPC_inbounds.json" "${addClientsStatus}"
fi
# VMess_WS
if echo "${selectCustomInstallType}" | grep -q 3 || [[ "$1" == "all" ]]; then
fallbacksList=${fallbacksList}',{"path":"/'${customPath}'vws","dest":31299,"xver":1}'
getClients "${configPath}../tmp/05_VMess_WS_inbounds.json" "${addClientsStatus}"
cat <<EOF >/etc/v2ray-agent/v2ray/conf/05_VMess_WS_inbounds.json
{
"inbounds":[
{
"listen": "127.0.0.1",
"port": 31299,
"protocol": "vmess",
"tag":"VMessWS",
"settings": {
"clients": [
{
"id": "${uuid}",
"alterId": 0,
"add": "${add}",
"email": "default_VMess_WS"
}
]
},
"streamSettings": {
"network": "ws",
"security": "none",
"wsSettings": {
"acceptProxyProtocol": true,
"path": "/${customPath}vws"
}
}
}
]
}
EOF
addClients "/etc/v2ray-agent/v2ray/conf/05_VMess_WS_inbounds.json" "${addClientsStatus}"
fi
if echo "${selectCustomInstallType}" | grep -q 5 || [[ "$1" == "all" ]]; then
getClients "${configPath}../tmp/06_VLESS_gRPC_inbounds.json" "${addClientsStatus}"
cat <<EOF >/etc/v2ray-agent/v2ray/conf/06_VLESS_gRPC_inbounds.json
{
"inbounds":[
{
"port": 31301,
"listen": "127.0.0.1",
"protocol": "vless",
"tag":"VLESSGRPC",
"settings": {
"clients": [
{
"id": "${uuid}",
"add": "${add}",
"email": "default_VLESS_gRPC"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "grpc",
"grpcSettings": {
"serviceName": "${customPath}grpc"
}
}
}
]
}
EOF
addClients "/etc/v2ray-agent/v2ray/conf/06_VLESS_gRPC_inbounds.json" "${addClientsStatus}"
fi
# VLESS_TCP
getClients "${configPath}../tmp/02_VLESS_TCP_inbounds.json" "${addClientsStatus}"
local defaultPort=443
if [[ -n "${customPort}" ]]; then
defaultPort=${customPort}
fi
cat <<EOF >/etc/v2ray-agent/v2ray/conf/02_VLESS_TCP_inbounds.json
{
"inbounds":[
{
"port": ${defaultPort},
"protocol": "vless",
"tag":"VLESSTCP",
"settings": {
"clients": [
{
"id": "${uuid}",
"add":"${add}",
"email": "default_VLESS_TCP"
}
],
"decryption": "none",
"fallbacks": [
${fallbacksList}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"minVersion": "1.2",
"alpn": [
"http/1.1",
"h2"
],
"certificates": [
{
"certificateFile": "/etc/v2ray-agent/tls/${domain}.crt",
"keyFile": "/etc/v2ray-agent/tls/${domain}.key",
"ocspStapling": 3600,
"usage":"encipherment"
}
]
}
}
}
]
}
EOF
addClients "/etc/v2ray-agent/v2ray/conf/02_VLESS_TCP_inbounds.json" "${addClientsStatus}"
}
# Initialize Xray Trojan XTLS configuration file
initXrayFrontingConfig() {
echoContent red " ---> Trojan does not currently support xtls-rprx-vision"
exit 0
if [[ -z "${configPath}" ]]; then
echoContent red " ---> Not installed, please use script to install"
menu
exit 0
fi
if [[ "${coreInstallType}" != "1" ]]; then
echoContent red " ---> Available types are not installed"
fi
local xtlsType=
if echo ${currentInstallProtocolType} | grep -q trojan; then
xtlsType=VLESS
else
xtlsType=Trojan
fi
echoContent skyBlue "\nFunction 1/${totalProgress}: Switch to ${xtlsType}"
echoContent red "\n================================================ ================="
echoContent yellow "# Notes\n"
echoContent yellow "will replace the prefix with ${xtlsType}"
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 yellow "Execute again to switch to the last prefix\n"
echoContent yellow "1.Switch to ${xtlsType}"
echoContent red "================================================== ==============="
read -r -p "Please select:" selectType
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
}
# Move the last configuration file to a temporary file
movePreviousConfig() {
if [[ -n "${configPath}" ]]; then
if [[ -z "${realityStatus}" ]]; then
rm -rf "${configPath}../tmp/*" 2>/dev/null
mv ${configPath}[0][2-6]* ${configPath}../tmp/ 2>/dev/null
else
rm -rf "${configPath}../tmp/*"
mv ${configPath}[0][7-8]* ${configPath}../tmp/ 2>/dev/null
mv ${configPath}[0][2]* ${configPath}../tmp/ 2>/dev/null
fi
fi
}
#Initialize Xray configuration file
initXrayConfig() {
echoContent skyBlue "\nProgress$2/${totalProgress}: Initializing Xray configuration"
echo
local uuid=
local addClientsStatus=
if [[ -n "${currentUUID}" ]]; 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 "\n ---> Used successfully"
fi
fi
if [[ -z "${addClientsStatus}" ]]; then
echoContent yellow "Please enter custom UUID [need to be legal], [Enter] random UUID"
read -r -p 'UUID:' customUUID
if [[ -n ${customUUID} ]]; then
uuid=${customUUID}
else
uuid=$(/etc/v2ray-agent/xray/xray uuid)
fi
fi
if [[ -z "${addClientsStatus}" && -z "${uuid}" ]]; then
addClientsStatus=
echoContent red "\n ---> uuid reading error, randomly generated"
uuid=$(/etc/v2ray-agent/xray/xray uuid)
fi
if [[ -n "${uuid}" ]]; then
currentClients='[{"id":"'${uuid}'","add":"'${add}'","flow":"xtls-rprx-vision","email":"'${uuid}'-VLESS_TCP/TLS_Vision"}]'
echoContent yellow "\n ${uuid}"
fi
#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"
}
}
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
# outbounds
if [[ ! -f "/etc/v2ray-agent/xray/conf/10_ipv6_outbounds.json" ]]; then
if [[ -n "${pingIPv6}" ]]; then
cat <<EOF >/etc/v2ray-agent/xray/conf/10_ipv6_outbounds.json
{
"outbounds": [
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
}
]
}
EOF
else
cat <<EOF >/etc/v2ray-agent/xray/conf/10_ipv4_outbounds.json
{
"outbounds":[
{
"protocol":"freedom",
"settings":{
"domainStrategy":"UseIPv4"
},
"tag":"IPv4-out"
},
{
"protocol":"freedom",
"settings":{
"domainStrategy":"UseIPv6"
},
"tag":"IPv6-out"
},
{
"protocol":"freedom",
"settings": {},
"tag":"direct"
},
{
"protocol":"blackhole",
"tag":"blackhole-out"
}
]
}
EOF
fi
fi
# 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
if [[ ! -f "/etc/v2ray-agent/xray/conf/09_routing.json" ]]; then
cat <<EOF >/etc/v2ray-agent/xray/conf/09_routing.json
{
"routing": {
"rules": [
{
"type": "field",
"domain": [
"domain:gstatic.com",
"domain:googleapis.com"
],
"outboundTag": "direct"
}
]
}
}
EOF
fi
# VLESS_TCP_TLS_Vision
# Fall back nginx
local fallbacksList='{"dest":31300,"xver":0},{"alpn":"h2","dest":31302,"xver":0}'
# trojan
if echo "${selectCustomInstallType}" | grep -q 4 || [[ "$1" == "all" ]]; then
fallbacksList='{"dest":31296,"xver":1},{"alpn":"h2","dest":31302,"xver":0}'
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"}
]
},
"streamSettings": {
"network": "tcp",
"security": "none",
"tcpSettings": {
"acceptProxyProtocol": true
}
}
}
]
}
EOF
else
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
else
rm /etc/v2ray-agent/xray/conf/03_VLESS_WS_inbounds.json >/dev/null 2>&1
fi
# trojan_grpc
if echo "${selectCustomInstallType}" | grep -q 2 || [[ "$1" == "all" ]]; then
if ! echo "${selectCustomInstallType}" | grep -q 5 && [[ -n ${selectCustomInstallType} ]]; then
fallbacksList=${fallbacksList//31302/31304}
fi
cat <<EOF >/etc/v2ray-agent/xray/conf/04_trojan_gRPC_inbounds.json
{
"inbounds": [
{
"port": 31304,
"listen": "127.0.0.1",
"protocol": "trojan",
"tag": "trojangRPCTCP",
"settings": {
"clients": $(initXrayClients 2),
"fallbacks": [
{
"dest": "31300"
}
]
},
"streamSettings": {
"network": "grpc",
"grpcSettings": {
"serviceName": "${customPath}trojangrpc"
}
}
}
]
}
EOF
else
rm /etc/v2ray-agent/xray/conf/04_trojan_gRPC_inbounds.json >/dev/null 2>&1
fi
# VMess_WS
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
else
rm /etc/v2ray-agent/xray/conf/05_VMess_WS_inbounds.json >/dev/null 2>&1
fi
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
else
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": {
"minVersion": "1.2",
"alpn": [
"http/1.1",
"h2"
],
"certificates": [
{
"certificateFile": "/etc/v2ray-agent/tls/${domain}.crt",
"keyFile": "/etc/v2ray-agent/tls/${domain}.key",
"ocspStapling": 3600,
"usage":"encipherment"
}
]
}
}
}
]
}
EOF
else
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 "\n===================== Configure VLESS+Reality ==================== =\n"
initRealityPort
initRealityDest
initRealityClientServersName
initRealityKey
cat <<EOF >/etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json
{
"inbounds": [
{
"port": ${realityPort},
"protocol": "vless",
"tag": "VLESSReality",
"settings": {
"clients": $(initXrayClients 7),
"decryption": "none",
"fallbacks":[
{
"dest": "31305",
"xver": 1
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"show": false,
"dest": "${realityDestDomain}",
"xver": 0,
"serverNames": [
${realityServerNames}
],
"privateKey": "${realityPrivateKey}",
"publicKey": "${realityPublicKey}",
"maxTimeDiff": 70000,
"shortIds": [
"6ba85179e30d4fc2"
]
}
}
}
]
}
EOF
cat <<EOF >/etc/v2ray-agent/xray/conf/08_VLESS_reality_fallback_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
else
rm /etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json >/dev/null 2>&1
rm /etc/v2ray-agent/xray/conf/08_VLESS_reality_fallback_grpc_inbounds.json >/dev/null 2>&1
fi
installSniffing
}
#Initialize Xray Reality configuration
# Custom CDN IP
customCDNIP() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Add cloudflare custom CNAME"
echoContent red "\n================================================ ================="
echoContent yellow "# Notes"
echoContent yellow "\nTutorial address:"
echoContent skyBlue "https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip"
echoContent red "\nIf you don't understand Cloudflare optimization, please do not use it"
echoContent yellow "\n1.CNAME www.digitalocean.com"
echoContent yellow "2.CNAME who.int"
echoContent yellow "3.CNAME blog.hostmonit.com"
echoContent skyBlue "----------------------------"
read -r -p "Please select [Enter is not used]:" selectCloudflareType
case ${selectCloudflareType} in
1)
add="www.digitalocean.com"
;;
2)
add="who.int"
;;
3)
add="blog.hostmonit.com"
;;
*)
add="${domain}"
echoContent yellow "\n ---> Not used"
;;
esac
}
# General
defaultBase64Code() {
local type=$1
local email=$2
local id=$3
local add=$4
local user=
user=$(echo "${email}" | awk -F "[-]" '{print $1}')
port=${currentDefaultPort}
if [[ "${type}" == "vlesstcp" ]]; then
if [[ "${coreInstallType}" == "1" ]] && echo "${currentInstallProtocolType}" | grep -q 0; then
echoContent yellow " ---> Universal format (VLESS+TCP+TLS_Vision)"
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"
echoContent yellow " ---> Formatted plain text (VLESS+TCP+TLS_Vision)"
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}@${currentHost}:${currentDefaultPort}?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: ${currentDefaultPort}
uuid: ${id}
network: tcp
tls: true
udp: true
flow: xtls-rprx-vision
client-fingerprint: chrome
EOF
echoContent yellow " ---> QR code VLESS(VLESS+TCP+TLS_Vision)"
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"
elif [[ "${coreInstallType}" == 2 ]]; then
echoContent yellow " ---> Universal format (VLESS+TCP+TLS)"
echoContent green " vless://${id}@${currentHost}:${currentDefaultPort}?security=tls&encryption=none&host=${currentHost}&fp=chrome&headerType=none&type=tcp#${email}\n"
echoContent yellow " ---> Formatted plain text (VLESS+TCP+TLS)"
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}@${currentHost}:${currentDefaultPort}?security=tls&encryption=none&host=${currentHost}&fp=chrome&headerType=none&type=tcp#${email}
EOF
echoContent yellow " ---> QR code VLESS(VLESS+TCP+TLS)"
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"
fi
elif [[ "${type}" == "trojanTCPXTLS" ]]; then
echoContent yellow " ---> Common format (Trojan+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"
echoContent yellow " ---> Formatted plain text (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"
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
trojan://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}
EOF
echoContent yellow " ---> QR code Trojan(Trojan+TCP+TLS_Vision)"
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"
elif [[ "${type}" == "vmessws" ]]; then
qrCodeBase64Default=$(echo -n "{\"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}\"}" | base64 -w 0)
qrCodeBase64Default="${qrCodeBase64Default// /}"
echoContent yellow " ---> Universal json(VMess+WS+TLS)"
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"
echoContent yellow " ---> Universal vmess (VMess+WS+TLS) link"
echoContent green " vmess://${qrCodeBase64Default}\n"
echoContent yellow " ---> QR code vmess(VMess+WS+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: ${currentDefaultPort}
uuid: ${id}
alterId: 0
cipher: none
udp: true
tls: true
client-fingerprint: chrome
servername: ${currentHost}
network: ws
ws-opts:
path: /${currentPath}vws
headers:
Host: ${currentHost}
EOF
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\n"
elif [[ "${type}" == "vlessws" ]]; then
echoContent yellow " ---> Universal format (VLESS+WS+TLS)"
echoContent green " vless://${id}@${add}:${currentDefaultPort}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=/${currentPath}ws #${email}\n"
echoContent yellow " ---> Formatted plain text (VLESS+WS+TLS)"
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"
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
vless://${id}@${add}:${currentDefaultPort}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=/${currentPath}ws#${email}
EOF
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
- name: "${email}"
type: vless
server: ${add}
port: ${currentDefaultPort}
uuid: ${id}
udp: true
tls: true
network: ws
client-fingerprint: chrome
servername: ${currentHost}
ws-opts:
path: /${currentPath}ws
headers:
Host: ${currentHost}
EOF
echoContent yellow " ---> QR code VLESS(VLESS+WS+TLS)"
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}"
elif [[ "${type}" == "vlessgrpc" ]]; then
echoContent yellow " ---> Universal format (VLESS+gRPC+TLS)"
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"
echoContent yellow " ---> Formatted plain text (VLESS+gRPC+TLS)"
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"
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
vless://${id}@${add}:${currentDefaultPort}?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: ${currentDefaultPort}
uuid: ${id}
udp: true
tls: true
network: grpc
client-fingerprint: chrome
servername: ${currentHost}
grpc-opts:
grpc-service-name: ${currentPath}grpc
EOF
echoContent yellow " ---> QR code VLESS(VLESS+gRPC+TLS)"
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}"
elif [[ "${type}" == "trojan" ]]; then
# URLEncode
echoContent yellow " ---> Trojan(TLS)"
echoContent green " trojan://${id}@${currentHost}:${currentDefaultPort}?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}:${currentDefaultPort}?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: ${currentDefaultPort}
password: ${id}
client-fingerprint: chrome
udp: true
sni: ${currentHost}
EOF
echoContent yellow " ---> QR code Trojan(TLS)"
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
echoContent yellow " ---> Trojan gRPC(TLS)"
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"
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
trojan://${id}@${add}:${currentDefaultPort}?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: ${currentDefaultPort}
type: trojan
password: ${id}
network: grpc
sni: ${currentHost}
udp: true
grpc-opts:
grpc-service-name: ${currentPath}trojangrpc
EOF
echoContent yellow " ---> QR code Trojan gRPC(TLS)"
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"
elif [[ "${type}" == "hysteria" ]]; then
local hysteriaEmail=
hysteriaEmail=$(echo "${email}" | awk -F "[-]" '{print $1}')_hysteria
echoContent yellow " ---> Hysteria(TLS)"
local clashMetaPortTmp="port: ${hysteriaPort}"
local v2rayNPortHopping=
local mport=
if [[ -n "${portHoppingStart}" ]]; then
mport="mport=${portHoppingStart}-${portHoppingEnd}&"
clashMetaPortTmp="ports: ${portHoppingStart}-${portHoppingEnd}"
v2rayNPortHopping=",${portHoppingStart}-${portHoppingEnd}"
fi
echoContent green " hysteria://${currentHost}:${hysteriaPort}?${mport}protocol=${hysteriaProtocol}&auth=${id}&peer=${currentHost}&insecure=0&alpn=h3&upmbps=${hysteriaClientUploadSpeed}&downmbps=${hysteriaClientDownloadSpeed}#${hysteriaEmail}\n"
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
hysteria://${currentHost}:${hysteriaPort}?${mport}protocol=${hysteriaProtocol}&auth=${id}&peer=${currentHost}&insecure=0&alpn=h3&upmbps=${hysteriaClientUploadSpeed}&downmbps=${hysteriaClientDownloadSpeed}#${hysteriaEmail}
EOF
echoContent yellow " ---> v2rayN(hysteria+TLS)"
cat <<EOF >"/etc/v2ray-agent/hysteria/conf/client.json"
{
"server": "${currentHost}:${hysteriaPort}${v2rayNPortHopping}",
"protocol": "${hysteriaProtocol}",
"up_mbps": ${hysteriaClientUploadSpeed},
"down_mbps": ${hysteriaClientDownloadSpeed},
"http": { "listen": "127.0.0.1:10809", "timeout": 300, "disable_udp": false },
"socks5": { "listen": "127.0.0.1:10808", "timeout": 300, "disable_udp": false },
"obfs": "",
"auth_str":"${id}",
"alpn": "h3",
"acl": "acl/routes.acl",
"mmdb": "acl/Country.mmdb",
"server_name": "${currentHost}",
"insecure": false,
"recv_window_conn": 5767168,
"recv_window": 23068672,
"disable_mtu_discovery": true,
"resolver": "https://223.5.5.5/dns-query",
"retry": 3,
"retry_interval": 3,
"quit_on_disconnect": false,
"handshake_timeout": 15,
"idle_timeout": 30,
"fast_open": true,
"hop_interval": 120
}
EOF
local v2rayNConf=
v2rayNConf="$(cat /etc/v2ray-agent/hysteria/conf/client.json)"
echoContent green "${v2rayNConf}\n"
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
- name: "${hysteriaEmail}"
type: hysteria
server: ${currentHost}
${clashMetaPortTmp}
auth_str: ${id}
alpn:
- h3
protocol: ${hysteriaProtocol}
up: "${hysteriaClientUploadSpeed}"
down: "${hysteriaClientDownloadSpeed}"
sni: ${currentHost}
EOF
echoContent yellow " ---> QR code Hysteria(TLS)"
if [[ -n "${mport}" ]]; then
mport="mport%3D${portHoppingStart}-${portHoppingEnd}%26"
fi
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"
elif [[ "${type}" == "vlessReality" ]]; then
echoContent yellow " ---> Universal format (VLESS+reality+uTLS+Vision)"
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"
echoContent yellow " ---> Formatted plain text (VLESS+reality+uTLS+Vision)"
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"
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
vless://${id}@$(getPublicIP):${currentRealityPort}?encryption=none&security=reality&type=tcp&sni=${currentRealityServerNames}&fp=chrome&pbk=${currentRealityPublicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email}
EOF
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
- name: "${email}"
type: vless
server: $(getPublicIP)
port: ${currentRealityPort}
uuid: ${id}
network: tcp
tls: true
udp: true
flow: xtls-rprx-vision
servername: ${currentRealityServerNames}
reality-opts:
public-key: ${currentRealityPublicKey}
short-id: 6ba85179e30d4fc2
client-fingerprint: chrome
EOF
echoContent yellow " ---> QR code VLESS(VLESS+reality+uTLS+Vision)"
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"
elif [[ "${type}" == "vlessRealityGRPC" ]]; then
echoContent yellow " ---> Universal format (VLESS+reality+uTLS+gRPC)"
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"
echoContent yellow " ---> Formatted plain text (VLESS+reality+uTLS+gRPC)"
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"
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/default/${user}"
vless://${id}@$(getPublicIP):${currentRealityPort}?encryption=none&security=reality&type=grpc&sni=${currentRealityServerNames}&fp=chrome&pbk=${currentRealityPublicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email}
EOF
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${user}"
- name: "${email}"
type: vless
server: $(getPublicIP)
port: ${currentRealityPort}
uuid: ${id}
network: grpc
tls: true
udp: true
servername: ${currentRealityServerNames}
reality-opts:
public-key: ${currentRealityPublicKey}
short-id: 6ba85179e30d4fc2
grpc-opts:
grpc-service-name: "grpc"
client-fingerprint: chrome
EOF
echoContent yellow " ---> QR code VLESS(VLESS+reality+uTLS+gRPC)"
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"
elif [[ "${type}" == "tuic" ]]; then
if [[ -z "${email}" ]]; then
echoContent red " ---> Failed to read configuration, please reinstall"
exit 0
fi
echoContent yellow " ---> Formatted plain text (Tuic+TLS)"
echoContent green "Protocol type: Tuic, address: ${currentHost}, port: ${tuicPort}, uuid: ${id}, password: ${id}, congestion-controller:${tuicAlgorithm}, alpn: h3, account Name:${email}_tuic\n"
echoContent yellow " ---> v2rayN(Tuic+TLS)"
cat <<EOF >"/etc/v2ray-agent/tuic/conf/v2rayN.json"
{
"relay": {
"server": "${currentHost}:${tuicPort}",
"uuid": "${id}",
"password": "${id}",
"ip": "$(getPublicIP)",
"congestion_control": "${tuicAlgorithm}",
"alpn": ["h3"]
},
"local": {
"server": "127.0.0.1:7798"
},
"log_level": "warn"
}
EOF
local v2rayNConf=
v2rayNConf="$(cat /etc/v2ray-agent/tuic/conf/v2rayN.json)"
echoContent green "${v2rayNConf}"
cat <<EOF >>"/etc/v2ray-agent/subscribe_local/clashMeta/${email}"
- name: "${email}_tuic"
server: ${currentHost}
type: tuic
port: ${tuicPort}
uuid: ${id}
password: ${id}
alpn:
- h3
congestion-controller: ${tuicAlgorithm}
disable-sni: true
reduce-rtt: true
fast-open: true
heartbeat-interval: 8000
request-timeout: 8000
max-udp-relay-packet-size: 1500
max-open-streams: 100
ip-version: dual
smux:
enabled: false
EOF
fi
}
# account
showAccounts() {
readInstallType
readInstallProtocolType
readConfigHostPathUUID
readHysteriaConfig
readXrayCoreRealityConfig
readHysteriaPortHopping
readTuicConfig
echo
echoContent skyBlue "\nProgress$1/${totalProgress}: account"
local show
# VLESS TCP
if echo "${currentInstallProtocolType}" | grep -q trojan; then
echoContent skyBlue "===================== Trojan TCP TLS_Vision ======================\n"
jq .inbounds[0].settings.clients ${configPath}02_trojan_TCP_inbounds.json | jq -c '.[]' | while read -r user; do
local email=
email=$(echo "${user}" | jq -r .email)
echoContent skyBlue "\n --->Account:${email}"
defaultBase64Code trojanTCPXTLS "${email}" "$(echo "${user}" | jq -r .password)"
done
elif echo ${currentInstallProtocolType} | grep -q 0; then
show=1
echoContent skyBlue "============================= VLESS TCP TLS_Vision ==============================\n"
jq .inbounds[0].settings.clients ${configPath}02_VLESS_TCP_inbounds.json | jq -c '.[]' | while read -r user; do
local email=
email=$(echo "${user}" | jq -r .email)
echoContent skyBlue "\n --->Account:${email}"
echo
defaultBase64Code vlesstcp "${email}" "$(echo "${user}" | jq -r .id)"
done
fi
# VLESS WS
if echo ${currentInstallProtocolType} | grep -q 1; then
echoContent skyBlue "\n================================ VLESS WS TLS CDN ================================\n"
jq .inbounds[0].settings.clients ${configPath}03_VLESS_WS_inbounds.json | jq -c '.[]' | while read -r user; do
local email=
email=$(echo "${user}" | jq -r .email)
echoContent skyBlue "\n --->Account:${email}"
echo
local path="${currentPath}ws"
local count=
while read -r line; do
if [[ -n "${line}" ]]; then
defaultBase64Code vlessws "${email}${count}" "$(echo "${user}" | jq -r .id)" "${line}"
count=$((count + 1))
fi
done < <(echo "${currentAdd}" | tr ',' '\n')
done
fi
#VLESS grpc
if echo ${currentInstallProtocolType} | grep -q 5; then
echoContent skyBlue "\n=============================== VLESS gRPC TLS CDN ===============================\n"
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)
echoContent skyBlue "\n --->Account:${email}"
echo
local count=
while read -r line; do
if [[ -n "${line}" ]]; then
defaultBase64Code vlessgrpc "${email}${count}" "$(echo "${user}" | jq -r .id)" "${line}"
count=$((count + 1))
fi
done < <(echo "${currentAdd}" | tr ',' '\n')
done
fi
# VMess WS
if echo ${currentInstallProtocolType} | grep -q 3; then
echoContent skyBlue "\n================================ VMess WS TLS CDN ================================\n"
local path="${currentPath}vws"
if [[ ${coreInstallType} == "1" ]]; then
path="${currentPath}vws"
fi
jq .inbounds[0].settings.clients ${configPath}05_VMess_WS_inbounds.json | jq -c '.[]' | while read -r user; do
local email=
email=$(echo "${user}" | jq -r .email)
echoContent skyBlue "\n --->Account:${email}"
echo
local count=
while read -r line; do
if [[ -n "${line}" ]]; then
defaultBase64Code vmessws "${email}${count}" "$(echo "${user}" | jq -r .id)" "${line}"
count=$((count + 1))
fi
done < <(echo "${currentAdd}" | tr ',' '\n')
done
fi
#trojantcp
if echo ${currentInstallProtocolType} | grep -q 4; then
echoContent skyBlue "\n================================== Trojan TLS ==================================\n"
jq .inbounds[0].settings.clients ${configPath}04_trojan_TCP_inbounds.json | jq -c '.[]' | while read -r user; do
local email=
email=$(echo "${user}" | jq -r .email)
echoContent skyBlue "\n --->Account:${email}"
defaultBase64Code trojan "${email}" "$(echo "${user}" | jq -r .password)"
done
fi
if echo ${currentInstallProtocolType} | grep -q 2; then
echoContent skyBlue "\n================================ Trojan gRPC TLS ================================\n"
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)
echoContent skyBlue "\n --->Account:${email}"
echo
local count=
while read -r line; do
if [[ -n "${line}" ]]; then
defaultBase64Code trojangrpc "${email}${count}" "$(echo "${user}" | jq -r .password)" "${line}"
count=$((count + 1))
fi
done < <(echo "${currentAdd}" | tr ',' '\n')
done
fi
if echo ${currentInstallProtocolType} | grep -q 6; then
echoContent skyBlue "\n================================ Hysteria TLS ================================\n"
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"
jq .auth.config ${hysteriaConfigPath}config.json | jq -r '.[]' | while read -r user; do
local defaultUser=
local uuidType=
uuidType=".id"
if [[ "${frontingType}" == "02_trojan_TCP_inbounds" ]]; then
uuidType=".password"
fi
defaultUser=$(jq '.inbounds[0].settings.clients[]|select('${uuidType}'=="'"${user}"'")' ${configPath}${frontingType}.json)
local email=
email=$(echo "${defaultUser}" | jq -r .email)
local hysteriaEmail=
hysteriaEmail=$(echo "${email}" | awk -F "[_]" '{print $1}')_hysteria
if [[ -n ${defaultUser} ]]; then
echoContent skyBlue "\n ---> Account:$(echo "${hysteriaEmail}" | awk -F "[-]" '{print $1"_hysteria"}')"
echo
defaultBase64Code hysteria "${hysteriaEmail}" "${user}"
fi
done
fi
# VLESS reality vision
if echo ${currentInstallProtocolType} | grep -q 7; then
show=1
echoContent skyBlue "============================= VLESS reality_vision ==============================\n"
jq .inbounds[0].settings.clients ${configPath}07_VLESS_vision_reality_inbounds.json | jq -c '.[]' | while read -r user; do
local email=
email=$(echo "${user}" | jq -r .email)
echoContent skyBlue "\n --->Account:${email}"
echo
defaultBase64Code vlessReality "${email}" "$(echo "${user}" | jq -r .id)"
done
fi
# VLESS reality
if echo ${currentInstallProtocolType} | grep -q 8; then
show=1
echoContent skyBlue "============================== VLESS reality_gRPC ===============================\n"
jq .inbounds[0].settings.clients ${configPath}08_VLESS_reality_fallback_grpc_inbounds.json | jq -c '.[]' | while read -r user; do
local email=
email=$(echo "${user}" | jq -r .email)
echoContent skyBlue "\n --->Account:${email}"
echo
defaultBase64Code vlessRealityGRPC "${email}" "$(echo "${user}" | jq -r .id)"
done
fi
#tuic
if echo ${currentInstallProtocolType} | grep -q 9; then
echoContent skyBlue "\n================================ Tuic TLS ================================\n"
echoContent yellow "\n --->Tuic will be warmer and may have a smoother user experience than Hysteria."
jq -r .users[] "${tuicConfigPath}config.json" | while read -r id; do
local tuicEmail=
tuicEmail=$(jq -r '.inbounds[0].settings.clients[]|select(.id=="'"${id}"'")|.email' ${configPath}${frontingType}. json | awk -F "[-]" '{print $1}')
if [[ -n ${tuicEmail} ]]; then
echoContent skyBlue "\n --->Account:${tuicEmail}_tuic"
echo
defaultBase64Code tuic "${tuicEmail}" "${id}"
fi
done
fi
if [[ -z ${show} ]]; then
echoContent red " ---> not installed"
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 " ---> 302 redirection set up successfully"
exit 0
fi
fi
echoContent red " ---> 302 redirection setting failed, please double check whether it is the same as the example"
backupNginxConfig restoreBackup
}
# Backup and restore nginx files
backupNginxConfig() {
if [[ "$1" == "backup" ]]; then
cp ${nginxConfigPath}alone.conf /etc/v2ray-agent/alone_backup.conf
echoContent green " ---> nginx configuration file backup successful"
fi
if [[ "$1" == "restoreBackup" ]] && [[ -f "/etc/v2ray-agent/alone_backup.conf" ]]; then
cp /etc/v2ray-agent/alone_backup.conf ${nginxConfigPath}alone.conf
echoContent green " ---> nginx configuration file restoration backup successful"
rm /etc/v2ray-agent/alone_backup.conf
fi
}
# Add 302 configuration
addNginx302() {
# local line302Result=
# line302Result=$(| tail -n 1)
local count=1
grep -n "Strict-Transport-Security" <"${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 " ---> 302 Add failed"
backupNginxConfig restoreBackup
fi
done
}
# Update camouflage station
updateNginxBlog() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Change disguise site"
if ! echo "${currentInstallProtocolType}" | grep -q "0" || [[ -z "${coreInstallType}" ]]; then
echoContent red "\n ---> Due to environmental dependencies, please install Xray-core's VLESS_TCP_TLS_Vision first"
exit 0
fi
echoContent red "================================================== =========== ===="
echoContent yellow "# If you need to customize, please manually copy the template file to ${nginxStaticPath} \n"
echoContent yellow "1.Newbie guide"
echoContent yellow "2.Game website"
echoContent yellow "3.Personal blog 01"
echoContent yellow "4.Enterprise Station"
echoContent yellow "5.Unlock encrypted music file template [https://github.com/ix64/unlock-music]"
echoContent yellow "6.mikutap[https://github.com/HFIProgramming/mikutap]"
echoContent yellow "7.Enterprise Station 02"
echoContent yellow "8.Personal blog 02"
echoContent yellow "9.404 automatically jumps to baidu"
echoContent yellow "10.302 redirect website"
echoContent red "================================================== ==============="
read -r -p "Please select:" selectInstallNginxBlogType
if [[ "${selectInstallNginxBlogType}" == "10" ]]; then
echoContent red "\n================================================ ================="
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."
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 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 " ---> Removed 302 redirect successfully"
exit 0
fi
fi
if [[ "${selectInstallNginxBlogType}" =~ ^[1-9]$ ]]; then
rm -rf "${nginxStaticPath}"
wget -q -P "${nginxStaticPath}" "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${selectInstallNginxBlogType}.zip" >/dev/null
unzip -o "${nginxStaticPath}html${selectInstallNginxBlogType}.zip" -d "${nginxStaticPath}" >/dev/null
rm -f "${nginxStaticPath}html${selectInstallNginxBlogType}.zip*"
echoContent green " ---> Pseudo site replaced successfully"
else
echoContent red " ---> Wrong selection, please select again"
updateNginxBlog
fi
}
#Add new port
addCorePort() {
readHysteriaConfig
echoContent skyBlue "\nFunction 1/${totalProgress}: Add new port"
echoContent red "\n================================================ ================="
echoContent yellow "# Notes\n"
echoContent yellow "Support batch addition"
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 yellow "Input example:2053,2083,2087\n"
echoContent yellow "1.Check the added port"
echoContent yellow "2.Add port"
echoContent yellow "3.Delete port"
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
# open port
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 " ---> Added successfully"
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 "\n ---> The number entered is wrong, please choose again"
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 " ---> Give up uninstalling"
menu
exit 0
fi
echoContent yellow " ---> The script will not delete acme related configurations. To delete, please execute manually [rm -rf /root/.acme.sh]"
handleNginx stop
if [[ -z $(pgrep -f "nginx") ]]; then
echoContent green " ---> Stop Nginx successfully"
fi
if [[ "${coreInstallType}" == "1" ]]; then
handleXray stop
rm -rf /etc/systemd/system/xray.service
echoContent green " ---> Delete Xray and it will start automatically after booting"
elif [[ "${coreInstallType}" == "2" ]]; then
handleV2Ray stop
rm -rf /etc/systemd/system/v2ray.service
echoContent green " ---> Delete V2Ray and it will start automatically after booting"
fi
if [[ -z "${hysteriaConfigPath}" ]]; then
handleHysteria stop
rm -rf /etc/systemd/system/hysteria.service
echoContent green " ---> Delete Hysteria and it will start automatically after booting"
fi
if [[ -z "${tuicConfigPath}" ]]; then
handleTuic stop
rm -rf /etc/systemd/system/tuic.service
echoContent green " ---> Delete Tuic and start automatically after booting"
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
if [[ -d "${nginxStaticPath}" && -f "${nginxStaticPath}/check" ]]; then
rm -rf "${nginxStaticPath}"
echoContent green " ---> Deletion of fake website completed"
fi
rm -rf /usr/bin/vasma
rm -rf /usr/sbin/vasma
echoContent green " ---> Uninstallation of shortcut completed"
echoContent green " ---> Uninstall v2ray-agent script completed"
}
# Modify V2Ray CDN node
updateV2RayCDN() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Modify CDN node"
if [[ -n "${currentAdd}" ]]; then
echoContent red "================================================== ==============="
echoContent yellow "1.CNAME www.digitalocean.com"
echoContent yellow "2.CNAME who.int"
echoContent yellow "3.CNAME blog.hostmonit.com"
echoContent yellow "4.Manual input [can enter multiple, such as:1.1.1.1,1.1.2.2, cloudflare.com separated by commas]"
echoContent yellow "5.Remove CDN node"
echoContent red "================================================== ==============="
read -r -p "Please select:" selectCDNType
case ${selectCDNType} in
1)
setDomain="www.digitalocean.com"
;;
2)
setDomain="who.int"
;;
3)
setDomain="blog.hostmonit.com"
;;
4)
read -r -p "Please enter the CDN IP or domain name you want to customize:" setDomain
;;
5)
setDomain=${currentHost}
;;
esac
if [[ -n "${setDomain}" ]]; then
local cdnAddressResult=
cdnAddressResult=$(jq -r ".inbounds[0].add = \"${setDomain}\" " ${configPath}${frontingType}.json)
echo "${cdnAddressResult}" | jq . >${configPath}${frontingType}.json
echoContent green " ---> CDN modified successfully"
fi
else
echoContent red " ---> Available types are not installed"
fi
}
# manageUser User management
manageUser() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Multi-user management"
echoContent skyBlue "------------------------------------------------- ------"
echoContent yellow "1.Add user"
echoContent yellow "2.Delete user"
echoContent skyBlue "------------------------------------------------- ------"
read -r -p "Please select:" manageUserType
if [[ "${manageUserType}" == "1" ]]; then
addUser
elif [[ "${manageUserType}" == "2" ]]; then
removeUser
else
echoContent red " ---> Wrong selection"
fi
}
# Custom uuid
customUUID() {
read -r -p "Please enter a legal UUID, [Enter] random UUID:" currentCustomUUID
echo
if [[ -z "${currentCustomUUID}" ]]; then
currentCustomUUID=$(${ctlPath} uuid)
echoContent yellow "uuid${currentCustomUUID}\n"
else
jq -r -c '.inbounds[0].settings.clients[].id' ${configPath}${frontingType}.json | while read -r line; do
if [[ "${line}" == "${currentCustomUUID}" ]]; then
echo >/tmp/v2ray-agent
fi
done
if [[ -f "/tmp/v2ray-agent" && -n $(cat /tmp/v2ray-agent) ]]; then
echoContent red " ---> UUID cannot be repeated"
rm /tmp/v2ray-agent
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 defaultConfig=${frontingType}
if echo "${currentInstallProtocolType}" | grep -q "7" && [[ -z "${frontingType}" ]]; then
defaultConfig="07_VLESS_vision_reality_inbounds"
fi
jq -r -c '.inbounds[0].settings.clients[].email' ${configPath}${defaultConfig}.json | while read -r line; do
if [[ "${line}" == "${currentCustomEmail}" ]]; then
echo >/tmp/v2ray-agent
fi
done
if [[ -f "/tmp/v2ray-agent" && -n $(cat /tmp/v2ray-agent) ]]; then
echoContent red " ---> email cannot be repeated"
rm /tmp/v2ray-agent
exit 0
fi
fi
#fi _
}
# Add user
addUserXray() {
readConfigHostPathUUID
read -r -p "Please enter the number of users to add:" userNum
echo
if [[ -z ${userNum} || ${userNum} -le 0 ]]; then
echoContent red " ---> Incorrect input, please re-enter"
exit 0
fi
# Generate user
if [[ "${userNum}" == "1" ]]; then
customUUID
customUserEmail
fi
while [[ ${userNum} -gt 0 ]]; do
local users=
((userNum--)) || true
if [[ -n "${currentCustomUUID}" ]]; then
uuid=${currentCustomUUID}
else
uuid=$(${ctlPath} uuid)
fi
local email=
if [[ -z "${currentCustomEmail}" ]]; then
email=${uuid}
else
email=${currentCustomEmail}
fi
# VLESS TCP
if echo "${currentInstallProtocolType}" | grep -q "0"; then
local clients=
clients=$(initXrayClients 0 "${uuid}" "${email}")
clients=$(jq -r ".inbounds[0].settings.clients = ${clients}" ${configPath}${frontingType}.json)
echo "${clients}" | jq . >${configPath}${frontingType}.json
fi
# VLESS WS
if echo "${currentInstallProtocolType}" | grep -q "1"; then
local clients=
clients=$(initXrayClients 1 "${uuid}" "${email}")
clients=$(jq -r ".inbounds[0].settings.clients = ${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=
clients=$(initXrayClients 2 "${uuid}" "${email}")
clients=$(jq -r ".inbounds[0].settings.clients = ${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=
clients=$(initXrayClients 3 "${uuid}" "${email}")
clients=$(jq -r ".inbounds[0].settings.clients = ${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=
clients=$(initXrayClients 4 "${uuid}" "${email}")
clients=$(jq -r ".inbounds[0].settings.clients = ${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=
clients=$(initXrayClients 5 "${uuid}" "${email}")
clients=$(jq -r ".inbounds[0].settings.clients = ${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=
clients=$(initXrayClients 7 "${uuid}" "${email}")
clients=$(jq -r ".inbounds[0].settings.clients = ${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=
clients=$(initXrayClients 8 "${uuid}" "${email}")
clients=$(jq -r ".inbounds[0].settings.clients = ${clients}" ${configPath}08_VLESS_reality_fallback_grpc_inbounds.json)
echo "${clients}" | jq . >${configPath}08_VLESS_reality_fallback_grpc_inbounds.json
fi
# hysteria
if echo "${currentInstallProtocolType}" | grep -q "6"; then
local clients=
clients=$(initXrayClients 6 "${uuid}" "${email}")
clients=$(jq -r ".auth.config = ${clients}" ${hysteriaConfigPath}config.json)
echo "${clients}" | jq . >${hysteriaConfigPath}config.json
fi
if echo ${currentInstallProtocolType} | grep -q 9; then
local tuicResult
tuicResult=$(jq -r ".users.\"${uuid}\" += \"${uuid}\"" "${tuicConfigPath}config.json")
echo "${tuicResult}" | jq . >"${tuicConfigPath}config.json"
fi
done
reloadCore
echoContent green " ---> Adding completed"
manageAccount 1
}
# Add user
addUser() {
echoContent yellow "After adding a new user, you need to check the subscription again"
read -r -p "Please enter the number of users to add:" userNum
echo
if [[ -z ${userNum} || ${userNum} -le 0 ]]; then
echoContent red " ---> Incorrect input, please re-enter"
exit 0
fi
# Generate user
if [[ "${userNum}" == "1" ]]; then
customUUID
customUserEmail
fi
while [[ ${userNum} -gt 0 ]]; do
local users=
((userNum--)) || true
if [[ -n "${currentCustomUUID}" ]]; then
uuid=${currentCustomUUID}
else
uuid=$(${ctlPath} uuid)
fi
if [[ -n "${currentCustomEmail}" ]]; then
email=${currentCustomEmail}_${uuid}
else
email=${currentHost}_${uuid}
fi
#Compatible with v2ray-core
users="{\"id\":\"${uuid}\",\"flow\":\"xtls-rprx-vision\",\"email\":\"${email}\",\"alterId\":0}"
if [[ "${coreInstallType}" == "2" ]]; then
users="{\"id\":\"${uuid}\",\"email\":\"${email}\",\"alterId\":0}"
fi
if echo ${currentInstallProtocolType} | grep -q 0; then
local vlessUsers="${users//\,\"alterId\":0/}"
vlessUsers="${users//${email}/${email}_VLESS_TCP}"
local vlessTcpResult
vlessTcpResult=$(jq -r ".inbounds[0].settings.clients += [${vlessUsers}]" ${configPath}${frontingType}.json)
echo "${vlessTcpResult}" | jq . >${configPath}${frontingType}.json
fi
if echo ${currentInstallProtocolType} | grep -q trojan; then
local trojanXTLSUsers="${users//\,\"alterId\":0/}"
trojanXTLSUsers="${trojanXTLSUsers//${email}/${email}_Trojan_TCP}"
trojanXTLSUsers=${trojanXTLSUsers//"id"/"password"}
local trojanXTLSResult
trojanXTLSResult=$(jq -r ".inbounds[0].settings.clients += [${trojanXTLSUsers}]" ${configPath}${frontingType}.json)
echo "${trojanXTLSResult}" | jq . >${configPath}${frontingType}.json
fi
if echo ${currentInstallProtocolType} | grep -q 1; then
local vlessUsers="${users//\,\"alterId\":0/}"
vlessUsers="${vlessUsers//${email}/${email}_VLESS_TCP}"
vlessUsers="${vlessUsers//\"flow\":\"xtls-rprx-vision\"\,/}"
local vlessWsResult
vlessWsResult=$(jq -r ".inbounds[0].settings.clients += [${vlessUsers}]" ${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="${users//\"flow\":\"xtls-rprx-vision\"\,/}"
trojangRPCUsers="${trojangRPCUsers//${email}/${email}_Trojan_gRPC}"
trojangRPCUsers="${trojangRPCUsers//\,\"alterId\":0/}"
trojangRPCUsers=${trojangRPCUsers//"id"/"password"}
local trojangRPCResult
trojangRPCResult=$(jq -r ".inbounds[0].settings.clients += [${trojangRPCUsers}]" ${configPath}04_trojan_gRPC_inbounds.json)
echo "${trojangRPCResult}" | jq . >${configPath}04_trojan_gRPC_inbounds.json
fi
if echo ${currentInstallProtocolType} | grep -q 3; then
local vmessUsers="${users//\"flow\":\"xtls-rprx-vision\"\,/}"
vmessUsers="${vmessUsers//${email}/${email}_VMess_TCP}"
local vmessWsResult
vmessWsResult=$(jq -r ".inbounds[0].settings.clients += [${vmessUsers}]" ${configPath}05_VMess_WS_inbounds.json)
echo "${vmessWsResult}" | jq . >${configPath}05_VMess_WS_inbounds.json
fi
if echo ${currentInstallProtocolType} | grep -q 5; then
local vlessGRPCUsers="${users//\"flow\":\"xtls-rprx-vision\"\,/}"
vlessGRPCUsers="${vlessGRPCUsers//\,\"alterId\":0/}"
vlessGRPCUsers="${vlessGRPCUsers//${email}/${email}_VLESS_gRPC}"
local vlessGRPCResult
vlessGRPCResult=$(jq -r ".inbounds[0].settings.clients += [${vlessGRPCUsers}]" ${configPath}06_VLESS_gRPC_inbounds.json)
echo "${vlessGRPCResult}" | jq . >${configPath}06_VLESS_gRPC_inbounds.json
fi
if echo ${currentInstallProtocolType} | grep -q 4; then
local trojanUsers="${users//\"flow\":\"xtls-rprx-vision\"\,/}"
trojanUsers="${trojanUsers//id/password}"
trojanUsers="${trojanUsers//\,\"alterId\":0/}"
trojanUsers="${trojanUsers//${email}/${email}_Trojan_TCP}"
local trojanTCPResult
trojanTCPResult=$(jq -r ".inbounds[0].settings.clients += [${trojanUsers}]" ${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 ".auth.config += [\"${uuid}\"]" ${hysteriaConfigPath}config.json)
echo "${hysteriaResult}" | jq . >${hysteriaConfigPath}config.json
fi
done
reloadCore
echoContent green " ---> Adding completed"
manageAccount 1
}
# Remove user
removeUser() {
local uuid=
if echo ${currentInstallProtocolType} | grep -q 0 || echo ${currentInstallProtocolType} | grep -q trojan; then
jq -r -c .inbounds[0].settings.clients[].email ${configPath}${frontingType}.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|length' ${configPath}${frontingType}.json) -lt ${delUserIndex} ]]; then
echoContent red " ---> Wrong selection"
else
delUserIndex=$((delUserIndex - 1))
local vlessTcpResult
uuid=$(jq -r ".inbounds[0].settings.clients[${delUserIndex}].id" ${configPath}${frontingType}.json)
vlessTcpResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}${frontingType}.json)
echo "${vlessTcpResult}" | jq . >${configPath}${frontingType}.json
fi
elif [[ -n "${realityStatus}" ]]; then
jq -r -c .inbounds[0].settings.clients[].email ${configPath}07_VLESS_vision_reality_inbounds.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|length' ${configPath}07_VLESS_vision_reality_inbounds.json) -lt ${delUserIndex} ]]; then
echoContent red " ---> Wrong selection"
else
delUserIndex=$((delUserIndex - 1))
local vlessRealityResult
uuid=$(jq -r ".inbounds[0].settings.clients[${delUserIndex}].id" ${configPath}${frontingType}.json)
vlessRealityResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}07_VLESS_vision_reality_inbounds.json)
echo "${vlessRealityResult}" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json
fi
fi
if [[ -n "${delUserIndex}" ]]; then
if echo ${currentInstallProtocolType} | grep -q 1; then
local vlessWSResult
vlessWSResult=$(jq -r 'del(.inbounds[0].settings.clients['${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}'])' ${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}'])' ${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}'])' ${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}'])' ${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(.auth.config['${delUserIndex}'])' ${hysteriaConfigPath}config.json)
echo "${hysteriaResult}" | jq . >${hysteriaConfigPath}config.json
fi
if echo ${currentInstallProtocolType} | grep -q 7; then
local vlessRealityResult
vlessRealityResult=$(jq -r 'del(.inbounds[0].settings.clients['${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}'])' ${configPath}08_VLESS_reality_fallback_grpc_inbounds.json)
echo "${vlessRealityGRPCResult}" | jq . >${configPath}08_VLESS_reality_fallback_grpc_inbounds.json
fi
if echo ${currentInstallProtocolType} | grep -q 9; then
local tuicResult
tuicResult=$(jq -r "del(.users.\"${uuid}\")" "${tuicConfigPath}config.json")
echo "${tuicResult}" | jq . >"${tuicConfigPath}config.json"
fi
reloadCore
fi
manageAccount 1
}
# update script
updateV2RayAgent() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Update v2ray-agent script"
rm -rf /etc/v2ray-agent/install.sh
# 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"
#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 "\n ---> Update completed"
echoContent yellow " ---> Please manually execute [vasma] to open the script"
echoContent green " ---> Current version: ${version}\n"
echoContent yellow "If the update fails, please manually execute the following command\n"
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 " ---> ufw closed successfully"
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 " ---> firewalld closed successfully"
fi
}
# Install BBR
bbrInstall() {
echoContent red "\n================================================ ================="
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"
echoContent yellow "1.Installation script [recommended original BBR+FQ]"
echoContent yellow "2.Return to the home directory"
echoContent red "================================================== ==============="
read -r -p "Please select:" installBBRStatus
if [[ "${installBBRStatus}" == "1" ]]; then
wget -N --no-check-certificate "https://raw.githubusercontent.com/ylx2016/Linux-NetSpeed/master/tcp.sh" && chmod +x tcp.sh && ./tcp.sh
else
menu
fi
}
# View and check logs
checkLog() {
if [[ -z "${configPath}" && -z "${realityStatus}" ]]; then
echoContent red " ---> The installation directory is not detected, please execute the script to install the content"
exit 0
fi
local realityLogShow=
local logStatus=false
if grep -q "access" ${configPath}00_log.json; then
logStatus=true
fi
echoContent skyBlue "\nFunction$1/${totalProgress}: View log"
echoContent red "\n================================================ ================="
echoContent yellow "# It is recommended to only open the access log during debugging\n"
if [[ "${logStatus}" == "false" ]]; then
echoContent yellow "1.Open access log"
else
echoContent yellow "1.Close access log"
fi
echoContent yellow "2.Monitor access log"
echoContent yellow "3.Monitor error log"
echoContent yellow "4.View certificate scheduled task log"
echoContent yellow "5.View certificate installation log"
echoContent yellow "6.Clear the log"
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 [[ -n ${realityStatus} ]]; 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
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 "The shortcut is created successfully, you can execute [vasma] to reopen the script"
fi
fi
}
# Check ipv6, ipv4
checkIPv6() {
currentIPv6IP=$(curl -s -6 http://www.cloudflare.com/cdn-cgi/trace | grep "ip" | cut -d "=" -f 2)
if [[ -z "${currentIPv6IP}" ]]; then
echoContent red " ---> does not support ipv6"
exit 0
fi
}
# ipv6 offload
ipv6Routing() {
if [[ -z "${configPath}" ]]; then
echoContent red " ---> Not installed, please use script to install"
menu
exit 0
fi
checkIPv6
echoContent skyBlue "\nFunction 1/${totalProgress}: IPv6 offload"
echoContent red "\n================================================ ============ ====="
echoContent yellow "1.View the diverted domain name"
echoContent yellow "2.Add domain name"
echoContent yellow "3.Set IPv6 global"
echoContent yellow "4.Uninstall IPv6 offloading"
echoContent red "================================================== ==============="
read -r -p "Please select:" ipv6Status
if [[ "${ipv6Status}" == "1" ]]; then
jq -r -c '.routing.rules[]|select (.outboundTag=="IPv6-out")|.domain' ${configPath}09_routing.json | jq -r
exit 0
elif [[ "${ipv6Status}" == "2" ]]; then
echoContent red "================================================== ==============="
echoContent yellow "# Notes\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 enter the domain name according to the above example:" domainList
addInstallRouting IPv6-out outboundTag "${domainList}"
unInstallOutbounds IPv6-out
outbounds=$(jq -r '.outbounds += [{"protocol":"freedom","settings":{"domainStrategy":"UseIPv6"},"tag":"IPv6-out"}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
echoContent green " ---> Added successfully"
elif [[ "${ipv6Status}" == "3" ]]; then
echoContent red "================================================== ==============="
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"
read -r -p "Confirm settings? [y/n]:" IPv6OutStatus
if [[ "${IPv6OutStatus}" == "y" ]]; then
cat <<EOF >${configPath}10_ipv4_outbounds.json
{
"outbounds":[
{
"protocol":"freedom",
"settings":{
"domainStrategy":"UseIPv6"
},
"tag":"IPv6-out"
}
]
}
EOF
rm ${configPath}09_routing.json >/dev/null 2>&1
echoContent green " ---> IPv6 global outbound setting successful"
else
echoContent green " ---> Abandon settings"
exit 0
fi
elif [[ "${ipv6Status}" == "4" ]]; then
unInstallRouting IPv6-out outboundTag
unInstallOutbounds IPv6-out
if ! grep -q "IPv4-out" <"${configPath}10_ipv4_outbounds.json"; then
outbounds=$(jq -r '.outbounds += [{"protocol":"freedom","settings": {"domainStrategy": "UseIPv4"},"tag":"IPv4-out"}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
fi
echoContent green " ---> IPv6 offload uninstall successful"
else
echoContent red " ---> Wrong selection"
exit 0
fi
reloadCore
}
# bt download management
btTools() {
if [[ -z "${configPath}" ]]; then
echoContent red " ---> Not installed, please use script to install"
menu
exit 0
fi
echoContent skyBlue "\nFunction 1/${totalProgress}: bt download management"
echoContent red "\n================================================ ================="
if [[ -f ${configPath}09_routing.json ]] && grep -q bittorrent <${configPath}09_routing.json; then
echoContent yellow "Current status: disabled"
else
echoContent yellow "Current status: not disabled"
fi
echoContent yellow "1.Disable"
echoContent yellow "2.Open"
echoContent red "================================================== ==============="
read -r -p "Please select:" btStatus
if [[ "${btStatus}" == "1" ]]; then
if [[ -f "${configPath}09_routing.json" ]]; then
unInstallRouting blackhole-out outboundTag
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
unInstallOutbounds blackhole-out
outbounds=$(jq -r '.outbounds += [{"protocol":"blackhole","tag":"blackhole-out"}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
echoContent green " ---> BT download disabled successfully"
elif [[ "${btStatus}" == "2" ]]; then
unInstallSniffing
unInstallRouting blackhole-out outboundTag bittorrent
# unInstallOutbounds blackhole-out
echoContent green " ---> BT download opened successfully"
else
echoContent red " ---> Wrong selection"
exit 0
fi
reloadCore
}
# Domain name blacklist
blacklist() {
if [[ -z "${configPath}" ]]; then
echoContent red " ---> Not installed, please use script to install"
menu
exit 0
fi
echoContent skyBlue "\nProgress$1/${totalProgress}: Domain name blacklist"
echoContent red "\n================================================ ================="
echoContent yellow "1.View blocked domain names"
echoContent yellow "2.Add domain name"
echoContent yellow "3.Block domestic domain names"
echoContent yellow "4.Delete blacklist"
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 "# 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"
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"
read -r -p "Please enter the domain name according to the above example:" domainList
if [[ -f "${configPath}09_routing.json" ]]; then
addInstallRouting blackhole-out outboundTag "${domainList}"
fi
unInstallOutbounds blackhole-out
outbounds=$(jq -r '.outbounds += [{"protocol":"blackhole","tag":"blackhole-out"}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
echoContent green " ---> Added successfully"
elif [[ "${blacklistStatus}" == "3" ]]; then
addInstallRouting blackhole-out outboundTag "cn"
unInstallOutbounds blackhole-out
outbounds=$(jq -r '.outbounds += [{"protocol":"blackhole","tag":"blackhole-out"}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
echoContent green " ---> Domestic domain name blocked successfully"
elif [[ "${blacklistStatus}" == "4" ]]; then
unInstallRouting blackhole-out outboundTag
echoContent green " ---> Domain name blacklist deleted successfully"
else
echoContent red " ---> Wrong selection"
exit 0
fi
reloadCore
}
#Add routing configuration
addInstallRouting() {
local tag=$1 # warp-socks
local type=$2 # outboundTag/inboundTag
local domain=$3 # Domain name
if [[ -z "${tag}" || -z "${type}" || -z "${domain}" ]]; then
echoContent red " ---> Parameter error"
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}"'")' ${configPath}09_routing.json)
if [[ -z "${routingRule}" ]]; then
if [[ "${tag}" == "dokodemoDoor-80" ]]; then
routingRule="{\"type\": \"field\",\"port\": 80,\"domain\": [],\"outboundTag\": \"${tag}\"}"
elif [[ "${tag}" == "dokodemoDoor-443" ]]; then
routingRule="{\"type\": \"field\",\"port\": 443,\"domain\": [],\"outboundTag\": \"${tag}\"}"
else
routingRule="{\"type\": \"field\",\"domain\": [],\"outboundTag\": \"${tag}\"}"
fi
fi
while read -r line; do
if echo "${routingRule}" | grep -q "${line}"; then
echoContent yellow " ---> ${line} already exists, skip"
else
local geositeStatus
geositeStatus=$(curl -s "https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}" | jq .message)
if [[ "${geositeStatus}" == "null" ]]; then
routingRule=$(echo "${routingRule}" | jq -r '.domain += ["geosite:'"${line}"'"]')
else
routingRule=$(echo "${routingRule}" | jq -r '.domain += ["domain:'"${line}"'"]')
fi
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\": [\"gstatic.com\"],\"outboundTag\": \"direct\"}]" ${configPath}09_routing.json)
echo "${routing}" | jq . >${configPath}09_routing.json
fi
routing=$(jq -r ".routing.rules += [${routingRule}]" ${configPath}09_routing.json)
echo "${routing}" | jq . >${configPath}09_routing.json
}
# 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 grep -q "${tag}" ${configPath}09_routing.json && grep -q "${type}" ${configPath}09_routing.json; then
jq -c .routing.rules[] ${configPath}09_routing.json | while read -r line; do
local index=$((index + 1))
local delStatus=0
if [[ "${type}" == "outboundTag" ]] && echo "${line}" | jq .outboundTag | grep -q "${tag}"; then
delStatus=1
elif [[ "${type}" == "inboundTag" ]] && echo "${line}" | jq .inboundTag | grep -q "${tag}"; then
delStatus=1
fi
if [[ -n ${protocol} ]] && echo "${line}" | jq .protocol | grep -q "${protocol}"; then
delStatus=1
elif [[ -z ${protocol} ]] && [[ $(echo "${line}" | jq .protocol) != "null" ]]; then
delStatus=0
fi
if [[ ${delStatus} == 1 ]]; then
routing=$(jq -r 'del(.routing.rules['$((index - 1))'])' ${configPath}09_routing.json)
echo "${routing}" | jq . >${configPath}09_routing.json
fi
done
fi
fi
}
# Uninstall outbound based on tag
unInstallOutbounds() {
local tag=$1
if grep -q "${tag}" ${configPath}10_ipv4_outbounds.json; then
local ipv6OutIndex
ipv6OutIndex=$(jq .outbounds[].tag ${configPath}10_ipv4_outbounds.json | awk '{print ""NR""":"$0}' | grep "${tag}" | awk -F "[:]" '{print $1}' | head -1)
if [[ ${ipv6OutIndex} -gt 0 ]]; then
routing=$(jq -r 'del(.outbounds['$((ipv6OutIndex - 1))'])' ${configPath}10_ipv4_outbounds.json)
echo "${routing}" | jq . >${configPath}10_ipv4_outbounds.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
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 '.inbounds[0].sniffing = {"enabled":true,"destOverride":["http","tls"]}' "${configPath}${inbound}")
echo "${sniffing}" | jq . >"${configPath}${inbound}"
fi
done
}
# warp diversion
warpRouting() {
echoContent skyBlue "\nProgress$1/${totalProgress}: WARP offload"
echoContent red "=============================================================="
if [[ -z $(which warp-cli) ]]; then
echo
read -r -p "WARP is not installed. Do you want to install it? [y/n]:" installCloudflareWarpStatus
if [[ "${installCloudflareWarpStatus}" == "y" ]]; then
installWarp
else
echoContent yellow " ---> Abort installation"
exit 0
fi
fi
echoContent red "\n================================================ ================="
echoContent yellow "1.View the diverted domain name"
echoContent yellow "2.Add domain name"
echoContent yellow "3.Set WARP global"
echoContent yellow "4.Uninstall WARP distribution"
echoContent red "================================================== ==============="
read -r -p "Please select:" warpStatus
if [[ "${warpStatus}" == "1" ]]; then
jq -r -c '.routing.rules[]|select (.outboundTag=="warp-socks-out")|.domain' ${configPath}09_routing.json | jq -r
exit 0
elif [[ "${warpStatus}" == "2" ]]; 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"
read -r -p "Please enter the domain name according to the above example:" domainList
addInstallRouting warp-socks-out outboundTag "${domainList}"
unInstallOutbounds warp-socks-out
local outbounds
outbounds=$(jq -r '.outbounds += [{"protocol":"socks","settings":{"servers":[{"address":"127.0.0.1","port":31303}]},"tag":"warp-socks-out"}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
echoContent green " ---> Added successfully"
elif [[ "${warpStatus}" == "3" ]]; then
echoContent red "================================================== ==============="
echoContent yellow "# Notes\n"
echoContent yellow "1.All diversion rules set will be deleted"
echoContent yellow "2.All outbound rules except WARP will be deleted"
read -r -p "Confirm settings? [y/n]:" warpOutStatus
if [[ "${warpOutStatus}" == "y" ]]; then
cat <<EOF >${configPath}10_ipv4_outbounds.json
{
"outbounds":[
{
"protocol": "socks",
"settings": {
"servers": [
{
"address": "127.0.0.1",
"port": 31303
}
]
},
"tag": "warp-socks-out"
}
]
}
EOF
rm ${configPath}09_routing.json >/dev/null 2>&1
echoContent green " ---> WARP global outbound setting successful"
else
echoContent green " ---> Abandon settings"
exit 0
fi
elif [[ "${warpStatus}" == "4" ]]; then
${removeType} cloudflare-warp >/dev/null 2>&1
unInstallRouting warp-socks-out outboundTag
unInstallOutbounds warp-socks-out
if ! grep -q "IPv4-out" <"${configPath}10_ipv4_outbounds.json"; then
outbounds=$(jq -r '.outbounds += [{"protocol":"freedom","settings": {"domainStrategy": "UseIPv4"},"tag":"IPv4-out"}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
fi
echoContent green " ---> WARP offload uninstall successful"
else
echoContent red " ---> Wrong selection"
exit 0
fi
reloadCore
}
# 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}')
}
# warp offload-third-party IPv4
warpRoutingReg() {
local type=$2
echoContent skyBlue "\nProgress$1/${totalProgress}: WARP offload [third party]"
echoContent red "================================================== ==============="
if [[ ! -f "/etc/v2ray-agent/warp/warp-reg" ]]; then
echo
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 "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 " ---> Abort installation"
exit 0
fi
fi
echoContent red "\n================================================ ================="
echoContent yellow "1.View the diverted domain name"
echoContent yellow "2.Add domain name"
echoContent yellow "3.Set WARP global"
echoContent yellow "4.Uninstall WARP distribution"
echoContent red "================================================== ==============="
read -r -p "Please select:" warpStatus
readConfigWarpReg
local address=
if [[ ${type} == "IPv4" ]]; then
address="172.16.0.2/32"
elif [[ ${type} == "IPv6" ]]; then
address="${addressWarpReg}/128"
else
echoContent red " ---> IP acquisition failed, exit installation"
fi
if [[ "${warpStatus}" == "1" ]]; then
jq -r -c '.routing.rules[]|select (.outboundTag=="wireguard-out-'"${type}"'")|.domain' ${configPath}09_routing.json | jq -r
exit 0
elif [[ "${warpStatus}" == "2" ]]; 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"
read -r -p "Please enter the domain name according to the above example:" domainList
addInstallRouting wireguard-out-"${type}" outboundTag "${domainList}"
unInstallOutbounds wireguard-out-"${type}"
local outbounds
outbounds=$(jq -r '.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":"wireguard-out-'"${type}"'"}]' ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
echoContent green " ---> Added successfully"
elif [[ "${warpStatus}" == "3" ]]; then
echoContent red "================================================== ==============="
echoContent yellow "# Notes\n"
echoContent yellow "1.All diversion rules set will be deleted"
echoContent yellow "2.All outbound rules except WARP [third party] will be deleted"
read -r -p "Confirm the settings? [y/n]:" warpOutStatus
if [[ "${warpOutStatus}" == "y" ]]; then
readConfigWarpReg
cat <<EOF >${configPath}10_ipv4_outbounds.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": "wireguard-out-${type}"
}
]
}
EOF
rm ${configPath}09_routing.json >/dev/null 2>&1
echoContent green " ---> WARP global outbound setting successful"
else
echoContent green " ---> Abandon settings"
exit 0
fi
elif [[ "${warpStatus}" == "4" ]]; then
unInstallRouting wireguard-out-"${type}" outboundTag
unInstallOutbounds wireguard-out-"${type}"
if [[ "${type}" == "IPv4" ]]; then
if ! grep -q "wireguard-out-IPv6" <${configPath}10_ipv4_outbounds.json; then
rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1
fi
elif [[ "${type}" == "IPv6" ]]; then
if ! grep -q "wireguard-out-IPv4" <${configPath}10_ipv4_outbounds.json; then
rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1
fi
fi
if ! grep -q "IPv4-out" <"${configPath}10_ipv4_outbounds.json"; then
cat <<EOF >${configPath}10_ipv4_outbounds.json
{
"outbounds":[
{
"protocol":"freedom",
"settings":{
"domainStrategy":"UseIPv4"
},
"tag":"IPv4-out"
},
{
"protocol":"freedom",
"settings":{
"domainStrategy":"UseIPv6"
},
"tag":"IPv6-out"
},
{
"protocol":"blackhole",
"tag":"blackhole-out"
}
]
}
EOF
fi
echoContent green " ---> WARP offload uninstall successful"
else
echoContent red " ---> Wrong selection"
exit 0
fi
reloadCore
}
# Diversion tool
routingToolsMenu() {
echoContent skyBlue "\nFunction 1/${totalProgress}: Diversion tool"
echoContent red "\n================================================ ================="
echoContent yellow "1.WARP diversion [Third-party IPv4]"
echoContent yellow "2.WARP diversion [Third-party IPv6]"
echoContent yellow "3.IPv6 offload"
echoContent yellow "4.Any door diversion"
echoContent yellow "5.DNS divert"
echoContent yellow "6.VMess+WS+TLS offload"
echoContent yellow "7.SNI reverse proxy offload"
read -r -p "Please select:" selectType
case ${selectType} in
1)
warpRoutingReg 1 IPv4
;;
2)
warpRoutingReg 1 IPv6
;;
3)
ipv6Routing 1
;;
4)
dokodemoDoorRouting 1
;;
5)
dnsRouting 1
;;
6)
vmessWSRouting 1
;;
7)
sniRouting 1
;;
esac
}
#Streaming Toolbox
streamingToolbox() {
echoContent skyBlue "\nFunction 1/${totalProgress}: Streaming Media Toolbox"
echoContent red "\n================================================ ============ ====="
echoContent yellow "1.Any door floor machine unlocks streaming media"
echoContent yellow "2.DNS unlock streaming media"
echoContent yellow "3.VMess+WS+TLS to unlock streaming media"
read -r -p "Please select:" selectType
case ${selectType} in
1)
dokodemoDoorRouting
;;
2)
dnsRouting
;;
3)
vmessWSRouting
;;
esac
}
#Any door unlock streaming
dokodemoDoorRouting() {
echoContent skyBlue "\nFunction 1/${totalProgress}: any door diversion"
echoContent red "\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"
echoContent yellow "1.Add outbound"
echoContent yellow "2.Add inbound"
echoContent yellow "3.Uninstall"
read -r -p "Please select:" selectType
case ${selectType} in
1)
setDokodemoDoorRoutingOutbounds
;;
2)
setDokodemoDoorRoutingInbounds
;;
3)
removeDokodemoDoorRouting
;;
esac
}
# VMess+WS+TLS offload
vmessWSRouting() {
echoContent skyBlue "\nFunction 1/${totalProgress}: VMess+WS+TLS offload"
echoContent red "\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"
echoContent yellow "1.Add outbound"
echoContent yellow "2.Uninstall"
read -r -p "Please select:" selectType
case ${selectType} in
1)
setVMessWSRoutingOutbounds
;;
2)
removeVMessWSRouting
;;
esac
}
# Set VMess+WS+TLS [outbound only]
setVMessWSRoutingOutbounds() {
read -r -p "Please enter the address of VMess+WS+TLS:" setVMessWSTLSAddress
echoContent red "================================================== ==============="
echoContent yellow "Input example:netflix,openai\n"
read -r -p "Please enter the domain name according to the above example:" domainList
if [[ -z ${domainList} ]]; then
echoContent red " ---> Domain name cannot be empty"
setVMessWSRoutingOutbounds
fi
if [[ -n "${setVMessWSTLSAddress}" ]]; then
unInstallOutboundsVMess-out
echo
read -r -p "Please enter the port of VMess+WS+TLS:" setVMessWSTLSPort
echo
if [[ -z "${setVMessWSTLSPort}" ]]; then
echoContent red " ---> Port cannot be empty"
fi
read -r -p "Please enter the UUID of VMess+WS+TLS:" setVMessWSTLSUUID
echo
if [[ -z "${setVMessWSTLSUUID}" ]]; then
echoContent red " ---> UUID cannot be empty"
fi
read -r -p "Please enter the Path of VMess+WS+TLS:" setVMessWSTLSPath
echo
if [[ -z "${setVMessWSTLSPath}" ]]; then
echoContent red " ---> The path cannot be empty"
elif ! echo "${setVMessWSTLSPath}" | grep -q "/"; then
setVMessWSTLSPath="/${setVMessWSTLSPath}"
fi
outbounds=$(jq -r ".outbounds += [{\"tag\":\"VMess-out\",\"protocol\":\"vmess\",\"streamSettings\":{\"network\":\"ws\",\"security\":\"tls\",\"tlsSettings\":{\"allowInsecure\":false},\"wsSettings\":{\"path\":\"${setVMessWSTLSPath}\"}},\"mux\":{\"enabled\":true,\"concurrency\":8},\"settings\":{\"vnext\":[{\"address\":\"${setVMessWSTLSAddress}\",\"port\":${setVMessWSTLSPort},\"users\":[{\"id\":\"${setVMessWSTLSUUID}\",\"security\":\"auto\",\"alterId\":0}]}]}}]" ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
addInstallRouting VMess-out outboundTag "${domainList}"
reloadCore
echoContent green " ---> Added shunt successfully"
exit 0
fi
echoContent red " ---> The address cannot be empty"
setVMessWSRoutingOutbounds
}
# Set any door diversion [outbound]
setDokodemoDoorRoutingOutbounds() {
read -r -p "Please enter the IP of the target vps:" setIP
echoContent red "=============================================================="
echoContent yellow "Input example:netflix,openai\n"
read -r -p "Please enter the domain name according to the above example:" domainList
if [[ -z ${domainList} ]]; then
echoContent red " ---> Domain name cannot be empty"
setDokodemoDoorRoutingOutbounds
fi
if [[ -n "${setIP}" ]]; then
unInstallOutbounds dokodemoDoor-80
unInstallOutbounds dokodemoDoor-443
addInstallRouting dokodemoDoor-80 outboundTag "${domainList}"
addInstallRouting dokodemoDoor-443 outboundTag "${domainList}"
outbounds=$(jq -r ".outbounds += [{\"tag\":\"dokodemoDoor-80\",\"protocol\":\"freedom\",\"settings\":{\"domainStrategy\":\"AsIs\",\"redirect\":\"${setIP}:22387\"}},{\"tag\":\"dokodemoDoor-443\",\"protocol\":\"freedom\",\"settings\":{\"domainStrategy\":\"AsIs\",\"redirect\":\"${setIP}:22388\"}}]" ${configPath}10_ipv4_outbounds.json)
echo "${outbounds}" | jq . >${configPath}10_ipv4_outbounds.json
reloadCore
echoContent green " ---> Add any door to divert successfully"
exit 0
fi
echoContent red " ---> ip cannot be empty"
}
# Set any door diversion [inbound]
setDokodemoDoorRoutingInbounds() {
echoContent skyBlue "\nFunction 1/${totalProgress}: Add inbound at any door"
echoContent red "\n================================================ ================="
echoContent yellow "ip entry example:1.1.1.1,1.1.1.2"
echoContent yellow "The domain name below must be consistent with the outbound vps"
echoContent yellow "Example of domain name entry: netflix,openai\n"
read -r -p "Please enter the IP allowed to access the vps:" setIPs
if [[ -n "${setIPs}" ]]; then
read -r -p "Please enter the domain name according to the above example:" domainList
allowPort 22387
allowPort 22388
cat <<EOF >${configPath}01_dokodemoDoor_inbounds.json
{
"inbounds": [
{
"listen": "0.0.0.0",
"port": 22387,
"protocol": "dokodemo-door",
"settings": {
"address": "0.0.0.0",
"port": 80,
"network": "tcp",
"followRedirect": false
},
"sniffing": {
"enabled": true,
"destOverride": [
"http"
]
},
"tag": "dokodemoDoor-80"
},
{
"listen": "0.0.0.0",
"port": 22388,
"protocol": "dokodemo-door",
"settings": {
"address": "0.0.0.0",
"port": 443,
"network": "tcp",
"followRedirect": false
},
"sniffing": {
"enabled": true,
"destOverride": [
"tls"
]
},
"tag": "dokodemoDoor-443"
}
]
}
EOF
local domains=
domains=[]
while read -r line; do
local geositeStatus
geositeStatus=$(curl -s "https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}" | jq .message)
if [[ "${geositeStatus}" == "null" ]]; then
domains=$(echo "${domains}" | jq -r '. += ["geosite:'"${line}"'"]')
else
domains=$(echo "${domains}" | jq -r '. += ["domain:'"${line}"'"]')
fi
done < <(echo "${domainList}" | tr ',' '\n')
if [[ -f "${configPath}09_routing.json" ]]; then
unInstallRouting dokodemoDoor-80 inboundTag
unInstallRouting dokodemoDoor-443 inboundTag
local routing
routing=$(jq -r ".routing.rules += [{\"source\":[\"${setIPs//,/\",\"}\"],\"domains\":${domains},\"type\":\"field\",\"inboundTag\":[\"dokodemoDoor-80\",\"dokodemoDoor-443\"],\"outboundTag\":\"direct\"},{\"type\":\"field\",\"inboundTag\":[\"dokodemoDoor-80\",\"dokodemoDoor-443\"],\"outboundTag\":\"blackhole-out\"}]" ${configPath}09_routing.json)
echo "${routing}" | jq . >${configPath}09_routing.json
else
cat <<EOF >${configPath}09_routing.json
{
"routing": {
"rules": [
{
"source": [
"${setIPs//,/\",\"}"
],
"domains":${domains},
"type": "field",
"inboundTag": [
"dokodemoDoor-80",
"dokodemoDoor-443"
],
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": [
"dokodemoDoor-80",
"dokodemoDoor-443"
],
"outboundTag": "blackhole-out"
}
]
}
}
EOF
fi
reloadCore
echoContent green " ---> Added landing machine inbound traffic successfully"
exit 0
fi
echoContent red " ---> ip cannot be empty"
}
# Remove any door shunt
removeDokodemoDoorRouting() {
unInstallOutbounds dokodemoDoor-80
unInstallOutbounds dokodemoDoor-443
unInstallRouting dokodemoDoor-80 inboundTag
unInstallRouting dokodemoDoor-443 inboundTag
unInstallRouting dokodemoDoor-80 outboundTag
unInstallRouting dokodemoDoor-443 outboundTag
rm -rf ${configPath}01_dokodemoDoor_inbounds.json
reloadCore
echoContent green " ---> Uninstall successful"
}
# Remove VMess+WS+TLS shunt
removeVMessWSRouting() {
unInstallOutbounds VMess-out
unInstallRouting VMess-out outboundTag
reloadCore
echoContent green " ---> Uninstall successful"
}
# Restart core
reloadCore() {
readInstallType
if [[ "${coreInstallType}" == "1" ]]; then
handleXray stop
handleXray start
elif [[ "${coreInstallType}" == "2" ]]; then
handleV2Ray stop
handleV2Ray start
fi
if [[ -n "${hysteriaConfigPath}" ]]; then
handleHysteria stop
handleHysteria start
fi
if [[ -n "${tuicConfigPath}" ]]; then
handleTuic stop
handleTuic start
fi
}
# dns divert
dnsRouting() {
if [[ -z "${configPath}" ]]; then
echoContent red " ---> Not installed, please use script to install"
menu
exit 0
fi
echoContent skyBlue "\nFunction 1/${totalProgress}: DNS offloading"
echoContent red "\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"
echoContent yellow "1.Add"
echoContent yellow "2.Uninstall"
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 " ---> Not installed, please use script to install"
menu
exit 0
fi
echoContent skyBlue "\nFunction 1/${totalProgress}: SNI reverse proxy offload"
echoContent red "\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"
echoContent yellow "1.Add"
echoContent yellow "2.Uninstall"
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 "================================================== ==============="
echoContent yellow "Input example: netflix, disney, hulu"
read -r -p "Please enter the domain name according to the above example:" domainList
if [[ -n "${domainList}" ]]; then
local hosts={}
while read -r domain; do
hosts=$(echo "${hosts}" | jq -r ".\"geosite:${domain}\"=\"${setSNIP}\"")
done < <(echo "${domainList}" | tr ',' '\n')
cat <<EOF >${configPath}11_dns.json
{
"dns": {
"hosts":${hosts},
"servers": [
"8.8.8.8",
"1.1.1.1"
]
}
}
EOF
echoContent red " ---> SNI reverse proxy distribution successful"
reloadCore
else
echoContent red " ---> Domain name cannot be empty"
fi
else
echoContent red " ---> SNI IP cannot be empty"
fi
exit 0
}
# Set dns
setUnlockDNS() {
read -r -p "Please enter the diverted DNS:" setDNS
if [[ -n ${setDNS} ]]; then
echoContent red "================================================== ==============="
echoContent yellow "Input example: netflix, disney, hulu"
echoContent yellow "Please enter 1 for the default scheme. The default scheme includes the following content"
echoContent yellow "netflix,bahamut,hulu,hbo,disney,bbc,4chan,fox,abema,dmm,niconico,pixiv,bilibili,viu"
read -r -p "Please enter the domain name according to the above example:" domainList
if [[ "${domainList}" == "1" ]]; then
cat <<EOF >${configPath}11_dns.json
{
"dns": {
"servers": [
{
"address": "${setDNS}",
"port": 53,
"domains": [
"geosite:netflix",
"geosite:bahamut",
"geosite:hulu",
"geosite:hbo",
"geosite:disney",
"geosite:bbc",
"geosite:4chan",
"geosite:fox",
"geosite:abema",
"geosite:dmm",
"geosite:niconico",
"geosite:pixiv",
"geosite:bilibili",
"geosite:viu"
]
},
"localhost"
]
}
}
EOF
elif [[ -n "${domainList}" ]]; then
cat <<EOF >${configPath}11_dns.json
{
"dns": {
"servers": [
{
"address": "${setDNS}",
"port": 53,
"domains": [
"geosite:${domainList//,/\",\"geosite:}"
]
},
"localhost"
]
}
}
EOF
fi
reloadCore
echoContent yellow "\n ---> If you still can't watch, you can try the following two solutions"
echoContent yellow "1.Restart vps"
echoContent yellow "2.After uninstalling dns unlocking, modify the local [/etc/resolv.conf] DNS settings and restart vps\n"
else
echoContent red " ---> dns cannot be empty"
fi
exit 0
}
# Remove DNS offloading
removeUnlockDNS() {
cat <<EOF >${configPath}11_dns.json
{
"dns": {
"servers": [
"localhost"
]
}
}
EOF
reloadCore
echoContent green " ---> Uninstall successful"
exit 0
}
# Remove SNI shunt
removeUnlockSNI() {
cat <<EOF >${configPath}11_dns.json
{
"dns": {
"servers": [
"localhost"
]
}
}
EOF
reloadCore
echoContent green " ---> Uninstall successful"
exit 0
}
# v2ray-core personalized installation
customV2RayInstall() {
echoContent skyBlue "\n========================Personalized installation================== =========="
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 "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]"
read -r -p "Please select [multiple selection], [for example: 123]:" selectCustomInstallType
echoContent skyBlue "------------------------------------------------- ---------------"
if [[ -z ${selectCustomInstallType} ]]; then
selectCustomInstallType=0
fi
if [[ "${selectCustomInstallType}" =~ ^[0-5]+$ ]]; then
cleanUp xrayClean
checkBTPanel
totalProgress=17
installTools 1
# Apply for tls
initTLSNginxConfig 2
installTLS 3
handleNginx stop
#random path
if echo ${selectCustomInstallType} | grep -q 1 || echo ${selectCustomInstallType} | grep -q 3 || echo ${selectCustomInstallType} | grep -q 4; then
randomPathFunction 5
customCDNIP 6
fi
nginxBlog 7
updateRedirectNginxConf
handleNginx start
# Install V2Ray
installV2Ray 8
installV2RayService 9
initV2RayConfig custom 10
cleanUp xrayDel
installCronTLS 14
handleV2Ray stop
handleV2Ray start
# Generate account
checkGFWStatue 15
showAccounts 16
else
echoContent red " ---> Input is illegal"
customV2RayInstall
fi
}
# Xray-core personalized installation
customXrayInstall() {
echoContent skyBlue "\n========================Personalized installation================== =========="
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[recommended]"
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 "8.VLESS+Reality+gRPC"
read -r -p "Please select [multiple selection], [for example: 123]:" selectCustomInstallType
echoContent skyBlue "------------------------------------------------- --------- ------"
if [[ -z ${selectCustomInstallType} ]]; then
echoContent red " ---> cannot be empty"
customXrayInstall
elif [[ "${selectCustomInstallType}" =~ ^[0-7]+$ ]]; then
if ! echo "${selectCustomInstallType}" | grep -q "0"; then
selectCustomInstallType="0${selectCustomInstallType}"
fi
cleanUp v2rayClean
checkBTPanel
totalProgress=12
installTools 1
if [[ -n "${btDomain}" ]]; then
echoContent skyBlue "\nProgress 3/${totalProgress}: Pagoda panel detected, skip applying for TLS"
handleXray stop
customPortFunction
else
# Apply for tls
initTLSNginxConfig 2
handleXray stop
# handleNginx start
installTLS 3
fi
handleNginx stop
#random path
if echo "${selectCustomInstallType}" | grep -q 1 || echo "${selectCustomInstallType}" | grep -q 2 || echo "${selectCustomInstallType}" | grep -q 3 || echo "${selectCustomInstallType}" | grep -q 5; then
randomPathFunction 4
customCDNIP 5
fi
if [[ -n "${btDomain}" ]]; then
echoContent skyBlue "\nProgress 6/${totalProgress}: Pagoda panel detected, skipping disguised website"
# echoContent red "============================================== ================"
# echoContent yellow "# Notes"
# echoContent yellow "The static directory under the currently installed website will be cleared. If it has been customized, please select [n]\n"
# read -r -p "Please select [y/n]:" nginxBlogBTStatus
# if [[ "${nginxBlogBTStatus}" == "y" ]]; then
#nginxBlog 6
#fi
else
nginxBlog 6
fi
updateRedirectNginxConf
handleNginx start
# Install Xray
installXray 7 false
installXrayService 8
initXrayConfig custom 9
cleanUp v2rayDel
installCronTLS 10
handleXray stop
handleXray start
# Generate account
checkGFWStatue 11
showAccounts 12
else
echoContent red " ---> Input is illegal"
customXrayInstall
fi
}
# Select core installation---v2ray-core, xray-core
selectCoreInstall() {
echoContent skyBlue "\nFunction 1/${totalProgress}: Select core installation"
echoContent red "\n================================================ ================="
echoContent yellow "1.Xray-core"
echoContent yellow "2.v2ray-core"
echoContent red "================================================== ==============="
read -r -p "Please select:" selectCoreType
case ${selectCoreType} in
1)
if [[ "${selectInstallType}" == "2" ]]; then
customXrayInstall
else
xrayCoreInstall
fi
;;
2)
v2rayCoreVersion=
echoContent red " ---> Since v2ray does not support many new features, maintenance is now discontinued in order to reduce development costs. It is recommended to use Xray-core, hysteria, and Tuic"
exit 0
if [[ "${selectInstallType}" == "2" ]]; then
customV2RayInstall
else
v2rayCoreInstall
fi
;;
3)
v2rayCoreVersion=v4.32.1
if [[ "${selectInstallType}" == "2" ]]; then
customV2RayInstall
else
v2rayCoreInstall
fi
;;
*)
echoContent red ' ---> Wrong selection, select again'
selectCoreInstall
;;
esac
}
# v2ray-core installation
v2rayCoreInstall() {
cleanUp xrayClean
checkBTPanel
selectCustomInstallType=
totalProgress=13
installTools 2
# Apply for tls
initTLSNginxConfig 3
handleV2Ray stop
handleNginx start
installTLS 4
handleNginx stop
randomPathFunction 5
# Install V2Ray
installV2Ray 6
installV2RayService 7
customCDNIP 8
initV2RayConfig all 9
cleanUp xrayDel
installCronTLS 10
nginxBlog 11
updateRedirectNginxConf
handleV2Ray stop
sleep 2
handleV2Ray start
handleNginx start
# Generate account
checkGFWStatue 12
showAccounts 13
}
# xray-core installation
xrayCoreInstall() {
cleanUp v2rayClean
checkBTPanel
selectCustomInstallType=
totalProgress=13
installTools 2
if [[ -n "${btDomain}" ]]; then
echoContent skyBlue "\nProgress 3/${totalProgress}: Pagoda panel detected, skip applying for TLS"
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
customCDNIP 8
initXrayConfig all 9
cleanUp v2rayDel
installCronTLS 10
if [[ -n "${btDomain}" ]]; then
echoContent skyBlue "\nProgress 11/${totalProgress}: Pagoda panel detected, skipping disguised website"
# echoContent red "============================================== ================"
# echoContent yellow "# Notes"
# echoContent yellow "The static directory under the currently installed website will be cleared. If it has been customized, please select [n]\n"
# read -r -p "Please select [y/n]:" nginxBlogBTStatus
# if [[ "${nginxBlogBTStatus}" == "y" ]]; then
#nginxBlog 11
#fi
else
nginxBlog 11
fi
updateRedirectNginxConf
handleXray stop
sleep 2
handleXray start
handleNginx start
# Generate account
checkGFWStatue 12
showAccounts 13
}
#HysteriaInstallation
hysteriaCoreInstall() {
if ! echo "${currentInstallProtocolType}" | grep -q "0" || [[ -z "${coreInstallType}" ]]; then
echoContent red "\n ---> Due to environmental dependencies, if you install hysteria, please install Xray-core's VLESS_TCP_TLS_Vision first"
exit 0
fi
totalProgress=5
installHysteria 1
initHysteriaConfig 2
installHysteriaService 3
reloadCore
showAccounts 4
}
# Uninstall hysteria
unInstallHysteriaCore() {
if [[ -z "${hysteriaConfigPath}" ]]; then
echoContent red "\n ---> not installed"
exit 0
fi
deleteHysteriaPortHoppingRules
handleHysteria stop
rm -rf /etc/v2ray-agent/hysteria/*
rm ${configPath}02_socks_inbounds_hysteria.json
rm -rf /etc/systemd/system/hysteria.service
echoContent green " ---> Uninstall completed"
}
# Uninstall Tuic
unInstallTuicCore() {
if [[ -z "${tuicConfigPath}" ]]; then
echoContent red "\n ---> not installed"
exit 0
fi
handleTuic stop
rm -rf /etc/v2ray-agent/tuic/*
rm -rf /etc/systemd/system/tuic.service
echoContent green " ---> Uninstall completed"
}
unInstallXrayCoreReality() {
if [[ -z "${realityStatus}" ]]; then
echoContent red "\n ---> not installed"
exit 0
fi
echoContent skyBlue "\nFunction 1/1: reality uninstall"
echoContent red "\n================================================ ================="
echoContent yellow "# Only delete VLESS Reality related configurations, other content will not be deleted."
echoContent yellow "# If you need to uninstall other content, please uninstall the script function"
handleXray stop
rm /etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json
rm /etc/v2ray-agent/xray/conf/08_VLESS_reality_fallback_grpc_inbounds.json
echoContent green " ---> Uninstall completed"
}
# Core Management
coreVersionManageMenu() {
if [[ -z "${coreInstallType}" ]]; then
echoContent red "\n >The installation directory is not detected, please execute the script to install the content"
menu
exit 0
fi
if [[ "${coreInstallType}" == "1" ]]; then
xrayVersionManageMenu 1
elif [[ "${coreInstallType}" == "2" ]]; then
v2rayCoreVersion=
v2rayVersionManageMenu 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 "\nFunction 1/${totalProgress}: Account Management"
if [[ -z "${configPath}" ]]; then
echoContent red " ---> not installed"
exit 0
fi
echoContent red "\n================================================ ================="
echoContent yellow "# You can customize email and uuid when adding a single user"
echoContent yellow "# If Hysteria or Tuic is installed, the account will be added to the corresponding type at the same time\n"
echoContent yellow "1.Check account"
echoContent yellow "2.View subscription"
echoContent yellow "3.Add subscription"
echoContent yellow "4.Add user"
echoContent yellow "5.Delete user"
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
addUserXray
elif [[ "${manageAccountStatus}" == "5" ]]; then
removeUser
else
echoContent red " ---> Wrong selection"
fi
}
#Add subscription
addSubscribeMenu() {
echoContent skyBlue "\n====================== Add other machine subscriptions==================== ==="
echoContent yellow "1.Add"
echoContent yellow "2.Remove"
echoContent red "================================================== ==============="
read -r -p "Please select:" addSubscribeStatus
if [[ "${addSubscribeStatus}" == "1" ]]; then
addOtherSubscribe
elif [[ "${addSubscribeStatus}" == "2" ]]; then
rm -rf /etc/v2ray-agent/subscribe_remote/clashMeta/*
rm -rf /etc/v2ray-agent/subscribe_remote/default/*
echo >/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl
echoContent green " ---> Other machine subscriptions were deleted successfully"
subscribe
fi
}
# Add other machines to clashMeta subscription
addOtherSubscribe() {
echoContent yellow "#Notes:"
echoContent yellow "Please read the following article carefully: https://www.v2ray-agent.com/archives/1681804748677"
echoContent skyBlue "Input example: www.v2ray-agent.com:443:vps1\n"
read -r -p "Please enter the domain name, port and machine alias:" remoteSubscribeUrl
if [[ -z "${remoteSubscribeUrl}" ]]; then
echoContent red " ---> cannot be empty"
addSubscribe
elif ! echo "${remoteSubscribeUrl}" | grep -q ":"; then
echoContent red " ---> Rule is illegal"
else
echo "${remoteSubscribeUrl}" >>/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl
local remoteUrl=
remoteUrl=$(echo "${remoteSubscribeUrl}" | awk -F "[:]" '{print $1":"$2}')
local serverAlias=
serverAlias=$(echo "${remoteSubscribeUrl}" | awk -F "[:]" '{print $3}')
if [[ -n $(ls /etc/v2ray-agent/subscribe/clashMeta/) || -n $(ls /etc/v2ray-agent/subscribe/default/) ]]; then
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}')
local emailMd5=
emailMd5=$(echo -n "${email}$(cat "/etc/v2ray-agent/subscribe_local/subscribeSalt")"$'\n' | md5sum | awk '{print $1}')
local clashMetaProxies=
clashMetaProxies=$(curl -s -4 "https://${remoteUrl}/s/clashMeta/${emailMd5}" | sed '/proxies:/d' | sed "s/${email}/${email}_${serverAlias}/g")
local default=
default=$(curl -s -4 "https://${remoteUrl}/s/default/${emailMd5}" | base64 -d | sed "s/${email}/${email}_${serverAlias}/g")
if echo "${default}" | grep -q "${email}"; then
echo "${default}" >>"/etc/v2ray-agent/subscribe/default/${emailMd5}"
echo "${default}" >>"/etc/v2ray-agent/subscribe_remote/default/${email}"
echoContent green " ---> Universal subscription ${email} added successfully"
else
echoContent red " ---> Universal subscription ${email} does not exist"
fi
if echo "${clashMetaProxies}" | grep -q "${email}"; then
echo "${clashMetaProxies}" >>"/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}"
echo "${clashMetaProxies}" >>"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}"
echoContent green " ---> clashMeta subscription ${email} added successfully"
else
echoContent red " ---> clashMeta subscription ${email} does not exist"
fi
done
else
echoContent red " ---> Please check the subscription first and then add the subscription"
fi
fi
}
# clashMeta configuration file
clashMetaConfig() {
local url=$1
local id=$2
cat <<EOF >"/etc/v2ray-agent/subscribe/clashMetaProfiles/${id}"
mixed-port: 7890
unified-delay: false
geodata-mode: true
tcp-concurrent: false
find-process-mode: strict
global-client-fingerprint: chrome
allow-lan: true
mode: rule
log-level: info
ipv6: true
external-controller: 127.0.0.1:9090
geox-url:
geoip: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat"
geosite: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat"
mmdb: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/country.mmdb"
profile:
store-selected: true
store-fake-ip: true
sniffer:
enable: false
sniff:
TLS:
ports: [443]
HTTP:
ports: [80]
override-destination: true
tun:
enable: true
stack: system
dns-hijack:
- 'any:53'
auto-route: true
auto-detect-interface: true
dns:
enable: true
listen: 0.0.0.0:1053
ipv6: true
enhanced-mode: fake-ip
fake-ip-range: 28.0.0.1/8
fake-ip-filter:
- '*'
- '+.lan'
default-nameserver:
- 223.5.5.5
nameserver:
- 'tls://8.8.4.4#DNS_Proxy'
- 'tls://1.0.0.1#DNS_Proxy'
proxy-server-nameserver:
- https://dns.alidns.com/dns-query#h3=true
nameserver-policy:
"geosite:cn,private":
- 223.5.5.5
- 114.114.114.114
- https://dns.alidns.com/dns-query#h3=true
proxy-providers:
${subscribeSalt}_provider:
type: http
path: ./${subscribeSalt}_provider.yaml
url: ${url}
interval: 3600
health-check:
enable: false
url: http://www.gstatic.com/generate_204
interval: 300
proxy-groups:
- name: 节点选择
type: select
use:
- ${subscribeSalt}_provider
proxies:
- 手动切换
- 自动选择
- 故障转移
- 负载均衡
- DIRECT
- name: 流媒体
type: select
use:
- ${subscribeSalt}_provider
proxies:
- 手动切换
- 自动选择
- 故障转移
- 负载均衡
- DIRECT
- 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: fallback
url: http://www.gstatic.com/generate_204
interval: 300
tolerance: 50
use:
- ${subscribeSalt}_provider
proxies:
- 自动选择
- name: 负载均衡
type: load-balance
url: http://www.gstatic.com/generate_204
interval: 300
tolerance: 50
use:
- ${subscribeSalt}_provider
proxies: null
- name: 全球代理
type: select
use:
- ${subscribeSalt}_provider
proxies:
- 手动切换
- 自动选择
- name: DNS_Proxy
type: select
use:
- ${subscribeSalt}_provider
proxies:
- 自动选择
- 节点选择
- DIRECT
- name: Telegram
type: select
use:
- ${subscribeSalt}_provider
proxies:
- 手动切换
- 自动选择
- name: YouTube
type: select
use:
- ${subscribeSalt}_provider
proxies:
- 手动切换
- 自动选择
- name: Netflix
type: select
use:
- ${subscribeSalt}_provider
proxies:
- 流媒体
- 节点选择
- 自动选择
- 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: Disney
type: select
use:
- ${subscribeSalt}_provider
proxies:
- 流媒体
- 节点选择
- 自动选择
- name: GitHub
type: select
use:
- ${subscribeSalt}_provider
proxies:
- 手动切换
- 自动选择
- DIRECT
- name: Spotify
type: select
use:
- ${subscribeSalt}_provider
proxies:
- 流媒体
- 手动切换
- 自动选择
- DIRECT
- name: Google
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://ghproxy.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://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/reject.txt
path: ./ruleset/reject.yaml
interval: 86400
proxy:
type: http
behavior: domain
url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/proxy.txt
path: ./ruleset/proxy.yaml
interval: 86400
direct:
type: http
behavior: domain
url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/direct.txt
path: ./ruleset/direct.yaml
interval: 86400
private:
type: http
behavior: domain
url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/private.txt
path: ./ruleset/private.yaml
interval: 86400
gfw:
type: http
behavior: domain
url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/gfw.txt
path: ./ruleset/gfw.yaml
interval: 86400
greatfire:
type: http
behavior: domain
url: https://ghproxy.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://ghproxy.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://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/telegramcidr.txt
path: ./ruleset/telegramcidr.yaml
interval: 86400
applications:
type: http
behavior: classical
url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/applications.txt
path: ./ruleset/applications.yaml
interval: 86400
Disney:
type: http
behavior: classical
url: https://ghproxy.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://ghproxy.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://ghproxy.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://ghproxy.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://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/OpenAI/OpenAI.yaml
path: ./ruleset/openai.yaml
interval: 86400
Bing:
type: http
behavior: classical
url: https://ghproxy.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://ghproxy.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://ghproxy.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://ghproxy.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://ghproxy.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://ghproxy.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,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
if echo "${currentInstallProtocolType}" | grep -q 0 && [[ -n "${configPath}" ]]; then
echoContent skyBlue "-------------------------Remarks--------------------- ----------"
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 red "# You need to manually enter the md5 encrypted salt value. If you don't know, just use random"
echoContent yellow "# Does not affect the content of added remote subscriptions\n"
if [[ -f "/etc/v2ray-agent/subscribe_local/subscribeSalt" && -n $(cat "/etc/v2ray-agent/subscribe_local/subscribeSalt") ]]; 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
read -r -p "Please enter the salt value, [Enter] use random:" subscribeSalt
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/*
showAccounts >/dev/null
if [[ -n $(ls /etc/v2ray-agent/subscribe_local/default/) ]]; then
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 [[ -f "/etc/v2ray-agent/subscribe_remote/default/${email}" ]]; then
echo >"/etc/v2ray-agent/subscribe_remote/default/${email}_tmp"
while read -r remoteUrl; do
updateRemoteSubscribe "${emailMd5}" "${email}" "${remoteUrl}" "default"
done < <(grep "VLESS_TCP/TLS_Vision" <"/etc/v2ray-agent/subscribe_remote/default/${email}" | awk -F "@" '{print $2}' | awk -F "?" '{print $1}')
echo >"/etc/v2ray-agent/subscribe_remote/default/${email}"
cat "/etc/v2ray-agent/subscribe_remote/default/${email}_tmp" >"/etc/v2ray-agent/subscribe_remote/default/${email}"
cat "/etc/v2ray-agent/subscribe_remote/default/${email}" >>"/etc/v2ray-agent/subscribe/default/${emailMd5}"
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
echoContent skyBlue "\n----------Default subscription----------\n"
echoContent green "email:${email}\n"
echoContent yellow "url:https://${currentDomain}/s/default/${emailMd5}\n"
echoContent yellow "Online QR code: https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=https://${currentDomain}/s/default/${emailMd5}\n "
echo "https://${currentDomain}/s/default/${emailMd5}" | qrencode -s 10 -m 1 -t UTF8
#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}"
if [[ -f "/etc/v2ray-agent/subscribe_remote/clashMeta/${email}" ]]; then
echo >"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}_tmp"
while read -r remoteUrl; do
updateRemoteSubscribe "${emailMd5}" "${email}" "${remoteUrl}" "ClashMeta"
done < <(grep -A3 "VLESS_TCP/TLS_Vision" <"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}" | awk '/server:|port:/ {print $2}' | paste -d ':' - -)
echo >"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}"
cat "/etc/v2ray-agent/subscribe_remote/clashMeta/${email}_tmp" >"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}"
cat "/etc/v2ray-agent/subscribe_remote/clashMeta/${email}" >>"/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}"
fi
sed -i '1i\proxies:' "/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}"
local clashProxyUrl="https://${currentDomain}/s/clashMeta/${emailMd5}"
clashMetaConfig "${clashProxyUrl}" "${emailMd5}"
echoContent skyBlue "\n----------clashMeta subscription----------\n"
echoContent yellow "url:https://${currentDomain}/s/clashMetaProfiles/${emailMd5}\n"
echoContent yellow "Online QR code: https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=https://${currentDomain}/s/clashMetaProfiles/${emailMd5}\n "
echo "https://${currentDomain}/s/clashMetaProfiles/${emailMd5}" | qrencode -s 10 -m 1 -t UTF8
fi
echoContent skyBlue "------------------------------------------------- ---------------"
done
fi
else
echoContent red " ---> The disguise site is not installed and the subscription service cannot be used"
fi
}
# Update remote subscription
updateRemoteSubscribe() {
local emailMD5=$1
local email=$2
local remoteUrl=$3
local type=$4
local remoteDomain=
remoteDomain=$(echo "${remoteUrl}" | awk -F ":" '{print $1}')
local serverAlias=
serverAlias=$(grep "${remoteDomain}" <"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl" | awk -F ":" '{print $3}')
if [[ "${type}" == "ClashMeta" ]]; then
local clashMetaProxies=
clashMetaProxies=$(curl -s -4 "https://${remoteUrl}/s/clashMeta/${emailMD5}" | sed '/proxies:/d' | sed "s/${email}/${email}_${serverAlias}/g")
if echo "${clashMetaProxies}" | grep -q "${email}"; then
echo "${clashMetaProxies}" >>"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}_tmp"
echoContent green " ---> clashMeta subscription ${remoteDomain}:${email} updated successfully"
else
echoContent red " ---> clashMeta subscription ${remoteDomain}:${email} does not exist"
fi
elif [[ "${type}" == "default" ]]; then
local default=
default=$(curl -s -4 "https://${remoteUrl}/s/default/${emailMD5}" | base64 -d | sed "s/${email}/${email}_${serverAlias}/g")
if echo "${default}" | grep -q "${email}"; then
echo "${default}" >>"/etc/v2ray-agent/subscribe_remote/default/${email}_tmp"
echoContent green " ---> Universal subscription ${remoteDomain}:${email} updated successfully"
else
echoContent red " ---> Universal subscription ${remoteDomain}:${email} does not exist"
fi
fi
}
# switch alpn
switchAlpn() {
echoContent skyBlue "\nFunction 1/${totalProgress}: switch alpn"
if [[ -z ${currentAlpn} ]]; then
echoContent red " ---> Unable to read alpn, please check whether it is installed"
exit 0
fi
echoContent red "\n================================================ ================="
echoContent green "The first bit of the current alpn is: ${currentAlpn}"
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]"
echoContent yellow "2.When h2 is the first, gRPC is available, and some trojan clients are available [the client supports manual selection of alpn]"
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"
echoContent red "================================================== ==============="
if [[ "${currentAlpn}" == "http/1.1" ]]; then
echoContent yellow "1.Switch alpn h2 first"
elif [[ "${currentAlpn}" == "h2" ]]; then
echoContent yellow "1.Switch alpn http/1.1 first"
else
echoContent red 'does not comply'
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 " ---> Wrong selection"
exit 0
fi
reloadCore
}
#Initialize realityKey
initRealityKey() {
echoContent skyBlue "\n========================== Generate key ================= =========\n"
if [[ -n "${currentRealityPublicKey}" ]]; 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
fi
if [[ -z "${realityPrivateKey}" ]]; then
realityX25519Key=$(/etc/v2ray-agent/xray/xray x25519)
realityPrivateKey=$(echo "${realityX25519Key}" | head -1 | awk '{print $3}')
realityPublicKey=$(echo "${realityX25519Key}" | tail -n 1 | awk '{print $3}')
fi
echoContent green "\n privateKey:${realityPrivateKey}"
echoContent green "\n publicKey:${realityPublicKey}"
}
# 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 ---> The domain name used is detected, hosted on cloudflare and the proxy is enabled. Using this type of domain name may cause VPS traffic to be used by others [not recommended]\n"
read -r -p "Continue? [y/n]" setRealityDestStatus
if [[ "${setRealityDestStatus}" != 'y' ]]; then
exit 0
fi
echoContent yellow "\n --->Ignore the risks and continue using"
fi
}
#Initialize reality dest
initRealityDest() {
if [[ -n "${domain}" ]]; then
realityDestDomain=${domain}:${port}
else
local realityDestDomainList=
realityDestDomainList="gateway.icloud.com,itunes.apple.com,swdist.apple.com,swcdn.apple.com,updates.cdn-apple.com,mensura.cdn-apple.com,osxapps.itunes.apple.com,aod.itunes.apple.com,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,www.nokia.com,auth.riotgames.com,xsso.riotgames.com,csgo.com"
echoContent skyBlue "\n====== Generate a domain name with fallback configuration , for example : [addons.mozilla.org:443] ======\n"
echoContent green "Fallback domain name list: https://www.v2ray-agent.com/archives/1680104902581#heading-8\n"
read -r -p "Please enter [Enter] to use random:" realityDestDomain
if [[ -z "${realityDestDomain}" ]]; then
local randomNum=
randomNum=$((RANDOM % 24 + 1))
realityDestDomain=$(echo "${realityDestDomainList}" | awk -F ',' -v randomNum="$randomNum" '{print $randomNum":443"}')
fi
if ! echo "${realityDestDomain}" | grep -q ":"; then
echoContent red "\n ---> The domain name does not comply with the standard, please re-enter"
initRealityDest
else
checkRealityDest
echoContent yellow "\n ---> Fallback domain name: ${realityDestDomain}"
fi
fi
}
# Initialize the ServersName available to the client
initRealityClientServersName() {
if [[ -n "${domain}" ]]; then
realityServerNames=\"${domain}\"
elif [[ -n "${realityDestDomain}" ]]; then
realityServerNames=$(echo "${realityDestDomain}" | cut -d ":" -f 1)
realityServerNames=\"${realityServerNames//,/\",\"}\"
else
echoContent skyBlue "\n================ Configure serverNames available to the client ================\n"
echoContent yellow "#Notes"
echoContent green "List of serverNames available to the client: https://www.v2ray-agent.com/archives/1680104902581#heading-8\n"
echoContent yellow "Input example: addons.mozilla.org\n"
read -r -p "Please enter [Enter] to use random:" realityServerNames
if [[ -z "${realityServerNames}" ]]; then
realityServerNames=\"addons.mozilla.org\"
else
realityServerNames=\"${realityServerNames//,/\",\"}\"
fi
fi
echoContent yellow "\n ---> Available client domain names: ${realityServerNames}\n"
}
#Initialize the reality port
initRealityPort() {
if [[ -n "${currentRealityPort}" ]]; 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=${currentRealityPort}
fi
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
read -r -p "Do you use TLS+Vision port? [y/n]:" realityPortTLSVisionStatus
if [[ "${realityPortTLSVisionStatus}" == "y" ]]; then
realityPort=${port}
fi
fi
if [[ -z "${realityPort}" ]]; then
echoContent yellow "Please enter the port [Enter random 10000-30000]"
read -r -p "port:" realityPort
if [[ -z "${realityPort}" ]]; then
realityPort=$((RANDOM % 20001 + 10000))
fi
fi
if [[ -n "${realityPort}" && "${currentRealityPort}" == "${realityPort}" ]]; then
handleXray stop
else
checkPort "${realityPort}"
# if [[ -n "${port}" && "${port}" == "${realityPort}" ]]; then
# echoContent red "The port cannot be the same as Vision--->"
# echo
#realityPort=
#fi
fi
fi
if [[ -z "${realityPort}" ]]; then
initRealityPort
else
allowPort "${realityPort}"
echoContent yellow "\n ---> Port: ${realityPort}"
fi
}
#Initialize reality configuration
initXrayRealityConfig() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Initializing Xray-core reality configuration"
initRealityPort
initRealityKey
initRealityDest
initRealityClientServersName
}
# Modify reality domain name port and other information
updateXrayRealityConfig() {
local realityVisionResult
realityVisionResult=$(jq -r ".inbounds[0].port = ${realityPort}" ${configPath}07_VLESS_vision_reality_inbounds.json)
realityVisionResult=$(echo "${realityVisionResult}" | jq -r ".inbounds[0].streamSettings.realitySettings.dest = \"${realityDestDomain}\"")
realityVisionResult=$(echo "${realityVisionResult}" | jq -r ".inbounds[0].streamSettings.realitySettings.serverNames = [${realityServerNames}]")
realityVisionResult=$(echo "${realityVisionResult}" | jq -r ".inbounds[0].streamSettings.realitySettings.privateKey = \"${realityPrivateKey}\"")
realityVisionResult=$(echo "${realityVisionResult}" | jq -r ".inbounds[0].streamSettings.realitySettings.publicKey = \"${realityPublicKey}\"")
echo "${realityVisionResult}" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json
reloadCore
echoContent green " ---> Modification completed"
}
# xray-core Reality installation
xrayCoreRealityInstall() {
totalProgress=13
installTools 2
# Download core
# prereleaseStatus=true
#updateXray
installXray 3 false
# Generate privateKey, configure fallback address, and configure serverNames
installXrayService 6
# initXrayRealityConfig 5
#Initialize configuration
initXrayConfig custom 7
handleXray stop
cleanUp v2rayClean
sleep 2
# start up
handleXray start
# Generate account
showAccounts 8
}
#realitymanagement
manageReality() {
echoContent skyBlue "\nProgress 1/1: reality management"
echoContent red "\n================================================ ================="
if [[ -n "${realityStatus}" ]]; then
echoContent yellow "1.Reinstall"
echoContent yellow "2.Uninstall"
echoContent yellow "3.Change configuration"
else
echoContent yellow "1.Installation"
fi
echoContent red "================================================== ==============="
read -r -p "Please select:" installRealityStatus
if [[ "${installRealityStatus}" == "1" ]]; then
selectCustomInstallType="7"
xrayCoreRealityInstall
elif [[ "${installRealityStatus}" == "2" ]]; then
unInstallXrayCoreReality
elif [[ "${installRealityStatus}" == "3" ]]; then
initXrayRealityConfig 1
updateXrayRealityConfig
fi
}
# hysteriaadmin
manageHysteria() {
echoContent skyBlue "\nProgress 1/1: Hysteria Management"
echoContent red "\n================================================ ================="
local hysteriaStatus=
if [[ -n "${hysteriaConfigPath}" ]]; then
echoContent yellow "1.Reinstall"
echoContent yellow "2.Uninstall"
echoContent yellow "3.Port jump management"
echoContent yellow "4.core management"
echoContent yellow "5.View log"
hysteriaStatus=true
else
echoContent yellow "1.Installation"
fi
echoContent red "================================================== ==============="
read -r -p "Please select:" installHysteriaStatus
if [[ "${installHysteriaStatus}" == "1" ]]; then
hysteriaCoreInstall
elif [[ "${installHysteriaStatus}" == "2" && "${hysteriaStatus}" == "true" ]]; then
unInstallHysteriaCore
elif [[ "${installHysteriaStatus}" == "3" && "${hysteriaStatus}" == "true" ]]; then
hysteriaPortHoppingMenu
elif [[ "${installHysteriaStatus}" == "4" && "${hysteriaStatus}" == "true" ]]; then
hysteriaVersionManageMenu 1
elif [[ "${installHysteriaStatus}" == "5" && "${hysteriaStatus}" == "true" ]]; then
journalctl -fu hysteria
fi
}
#tuicadmin
manageTuic() {
echoContent skyBlue "\nProgress 1/1: Tuic Management"
echoContent red "\n================================================ ================="
local tuicStatus=
if [[ -n "${tuicConfigPath}" ]]; then
echoContent yellow "1.Reinstall"
echoContent yellow "2.Uninstall"
echoContent yellow "3.core management"
echoContent yellow "4.View log"
tuicStatus=true
else
echoContent yellow "1.Installation"
fi
echoContent red "================================================== ==============="
read -r -p "Please select:" installTuicStatus
if [[ "${installTuicStatus}" == "1" ]]; then
tuicCoreInstall
elif [[ "${installTuicStatus}" == "2" && "${tuicStatus}" == "true" ]]; then
unInstallTuicCore
elif [[ "${installTuicStatus}" == "3" && "${tuicStatus}" == "true" ]]; then
tuicVersionManageMenu 1
elif [[ "${installTuicStatus}" == "4" && "${tuicStatus}" == "true" ]]; then
journalctl -fu tuic
fi
}
# hysteria version management
hysteriaVersionManageMenu() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Hysteria version management"
if [[ ! -d "/etc/v2ray-agent/hysteria/" ]]; then
echoContent red " ---> The installation directory is not detected, please execute the script to install the content"
menu
exit 0
fi
echoContent red "\n================================================ ================="
echoContent yellow "1.Upgrade Hysteria"
echoContent yellow "2.Close Hysteria"
echoContent yellow "3.Open Hysteria"
echoContent yellow "4.Restart Hysteria"
echoContent red "================================================== ==============="
read -r -p "Please select:" selectHysteriaType
if [[ "${selectHysteriaType}" == "1" ]]; then
installHysteria 1
handleHysteria start
elif [[ "${selectHysteriaType}" == "2" ]]; then
handleHysteria stop
elif [[ "${selectHysteriaType}" == "3" ]]; then
handleHysteria start
elif [[ "${selectHysteriaType}" == "4" ]]; then
handleHysteria stop
handleHysteria start
fi
}
# Tuic version management
tuicVersionManageMenu() {
echoContent skyBlue "\nProgress$1/${totalProgress}: Tuic version management"
if [[ ! -d "/etc/v2ray-agent/tuic/" ]]; then
echoContent red " ---> The installation directory is not detected, please execute the script to install the content"
menu
exit 0
fi
echoContent red "\n================================================ ================="
echoContent yellow "1.Upgrade Tuic"
echoContent yellow "2.Close Tuic"
echoContent yellow "3.Open Tuic"
echoContent yellow "4.Restart Tuic"
echoContent red "================================================== ==============="
read -r -p "Please select:" selectTuicType
if [[ "${selectTuicType}" == "1" ]]; then
installTuic 1
handleTuic start
elif [[ "${selectTuicType}" == "2" ]]; then
handleTuic stop
elif [[ "${selectTuicType}" == "3" ]]; then
handleTuic start
elif [[ "${selectTuicType}" == "4" ]]; then
handleTuic stop
handleTuic start
fi
}
# main menu
menu() {
cd "$HOME" || exit
echoContent red "\n================================================ ================="
echoContent green "Author: mack-a"
echoContent green "Current version: v2.10.20"
echoContent green "Github: https://github.com/mack-a/v2ray-agent"
echoContent green "Description: 8-in-1 coexistence script\c"
showInstallStatus
checkWgetShowProgress
echoContent red "\n============================ Promotion area================ ============"
echoContent red " "
echoContent green "For promotion, please contact TG: @mackaff\n"
echoContent green "VPS purchasing guide: https://www.v2ray-agent.com/archives/1679975663984"
echoContent green "Low-price VPS AS4837 with an annual payment of 10 US dollars: https://www.v2ray-agent.com/archives/racknerdtao-can-zheng-li-nian-fu-10mei-yuan"
echoContent red "================================================== ==============="
if [[ -n "${coreInstallType}" ]]; then
echoContent yellow "1.Reinstall"
else
echoContent yellow "1.Installation"
fi
echoContent yellow "2.Install in any combination"
if echo ${currentInstallProtocolType} | grep -q trojan; then
echoContent yellow "3.Switch VLESS[XTLS]"
elif echo ${currentInstallProtocolType} | grep -q 0; then
echoContent yellow "3.Switch Trojan[XTLS]"
fi
echoContent yellow "4.Hysteria Management"
echoContent yellow "5.REALITY Management"
echoContent yellow "6.Tuic Management"
echoContent skyBlue "-------------------------Tool 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 yellow "11.Diversion tool"
echoContent yellow "12.Add new port"
echoContent yellow "13.BT download management"
echoContent yellow "14.Switch alpn"
echoContent yellow "15.Domain name blacklist"
echoContent skyBlue "-------------------------Version Management-------------------- ---------"
echoContent yellow "16.core management"
echoContent yellow "17.Update script"
echoContent yellow "18.Install BBR and DD scripts"
echoContent skyBlue "-------------------------Script Management-------------------- --- ------"
echoContent yellow "19.View log"
echoContent yellow "20.Uninstall script"
echoContent red "================================================== ==============="
mkdirTools
aliasInstall
read -r -p "Please select:" selectInstallType
case ${selectInstallType} in
1)
selectCoreInstall
;;
2)
selectCoreInstall
;;
3)
initXrayFrontingConfig 1
;;
4)
manageHysteria
;;
5)
manageReality 1
;;
6)
manageTuic
;;
7)
manageAccount 1
;;
8)
updateNginxBlog 1
;;
9)
renewalTLS 1
;;
10)
updateV2RayCDN 1
;;
11)
routingToolsMenu 1
;;
12)
addCorePort 1
;;
13)
btTools 1
;;
14)
switchAlpn 1
;;
15)
blacklist 1
;;
16)
coreVersionManageMenu 1
;;
17)
updateV2RayAgent 1
;;
18)
bbrInstall
;;
19)
checkLog 1
;;
20)
unInstall 1
;;
esac
}
cronFunction
menu