v2Ray安装脚本
#!/bin/bash
# v2ray安装脚本
RED="\033[91m" # Error message
GREEN="\033[92m" # Success message
YELLOW="\033[93m" # Warning message
BLUE="\033[94m" # Info message
PLAIN='\033[0m'
# 反代的小说网站
SITES=(
https://www.qidian.com
https://www.jjwxc.net
https://fanqienovel.com
https://www.zongheng.com
https://read.douban.com
https://www.wattpad.com
https://www.royalroad.com
https://www.gutenberg.org
)
V2RAY_CONFIG_FILE="/etc/v2ray/config.json"
V2RAY_SERVICE_FILE="/etc/systemd/system/v2ray.service"
OS=$(hostnamectl | grep -i system | cut -d: -f2)
NGINX_CONF_PATH="/etc/nginx/conf.d/"
XTLS="false"
# 彩色输出
colorEcho() {
echo -e "${1}${@:2}${PLAIN}"
}
# v4 v6 IP
check_v4_v6(){
v6=$(curl -s6m8 api64.ipify.org -k)
v4=$(curl -s4m8 api64.ipify.org -k)
}
# 检查环境
check_env(){
# 检测IPv4/IPv6的WARP状态(on/plus表示已开启WARP)
colorEcho $YELLOW "正在检查VPS的IP配置环境, 请稍等..." && sleep 1
WgcfIPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2)
WgcfIPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2)
if [[ $WgcfIPv4Status =~ "on"|"plus" ]] || [[ $WgcfIPv6Status =~ "on"|"plus" ]]; then
# 如果检测到WARP已开启,则临时关闭WARP服务
wg-quick down wgcf >/dev/null 2>&1
systemctl stop warp-go >/dev/null 2>&1
# 获取真实IP地址
check_v4_v6
# 重新启用WARP服务
wg-quick up wgcf >/dev/null 2>&1
systemctl start warp-go >/dev/null 2>&1
else
# 没有WARP时直接获取IP
check_v4_v6
if [[ -z $v4 && -n $v6 ]]; then
# 纯IPv6环境配置DNS64服务器
colorEcho $GREEN "检测到为纯IPv6 VPS, 已自动添加DNS64解析服务器"
echo -e "nameserver 2a01:4f8:c2c:123f::1" > /etc/resolv.conf
# 使用IPv6地址
IP=$v6
# 设置IPv6状态标记
ipv6Status="on"
else
# 使用IPv4地址
IP=$v4
fi
fi
}
# 检查系统
check_system(){
if [[ $(id -u) -ne "0" ]]; then
colorEcho $RED "请以root身份执行该脚本"
exit 1
fi
# 包管理器检测
if ! res=$(which yum 2>/dev/null); then
if ! res=$(which apt 2>/dev/null); then
colorEcho $RED "不支持的Linux系统"
colorEcho $GREEN "只支持的包管理器为apt或yum的Linux系统"
exit 1
fi
# 设置APT相关命令
PMT="apt"
CMD_INSTALL="apt install -y "
CMD_REMOVE="apt remove -y "
CMD_UPGRADE="apt update -y && apt upgrade -y && apt autoremove -y"
else
# 设置YUM相关命令
PMT="yum"
CMD_INSTALL="yum install -y "
CMD_REMOVE="yum remove -y "
CMD_UPGRADE="yum update -y"
fi
# 系统服务管理器检测
if ! res=$(which systemctl 2>/dev/null); then
colorEcho $RED "系统版本过低,请升级到最新版本"
exit 1
fi
}
# 检查是否需要配置Nginx
config_need_nginx(){
# wsSettings配置是否为空
[[ -n $(grep wsSettings $V2RAY_CONFIG_FILE) ]] && echo "yes" || echo "no"
}
# 停止Nginx
stop_nginx(){
# 检查systemd服务是否存在
if systemctl list-unit-files | grep -q nginx.service; then
systemctl stop nginx
else
# 如果服务不存在但进程存在,使用nginx命令停止
if [[ -n $(ps -ef | grep -i nginx | grep -v grep) ]]; then
nginx -s stop
fi
fi
}
# 启动Nginx
start_nginx() {
# 检查systemd服务是否存在
if systemctl list-unit-files | grep -q nginx.service; then
systemctl start nginx
else
# 如果服务不存在但nginx可执行文件存在
if which nginx &> /dev/null; then
nginx
else
colorEcho $RED "Nginx未安装,请先安装!"
exit 1
fi
fi
# 检查启动是否成功
if [[ $? -ne 0 ]]; then
colorEcho $RED "Nginx启动失败,请检查配置!"
exit 1
fi
}
# v2ray状态检检测
v2ray_status(){
if [[ ! -f /usr/bin/v2ray/v2ray ]]; then
echo 0
return
fi
if [[ ! -f $V2RAY_CONFIG_FILE ]]; then
echo 1
return
fi
port=$(grep port $V2RAY_CONFIG_FILE | head -n 1| cut -d: -f2| tr -d \",' ')
res=$(ss -nutlp| grep ${port} | grep -i v2ray)
if [[ -z $res ]]; then
echo 2
return
fi
if [[ $(config_need_nginx) != "yes" ]]; then
echo 3
else
res=$(ss -nutlp | grep -i nginx)
if [[ -z $res ]]; then
echo 4
else
echo 5
fi
fi
}
# v2ray状态结果
v2ray_status_result(){
res=$(v2ray_status)
case $res in
2)
echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN}
;;
3)
echo -e ${GREEN}已安装${PLAIN} ${GREEN}V2ray正在运行${PLAIN}
;;
4)
echo -e ${GREEN}已安装${PLAIN} ${GREEN}V2ray正在运行${PLAIN}, ${RED}Nginx未运行${PLAIN}
;;
5)
echo -e ${GREEN}已安装${PLAIN} ${GREEN}V2ray正在运行, Nginx正在运行${PLAIN}
;;
*)
echo -e ${RED}未安装${PLAIN}
;;
esac
}
# v2ray启动
start(){
res=$(v2ray_status)
if [[ $res -lt 2 ]]; then
colorEcho $RED " V2ray未安装,请先安装!"
return
fi
stop_nginx
start_nginx
systemctl restart v2ray
sleep 2
port=$(grep port $V2RAY_CONFIG_FILE | head -n 1| cut -d: -f2 | tr -d \",' ')
res=$(ss -nutlp| grep ${port} | grep -i v2ray)
if [[ $res = "" ]]; then
colorEcho $RED " v2ray启动失败,请检查日志或查看端口是否被占用!"
else
colorEcho $BLUE " v2ray启动成功"
fi
}
# v2ray停止
stop(){
stop_nginx
systemctl stop v2ray
colorEcho $BLUE " V2ray停止成功"
}
# v2ray重启
restart(){
res=$(v2ray_status)
if [[ $res -lt 2 ]]; then
colorEcho $RED " V2ray未安装,请先安装!"
return
fi
stop
start
}
# v2ray更新
update(){
res=$(v2ray_status)
if [[ $res -lt 2 ]]; then
colorEcho $RED " V2ray未安装,请先安装!"
return
fi
get_version
RETVAL=$?
if [[ $RETVAL == 0 ]]; then
colorEcho $BLUE " V2ray最新版 ${CUR_VER} 已经安装"
elif [[ $RETVAL == 3 ]]; then
exit 1
else
colorEcho $BLUE " 安装V2Ray ${NEW_VER} ,架构$(archAffix)"
stop
install_v2ray
start
colorEcho $GREEN " 最新版V2ray安装成功!"
fi
}
# v2ray卸载
uninstall(){
res=$(v2ray_status)
if [[ $res -lt 2 ]]; then
colorEcho $RED " V2ray未安装,请先安装!"
return
fi
echo ""
read -p " 确定卸载V2ray?[y/n]:" answer
if [[ ${answer,,} = "y" ]]; then
domain=$(grep Host $V2RAY_CONFIG_FILE | cut -d: -f2 | tr -d \",' ')
if [[ $domain = "" ]]; then
domain=$(grep serverName $V2RAY_CONFIG_FILE | cut -d: -f2 | tr -d \",' ')``
fi
stop
systemctl disable v2ray
rm -rf $SERVICE_FILE
rm -rf /etc/v2ray
rm -rf /usr/bin/v2ray
systemctl disable nginx
$CMD_REMOVE nginx
if [[ $PMT = "apt" ]]; then
$CMD_REMOVE nginx-common
fi
rm -rf /etc/nginx/nginx.conf
if [[ -f /etc/nginx/nginx.conf.bak ]]; then
mv /etc/nginx/nginx.conf.bak /etc/nginx/nginx.conf
fi
if [[ $domain != "" ]]; then
rm -rf $NGINX_CONF_PATH${domain}.conf
fi
[[ -f ~/.acme.sh/acme.sh ]] && ~/.acme.sh/acme.sh --uninstall
# 移除日志切割配置
[[ -f /etc/logrotate.d/v2ray ]] && rm -f /etc/logrotate.d/v2ray
colorEcho $GREEN " V2ray卸载成功"
fi
}
# v2ray版本号前加v或去除v
normalizeVersion(){
if [ -n "$1" ]; then
case $1 in
v*)
echo "$1"
;;
*)
echo "v$1"
;;
esac
else
echo ""
fi
}
# 获取V2ray版本
# 0: 已是最新版本. 1: 有新版本可用. 2: V2Ray未安装. 3: 检查版本失败.
get_version(){
# 判断是否已安装V2ray
if [[ -f /usr/bin/v2ray/v2ray ]]; then
if /usr/bin/v2ray/v2ray -version >/dev/null 2>&1; then
# 旧版本获取方式(v4.x)
VER=$(/usr/bin/v2ray/v2ray -version | awk 'NR==1 {print $2}')
else
# 新版本获取方式(v5.x)
VER="$(/usr/bin/v2ray/v2ray version | awk 'NR==1 {print $2}')"
fi
fi
RETVAL=$?
# 标准化当前版本格式(添加v前缀)
CUR_VER=$(normalizeVersion "$(echo "$VER" | head -n 1 | cut -d " " -f2)")
# 通过Github API获取v2ray最新版本
TAG_URL="https://api.github.com/repos/v2fly/v2ray-core/releases/latest"
NEW_VER=$(normalizeVersion $(curl -s "${TAG_URL}" --connect-timeout 10| tr ',' '\n' | grep 'tag_name' | cut -d\" -f4))
# 使用XTLS直连模式,至少在客户端使用V2Ray v4.32.1+
if [[ $NEW_VER == "" ]]; then
# 如果获取失败则设置默认版本
NEW_VER=v5.1.0
fi
if [[ $? -ne 0 ]] || [[ $NEW_VER == "" ]]; then
colorEcho $RED " 检查V2ray版本信息失败,请检查网络"
return 3
elif [[ $RETVAL -ne 0 ]]; then
return 2
elif [[ $NEW_VER != $CUR_VER ]]; then
return 1
fi
return 0
}
# 检查系统架构
archAffix(){
case "$(uname -m)" in
i686|i386)
echo '32'
;;
x86_64|amd64)
echo '64'
;;
*armv7*)
echo 'arm32-v7a'
;;
armv6*)
echo 'arm32-v6a'
;;
*armv8*|aarch64)
echo 'arm64-v8a'
;;
*mips64le*)
echo 'mips64le'
;;
*mips64*)
echo 'mips64'
;;
*mipsle*)
echo 'mipsle'
;;
*mips*)
echo 'mips'
;;
*s390x*)
echo 's390x'
;;
ppc64le)
echo 'ppc64le'
;;
ppc64)
echo 'ppc64'
;;
*)
colorEcho $RED " 不支持的CPU架构!"
exit 1
;;
esac
return 0
}
# 获取用户输入
get_input(){
echo " V2ray一键脚本,运行之前请确认如下条件已经具备:"
colorEcho ${YELLOW} " 1. 一个伪装域名"
colorEcho ${YELLOW} " 2. 伪装域名DNS解析指向当前服务器ip(${IP})"
colorEcho ${YELLOW} " 3. 如果/root目录下有 v2ray.pem 和 v2ray.key 证书密钥文件,无需理会条件2"
echo ""
read -p " 确认满足按y,按其他退出脚本:" answer
if [[ ${answer,,} != "y" ]]; then
exit 0
fi
# 伪装域名
echo ""
while true; do
read -p " 请输入伪装域名:" domain
if [[ -z $domain ]]; then
colorEcho $RED " 伪装域名不能为空,请重新输入!"
else
break
fi
done
DOMAIN=${domain,,}
colorEcho ${BLUE} " 伪装域名(host):${DOMAIN}"
# 检测是否存在证书文件
if [[ -f ~/v2ray.pem && -f ~/v2ray.key ]]; then
colorEcho ${BLUE} " 检测到自有证书,将使用其部署"
CERT_FILE="/etc/v2ray/${DOMAIN}.pem"
KEY_FILE="/etc/v2ray/${DOMAIN}.key"
else
# 解析域名
response=$(curl -sm8 -A "Mozilla/5.0" https://ipget.net/?ip=${DOMAIN} 2>&1)
if echo $response | grep -iq html; then
# 解析IP
resolve=$(echo $response | grep -oP '<title>\K[0-9]{1,3}(\.[0-9]{1,3}){3}')
if [[ $resolve != $v4 ]] && [[ $resolve != $v6 ]]; then
colorEcho ${RED} " 域名未解析到当前服务器IP("${BLUE}"ipv4:"${RED}"${v4} / "${BLUE}"ipv6:"${RED}"${v6} )"
exit 1
else
colorEcho ${BLUE} " ${DOMAIN} 解析结果:${resolve}"
fi
else
http_code=$(echo $response | awk '{print $3}')
if [[ $http_code -ne 200 ]]; then
colorEcho ${RED} " 域名解析失败,请添加域名解析记录或等待DNS同步,稍后再试。"
exit 1
fi
fi
fi
# v2ray监听端口
echo ""
read -p " 请输入v2ray监听端口[强烈建议443,默认443]:" PORT
[[ -z $PORT ]] && PORT=443
colorEcho ${BLUE} " v2ray端口:$PORT"
# 输入密码
echo ""
read -p " 请设置Trojan密码(不输则随机生成UUID): " PASSWORD
[[ -z $PASSWORD ]] && gen_uuid && PASSWORD=$UUID
colorEcho $BLUE " Trojan密码:$PASSWORD"
# 流控模式
if [[ $XTLS = "true" ]]; then
echo ""
colorEcho $BLUE " 请选择流控模式:"
echo -e " 1) xtls-rprx-direct [${RED}推荐${PLAIN}]"
echo " 2) xtls-rprx-origin"
read -p " 请选择流控模式[默认:direct]" answer
[[ -z $answer ]] && answer=1
case $answer in
1)
FLOW="xtls-rprx-direct"
;;
2)
FLOW="xtls-rprx-origin"
;;
*)
colorEcho $RED " 无效选项,使用默认的xtls-rprx-direct"
FLOW="xtls-rprx-direct"
exit 1
;;
esac
colorEcho $BLUE " 流控模式:$FLOW"
fi
# 反代网站
echo ""
colorEcho $BLUE " 请选择伪装站类型:"
echo " 1) 小说站(随机选择)"
echo " 2) 高清壁纸站(https://wallhaven.cc/)"
read -p " 请选择伪装网站类型[默认:高清壁纸站]" answer
if [[ -z $answer ]]; then
PROXY_URL="https://wallhaven.cc/"
else
case $answer in
1)
len=${#SITES[@]}
((len--))
while true; do
index=$(shuf -i0-${len} -n1)
PROXY_URL=${SITES[$index]}
host=$(echo ${PROXY_URL} | cut -d/ -f3)
ip=$(curl -sm8 ipget.net/?ip=${host})
res=$(echo -n ${ip} | grep ${host})
if [[ "${res}" = "" ]]; then
echo "$ip $host" >> /etc/hosts
break
fi
done
;;
2)
PROXY_URL="https://wallhaven.cc/"
;;
esac
fi
REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3)
colorEcho $BLUE " 伪装网站:$PROXY_URL"
# 是否启用BBR
# 检查内核版本是否支持BBR
KERNEL_VER=$(uname -r | awk -F. '{printf "%d.%d", $1, $2}')
MIN_VER="4.9"
# BBR从4.9内核开始被引入
if [ $(echo "$KERNEL_VER >= $MIN_VER" | bc -l) -eq 1 ]; then
echo ""
read -p " 是否启用BBR(默认启用)?[y/n]:" NEED_BBR
[[ -z $NEED_BBR ]] && NEED_BBR=y
[[ $NEED_BBR = "y" ]] && NEED_BBR=y
colorEcho $BLUE " 启用BBR:$NEED_BBR"
else
colorEcho $RED " 内核版本过低,不支持BBR"
NEED_BBR=n
fi
}
# 生成UUID
gen_uuid(){
if command -v uuidgen &> /dev/null; then
UUID=$(uuidgen)
else
# 使用系统内置的UUID生成器
UUID=$(cat /proc/sys/kernel/random/uuid)
fi
}
# 安装Nginx
install_nginx(){
echo ""
colorEcho $BLUE " 安装nginx..."
$CMD_INSTALL nginx
if [[ $? -ne 0 ]]; then
colorEcho $RED " nginx安装失败,请检查网络"
exit 1
fi
# 自启动
systemctl enable nginx
}
# 安装V2ray
install_v2ray(){
rm -rf /tmp/v2ray
mkdir -p /tmp/v2ray
DOWNLOAD_LINK="https://github.com/v2fly/v2ray-core/releases/download/${NEW_VER}/v2ray-linux-$(archAffix).zip"
colorEcho $BLUE " 下载V2Ray: ${DOWNLOAD_LINK}"
curl -sSL -H "Cache-Control: no-cache" -o /tmp/v2ray/v2ray.zip ${DOWNLOAD_LINK}
if [ $? != 0 ]; then
colorEcho $RED " 下载V2ray文件失败,请检查服务器网络设置"
exit 1
fi
#(v5.x)版本读取配置文件启动命令
v2ray_start_config="run -config"
#(v4.x)版本读取配置文件启动命令
#v2ray_start_config="-config"
mkdir -p '/etc/v2ray' '/var/log/v2ray' && \
unzip /tmp/v2ray/v2ray.zip -d /tmp/v2ray
mkdir -p /usr/bin/v2ray
cp /tmp/v2ray/v2ray /usr/bin/v2ray/; cp /tmp/v2ray/geo* /usr/bin/v2ray/;
chmod +x '/usr/bin/v2ray/v2ray' || {
colorEcho $RED " v2ray可执行文件安装失败"
exit 1
}
cat >$V2RAY_SERVICE_FILE<<-EOF
[Unit]
Description=V2ray Service
Documentation=https://www.v2fly.org/
After=network.target nss-lookup.target
[Service]
# If the version of systemd is 240 or above, then uncommenting Type=exec and commenting out Type=simple
#Type=exec
Type=simple
# This service runs as root. You may consider to run it as another user for security concerns.
# By uncommenting User=nobody and commenting out User=root, the service will run as user nobody.
# More discussion at https://github.com/v2ray/v2ray-core/issues/1011
User=root
#User=nobody
NoNewPrivileges=true
ExecStart=/usr/bin/v2ray/v2ray $v2ray_start_config /etc/v2ray/config.json
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
# 重新加载使新服务配置生效
systemctl daemon-reload
systemctl enable v2ray.service
}
# 启用BBR
install_bbr(){
if [[ $NEED_BBR != "y" ]]; then
INSTALL_BBR=false
return
fi
res=$(hostnamectl | grep -i openvz)
if [[ $res != "" ]]; then
colorEcho $BLUE " openvz机器,跳过安装"
INSTALL_BBR=false
return
fi
# 检查是否已经启用
if sysctl net.ipv4.tcp_congestion_control | grep -q "bbr"; then
colorEcho $BLUE " BBR模块已启用"
INSTALL_BBR=false
return
fi
# 启用BBR
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
sysctl -p
# 持久化配置
echo "tcp_bbr" >> /etc/modules-load.d/bbr.conf
INSTALL_BBR=true
# 验证
if sysctl net.ipv4.tcp_congestion_control | grep -q "bbr"; then
colorEcho $GREEN " BBR模块已启用"
INSTALL_BBR=false
return
fi
}
# 使BBR模块生效,重启系统
bbr_reboot(){
if [[ $INSTALL_BBR = "true" ]]; then
echo
echo " 为使BBR模块生效,系统将在10秒后重启"
echo
echo -e " 您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统"
sleep 10
reboot
fi
}
# 防火墙放行端口
set_firewall(){
res=$(which firewall-cmd 2>/dev/null)
if [[ $? -eq 0 ]]; then
systemctl status firewalld > /dev/null 2>&1
if [[ $? -eq 0 ]]; then
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
if [[ $PORT != "443" ]]; then
firewall-cmd --permanent --add-port=${PORT}/tcp
firewall-cmd --permanent --add-port=${PORT}/udp
fi
firewall-cmd --reload
else
nl=$(iptables -nL | nl | grep FORWARD | awk '{print $1}')
if [[ $nl != "3" ]]; then
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
iptables -I INPUT -p tcp --dport 443 -j ACCEPT
if [[ $PORT != "443" ]]; then
iptables -I INPUT -p tcp --dport ${PORT} -j ACCEPT
iptables -I INPUT -p udp --dport ${PORT} -j ACCEPT
fi
fi
fi
else
res=$(which iptables 2>/dev/null)
if [[ $? -eq 0 ]]; then
nl=$(iptables -nL | nl | grep FORWARD | awk '{print $1}')
if [[ $nl != "3" ]]; then
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
iptables -I INPUT -p tcp --dport 443 -j ACCEPT
if [[ $PORT != "443" ]]; then
iptables -I INPUT -p tcp --dport ${PORT} -j ACCEPT
iptables -I INPUT -p udp --dport ${PORT} -j ACCEPT
fi
fi
else
res=$(which ufw 2>/dev/null)
if [[ $? -eq 0 ]]; then
res=$(ufw status | grep -i inactive)
if [[ $res = "" ]]; then
ufw allow http/tcp
ufw allow https/tcp
if [[ $PORT != "443" ]]; then
ufw allow ${PORT}/tcp
ufw allow ${PORT}/udp
fi
fi
fi
fi
fi
}
# 自动化申请和安装 SSL/TLS 证书(Let's Encrypt)
get_cert(){
mkdir -p /etc/v2ray
# 检查是否已有证书
if [[ -z ${CERT_FILE+x} ]]; then
systemctl stop nginx
res=$(netstat -ntlp| grep -E ':80 |:443 ')
if [[ $res != "" ]]; then
colorEcho ${RED} " 其他进程占用了80或443端口,请先关闭再运行脚本"
echo " 端口占用信息如下:"
echo ${res}
exit 1
fi
# 安装依赖工具
$CMD_INSTALL socat openssl
if [[ $PMT = "yum" ]]; then
$CMD_INSTALL cronie
systemctl start crond
systemctl enable crond
else
$CMD_INSTALL cron
systemctl start cron
systemctl enable cron
fi
# 安装acme.sh客户端
# 设置默认邮箱和证书颁发机构(Let's Encrypt)
# 启用自动升级
curl -sL https://get.acme.sh | sh -s email=webmaster@hicairo.com
# shellcheck disable=SC1090
source ~/.bashrc
~/.acme.sh/acme.sh --upgrade --auto-upgrade
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
if [[ $ipv6Status = "on" ]]; then
# 申请IPv6证书
~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone --listen-v6 --insecure
else
~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone --insecure
fi
if [[ ! -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]]; then
colorEcho $RED " 证书申请失败"
exit 1
fi
KEY_FILE="/etc/v2ray/${DOMAIN}.key"
CERT_FILE="/etc/v2ray/${DOMAIN}.pem"
~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \
--key-file $KEY_FILE \
--fullchain-file $CERT_FILE \
--reloadcmd "systemctl restart nginx"
if [[ ! (-f $CERT_FILE && -f $KEY_FILE) ]]; then
colorEcho $RED " 获取证书失败"
exit 1
fi
else
# 使用已有的证书
cp ~/v2ray.pem /etc/v2ray/${DOMAIN}.pem
cp ~/v2ray.key /etc/v2ray/${DOMAIN}.key
fi
}
# 配置Nginx
config_nginx(){
mkdir -p /etc/nginx/ssl;
# 备份Nginx配置文件
if [[ ! -f /etc/nginx/nginx.conf.bak ]]; then
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
fi
res=$(id nginx 2>/dev/null)
if [[ $? -ne 0 ]]; then
user="www-data"
else
user="nginx"
fi
# 配置Nginx
cat > /etc/nginx/nginx.conf <<EOF
user $user;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
'\$status \$body_bytes_sent "\$http_referer" '
'"\$http_user_agent" "\$http_x_forwarded_for"';
log_format json escape=json
'{'
'"time_local": "$time_iso8601",'
'"remote_addr": "$remote_addr",'
'"request": "$request",'
'"status": "$status",'
'"body_bytes_sent": "$body_bytes_sent",'
'"request_time": "$request_time",'
'"http_referer": "$http_referer",'
'"http_user_agent": "$http_user_agent",'
'"http_x_forwarded_for": "$http_x_forwarded_for",'
'"host": "$host",'
'"upstream_addr": "$upstream_addr",'
'"upstream_status": "$upstream_status",'
'"upstream_response_time": "$upstream_response_time"'
'}';
access_log /var/log/nginx/access.log json;
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
gzip on;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
}
EOF
mkdir -p $NGINX_CONF_PATH
# Trojan
cat > $NGINX_CONF_PATH${DOMAIN}.conf <<EOF
server {
listen 80;
listen [::]:80;
listen 81;
server_name ${DOMAIN};
access_log /var/log/nginx/v2ray-access.log json;
error_log /var/log/nginx/v2ray-error.log;
root /usr/share/nginx/html;
location / {
proxy_ssl_server_name on;
proxy_pass ${PROXY_URL};
proxy_set_header Accept-Encoding '';
sub_filter "${REMOTE_HOST}" "${DOMAIN}";
sub_filter_once off;
}
}
EOF
#cp /etc/v2ray/${DOMAIN}.pem /etc/nginx/ssl/${DOMAIN}.pem
#cp /etc/v2ray/${DOMAIN}.key /etc/nginx/ssl/${DOMAIN}.key
}
# 修改安全策略
set_selinux(){
# enforcing: 强制模式(拦截违规操作并记录日志)
# permissive: 宽容模式(仅记录违规操作不拦截)
if [[ -s /etc/selinux/config ]] && grep 'SELINUX=enforcing' /etc/selinux/config; then
sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config
setenforce 0
fi
}
# Trojan + XTLS (新版v2ray移除了XTLS)
# 可以安装 v4.32.1版本支持
trojanXTLSConfig(){
cat > $V2RAY_CONFIG_FILE <<-EOF
{
"log": {
"access": "/var/log/v2ray/access.log",
"error": "/var/log/v2ray/error.log"
},
"inbounds": [{
"port": $PORT,
"protocol": "trojan",
"settings": {
"clients": [
{
"password": "$PASSWORD",
"flow": "$FLOW"
}
],
"fallbacks": [
{
"alpn": "http/1.1",
"dest": 80
},
{
"alpn": "h2",
"dest": 81
}
]
},
"streamSettings": {
"network": "tcp",
"security": "xtls",
"xtlsSettings": {
"serverName": "$DOMAIN",
"alpn": ["http/1.1", "h2"],
"certificates": [
{
"certificateFile": "$CERT_FILE",
"keyFile": "$KEY_FILE"
}
]
}
}
}],
"outbounds": [{
"protocol": "freedom",
"settings": {}
},{
"protocol": "blackhole",
"settings": {},
"tag": "blocked"
}]
}
EOF
}
# Trojan + TLS
trojanConfig(){
cat > $V2RAY_CONFIG_FILE <<-EOF
{
"log": {
"access": "/var/log/v2ray/access.log",
"error": "/var/log/v2ray/error.log",
"loglevel": "warning"
},
"inbounds": [{
"port": $PORT,
"protocol": "trojan",
"settings": {
"clients": [
{
"password": "$PASSWORD"
}
],
"fallbacks": [
{
"alpn": "http/1.1",
"dest": 80
},
{
"alpn": "h2",
"dest": 81
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "$DOMAIN",
"alpn": ["http/1.1", "h2"],
"certificates": [
{
"certificateFile": "$CERT_FILE",
"keyFile": "$KEY_FILE"
}
]
}
}
}],
"outbounds": [{
"protocol": "freedom",
"settings": {}
},{
"protocol": "blackhole",
"settings": {},
"tag": "blocked"
}]
}
EOF
}
# 配置V2ray
config_v2ray(){
mkdir -p /etc/v2ray
if [[ $XTLS = "true" ]]; then
trojanXTLSConfig
else
trojanConfig
fi
return 0
}
# 安装软件
install_pkg(){
for pkg in "$@"; do
if [[ $PMT = "yum" ]]; then
# 精确匹配包名
if ! yum list installed "$pkg" &>/dev/null; then
if ! $CMD_INSTALL "$pkg"; then
colorEcho $RED " 安装 $pkg 失败!"
exit 1
fi
fi
elif [[ $PMT = "apt" ]]; then
# 使用dpkg-query精确查询
if ! dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null | grep -q "ok installed"; then
if ! $CMD_INSTALL "$pkg"; then
colorEcho $RED " 安装 $pkg 失败!"
exit 1
fi
fi
else
colorEcho $RED " 不支持的包管理器"
exit 1
fi
done
}
# 安装
install(){
get_input
# 清除包管理器缓存
$PMT clean all
# 更新软件源
$CMD_UPGRADE
# 安装必要软件
install_pkg wget vim unzip tar gcc openssl logrotate net-tools
if [[ $PMT = "apt" ]]; then
install_pkg libssl-dev g++
fi
res=$(which unzip 2>/dev/null)
if [[ $? -ne 0 ]]; then
colorEcho $RED " unzip安装失败,请检查网络"
exit 1
fi
# 安装Nginx
install_nginx
# 防火墙放行端口
set_firewall
# 获取证书
get_cert
# 配置Nginx
config_nginx
colorEcho $BLUE " 安装V2ray..."
get_version
RETVAL=$?
if [[ $RETVAL == 0 ]]; then
colorEcho $BLUE " V2ray最新版 ${CUR_VER} 已经安装"
elif [[ $RETVAL == 3 ]]; then
exit 1
else
colorEcho $BLUE " 安装V2Ray ${NEW_VER} ,架构$(archAffix)"
install_v2ray
fi
# 配置V2ray
config_v2ray
# 修改安全策略
set_selinux
# 安装BBR
install_bbr
# 启动V2ray
start
# 打印配置
showConfig
# 日志切割
set_logrotate
# 重启系统
bbr_reboot
}
# 日志切割配置(保留七天日志)
set_logrotate(){
cat > /etc/logrotate.d/v2ray <<EOF
/var/log/v2ray/*.log
{
nocompress
daily
rotate 7
copytruncate
create
ifempty
dateext
missingok
notifempty
noolddir
}
EOF
chmod 644 /etc/logrotate.d/v2ray
}
# 配置文件信息
get_config_file_info(){
protocol="Trojan"
network=$(grep network $V2RAY_CONFIG_FILE | tail -n1| cut -d: -f2 | tr -d \",' ')
domain=$(grep serverName $V2RAY_CONFIG_FILE | cut -d: -f2 | tr -d \",' ')
port=$(grep port $V2RAY_CONFIG_FILE | cut -d: -f2 | tr -d \",' ')
password=$(grep password $V2RAY_CONFIG_FILE | cut -d: -f2 | tr -d \",' ')
if [[ $XTLS = "true" ]]; then
encryption="none"
flow=$(grep flow $V2RAY_CONFIG_FILE | cut -d: -f2 | tr -d \",' ')
fi
}
# 输出Trojan配置信息
output_trojan(){
if [[ $XTLS = "true" ]]; then
echo -e " ${BLUE}IP/域名(address): ${PLAIN} ${RED}${domain}${PLAIN}"
echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}"
echo -e " ${BLUE}密码(password):${PLAIN}${RED}${password}${PLAIN}"
echo -e " ${BLUE}流控(flow):${PLAIN}${RED}${flow}${PLAIN}"
echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}${encryption}${PLAIN}"
echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}"
echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}"
else
echo -e " ${BLUE}IP/域名(address): ${PLAIN} ${RED}${domain}${PLAIN}"
echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}"
echo -e " ${BLUE}密码(password):${PLAIN}${RED}${password}${PLAIN}"
echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}"
echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}"
fi
}
# 展示v2ray配置
showConfig(){
res=$(v2ray_status)
if [[ $res -lt 2 ]]; then
colorEcho $RED " V2ray未安装,请先安装!"
return
fi
echo ""
echo -n -e " ${BLUE}V2ray运行状态:${PLAIN}"
v2ray_status_result
echo -e " ${BLUE}V2ray配置文件: ${PLAIN} ${RED}${V2RAY_CONFIG_FILE}${PLAIN}"
colorEcho $BLUE " V2ray配置信息:"
get_config_file_info
echo -e " ${BLUE}协议: ${PLAIN} ${RED}${protocol}${PLAIN}"
output_trojan
}
# 查看日志
showLog(){
res=$(v2ray_status)
if [[ $res -lt 2 ]]; then
colorEcho $RED " V2ray未安装,请先安装!"
return
fi
journalctl -xen -u v2ray --no-pager
}
# 检查更新
check_update(){
get_version
RETVAL=$?
if [[ $RETVAL == 1 ]]; then
colorEcho $BLUE " 有新版本可用:${NEW_VER}"
fi
}
# 菜单
menu(){
clear
get_version
colorEcho $BLUE "=================================================="
colorEcho $BLUE " v2ray一键安装脚本 "
colorEcho $BLUE " 默认支持BBR加速 | 版本:${CUR_VER} "
colorEcho $BLUE "--------------------------------------------------"
colorEcho $GREEN " 1. 安装Trojan 2. 安装Trojan+TLS "
colorEcho $BLUE "--------------------------------------------------"
colorEcho $GREEN " 3. 更新V2ray 4. 卸载V2ray "
colorEcho $BLUE "--------------------------------------------------"
colorEcho $GREEN " 5. 启动V2ray 6. 重启V2ray "
colorEcho $GREEN " 7. 停止V2ray "
colorEcho $BLUE "--------------------------------------------------"
colorEcho $GREEN " 8. 查看配置 9. 查看日志 "
colorEcho $BLUE "--------------------------------------------------"
colorEcho $GREEN " 0. 退出 "
colorEcho $BLUE "=================================================="
check_update
echo -n " 当前状态:"
v2ray_status_result
echo
read -p " 请选择操作[0-9]:" answer
case $answer in
0)
exit 0
;;
1)
install
;;
2)
#XTLS="true"
install
;;
3)
update
;;
4)
uninstall
;;
5)
start
;;
6)
restart
;;
7)
stop
;;
8)
showConfig
;;
9)
showLog
;;
*)
colorEcho $RED " 请输入正确的数字[0-9]"
exit 1
;;
esac
}
# 主流程
check_env
check_system
action=$1
[[ -z $1 ]] && action=menu
case $action in
menu|update|uninstall|start|restart|stop|showConfig|showLog)
$action
;;
*)
colorEcho $RED " 参数错误"
colorEcho $BLUE " 用法: $(basename $0) [menu|update|uninstall|start|restart|stop|showConfig|showLog]"
;;
esac