5548 lines
184 KiB
Bash
5548 lines
184 KiB
Bash
#!/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
|
||
}
|
||
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"
|
||
|
||
elif grep </etc/issue -q -i "debian" && [[ -f "/etc/issue" ]] || grep </etc/issue -q -i "debian" && [[ -f "/proc/version" ]]; then
|
||
release="debian"
|
||
installType='apt -y install'
|
||
upgrade="apt update"
|
||
updateReleaseInfoChange='apt-get --allow-releaseinfo-change update'
|
||
removeType='apt -y autoremove'
|
||
|
||
elif grep </etc/issue -q -i "ubuntu" && [[ -f "/etc/issue" ]] || grep </etc/issue -q -i "ubuntu" && [[ -f "/proc/version" ]]; then
|
||
release="ubuntu"
|
||
installType='apt -y install'
|
||
upgrade="apt update"
|
||
updateReleaseInfoChange='apt-get --allow-releaseinfo-change update'
|
||
removeType='apt -y autoremove'
|
||
if grep </etc/issue -q -i "16."; then
|
||
release=
|
||
fi
|
||
fi
|
||
|
||
if [[ -z ${release} ]]; then
|
||
echoContent red "\nThis script does not support this system, please feedback the log below 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"
|
||
;;
|
||
'armv8' | 'aarch64')
|
||
xrayCoreCPUVendor="Xray-linux-arm64-v8a"
|
||
v2rayCoreCPUVendor="v2ray-linux-arm64-v8a"
|
||
hysteriaCoreCPUVendor="hysteria-linux-arm64"
|
||
;;
|
||
*)
|
||
echo "This CPU architecture is not supported--->"
|
||
exit 1
|
||
;;
|
||
esac
|
||
fi
|
||
else
|
||
echoContent red "This CPU architecture cannot be recognized, default 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'
|
||
|
||
# Core supported cpu version
|
||
xrayCoreCPUVendor=""
|
||
v2rayCoreCPUVendor=""
|
||
hysteriaCoreCPUVendor=""
|
||
|
||
# domain name
|
||
domain=
|
||
|
||
# address of the CDN node
|
||
add=
|
||
|
||
# The total progress of the installation
|
||
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=
|
||
|
||
# prepended type
|
||
frontingType=
|
||
|
||
# Personalized installation method selected
|
||
selectCustomInstallType=
|
||
|
||
# Path to v2ray-core, xray-core configuration files
|
||
configPath=
|
||
|
||
# Path to hysteria configuration file
|
||
hysteriaConfigPath=
|
||
|
||
# The path to the configuration file
|
||
currentPath=
|
||
|
||
# config file host
|
||
currentHost=
|
||
|
||
# The core type selected during installation
|
||
selectCoreType=
|
||
|
||
# Default core version
|
||
v2rayCoreVersion=
|
||
|
||
# random path
|
||
customPath=
|
||
|
||
# centos version
|
||
centosVersion=
|
||
|
||
# UUID
|
||
currentUUID=
|
||
|
||
# previousClients
|
||
previousClients=
|
||
|
||
localIP=
|
||
|
||
# Integrated update certificate logic no longer uses a separate script --RenewTLS
|
||
renewTLS=$1
|
||
|
||
# The number of attempts after tls install failed
|
||
installTLSCount=
|
||
|
||
# BTPanel state
|
||
# BTPanelStatus=
|
||
|
||
# nginx configuration file path
|
||
nginxConfigPath=/etc/nginx/conf.d/
|
||
|
||
# Is it a preview version
|
||
prereleaseStatus=false
|
||
|
||
# ssl type
|
||
sslType=
|
||
|
||
# ssl mailbox
|
||
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=
|
||
|
||
# hysteria port
|
||
hysteriaPort=
|
||
|
||
# hysteria protocol
|
||
hysteriaProtocol=
|
||
|
||
# hysteria delay
|
||
hysteriaLag=
|
||
|
||
# hysteria downlink speed
|
||
hysteriaClientDownloadSpeed=
|
||
|
||
# hysteria uplink speed
|
||
hysteriaClientUploadSpeed=
|
||
|
||
}
|
||
|
||
# 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}" ]]; then
|
||
local port=
|
||
port=$(jq -r .inbounds[0].port "${configPath}${frontingType}.json")
|
||
if [[ "${port}" != "443" ]]; then
|
||
customPort=${port}
|
||
fi
|
||
fi
|
||
}
|
||
# Check the 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
|
||
# v2ray-core without XTLS
|
||
coreInstallType=2
|
||
ctlPath=/etc/v2ray-agent/v2ray/v2ctl
|
||
elif grep </etc/v2ray-agent/v2ray/conf/02_VLESS_TCP_inbounds.json -q '"security": "xtls"'; then
|
||
# v2ray-core with XTLS
|
||
ctlPath=/etc/v2ray-agent/v2ray/v2ctl
|
||
coreInstallType=3
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
if [[ -d "/etc/v2ray-agent/xray" && -f "/etc/v2ray-agent/xray/xray" ]]; then
|
||
# Check 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" ]]; then
|
||
# xray-core
|
||
configPath=/etc/v2ray-agent/xray/conf/
|
||
ctlPath=/etc/v2ray-agent/xray/xray
|
||
coreInstallType=1
|
||
fi
|
||
fi
|
||
|
||
if [[ -d "/etc/v2ray-agent/hysteria" && -f "/etc/v2ray-agent/hysteria/hysteria" ]]; then
|
||
# Check 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
|
||
|
||
fi
|
||
}
|
||
|
||
# read protocol type
|
||
readInstallProtocolType() {
|
||
currentInstallProtocolType=
|
||
|
||
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
|
||
done < <(find ${configPath} -name "*inbounds.json" | awk -F "[.]" '{print $1}')
|
||
|
||
if [[ -n "${hysteriaConfigPath}" ]]; then
|
||
currentInstallProtocolType=${currentInstallProtocolType}'6'
|
||
fi
|
||
}
|
||
|
||
# Check if pagoda is installed
|
||
checkBTPanel() {
|
||
if pgrep -f "BT-Panel"; then
|
||
nginxConfigPath=/www/server/panel/vhost/nginx/
|
||
# BTPanelStatus=true
|
||
fi
|
||
}
|
||
# Read the order of the current alpn
|
||
readInstallAlpn() {
|
||
if [[ -n ${currentInstallProtocolType} ]]; then
|
||
local alpn
|
||
alpn=$(jq -r .inbounds[0].streamSettings.xtlsSettings.alpn[0] ${configPath}${frontingType}.json)
|
||
if [[ -n ${alpn} ]]; then
|
||
currentAlpn=${alpn}
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# check firewall
|
||
allowPort() {
|
||
# 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(mack-a)"; then
|
||
updateFirewalldStatus=true
|
||
iptables -I INPUT -p tcp --dport "$1" -m comment --comment "allow $1(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"; then
|
||
sudo ufw allow "$1"
|
||
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/tcp"; then
|
||
updateFirewalldStatus=true
|
||
firewall-cmd --zone=public --add-port="$1/tcp" --permanent
|
||
checkFirewalldAllowPort "$1"
|
||
fi
|
||
|
||
if echo "${updateFirewalldStatus}" | grep -q "true"; then
|
||
firewall-cmd --reload
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Check the occupancy of ports 80 and 443
|
||
checkPortUsedStatus() {
|
||
if lsof -i tcp:80 | grep -q LISTEN; then
|
||
echoContent red "\n ---> Port 80 is occupied, please close it manually and install\n"
|
||
lsof -i tcp:80 | grep LISTEN
|
||
exit 0
|
||
fi
|
||
|
||
if lsof -i tcp:443 | grep -q LISTEN; then
|
||
echoContent red "\n ---> Port 443 is occupied, please close it manually and install\n"
|
||
lsof -i tcp:80 | grep LISTEN
|
||
exit 0
|
||
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 the 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
|
||
}
|
||
# Check the file directory and path path
|
||
readConfigHostPathUUID() {
|
||
currentPath=
|
||
currentDefaultPort=
|
||
currentUUID=
|
||
currentHost=
|
||
currentPort=
|
||
currentAdd=
|
||
# read path
|
||
if [[ -n "${configPath}" ]]; 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) == 31298 ]]; then
|
||
currentPath=$(echo "${path}" | awk -F "[t][c][p]" '{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
|
||
|
||
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
|
||
|
||
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
|
||
|
||
fi
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
currentHost=$(jq -r .inbounds[0].streamSettings.xtlsSettings.certificates[0].certificateFile ${configPath}${frontingType}.json | awk -F '[t][l][s][/]' '{print $2}' | awk -F '[.][c][r][t]' '{print $1}')
|
||
currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}${frontingType}.json)
|
||
currentAdd=$(jq -r .inbounds[0].settings.clients[0].add ${configPath}${frontingType}.json)
|
||
if [[ "${currentAdd}" == "null" ]]; then
|
||
currentAdd=${currentHost}
|
||
fi
|
||
currentPort=$(jq .inbounds[0].port ${configPath}${frontingType}.json)
|
||
|
||
elif [[ "${coreInstallType}" == "2" || "${coreInstallType}" == "3" ]]; then
|
||
if [[ "${coreInstallType}" == "3" ]]; then
|
||
|
||
currentHost=$(jq -r .inbounds[0].streamSettings.xtlsSettings.certificates[0].certificateFile ${configPath}${frontingType}.json | awk -F '[t][l][s][/]' '{print $2}' | awk -F '[.][c][r][t]' '{print $1}')
|
||
else
|
||
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}')
|
||
fi
|
||
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
|
||
}
|
||
|
||
# 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 "Protocol installed: \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/XTLS] \c"
|
||
fi
|
||
fi
|
||
|
||
if echo ${currentInstallProtocolType} | grep -q trojan; then
|
||
if [[ "${coreInstallType}" == 1 ]]; then
|
||
echoContent yellow "Trojan+TCP[TLS/XTLS] \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
|
||
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
|
||
checkBTPanel
|
||
#----------------------------------------------------
|
||
|
||
# Initialize the installation directory
|
||
mkdirTools() {
|
||
mkdir -p /etc/v2ray-agent/tls
|
||
mkdir -p /etc/v2ray-agent/subscribe
|
||
mkdir -p /etc/v2ray-agent/subscribe_tmp
|
||
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/trojan
|
||
mkdir -p /etc/v2ray-agent/hysteria/conf
|
||
mkdir -p /etc/systemd/system/
|
||
mkdir -p /tmp/v2ray-agent-tls/
|
||
}
|
||
|
||
# install toolkit
|
||
installTools() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : Install Tool"
|
||
# Fix ubuntu individual system issues
|
||
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 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 the nginx version and provide the option to uninstall
|
||
|
||
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 then reinstall it? [y/n]:" unInstallNginxStatus
|
||
if [[ "${unInstallNginxStatus}" == "y" ]]; then
|
||
${removeType} nginx >/dev/null 2>&1
|
||
echoContent yellow " ---> nginx uninstallation completed"
|
||
echoContent green " ---> install nginx"
|
||
installNginxTools >/dev/null 2>&1
|
||
else
|
||
exit 0
|
||
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 [[ ! -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, the recovery progress can be viewed at [https://www.githubstatus.com/]"
|
||
echoContent red "There is a bug in the 2.acme.sh script, see [https://github.com/acmesh-official/acme.sh] issues"
|
||
echoContent red " 3.For pure IPv6 machines, please set up NAT64 and execute the following commands"
|
||
echoContent skyBlue " echo -e \"nameserver 2001:67c:2b0::4\\\nnameserver 2001:67c:2b0::6\" >> /etc/resolv.conf"
|
||
exit 0
|
||
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() {
|
||
${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
|
||
|
||
# if [[]];then
|
||
# fi
|
||
# todo curl --socks5 127.0.0.1:31303 https://www.cloudflare.com/cdn-cgi/trace
|
||
# systemctl daemon-reload
|
||
# systemctl enable cloudflare-warp
|
||
}
|
||
# Initialize Nginx application certificate configuration
|
||
initTLSNginxConfig() {
|
||
handleNginx stop
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : Initialize Nginx application certificate configuration"
|
||
if [[ -n "${currentHost}" ]]; then
|
||
echo
|
||
read -r -p "Read the last installation record, do you use the domain name of 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 Example: www.v2ray-agent.com --->"
|
||
read -r -p "domain name:" domain
|
||
fi
|
||
else
|
||
echo
|
||
echoContent yellow "Please enter the domain name to be configured Example: www.v2ray-agent.com --->"
|
||
read -r -p "domain name:" domain
|
||
fi
|
||
|
||
if [[ -z ${domain} ]]; then
|
||
echoContent red "The domain name cannot be empty--->"
|
||
initTLSNginxConfig 3
|
||
else
|
||
dnsTLSDomain=$(echo "${domain}" | awk -F "[.]" '{print $(NF-1)"."$NF}')
|
||
customPortFunction
|
||
local port=80
|
||
if [[ -n "${customPort}" ]]; then
|
||
port=${customPort}
|
||
fi
|
||
|
||
# Change setting
|
||
touch ${nginxConfigPath}alone.conf
|
||
cat <<EOF >${nginxConfigPath}alone.conf
|
||
server {
|
||
listen ${port};
|
||
listen [::]:${port};
|
||
server_name ${domain};
|
||
root /usr/share/nginx/html;
|
||
location ~ /.well-known {
|
||
allow all;
|
||
}
|
||
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
|
||
}
|
||
|
||
# Modify nginx redirect configuration
|
||
updateRedirectNginxConf() {
|
||
|
||
# if [[ ${BTPanelStatus} == "true" ]]; then
|
||
#
|
||
# cat <<EOF >${nginxConfigPath}alone.conf
|
||
# server {
|
||
# listen 127.0.0.1:31300;
|
||
# server_name _;
|
||
# return 403;
|
||
# }
|
||
#EOF
|
||
#
|
||
# elif [[ -n "${customPort}" ]]; then
|
||
# cat <<EOF >${nginxConfigPath}alone.conf
|
||
# server {
|
||
# listen 127.0.0.1:31300;
|
||
# server_name _;
|
||
# return 403;
|
||
# }
|
||
#EOF
|
||
# fi
|
||
local redirectDomain=${domain}
|
||
if [[ -n "${customPort}" ]]; then
|
||
redirectDomain=${domain}:${customPort}
|
||
fi
|
||
cat <<EOF >${nginxConfigPath}alone.conf
|
||
server {
|
||
listen 80;
|
||
server_name ${domain};
|
||
return 302 https://${redirectDomain};
|
||
}
|
||
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
|
||
|
||
cat <<EOF >>${nginxConfigPath}alone.conf
|
||
server {
|
||
listen 127.0.0.1:31302 http2 so_keepalive=on;
|
||
server_name ${domain};
|
||
root /usr/share/nginx/html;
|
||
|
||
client_header_timeout 1071906480m;
|
||
keepalive_timeout 1071906480m;
|
||
|
||
location /s/ {
|
||
add_header Content-Type text/plain;
|
||
alias /etc/v2ray-agent/subscribe/;
|
||
}
|
||
|
||
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 /usr/share/nginx/html;
|
||
location /s/ {
|
||
add_header Content-Type text/plain;
|
||
alias /etc/v2ray-agent/subscribe/;
|
||
}
|
||
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 /usr/share/nginx/html;
|
||
location /s/ {
|
||
add_header Content-Type text/plain;
|
||
alias /etc/v2ray-agent/subscribe/;
|
||
}
|
||
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 /usr/share/nginx/html;
|
||
location /s/ {
|
||
add_header Content-Type text/plain;
|
||
alias /etc/v2ray-agent/subscribe/;
|
||
}
|
||
location / {
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
cat <<EOF >>${nginxConfigPath}alone.conf
|
||
server {
|
||
listen 127.0.0.1:31300;
|
||
server_name ${domain};
|
||
root /usr/share/nginx/html;
|
||
location /s/ {
|
||
add_header Content-Type text/plain;
|
||
alias /etc/v2ray-agent/subscribe/;
|
||
}
|
||
location / {
|
||
add_header Strict-Transport-Security "max-age=15552000; preload" always;
|
||
}
|
||
}
|
||
EOF
|
||
|
||
}
|
||
|
||
# check ip
|
||
checkIP() {
|
||
echoContent skyBlue "\n ---> Check the domain name ip"
|
||
local checkDomain=${domain}
|
||
if [[ -n "${customPort}" ]]; then
|
||
checkDomain="http://${domain}:${customPort}"
|
||
fi
|
||
localIP=$(curl -s -m 2 "${checkDomain}/ip")
|
||
|
||
handleNginx stop
|
||
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 dns to take effect, it is expected to take effect within three minutes"
|
||
echoContent yellow " ---> 4.If a problem with Nginx startup is reported, please manually start nginx to check the error.If you can't handle it yourself, please file issues"
|
||
echoContent yellow " ---> 5.Error log: ${localIP}"
|
||
echo
|
||
echoContent skyBlue " ---> If the above settings are correct, please reinstall the pure system and try again"
|
||
|
||
if [[ -n ${localIP} ]]; then
|
||
echoContent yellow " ---> The detection return value is abnormal, it is recommended to manually uninstall nginx and re-execute the script"
|
||
fi
|
||
local portFirewallPortStatus="443、80"
|
||
|
||
if [[ -n "${customPort}" ]]; then
|
||
portFirewallPortStatus="${customPort}"
|
||
fi
|
||
echoContent red " ---> Please check if firewall rules are open ${portFirewallPortStatus}\n"
|
||
read -r -p "Do you want to modify the firewall rules by script to open the port ${portFirewallPortStatus}? [y/n]:" allPortFirewallStatus
|
||
|
||
if [[ ${allPortFirewallStatus} == "y" ]]; then
|
||
if [[ -n "${customPort}" ]]; then
|
||
allowPort "${customPort}"
|
||
else
|
||
allowPort 80
|
||
allowPort 443
|
||
fi
|
||
|
||
handleNginx start
|
||
checkIP
|
||
else
|
||
exit 0
|
||
fi
|
||
else
|
||
if echo "${localIP}" | awk -F "[,]" '{print $2}' | grep -q "." || echo "${localIP}" | awk -F "[,]" '{print $2}' | grep -q ":"; then
|
||
echoContent red "\n ---> Multiple IPs detected, please confirm whether to close cloudflare's cloud"
|
||
echoContent yellow " ---> After closing the cloud, wait three minutes and try again"
|
||
echoContent yellow " ---> The detected ip is as follows: [${localIP}]"
|
||
exit 0
|
||
fi
|
||
echoContent green " ---> The current domain name ip is: [${localIP}]"
|
||
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 email address:" sslEmail
|
||
if echo "${sslEmail}" | grep -q "@"; then
|
||
echo "ACCOUNT_EMAIL='${sslEmail}'" >>/root/.acme.sh/account.conf
|
||
echoContent green " ---> Add 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[DNS request not supported]"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select [Enter] to use default:" selectSSLType
|
||
case ${selectSSLType} in
|
||
1)
|
||
sslType="letsencrypt"
|
||
;;
|
||
2)
|
||
sslType="zerossl"
|
||
;;
|
||
3)
|
||
sslType="buypass"
|
||
;;
|
||
*)
|
||
sslType="letsencrypt"
|
||
;;
|
||
esac
|
||
touch /etc/v2ray-agent/tls
|
||
echo "${sslType}" >/etc/v2ray-agent/tls/ssl_type
|
||
|
||
fi
|
||
}
|
||
|
||
# Select the 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
|
||
read -r -p "Whether to use DNS to apply for certificate [y/n]:" installSSLDNSStatus
|
||
if [[ ${installSSLDNStatus} == 'y' ]]; then
|
||
dnsSSLStatus=true
|
||
fi
|
||
fi
|
||
acmeInstallSSL
|
||
|
||
readAcmeTLS
|
||
}
|
||
|
||
# Install SSL certificate
|
||
acmeInstallSSL() {
|
||
if [[ "${dnsSSLStatus}" == "true" ]]; then
|
||
|
||
sudo "$HOME/.acme.sh/acme.sh" --issue -d "*.${dnsTLSDomain}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --standalone -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 manually add DNS TXT record"
|
||
echoContent yellow " ---> Please refer to this tutorial for adding methods, https://github.com/mack-a/v2ray-agent/blob/master/documents/dns_txt.md"
|
||
echoContent green " ---> name:_acme-challenge"
|
||
echoContent green " ---> value:${txtValue}"
|
||
echoContent yellow " ---> Please wait for 1-2 minutes after the addition is complete"
|
||
echo
|
||
read -r -p "Whether the addition is complete [y/n]:" addDNSTXTRecordStatus
|
||
if [[ "${addDNSTXTRecordStatus}" == "y" ]]; then
|
||
local txtAnswer=
|
||
txtAnswer=$(dig +nocmd "_acme-challenge.${dnsTLSDomain}" txt +noall +answer | awk -F "[\"]" '{print $2}')
|
||
if [[ "${txtAnswer}" == "${txtValue}" ]]; then
|
||
echoContent green " ---> TXT record verification passed"
|
||
echoContent green "---> Generating certificate"
|
||
sudo "$HOME/.acme.sh/acme.sh" --renew -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
|
||
echoContent red " ---> Authentication failed, please try again after 1-2 minutes"
|
||
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=
|
||
local showPort=
|
||
if [[ -n "${customPort}" || -n "${currentPort}" ]]; then
|
||
echo
|
||
read -r -p "Read the port of the last installation, do you use the port of the last installation? [y/n]:" historyCustomPortStatus
|
||
if [[ "${historyCustomPortStatus}" == "y" ]]; then
|
||
showPort="${currentPort}"
|
||
if [[ -n "${customPort}" ]]; then
|
||
showPort="${customPort}"
|
||
fi
|
||
echoContent yellow "\n ---> Port: ${showPort}"
|
||
fi
|
||
fi
|
||
|
||
if [[ "${historyCustomPortStatus}" == "n" ]] && [[ -z "${customPort}" && -z "${currentPort}" ]]; then
|
||
echo
|
||
echoContent yellow "Please enter the port [default: 443], such as a custom port, only allow the use of DNS to apply for a certificate [enter to use the default]"
|
||
read -r -p "port:" customPort
|
||
if [[ -n "${customPort}" ]]; then
|
||
if ((customPort >= 1 && customPort <= 65535)); then
|
||
checkCustomPort
|
||
allowPort "${customPort}"
|
||
else
|
||
echoContent red " ---> Port input error"
|
||
exit
|
||
fi
|
||
else
|
||
echoContent yellow "\n ---> Port: 443"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Check if the port is occupied
|
||
checkCustomPort() {
|
||
if lsof -i "tcp:${customPort}" | grep -q LISTEN; then
|
||
echoContent red "\n ---> ${customPort} port is occupied, please close it manually and install it\n"
|
||
lsof -i tcp:80 | 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 not expired or custom certificate, 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"
|
||
|
||
if [[ "${installDNSACMEStatus}" != "true" ]]; then
|
||
switchSSLType
|
||
customSSLEmail
|
||
selectAcmeInstallSSL
|
||
else
|
||
echoContent green " ---> Detected that a wildcard certificate has been installed, automatically generating"
|
||
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}" -d "*.${dnsTLSDomain}" --fullchainpath "/etc/v2ray-agent/tls/${tlsDomain}.crt" --keypath "/etc/v2ray-agent/tls/${tlsDomain}.key" --ecc >/dev/null
|
||
fi
|
||
|
||
elif [[ -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
|
||
echoContent red "---> TLS installation failed, checking whether ports 80 and 443 are open"
|
||
allowPort 80
|
||
allowPort 443
|
||
echoContent yellow " ---> Retry to install TLS certificate"
|
||
|
||
if tail -n 10 /etc/v2ray-agent/tls/acme.log | grep -q "Could not validate email address as valid"; then
|
||
echoContent red " ---> The mailbox cannot be verified by the SSL manufacturer, 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
|
||
}
|
||
# Configure fake blog
|
||
initNginxConfig() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : configure Nginx"
|
||
|
||
cat <<EOF >${nginxConfigPath}alone.conf
|
||
server {
|
||
listen 80;
|
||
listen [::]:80;
|
||
server_name ${domain};
|
||
root /usr/share/nginx/html;
|
||
location ~ /.well-known {allow all;}
|
||
location /test {return 200 'fjkvymb6len';}
|
||
}
|
||
EOF
|
||
}
|
||
|
||
# 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 use the path of the last installation? [y/n]:" historyPathStatus
|
||
echo
|
||
fi
|
||
|
||
if [[ "${historyPathStatus}" == "y" ]]; then
|
||
customPath=${currentPath}
|
||
echoContent green " ---> Use successfully\n"
|
||
else
|
||
echoContent yellow "Please enter a custom path [example: alone], no slashes required, [enter] random path"
|
||
read -r -p 'path:' customPath
|
||
|
||
if [[ -z "${customPath}" ]]; then
|
||
customPath=$(head -n 50 /dev/urandom | sed 's/[^a-z]//g' | strings -n 4 | tr '[:upper:]' '[:lower:]' | head -1)
|
||
currentPath=${customPath:0:4}
|
||
customPath=${currentPath}
|
||
else
|
||
currentPath=${customPath}
|
||
fi
|
||
|
||
fi
|
||
echoContent yellow "\n path:${currentPath}"
|
||
echoContent skyBlue "\n----------------------------"
|
||
}
|
||
# Nginx Camouflage Blog
|
||
nginxBlog() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : Add fake site"
|
||
if [[ -d "/usr/share/nginx/html" && -f "/usr/share/nginx/html/check" ]]; then
|
||
echo
|
||
read -r -p "Detected installation of fake sites, do you need to reinstall [y/n]:" nginxBlogInstallStatus
|
||
if [[ "${nginxBlogInstallStatus}" == "y" ]]; then
|
||
rm -rf /usr/share/nginx/html
|
||
randomNum=$((RANDOM % 6 + 1))
|
||
wget -q -P /usr/share/nginx https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip >/dev/null
|
||
unzip -o /usr/share/nginx/html${randomNum}.zip -d /usr/share/nginx/html >/dev/null
|
||
rm -f /usr/share/nginx/html${randomNum}.zip*
|
||
echoContent green " ---> Add fake site successfully"
|
||
fi
|
||
else
|
||
randomNum=$((RANDOM % 6 + 1))
|
||
rm -rf /usr/share/nginx/html
|
||
wget -q -P /usr/share/nginx https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip >/dev/null
|
||
unzip -o /usr/share/nginx/html${randomNum}.zip -d /usr/share/nginx/html >/dev/null
|
||
rm -f /usr/share/nginx/html${randomNum}.zip*
|
||
echoContent green " ---> Add 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 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
|
||
}
|
||
|
||
# Operate 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() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : Add scheduled maintenance certificate"
|
||
crontab -l >/etc/v2ray-agent/backup_crontab.cron
|
||
local historyCrontab
|
||
historyCrontab=$(sed '/v2ray-agent/d;/acme.sh/d' /etc/v2ray-agent/backup_crontab.cron)
|
||
echo "${historyCrontab}" >/etc/v2ray-agent/backup_crontab.cron
|
||
echo "30 1 * * * /bin/bash /etc/v2ray-agent/install.sh RenewTLS >> /etc/v2ray-agent/crontab_tls.log 2>&1" >>/etc/v2ray-agent/backup_crontab.cron
|
||
crontab /etc/v2ray-agent/backup_crontab.cron
|
||
echoContent green "\n ---> Adding the timing maintenance certificate successfully"
|
||
}
|
||
|
||
# update certificate
|
||
renewalTLS() {
|
||
|
||
if [[ -n $1 ]]; then
|
||
echoContent skyBlue "\nProgress $1/1 : Renew 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 "$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer" | sed -n '7,6p' | awk '{print $2" "$3" "$4" "$5}')
|
||
else
|
||
modifyTime=$(stat "$HOME/.acme.sh/${domain}_ecc/${domain}.cer" | sed -n '7,6p' | awk '{print $2" "$3" "$4" "$5}')
|
||
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 " ---> Certificate remaining days:"${tlsStatus}
|
||
echoContent skyBlue " ---> The certificate will be automatically updated on the last day before the certificate expires.If the update fails, please update it manually"
|
||
|
||
if [[ ${remainingDays} -le 1 ]]; then
|
||
echoContent yellow " ---> regenerate certificate"
|
||
handleNginx stop
|
||
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 " ---> Certificate valid"
|
||
fi
|
||
else
|
||
echoContent red "---> not installed"
|
||
fi
|
||
}
|
||
# View the status of the 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 " ---> Certificate remaining days: ${tlsStatus}"
|
||
fi
|
||
}
|
||
|
||
# Install V2Ray, specify the 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 | 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 --show-progress -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, 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} : Install Hysteria"
|
||
|
||
if [[ -z "${hysteriaConfigPath}" ]]; then
|
||
|
||
version=$(curl -s https://api.github.com/repos/apernet/hysteria/hysteria/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | head -1)
|
||
|
||
echoContent green " ---> Hysteria version: ${version}"
|
||
if wget --help | grep -q show-progress; then
|
||
wget -c -q --show-progress -P /etc/v2ray-agent/hysteria/ "https://github.com/apernet/hysteria/hysteria/releases/download/${version}/${hysteriaCoreCPUVendor}"
|
||
else
|
||
wget -c -P /etc/v2ray-agent/hysteria/ "https://github.com/apernet/hysteria/hysteria/releases/download/${version}/${hysteriaCoreCPUVendor}" >/dev/null 2>&1
|
||
fi
|
||
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 "Update, upgrade? [y/n]:" reInstallHysteriaStatus
|
||
if [[ "${reInstallHysteriaStatus}" == "y" ]]; then
|
||
rm -f /etc/v2ray-agent/hysteria/hysteria
|
||
installHysteria "$1"
|
||
fi
|
||
fi
|
||
|
||
}
|
||
# install xray
|
||
installXray() {
|
||
readInstallType
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : Install Xray"
|
||
|
||
if [[ "${coreInstallType}" != "1" ]]; then
|
||
|
||
version=$(curl -s https://api.github.com/repos/XTLS/Xray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | head -1)
|
||
|
||
echoContent green " ---> Xray-core version: ${version}"
|
||
if wget --help | grep -q show-progress; then
|
||
wget -c -q --show-progress -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip"
|
||
else
|
||
wget -c -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip" >/dev/null 2>&1
|
||
fi
|
||
|
||
unzip -o "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" -d /etc/v2ray-agent/xray >/dev/null
|
||
rm -rf "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip"
|
||
chmod 655 /etc/v2ray-agent/xray/xray
|
||
else
|
||
echoContent green " ---> Xray-core version:$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)"
|
||
read -r -p "Update, upgrade? [y/n]:" reInstallXrayStatus
|
||
if [[ "${reInstallXrayStatus}" == "y" ]]; then
|
||
rm -f /etc/v2ray-agent/xray/xray
|
||
installXray "$1"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# v2ray version management
|
||
v2rayVersionManageMenu() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : V2Ray version management"
|
||
if [[ ! -d "/etc/v2ray-agent/v2ray/" ]]; then
|
||
echoContent red " ---> No installation directory 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 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.It is not guaranteed that it can be used normally after the rollback"
|
||
echoContent yellow "3.If the rolled back version does not support the current config, it will not be able to connect, 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 ---> Input error, please re-enter"
|
||
v2rayVersionManageMenu 1
|
||
fi
|
||
elif [[ "${selectV2RayType}" == "3" ]]; then
|
||
handleV2Ray stop
|
||
elif [[ "${selectV2RayType}" == "4" ]]; then
|
||
handleV2Ray start
|
||
elif [[ "${selectV2RayType}" == "5" ]]; then
|
||
reloadCore
|
||
fi
|
||
}
|
||
|
||
# xray version management
|
||
xrayVersionManageMenu() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : Xray Version Management"
|
||
if [[ ! -d "/etc/v2ray-agent/xray/" ]]; then
|
||
echoContent red " ---> No installation directory 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 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.It is not guaranteed that it can be used normally after the rollback"
|
||
echoContent yellow "3.If the rolled back version does not support the current config, it will not be able to connect, operate with caution"
|
||
echoContent skyBlue "------------------------Version-------------------------------"
|
||
curl -s https://api.github.com/repos/XTLS/Xray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | head -5 | awk '{print ""NR""":"$0}'
|
||
echoContent skyBlue "--------------------------------------------------------------"
|
||
read -r -p "Please enter the version to be rolled back:" selectXrayVersionType
|
||
version=$(curl -s https://api.github.com/repos/XTLS/Xray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | head -5 | awk '{print ""NR""":"$0}' | grep "${selectXrayVersionType}:" | awk -F "[:]" '{print $2}')
|
||
if [[ -n "${version}" ]]; then
|
||
updateXray "${version}"
|
||
else
|
||
echoContent red "\n ---> Input error, please re-enter"
|
||
xrayVersionManageMenu 1
|
||
fi
|
||
elif [[ "${selectXrayType}" == "4" ]]; then
|
||
handleXray stop
|
||
elif [[ "${selectXrayType}" == "5" ]]; then
|
||
handleXray start
|
||
elif [[ "${selectXrayType}" == "6" ]]; then
|
||
reloadCore
|
||
fi
|
||
|
||
}
|
||
# 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 --show-progress -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" || "${coreInstallType}" == "3" ]]; 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 " ---> Abort the fallback 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 " ---> Abort reinstallation"
|
||
fi
|
||
else
|
||
read -r -p "The latest version is: ${version}, 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 | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1)
|
||
fi
|
||
|
||
echoContent green " ---> Xray-core version: ${version}"
|
||
|
||
if wget --help | grep -q show-progress; then
|
||
wget -c -q --show-progress -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip"
|
||
else
|
||
wget -c -P /etc/v2ray-agent/xray/ "https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip" >/dev/null 2>&1
|
||
fi
|
||
|
||
unzip -o "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip" -d /etc/v2ray-agent/xray >/dev/null
|
||
rm -rf "/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip"
|
||
chmod 655 /etc/v2ray-agent/xray/xray
|
||
handleXray stop
|
||
handleXray start
|
||
else
|
||
echoContent green " ---> 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 | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1)
|
||
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 " ---> Abort the fallback 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 " ---> Abort reinstallation"
|
||
fi
|
||
else
|
||
read -r -p "The latest version is: ${version}, update? [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" || "${coreInstallType}" == "3" ]] && [[ -n $(pgrep -f v2ray/v2ray) ]]; then
|
||
echoContent green " ---> Service started successfully"
|
||
else
|
||
echoContent red " ---> The service failed to start, please check whether the terminal has log printing"
|
||
exit 0
|
||
fi
|
||
|
||
}
|
||
|
||
# V2Ray starts automatically
|
||
installV2RayService() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : configure V2Ray to start automatically"
|
||
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 after booting successfully"
|
||
fi
|
||
}
|
||
|
||
# Install hysteria to start automatically
|
||
installHysteriaService() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : configure Hysteria to start automatically"
|
||
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/hysteria/hysteria/wiki
|
||
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 hysteria.service
|
||
echoContent green " ---> Configure Hysteria to boot successfully"
|
||
fi
|
||
}
|
||
# Xray starts automatically at boot
|
||
installXrayService() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : configure Xray to start automatically"
|
||
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/Xray-core
|
||
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 xray.service
|
||
echoContent green " ---> Configure Xray to boot successfully"
|
||
fi
|
||
}
|
||
|
||
# Operate 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] to view 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 "Failed to close V2Ray"
|
||
echoContent red "Please manually execute [ps -ef|grep -v grep|grep v2ray|awk '{print \$2}'|xargs kill -9]"
|
||
exit 0
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Operate 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 failed to start"
|
||
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 manually execute [ps -ef|grep -v grep|grep hysteria|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 failed to start"
|
||
echoContent red "Please manually execute [/etc/v2ray-agent/xray/xray -confdir /etc/v2ray-agent/xray/conf] to view 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 close failed"
|
||
echoContent red "Please manually execute [ps -ef|grep -v grep|grep xray|awk '{print \$2}'|xargs kill -9]"
|
||
exit 0
|
||
fi
|
||
fi
|
||
}
|
||
# Get clients configuration
|
||
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 last installed configuration file of this protocol [${protocol}] was not read, the first uuid of the configuration file is 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 the hysteria port
|
||
initHysteriaPort() {
|
||
readHysteriaConfig
|
||
if [[ -n "${hysteriaPort}" ]]; then
|
||
read -r -p "Read the port of the last installation, do you use the port of 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 [Example: 10000], which cannot be repeated with other services"
|
||
read -r -p "Port:" hysteriaPort
|
||
fi
|
||
if [[ -z ${hysteriaPort} ]]; then
|
||
echoContent red " ---> Port cannot be empty"
|
||
initHysteriaPort "$2"
|
||
elif ((hysteriaPort < 1 || hysteriaPort > 65535)); then
|
||
echoContent red " ---> The port is invalid"
|
||
initHysteriaPort "$2"
|
||
fi
|
||
allowPort "${hysteriaPort}"
|
||
}
|
||
|
||
# Initialize the protocol of hysteria
|
||
initHysteriaProtocol() {
|
||
echoContent skyBlue "\nPlease select a 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 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 downlink speed (default: 100, unit: Mbps)"
|
||
read -r -p "Download speed:" hysteriaClientDownloadSpeed
|
||
if [[ -z "${hysteriaClientDownloadSpeed}" ]]; then
|
||
hysteriaClientDownloadSpeed=100
|
||
echoContent yellow "\n ---> Downlink 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 ---> Uplink speed: ${hysteriaClientUploadSpeed}\n"
|
||
fi
|
||
|
||
cat <<EOF >/etc/v2ray-agent/hysteria/conf/client_network.json
|
||
{
|
||
"hysteriaLag":"${hysteriaLag}",
|
||
"hysteriaClientUploadSpeed":"${hysteriaClientUploadSpeed}",
|
||
"hysteriaClientDownloadSpeed":"${hysteriaClientDownloadSpeed}"
|
||
}
|
||
EOF
|
||
|
||
}
|
||
# Initialize Hysteria configuration
|
||
initHysteriaConfig() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : Initialize Hysteria configuration"
|
||
|
||
initHysteriaPort
|
||
initHysteriaProtocol
|
||
initHysteriaNetwork
|
||
|
||
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": []
|
||
},
|
||
"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
|
||
}
|
||
|
||
# Initialize V2Ray configuration file
|
||
initV2RayConfig() {
|
||
echoContent skyBlue "\nProgress $2/${totalProgress} : Initialize V2Ray configuration"
|
||
echo
|
||
|
||
read -r -p "Custom 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 use the UUID of 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 read 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 to 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": "${domain}_${uuid}"
|
||
}
|
||
],
|
||
"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": "${domain}_${uuid}"
|
||
}
|
||
],
|
||
"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": "${domain}_${uuid}"
|
||
}
|
||
],
|
||
"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": "${domain}_${uuid}"
|
||
}
|
||
]
|
||
},
|
||
"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": "${domain}_${uuid}"
|
||
}
|
||
],
|
||
"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": "${domain}_VLESS_TLS-direct_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() {
|
||
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 "replaces the prefix with ${xtlsType}"
|
||
echoContent yellow "If the prefix is Trojan, when viewing the account, there will be two nodes of the Trojan protocol, one of which is unavailable xtls"
|
||
echoContent yellow "Execute again to switch to the previous preamble\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}" ]] && [[ -f "${configPath}02_VLESS_TCP_inbounds.json" ]]; then
|
||
rm -rf ${configPath}../tmp/*
|
||
mv ${configPath}* ${configPath}../tmp/
|
||
fi
|
||
|
||
}
|
||
|
||
# Initialize Xray configuration file
|
||
initXrayConfig() {
|
||
echoContent skyBlue "\nProgress $2/${totalProgress} : Initialize Xray configuration"
|
||
echo
|
||
local uuid=
|
||
local addClientsStatus=
|
||
if [[ -n "${currentUUID}" ]]; then
|
||
read -r -p "Read the last installation record, do you use the UUID of the last installation? [y/n]:" historyUUIDStatus
|
||
if [[ "${historyUUIDStatus}" == "y" ]]; then
|
||
addClientsStatus=true
|
||
uuid=${currentUUID}
|
||
echoContent green "\n ---> Successfully used"
|
||
fi
|
||
fi
|
||
|
||
if [[ -z "${uuid}" ]]; then
|
||
echoContent yellow "Please enter a custom UUID [must 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 "${uuid}" ]]; then
|
||
addClientsStatus=
|
||
echoContent red "\n ---> uuid read error, regenerate"
|
||
uuid=$(/etc/v2ray-agent/xray/xray uuid)
|
||
fi
|
||
|
||
echoContent yellow "\n ${uuid}"
|
||
|
||
movePreviousConfig
|
||
|
||
# log
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/00_log.json
|
||
{
|
||
"log": {
|
||
"error": "/etc/v2ray-agent/xray/error.log",
|
||
"loglevel": "warning"
|
||
}
|
||
}
|
||
EOF
|
||
|
||
# outbounds
|
||
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":"blackhole",
|
||
"tag":"blackhole-out"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
# dns
|
||
cat <<EOF >/etc/v2ray-agent/xray/conf/11_dns.json
|
||
{
|
||
"dns": {
|
||
"servers": [
|
||
"localhost"
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
|
||
# VLESS_TCP_TLS/XTLS
|
||
# fall back to 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/xray/conf/04_trojan_TCP_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"port": 31296,
|
||
"listen": "127.0.0.1",
|
||
"protocol": "trojan",
|
||
"tag":"trojanTCP",
|
||
"settings": {
|
||
"clients": [
|
||
{
|
||
"password": "${uuid}",
|
||
"email": "${domain}_${uuid}"
|
||
}
|
||
],
|
||
"fallbacks":[
|
||
{"dest":"31300"}
|
||
]
|
||
},
|
||
"streamSettings": {
|
||
"network": "tcp",
|
||
"security": "none",
|
||
"tcpSettings": {
|
||
"acceptProxyProtocol": true
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
addClients "/etc/v2ray-agent/xray/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/xray/conf/03_VLESS_WS_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"port": 31297,
|
||
"listen": "127.0.0.1",
|
||
"protocol": "vless",
|
||
"tag":"VLESSWS",
|
||
"settings": {
|
||
"clients": [
|
||
{
|
||
"id": "${uuid}",
|
||
"email": "${domain}_${uuid}"
|
||
}
|
||
],
|
||
"decryption": "none"
|
||
},
|
||
"streamSettings": {
|
||
"network": "ws",
|
||
"security": "none",
|
||
"wsSettings": {
|
||
"acceptProxyProtocol": true,
|
||
"path": "/${customPath}ws"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
addClients "/etc/v2ray-agent/xray/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/xray/conf/04_trojan_gRPC_inbounds.json
|
||
{
|
||
"inbounds": [
|
||
{
|
||
"port": 31304,
|
||
"listen": "127.0.0.1",
|
||
"protocol": "trojan",
|
||
"tag": "trojangRPCTCP",
|
||
"settings": {
|
||
"clients": [
|
||
{
|
||
"password": "${uuid}",
|
||
"email": "${domain}_${uuid}"
|
||
}
|
||
],
|
||
"fallbacks": [
|
||
{
|
||
"dest": "31300"
|
||
}
|
||
]
|
||
},
|
||
"streamSettings": {
|
||
"network": "grpc",
|
||
"grpcSettings": {
|
||
"serviceName": "${customPath}trojangrpc"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
addClients "/etc/v2ray-agent/xray/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/xray/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": "${domain}_${uuid}"
|
||
}
|
||
]
|
||
},
|
||
"streamSettings": {
|
||
"network": "ws",
|
||
"security": "none",
|
||
"wsSettings": {
|
||
"acceptProxyProtocol": true,
|
||
"path": "/${customPath}vws"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
addClients "/etc/v2ray-agent/xray/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/xray/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": "${domain}_${uuid}"
|
||
}
|
||
],
|
||
"decryption": "none"
|
||
},
|
||
"streamSettings": {
|
||
"network": "grpc",
|
||
"grpcSettings": {
|
||
"serviceName": "${customPath}grpc"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
addClients "/etc/v2ray-agent/xray/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/xray/conf/02_VLESS_TCP_inbounds.json
|
||
{
|
||
"inbounds":[
|
||
{
|
||
"port": ${defaultPort},
|
||
"protocol": "vless",
|
||
"tag":"VLESSTCP",
|
||
"settings": {
|
||
"clients": [
|
||
{
|
||
"id": "${uuid}",
|
||
"add":"${add}",
|
||
"flow":"xtls-rprx-direct",
|
||
"email": "${domain}_${uuid}"
|
||
}
|
||
],
|
||
"decryption": "none",
|
||
"fallbacks": [
|
||
${fallbacksList}
|
||
]
|
||
},
|
||
"streamSettings": {
|
||
"network": "tcp",
|
||
"security": "xtls",
|
||
"xtlsSettings": {
|
||
"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/xray/conf/02_VLESS_TCP_inbounds.json" "${addClientsStatus}"
|
||
}
|
||
|
||
# Initialize Trojan-Go configuration
|
||
initTrojanGoConfig() {
|
||
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : Initialize Trojan configuration"
|
||
cat <<EOF >/etc/v2ray-agent/trojan/config_full.json
|
||
{
|
||
"run_type": "server",
|
||
"local_addr": "127.0.0.1",
|
||
"local_port": 31296,
|
||
"remote_addr": "127.0.0.1",
|
||
"remote_port": 31300,
|
||
"disable_http_check":true,
|
||
"log_level":3,
|
||
"log_file":"/etc/v2ray-agent/trojan/trojan.log",
|
||
"password": [
|
||
"${uuid}"
|
||
],
|
||
"dns":[
|
||
"localhost"
|
||
],
|
||
"transport_plugin":{
|
||
"enabled":true,
|
||
"type":"plaintext"
|
||
},
|
||
"websocket": {
|
||
"enabled": true,
|
||
"path": "/${customPath}tws",
|
||
"host": "${domain}",
|
||
"add":"${add}"
|
||
},
|
||
"router": {
|
||
"enabled": false
|
||
}
|
||
}
|
||
EOF
|
||
}
|
||
|
||
# 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://github.com/mack-a/v2ray-agent/blob/master/documents/optimize_V2Ray.md"
|
||
echoContent red "\nIf you don't know about Cloudflare optimization, please don't use"
|
||
echoContent yellow "\n 1.Mobile: 104.16.123.96"
|
||
echoContent yellow " 2.Unicom: www.cloudflare.com"
|
||
echoContent yellow " 3.Telecom: www.digitalocean.com"
|
||
echoContent skyBlue "----------------------------"
|
||
read -r -p "Please select [Enter not used]:" selectCloudflareType
|
||
case ${selectCloudflareType} in
|
||
1)
|
||
add="104.16.123.96"
|
||
;;
|
||
2)
|
||
add="www.cloudflare.com"
|
||
;;
|
||
3)
|
||
add="www.digitalocean.com"
|
||
;;
|
||
*)
|
||
add="${domain}"
|
||
echoContent yellow "\n ---> not used"
|
||
;;
|
||
esac
|
||
}
|
||
# generic
|
||
defaultBase64Code() {
|
||
local type=$1
|
||
local email=$2
|
||
local id=$3
|
||
|
||
port=${currentDefaultPort}
|
||
|
||
local subAccount
|
||
subAccount=$(echo "${email}" | awk -F "[_]" '{print $1}')_$(echo "${id}_currentHost" | md5sum | awk '{print $1}')
|
||
if [[ "${type}" == "vlesstcp" ]]; then
|
||
|
||
if [[ "${coreInstallType}" == "1" ]] && echo "${currentInstallProtocolType}" | grep -q 0; then
|
||
echoContent yellow " ---> General format (VLESS+TCP+TLS/xtls-rprx-direct)"
|
||
echoContent green " vless://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-direct#${email}\n"
|
||
|
||
echoContent yellow " ---> formatted plaintext (VLESS+TCP+TLS/xtls-rprx-direct)"
|
||
echoContent green "Protocol type: VLESS, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: xtls, transmission method: tcp, flow: xtls-rprx-direct, account name: ${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
vless://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-direct#${email}
|
||
EOF
|
||
echoContent yellow " ---> QR code VLESS(VLESS+TCP+TLS/xtls-rprx-direct)"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%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-direct%23${email}\n"
|
||
|
||
echoContent skyBlue "----------------------------------------------------------------------------------"
|
||
|
||
echoContent yellow " ---> General format (VLESS+TCP+TLS/xtls-rprx-splice)"
|
||
echoContent green " vless://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-splice#${email/direct/splice}\n"
|
||
|
||
echoContent yellow " ---> formatted plaintext (VLESS+TCP+TLS/xtls-rprx-splice)"
|
||
echoContent green " Protocol type: VLESS, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: xtls, transmission method: tcp, flow: xtls-rprx-splice, account name: ${email/direct/splice}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
vless://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-splice#${email/direct/splice}
|
||
EOF
|
||
echoContent yellow " ---> QR code VLESS(VLESS+TCP+TLS/xtls-rprx-splice)"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%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-splice%23${email/direct/splice}\n"
|
||
|
||
elif [[ "${coreInstallType}" == 2 || "${coreInstallType}" == "3" ]]; then
|
||
echoContent yellow " ---> General format (VLESS+TCP+TLS)"
|
||
echoContent green " vless://${id}@${currentHost}:${currentDefaultPort}?security=tls&encryption=none&host=${currentHost}&headerType=none&type=tcp#${email}\n"
|
||
|
||
echoContent yellow " ---> formatted plaintext (VLESS+TCP+TLS/xtls-rprx-splice)"
|
||
echoContent green " Protocol type: VLESS, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, transmission method: tcp, account name: ${email/direct/splice} \n"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
vless://${id}@${currentHost}:${currentDefaultPort}?security=tls&encryption=none&host=${currentHost}&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%26host%3d${currentHost}%26headerType%3dnone%26type%3dtcp%23${email}\n"
|
||
fi
|
||
|
||
elif [[ "${type}" == "trojanTCPXTLS" ]]; then
|
||
echoContent yellow " ---> General format (Trojan+TCP+TLS/xtls-rprx-direct)"
|
||
echoContent green " trojan://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-direct#${email}\n"
|
||
|
||
echoContent yellow " ---> formatted plaintext (Trojan+TCP+TLS/xtls-rprx-direct)"
|
||
echoContent green "Protocol type: Trojan, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: xtls, transmission method: tcp, flow: xtls-rprx-direct, account name: ${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
trojan://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-direct#${email}
|
||
EOF
|
||
echoContent yellow " ---> QR code Trojan(Trojan+TCP+TLS/xtls-rprx-direct)"
|
||
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-direct%23${email}\n"
|
||
|
||
echoContent skyBlue "----------------------------------------------------------------------------------"
|
||
|
||
echoContent yellow " ---> Common format (Trojan+TCP+TLS/xtls-rprx-splice)"
|
||
echoContent green " trojan://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-splice#${email/direct/splice}\n"
|
||
|
||
echoContent yellow " ---> formatted plaintext (Trojan+TCP+TLS/xtls-rprx-splice)"
|
||
echoContent green " Protocol type: VLESS, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: xtls, transmission method: tcp, flow: xtls-rprx-splice, account name: ${email/direct/splice}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
trojan://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-splice#${email/direct/splice}
|
||
EOF
|
||
echoContent yellow " ---> QR code Trojan(Trojan+TCP+TLS/xtls-rprx-splice)"
|
||
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-splice%23${email/direct/splice}\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\":\"${currentAdd}\",\"allowInsecure\":0,\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}" | base64 -w 0)
|
||
qrCodeBase64Default="${qrCodeBase64Default// /}"
|
||
|
||
echoContent yellow " ---> 通用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\":\"${currentAdd}\",\"allowInsecure\":0,\"method\":\"none\",\"peer\":\"${currentHost}\",\"sni\":\"${currentHost}\"}\n"
|
||
echoContent yellow "---> Generic vmess(VMess+WS+TLS) link"
|
||
echoContent green " vmess://${qrCodeBase64Default}\n"
|
||
echoContent yellow " ---> QR code vmess(VMess+WS+TLS)"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
vmess://${qrCodeBase64Default}
|
||
EOF
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\n"
|
||
|
||
# elif [[ "${type}" == "vmesstcp" ]]; then
|
||
#
|
||
# echoContent red "path:${path}"
|
||
# qrCodeBase64Default=$(echo -n "{\"add\":\"${add}\",\"aid\":0,\"host\":\"${host}\",\"id\":\"${id}\",\"net\":\"tcp\",\"path\":\"${path}\",\"port\":${port},\"ps\":\"${email}\",\"scy\":\"none\",\"sni\":\"${host}\",\"tls\":\"tls\",\"v\":2,\"type\":\"http\",\"allowInsecure\":0,\"peer\":\"${host}\",\"obfs\":\"http\",\"obfsParam\":\"${host}\"}" | base64)
|
||
# qrCodeBase64Default="${qrCodeBase64Default// /}"
|
||
#
|
||
# echoContent yellow " ---> 通用json(VMess+TCP+TLS)"
|
||
# echoContent green " {\"port\":'${port}',\"ps\":\"${email}\",\"tls\":\"tls\",\"id\":\"${id}\",\"aid\":0,\"v\":2,\"host\":\"${host}\",\"type\":\"http\",\"path\":\"${path}\",\"net\":\"http\",\"add\":\"${add}\",\"allowInsecure\":0,\"method\":\"post\",\"peer\":\"${host}\",\"obfs\":\"http\",\"obfsParam\":\"${host}\"}\n"
|
||
# echoContent yellow " ---> Generic vmess(VMess+TCP+TLS) link"
|
||
# echoContent green " vmess://${qrCodeBase64Default}\n"
|
||
#
|
||
# cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
#vmess://${qrCodeBase64Default}
|
||
#EOF
|
||
# echoContent yellow " ---> QR code vmess(VMess+TCP+TLS)"
|
||
# echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\n"
|
||
|
||
elif [[ "${type}" == "vlessws" ]]; then
|
||
|
||
echoContent yellow " ---> General format (VLESS+WS+TLS)"
|
||
echoContent green " vless://${id}@${currentAdd}:${currentDefaultPort}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&path=/${currentPath}ws#${email}\n"
|
||
|
||
echoContent yellow " ---> formatted plaintext (VLESS+WS+TLS)"
|
||
echoContent green " Protocol type: VLESS, address: ${currentAdd}, fake domain name/SNI: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, transmission method: ws, path :/${currentPath}ws, account name: ${email}\n"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
vless://${id}@${currentAdd}:${currentDefaultPort}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&path=/${currentPath}ws#${email}
|
||
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${currentAdd}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dws%26host%3D${currentHost}%26sni%3D${currentHost}%26path%3D%252f${currentPath}ws%23${email}"
|
||
|
||
elif [[ "${type}" == "vlessgrpc" ]]; then
|
||
|
||
echoContent yellow " ---> General format (VLESS+gRPC+TLS)"
|
||
echoContent green " vless://${id}@${currentAdd}:${currentDefaultPort}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&serviceName=${currentPath}grpc&alpn=h2&sni=${currentHost}#${email}\n"
|
||
|
||
echoContent yellow " ---> formatted plaintext (VLESS+gRPC+TLS)"
|
||
echoContent green " Protocol type: VLESS, address: ${currentAdd}, fake domain name/SNI: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, transmission method: gRPC, alpn :h2, serviceName: ${currentPath}grpc, account name: ${email}\n"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
vless://${id}@${currentAdd}:${currentDefaultPort}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&serviceName=${currentPath}grpc&alpn=h2&sni=${currentHost}#${email}
|
||
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${currentAdd}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dgrpc%26host%3D${currentHost}%26serviceName%3D${currentPath}grpc%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}&sni=${currentHost}&alpn=http/1.1#${currentHost}_Trojan\n"
|
||
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
trojan://${id}@${currentHost}:${currentDefaultPort}?peer=${currentHost}&sni=${currentHost}&alpn=http/1.1#${email}_Trojan
|
||
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}%26sni%3d${currentHost}%26alpn%3Dhttp/1.1%23${email}\n"
|
||
|
||
elif [[ "${type}" == "trojangrpc" ]]; then
|
||
# URLEncode
|
||
|
||
echoContent yellow " ---> Trojan gRPC(TLS)"
|
||
echoContent green " trojan://${id}@${currentAdd}:${currentDefaultPort}?encryption=none&peer=${currentHost}&security=tls&type=grpc&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
trojan://${id}@${currentAdd}:${currentDefaultPort}?encryption=none&peer=${currentHost}&security=tls&type=grpc&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}
|
||
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${currentAdd}%3a${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dtls%26peer%3d${currentHost}%26type%3Dgrpc%26sni%3d${currentHost}%26path%3D${currentPath}trojangrpc%26alpn%3Dh2%26serviceName%3D${currentPath}trojangrpc%23${email}\n"
|
||
|
||
elif [[ "${type}" == "hysteria" ]]; then
|
||
echoContent yellow " ---> Hysteria(TLS)"
|
||
echoContent green " hysteria://${currentHost}:${hysteriaPort}?protocol=${hysteriaProtocol}&auth=${id}&peer=${currentHost}&insecure=0&alpn=h3&upmbps=${hysteriaClientUploadSpeed}&downmbps=${hysteriaClientDownloadSpeed}#${email}\n"
|
||
cat <<EOF >>"/etc/v2ray-agent/subscribe_tmp/${subAccount}"
|
||
hysteria://${currentHost}:${hysteriaPort}?protocol=${hysteriaProtocol}&auth=${id}&peer=${currentHost}&insecure=0&alpn=h3&upmbps=${hysteriaClientUploadSpeed}&downmbps=${hysteriaClientDownloadSpeed}#${email}
|
||
EOF
|
||
echoContent yellow " ---> QR code Hysteria(TLS)"
|
||
echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=hysteria%3A%2F%2F${currentHost}%3A${hysteriaPort}%3Fprotocol%3D${hysteriaProtocol}%26auth%3D${id}%26peer%3D${currentHost}%26insecure%3D0%26alpn%3Dh3%26upmbps%3D${hysteriaClientUploadSpeed}%26downmbps%3D${hysteriaClientDownloadSpeed}%23${email}\n"
|
||
fi
|
||
|
||
}
|
||
|
||
# account
|
||
showAccounts() {
|
||
readInstallType
|
||
readInstallProtocolType
|
||
readConfigHostPathUUID
|
||
readHysteriaConfig
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : Account"
|
||
local show
|
||
# VLESS TCP
|
||
if [[ -n "${configPath}" ]]; then
|
||
show=1
|
||
if echo "${currentInstallProtocolType}" | grep -q trojan; then
|
||
echoContent skyBlue "===================== Trojan TCP TLS/XTLS-direct/XTLS-splice ======================\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
|
||
|
||
else
|
||
echoContent skyBlue "===================== VLESS TCP TLS/XTLS-direct/XTLS-splice ======================\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"
|
||
# if [[ ${coreInstallType} == "1" ]]; then
|
||
# echoContent yellow "Xray's 0-RTT path will be behind it.It is not compatible with v2ray-based clients.Please delete it manually and use it\n"
|
||
# path="${currentPath}ws"
|
||
# fi
|
||
defaultBase64Code vlessws "${email}" "$(echo "${user}" | jq -r .id)"
|
||
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
|
||
defaultBase64Code vmessws "${email}" "$(echo "${user}" | jq -r .id)"
|
||
done
|
||
fi
|
||
|
||
# VLESS grpc
|
||
if echo ${currentInstallProtocolType} | grep -q 5; then
|
||
echoContent skyBlue "\n=============================== VLESS gRPC TLS CDN ===============================\n"
|
||
echoContent red "\n ---> gRPC is in the testing stage and may not be compatible with the client you are using.If it cannot be used, please ignore it"
|
||
# local serviceName
|
||
# serviceName=$(jq -r .inbounds[0].streamSettings.grpcSettings.serviceName ${configPath}06_VLESS_gRPC_inbounds.json)
|
||
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
|
||
defaultBase64Code vlessgrpc "${email}" "$(echo "${user}" | jq -r .id)"
|
||
done
|
||
fi
|
||
fi
|
||
|
||
# trojan tcp
|
||
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"
|
||
echoContent red "\n ---> gRPC is in the testing stage and may not be compatible with the client you are using.If it cannot be used, please ignore it"
|
||
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
|
||
defaultBase64Code trojangrpc "${email}" "$(echo "${user}" | jq -r .password)"
|
||
done
|
||
fi
|
||
if echo ${currentInstallProtocolType} | grep -q 6; then
|
||
echoContent skyBlue "\n================================ Hysteria TLS ================================\n"
|
||
echoContent red "\n ---> The speed of Hysteria 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)
|
||
|
||
if [[ -n ${defaultUser} ]]; then
|
||
echoContent skyBlue "\n ---> Account:${email}"
|
||
echo
|
||
defaultBase64Code hysteria "${email}" "${user}"
|
||
fi
|
||
|
||
done
|
||
|
||
fi
|
||
|
||
if [[ -z ${show} ]]; then
|
||
echoContent red "---> not installed"
|
||
fi
|
||
}
|
||
# Remove nginx302 configuration
|
||
removeNginx302() {
|
||
local count=0
|
||
grep -n "return 302" <"/etc/nginx/conf.d/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" /etc/nginx/conf.d/alone.conf
|
||
count=$((count - 1))
|
||
fi
|
||
done
|
||
}
|
||
|
||
# Check if 302 is successful
|
||
checkNginx302() {
|
||
local domain302Status=
|
||
domain302Status=$(curl -s "https://${currentHost}")
|
||
if echo "${domain302Status}" | grep -q "302"; then
|
||
local domain302Result=
|
||
domain302Result=$(curl -L -s "https://${currentHost}")
|
||
if [[ -n "${domain302Result}" ]]; then
|
||
echoContent green "---> 302 redirection set successfully"
|
||
exit 0
|
||
fi
|
||
fi
|
||
echoContent red "---> 302 redirection setting failed, please double check if it is the same as the example"
|
||
backupNginxConfig restoreBackup
|
||
}
|
||
|
||
# Backup and restore nginx files
|
||
backupNginxConfig() {
|
||
if [[ "$1" == "backup" ]]; then
|
||
cp /etc/nginx/conf.d/alone.conf /etc/v2ray-agent/alone_backup.conf
|
||
echoContent green " ---> nginx configuration file backup successfully"
|
||
fi
|
||
|
||
if [[ "$1" == "restoreBackup" ]] && [[ -f "/etc/v2ray-agent/alone_backup.conf" ]]; then
|
||
cp /etc/v2ray-agent/alone_backup.conf /etc/nginx/conf.d/alone.conf
|
||
echoContent green " ---> nginx configuration file restore and backup successfully"
|
||
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" <"/etc/nginx/conf.d/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';" /etc/nginx/conf.d/alone.conf >/etc/nginx/conf.d/tmpfile && mv /etc/nginx/conf.d/tmpfile /etc/nginx/conf.d/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 fake site"
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "# For customization, please manually copy the template file to /usr/share/nginx/html \n"
|
||
echoContent yellow "1.Novice guide"
|
||
echoContent yellow "2.Game website"
|
||
echoContent yellow "3.Personal blog 01"
|
||
echoContent yellow "4.Enterprise Station"
|
||
echoContent yellow "5.Unlock the 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 jump to baidu"
|
||
echoContent yellow "10.302 redirect site"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" selectInstallNginxBlogType
|
||
|
||
if [[ "${selectInstallNginxBlogType}" == "10" ]]; then
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "The priority of redirection is higher.If you change the fake site after configuring 302, the fake site under the root route will not work"
|
||
echoContent yellow "If you want to disguise the site to achieve the effect, 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, such as 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 " ---> Remove 302 redirect successfully"
|
||
exit 0
|
||
fi
|
||
fi
|
||
if [[ "${selectInstallNginxBlogType}" =~ ^[1-9]$ ]]; then
|
||
rm -rf /usr/share/nginx/*
|
||
if wget --help | grep -q show-progress; then
|
||
wget -c -q --show-progress -P /usr/share/nginx "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${selectInstallNginxBlogType}.zip" >/dev/null
|
||
else
|
||
wget -c -P /usr/share/nginx "https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${selectInstallNginxBlogType}.zip" >/dev/null
|
||
fi
|
||
|
||
unzip -o "/usr/share/nginx/html${selectInstallNginxBlogType}.zip" -d /usr/share/nginx/html >/dev/null
|
||
rm -f "/usr/share/nginx/html${selectInstallNginxBlogType}.zip*"
|
||
echoContent green " ---> Replace the fake station successfully"
|
||
else
|
||
echoContent red " ---> Selection error, please select again"
|
||
updateNginxBlog
|
||
fi
|
||
}
|
||
|
||
# add new port
|
||
addCorePort() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress} : add new port"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "Support batch add"
|
||
echoContent yellow "does not affect the use of the default port"
|
||
echoContent yellow "When viewing an account, only the account with the default port will be displayed"
|
||
echoContent yellow "Special characters are not allowed, pay attention to the comma format"
|
||
echoContent yellow "Entry example: 2053,2083,2087\n"
|
||
|
||
echoContent yellow "1.Add port"
|
||
echoContent yellow "2.Delete port"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" selectNewPortType
|
||
if [[ "${selectNewPortType}" == "1" ]]; 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=
|
||
if [[ -n "${defaultPort}" && "${port}" == "${defaultPort}" ]]; then
|
||
fileName="${configPath}02_dokodemodoor_inbounds_${port}_default.json"
|
||
else
|
||
fileName="${configPath}02_dokodemodoor_inbounds_${port}.json"
|
||
fi
|
||
|
||
# open port
|
||
allowPort "${port}"
|
||
|
||
local settingsPort=443
|
||
if [[ -n "${customPort}" ]]; then
|
||
settingsPort=${customPort}
|
||
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 " ---> Add successfully"
|
||
reloadCore
|
||
fi
|
||
elif [[ "${selectNewPortType}" == "2" ]]; then
|
||
|
||
find ${configPath} -name "*dokodemodoor*" | awk -F "[c][o][n][f][/]" '{print ""NR""":"$2}'
|
||
read -r -p "Please enter the port number to delete:" portIndex
|
||
local dokoConfig
|
||
dokoConfig=$(find ${configPath} -name "*dokodemodoor*" | awk -F "[c][o][n][f][/]" '{print ""NR""":"$2}' | grep "${portIndex}:")
|
||
if [[ -n "${dokoConfig}" ]]; then
|
||
rm "${configPath}/$(echo "${dokoConfig}" | awk -F "[:]" '{print $2}')"
|
||
reloadCore
|
||
else
|
||
echoContent yellow "\n ---> The input number is wrong, please select again"
|
||
addCorePort
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# uninstall script
|
||
unInstall() {
|
||
read -r -p "Are you sure to uninstall the installation content? [y/n]:" unInstallStatus
|
||
if [[ "${unInstallStatus}" != "y" ]]; then
|
||
echoContent green " ---> Abort uninstall"
|
||
menu
|
||
exit 0
|
||
fi
|
||
|
||
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 boot auto-start complete"
|
||
|
||
elif [[ "${coreInstallType}" == "2" ]]; then
|
||
|
||
handleV2Ray stop
|
||
rm -rf /etc/systemd/system/v2ray.service
|
||
echoContent green " ---> Delete V2Ray boot auto-start complete"
|
||
|
||
fi
|
||
|
||
if [[ -z "${hysteriaConfigPath}" ]]; then
|
||
handleHysteria stop
|
||
rm -rf /etc/systemd/system/hysteria.service
|
||
echoContent green " ---> Delete Hysteria boot auto-start complete"
|
||
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
|
||
echoContent green "---> delete acme.sh complete"
|
||
|
||
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 " ---> The backup certificate is successful, please keep it.[/tmp/v2ray-agent-tls]"
|
||
fi
|
||
fi
|
||
|
||
rm -rf /etc/v2ray-agent
|
||
rm -rf ${nginxConfigPath}alone.conf
|
||
|
||
if [[ -d "/usr/share/nginx/html" && -f "/usr/share/nginx/html/check" ]]; then
|
||
rm -rf /usr/share/nginx/html
|
||
echoContent green " ---> Delete the fake website completed"
|
||
fi
|
||
|
||
rm -rf /usr/bin/vasma
|
||
rm -rf /usr/sbin/vasma
|
||
echoContent green " ---> Uninstall shortcut completed"
|
||
echoContent green "---> Uninstall v2ray-agent script completed"
|
||
}
|
||
|
||
#updateGeoSite
|
||
|
||
# Modify V2Ray CDN node
|
||
updateV2RayCDN() {
|
||
|
||
# todo refactor this method
|
||
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 www.cloudflare.com"
|
||
echoContent yellow "3.CNAME hostmonit.com"
|
||
echoContent yellow "4.Manual input"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" selectCDNType
|
||
case ${selectCDNType} in
|
||
1)
|
||
setDomain="www.digitalocean.com"
|
||
;;
|
||
2)
|
||
setDomain="www.cloudflare.com"
|
||
;;
|
||
3)
|
||
setDomain="hostmonit.com"
|
||
;;
|
||
4)
|
||
read -r -p "Please enter the CDN IP or domain name you want to customize:" setDomain
|
||
;;
|
||
esac
|
||
|
||
if [[ -n ${setDomain} ]]; then
|
||
if [[ -n "${currentAdd}" ]]; then
|
||
sed -i "s/\"${currentAdd}\"/\"${setDomain}\"/g" "$(grep "${currentAdd}" -rl ${configPath}${frontingType}.json)"
|
||
fi
|
||
if [[ $(jq -r .inbounds[0].settings.clients[0].add ${configPath}${frontingType}.json) == "${setDomain}" ]]; then
|
||
echoContent green " ---> CDN modified successfully"
|
||
reloadCore
|
||
else
|
||
echoContent red " ---> Failed to modify CDN"
|
||
fi
|
||
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 " ---> Selection error"
|
||
fi
|
||
}
|
||
|
||
# custom uuid
|
||
customUUID() {
|
||
# read -r -p "Do you want to customize UUID? [y/n]:" customUUIDStatus
|
||
# echo
|
||
# if [[ "${customUUIDStatus}" == "y" ]]; then
|
||
read -r -p "Please enter a valid UUID, [Enter] Random UUID:" currentCustomUUID
|
||
echo
|
||
if [[ -z "${currentCustomUUID}" ]]; then
|
||
# echoContent red " ---> UUID cannot be empty"
|
||
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
|
||
# fi
|
||
}
|
||
|
||
# custom email
|
||
customUserEmail() {
|
||
# read -r -p "Do you want to customize email? [y/n]:" customEmailStatus
|
||
# echo
|
||
# if [[ "${customEmailStatus}" == "y" ]]; then
|
||
read -r -p "Please enter a valid email, [Enter] random email:" currentCustomEmail
|
||
echo
|
||
if [[ -z "${currentCustomEmail}" ]]; then
|
||
currentCustomEmail="${currentHost}_${currentCustomUUID}"
|
||
echoContent yellow "email: ${currentCustomEmail}\n"
|
||
# echoContent red " ---> email cannot be empty"
|
||
else
|
||
jq -r -c '.inbounds[0].settings.clients[].email' ${configPath}${frontingType}.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
|
||
addUser() {
|
||
|
||
echoContent yellow "After adding a new user, you need to review 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 " ---> Input error, 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}
|
||
else
|
||
email=${currentHost}_${uuid}
|
||
fi
|
||
|
||
# Compatible with v2ray-core
|
||
users="{\"id\":\"${uuid}\",\"flow\":\"xtls-rprx-direct\",\"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/}"
|
||
|
||
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//"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//\"flow\":\"xtls-rprx-direct\"\,/}"
|
||
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-direct\"\,/}"
|
||
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-direct\"\,/}"
|
||
|
||
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-direct\"\,/}"
|
||
vlessGRPCUsers="${vlessGRPCUsers//\,\"alterId\":0/}"
|
||
|
||
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-direct\"\,/}"
|
||
trojanUsers="${trojanUsers//id/password}"
|
||
trojanUsers="${trojanUsers//\,\"alterId\":0/}"
|
||
|
||
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 " ---> Add complete"
|
||
manageAccount 1
|
||
}
|
||
|
||
# remove user
|
||
removeUser() {
|
||
|
||
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 single delete is supported]:" delUserIndex
|
||
if [[ $(jq -r '.inbounds[0].settings.clients|length' ${configPath}${frontingType}.json) -lt ${delUserIndex} ]]; then
|
||
echoContent red " ---> Selection error"
|
||
else
|
||
delUserIndex=$((delUserIndex - 1))
|
||
local vlessTcpResult
|
||
vlessTcpResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}${frontingType}.json)
|
||
echo "${vlessTcpResult}" | jq .>${configPath}${frontingType}.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
|
||
|
||
reloadCore
|
||
fi
|
||
manageAccount 1
|
||
}
|
||
# Updated 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 --show-progress -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 is unsuccessful, 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] for BBR and DD scripts, the address is [https://github.com/ylx2016/Linux-NetSpeed], please be familiar with"
|
||
echoContent yellow "1.Installation script [recommended original BBR+FQ]"
|
||
echoContent yellow "2.Fallback 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} ]]; then
|
||
echoContent red " ---> No installation directory detected, please execute the script to install the content"
|
||
fi
|
||
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 open access log only when debugging\n"
|
||
|
||
if [[ "${logStatus}" == "false" ]]; then
|
||
echoContent yellow "1.Open access log"
|
||
else
|
||
echoContent yellow "1.Close the access log"
|
||
fi
|
||
|
||
echoContent yellow "2.Monitor access log"
|
||
echoContent yellow "3.Monitor error log"
|
||
echoContent yellow "4.View the certificate timing 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
|
||
cat <<EOF >${configPath}00_log.json
|
||
{
|
||
"log": {
|
||
"access":"${configPathLog}access.log",
|
||
"error": "${configPathLog}error.log",
|
||
"loglevel": "debug"
|
||
}
|
||
}
|
||
EOF
|
||
elif [[ "${logStatus}" == "true" ]]; then
|
||
cat <<EOF >${configPath}00_log.json
|
||
{
|
||
"log": {
|
||
"error": "${configPathLog}error.log",
|
||
"loglevel": "warning"
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
reloadCore
|
||
checkLog 1
|
||
;;
|
||
2)
|
||
tail -f ${configPathLog}access.log
|
||
;;
|
||
3)
|
||
tail -f ${configPathLog}error.log
|
||
;;
|
||
4)
|
||
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 "Shortcut created successfully, executable [vasma] to reopen the script"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# check ipv6, ipv4
|
||
checkIPv6() {
|
||
# pingIPv6=$(ping6 -c 1 www.google.com | sed '2{s/[^(]*(//;s/).*//;q;}' | tail -n +2)
|
||
pingIPv6=$(ping6 -c 1 www.google.com | sed -n '1p' | sed 's/.*(//g;s/).*//g')
|
||
|
||
if [[ -z "${pingIPv6}" ]]; then
|
||
echoContent red " ---> ipv6 is not supported"
|
||
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.Add domain name"
|
||
echoContent yellow "2.Uninstall IPv6 offload"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" ipv6Status
|
||
if [[ "${ipv6Status}" == "1" ]]; then
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "1.The rule only supports the predefined domain name list [https://github.com/v2fly/domain-list-community]"
|
||
echoContent yellow "2.Detailed documentation [https://www.v2fly.org/config/routing.html]"
|
||
echoContent yellow "3.If the kernel fails to start, please check the domain name and add the domain name again"
|
||
echoContent yellow "4.Special characters are not allowed, pay attention to the format of commas"
|
||
echoContent yellow "5.Every time you add it, it will be added again, and the last domain name will not be retained"
|
||
echoContent yellow "6.It is strongly recommended to block domestic websites, enter [cn] below to block"
|
||
echoContent yellow "7.Input example: google,youtube,facebook,cn\n"
|
||
read -r -p "Please enter the domain name according to the above example:" domainList
|
||
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
|
||
unInstallRouting IPv6-out outboundTag
|
||
|
||
routing=$(jq -r ".routing.rules += [{\"type\":\"field\",\"domain\":[\"geosite:${domainList//,/\",\"geosite:}\"],\"outboundTag\":\"IPv6-out\"}]" ${configPath}09_routing.json)
|
||
|
||
echo "${routing}" | jq .>${configPath}09_routing.json
|
||
|
||
else
|
||
cat <<EOF >"${configPath}09_routing.json"
|
||
{
|
||
"routing":{
|
||
"domainStrategy": "IPOnDemand",
|
||
"rules": [
|
||
{
|
||
"type": "field",
|
||
"domain": [
|
||
"geosite:${domainList//,/\",\"geosite:}"
|
||
],
|
||
"outboundTag": "IPv6-out"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
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 " ---> Add successfully"
|
||
|
||
elif [[ "${ipv6Status}" == "2" ]]; then
|
||
|
||
unInstallRouting IPv6-out outboundTag
|
||
|
||
unInstallOutbounds IPv6-out
|
||
|
||
echoContent green "---> IPv6 offloading succeeded"
|
||
else
|
||
echoContent red " ---> Selection error"
|
||
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 successfully opened"
|
||
else
|
||
echoContent red " ---> Selection error"
|
||
exit 0
|
||
fi
|
||
|
||
reloadCore
|
||
}
|
||
|
||
# Domain 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.Add domain name"
|
||
echoContent yellow "2.Delete blacklist"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" blacklistStatus
|
||
if [[ "${blacklistStatus}" == "1" ]]; then
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "1.The rule only supports the predefined domain name list [https://github.com/v2fly/domain-list-community]"
|
||
echoContent yellow "2.Detailed documentation [https://www.v2fly.org/config/routing.html]"
|
||
echoContent yellow "3.If the kernel fails to start, please check the domain name and add the domain name again"
|
||
echoContent yellow "4.Special characters are not allowed, pay attention to the format of commas"
|
||
echoContent yellow "5.Every time you add it, it will be added again, and the last domain name will not be retained"
|
||
echoContent yellow "6.Input example: speedtest,facebook\n"
|
||
read -r -p "Please enter the domain name according to the above example:" domainList
|
||
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
unInstallRouting blackhole-out outboundTag
|
||
|
||
routing=$(jq -r ".routing.rules += [{\"type\":\"field\",\"domain\":[\"geosite:${domainList//,/\",\"geosite:}\"],\"outboundTag\":\"blackhole-out\"}]" ${configPath}09_routing.json)
|
||
|
||
echo "${routing}" | jq .>${configPath}09_routing.json
|
||
|
||
else
|
||
cat <<EOF >${configPath}09_routing.json
|
||
{
|
||
"routing":{
|
||
"domainStrategy": "IPOnDemand",
|
||
"rules": [
|
||
{
|
||
"type": "field",
|
||
"domain": [
|
||
"geosite:${domainList//,/\",\"geosite:}"
|
||
],
|
||
"outboundTag": "blackhole-out"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
echoContent green " ---> Add successfully"
|
||
|
||
elif [[ "${blacklistStatus}" == "2" ]]; then
|
||
|
||
unInstallRouting blackhole-out outboundTag
|
||
|
||
echoContent green " ---> Domain name blacklist deleted successfully"
|
||
else
|
||
echoContent red " ---> Selection error"
|
||
exit 0
|
||
fi
|
||
reloadCore
|
||
}
|
||
|
||
# Uninstall Routing according to 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
|
||
partStatus=1
|
||
elif [[ "${type}" == "inboundTag" ]] && echo "${line}" | jq .inboundTag | grep -q "${tag}"; then
|
||
partStatus=1
|
||
fi
|
||
|
||
if [[ -n ${protocol} ]] && echo "${line}" | jq .protocol | grep -q "${protocol}"; then
|
||
partStatus=1
|
||
elif [[ -z ${protocol} ]] && [[ $(echo "${line}" | jq .protocol) != "null" ]]; then
|
||
partStatus=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 according to 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
|
||
sniffing=$(jq -r 'del(.inbounds[0].sniffing)' "${configPath}${inbound}")
|
||
echo "${sniffing}" | jq .>"${configPath}${inbound}"
|
||
done
|
||
}
|
||
|
||
# install sniff
|
||
installSniffing() {
|
||
|
||
find ${configPath} -name "*inbounds.json*" | awk -F "[c][o][n][f][/]" '{print $2}' | while read -r inbound; do
|
||
sniffing=$(jq -r '.inbounds[0].sniffing = {"enabled":true,"destOverride":["http","tls"]}' "${configPath}${inbound}")
|
||
echo "${sniffing}" | jq .>"${configPath}${inbound}"
|
||
done
|
||
}
|
||
|
||
# warp triage
|
||
warpRouting() {
|
||
echoContent skyBlue "\nProgress $1/${totalProgress} : WARP diversion"
|
||
echoContent red "=============================================================="
|
||
# echoContent yellow "# Notes\n"
|
||
# echoContent yellow "1.There are bugs in the official warp after several rounds of testing.Restarting the warp will cause the warp to fail and fail to start, and the CPU usage may also skyrocket"
|
||
# echoContent yellow "2.The machine can be used normally without restarting the machine.If you have to use the official warp, it is recommended not to restart the machine"
|
||
# echoContent yellow "3.Some machines still work normally after restarting"
|
||
# echoContent yellow "4.Can't be used after restart, you can also uninstall and reinstall"
|
||
# install warp
|
||
if [[ -z $(which warp-cli) ]]; then
|
||
echo
|
||
read -r -p "WARP is not installed, is it installed? [y/n]:" installCloudflareWarpStatus
|
||
if [[ "${installCloudflareWarpStatus}" == "y" ]]; then
|
||
installWarp
|
||
else
|
||
echoContent yellow " ---> Abort installation"
|
||
exit 0
|
||
fi
|
||
fi
|
||
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "1.Add domain name"
|
||
echoContent yellow "2.Uninstall WARP offload"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please select:" warpStatus
|
||
if [[ "${warpStatus}" == "1" ]]; then
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "1.The rule only supports the predefined domain name list [https://github.com/v2fly/domain-list-community]"
|
||
echoContent yellow "2.Detailed documentation [https://www.v2fly.org/config/routing.html]"
|
||
echoContent yellow "3.Only traffic can be distributed to warp, not ipv4 or ipv6"
|
||
echoContent yellow "4.If the kernel fails to start, please check the domain name and add the domain name again"
|
||
echoContent yellow "5.Special characters are not allowed, pay attention to the format of comma"
|
||
echoContent yellow "6.Every time you add it, it will be added again, and the last domain name will not be retained"
|
||
echoContent yellow "7.Input example: google,youtube,facebook\n"
|
||
read -r -p "Please enter the domain name according to the above example:" domainList
|
||
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
unInstallRouting warp-socks-out outboundTag
|
||
|
||
routing=$(jq -r ".routing.rules += [{\"type\":\"field\",\"domain\":[\"geosite:${domainList//,/\",\"geosite:}\"],\"outboundTag\":\"warp-socks-out\"}]" ${configPath}09_routing.json)
|
||
|
||
echo "${routing}" | jq .>${configPath}09_routing.json
|
||
|
||
else
|
||
cat <<EOF >${configPath}09_routing.json
|
||
{
|
||
"routing":{
|
||
"domainStrategy": "IPOnDemand",
|
||
"rules": [
|
||
{
|
||
"type": "field",
|
||
"domain": [
|
||
"geosite:${domainList//,/\",\"geosite:}"
|
||
],
|
||
"outboundTag": "warp-socks-out"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
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 " ---> Add successfully"
|
||
|
||
elif [[ "${warpStatus}" == "2" ]]; then
|
||
|
||
${removeType} cloudflare-warp >/dev/null 2>&1
|
||
|
||
unInstallRouting warp-socks-out outboundTag
|
||
|
||
unInstallOutbounds warp-socks-out
|
||
|
||
echoContent green " ---> WARP offloading uninstalled successfully"
|
||
else
|
||
echoContent red " ---> Selection error"
|
||
exit 0
|
||
fi
|
||
reloadCore
|
||
}
|
||
# Streaming Toolbox
|
||
streamingToolbox() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress} : Streaming Toolbox"
|
||
echoContent red "\n=============================================================="
|
||
# echoContent yellow "1.Netflix detection"
|
||
echoContent yellow "1.Any door landing machine unlocks streaming media"
|
||
echoContent yellow "2.DNS unlock streaming"
|
||
echoContent yellow "3.VMess+WS+TLS unlock streaming"
|
||
read -r -p "Please select:" selectType
|
||
|
||
case ${selectType} in
|
||
1)
|
||
dokodemoDoorUnblockStreamingMedia
|
||
;;
|
||
2)
|
||
dnsUnlockNetflix
|
||
;;
|
||
3)
|
||
unblockVMessWSTLSStreamingMedia
|
||
;;
|
||
esac
|
||
|
||
}
|
||
|
||
# Arbitrary door unlock streaming
|
||
dokodemoDoorUnblockStreamingMedia() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress} : Unlock streaming media with any door landing machine"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "# Notes"
|
||
echoContent yellow "Any door unlock details, please check this article [https://github.com/mack-a/v2ray-agent/blob/master/documents/netflix/dokodemo-unblock_netflix.md]\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)
|
||
setDokodemoDoorUnblockStreamingMediaOutbounds
|
||
;;
|
||
2)
|
||
setDokodemoDoorUnblockStreamingMediaInbounds
|
||
;;
|
||
3)
|
||
removeDokodemoDoorUnblockStreamingMedia
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# VMess+WS+TLS to unlock streaming media [outbound only]
|
||
unblockVMessWSTLSStreamingMedia() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress} : VMess+WS+TLS outbound unblock streaming"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "# Notes"
|
||
echoContent yellow "Suitable for unlocking services via VMess provided by other service providers\n"
|
||
|
||
echoContent yellow "1.Add outbound"
|
||
echoContent yellow "2.Uninstall"
|
||
read -r -p "Please select:" selectType
|
||
|
||
case ${selectType} in
|
||
1)
|
||
setVMessWSTLSUnblockStreamingMediaOutbounds
|
||
;;
|
||
2)
|
||
removeVMessWSTLSUnblockStreamingMedia
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# Set VMess+WS+TLS to unblock Netflix [outbound only]
|
||
setVMessWSTLSUnblockStreamingMediaOutbounds() {
|
||
read -r -p "Please enter the address to unlock the streaming media VMess+WS+TLS:" setVMessWSTLSAddress
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "1.The rule only supports the predefined domain name list [https://github.com/v2fly/domain-list-community]"
|
||
echoContent yellow "2.Detailed documentation [https://www.v2fly.org/config/routing.html]"
|
||
echoContent yellow "3.If the kernel fails to start, please check the domain name and add the domain name again"
|
||
echoContent yellow "4.Special characters are not allowed, pay attention to the format of commas"
|
||
echoContent yellow "5.Every time you add it, it will be added again, and the last domain name will not be retained"
|
||
echoContent yellow "6.Input example: netflix, disney, hulu\n"
|
||
read -r -p "Please enter the domain name according to the above example:" domainList
|
||
|
||
if [[ -z ${domainList} ]]; then
|
||
echoContent red " ---> The domain name cannot be empty"
|
||
setVMessWSTLSUnblockStreamingMediaOutbounds
|
||
fi
|
||
|
||
if [[ -n "${setVMessWSTLSAddress}" ]]; then
|
||
|
||
unInstallOutbounds VMess-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 " ---> Path cannot be empty"
|
||
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
|
||
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
unInstallRouting VMess-out outboundTag
|
||
|
||
local routing
|
||
|
||
routing=$(jq -r ".routing.rules += [{\"type\":\"field\",\"domain\":[\"ip.sb\",\"geosite:${domainList//,/\",\"geosite:}\"],\"outboundTag\":\"VMess-out\"}]" ${configPath}09_routing.json)
|
||
|
||
echo "${routing}" | jq .>${configPath}09_routing.json
|
||
else
|
||
cat <<EOF >${configPath}09_routing.json
|
||
{
|
||
"routing": {
|
||
"rules": [
|
||
{
|
||
"type": "field",
|
||
"domain": [
|
||
"ip.sb",
|
||
"geosite:${domainList//,/\",\"geosite:}"
|
||
],
|
||
"outboundTag": "VMess-out"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
reloadCore
|
||
echoContent green " ---> Add outbound unlock success"
|
||
exit 0
|
||
fi
|
||
echoContent red " ---> The address cannot be empty"
|
||
setVMessWSTLSUnblockStreamingMediaOutbounds
|
||
}
|
||
|
||
# Set any door to unlock Netflix [outbound]
|
||
setDokodemoDoorUnblockStreamingMediaOutbounds() {
|
||
read -r -p "Please enter the IP to unlock the streaming vps:" setIP
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "1.The rule only supports the predefined domain name list [https://github.com/v2fly/domain-list-community]"
|
||
echoContent yellow "2.Detailed documentation [https://www.v2fly.org/config/routing.html]"
|
||
echoContent yellow "3.If the kernel fails to start, please check the domain name and add the domain name again"
|
||
echoContent yellow "4.Special characters are not allowed, pay attention to the format of commas"
|
||
echoContent yellow "5.Every time you add it, it will be added again, and the last domain name will not be retained"
|
||
echoContent yellow "6.Input example: netflix, disney, hulu\n"
|
||
read -r -p "Please enter the domain name according to the above example:" domainList
|
||
|
||
if [[ -z ${domainList} ]]; then
|
||
echoContent red " ---> The domain name cannot be empty"
|
||
setDokodemoDoorUnblockStreamingMediaOutbounds
|
||
fi
|
||
|
||
if [[ -n "${setIP}" ]]; then
|
||
|
||
unInstallOutbounds streamingMedia-80
|
||
unInstallOutbounds streamingMedia-443
|
||
|
||
outbounds=$(jq -r ".outbounds += [{\"tag\":\"streamingMedia-80\",\"protocol\":\"freedom\",\"settings\":{\"domainStrategy\":\"AsIs\",\"redirect\":\"${setIP}:22387\"}},{\"tag\":\"streamingMedia-443\",\"protocol\":\"freedom\",\"settings\":{\"domainStrategy\":\"AsIs\",\"redirect\":\"${setIP}:22388\"}}]" ${configPath}10_ipv4_outbounds.json)
|
||
|
||
echo "${outbounds}" | jq .>${configPath}10_ipv4_outbounds.json
|
||
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
unInstallRouting streamingMedia-80 outboundTag
|
||
unInstallRouting streamingMedia-443 outboundTag
|
||
|
||
local routing
|
||
|
||
routing=$(jq -r ".routing.rules += [{\"type\":\"field\",\"port\":80,\"domain\":[\"ip.sb\",\"geosite:${domainList//,/\",\"geosite:}\"],\"outboundTag\":\"streamingMedia-80\"},{\"type\":\"field\",\"port\":443,\"domain\":[\"ip.sb\",\"geosite:${domainList//,/\",\"geosite:}\"],\"outboundTag\":\"streamingMedia-443\"}]" ${configPath}09_routing.json)
|
||
|
||
echo "${routing}" | jq .>${configPath}09_routing.json
|
||
else
|
||
cat <<EOF >${configPath}09_routing.json
|
||
{
|
||
"routing": {
|
||
"domainStrategy": "AsIs",
|
||
"rules": [
|
||
{
|
||
"type": "field",
|
||
"port": 80,
|
||
"domain": [
|
||
"ip.sb",
|
||
"geosite:${domainList//,/\",\"geosite:}"
|
||
],
|
||
"outboundTag": "streamingMedia-80"
|
||
},
|
||
{
|
||
"type": "field",
|
||
"port": 443,
|
||
"domain": [
|
||
"ip.sb",
|
||
"geosite:${domainList//,/\",\"geosite:}"
|
||
],
|
||
"outboundTag": "streamingMedia-443"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
reloadCore
|
||
echoContent green " ---> Add outbound unlock success"
|
||
exit 0
|
||
fi
|
||
echoContent red " ---> ip cannot be empty"
|
||
}
|
||
|
||
# Set any door to unlock Netflix [inbound]
|
||
setDokodemoDoorUnblockStreamingMediaInbounds() {
|
||
|
||
echoContent skyBlue "\nFunction 1/${totalProgress} : add inbound to any door"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "1.The rule only supports the predefined domain name list [https://github.com/v2fly/domain-list-community]"
|
||
echoContent yellow "2.Detailed documentation [https://www.v2fly.org/config/routing.html]"
|
||
echoContent yellow "3.If the kernel fails to start, please check the domain name and add the domain name again"
|
||
echoContent yellow "4.Special characters are not allowed, pay attention to the format of commas"
|
||
echoContent yellow "5.Every time you add it, it will be added again, and the last domain name will not be retained"
|
||
echoContent yellow "6.ip input example: 1.1.1.1,1.1.1.2"
|
||
echoContent yellow "7.The domain name below must be the same as the outbound vps"
|
||
# echoContent yellow "8.If there is a firewall, please manually open ports 22387 and 22388"
|
||
echoContent yellow "8.Example of domain name entry: netflix, disney, hulu\n"
|
||
read -r -p "Please enter the IP that is allowed to access the unlocked 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_netflix_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": "streamingMedia-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": "streamingMedia-443"
|
||
}
|
||
]
|
||
}
|
||
EOF
|
||
|
||
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
|
||
|
||
if [[ -f "${configPath}09_routing.json" ]]; then
|
||
unInstallRouting streamingMedia-80 inboundTag
|
||
unInstallRouting streamingMedia-443 inboundTag
|
||
|
||
local routing
|
||
routing=$(jq -r ".routing.rules += [{\"source\":[\"${setIPs//,/\",\"}\"],\"type\":\"field\",\"inboundTag\":[\"streamingMedia-80\",\"streamingMedia-443\"],\"outboundTag\":\"direct\"},{\"domains\":[\"geosite:${domainList//,/\",\"geosite:}\"],\"type\":\"field\",\"inboundTag\":[\"streamingMedia-80\",\"streamingMedia-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//,/\",\"}"
|
||
],
|
||
"type": "field",
|
||
"inboundTag": [
|
||
"streamingMedia-80",
|
||
"streamingMedia-443"
|
||
],
|
||
"outboundTag": "direct"
|
||
},
|
||
{
|
||
"domains": [
|
||
"geosite:${domainList//,/\",\"geosite:}"
|
||
],
|
||
"type": "field",
|
||
"inboundTag": [
|
||
"streamingMedia-80",
|
||
"streamingMedia-443"
|
||
],
|
||
"outboundTag": "blackhole-out"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
EOF
|
||
|
||
fi
|
||
|
||
reloadCore
|
||
echoContent green " ---> Add landing machine inbound unlock successfully"
|
||
exit 0
|
||
fi
|
||
echoContent red " ---> ip cannot be empty"
|
||
}
|
||
|
||
# Remove any door to unlock Netflix
|
||
removeDokodemoDoorUnblockStreamingMedia() {
|
||
|
||
unInstallOutbounds streamingMedia-80
|
||
unInstallOutbounds streamingMedia-443
|
||
|
||
unInstallRouting streamingMedia-80 inboundTag
|
||
unInstallRouting streamingMedia-443 inboundTag
|
||
|
||
unInstallRouting streamingMedia-80 outboundTag
|
||
unInstallRouting streamingMedia-443 outboundTag
|
||
|
||
rm -rf ${configPath}01_netflix_inbounds.json
|
||
|
||
reloadCore
|
||
echoContent green " ---> Uninstall successful"
|
||
}
|
||
|
||
# Remove VMess+WS+TLS to unlock streaming
|
||
removeVMessWSTLSUnblockStreamingMedia() {
|
||
|
||
unInstallOutbounds VMess-out
|
||
|
||
unInstallRouting VMess-out outboundTag
|
||
|
||
reloadCore
|
||
echoContent green " ---> Uninstall successful"
|
||
}
|
||
|
||
# restart the core
|
||
reloadCore() {
|
||
if [[ "${coreInstallType}" == "1" ]]; then
|
||
handleXray stop
|
||
handleXray start
|
||
elif [[ "${coreInstallType}" == "2" || "${coreInstallType}" == "3" ]]; then
|
||
handleV2Ray stop
|
||
handleV2Ray start
|
||
fi
|
||
|
||
if [[ -n "${hysteriaConfigPath}" ]]; then
|
||
handleHysteria stop
|
||
handleHysteria start
|
||
fi
|
||
}
|
||
|
||
# dns unblock Netflix
|
||
dnsUnlockNetflix() {
|
||
if [[ -z "${configPath}" ]]; then
|
||
echoContent red " ---> Not installed, please use script to install"
|
||
menu
|
||
exit 0
|
||
fi
|
||
echoContent skyBlue "\nFunction 1/${totalProgress} : DNS unblock streaming"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "1.Add"
|
||
echoContent yellow "2.Uninstall"
|
||
read -r -p "Please select:" selectType
|
||
|
||
case ${selectType} in
|
||
1)
|
||
setUnlockDNS
|
||
;;
|
||
2)
|
||
removeUnlockDNS
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# set dns
|
||
setUnlockDNS() {
|
||
read -r -p "Please enter Unblock Streaming DNS:" setDNS
|
||
if [[ -n ${setDNS} ]]; then
|
||
echoContent red "=============================================================="
|
||
echoContent yellow "# Notes\n"
|
||
echoContent yellow "1.The rule only supports the predefined domain name list [https://github.com/v2fly/domain-list-community]"
|
||
echoContent yellow "2.Detailed documentation [https://www.v2fly.org/config/routing.html]"
|
||
echoContent yellow "3.If the kernel fails to start, please check the domain name and add the domain name again"
|
||
echoContent yellow "4.Special characters are not allowed, pay attention to the format of commas"
|
||
echoContent yellow "5.Every time you add it, it will be added again, and the last domain name will not be retained"
|
||
echoContent yellow "6.Input example: netflix, disney, hulu"
|
||
echoContent yellow "7.Please enter 1 for the default scheme, the default scheme includes the following"
|
||
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 it, you can try the following two solutions"
|
||
echoContent yellow "1.Restart vps"
|
||
echoContent yellow " 2.After uninstalling dns unlock, modify the local [/etc/resolv.conf] DNS settings and restart vps\n"
|
||
else
|
||
echoContent red " ---> dns cannot be empty"
|
||
fi
|
||
exit 0
|
||
}
|
||
|
||
# remove Netflix unblock
|
||
removeUnlockDNS() {
|
||
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 pre-installed, and 0 is installed by default.If only 0 needs to be installed, only 0 can be selected"
|
||
echoContent yellow "0.VLESS+TLS/XTLS+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"
|
||
echoContent yellow "5.VLESS+TLS+gRPC[CDN]"
|
||
read -r -p "Please select [multiple choices], [eg: 123]:" selectCustomInstallType
|
||
echoContent skyBlue "--------------------------------------------------------------"
|
||
if [[ -z ${selectCustomInstallType} ]]; then
|
||
selectCustomInstallType=0
|
||
fi
|
||
if [[ "${selectCustomInstallType}" =~ ^[0-5]+$ ]]; then
|
||
cleanUp xrayClean
|
||
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 " ---> Invalid input"
|
||
customV2RayInstall
|
||
fi
|
||
}
|
||
|
||
# Xray-core personalized installation
|
||
customXrayInstall() {
|
||
echoContent skyBlue "\n========================Personalized installation==================== =========="
|
||
echoContent yellow "VLESS is pre-installed, and 0 is installed by default.If only 0 needs to be installed, only 0 can be selected"
|
||
echoContent yellow "0.VLESS+TLS/XTLS+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"
|
||
echoContent yellow "5.VLESS+TLS+gRPC[CDN]"
|
||
read -r -p "Please select [multiple choices], [eg: 123]:" selectCustomInstallType
|
||
echoContent skyBlue "--------------------------------------------------------------"
|
||
if [[ -z ${selectCustomInstallType} ]]; then
|
||
echoContent red " ---> cannot be empty"
|
||
customXrayInstall
|
||
elif [[ "${selectCustomInstallType}" =~ ^[0-5]+$ ]]; then
|
||
cleanUp v2rayClean
|
||
totalProgress=17
|
||
installTools 1
|
||
# apply for tls
|
||
initTLSNginxConfig 2
|
||
handleXray stop
|
||
handleNginx start
|
||
checkIP
|
||
|
||
installTLS 3
|
||
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 5
|
||
customCDNIP 6
|
||
fi
|
||
nginxBlog 7
|
||
updateRedirectNginxConf
|
||
handleNginx start
|
||
|
||
# Install V2Ray
|
||
installXray 8
|
||
installXrayService 9
|
||
initXrayConfig custom 10
|
||
cleanUp v2rayDel
|
||
|
||
installCronTLS 14
|
||
handleXray stop
|
||
handleXray start
|
||
# generate account
|
||
checkGFWStatue 15
|
||
showAccounts 16
|
||
else
|
||
echoContent red " ---> Invalid input"
|
||
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=
|
||
if [[ "${selectInstallType}" == "2" ]]; then
|
||
customV2RayInstall
|
||
else
|
||
v2rayCoreInstall
|
||
fi
|
||
;;
|
||
3)
|
||
v2rayCoreVersion=v4.32.1
|
||
if [[ "${selectInstallType}" == "2" ]]; then
|
||
customV2RayInstall
|
||
else
|
||
v2rayCoreInstall
|
||
fi
|
||
;;
|
||
*)
|
||
echoContent red ' ---> selection error, re-select'
|
||
selectCoreInstall
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# v2ray-core install
|
||
v2rayCoreInstall() {
|
||
cleanUp xrayClean
|
||
selectCustomInstallType=
|
||
totalProgress=13
|
||
installTools 2
|
||
# apply for tls
|
||
initTLSNginxConfig 3
|
||
|
||
handleV2Ray stop
|
||
handleNginx start
|
||
checkIP
|
||
|
||
installTLS 4
|
||
handleNginx stop
|
||
# initNginxConfig 5
|
||
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 install
|
||
xrayCoreInstall() {
|
||
cleanUp v2rayClean
|
||
selectCustomInstallType=
|
||
totalProgress=13
|
||
installTools 2
|
||
# apply for tls
|
||
initTLSNginxConfig 3
|
||
|
||
handleXray stop
|
||
handleNginx start
|
||
checkIP
|
||
|
||
installTLS 4
|
||
handleNginx stop
|
||
randomPathFunction 5
|
||
# install Xray
|
||
# handleV2Ray stop
|
||
installXray 6
|
||
installXrayService 7
|
||
customCDNIP 8
|
||
initXrayConfig all 9
|
||
cleanUp v2rayDel
|
||
installCronTLS 10
|
||
nginxBlog 11
|
||
updateRedirectNginxConf
|
||
handleXray stop
|
||
sleep 2
|
||
handleXray start
|
||
|
||
handleNginx start
|
||
# generate account
|
||
checkGFWStatue 12
|
||
showAccounts 13
|
||
}
|
||
# Hysteria installation
|
||
hysteriaCoreInstall() {
|
||
if [[ -z "${coreInstallType}" ]]; then
|
||
echoContent red "\n ---> Due to environment dependencies, such as installing hysteria, please install Xray/V2ray first"
|
||
menu
|
||
exit 0
|
||
fi
|
||
totalProgress=5
|
||
installHysteria 1
|
||
initHysteriaConfig 2
|
||
installHysteriaService 3
|
||
handleHysteria stop
|
||
handleHysteria start
|
||
showAccounts 5
|
||
}
|
||
# uninstall hysteria
|
||
unInstallHysteriaCore() {
|
||
|
||
if [[ -z "${hysteriaConfigPath}" ]]; then
|
||
echoContent red "\n ---> Not installed"
|
||
exit 0
|
||
fi
|
||
handleHysteria stop
|
||
rm -rf /etc/v2ray-agent/hysteria/*
|
||
rm -rf /etc/systemd/system/hysteria.service
|
||
echoContent green " ---> Uninstallation completed"
|
||
}
|
||
|
||
# Core management
|
||
coreVersionManageMenu() {
|
||
|
||
if [[ -z "${coreInstallType}" ]]; then
|
||
echoContent red "\n ---> No installation directory 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
|
||
|
||
elif [[ "${coreInstallType}" == "3" ]]; then
|
||
v2rayCoreVersion=v4.32.1
|
||
v2rayVersionManageMenu 1
|
||
fi
|
||
}
|
||
# cron task check certificate
|
||
cronRenewTLS() {
|
||
if [[ "${renewTLS}" == "RenewTLS" ]]; then
|
||
renewalTLS
|
||
exit 0
|
||
fi
|
||
}
|
||
# Account management
|
||
manageAccount() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress} : Account Management"
|
||
echoContent red "\n=============================================================="
|
||
echoContent yellow "# Every time you delete or add an account, you need to re-check the subscription to generate a subscription"
|
||
echoContent yellow "# If Hysteria is installed, the account will be added to Hysteria at the same time\n"
|
||
echoContent yellow "1.View account"
|
||
echoContent yellow "2.View subscription"
|
||
echoContent yellow "3.Add user"
|
||
echoContent yellow "4.Delete user"
|
||
echoContent red "=============================================================="
|
||
read -r -p "Please enter:" manageAccountStatus
|
||
if [[ "${manageAccountStatus}" == "1" ]]; then
|
||
showAccounts 1
|
||
elif [[ "${manageAccountStatus}" == "2" ]]; then
|
||
subscribe 1
|
||
elif [[ "${manageAccountStatus}" == "3" ]]; then
|
||
addUser
|
||
elif [[ "${manageAccountStatus}" == "4" ]]; then
|
||
removeUser
|
||
else
|
||
echoContent red " ---> Selection error"
|
||
fi
|
||
}
|
||
|
||
# subscribe
|
||
subscribe() {
|
||
if [[ -n "${configPath}" ]]; then
|
||
echoContent skyBlue "-------------------------Note-------------------------"
|
||
echoContent yellow "# Subscriptions will be regenerated when viewing subscriptions"
|
||
echoContent yellow "# Every time you add or delete an account, you need to check the subscription again"
|
||
rm -rf /etc/v2ray-agent/subscribe/*
|
||
rm -rf /etc/v2ray-agent/subscribe_tmp/*
|
||
showAccounts >/dev/null
|
||
mv /etc/v2ray-agent/subscribe_tmp/* /etc/v2ray-agent/subscribe/
|
||
|
||
if [[ -n $(ls /etc/v2ray-agent/subscribe/) ]]; then
|
||
find /etc/v2ray-agent/subscribe/* | while read -r email; do
|
||
email=$(echo "${email}" | awk -F "[b][e][/]" '{print $2}')
|
||
|
||
local base64Result
|
||
base64Result=$(base64 -w 0 "/etc/v2ray-agent/subscribe/${email}")
|
||
echo "${base64Result}" >"/etc/v2ray-agent/subscribe/${email}"
|
||
echoContent skyBlue "--------------------------------------------------------------"
|
||
echoContent yellow "email:${email}\n"
|
||
local currentDomain=${currentHost}
|
||
|
||
if [[ -n "${currentDefaultPort}" && "${currentDefaultPort}" != "443" ]]; then
|
||
currentDomain="${currentHost}:${currentDefaultPort}"
|
||
fi
|
||
|
||
echoContent yellow "url:https://${currentDomain}/s/${email}\n"
|
||
echoContent yellow "Online QR code: https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=https://${currentDomain}/s/${email}\n"
|
||
echo "https://${currentDomain}/s/${email}" | qrencode -s 10 -m 1 -t UTF8
|
||
echoContent skyBlue "--------------------------------------------------------------"
|
||
done
|
||
fi
|
||
else
|
||
echoContent red "---> not installed"
|
||
fi
|
||
}
|
||
|
||
# toggle alpn
|
||
switchAlpn() {
|
||
echoContent skyBlue "\nFunction 1/${totalProgress} : toggle alpn"
|
||
if [[ -z ${currentAlpn} ]]; then
|
||
echoContent red " ---> Unable to read alpn, please check if it is installed"
|
||
exit 0
|
||
fi
|
||
|
||
echoContent red "\n=============================================================="
|
||
echoContent green "The current alpn first is: ${currentAlpn}"
|
||
echoContent yellow " 1.When http/1.1 is the first, trojan is available, and some gRPC clients are available [client supports manual selection of alpn available]"
|
||
echoContent yellow " 2.When h2 is the first, gRPC is available, and some trojan clients are available [clients support manual selection of alpn available]"
|
||
echoContent yellow " 3.If the client does not support manual replacement of alpn, it is recommended to use this function to change the order of alpn on the server to use the corresponding protocol"
|
||
echoContent red "=============================================================="
|
||
|
||
if [[ "${currentAlpn}" == "http/1.1" ]]; then
|
||
echoContent yellow "1.Switch the first position of alpn h2"
|
||
elif [[ "${currentAlpn}" == "h2" ]]; then
|
||
echoContent yellow "1.Switch alpn http/1.1 first"
|
||
else
|
||
echoContent red 'incompatible'
|
||
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.xtlsSettings.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.xtlsSettings.alpn =[\"http/1.1\",\"h2\"]" ${configPath}${frontingType}.json)
|
||
echo "${frontingTypeJSON}" | jq .>${configPath}${frontingType}.json
|
||
else
|
||
echoContent red " ---> Selection error"
|
||
exit 0
|
||
fi
|
||
reloadCore
|
||
}
|
||
|
||
#hysteria management
|
||
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.upgrade core"
|
||
echoContent yellow "4.View log"
|
||
hysteriaStatus=true
|
||
else
|
||
echoContent yellow "1.Install"
|
||
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
|
||
installHysteria 1
|
||
handleHysteria start
|
||
elif [[ "${installHysteriaStatus}" == "4" && "${hysteriaStatus}" == "true" ]]; then
|
||
journalctl -fu hysteria
|
||
fi
|
||
}
|
||
# main menu
|
||
menu() {
|
||
cd "$HOME" || exit
|
||
echoContent red "\n=============================================================="
|
||
echoContent green "author:mack-a"
|
||
echoContent green "Current version: v2.6.10"
|
||
echoContent green "Github:https://github.com/mack-a/v2ray-agent"
|
||
echoContent green "Description: 8-in-1 coexistence script\c"
|
||
showInstallStatus
|
||
echoContent red "\n=============================================================="
|
||
echoContent red "Promotion Area"
|
||
echoContent green "AFF donation: https://github.com/mack-a/v2ray-agent/blob/master/documents/donation_aff.md\n"
|
||
echoContent green "Virtual currency donation: 0xB08b731653515b083deE362fefFc45d5eb96c35d\n"
|
||
echoContent green "Contact TG for promotion: https://t.me/mackaff"
|
||
echoContent red "=============================================================="
|
||
if [[ -n "${coreInstallType}" ]]; then
|
||
echoContent yellow "1.Reinstall"
|
||
else
|
||
echoContent yellow "1.Install"
|
||
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 skyBlue "-------------------------Tool management--------------------"
|
||
echoContent yellow "5.Account Management"
|
||
echoContent yellow "6.Replace camouflage station"
|
||
echoContent yellow "7.Update certificate"
|
||
echoContent yellow "8.Replace CDN node"
|
||
echoContent yellow "9.IPv6 offload"
|
||
echoContent yellow "10.WARP shunt"
|
||
echoContent yellow "11.Streaming tools"
|
||
echoContent yellow "12.Add new port"
|
||
echoContent yellow "13.BT download management"
|
||
echoContent yellow "14.Switch alpn"
|
||
echoContent yellow "15.Domain 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)
|
||
manageAccount 1
|
||
;;
|
||
6)
|
||
updateNginxBlog 1
|
||
;;
|
||
7)
|
||
renewalTLS 1
|
||
;;
|
||
8)
|
||
updateV2RayCDN 1
|
||
;;
|
||
9)
|
||
ipv6Routing 1
|
||
;;
|
||
10)
|
||
warpRouting 1
|
||
;;
|
||
11)
|
||
streamingToolbox 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
|
||
}
|
||
cronRenewTLS
|
||
menu
|