v2Ray安装脚本

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