diff --git a/2.sh b/2.sh new file mode 100644 index 00000000..c4b1e77c --- /dev/null +++ b/2.sh @@ -0,0 +1,296 @@ +#!/bin/bash + +# 控制台字体 +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +# 判断是否为root用户 +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +# 检测系统,本部分代码感谢fscarmen的指导 +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +WgcfWarpCli=0 # 0为安装Wgcf、1为安装WARP Cli +WgcfMode=0 # 0为Wgcf单栈模式、1为Wgcf双栈模式 + +VIRT=$(systemd-detect-virt) # 判断VPS虚拟化架构 +KernelVER1=$(uname -r | awk -F . '{print $1 }') && KernelVER2=$(uname -r | awk -F . '{print $2}') # 判断VPS内核版本 + +# 修改相对应模式下的Wgcf配置文件内容 +ud4='sed -i "5 s/^/PostUp = ip -4 rule add from $(ip route get 162.159.192.1 | grep -oP '"'src \K\S+') lookup main\n/"'" wgcf-profile.conf && sed -i "6 s/^/PostDown = ip -4 rule delete from $(ip route get 162.159.192.1 | grep -oP '"'src \K\S+') lookup main\n/"'" wgcf-profile.conf' +ud6='sed -i "7 s/^/PostUp = ip -6 rule add from $(ip route get 2606:4700:d0::a29f:c001 | grep -oP '"'src \K\S+') lookup main\n/"'" wgcf-profile.conf && sed -i "8 s/^/PostDown = ip -6 rule delete from $(ip route get 2606:4700:d0::a29f:c001 | grep -oP '"'src \K\S+') lookup main\n/"'" wgcf-profile.conf' +ud4ud6='sed -i "5 s/^/PostUp = ip -4 rule add from $(ip route get 162.159.192.1 | grep -oP '"'src \K\S+') lookup main\n/"'" wgcf-profile.conf && sed -i "6 s/^/PostDown = ip -4 rule delete from $(ip route get 162.159.192.1 | grep -oP '"'src \K\S+') lookup main\n/"'" wgcf-profile.conf && sed -i "7 s/^/PostUp = ip -6 rule add from $(ip route get 2606:4700:d0::a29f:c001 | grep -oP '"'src \K\S+') lookup main\n/"'" wgcf-profile.conf && sed -i "8 s/^/PostDown = ip -6 rule delete from $(ip route get 2606:4700:d0::a29f:c001 | grep -oP '"'src \K\S+') lookup main\n/"'" wgcf-profile.conf' +c1="sed -i '/0\.0\.0\.0\/0/d' wgcf-profile.conf" +c2="sed -i '/\:\:\/0/d' wgcf-profile.conf" +c3="sed -i 's/engage.cloudflareclient.com/162.159.193.10/g' wgcf-profile.conf" +c4="sed -i 's/engage.cloudflareclient.com/2606:4700:d0::a29f:c001/g' wgcf-profile.conf" +c5="sed -i 's/1.1.1.1/8.8.8.8,2001:4860:4860::8888/g' wgcf-profile.conf" +c6="sed -i 's/1.1.1.1/2001:4860:4860::8888,8.8.8.8/g' wgcf-profile.conf" + +# 确定CPU架构 +arch_affix() { + case "$(uname -m)" in + x86_64 | amd64) cpuArch='amd64' ;; + armv8 | arm64 | aarch64) cpuArch='arm64' ;; + s390x) cpuArch='s390x' ;; + *) red "不支持的CPU架构!" && exit 1 ;; + esac +} + +# 检查TUN模块状态 +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]] && red "检测到未开启TUN模块,请到VPS控制面板处开启" && exit 1 +} + +# 获取VPS IP特征及WARP状态 +get_status(){ + [[ -z $(type -P curl) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl + WARPIPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPIPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + [[ $WARPIPv4Status == "on" ]] && WARPIPv4Status="WARP IPv4" + [[ $WARPIPv4Status == "off" ]] && WARPIPv4Status="原生IPv4" + [[ $WARPIPv6Status == "on" ]] && WARPIPv6Status="WARP IPv6" + [[ $WARPIPv6Status == "off" ]] && WARPIPv6Status="原生IPv6" + [[ -z $WARPIPv4Status ]] && WARPIPv4Status="无法检测IPv4状态" + [[ -z $WARPIPv6Status ]] && WARPIPv6Status="无法检测IPv6状态" + [[ ! -f /usr/local/bin/wgcf ]] && WgcfStatus="未安装" + [[ -f /usr/local/bin/wgcf ]] && WgcfStatus="未启动" && [[ -n $(wg) ]] && WgcfStatus="已启动" +} + +# 安装Wgcf组件——WireGuard +install_wireguard(){ + ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl wget sudo grep + if [[ $RELEASE == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} epel-release + ${PACKAGE_INSTALL[int]} wireguard-tools net-tools iptables + if [ "$KernelVER1" -lt 5 ]|| [ "$KernelVER2" -lt 6 ]; then + if [[ ${VIRT} == "kvm" || ${VIRT} == "xen" || ${VIRT} == "microsoft" ]]; then + vsid=`grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1` + curl -Lo /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-$vsid/jdoss-wireguard-epel-$vsid.repo + yum -y install epel-release wireguard-dkms + fi + fi + fi + if [[ $RELEASE == "Debian" ]]; then + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} lsb-release + echo "deb http://deb.debian.org/debian $(lsb_release -sc)-backports main" > /etc/apt/sources.list.d/backports.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables + if [ "$KernelVER1" -lt 5 ]|| [ "$KernelVER2" -lt 6 ]; then + if [[ ${VIRT} == "kvm" || ${VIRT} == "xen" || ${VIRT} == "microsoft" ]]; then + ${PACKAGE_INSTALL[int]} --no-install-recommends linux-headers-$(uname -r) + ${PACKAGE_INSTALL[int]} --no-install-recommends install wireguard-dkms + fi + fi + fi + if [[ $RELEASE == "Ubuntu" ]]; then + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables + fi + if [[ $VIRT =~ lxc|openvz ]]; then + [[ -e /usr/bin/wireguard-go ]] || wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP/master/wireguard-go -O /usr/bin/wireguard-go && chmod +x /usr/bin/wireguard-go + fi +} + +# 下载并安装Wgcf +wgcf_install(){ + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP/master/wgcf_2.2.12_linux_$cpuArch -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf +} + +# 注册WARP账号 +wgcf_register(){ + while [[ ! -f wgcf-account.toml ]]; do + yes | wgcf register + sleep 5 + done +} + +# 生成WireGuard配置文件 +wgcf_generate(){ + yellow "使用WARP免费版账户请按回车跳过 \n如需启用WARP+账户,请复制WARP+的许可证秘钥(26个字符)后回车" + read -p "WARP+许可证秘钥(26个字符):" WarpPlusID + if [[ -n $WarpPlusID ]]; then + sed -i "s/license_key.*/license_key = \"$WarpPlusID\"/g" wgcf-account.toml + wgcf update + green "正在启用WARP+账户中,如提示:400 Bad Request,则使用WARP免费账户" + fi + while [[ ! -f wgcf-profile.conf ]]; do + wgcf generate + done + MTUy=1500 + MTUc=10 + if [[ $WARPIPv4Status == "原生IPv6" && $WARPIPv4Status == "无法检测IPv4状态" ]]; then + ping='ping6' + IP1='2606:4700:4700::1111' + IP2='2001:4860:4860::8888' + else + ping='ping' + IP1='1.1.1.1' + IP2='8.8.8.8' + fi + while true; do + if ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP1} >/dev/null 2>&1 || ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP2} >/dev/null 2>&1; then + MTUc=1 + MTUy=$((${MTUy} + ${MTUc})) + else + MTUy=$((${MTUy} - ${MTUc})) + [[ ${MTUc} == 1 ]] && break + fi + [[ ${MTUy} -le 1360 ]] && MTUy='1360' && break + done + MTU=$((${MTUy} - 80)) + green "MTU最佳网络吞吐量值= $MTU 已设置完毕" + sed -i "s/MTU.*/MTU = $MTU/g" wgcf-profile.conf + if [[ $WgcfMode == 0 ]]; then + if [[ $WARPIPv4Status == "原生IPv6" && $WARPIPv4Status == "无法检测IPv4状态" ]]; then + echo ${c4} | sh + echo ${c2} | sh + echo ${c6} | sh + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "无法检测IPv6状态" ]]; then + echo ${c1} | sh + echo ${c3} | sh + echo ${c5} | sh + fi + fi + if [[ $WgcfMode == 1 ]]; then + if [[ $WARPIPv4Status == "原生IPv6" && $WARPIPv4Status == "无法检测IPv4状态" ]]; then + echo ${ud6} | sh + echo ${c4} | sh + echo ${c5} | sh + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "无法检测IPv6状态" ]]; then + echo ${ud4} | sh + echo ${c3} | sh + echo ${c5} | sh + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "原生IPv6" ]]; then + echo ${ud4ud6} | sh + echo ${c5} | sh + fi + fi +} + +# 移动Wgcf配置文件到WireGuard文件夹 +mv_wgcf_to_wireguard(){ + cp -f wgcf-profile.conf /etc/wireguard/wgcf.conf >/dev/null 2>&1 + mv -f wgcf-profile.conf /etc/wireguard >/dev/null 2>&1 + mv -f wgcf-account.toml /etc/wireguard >/dev/null 2>&1 +} + +# 启动Wgcf-WARP +start_wgcf_warp(){ + systemctl enable wg-quick@wgcf + wg-quick down wgcf + systemctl start wg-quick@wgcf + checkstatus +} + +# Wgcf-WARP临时开关 +onoff_wgcf_warp(){ + if [ $WgcfStatus == "已启动" ]; then + wg-quick down wgcf + green "关闭WARP成功" + fi + if [ $WgcfStatus == "未启动" ]; then + systemctl restart wg-quick@wgcf + green "恢复WARP成功" + fi +} + +# 安装过程 +install(){ + [[ $WARPIPv4Status == "WARP IPv4" ]] && exit 1 + [[ $WARPIPv6Status == "WARP IPv6" ]] && exit 1 + if [ $WgcfWarpCli == 0 ]; then + install_wireguard + wgcf_install + wgcf_register + wgcf_generate + mv_wgcf_to_wireguard + start_wgcf_warp + fi +} + +# 卸载WARP +uninstall(){ + wg-quick down wgcf >/dev/null 2>&1 + systemctl disable --now wg-quick@wgcf >/dev/null 2>&1 + rpm -e wireguard-tools 2>/dev/null + [[ $(systemctl is-active systemd-resolved) != active ]] && systemctl enable --now systemd-resolved >/dev/null 2>&1 + rm -rf /usr/local/bin/wgcf /etc/wireguard /usr/bin/wireguard-go wgcf-account.toml wgcf-profile.conf /usr/bin/warp /etc/dnsmasq.d/warp.conf + [[ -e /etc/gai.conf ]] && sed -i '/^precedence \:\:ffff\:0\:0/d;/^label 2002\:\:\/16/d' /etc/gai.conf + sed -i "/250 warp/d" /etc/iproute2/rt_tables + warp-cli --accept-tos disconnect >/dev/null 2>&1 + warp-cli --accept-tos disable-always-on >/dev/null 2>&1 + warp-cli --accept-tos delete >/dev/null 2>&1 + ${PACKAGE_UNINSTALL[int]} wireguard-tools wireguard-dkms ipset dnsmasq resolvconf mtr + ${PACKAGE_UNINSTALL[int]} cloudflare-warp + green "CloudFlare WARP 已卸载成功!" +} + +# 菜单 +menu(){ + clear + get_status + red "==========================" + red " Misaka WARP Script " + red " Site: owo.misaka.rest " + echo " " + green "VPS IPv4状态:$WARPIPv4Status" + green "VPS IPv6状态:$WARPIPv6Status" + green "Wgcf状态:$WgcfStatus" + red "==========================" + echo " " + if [[ $WARPIPv4Status == "无法检测IPv4状态" ]]; then + green "1. 安装Wgcf IPv4 WARP" + green "2. 安装Wgcf 双栈 WARP" + fi + if [[ $WARPIPv6Status == "无法检测IPv6状态" ]]; then + green "1. 安装Wgcf IPv6 WARP" + green "2. 安装Wgcf 双栈 WARP" + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "原生IPv6" ]]; then + green "1. 检测到双栈VPS、无法使用单栈WARP" + green "2. 安装Wgcf 双栈 WARP" + fi + read -p "请输入选项:" menuNumberInput + case "$menuNumberInput" in + 1 ) install ;; + 2 ) WgcfMode=1 && install ;; + * ) exit 1 ;; + esac +} + +check_tun +arch_affix +menu \ No newline at end of file diff --git a/3.sh b/3.sh new file mode 100644 index 00000000..93a9204e --- /dev/null +++ b/3.sh @@ -0,0 +1,232 @@ +#!/usr/bin/env bash +# +# Description: Choose a faster mirror for Linux script +# +# Copyright (C) 2017 - 2018 Oldking +# +# URL: https://www.oldking.net/697.html +# + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +SKYBLUE='\033[0;36m' +PLAIN='\033[0m' + +getAbout() { + echo "" + echo " ========================================================= " + echo " \ SuperUpdate.sh Script / " + echo " \ Choose a faster mirror for Linux / " + echo " \ Created by Oldking / " + echo " ========================================================= " + echo "" + echo " Intro: https://www.oldking.net/697.html" + echo " Copyright (C) 2018 Oldking oooldking@gmail.com" + echo -e " Version: ${GREEN}1.0.3${PLAIN} (2 Nov 2018)" + echo " Usage: wget -qO- git.io/superupdate.sh | bash" + echo "" +} + +getHelp() { + echo " $(bash superupdate.sh)" + ehco " - set sources from cdn-fastly " + echo " $(bash superupdate.sh cn) " + echo " - set sources from USTC " + echo " $(bash superupdate.sh 163) " + echo " - set sources from 163.com " + echo " $(bash superupdate.sh aliyun) " + echo " - set sources from aliyun.com " + echo " $(bash superupdate.sh aws) " + echo " - set sources from cdn-aws " + echo " $(bash superupdate.sh restore) " + echo " - restore sources from backup file " +} + +updateInit() { + [[ $EUID -ne 0 ]] && echo -e " ${RED}Error:${PLAIN} This script must be run as root!" && exit 1 + + if [ -f /etc/redhat-release ]; then + release="centos" + elif cat /etc/issue | grep -Eqi "debian"; then + release="debian" + elif cat /etc/issue | grep -Eqi "ubuntu"; then + release="ubuntu" + elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then + release="centos" + elif cat /proc/version | grep -Eqi "debian"; then + release="debian" + elif cat /proc/version | grep -Eqi "ubuntu"; then + release="ubuntu" + elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then + release="centos" + fi + + if [ $release == "debian" ]; then + debianVersion=$(awk -F'[= "]' '/VERSION_ID/{print $3}' /etc/os-release) + elif [ $release == "ubuntu" ]; then + ubuntuVersion=$(awk -F'[= "]' '/VERSION_ID/{print $3}' /etc/os-release) + elif [ $release == "centos" ]; then + os_release=$(grep "CentOS" /etc/redhat-release 2>/dev/null) + if echo "$os_release" | grep "release 5" >/dev/null 2>&1; then + centosVersion=5 + elif echo "$os_release" | grep "release 6" >/dev/null 2>&1; then + centosVersion=6 + elif echo "$os_release" | grep "release 7" >/dev/null 2>&1; then + centosVersion=7 + else + centosVersion="" + fi + else + echo -e " ${RED}Error:${PLAIN} This script can not be run in your system now!" && exit 1 + fi +} + +setDebian() { + if [[ -f /etc/apt/sources.list.bak ]]; then + echo -e " ${GREEN}sources.list.bak exists${PLAIN}" + else + mv /etc/apt/sources.list{,.bak} + fi + + [ -f /etc/apt/sources.list ] && rm /etc/apt/sources.list + + echo "deb http://cdn-fastly.deb.debian.org/debian/ jessie main non-free contrib" >>/etc/apt/sources.list + echo "deb http://cdn-fastly.deb.debian.org/debian/ jessie-updates main non-free contrib" >>/etc/apt/sources.list + echo "deb http://cdn-fastly.deb.debian.org/debian/ jessie-backports main non-free contrib" >>/etc/apt/sources.list + echo "deb-src http://cdn-fastly.deb.debian.org/debian/ jessie main non-free contrib" >>/etc/apt/sources.list + echo "deb-src http://cdn-fastly.deb.debian.org/debian/ jessie-updates main non-free contrib" >>/etc/apt/sources.list + echo "deb-src http://cdn-fastly.deb.debian.org/debian/ jessie-backports main non-free contrib" >>/etc/apt/sources.list + echo "deb http://cdn-fastly.deb.debian.org/debian-security/ jessie/updates main non-free contrib" >>/etc/apt/sources.list + echo "deb-src http://cdn-fastly.deb.debian.org/debian-security/ jessie/updates main non-free contrib" >>/etc/apt/sources.list + + [ "$debianVersion" == '7' ] && sed -i 's/jessie/wheezy/'g /etc/apt/sources.list + [ "$debianVersion" == '8' ] && echo -n "" + [ "$debianVersion" == '9' ] && sed -i 's/jessie/stretch/'g /etc/apt/sources.list +} + +setUbuntu() { + if [[ -f /etc/apt/sources.list.bak ]]; then + echo -e " ${GREEN}sources.list.bak exists${PLAIN}" + else + mv /etc/apt/sources.list{,.bak} + fi + + [ -f /etc/apt/sources.list ] && rm /etc/apt/sources.list + + echo "deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse" >>/etc/apt/sources.list + echo "deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse" >>/etc/apt/sources.list + echo "deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse" >>/etc/apt/sources.list + echo "deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse" >>/etc/apt/sources.list + echo "deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse" >>/etc/apt/sources.list + echo "deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse" >>/etc/apt/sources.list + echo "deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse" >>/etc/apt/sources.list + echo "deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse" >>/etc/apt/sources.list + + [ "$ubuntuVersion" == '14.04' ] && sed -i 's/xenial/trusty/'g /etc/apt/sources.list + [ "$ubuntuVersion" == '16.06' ] && echo -n "" + [ "$ubuntuVersion" == '18.04' ] && sed -i 's/xenial/bionic/'g /etc/apt/sources.list +} + +setCentos() { + if [ -f /etc/yum.repos.d/CentOS-Base.repo.bak ]; then + echo -e " ${GREEN}CentOS-Base.repo.bak exists${PLAIN}" + else + mv /etc/yum.repos.d/CentOS-Base.repo{,.bak} + fi + + [ -f /etc/yum.repos.d/CentOS-Base.repo ] && rm /etc/yum.repos.d/CentOS-Base.repo + + [ "$centosVersion" == '5' ] && wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-5.repo + [ "$centosVersion" == '6' ] && wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo + [ "$centosVersion" == '7' ] && wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo +} + +setAWS() { + sed -i 's/cdn-fastly.deb.debian.org/cdn-aws.deb.debian.org/'g /etc/apt/sources.list +} + +setCn() { + sed -i 's/cdn-fastly.deb.debian.org/mirrors.ustc.edu.cn/'g /etc/apt/sources.list +} + +set163() { + sed -i 's/cdn-fastly.deb.debian.org/mirrors.163.com/'g /etc/apt/sources.list +} + +setAliyun() { + sed -i 's/cdn-fastly.deb.debian.org/mirrors.aliyun.com/'g /etc/apt/sources.list +} + +restore() { + if [ -f /etc/apt/sources.list.bak ]; then + rm /etc/apt/sources.list + mv /etc/apt/sources.list.bak /etc/apt/sources.list + elif [ -f /etc/yum.repos.d/CentOS-Base.repo.bak ]; then + rm /etc/yum.repos.d/CentOS-Base.repo + mv /etc/yum.repos.d/CentOS-Base.repo.bak /etc/yum.repos.d/CentOS-Base.repo + fi +} + +setSources() { + getAbout + updateInit + case "$release" in + debian) + case $para in + 'fastly' | '-fastly' | '--fastly') + setDebian + ;; + 'cn' | '-cn' | '--cn') + setDebian + setCn + ;; + '163' | '-163' | '--163') + setDebian + set163 + ;; + 'aliyun' | '-aliyun' | '--aliyun') + setDebian + setAliyun + ;; + 'aws' | '-aws' | '--aws') + setDebian + setAWS + ;; + 'restore' | '-restore' | '--restore') + restore + ;; + *) + setDebian + ;; + esac + apt-get update + ;; + ubuntu) + case $para in + 'restore' | '-restore' | '--restore') + restore + ;; + *) + setUbuntu + ;; + esac + apt-get update + ;; + centos) + case $para in + 'restore' | '-restore' | '--restore') + restore + ;; + *) + setCentos + ;; + esac + yum makecache + ;; + esac +} + +para=$1 +setSources +echo -e "${GREEN}Done${PLAIN}" \ No newline at end of file diff --git a/666.sh b/666.sh new file mode 100644 index 00000000..0e80ade6 --- /dev/null +++ b/666.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# one key v2ray +rm -rf v2ray cloudflared-linux-amd64 v2ray-linux-64.zip +wget https://github.com/v2fly/v2ray-core/releases/latest/download/v2ray-linux-64.zip +wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 +chmod +x cloudflared-linux-amd64 +unzip -d v2ray v2ray-linux-64.zip +rm -rf v2ray-linux-64.zip +cat>v2ray/config.json<argo.log 2>&1 & +sleep 2 +clear +echo 等到cloudflare argo生成地址 +sleep 3 +argo=$(cat argo.log | grep trycloudflare.com | awk 'NR==2{print}' | awk -F// '{print $2}' | awk '{print $1}') +clear +echo vmess链接已经生成,IP地址可替换为CF优选IP +echo 'vmess://'$(echo '{"add":"icook.hk","aid":"0","host":"'$argo'","id":"ffffffff-ffff-ffff-ffff-ffffffffffff","net":"ws","path":"","port":"443","ps":"argo v2ray","tls":"tls","type":"none","v":"2"}' | base64 -w 0) diff --git a/Koyeb.sh b/Koyeb.sh new file mode 100644 index 00000000..047bd171 --- /dev/null +++ b/Koyeb.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +rm -rf v2ray cloudflared-linux-amd64 v2ray-linux-64.zip +wget https://github.com/v2fly/v2ray-core/releases/latest/download/v2ray-linux-64.zip +wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 +chmod +x cloudflared-linux-amd64 +unzip -d v2ray v2ray-linux-64.zip +rm -rf v2ray-linux-64.zip +cat>v2ray/config.json<argo.log 2>&1 & +sleep 2 +clear +echo 等到cloudflare argo生成地址 +sleep 3 +argo=$(cat argo.log | grep trycloudflare.com | awk 'NR==2{print}' | awk -F// '{print $2}' | awk '{print $1}') +clear +echo vmess链接已经生成,IP地址可替换为CF优选IP +echo 'vmess://'$(echo '{"add":"icook.hk","aid":"0","host":"'$argo'","id":"ffffffff-ffff-ffff-ffff-ffffffffffff","net":"ws","path":"","port":"443","ps":"Koyeb-v2ray","tls":"tls","type":"none","v":"2"}' | base64 -w 0) diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 5c93f456..00000000 --- a/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2004 Sam Hocevar - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/MisakaLetter.sh b/MisakaLetter.sh new file mode 100644 index 00000000..d7beb93d --- /dev/null +++ b/MisakaLetter.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# 控制台字体 +red(){ + echo -e "\033[31m\033[01m$1\033[0m" +} + +green(){ + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow(){ + echo -e "\033[33m\033[01m$1\033[0m" +} + +red "====================================================" +red " __ __ _ _ _ " +red " | \/ (_)___ __ _| | ____ _ _ __ ___ ___| |_ " +red " | |\/| | / __|/ _ | |/ / _ | | __/ _ \/ __| __| " +red " | | | | \__ \ (_| | < (_| |_| | | __/\__ \ |_ " +red " |_| |_|_|___/\__,_|_|\_\__,_(_)_| \___||___/\__| " +echo " " +red "====================================================" diff --git a/README.md b/README.md index 6d3b075a..9d9c54f9 100644 --- a/README.md +++ b/README.md @@ -1,228 +1 @@ -# 网络跳越一键脚本 - -官网: - -论坛: - -TG讨论组: [@hijkclub](https://t.me/hijkclub) - -Youtube频道: - -联系邮箱:hijk.pw@protonmail.ch - - -> **PS**: 本站所有文章和Github上所有脚本均可随意转载和修改使用,无任何约束,无需附上原文链接和本人名字 - -## 一键脚本 - -[本站脚本资源汇总](https://v2raytech.com/script-collection/) - -[CentOS 7/8系统Shadowsocks/SS一键脚本](https://v2raytech.com/shadowsocks-ss-one-click-script) - -[Ubuntu TLS/Debian系统Shadowsocks/SS一键脚本](https://v2raytech.com/ubuntu-shadowsocks-ss-one-click-script/) - -[CentOS 7/8系统ShadowsocksR/SSR一键脚本](https://v2raytech.com/shadowsocksr-ssr-one-click-script/) - -[Ubuntu TLS/Debian系统ShadowsocksR/SS一键脚本](https://v2raytech.com/ubuntu-shadowsocksr-ssr-one-click-script/) - -[CentOS 7/8系统V2Ray一键脚本](https://v2raytech.com/centos-one-click-install-v2ray/) - -[Ubuntu TLS/Debian系统V2Ray一键脚本](https://v2raytech.com/ubuntu-one-click-install-v2ray/) - -[CentOS 7/8系统带伪装V2Ray一键脚本](https://v2raytech.com/v2ray-one-click-script-with-mask/) - -[Ubuntu TLS/Debian系统带伪装V2Ray一键脚本](https://v2raytech.com/ubuntu-v2ray-one-click-script-with-mask/) - -[trojan一键脚本](https://v2raytech.com/trojan-one-click-scrip/) - -[一键搭建Telegram的MTProto代理](https://v2raytech.com/one-click-telegram-mtproto-proxy/) - -[trojan-go一键脚本](https://v2raytech.com/trojan-go-one-click-script/) - -[V2ray多合一脚本,支持VMESS+websocket+TLS+Nginx、VLESS+TCP+XTLS、VLESS+TCP+TLS等组合](https://v2raytech.com/v2ray-all-in-one-script-vless-tcp-xtls-support/) - -[Xray一键脚本](https://v2raytech.com/xray-one-click-script/) - -# 客户端配置教程 - -## SS - -[Shadowsocks/SS windows客户端配置教程](https://v2raytech.com/shadowsocks-windows-client-config-tutorial/) - -[Shadowsocks/SS安卓配置教程](https://v2raytech.com/shadowsocks-android-config-tutorial/) - -[小火箭(Shadowrocket)配置ss/ssr教程](https://v2raytech.com/shadowrocket-config-shadowsocks-shadowsocksr-tutorial/) - -[ShadowsocksX-NG配置教程](https://v2raytech.com/shadowsocksx-ng-config-tutorial/) - -## SSR - -[ShadowsocksR/SSR windows客户端配置教程](https://v2raytech.com/shadowsocksr-ssr-windows-client-config-tutorial/) - -[ShadowsocksR/SSR/SSRR安卓客户端配置教程](https://v2raytech.com/shadowsocksr-ssr-ssrr-android-config-tutorial/) - -[小火箭(Shadowrocket)配置ss/ssr教程](https://v2raytech.com/shadowrocket-config-shadowsocks-shadowsocksr-tutorial/) - -[SSR版ShadowsocksX-NG配置教程](https://v2raytech.com/ssr-shadowsocksx-ng-config-tutorial/) - -## V2Ray - -[V2rayN 4.12配置教程](https://v2raytech.com/v2rayn-4-12-config-tutorial/) - -[V2rayN配置教程](https://v2raytech.com/v2rayn-config-tutorial/) - -[V2rayW配置教程](https://v2raytech.com/v2rayw-config-tutorial/) - -[V2rayU配置教程](https://v2raytech.com/v2rayu-config-tutorial/) - -[V2rayX配置教程](https://v2raytech.com/v2rayx-config-tutorial/) - -[V2rayNG配置教程](https://v2raytech.com/v2rayng-config-tutorial/) - -[Kitsunebi安卓版配置教程](https://v2raytech.com/kitsunebi-android-config-tutorial/) - -[bifrostV配置教程](https://v2raytech.com/bifrostv-config-tutorial/) - -[v2ray多用户配置](https://v2raytech.com/v2ray-multiple-users/) - -[v2ray伪装建站教程](https://v2raytech.com/v2ray-mask-with-website/) - -[Clash for Windows配置V2ray教程](https://v2raytech.com/clash-for-windows-v2ray-tutorial/) - -[ClashX配置V2ray教程](https://v2raytech.com/clashx-config-v2ray-tutorial/) - -[Clash for Android配置V2ray教程](https://v2raytech.com/clash-for-android-config-v2ray-tutorial/) - -## trojan - -[trojan Windows客户端配置教程](https://v2raytech.com/trojan-windows-client-tutorial/) - -[trojan安卓客户端配置教程](https://v2raytech.com/trojan-android-client-config-tutorial/) - -[trojan mac客户端配置教程](https://v2raytech.com/trojan-mac-client-config-tutorial/) - -[Shadowrocket配置trojan教程](https://v2raytech.com/shadowrocket-config-trojan-tutorial/) - -[Clash for Windows配置trojan教程](https://v2raytech.com/clash-for-windows-trojan-config/) - -[ClashX配置Trojan教程](https://v2raytech.com/clashx-config-trojan-tutorial/) - -[Clash for Android配置trojan教程](https://v2raytech.com/clash-for-android-config-trojan-tutorial/) - -[trojan建站教程](https://v2raytech.com/build-website-with-trojan/) - -[trojan-go建站教程](https://v2raytech.com/trojan-go-with-website/) - -# VPS教程 - -[VPS可以用来做什么?](https://v2raytech.com/what-can-vps-do/) - -[CN2 GIA商家推荐](https://v2raytech.com/cn2-gia-merchants/) - -[做站VPS推荐](https://v2raytech.com/vps-for-website/) - -[搬瓦工购买服务器详细教程](https://v2raytech.com/bandwagonghost-buy-vps-tutorial/) - -[购买vultr服务器超详细图文教程](https://v2raytech.com/vultr-buy-vps-tutorial/) - -[DMIT服务器购买和使用教程](https://v2raytech.com/dmit-vps-tutorial/) - -[性价比最高的香港服务器](https://v2raytech.com/best-hongkong-vps/) - -[HostDare购买服务器超详细教程](https://v2raytech.com/hostdare-buy-vps-tutorial/) - -[vps ping测试、去程/回程路由跟踪、vps一键测试脚本](https://v2raytech.com/benchmark-your-vps/) - -[IP、域名、DNS和VPS之间的关系](https://v2raytech.com/ip-vps-domain-relations/) - -[为什么回程路由比去程路由重要?](https://v2raytech.com/why-return-route-important/) - -[CloudCone CN2 GIA套餐开售了,趁还没超售可买来香一把](https://v2raytech.com/cloudcone-cn2-gia-plans-on-sale/) - -[Bitvise连接Linux服务器教程](https://v2raytech.com/bitvise-connect-linux-server-tutorial/) - -[Mac电脑连接Linux教程](https://v2raytech.com/mac-connect-to-linux-tutorial/) - -[vultr常见问题](https://v2raytech.com/vultr-faq/) - -[v2ray使用cloudflare中转流量,拯救被墙ip](https://v2raytech.com/use-cloudflare-unlock-blocked-ip/) - -[CloudCone特价VPS促销,就在今天!](https://v2raytech.com/cloudcone-special-vps-offers/) - -[购买VPS的建议](https://v2raytech.com/buy-vps-tips/) - -[使用NAT VPS中转加速](https://v2raytech.com/use-nat-vps-forward-traffic/) - -[frp内网穿透教程](https://v2raytech.com/frp-nat-tunnel-tutorial/) - -[流畅看1080p、2k、4k视频需要多大带宽?](https://v2raytech.com/1080p-2k-4k-video-bandwidth-requirement/) - -[阿里云卸载云盾/安骑士](https://v2raytech.com/uninstall-aliyun-dun/) - -[腾讯云监控软件一键卸载脚本](https://v2raytech.com/uninstall-tencent-cloud-monitors/) - -[致富经:每天1000+京豆,京东薅羊毛全攻略(星推官、红包、游戏、签到等)](https://v2raytech.com/jd-script-to-get-rich/) - -# Just My Socks - -[Just My Socks购买和使用教程](https://v2raytech.com/just-my-socks-buy-and-use-tutorial/) - -[Just My Socks Windows配置教程](https://v2raytech.com/just-my-socks-windows-config-tutorial/) - -[Just My Socks安卓配置教程](https://v2raytech.com/just-my-socks-android-config-tutorial/) - -[Just My Socks iOS配置教程](https://v2raytech.com/just-my-socks-ios-config-tutorial/) - -[Just My Socks苹果配置教程](https://v2raytech.com/just-my-socks-mac-config-tutorial/) - -[Clash for Windows配置Just My Socks教程](https://v2raytech.com/clash-for-windows-config-just-my-socks-tutorial/) - -[ClashX配置Just My Socks教程](https://v2raytech.com/clashx-config-just-my-socks-tutorial/) - -[Clash for Android配置Just My Socks教程](https://v2raytech.com/clash-for-android-config-just-my-socks-tutorial/) - -[深入理解Clash配置文件](https://v2raytech.com/deep-in-clash-config-file/) - -# 其他 - -[境外apple id信息汇总](https://v2raytech.com/external-apple-id-summary/) - -[切换apple id下载其它国家和地区的应用](https://v2raytech.com/switch-appleid-to-download-app/) - -[Namesilo购买域名详细教程](https://v2raytech.com/namesilo-buy-domain-tutorial/) - -[免费vpn有风险,请慎用](https://v2raytech.com/be-careful-when-use-free-vpn/) - -[对机场/vpn的看法](https://v2raytech.com/opinion-on-vpn-service/) - -[Telegram新手指南和使用教程](https://v2raytech.com/telegram-tutorial/) - -[别太把自己当回事](https://v2raytech.com/do-not-treat-yourself-important/) - -[那些年跑路的机场](https://v2raytech.com/proxy-service-suspended-unexpected/) - -[科学上网常见问题](https://v2raytech.com/vpn-faq/) - -[PC端科学上网常见问题](https://v2raytech.com/pc-vpn-problem-faq/) - -[通过国内服务器转发流量](https://v2raytech.com/forward-traffic-via-internal-vps/) - -[该选用哪种加密算法?](https://v2raytech.com/choose-crypto-method/) - -[添加ipv6支持](https://v2raytech.com/add-ipv6-support/) - -[不建议开启tcp fast open功能](https://v2raytech.com/donot-use-tcp-fast-open/) - -[安装魔改BBR/BBR Plus/锐速(Lotserver)](https://v2raytech.com/install-bbr-plus-lotserver/) - -[配置Telegram走SS/SSR/V2ray/trojan代理](https://v2raytech.com/pc-config-telegram-use-proxy/) - -[WordPress插件推荐及性能优化建议](https://v2raytech.com/wordpress-plugin-recommand-and-mentions/) - -[Google Scholar/谷歌学术403: your client does not have permission to get URL或者we’re sorry的解决办法](https://v2raytech.com/google-scholar-403-error-solution/) - -## 捐赠 - -BTC: 1ND1Gg7oEQCNVPyHVoAaq1sM9Ee3XLJZQG - -ETH: 0x3921dc87110467324A01e1113E6aFa3c8DCD865D +# Hello World! \ No newline at end of file diff --git a/acme.sh b/acme.sh new file mode 100644 index 00000000..8423c4e7 --- /dev/null +++ b/acme.sh @@ -0,0 +1,177 @@ +#!/bin/bash + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "alpine") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Alpine") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update" "apk update -f") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "apk add -f") + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +[[ $EUID -ne 0 ]] && yellow "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 + +checktls() { + if [[ -f /root/cert.crt && -f /root/private.key ]]; then + if [[ -s /root/cert.crt && -s /root/private.key ]]; then + green "证书申请成功!证书(cert.crt)和私钥(private.key)已保存到 /root 文件夹" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + exit 1 + else + red "抱歉,证书申请失败" + green "建议如下:" + yellow "1. 检测防火墙是否打开,如打开请关闭防火墙或放行80端口" + yellow "2. 检查80端口是否开放或占用" + yellow "3. 域名触发Acme.sh官方风控,更换域名或等待7天后再尝试执行脚本" + yellow "4. 脚本可能跟不上时代,建议截图发布到TG群询问" + exit 1 + fi + fi +} + +acme() { + [[ -z $(type -P curl) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P wget) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} wget + [[ -z $(type -P socat) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} socat + [[ -n $(wg 2>/dev/null) ]] && wg-quick down wgcf && yellow "已检测WARP状态打开,为你自动关闭WARP以保证证书申请" + v6=$(ip route get 1.0.0.1 2>/dev/null | grep -oP 'src \K\S+') + v4=$(ip route get 2606:4700:4700::1001 2>/dev/null | grep -oP 'src \K\S+') + [[ -z $v4 ]] && echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + read -p "请输入注册邮箱(例:admin@misaka.rest,或留空自动生成):" acmeEmail + [ -z $acmeEmail ] && autoEmail=$(date +%s%N | md5sum | cut -c 1-32) && acmeEmail=$autoEmail@gmail.com + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && curl https://get.acme.sh | sh -s email=$acmeEmail && source ~/.bashrc && bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade + read -p "请输入解析完成的域名:" domain + green "已输入的域名: $domain" && sleep 1 + domainIP=$(curl -sm8 ipget.net/?ip="cloudflare.1.1.1.1.$domain") + if [[ -n $(echo $domainIP | grep nginx) ]]; then + domainIP=$(curl -sm8 ipget.net/?ip="$domain") + if [[ $domainIP == $v4 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt --force + fi + if [[ $domainIP == $v6 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt --force --listen-v6 + fi + if [[ -n $(echo $domainIP | grep nginx) ]]; then + green "当前域名解析IP:$domainIP" + yellow "域名未解析到当前服务器IP,请检查域名是否填写正确或等待域名解析完成再执行脚本" + exit 1 + elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then + if [[ $domainIP != $v4 ]] && [[ $domainIP != $v6 ]]; then + red "当前域名解析的IP与VPS的IP不匹配" + green "建议如下:" + yellow "1、请确保Cloudflare小云朵为关闭状态(仅限DNS)" + yellow "2、请检查DNS解析设置的IP是否为VPS的IP" + exit 1 + fi + fi + else + read -p "当前为泛域名申请证书,请输入CloudFlare Global API Key:" GAK + export CF_Key="$GAK" + read -p "当前为泛域名申请证书,请输入CloudFlare登录邮箱:" CFemail + export CF_Email="$CFemail" + if [[ $domainIP == $v4 ]]; then + yellow "当前泛域名解析的IPV4:$domainIP" && sleep 1 + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d ${domain} -d *.${domain} -k ec-256 --server letsencrypt + fi + if [[ $domainIP == $v6 ]]; then + yellow "当前泛域名解析的IPV6:$domainIP" && sleep 1 + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d ${domain} -d *.${domain} -k ec-256 --server letsencrypt --listen-v6 + fi + fi + bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls + exit 1 +} + +certificate() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要撤销的域名证书(复制Main_Domain下显示的域名):" domain + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc + bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc + green "撤销并删除${domain}域名证书成功" + exit 1 + else + red "未找到你输入的${domain}域名证书,请自行检查!" + exit 1 + fi +} + +acmerenew() { + [[ -z $(~/.acme.sh/acme.sh -v) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要续期的域名证书(复制Main_Domain下显示的域名):" domain + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + [[ -n $(wg) ]] && wg-quick down wgcf + bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc + checktls + exit 1 + else + red "未找到你输入的${domain}域名证书,请再次检查域名输入正确" + exit 1 + fi +} + +uninstall() { + [[ -z $(~/.acme.sh/acme.sh -v) ]] && yellow "未安装acme.sh无法执行" && exit 1 + ~/.acme.sh/acme.sh --uninstall + rm -rf ~/.acme.sh + rm -f acme1key.sh +} + +upgrade() { + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/acme-1key@master/acme1key.sh && chmod -R 777 acme1key.sh && bash acme1key.sh +} + +menu() { + clear + red "==================================" + echo " " + red " Acme.sh 域名证书一键申请脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 安装Acme.sh并申请证书" + green "2. 撤销并删除已申请的证书" + green "3. 手动续期域名证书" + green "4. 卸载Acme.sh证书申请" + green "5. 更新脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) acme ;; + 2) certificate ;; + 3) acmerenew ;; + 4) uninstall ;; + 5) upgrade ;; + 0) exit 1 ;; + esac +} + +menu \ No newline at end of file diff --git a/acme/acme1key.sh b/acme/acme1key.sh new file mode 100644 index 00000000..1954715a --- /dev/null +++ b/acme/acme1key.sh @@ -0,0 +1,252 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +install_acme(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P wget) ]] && ${PACKAGE_INSTALL[int]} wget + [[ -z $(type -P socat) ]] && ${PACKAGE_INSTALL[int]} socat + [[ -z $(type -P cron) && $SYSTEM =~ Debian|Ubuntu ]] && ${PACKAGE_INSTALL[int]} cron && systemctl start cron systemctl enable cron + [[ -z $(type -P crond) && $SYSTEM == CentOS ]] && ${PACKAGE_INSTALL[int]} cronie && systemctl start crond && systemctl enable crond + read -p "请输入注册邮箱(例:admin@misaka.rest,或留空自动生成):" acmeEmail + [[ -z $acmeEmail ]] && autoEmail=$(date +%s%N | md5sum | cut -c 1-32) && acmeEmail=$autoEmail@gmail.com + curl https://get.acme.sh | sh -s email=$acmeEmail + source ~/.bashrc + bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [[ -n $(~/.acme.sh/acme.sh -v 2>/dev/null) ]]; then + green "Acme.sh证书申请脚本安装成功!" + else + red "抱歉,Acme.sh证书申请脚本安装失败" + green "建议如下:" + yellow "1. 检查VPS的网络环境,如为IPv6 Only的VPS请自行添加WARP或DNS64以安装Acme.sh" + yellow "2. GitHub上游可能出了一些问题,请过一会儿再试" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + fi + back2menu +} + +singleStandalone(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + WARPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + realip=$(curl -sm8 ip.sb) + read -p "请输入解析完成的域名:" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + green "已输入的域名:$domain" && sleep 1 + domainIP=$(curl -s ipget.net/?ip="cloudflare.1.1.1.1.$domain") + if [[ -n $(echo $domainIP | grep nginx) ]]; then + domainIP=$(curl -s ipget.net/?ip="$domain") + if [[ $WARPv4Status =~ on|plus ]] || [[ $WARPv6Status =~ on|plus ]]; then + if [[ -n $(echo $realip | grep ":") ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt + fi + else + if [[ $domainIP == $ipv6 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt --listen-v6 + fi + if [[ $domainIP == $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt + fi + fi + + if [[ -n $(echo $domainIP | grep nginx) ]]; then + yellow "域名解析无效,请检查域名是否填写正确或稍等几分钟等待解析完成再执行脚本" + exit 1 + elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then + if [[ $domainIP != $ipv4 ]] && [[ $domainIP != $ipv6 ]] && [[ $domainIP != $realip ]]; then + green "${domain} 解析结果:($domainIP)" + red "当前二级域名解析的IP与当前VPS使用的IP不匹配" + green "建议如下:" + yellow "1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow "2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +dnsapiNTLD(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的泛域名(输入格式:example.com):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + read -p "请输入Cloudflare Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入Cloudflare的登录邮箱:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server letsencrypt --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server letsencrypt + fi + bash ~/.acme.sh/acme.sh --install-cert -d "*.${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +dnsapiSingle(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的域名:" domain + read -p "请复制Cloudflare的Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入登录Cloudflare的注册邮箱地址:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server letsencrypt --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server letsencrypt + fi + bash ~/.acme.sh/acme.sh --install-cert -d "${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +checktls() { + if [[ -f /root/cert.crt && -f /root/private.key ]]; then + if [[ -s /root/cert.crt && -s /root/private.key ]]; then + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab + green "证书申请成功!脚本申请到的证书(cert.crt)和私钥(private.key)已保存到 /root 文件夹" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + back2menu + else + red "抱歉,证书申请失败" + green "建议如下:" + yellow "1. 自行检测防火墙是否打开,如使用80端口申请模式时,请关闭防火墙或放行80端口" + yellow "2. 在使用CF API申请模式时,如果使用Freenom域名,由于API限制,暂时不能使用此方式申请" + yellow "3. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow "4. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + back2menu + fi + fi +} + +revoke_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要撤销的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc + bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc + rm -rf ~/.acme.sh/${domain}_ecc + green "撤销${domain}的域名证书成功" + back2menu + else + red "未找到你输入的${domain}域名证书,请自行检查!" + back2menu + fi +} + +renew_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要续期的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc + checktls + back2menu + else + red "未找到你输入的${domain}域名证书,请再次检查域名输入正确" + back2menu + fi +} + +uninstall() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh无法执行" && exit 1 + curl https://get.acme.sh | sh + ~/.acme.sh/acme.sh --uninstall + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + rm -rf ~/.acme.sh + rm -f acme1key.sh + back2menu +} + +menu() { + clear + red "==================================" + echo " " + red " Acme.sh 域名证书一键申请脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 安装Acme.sh域名证书申请脚本" + green "2. 申请单域名证书(80端口申请)" + green "3. 申请单域名证书(CF API申请)" + green "4. 申请泛域名证书(CF API申请)" + green "5. 撤销并删除已申请的证书" + green "6. 手动续期域名证书" + green "7. 卸载Acme.sh域名证书申请脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) install_acme ;; + 2) singleStandalone ;; + 3) dnsapiSingle ;; + 4) dnsapiNTLD ;; + 5) revoke_cert ;; + 6) renew_cert ;; + 7) uninstall ;; + *) exit 1 ;; + esac +} + +menu \ No newline at end of file diff --git a/acme1.sh b/acme1.sh new file mode 100644 index 00000000..c9b8dc4d --- /dev/null +++ b/acme1.sh @@ -0,0 +1,239 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +adddns64(){ + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + if [[ -z $ipv4 ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + yellow "检测到VPS为IPv6 Only,已自动设置为DNS64服务器" + fi +} + +checkwarp(){ + WARPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + if [[ $WARPv4Status =~ on|plus || $WARPv6Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + yellow "检测到Wgcf-WARP已启动,为确保正常申请证书已暂时关闭" + fi +} + +install_acme(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P wget) ]] && ${PACKAGE_INSTALL[int]} wget + [[ -z $(type -P socat) ]] && ${PACKAGE_INSTALL[int]} socat + read -p "请输入注册邮箱(例:admin@misaka.rest,或留空自动生成):" acmeEmail + [[ -z $acmeEmail ]] && autoEmail=$(date +%s%N | md5sum | cut -c 1-32) && acmeEmail=$autoEmail@gmail.com + curl https://get.acme.sh | sh -s email=$acmeEmail + source ~/.bashrc + bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade +} + +getCert(){ + [[ -z $(~/.acme.sh/acme.sh -v) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入解析完成的域名:" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" $$ exit 1 + green "已输入的域名:$domain" && sleep 1 + domainIP=$(curl -s ipget.net/?ip="cloudflare.1.1.1.1.$domain") + if [[ -n $(echo $domainIP | grep nginx) ]]; then + domainIP=$(curl -s ipget.net/?ip="$domain") + if [[ $domainIP == $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt + fi + if [[ $domainIP == $ipv6 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt --listen-v6 + fi + + if [[ -n $(echo $domainIP | grep nginx) ]]; then + yellow "域名解析无效,请检查二级域名是否填写正确或稍等几分钟等待解析完成再执行脚本" + exit 1 + elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then + if [[ $domainIP != $ipv4 ]] && [[ $domainIP != $ipv6 ]]; then + green "${domain} 解析结果:($domainIP)" + red "当前二级域名解析的IP与当前VPS使用的IP不匹配" + green "建议如下:" + yellow "1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow "2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + else + green "当前为泛域名申请证书模式,目前脚本仅支持Cloudflare的DNS申请方式" + read -p "请复制Cloudflare的Global API Key:" GAK + export CF_Key="$GAK" + read -p "请输入登录Cloudflare的注册邮箱地址:" CFemail + export CF_Email="$CFemail" + if [[ $domainIP == $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d ${domain} -d *.${domain} -k ec-256 --server letsencrypt + fi + if [[ $domainIP == $ipv6 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d ${domain} -d *.${domain} -k ec-256 --server letsencrypt --listen-v6 + fi + fi + bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +checktls() { + if [[ -f /root/cert.crt && -f /root/private.key ]]; then + if [[ -s /root/cert.crt && -s /root/private.key ]]; then + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab + green "证书申请成功!申请到的证书(cert.crt)和私钥(private.key)已保存到 /root 文件夹" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + exit 1 + else + red "抱歉,证书申请失败" + green "建议如下:" + yellow "1. 检测防火墙是否打开,如打开请关闭防火墙或放行80端口" + yellow "2. 检查80端口是否开放或占用" + yellow "3. 域名触发Acme.sh官方风控,更换域名或等待7天后再尝试执行脚本" + yellow "4. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + exit 1 + fi + fi +} + +revoke_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要撤销的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" $$ exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc + bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc + rm -rf ~/.acme.sh/${domain}_ecc + green "撤销${domain}的域名证书成功" + exit 1 + else + red "未找到你输入的${domain}域名证书,请自行检查!" + exit 1 + fi +} + +renew_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要续期的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" $$ exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + checkwarp + bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc + checktls + exit 1 + else + red "未找到你输入的${domain}域名证书,请再次检查域名输入正确" + exit 1 + fi +} + +uninstall() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh无法执行" && exit 1 + curl https://get.acme.sh | sh + ~/.acme.sh/acme.sh --uninstall + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + rm -rf ~/.acme.sh + rm -f acme1key.sh +} + +menu() { + clear + red "==================================" + echo " " + red " Acme.sh 域名证书一键申请脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 安装Acme.sh域名证书申请脚本" + green "2. 申请域名证书" + green "3. 撤销并删除已申请的证书" + green "4. 手动续期域名证书" + green "5. 卸载Acme.sh域名证书申请脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) install_acme ;; + 2) getCert ;; + 3) revoke_cert ;; + 4) renew_cert ;; + 5) uninstall ;; + *) exit 1 ;; + esac +} + +menu diff --git a/acme2.sh b/acme2.sh new file mode 100644 index 00000000..2fb4bf69 --- /dev/null +++ b/acme2.sh @@ -0,0 +1,261 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +adddns64(){ + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + if [[ -z $ipv4 ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + yellow "检测到VPS为IPv6 Only,已自动设置为DNS64服务器" + fi +} + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +checkwarp(){ + WARPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + if [[ $WARPv4Status =~ on|plus || $WARPv6Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + yellow "检测到Wgcf-WARP已启动,为确保正常申请证书已暂时关闭" + fi +} + +install_acme(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P wget) ]] && ${PACKAGE_INSTALL[int]} wget + [[ -z $(type -P socat) ]] && ${PACKAGE_INSTALL[int]} socat + read -p "请输入注册邮箱(例:admin@misaka.rest,或留空自动生成):" acmeEmail + [[ -z $acmeEmail ]] && autoEmail=$(date +%s%N | md5sum | cut -c 1-32) && acmeEmail=$autoEmail@gmail.com + curl https://get.acme.sh | sh -s email=$acmeEmail + source ~/.bashrc + bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade + back2menu +} + +getSingleCert(){ + [[ -z $(~/.acme.sh/acme.sh -v) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入解析完成的域名:" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" $$ exit 1 + green "已输入的域名:$domain" && sleep 1 + domainIP=$(curl -s ipget.net/?ip="cloudflare.1.1.1.1.$domain") + if [[ -n $(echo $domainIP | grep nginx) ]]; then + domainIP=$(curl -s ipget.net/?ip="$domain") + if [[ $domainIP == $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt + fi + if [[ $domainIP == $ipv6 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt --listen-v6 + fi + + if [[ -n $(echo $domainIP | grep nginx) ]]; then + yellow "域名解析无效,请检查域名是否填写正确或稍等几分钟等待解析完成再执行脚本" + exit 1 + elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then + if [[ $domainIP != $ipv4 ]] && [[ $domainIP != $ipv6 ]]; then + green "${domain} 解析结果:($domainIP)" + red "当前二级域名解析的IP与当前VPS使用的IP不匹配" + green "建议如下:" + yellow "1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow "2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的泛域名(输入格式:example.com):" domain + read -p "请复制Cloudflare的Global API Key:" GAK + export CF_Key="$GAK" + read -p "请输入登录Cloudflare的注册邮箱地址:" CFemail + export CF_Email="$CFemail" + if [ -z $ipv4 ]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server letsencrypt --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server letsencrypt + fi + bash ~/.acme.sh/acme.sh --install-cert -d "*.${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +checktls() { + if [[ -f /root/cert.crt && -f /root/private.key ]]; then + if [[ -s /root/cert.crt && -s /root/private.key ]]; then + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + green "证书申请成功!脚本申请到的证书(cert.crt)和私钥(private.key)已保存到 /root 文件夹" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + back2menu + else + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + red "抱歉,证书申请失败" + green "建议如下:" + yellow "1. 检测防火墙是否打开,如打开请关闭防火墙或放行80端口" + yellow "2. 检查80端口是否开放或占用" + yellow "3. 域名触发Acme.sh官方风控,更换域名或等待7天后再尝试执行脚本" + yellow "4. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + back2menu + fi + fi +} + +revoke_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要撤销的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" $$ exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc + bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc + rm -rf ~/.acme.sh/${domain}_ecc + green "撤销${domain}的域名证书成功" + back2menu + else + red "未找到你输入的${domain}域名证书,请自行检查!" + back2menu + fi +} + +renew_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要续期的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" $$ exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + checkwarp + adddns64 + bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc + checktls + back2menu + else + red "未找到你输入的${domain}域名证书,请再次检查域名输入正确" + back2menu + fi +} + +uninstall() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh无法执行" && exit 1 + curl https://get.acme.sh | sh + ~/.acme.sh/acme.sh --uninstall + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + rm -rf ~/.acme.sh + rm -f acme1key.sh + back2menu +} + +menu() { + clear + red "==================================" + echo " " + red " Acme.sh 域名证书一键申请脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 安装Acme.sh域名证书申请脚本" + green "2. 申请单域名证书(80端口申请)" + green "3. 申请泛域名证书(CF API申请)" + green "4. 撤销并删除已申请的证书" + green "5. 手动续期域名证书" + green "6. 卸载Acme.sh域名证书申请脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) install_acme ;; + 2) getSingleCert ;; + 3) getDomainCert ;; + 4) revoke_cert ;; + 5) renew_cert ;; + 6) uninstall ;; + *) exit 1 ;; + esac +} + +menu diff --git a/acme3.sh b/acme3.sh new file mode 100644 index 00000000..85bc4bd3 --- /dev/null +++ b/acme3.sh @@ -0,0 +1,299 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +adddns64(){ + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + if [[ -z $ipv4 ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + yellow "检测到VPS为IPv6 Only,已自动设置为DNS64服务器" + fi +} + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +checkwarp(){ + WARPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + if [[ $WARPv4Status =~ on|plus || $WARPv6Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + yellow "检测到Wgcf-WARP已启动,为确保正常申请证书已暂时关闭" + fi +} + +install_acme(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P wget) ]] && ${PACKAGE_INSTALL[int]} wget + [[ -z $(type -P socat) ]] && ${PACKAGE_INSTALL[int]} socat + [[ -z $(type -P cron) && $SYSTEM =~ Debian|Ubuntu ]] && ${PACKAGE_INSTALL[int]} cron && systemctl start cron systemctl enable cron + [[ -z $(type -P crond) && $SYSTEM == CentOS ]] && ${PACKAGE_INSTALL[int]} cronie && systemctl start crond && systemctl enable crond + read -p "请输入注册邮箱(例:admin@misaka.rest,或留空自动生成):" acmeEmail + [[ -z $acmeEmail ]] && autoEmail=$(date +%s%N | md5sum | cut -c 1-32) && acmeEmail=$autoEmail@gmail.com + curl https://get.acme.sh | sh -s email=$acmeEmail + source ~/.bashrc + bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [[ -n $(~/.acme.sh/acme.sh -v 2>/dev/null) ]]; then + green "Acme.sh证书申请脚本安装成功!" + else + red "抱歉,Acme.sh证书申请脚本安装失败" + green "建议如下:" + yellow "1. 检查VPS的网络环境,如为IPv6 Only的VPS请自行添加WARP或DNS64以安装Acme.sh" + yellow "2. GitHub上游可能出了一些问题,请过一会儿再试" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + fi + back2menu +} + +getSingleCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入解析完成的域名:" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + green "已输入的域名:$domain" && sleep 1 + domainIP=$(curl -s ipget.net/?ip="cloudflare.1.1.1.1.$domain") + if [[ -n $(echo $domainIP | grep nginx) ]]; then + domainIP=$(curl -s ipget.net/?ip="$domain") + if [[ $domainIP == $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt + fi + if [[ $domainIP == $ipv6 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt --listen-v6 + fi + + if [[ -n $(echo $domainIP | grep nginx) ]]; then + yellow "域名解析无效,请检查域名是否填写正确或稍等几分钟等待解析完成再执行脚本" + exit 1 + elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then + if [[ $domainIP != $ipv4 ]] && [[ $domainIP != $ipv6 ]]; then + green "${domain} 解析结果:($domainIP)" + red "当前二级域名解析的IP与当前VPS使用的IP不匹配" + green "建议如下:" + yellow "1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow "2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的泛域名(输入格式:example.com):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + read -p "请输入Cloudflare Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入Cloudflare的登录邮箱:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server letsencrypt --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server letsencrypt + fi + bash ~/.acme.sh/acme.sh --install-cert -d "*.${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getSingleDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的域名:" domain + read -p "请复制Cloudflare的Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入登录Cloudflare的注册邮箱地址:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server letsencrypt --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server letsencrypt + fi + bash ~/.acme.sh/acme.sh --install-cert -d "${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +checktls() { + if [[ -f /root/cert.crt && -f /root/private.key ]]; then + if [[ -s /root/cert.crt && -s /root/private.key ]]; then + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + green "证书申请成功!脚本申请到的证书(cert.crt)和私钥(private.key)已保存到 /root 文件夹" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + back2menu + else + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + red "抱歉,证书申请失败" + green "建议如下:" + yellow "1. 自行检测防火墙是否打开,如使用80端口申请模式时,请关闭防火墙或放行80端口" + yellow "2. 在使用CF API申请模式时,如果使用Freenom域名,由于API限制,暂时不能使用此方式申请" + yellow "3. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow "4. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + back2menu + fi + fi +} + +revoke_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要撤销的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc + bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc + rm -rf ~/.acme.sh/${domain}_ecc + green "撤销${domain}的域名证书成功" + back2menu + else + red "未找到你输入的${domain}域名证书,请自行检查!" + back2menu + fi +} + +renew_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要续期的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + checkwarp + adddns64 + bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc + checktls + back2menu + else + red "未找到你输入的${domain}域名证书,请再次检查域名输入正确" + back2menu + fi +} + +uninstall() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh无法执行" && exit 1 + curl https://get.acme.sh | sh + ~/.acme.sh/acme.sh --uninstall + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + rm -rf ~/.acme.sh + rm -f acme1key.sh + back2menu +} + +menu() { + clear + red "==================================" + echo " " + red " Acme.sh 域名证书一键申请脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 安装Acme.sh域名证书申请脚本" + green "2. 申请单域名证书(80端口申请)" + green "3. 申请单域名证书(CF API申请)" + green "4. 申请泛域名证书(CF API申请)" + green "5. 撤销并删除已申请的证书" + green "6. 手动续期域名证书" + green "7. 卸载Acme.sh域名证书申请脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) install_acme ;; + 2) getSingleCert ;; + 3) getSingleDomainCert ;; + 4) getDomainCert ;; + 5) revoke_cert ;; + 6) renew_cert ;; + 7) uninstall ;; + *) exit 1 ;; + esac +} + +menu diff --git a/acme4.sh b/acme4.sh new file mode 100644 index 00000000..808c876e --- /dev/null +++ b/acme4.sh @@ -0,0 +1,307 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +certsrv="letsencrypt" + +adddns64(){ + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + if [[ -z $ipv4 ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + yellow "检测到VPS为IPv6 Only,已自动设置为DNS64服务器" + fi +} + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +checkwarp(){ + WARPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + if [[ $WARPv4Status =~ on|plus || $WARPv6Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + yellow "检测到Wgcf-WARP已启动,为确保正常申请证书已暂时关闭" + fi +} + +install_acme(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P wget) ]] && ${PACKAGE_INSTALL[int]} wget + [[ -z $(type -P socat) ]] && ${PACKAGE_INSTALL[int]} socat + [[ -z $(type -P cron) && $SYSTEM =~ Debian|Ubuntu ]] && ${PACKAGE_INSTALL[int]} cron && systemctl start cron systemctl enable cron + [[ -z $(type -P crond) && $SYSTEM == CentOS ]] && ${PACKAGE_INSTALL[int]} cronie && systemctl start crond && systemctl enable crond + read -p "请输入注册邮箱(例:admin@misaka.rest,或留空自动生成):" acmeEmail + [[ -z $acmeEmail ]] && autoEmail=$(date +%s%N | md5sum | cut -c 1-32) && acmeEmail=$autoEmail@gmail.com + curl https://get.acme.sh | sh -s email=$acmeEmail + source ~/.bashrc + bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [[ -n $(~/.acme.sh/acme.sh -v 2>/dev/null) ]]; then + green "Acme.sh证书申请脚本安装成功!" + else + red "抱歉,Acme.sh证书申请脚本安装失败" + green "建议如下:" + yellow "1. 检查VPS的网络环境,如为IPv6 Only的VPS请自行添加WARP或DNS64以安装Acme.sh" + yellow "2. GitHub上游可能出了一些问题,请过一会儿再试" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + fi + back2menu +} + +getSingleCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入解析完成的域名:" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + green "已输入的域名:$domain" && sleep 1 + domainIP=$(curl -s ipget.net/?ip="cloudflare.1.1.1.1.$domain") + if [[ -n $(echo $domainIP | grep nginx) ]]; then + domainIP=$(curl -s ipget.net/?ip="$domain") + if [[ $domainIP == $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server $certsrv + fi + if [[ $domainIP == $ipv6 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server $certsrv --listen-v6 + fi + + if [[ -n $(echo $domainIP | grep nginx) ]]; then + yellow "域名解析无效,请检查域名是否填写正确或稍等几分钟等待解析完成再执行脚本" + exit 1 + elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then + if [[ $domainIP != $ipv4 ]] && [[ $domainIP != $ipv6 ]]; then + green "${domain} 解析结果:($domainIP)" + red "当前二级域名解析的IP与当前VPS使用的IP不匹配" + green "建议如下:" + yellow "1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow "2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的泛域名(输入格式:example.com):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + read -p "请输入Cloudflare Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入Cloudflare的登录邮箱:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server $certsrv --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server $certsrv + fi + bash ~/.acme.sh/acme.sh --install-cert -d "*.${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getSingleDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的域名:" domain + read -p "请复制Cloudflare的Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入登录Cloudflare的注册邮箱地址:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server $certsrv --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server $certsrv + fi + bash ~/.acme.sh/acme.sh --install-cert -d "${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +checktls() { + if [[ -f /root/cert.crt && -f /root/private.key ]]; then + if [[ -s /root/cert.crt && -s /root/private.key ]]; then + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + green "证书申请成功!脚本申请到的证书(cert.crt)和私钥(private.key)已保存到 /root 文件夹" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + back2menu + else + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + red "抱歉,证书申请失败" + green "建议如下:" + yellow "1. 自行检测防火墙是否打开,如使用80端口申请模式时,请关闭防火墙或放行80端口" + yellow "2. 在使用CF API申请模式时,如果使用Freenom域名,由于API限制,暂时不能使用此方式申请" + yellow "3. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow "4. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + back2menu + fi + fi +} + +revoke_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要撤销的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc + bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc + rm -rf ~/.acme.sh/${domain}_ecc + green "撤销${domain}的域名证书成功" + back2menu + else + red "未找到你输入的${domain}域名证书,请自行检查!" + back2menu + fi +} + +renew_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要续期的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + checkwarp + adddns64 + bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc + checktls + back2menu + else + red "未找到你输入的${domain}域名证书,请再次检查域名输入正确" + back2menu + fi +} + +uninstall() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh无法执行" && exit 1 + curl https://get.acme.sh | sh + ~/.acme.sh/acme.sh --uninstall + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + rm -rf ~/.acme.sh + rm -f acme1key.sh + back2menu +} + +menu() { + clear + red "==================================" + echo " " + red " Acme.sh 域名证书一键申请脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 安装Acme.sh域名证书申请脚本" + green "2. 申请单域名证书(80端口申请) (Let's Encrypt)" + green "3. 申请单域名证书(80端口申请) (ZeroSSL)" + green "4. 申请单域名证书(CF API申请) (Let's Encrypt)" + green "5. 申请单域名证书(CF API申请) (ZeroSSL)" + green "6. 申请泛域名证书(CF API申请) (Let's Encrypt)" + green "7. 申请泛域名证书(CF API申请) (ZeroSSL)" + green "8. 撤销并删除已申请的证书" + green "9. 手动续期域名证书" + green "10. 卸载Acme.sh域名证书申请脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) install_acme ;; + 2) getSingleCert ;; + 3) certsrv="zerossl" && getSingleCert ;; + 4) getSingleDomainCert ;; + 5) certsrv="zerossl" && getSingleDomainCert ;; + 6) getDomainCert ;; + 7) certsrv="zerossl" && getDomainCert ;; + 8) revoke_cert ;; + 9) renew_cert ;; + 10) uninstall ;; + *) exit 1 ;; + esac +} + +menu \ No newline at end of file diff --git a/acme5.sh b/acme5.sh new file mode 100644 index 00000000..534cbb92 --- /dev/null +++ b/acme5.sh @@ -0,0 +1,299 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +adddns64(){ + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + if [[ -z $ipv4 ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + yellow "检测到VPS为IPv6 Only,已自动设置为DNS64服务器" + fi +} + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +checkwarp(){ + WARPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + if [[ $WARPv4Status =~ on|plus || $WARPv6Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + yellow "检测到Wgcf-WARP已启动,为确保正常申请证书已暂时关闭" + fi +} + +install_acme(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P wget) ]] && ${PACKAGE_INSTALL[int]} wget + [[ -z $(type -P socat) ]] && ${PACKAGE_INSTALL[int]} socat + [[ -z $(type -P cron) && $SYSTEM =~ Debian|Ubuntu ]] && ${PACKAGE_INSTALL[int]} cron && systemctl start cron systemctl enable cron + [[ -z $(type -P crond) && $SYSTEM == CentOS ]] && ${PACKAGE_INSTALL[int]} cronie && systemctl start crond && systemctl enable crond + read -p "请输入注册邮箱(例:admin@misaka.rest,或留空自动生成):" acmeEmail + [[ -z $acmeEmail ]] && autoEmail=$(date +%s%N | md5sum | cut -c 1-32) && acmeEmail=$autoEmail@gmail.com + curl https://get.acme.sh | sh -s email=$acmeEmail + source ~/.bashrc + bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [[ -n $(~/.acme.sh/acme.sh -v 2>/dev/null) ]]; then + green "Acme.sh证书申请脚本安装成功!" + else + red "抱歉,Acme.sh证书申请脚本安装失败" + green "建议如下:" + yellow "1. 检查VPS的网络环境,如为IPv6 Only的VPS请自行添加WARP或DNS64以安装Acme.sh" + yellow "2. GitHub上游可能出了一些问题,请过一会儿再试" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + fi + back2menu +} + +getSingleCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入解析完成的域名:" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + green "已输入的域名:$domain" && sleep 1 + domainIP=$(curl -s ipget.net/?ip="cloudflare.1.1.1.1.$domain") + if [[ -n $(echo $domainIP | grep nginx) ]]; then + domainIP=$(curl -s ipget.net/?ip="$domain") + if [[ $domainIP == $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server zerossl + fi + if [[ $domainIP == $ipv6 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server zerossl --listen-v6 + fi + + if [[ -n $(echo $domainIP | grep nginx) ]]; then + yellow "域名解析无效,请检查域名是否填写正确或稍等几分钟等待解析完成再执行脚本" + exit 1 + elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then + if [[ $domainIP != $ipv4 ]] && [[ $domainIP != $ipv6 ]]; then + green "${domain} 解析结果:($domainIP)" + red "当前二级域名解析的IP与当前VPS使用的IP不匹配" + green "建议如下:" + yellow "1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow "2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的泛域名(输入格式:example.com):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + read -p "请输入Cloudflare Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入Cloudflare的登录邮箱:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server zerossl --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server zerossl + fi + bash ~/.acme.sh/acme.sh --install-cert -d "*.${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getSingleDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的域名:" domain + read -p "请复制Cloudflare的Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入登录Cloudflare的注册邮箱地址:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server zerossl --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server zerossl + fi + bash ~/.acme.sh/acme.sh --install-cert -d "${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +checktls() { + if [[ -f /root/cert.crt && -f /root/private.key ]]; then + if [[ -s /root/cert.crt && -s /root/private.key ]]; then + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + green "证书申请成功!脚本申请到的证书(cert.crt)和私钥(private.key)已保存到 /root 文件夹" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + back2menu + else + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + red "抱歉,证书申请失败" + green "建议如下:" + yellow "1. 自行检测防火墙是否打开,如使用80端口申请模式时,请关闭防火墙或放行80端口" + yellow "2. 在使用CF API申请模式时,如果使用Freenom域名,由于API限制,暂时不能使用此方式申请" + yellow "3. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow "4. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + back2menu + fi + fi +} + +revoke_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要撤销的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc + bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc + rm -rf ~/.acme.sh/${domain}_ecc + green "撤销${domain}的域名证书成功" + back2menu + else + red "未找到你输入的${domain}域名证书,请自行检查!" + back2menu + fi +} + +renew_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要续期的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + checkwarp + adddns64 + bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc + checktls + back2menu + else + red "未找到你输入的${domain}域名证书,请再次检查域名输入正确" + back2menu + fi +} + +uninstall() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh无法执行" && exit 1 + curl https://get.acme.sh | sh + ~/.acme.sh/acme.sh --uninstall + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + rm -rf ~/.acme.sh + rm -f acme1key.sh + back2menu +} + +menu() { + clear + red "==================================" + echo " " + red " Acme.sh 域名证书一键申请脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 安装Acme.sh域名证书申请脚本" + green "2. 申请单域名证书(80端口申请)" + green "3. 申请单域名证书(CF API申请)" + green "4. 申请泛域名证书(CF API申请)" + green "5. 撤销并删除已申请的证书" + green "6. 手动续期域名证书" + green "7. 卸载Acme.sh域名证书申请脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) install_acme ;; + 2) getSingleCert ;; + 3) getSingleDomainCert ;; + 4) getDomainCert ;; + 5) revoke_cert ;; + 6) renew_cert ;; + 7) uninstall ;; + *) exit 1 ;; + esac +} + +menu diff --git a/acme6.sh b/acme6.sh new file mode 100644 index 00000000..2105c606 --- /dev/null +++ b/acme6.sh @@ -0,0 +1,299 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +adddns64(){ + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + if [[ -z $ipv4 ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + yellow "检测到VPS为IPv6 Only,已自动设置为DNS64服务器" + fi +} + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +checkwarp(){ + WARPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + if [[ $WARPv4Status =~ on|plus || $WARPv6Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + yellow "检测到Wgcf-WARP已启动,为确保正常申请证书已暂时关闭" + fi +} + +install_acme(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P wget) ]] && ${PACKAGE_INSTALL[int]} wget + [[ -z $(type -P socat) ]] && ${PACKAGE_INSTALL[int]} socat + [[ -z $(type -P cron) && $SYSTEM =~ Debian|Ubuntu ]] && ${PACKAGE_INSTALL[int]} cron && systemctl start cron systemctl enable cron + [[ -z $(type -P crond) && $SYSTEM == CentOS ]] && ${PACKAGE_INSTALL[int]} cronie && systemctl start crond && systemctl enable crond + read -p "请输入注册邮箱(例:admin@misaka.rest,或留空自动生成):" acmeEmail + [[ -z $acmeEmail ]] && autoEmail=$(date +%s%N | md5sum | cut -c 1-32) && acmeEmail=$autoEmail@gmail.com + curl https://get.acme.sh | sh -s email=$acmeEmail + source ~/.bashrc + bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [[ -n $(~/.acme.sh/acme.sh -v 2>/dev/null) ]]; then + green "Acme.sh证书申请脚本安装成功!" + else + red "抱歉,Acme.sh证书申请脚本安装失败" + green "建议如下:" + yellow "1. 检查VPS的网络环境,如为IPv6 Only的VPS请自行添加WARP或DNS64以安装Acme.sh" + yellow "2. GitHub上游可能出了一些问题,请过一会儿再试" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + fi + back2menu +} + +getSingleCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入解析完成的域名:" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + green "已输入的域名:$domain" && sleep 1 + domainIP=$(curl -s ipget.net/?ip="cloudflare.1.1.1.1.$domain") + if [[ -n $(echo $domainIP | grep nginx) ]]; then + domainIP=$(curl -s ipget.net/?ip="$domain") + if [[ $domainIP == $ipv6 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt --listen-v6 + fi + if [[ $domainIP == $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server letsencrypt + fi + + if [[ -n $(echo $domainIP | grep nginx) ]]; then + yellow "域名解析无效,请检查域名是否填写正确或稍等几分钟等待解析完成再执行脚本" + exit 1 + elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then + if [[ $domainIP != $ipv4 ]] && [[ $domainIP != $ipv6 ]]; then + green "${domain} 解析结果:($domainIP)" + red "当前二级域名解析的IP与当前VPS使用的IP不匹配" + green "建议如下:" + yellow "1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow "2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的泛域名(输入格式:example.com):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + read -p "请输入Cloudflare Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入Cloudflare的登录邮箱:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server letsencrypt --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server letsencrypt + fi + bash ~/.acme.sh/acme.sh --install-cert -d "*.${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getSingleDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + checkwarp + adddns64 + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的域名:" domain + read -p "请复制Cloudflare的Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入登录Cloudflare的注册邮箱地址:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $ipv4 ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server letsencrypt --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server letsencrypt + fi + bash ~/.acme.sh/acme.sh --install-cert -d "${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +checktls() { + if [[ -f /root/cert.crt && -f /root/private.key ]]; then + if [[ -s /root/cert.crt && -s /root/private.key ]]; then + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + green "证书申请成功!脚本申请到的证书(cert.crt)和私钥(private.key)已保存到 /root 文件夹" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + back2menu + else + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + red "抱歉,证书申请失败" + green "建议如下:" + yellow "1. 自行检测防火墙是否打开,如使用80端口申请模式时,请关闭防火墙或放行80端口" + yellow "2. 在使用CF API申请模式时,如果使用Freenom域名,由于API限制,暂时不能使用此方式申请" + yellow "3. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow "4. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + back2menu + fi + fi +} + +revoke_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要撤销的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc + bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc + rm -rf ~/.acme.sh/${domain}_ecc + green "撤销${domain}的域名证书成功" + back2menu + else + red "未找到你输入的${domain}域名证书,请自行检查!" + back2menu + fi +} + +renew_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要续期的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + checkwarp + adddns64 + bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc + checktls + back2menu + else + red "未找到你输入的${domain}域名证书,请再次检查域名输入正确" + back2menu + fi +} + +uninstall() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh无法执行" && exit 1 + curl https://get.acme.sh | sh + ~/.acme.sh/acme.sh --uninstall + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + rm -rf ~/.acme.sh + rm -f acme1key.sh + back2menu +} + +menu() { + clear + red "==================================" + echo " " + red " Acme.sh 域名证书一键申请脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 安装Acme.sh域名证书申请脚本" + green "2. 申请单域名证书(80端口申请)" + green "3. 申请单域名证书(CF API申请)" + green "4. 申请泛域名证书(CF API申请)" + green "5. 撤销并删除已申请的证书" + green "6. 手动续期域名证书" + green "7. 卸载Acme.sh域名证书申请脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) install_acme ;; + 2) getSingleCert ;; + 3) getSingleDomainCert ;; + 4) getDomainCert ;; + 5) revoke_cert ;; + 6) renew_cert ;; + 7) uninstall ;; + *) exit 1 ;; + esac +} + +menu diff --git a/acme7.sh b/acme7.sh new file mode 100644 index 00000000..9ea5f248 --- /dev/null +++ b/acme7.sh @@ -0,0 +1,299 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +adddns64(){ + ipv4=$(curl -s4m8 https://ip.gs) + ipv6=$(curl -s6m8 https://ip.gs) + if [[ -z $ipv4 ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + yellow "检测到VPS为IPv6 Only,已自动设置为DNS64服务器" + fi +} + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +checkwarp(){ + WARPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + if [[ $WARPv4Status =~ on|plus || $WARPv6Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + yellow "检测到Wgcf-WARP已启动,为确保正常申请证书已暂时关闭" + fi +} + +install_acme(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P wget) ]] && ${PACKAGE_INSTALL[int]} wget + [[ -z $(type -P socat) ]] && ${PACKAGE_INSTALL[int]} socat + [[ -z $(type -P cron) && $SYSTEM =~ Debian|Ubuntu ]] && ${PACKAGE_INSTALL[int]} cron && systemctl start cron systemctl enable cron + [[ -z $(type -P crond) && $SYSTEM == CentOS ]] && ${PACKAGE_INSTALL[int]} cronie && systemctl start crond && systemctl enable crond + read -p "请输入注册邮箱(例:admin@misaka.rest,或留空自动生成):" acmeEmail + [[ -z $acmeEmail ]] && autoEmail=$(date +%s%N | md5sum | cut -c 1-32) && acmeEmail=$autoEmail@gmail.com + curl https://get.acme.sh | sh -s email=$acmeEmail + source ~/.bashrc + bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [[ -n $(~/.acme.sh/acme.sh -v 2>/dev/null) ]]; then + green "Acme.sh证书申请脚本安装成功!" + else + red "抱歉,Acme.sh证书申请脚本安装失败" + green "建议如下:" + yellow "1. 检查VPS的网络环境,如为IPv6 Only的VPS请自行添加WARP或DNS64以安装Acme.sh" + yellow "2. GitHub上游可能出了一些问题,请过一会儿再试" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + fi + back2menu +} + +getSingleCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + # checkwarp + # adddns64 + # ipv4=$(curl -s4m8 https://ip.gs) + # ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入解析完成的域名:" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + green "已输入的域名:$domain" && sleep 1 + domainIP=$(curl -s ipget.net/?ip="cloudflare.1.1.1.1.$domain") + if [[ -n $(echo $domainIP | grep nginx) ]]; then + domainIP=$(curl -s ipget.net/?ip="$domain") + if [[ $domainIP == $(curl -sm8 ip.sb | grep ":") ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server zerossl --listen-v6 + fi + if [[ $domainIP == $(curl -sm8 ip.sb | grep ".") ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server zerossl + fi + + if [[ -n $(echo $domainIP | grep nginx) ]]; then + yellow "域名解析无效,请检查域名是否填写正确或稍等几分钟等待解析完成再执行脚本" + exit 1 + elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then + if [[ $domainIP != $(curl -sm8 ip.sb | grep ".") ]] && [[ $domainIP != $(curl -sm8 ip.sb | grep ":") ]]; then + green "${domain} 解析结果:($domainIP)" + red "当前二级域名解析的IP与当前VPS使用的IP不匹配" + green "建议如下:" + yellow "1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow "2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + # checkwarp + # adddns64 + # ipv4=$(curl -s4m8 https://ip.gs) + # ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的泛域名(输入格式:example.com):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + read -p "请输入Cloudflare Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入Cloudflare的登录邮箱:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $(curl -sm8 ip.sb | grep ":") ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server zerossl --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server zerossl + fi + bash ~/.acme.sh/acme.sh --install-cert -d "*.${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getSingleDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + # checkwarp + # adddns64 + # ipv4=$(curl -s4m8 https://ip.gs) + # ipv6=$(curl -s6m8 https://ip.gs) + read -p "请输入需要申请证书的域名:" domain + read -p "请复制Cloudflare的Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入登录Cloudflare的注册邮箱地址:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $(curl -sm8 ip.sb | grep ":") ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server zerossl --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server zerossl + fi + bash ~/.acme.sh/acme.sh --install-cert -d "${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +checktls() { + if [[ -f /root/cert.crt && -f /root/private.key ]]; then + if [[ -s /root/cert.crt && -s /root/private.key ]]; then + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + green "证书申请成功!脚本申请到的证书(cert.crt)和私钥(private.key)已保存到 /root 文件夹" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + back2menu + else + if [[ -n $(type -P wgcf) ]]; then + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP 已启动成功" + fi + red "抱歉,证书申请失败" + green "建议如下:" + yellow "1. 自行检测防火墙是否打开,如使用80端口申请模式时,请关闭防火墙或放行80端口" + yellow "2. 在使用CF API申请模式时,如果使用Freenom域名,由于API限制,暂时不能使用此方式申请" + yellow "3. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow "4. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + back2menu + fi + fi +} + +revoke_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要撤销的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc + bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc + rm -rf ~/.acme.sh/${domain}_ecc + green "撤销${domain}的域名证书成功" + back2menu + else + red "未找到你输入的${domain}域名证书,请自行检查!" + back2menu + fi +} + +renew_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要续期的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + checkwarp + adddns64 + bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc + checktls + back2menu + else + red "未找到你输入的${domain}域名证书,请再次检查域名输入正确" + back2menu + fi +} + +uninstall() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh无法执行" && exit 1 + curl https://get.acme.sh | sh + ~/.acme.sh/acme.sh --uninstall + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + rm -rf ~/.acme.sh + rm -f acme1key.sh + back2menu +} + +menu() { + clear + red "==================================" + echo " " + red " Acme.sh 域名证书一键申请脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 安装Acme.sh域名证书申请脚本" + green "2. 申请单域名证书(80端口申请)" + green "3. 申请单域名证书(CF API申请)" + green "4. 申请泛域名证书(CF API申请)" + green "5. 撤销并删除已申请的证书" + green "6. 手动续期域名证书" + green "7. 卸载Acme.sh域名证书申请脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) install_acme ;; + 2) getSingleCert ;; + 3) getSingleDomainCert ;; + 4) getDomainCert ;; + 5) revoke_cert ;; + 6) renew_cert ;; + 7) uninstall ;; + *) exit 1 ;; + esac +} + +menu diff --git a/acme8.sh b/acme8.sh new file mode 100644 index 00000000..d23df099 --- /dev/null +++ b/acme8.sh @@ -0,0 +1,240 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +install_acme(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P wget) ]] && ${PACKAGE_INSTALL[int]} wget + [[ -z $(type -P socat) ]] && ${PACKAGE_INSTALL[int]} socat + [[ -z $(type -P cron) && $SYSTEM =~ Debian|Ubuntu ]] && ${PACKAGE_INSTALL[int]} cron && systemctl start cron systemctl enable cron + [[ -z $(type -P crond) && $SYSTEM == CentOS ]] && ${PACKAGE_INSTALL[int]} cronie && systemctl start crond && systemctl enable crond + read -p "请输入注册邮箱(例:admin@misaka.rest,或留空自动生成):" acmeEmail + [[ -z $acmeEmail ]] && autoEmail=$(date +%s%N | md5sum | cut -c 1-32) && acmeEmail=$autoEmail@gmail.com + curl https://get.acme.sh | sh -s email=$acmeEmail + source ~/.bashrc + bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [[ -n $(~/.acme.sh/acme.sh -v 2>/dev/null) ]]; then + green "Acme.sh证书申请脚本安装成功!" + else + red "抱歉,Acme.sh证书申请脚本安装失败" + green "建议如下:" + yellow "1. 检查VPS的网络环境,如为IPv6 Only的VPS请自行添加WARP或DNS64以安装Acme.sh" + yellow "2. GitHub上游可能出了一些问题,请过一会儿再试" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + fi + back2menu +} + +getSingleCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + read -p "请输入解析完成的域名:" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + green "已输入的域名:$domain" && sleep 1 + domainIP=$(curl -s ipget.net/?ip="cloudflare.1.1.1.1.$domain") + if [[ -n $(echo $domainIP | grep nginx) ]]; then + domainIP=$(curl -s ipget.net/?ip="$domain") + if [[ $domainIP == $(curl -s6m8 ip.sb | grep ":") ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server zerossl --listen-v6 + fi + if [[ $domainIP == $(curl -s4m8 ip.sb | grep ".") ]]; then + bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --server zerossl + fi + + if [[ -n $(echo $domainIP | grep nginx) ]]; then + yellow "域名解析无效,请检查域名是否填写正确或稍等几分钟等待解析完成再执行脚本" + exit 1 + elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then + if [[ $domainIP != $(curl -s4m8 ip.sb | grep ".") ]] && [[ $domainIP != $(curl -s6m8 ip.sb | grep ":") ]]; then + green "${domain} 解析结果:($domainIP)" + red "当前二级域名解析的IP与当前VPS使用的IP不匹配" + green "建议如下:" + yellow "1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow "2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + else + red "当前二级域名未设置DNS解析服务器" + green "建议如下:" + yellow "1. 请确保域名解析网站设置已正确解析到域名" + yellow "2. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + fi + bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + read -p "请输入需要申请证书的泛域名(输入格式:example.com):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + read -p "请输入Cloudflare Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入Cloudflare的登录邮箱:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $(curl -s6m8 ip.sb | grep ":") ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server zerossl --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --server zerossl + fi + bash ~/.acme.sh/acme.sh --install-cert -d "*.${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +getSingleDomainCert(){ + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "未安装acme.sh,无法执行操作" && exit 1 + read -p "请输入需要申请证书的域名:" domain + read -p "请复制Cloudflare的Global API Key:" GAK + [[ -z $GAK ]] && red "未输入Cloudflare Global API Key,无法执行操作!" && exit 1 + export CF_Key="$GAK" + read -p "请输入登录Cloudflare的注册邮箱地址:" CFemail + [[ -z $domain ]] && red "未输入Cloudflare的登录邮箱,无法执行操作!" && exit 1 + export CF_Email="$CFemail" + if [[ -z $(curl -s6m8 ip.sb | grep ":") ]]; then + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server zerossl --listen-v6 + else + bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --server zerossl + fi + bash ~/.acme.sh/acme.sh --install-cert -d "${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc + checktls +} + +checktls() { + if [[ -f /root/cert.crt && -f /root/private.key ]]; then + if [[ -s /root/cert.crt && -s /root/private.key ]]; then + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab + green "证书申请成功!脚本申请到的证书(cert.crt)和私钥(private.key)已保存到 /root 文件夹" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + back2menu + else + red "抱歉,证书申请失败" + green "建议如下:" + yellow "1. 自行检测防火墙是否打开,如使用80端口申请模式时,请关闭防火墙或放行80端口" + yellow "2. 在使用CF API申请模式时,如果使用Freenom域名,由于API限制,暂时不能使用此方式申请" + yellow "3. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow "4. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + back2menu + fi + fi +} + +revoke_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要撤销的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc + bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc + rm -rf ~/.acme.sh/${domain}_ecc + green "撤销${domain}的域名证书成功" + back2menu + else + red "未找到你输入的${domain}域名证书,请自行检查!" + back2menu + fi +} + +renew_cert() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh,无法执行操作" && exit 1 + bash ~/.acme.sh/acme.sh --list + read -p "请输入要续期的域名证书(复制Main_Domain下显示的域名):" domain + [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1 + if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then + bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc + checktls + back2menu + else + red "未找到你输入的${domain}域名证书,请再次检查域名输入正确" + back2menu + fi +} + +uninstall() { + [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "未安装acme.sh无法执行" && exit 1 + curl https://get.acme.sh | sh + ~/.acme.sh/acme.sh --uninstall + sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1 + rm -rf ~/.acme.sh + rm -f acme1key.sh + back2menu +} + +menu() { + clear + red "==================================" + echo " " + red " Acme.sh 域名证书一键申请脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 安装Acme.sh域名证书申请脚本" + green "2. 申请单域名证书(80端口申请)" + green "3. 申请单域名证书(CF API申请)" + green "4. 申请泛域名证书(CF API申请)" + green "5. 撤销并删除已申请的证书" + green "6. 手动续期域名证书" + green "7. 卸载Acme.sh域名证书申请脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) install_acme ;; + 2) getSingleCert ;; + 3) getSingleDomainCert ;; + 4) getDomainCert ;; + 5) revoke_cert ;; + 6) renew_cert ;; + 7) uninstall ;; + *) exit 1 ;; + esac +} + +menu diff --git a/argo.sh b/argo.sh new file mode 100644 index 00000000..c5e27786 --- /dev/null +++ b/argo.sh @@ -0,0 +1,222 @@ +#!/bin/bash + +# 控制台字体 +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Alpine") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "apk add -f") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") + +# 判断系统CPU架构 +cpuArch=$(uname -m) + +# 判断cloudflared状态 +cloudflaredStatus="未安装" +loginStatus="未登录" + +# 判断是否为root用户 +[[ $EUID -ne 0 ]] && yellow "请在root用户下运行脚本" && exit 1 + +# 检测系统,本部分代码感谢fscarmen的指导 +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持VPS的当前系统,请使用主流的操作系统" && exit 1 + +## 统计脚本运行次数 +COUNT=$(curl -sm1 "https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2FMisaka-blog%2Fargo-tunnel-script%40master%2Fargo.sh&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false" 2>&1) && + TODAY=$(expr "$COUNT" : '.*\s\([0-9]\{1,\}\)\s/.*') +TOTAL=$(expr "$COUNT" : '.*/\s\([0-9]\{1,\}\)\s.*') + +archAffix() { + case "$cpuArch" in + i686 | i386) cpuArch='386' ;; + x86_64 | amd64) cpuArch='amd64' ;; + armv5tel | arm6l | armv7 | armv7l) cpuArch='arm' ;; + armv8 | aarch64) cpuArch='aarch64' ;; + *) red "不支持的CPU架构!" && exit 1 ;; + esac +} + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +checkStatus() { + [[ -z $(cloudflared -help 2>/dev/null) ]] && cloudflaredStatus="未安装" + [[ -n $(cloudflared -help 2>/dev/null) ]] && cloudflaredStatus="已安装" + [[ -f /root/.cloudflared/cert.pem ]] && loginStatus="已登录" + [[ ! -f /root/.cloudflared/cert.pem ]] && loginStatus="未登录" +} + +installCloudFlared() { + [ $cloudflaredStatus == "已安装" ] && red "检测到已安装并登录CloudFlare Argo Tunnel,无需重复安装!!" && exit 1 + if [ ${RELEASE[int]} == "CentOS" ]; then + [ $cpuArch == "amd64" ] && cpuArch="x86_64" + wget -N https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-$cpuArch.rpm + rpm -i cloudflared-linux-$cpuArch.rpm + else + [ $cpuArch == "aarch64" ] && cpuArch="arm64" + wget -N https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-$cpuArch.deb + dpkg -i cloudflared-linux-$cpuArch.deb + fi + green "请访问下方提示的网址,登录自己的CloudFlare账号" + green "然后授权自己的域名给CloudFlare Argo Tunnel即可" + cloudflared tunnel login + back2menu +} + +uninstallCloudFlared() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + ${PACKAGE_REMOVE[int]} cloudflared + rm -rf /root/.cloudflared + yellow "CloudFlared 客户端已卸载成功" +} + +makeTunnel() { + read -p "请输入需要创建的隧道名称:" tunnelName + cloudflared tunnel create $tunnelName + read -p "请输入域名:" tunnelDomain + cloudflared tunnel route dns $tunnelName $tunnelDomain + cloudflared tunnel list + read -p "请输入隧道UUID(复制ID里面的内容):" tunnelUUID + read -p "请输入传输协议(默认http):" tunnelProtocol + [ -z $tunnelProtocol ] && tunnelProtocol="http" + read -p "请输入反代端口(默认80):" tunnelPort + [ -z $tunnelPort ] && tunnelPort=80 + read -p "请输入将要保存的配置文件名:" tunnelFileName + cat <~/$tunnelFileName.yml +tunnel: $tunnelName +credentials-file: /root/.cloudflared/$tunnelUUID.json +originRequest: + connectTimeout: 30s + noTLSVerify: true +ingress: + - hostname: $tunnelDomain + service: $tunnelProtocol://localhost:$tunnelPort + - service: http_status:404 +EOF + green "配置文件生成成功,已保存为 /root/$tunnelFileName.yml" + back2menu +} + +listTunnel() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ $loginStatus == "未登录" ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + cloudflared tunnel list + back2menu +} + +runTunnel() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ $loginStatus == "未登录" ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + [[ -z $(type -P screen) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} screen + read -p "请复制粘贴配置文件的位置(例:/root/tunnel.yml):" ymlLocation + read -p "请输入创建Screen会话的名字:" screenName + screen -USdm $screenName cloudflared tunnel --config $ymlLocation run + green "隧道已运行成功,请等待1-3分钟启动并解析完毕" + back2menu +} + +killTunnel() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ $loginStatus == "未登录" ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + [[ -z $(type -P screen) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} screen + read -p "请输入需要删除的Screen会话名字:" screenName + screen -S $screenName -X quit + green "Screen会话停止成功!" + back2menu +} + +deleteTunnel() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ $loginStatus == "未登录" ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + read -p "请输入需要删除的隧道名称:" tunnelName + cloudflared tunnel delete $tunnelName + back2menu +} + +argoCert() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ $loginStatus == "未登录" ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + sed -n "1, 5p" /root/.cloudflared/cert.pem >>/root/private.key + sed -n "6, 24p" /root/.cloudflared/cert.pem >>/root/cert.crt + green "CloudFlare Argo Tunnel证书提取成功!" + yellow "证书crt路径如下:/root/cert.crt" + yellow "私钥key路径如下:/root/private.key" + green "使用证书提示:" + yellow "1. 当前证书只能使用于CF Argo Tunnel授权过的域名" + yellow "2. 在需要使用证书的服务使用Argo Tunnel的域名,必须使用其证书" + back2menu +} + +menu() { + clear + checkStatus + red "==================================" + echo " " + red " CloudFlare Argo Tunnel一键脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + yellow "今日运行次数:$TODAY 总共运行次数:$TOTAL" + echo " " + green "CloudFlared 客户端状态:$cloudflaredStatus" + green "账户登录状态:$loginStatus" + echo " " + echo "1. 安装并登录CloudFlared客户端" + echo "2. 配置Argo Tunnel隧道" + echo "3. 列出Argo Tunnel隧道" + echo "4. 运行Argo Tunnel隧道" + echo "5. 停止Argo Tunnel隧道" + echo "6. 删除Argo Tunnel隧道" + echo "7. 获取Argo Tunnel证书" + echo "8. 卸载CloudFlared客户端" + echo "9. 更新脚本" + echo "0. 退出脚本" + echo " " + read -p "请输入选项:" menuNumberInput + case "$menuNumberInput" in + 1) installCloudFlared ;; + 2) makeTunnel ;; + 3) listTunnel ;; + 4) runTunnel ;; + 5) killTunnel ;; + 6) deleteTunnel ;; + 7) argoCert ;; + 8) uninstallCloudFlared ;; + 9) wget -N https://raw.githubusercontent.com/Misaka-blog/argo-tunnel-script/master/argo.sh && bash argo.sh ;; + *) exit 1 ;; + esac +} + +archAffix +menu \ No newline at end of file diff --git a/argo3.sh b/argo3.sh new file mode 100644 index 00000000..3928c662 --- /dev/null +++ b/argo3.sh @@ -0,0 +1,218 @@ +#!/bin/bash + +# 控制台字体 +red(){ + echo -e "\033[31m\033[01m$1\033[0m"; +} + +green(){ + echo -e "\033[32m\033[01m$1\033[0m"; +} + +yellow(){ + echo -e "\033[33m\033[01m$1\033[0m"; +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Alpine") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +ARCH=`uname -m` + +# 判断是否为root用户 +[[ $EUID -ne 0 ]] && yellow "请在root用户下运行脚本" && exit 1 + +# 检测系统,本部分代码感谢fscarmen的指导 +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int=0; int<${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持VPS的当前系统,请使用主流的操作系统" && exit 1 + +[ $ARCH == "s390x" ] && red "不支持VPS的当前系统架构,请换用主流的VPS架构" && exit 1 +[ $ARCH = "x86_64" ] && ARCH="amd64" + +## 统计脚本运行次数 +COUNT=$(curl -sm1 "https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2FMisaka-blog%2Fargo-tunnel-script%40master%2Fargo.sh&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false" 2>&1) && +TODAY=$(expr "$COUNT" : '.*\s\([0-9]\{1,\}\)\s/.*') +TOTAL=$(expr "$COUNT" : '.*/\s\([0-9]\{1,\}\)\s.*') + +back2menu(){ + green "所选操作执行完成" + read -p "请输入“y”回到主菜单,或按任意键退出脚本:" back2menuInput + case "$back2menuInput" in + y ) menu + esac +} + +install(){ + [[ -n $(cloudflared -help) ]] && red "检测到已安装CloudFlare Argo Tunnel,无需重复安装!!" && exit 1 + ${PACKAGE_UPDATE[int]} + if [ $RELEASE == "CentOS" ]; then + wget -N https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${ARCH}.rpm + rpm -i cloudflared-linux-${ARCH}.rpm + else + wget -N https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${ARCH}.deb + dpkg -i cloudflared-linux-${ARCH}.deb + fi + back2menu +} + +tryHTTPTunnel(){ + [[ -z $(cloudflared -help) ]] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + read -p "请输入你需要穿透的http端口号(默认80):" httpPort + [ -z $httpPort ] && httpPort=80 + cloudflared tunnel --url http://127.0.0.1:$httpPort +} + +tryTCPTunnel(){ + [[ -z $(cloudflared -help) ]] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + read -p "请输入你需要穿透的tcp端口号(默认80):" tcpPort + [ -z $tcpPort ] && tcpPort=80 + cloudflared tunnel --url tcp://127.0.0.1:$tcpPort +} + +cfargoLogin(){ + [[ -z $(cloudflared -help) ]] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [[ -f /root/.cloudflared/cert.pem ]] && red "已登录CloudFlare Argo Tunnel客户端,无需重复登录!!!" && exit 1 + green "请访问下方提示的网址,登录自己的CloudFlare账号" + green "然后授权自己的域名给CloudFlare Argo Tunnel即可" + cloudflared tunnel login + back2menu +} + +createTunnel(){ + read -p "请输入需要创建的隧道名称:" tunnelName + cloudflared tunnel create $tunnelName + back2menu +} + +deleteTunnel(){ + read -p "请输入需要删除的隧道名称:" tunnelName + cloudflared tunnel delete $tunnelName + back2menu +} + +tunnelFile(){ + cloudflared tunnel list + read -p "请输入隧道名称(复制NAME里面的内容):" tunnelName + read -p "请输入隧道UUID(复制ID里面的内容):" tunnelUUID + read -p "请输入传输协议(默认http):" tunnelProtocol + [ -z $tunnelProtocol ] && tunnelProtocol="http" + read -p "请输入域名:" tunnelDomain + read -p "请输入反代端口:" tunnelPort + read -p "请输入配置文件名:" tunnelFileName + cat < ~/$tunnelFileName.yml +tunnel: $tunnelName +credentials-file: /root/.cloudflared/$tunnelUUID.json +originRequest: + connectTimeout: 30s + noTLSVerify: true +ingress: + - hostname: $tunnelDomain + service: $tunnelProtocol://localhost:$tunnelPort + - service: http_status:404 +EOF + back2menu +} + +tunnelConfig(){ + read -p "请输入需要配置的隧道名称:" tunnelName + read -p "请输入需要配置的域名:" tunnelDomain + cloudflared tunnel route dns $tunnelName $tunnelDomain + back2menu +} + +tunnelSelection(){ + [[ -z $(cloudflared -help) ]] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ ! -f /root/.cloudflared/cert.pem ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + echo "1. 创建隧道" + echo "2. 删除隧道" + echo "3. 配置隧道" + echo "4. 创建隧道配置yml文件" + echo "5. 列出隧道" + read -p "请输入选项:" tunnelNumberInput + case "$tunnelNumberInput" in + 1 ) createTunnel ;; + 2 ) deleteTunnel ;; + 3 ) tunnelConfig ;; + 4 ) tunnelFile ;; + 5 ) cloudflared tunnel list && back2menu;; + 0 ) exit 1 + esac +} + +runHTTPTunnel(){ + [[ -z $(cloudflared -help) ]] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ ! -f /root/.cloudflared/cert.pem ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + read -p "请输入需要运行的隧道名称:" tunnelName + read -p "请输入你需要穿透的http端口号(默认80):" httpPort + [ -z $httpPort ] && httpPort=80 + read -p "请选择http / https协议(默认http):" httpHttps + cloudflared tunnel run --url $httpHttps://127.0.0.1:$httpPort $tunnelName +} + +runTCPTunnel(){ + [[ -z $(cloudflared -help) ]] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ ! -f /root/.cloudflared/cert.pem ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + read -p "请输入需要运行的隧道名称:" tunnelName + read -p "请输入你需要穿透的tcp端口号(默认80):" tcpPort + [ -z $tcpPort ] && tcpPort=80 + cloudflared tunnel run --url tcp://127.0.0.1:$tcpPort $tunnelName +} + +runTunnelUseYml(){ + [[ -z $(cloudflared -help) ]] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ ! -f /root/.cloudflared/cert.pem ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + read -p "请复制粘贴配置文件的位置(例:/root/tunnel.yml):" ymlLocation + cloudflared tunnel --config $ymlLocation run +} + +menu(){ + clear + red "==================================" + echo " " + red " CloudFlare Argo Tunnel一键脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + yellow "今日运行次数:$TODAY 总共运行次数:$TOTAL" + echo " " + echo "1. 安装CloudFlare Argo Tunnel客户端" + echo "2. 体验CloudFlare Argo Tunnel HTTP隧道" + echo "3. 体验CloudFlare Argo Tunnel TCP隧道" + echo "4. 登录CloudFlare Argo Tunnel客户端" + echo "5. 创建、删除、配置和列出隧道" + echo "6. 运行HTTP隧道" + echo "7. 运行TCP隧道" + echo "8. 运行任意隧道(使用yml配置文件)" + echo "9. 卸载CloudFlare Argo Tunnel客户端" + echo "10. 更新脚本" + echo "0. 退出脚本" + read -p "请输入选项:" menuNumberInput + case "$menuNumberInput" in + 1 ) install ;; + 2 ) tryHTTPTunnel ;; + 3 ) tryTCPTunnel ;; + 4 ) cfargoLogin ;; + 5 ) tunnelSelection ;; + 6 ) runHTTPTunnel ;; + 7 ) runTCPTunnel ;; + 8 ) runTunnelUseYml ;; + 9 ) ${PACKAGE_REMOVE[int]} cloudflared ;; + 10 ) wget -N https://raw.githubusercontents.com/Misaka-blog/argo-tunnel-script/master/argo.sh && bash argo.sh ;; + 0 ) exit 1 + esac +} + +menu \ No newline at end of file diff --git a/argoFile2.sh b/argoFile2.sh new file mode 100644 index 00000000..b68f4834 --- /dev/null +++ b/argoFile2.sh @@ -0,0 +1,20 @@ +read -p "请输入隧道名称:" tunnelName +read -p "请输入隧道UUID:" tunnelUUID +read -p "请输入传输协议(默认http):" tunnelProtocol +if [ -z $tunnelProtocol ]; then + tunnelProtocol="http" +fi +read -p "请输入域名:" tunnelDomain +read -p "请输入反代端口:" tunnelPort +read -p "请输入配置文件名:" tunnelFileName +cat < ~/$tunnelFileName.yml +tunnel: $tunnelName +credentials-file: /root/.cloudflared/$tunnelUUID.json +originRequest: + connectTimeout: 30s + noTLSVerify: true +ingress: + - hostname: $tunnelDomain + service: $tunnelProtocol://localhost:$tunnelPort + - service: http_status:404 +EOF \ No newline at end of file diff --git a/argo_mai.sh b/argo_mai.sh new file mode 100644 index 00000000..0dbcc30b --- /dev/null +++ b/argo_mai.sh @@ -0,0 +1,229 @@ +#!/bin/bash + +# 控制台字体 +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Alpine") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "apk add -f") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") + +# 判断系统CPU架构 +cpuArch=$(uname -m) + +# 判断cloudflared状态 +cloudflaredStatus="未安装" +loginStatus="未登录" + +# 判断是否为root用户 +[[ $EUID -ne 0 ]] && yellow "请在root用户下运行脚本" && exit 1 + +# 检测系统,本部分代码感谢fscarmen的指导 +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持VPS的当前系统,请使用主流的操作系统" && exit 1 + +## 统计脚本运行次数 +COUNT=$(curl -sm1 "https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2FMisaka-blog%2Fargo-tunnel-script%40master%2Fargo.sh&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false" 2>&1) && +TODAY=$(expr "$COUNT" : '.*\s\([0-9]\{1,\}\)\s/.*') +TOTAL=$(expr "$COUNT" : '.*/\s\([0-9]\{1,\}\)\s.*') + +archAffix() { + case "$cpuArch" in + i686 | i386) cpuArch='386' ;; + x86_64 | amd64) cpuArch='amd64' ;; + armv5tel | arm6l | armv7 | armv7l) cpuArch='arm' ;; + armv8 | aarch64) cpuArch='aarch64' ;; + *) red "不支持的CPU架构!" && exit 1 ;; + esac +} + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +checkStatus() { + [[ -z $(cloudflared -help 2>/dev/null) ]] && cloudflaredStatus="未安装" + [[ -n $(cloudflared -help 2>/dev/null) ]] && cloudflaredStatus="已安装" + [[ -f /root/.cloudflared/cert.pem ]] && loginStatus="已登录" + [[ ! -f /root/.cloudflared/cert.pem ]] && loginStatus="未登录" +} + +installCloudFlared() { + [ $cloudflaredStatus == "已安装" ] && red "检测到已安装CloudFlare Argo Tunnel,无需重复安装!!" && exit 1 + if [ ${RELEASE[int]} == "CentOS" ]; then + [ $cpuArch == "amd64" ] && cpuArch="x86_64" + wget -N https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-$cpuArch.rpm + rpm -i cloudflared-linux-$cpuArch.rpm + else + [ $cpuArch == "aarch64" ] && cpuArch="arm64" + wget -N https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-$cpuArch.deb + dpkg -i cloudflared-linux-$cpuArch.deb + fi + back2menu +} + +uninstallCloudFlared() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + ${PACKAGE_REMOVE[int]} cloudflared + rm -rf /root/.cloudflared + yellow "CloudFlared 客户端已卸载成功" +} + +loginCloudFlared() { + [ $loginStatus == "已登录" ] && red "已登录CloudFlare Argo Tunnel客户端,无需重复登录!!!" && exit 1 + green "请访问下方提示的网址,登录自己的CloudFlare账号" + green "然后授权自己的域名给CloudFlare Argo Tunnel即可" + cloudflared tunnel login + back2menu +} + +makeTunnel() { + read -p "请输入需要创建的隧道名称:" tunnelName + cloudflared tunnel create $tunnelName + read -p "请输入域名:" tunnelDomain + cloudflared tunnel route dns $tunnelName $tunnelDomain + cloudflared tunnel list + read -p "请输入隧道UUID(复制ID里面的内容):" tunnelUUID + read -p "请输入传输协议(默认http):" tunnelProtocol + [ -z $tunnelProtocol ] && tunnelProtocol="http" + read -p "请输入反代端口(默认80):" tunnelPort + [ -z $tunnelPort ] && tunnelPort=80 + read -p "请输入将要保存的配置文件名:" tunnelFileName + cat <~/$tunnelFileName.yml +tunnel: $tunnelName +credentials-file: /root/.cloudflared/$tunnelUUID.json +originRequest: + connectTimeout: 30s + noTLSVerify: true +ingress: + - hostname: $tunnelDomain + service: $tunnelProtocol://localhost:$tunnelPort + - service: http_status:404 +EOF + green "配置文件生成成功,已保存为 /root/$tunnelFileName.yml" + back2menu +} + +listTunnel() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ $loginStatus == "未登录" ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + cloudflared tunnel list + back2menu +} + +runTunnel() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ $loginStatus == "未登录" ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + [[ -z $(type -P screen) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} screen + read -p "请复制粘贴配置文件的位置(例:/root/tunnel.yml):" ymlLocation + read -p "请输入创建Screen会话的名字:" screenName + screen -USdm $screenName cloudflared tunnel --config $ymlLocation run + green "隧道已运行成功,请等待1-3分钟启动并解析完毕" + back2menu +} + +killTunnel() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ $loginStatus == "未登录" ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + [[ -z $(type -P screen) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} screen + read -p "请输入需要删除的Screen会话名字:" screenName + screen -S $screenName -X quit + green "Screen会话停止成功!" + back2menu +} + +deleteTunnel() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ $loginStatus == "未登录" ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + read -p "请输入需要删除的隧道名称:" tunnelName + cloudflared tunnel delete $tunnelName + back2menu +} + +argoCert() { + [ $cloudflaredStatus == "未安装" ] && red "检测到未安装CloudFlare Argo Tunnel客户端,无法执行操作!!!" && exit 1 + [ $loginStatus == "未登录" ] && red "请登录CloudFlare Argo Tunnel客户端后再执行操作!!!" && exit 1 + sed -n "1, 5p" /root/.cloudflared/cert.pem >>/usr/local/share/au/server.key + sed -n "6, 24p" /root/.cloudflared/cert.pem >>/usr/local/share/au/server.crt + green "CloudFlare Argo Tunnel证书提取成功!" + yellow "证书crt路径如下:/usr/local/share/au/server.crt" + yellow "私钥key路径如下:/usr/local/share/au/server.key" + green "使用证书提示:" + yellow "1. 当前证书只能使用于CF Argo Tunnel授权过的域名" + yellow "2. 在需要使用证书的服务使用Argo Tunnel的域名,必须使用其证书" + back2menu +} + +menu() { + clear + checkStatus + red "==================================" + echo " " + red " CloudFlare Argo Tunnel一键脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + yellow "今日运行次数:$TODAY 总共运行次数:$TOTAL" + echo " " + green "CloudFlared 客户端状态:$cloudflaredStatus" + green "账户登录状态:$loginStatus" + echo " " + echo "1. 安装CloudFlared客户端" + echo "2. 登录CloudFlared客户端" + echo "3. 配置Argo Tunnel隧道" + echo "4. 列出Argo Tunnel隧道" + echo "5. 运行Argo Tunnel隧道" + echo "6. 停止Argo Tunnel隧道" + echo "7. 删除Argo Tunnel隧道" + echo "8. 获取Argo Tunnel证书" + echo "9. 卸载CloudFlared客户端" + echo "10. 更新脚本" + echo "0. 退出脚本" + echo " " + read -p "请输入选项:" menuNumberInput + case "$menuNumberInput" in + 1) installCloudFlared ;; + 2) loginCloudFlared ;; + 3) makeTunnel ;; + 4) listTunnel ;; + 5) runTunnel ;; + 6) killTunnel ;; + 7) deleteTunnel ;; + 8) argoCert ;; + 9) uninstallCloudFlared ;; + 10) wget -N https://raw.githubusercontent.com/Misaka-blog/argo-tunnel-script/master/argo.sh && bash argo.sh ;; + *) exit 1 ;; + esac +} + +archAffix +menu diff --git a/certs/4400bcd9-43b4-4291-8187-422f2d0a4a3d.json b/certs/4400bcd9-43b4-4291-8187-422f2d0a4a3d.json new file mode 100644 index 00000000..9f3215fd --- /dev/null +++ b/certs/4400bcd9-43b4-4291-8187-422f2d0a4a3d.json @@ -0,0 +1 @@ +{"AccountTag":"01566075511aa9a8032e91c0de66adb2","TunnelSecret":"Unjnc4F6+tO/fjxSpZYHdfyNq5yqwGmH5EFVGGfD4Uc=","TunnelID":"4400bcd9-43b4-4291-8187-422f2d0a4a3d","TunnelName":"koyeb1"} diff --git a/certs/cert.pem b/certs/cert.pem new file mode 100644 index 00000000..56e6444a --- /dev/null +++ b/certs/cert.pem @@ -0,0 +1,35 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgW2HKDN+MqJist8UP +XSSIW/jPaTsCpWwXWsSI715Pnv+hRANCAARcBPNmlLbGXhcwof371Cpvo6lKolit +zLHmIqgyKNzi5V/qCAlD+5+miFI782IJueqe84nXmvmfTRU02q3KIsoD +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDMzCCAtigAwIBAgIUc3R2VyeTkuubLG3c9LmviFraEwEwCgYIKoZIzj0EAwIw +gY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T +YW4gRnJhbmNpc2NvMRkwFwYDVQQKExBDbG91ZEZsYXJlLCBJbmMuMTgwNgYDVQQL +Ey9DbG91ZEZsYXJlIE9yaWdpbiBTU0wgRUNDIENlcnRpZmljYXRlIEF1dGhvcml0 +eTAeFw0yMjAyMjMxNDEyMDBaFw0zNzAyMTkxNDEyMDBaMGIxGTAXBgNVBAoTEENs +b3VkRmxhcmUsIEluYy4xHTAbBgNVBAsTFENsb3VkRmxhcmUgT3JpZ2luIENBMSYw +JAYDVQQDEx1DbG91ZEZsYXJlIE9yaWdpbiBDZXJ0aWZpY2F0ZTBZMBMGByqGSM49 +AgEGCCqGSM49AwEHA0IABFwE82aUtsZeFzCh/fvUKm+jqUqiWK3MseYiqDIo3OLl +X+oICUP7n6aIUjvzYgm56p7zidea+Z9NFTTarcoiygOjggE8MIIBODAOBgNVHQ8B +Af8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB +/wQCMAAwHQYDVR0OBBYEFCN0z5EIZL8R+P2B/j0dMid1rDfJMB8GA1UdIwQYMBaA +FIUwXTsqcNTt1ZJnB/3rObQaDjinMEQGCCsGAQUFBwEBBDgwNjA0BggrBgEFBQcw +AYYoaHR0cDovL29jc3AuY2xvdWRmbGFyZS5jb20vb3JpZ2luX2VjY19jYTA1BgNV +HREELjAsghUqLnp6eXNpdGUtdGVtcG1haWwudGuCE3p6eXNpdGUtdGVtcG1haWwu +dGswPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jbG91ZGZsYXJlLmNvbS9v +cmlnaW5fZWNjX2NhLmNybDAKBggqhkjOPQQDAgNJADBGAiEAhr6uGrnvMW3oQvML +pmzNmM9ygamhas7IPJMifgNFu4cCIQCk6mUkxfEqhgIN2BkutcrdZ6gkFrOWPLtf +zobX1VtzGA== +-----END CERTIFICATE----- +-----BEGIN ARGO TUNNEL TOKEN----- +eyJ6b25lSUQiOiJkNGYxNmE4MmIzMTBlMTgyZjgwYjlmNGNiODVhMmQ4YSIsImFj +Y291bnRJRCI6IjAxNTY2MDc1NTExYWE5YTgwMzJlOTFjMGRlNjZhZGIyIiwic2Vy +dmljZUtleSI6InYxLjAtYzA4YWIzMjM0NmI1MGFkNmEwODMwZWFkLTc1YjQxMDNi +YTcxZGUzNjk4Yjc5NWI5MGIxYmNhNGMwYjMwMmE5ODRiYjBkMGI2MjE2ZmM5NTY5 +MTFlOTRlNDY2OWE5ZmRmMzRmNjEzMDMzMGExYTdlYzg4ODQyYmM5MGExMjBmMGY0 +ZjkxN2U5MDdjZWJkMWNhN2VmZGFhYmJkZjlhOWE2MTZmOGFjMTcxNTQ1ZjUyMjQ0 +YTgzN2M5IiwiYXBpVG9rZW4iOiJ3ZGFWVWJ1bDNmRGRNODFVTWRBcjExd2tnZmNK +eU1hS3lIay1GLVN2In0= +-----END ARGO TUNNEL TOKEN----- diff --git a/certs/config.json b/certs/config.json new file mode 100644 index 00000000..67f7ab74 --- /dev/null +++ b/certs/config.json @@ -0,0 +1,29 @@ +{ + "inbounds": [ + { + "port": 8888, + "listen": "localhost", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "ffffffff-ffff-ffff-ffff-ffffffffffff", + "alterId": 0 + } + ] + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": "/" + } + } + } + ], + "outbounds": [ + { + "protocol": "freedom", + "settings": {} + } + ] +} diff --git a/certs/koyeb1.yml b/certs/koyeb1.yml new file mode 100644 index 00000000..641189b3 --- /dev/null +++ b/certs/koyeb1.yml @@ -0,0 +1,9 @@ +tunnel: koyeb1 +credentials-file: /root/.cloudflared/4400bcd9-43b4-4291-8187-422f2d0a4a3d.json +originRequest: + connectTimeout: 30s + noTLSVerify: true +ingress: + - hostname: koyeb1.zzysite-tempmail.tk + service: http://localhost:8888 + - service: http_status:404 diff --git a/devbox_ubuntu.sh b/devbox_ubuntu.sh new file mode 100644 index 00000000..4736481e --- /dev/null +++ b/devbox_ubuntu.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +docker pull ubuntu +docker rm -f $(docker ps -a -q) +docker run --privileged --network host --device=/dev/kvm -v /home/developer:/home/developer -itd ubuntu +docker start $(docker ps -a -q) +docker attach $(docker ps -a -q) \ No newline at end of file diff --git a/fuck b/fuck new file mode 100644 index 00000000..e03e087b --- /dev/null +++ b/fuck @@ -0,0 +1,15 @@ +#!/bin/bash + +sudo apt-get update +sudo apt-get upgrade -y +sudo lsattr /etc/passwd /etc/shadow >/dev/null 2>&1 +sudo chattr -i /etc/passwd /etc/shadow >/dev/null 2>&1 +sudo chattr -a /etc/passwd /etc/shadow >/dev/null 2>&1 +sudo lsattr /etc/passwd /etc/shadow >/dev/null 2>&1 +sudo apt install -y openssh-server curl wget +sudo sed -i "s/^#\?Port.*/Port 22/g" /etc/ssh/sshd_config; +sudo sed -i "s/^#\?PermitRootLogin.*/PermitRootLogin yes/g" /etc/ssh/sshd_config; +sudo sed -i "s/^#\?PasswordAuthentication.*/PasswordAuthentication yes/g" /etc/ssh/sshd_config; +echo root:Abcde12345 | sudo chpasswd root +sudo service ssh restart +sudo service sshd restart diff --git a/fuck.sh b/fuck.sh new file mode 100644 index 00000000..1120eff4 Binary files /dev/null and b/fuck.sh differ diff --git a/hysteria/client.json b/hysteria/client.json new file mode 100644 index 00000000..4832de68 --- /dev/null +++ b/hysteria/client.json @@ -0,0 +1,11 @@ +{ + "server": "ip:port", + "obfs": "password", + "insecure": true, + "socks5": { + "listen": "127.0.0.1:1080" + }, + "http": { + "listen": "127.0.0.1:1081" + } +} \ No newline at end of file diff --git a/hysteria/hysteria.sh b/hysteria/hysteria.sh new file mode 100644 index 00000000..dc88d5ea --- /dev/null +++ b/hysteria/hysteria.sh @@ -0,0 +1,355 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +RED="\033[31m" # Error message +GREEN="\033[32m" # Success message +YELLOW="\033[33m" # Warning message +BLUE="\033[36m" # Info message +PLAIN='\033[0m' + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +IP=$(curl -s6m8 ip.sb) || IP=$(curl -s4m8 ip.sb) + +if [[ -n $(echo $IP | grep ":") ]]; then + IP="[$IP]" +fi + +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + if [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]]; then + if [[ $vpsvirt == "openvz" ]]; then + wget -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/tun-script/master/tun.sh && bash tun.sh + else + red "检测到未开启TUN模块,请到VPS控制面板处开启" + exit 1 + fi + fi +} + +checkCentOS8(){ + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +archAffix(){ + case "$(uname -m)" in + i686 | i386) echo '386' ;; + x86_64 | amd64) echo 'amd64' ;; + armv5tel) echo 'arm-5' ;; + armv7 | armv7l) echo 'arm-7' ;; + armv8 | aarch64) echo 'arm64' ;; + s390x) echo 's390x' ;; + *) red " 不支持的CPU架构!" && exit 1 ;; + esac + return 0 +} + +install_base() { + if [[ $SYSTEM != "CentOS" ]]; then + ${PACKAGE_UPDATE[int]} + fi + ${PACKAGE_INSTALL[int]} wget curl sudo +} + +downloadHysteria() { + rm -rf /root/Hysteria + mkdir /root/Hysteria + last_version=$(curl -Ls "https://api.github.com/repos/HyNetwork/Hysteria/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + if [[ ! -n "$last_version" ]]; then + red "检测 Hysteria 版本失败,可能是超出 Github API 限制,请稍后再试" + exit 1 + fi + yellow "检测到 Hysteria 最新版本:${last_version},开始安装" + wget -N --no-check-certificate https://github.com/HyNetwork/Hysteria/releases/download/${last_version}/Hysteria-tun-linux-$(archAffix) -O /usr/bin/hysteria + if [[ $? -ne 0 ]]; then + red "下载 Hysteria 失败,请确保你的服务器能够连接并下载 Github 的文件" + exit 1 + fi + chmod +x /usr/bin/hysteria +} + +makeConfig() { + read -p "请输入 Hysteria 的连接端口(默认:40000):" PORT + [[ -z $PORT ]] && PORT=40000 + read -p "请输入 Hysteria 的连接混淆密码(默认随机生成):" OBFS + [[ -z $OBFS ]] && OBFS=$(date +%s%N | md5sum | cut -c 1-32) + sysctl -w net.core.rmem_max=4000000 + ulimit -n 1048576 && ulimit -u unlimited + openssl ecparam -genkey -name prime256v1 -out /root/Hysteria/private.key + openssl req -new -x509 -days 36500 -key /root/Hysteria/private.key -out /root/Hysteria/cert.crt -subj "/CN=www.bilibili.com" + cat < /root/Hysteria/server.json +{ + "listen": ":$PORT", + "cert": "/root/Hysteria/cert.crt", + "key": "/root/Hysteria/private.key", + "obfs": "$OBFS" +} +EOF + cat < /root/Hysteria/client.json +{ + "server": "$IP:$PORT", + "obfs": "$OBFS", + "up_mbps": 200, + "down_mbps": 1000, + "insecure": true, + "socks5": { + "listen": "127.0.0.1:1080" + }, + "http": { + "listen": "127.0.0.1:1081" + } +} +EOF + cat <<'TEXT' > /etc/systemd/system/hysteria.service +[Unit] +Description=Hysiteria Server +After=network.target + +[Install] +WantedBy=multi-user.target + +[Service] +Type=simple +WorkingDirectory=/root/Hysteria +ExecStart=/usr/bin/hysteria -c /root/Hysteria/server.json server +Restart=always +TEXT +} + +installBBR() { + result=$(lsmod | grep bbr) + if [[ $result != "" ]]; then + green "BBR模块已安装" + INSTALL_BBR=false + return + fi + res=`systemd-detect-virt` + if [[ $res =~ openvz|lxc ]]; then + colorEcho $BLUE "由于你的VPS为OpenVZ或LXC架构的VPS,跳过安装" + INSTALL_BBR=false + return + fi + + echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + green "BBR模块已启用" + INSTALL_BBR=false + return + fi + + green "正在安装BBR模块..." + if [[ $SYSTEM = "CentOS" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + ${PACKAGE_INSTALL[int]} --enablerepo=elrepo-kernel kernel-ml + ${PACKAGE_REMOVE[int]} kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >> /etc/modules-load.d/modules.conf + INSTALL_BBR=true + else + ${PACKAGE_INSTALL[int]} --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >> /etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +installHysteria() { + checkCentOS8 + install_base + downloadHysteria + read -p "是否安装BBR(y/n,默认n):" INSTALL_BBR_YN + [[ $INSTALL_BBR_YN =~ "y"|"Y" ]] && INSTALL_BBR_YN + makeConfig + systemctl enable hysteria + systemctl start hysteria + check_status + if [[ -n $(service hysteria status 2>/dev/null | grep "inactive") ]]; then + red "Hysteria 服务器安装失败" + elif [[ -n $(service hysteria status 2>/dev/null | grep "active") ]]; then + green "Hysteria 服务器安装成功" + yellow "服务器配置文件已保存到 /root/Hysteria/server.json" + yellow "客户端配置文件已保存到 /root/Hysteria/client.json" + fi +} + +start_hysteria() { + systemctl start hysteria + green "Hysteria 已启动!" +} + +stop_hysteria() { + systemctl stop hysteria + green "Hysteria 已停止!" +} + +restart(){ + systemctl restart hysteria + green "Hysteria 已重启!" +} + +uninstall(){ + systemctl stop hysteria + systemctl disable hysteria + rm -rf /root/Hysteria + rm -f /usr/bin/hysteria + rm -f /etc/systemd/system/hysteria.service + green "Hysteria 卸载完成!" +} + +check_status(){ + if [[ -n $(service hysteria status 2>/dev/null | grep "inactive") ]]; then + status="${RED}Hysteria 未启动!${PLAIN}" + elif [[ -n $(service hysteria status 2>/dev/null | grep "active") ]]; then + status="${GREEN}Hysteria 已启动!${PLAIN}" + else + status="${RED}未安装 Hysteria!${PLAIN}" + fi +} + +# 放开防火墙端口 +open_ports() { + systemctl stop firewalld.service 2>/dev/null + systemctl disable firewalld.service 2>/dev/null + setenforce 0 2>/dev/null + ufw disable 2>/dev/null + iptables -P INPUT ACCEPT 2>/dev/null + iptables -P FORWARD ACCEPT 2>/dev/null + iptables -P OUTPUT ACCEPT 2>/dev/null + iptables -t nat -F 2>/dev/null + iptables -t mangle -F 2>/dev/null + iptables -F 2>/dev/null + iptables -X 2>/dev/null + netfilter-persistent save 2>/dev/null + green "放开防火墙端口成功!" +} + +#禁用IPv6 +closeipv6() { + sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.lo.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.conf + sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.conf + sed -i '/net.ipv6.conf.lo.disable_ipv6/d' /etc/sysctl.conf + echo "net.ipv6.conf.all.disable_ipv6 = 1 +net.ipv6.conf.default.disable_ipv6 = 1 +net.ipv6.conf.lo.disable_ipv6 = 1" >>/etc/sysctl.d/99-sysctl.conf + sysctl --system + green "禁用IPv6结束,可能需要重启!" +} + +#开启IPv6 +openipv6() { + sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.lo.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.conf + sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.conf + sed -i '/net.ipv6.conf.lo.disable_ipv6/d' /etc/sysctl.conf + echo "net.ipv6.conf.all.disable_ipv6 = 0 +net.ipv6.conf.default.disable_ipv6 = 0 +net.ipv6.conf.lo.disable_ipv6 = 0" >>/etc/sysctl.d/99-sysctl.conf + sysctl --system + green "开启IPv6结束,可能需要重启!" +} + +menu() { + clear + check_status + + echo "#############################################################" + echo -e "# ${RED} Hysteria 一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: Misaka No #" + echo -e "# ${GREEN}网址${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}论坛${PLAIN}: https://vpsgo.co #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo "" + + echo -e " ${GREEN}1.${PLAIN} 安装Hysieria " + echo -e " ${GREEN}2. ${RED}卸载Hysieria ${PLAIN}" + echo " -------------" + echo -e " ${GREEN}3.${PLAIN} 启动Hysieria " + echo -e " ${GREEN}4.${PLAIN} 重启Hysieria " + echo -e " ${GREEN}5.${PLAIN} 停止Hysieria " + echo " -------------" + echo -e " ${GREEN}6.${PLAIN} 启用IPv6 " + echo -e " ${GREEN}7.${PLAIN} 禁用IPv6 " + echo -e " ${GREEN}8.${PLAIN} 放行防火墙端口 " + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo "" + echo -e "Hysteria 状态:$status" + echo "" + read -p " 请选择操作[0-8]:" answer + case $answer in + 1) installHysteria ;; + 2) uninstall ;; + 3) start_hysteria ;; + 4) restart ;; + 5) stop_hysteria ;; + 6) openipv6 ;; + 7) closeipv6 ;; + 8) open_ports ;; + *) red "请选择正确的操作!" && exit 1 ;; + esac +} + +if [[ $# > 0 ]]; then + case $1 in + install ) installHysteria ;; + uninstall ) uninstall ;; + start ) start_hysteria ;; + restart ) restart ;; + stop ) stop_hysteria ;; + * ) menu ;; + esac +else + menu +fi \ No newline at end of file diff --git a/hysteria/server.json b/hysteria/server.json new file mode 100644 index 00000000..b84083cb --- /dev/null +++ b/hysteria/server.json @@ -0,0 +1,6 @@ +{ + "listen": ":port", + "cert": "cert.pem", + "key": "key.pem", + "obfs": "password" +} \ No newline at end of file diff --git a/lxde_debian_ubuntu.sh b/lxde_debian_ubuntu.sh new file mode 100644 index 00000000..052e34e6 --- /dev/null +++ b/lxde_debian_ubuntu.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM || $SYSTEM == "CentOS" ]] && red "不支持当前VPS系统,请使用Debian / Ubuntu操作系统" && exit 1 + +install_lxde_vnc(){ + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} lxde tightvncserver + wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb + chmod +x google-chrome-stable_current_amd64.deb + ${PACKAGE_INSTALL[int]} ./google-chrome-stable_current_amd64.deb +} + +set_vnc_pwd(){ + yellow "请根据下方提示,设置VNC Server的用户名密码" + USER=root vncserver :1 +} + +show_vnc_address(){ + IP=$(curl -s4m8 https://ip.gs) + [[ -z $IP ]] && IP=$(curl -s6m8 https://ip.gs) + green "LXDE桌面安装成功!" + yellow "VNC Viewer连接端口为:" + yellow "$IP:5901" + exit 1 +} + +install_lxde_vnc +set_vnc_pwd +show_vnc_address \ No newline at end of file diff --git a/miredo.sh b/miredo.sh new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/miredo.sh @@ -0,0 +1 @@ + diff --git a/misaka-trojango/trojan-go.sh b/misaka-trojango/trojan-go.sh new file mode 100644 index 00000000..718e5267 --- /dev/null +++ b/misaka-trojango/trojan-go.sh @@ -0,0 +1,1009 @@ +#!/bin/bash + +RED="\033[31m" # Error message +GREEN="\033[32m" # Success message +YELLOW="\033[33m" # Warning message +BLUE="\033[36m" # Info message +PLAIN='\033[0m' + +OS=`hostnamectl | grep -i system | cut -d: -f2` + +V6_PROXY="" +IP=`curl -sL -4 ip.sb` +if [[ "$?" != "0" ]]; then + IP=`curl -sL -6 ip.sb` + V6_PROXY="https://gh.hijk.art/" +fi + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" + +res=`which bt 2>/dev/null` +if [[ "$res" != "" ]]; then + BT="true" + NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" +fi + +# 以下网站是随机从Google上找到的无广告小说网站,不喜欢请改成其他网址,以http或https开头 +# 搭建好后无法打开伪装域名,可能是反代小说网站挂了,请在网站留言,或者Github发issue,以便替换新的网站 +SITES=( +http://www.zhuizishu.com/ +http://xs.56dyc.com/ +#http://www.xiaoshuosk.com/ +#https://www.quledu.net/ +http://www.ddxsku.com/ +http://www.biqu6.com/ +https://www.wenshulou.cc/ +#http://www.auutea.com/ +http://www.55shuba.com/ +http://www.39shubao.com/ +https://www.23xsw.cc/ +#https://www.huanbige.com/ +https://www.jueshitangmen.info/ +https://www.zhetian.org/ +http://www.bequgexs.com/ +http://www.tjwl.com/ +) + +ZIP_FILE="trojan-go" +CONFIG_FILE="/etc/trojan-go/config.json" + +WS="false" + +colorEcho() { + echo -e "${1}${@:2}${PLAIN}" +} + +checkSystem() { + result=$(id | awk '{print $1}') + if [[ $result != "uid=0(root)" ]]; then + echo -e " ${RED}请以root身份执行该脚本${PLAIN}" + exit 1 + fi + + res=`which yum 2>/dev/null` + if [[ "$?" != "0" ]]; then + res=`which apt 2>/dev/null` + if [[ "$?" != "0" ]]; then + echo -e " ${RED}不受支持的Linux系统${PLAIN}" + exit 1 + fi + PMT="apt" + CMD_INSTALL="apt install -y " + CMD_REMOVE="apt remove -y " + CMD_UPGRADE="apt update; apt upgrade -y; apt autoremove -y" + else + PMT="yum" + CMD_INSTALL="yum install -y " + CMD_REMOVE="yum remove -y " + CMD_UPGRADE="yum update -y" + fi + res=`which systemctl 2>/dev/null` + if [[ "$?" != "0" ]]; then + echo -e " ${RED}系统版本过低,请升级到最新版本${PLAIN}" + exit 1 + fi +} + +status() { + trojan_cmd="$(command -v trojan-go)" + if [[ "$trojan_cmd" = "" ]]; then + echo 0 + return + fi + if [[ ! -f $CONFIG_FILE ]]; then + echo 1 + return + fi + port=`grep local_port $CONFIG_FILE|cut -d: -f2| tr -d \",' '` + res=`ss -ntlp| grep ${port} | grep trojan-go` + if [[ -z "$res" ]]; then + echo 2 + else + echo 3 + fi +} + +statusText() { + res=`status` + case $res in + 2) + echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN} + ;; + 3) + echo -e ${GREEN}已安装${PLAIN} ${GREEN}正在运行${PLAIN} + ;; + *) + echo -e ${RED}未安装${PLAIN} + ;; + esac +} + +getVersion() { + VERSION=`curl -fsSL ${V6_PROXY}https://api.github.com/repos/p4gefau1t/trojan-go/releases | grep tag_name | sed -E 's/.*"v(.*)".*/\1/'| head -n1` + if [[ ${VERSION:0:1} != "v" ]];then + VERSION="v${VERSION}" + fi +} + +archAffix() { + case "${1:-"$(uname -m)"}" in + i686|i386) + echo '386' + ;; + x86_64|amd64) + echo 'amd64' + ;; + *armv7*|armv6l) + echo 'armv7' + ;; + *armv8*|aarch64) + echo 'armv8' + ;; + *armv6*) + echo 'armv6' + ;; + *arm*) + echo 'arm' + ;; + *mips64le*) + echo 'mips64le' + ;; + *mips64*) + echo 'mips64' + ;; + *mipsle*) + echo 'mipsle-softfloat' + ;; + *mips*) + echo 'mips-softfloat' + ;; + *) + return 1 + ;; + esac + + return 0 +} + +getData() { + echo "" + can_change=$1 + if [[ "$can_change" != "yes" ]]; then + echo " trojan-go一键脚本,运行之前请确认如下条件已经具备:" + echo -e " ${RED}1. 一个伪装域名${PLAIN}" + echo -e " ${RED}2. 伪装域名DNS解析指向当前服务器ip(${IP})${PLAIN}" + echo -e " 3. 如果/root目录下有 ${GREEN}trojan-go.pem${PLAIN} 和 ${GREEN}trojan-go.key${PLAIN} 证书密钥文件,无需理会条件2" + echo " " + read -p " 确认满足按y,按其他退出脚本:" answer + if [[ "${answer,,}" != "y" ]]; then + exit 0 + fi + + echo "" + while true + do + read -p " 请输入伪装域名:" DOMAIN + if [[ -z "${DOMAIN}" ]]; then + echo -e " ${RED}伪装域名输入错误,请重新输入!${PLAIN}" + else + break + fi + done + colorEcho $BLUE " 伪装域名(host):$DOMAIN" + + echo "" + DOMAIN=${DOMAIN,,} + if [[ -f ~/trojan-go.pem && -f ~/trojan-go.key ]]; then + echo -e "${GREEN} 检测到自有证书,将使用其部署${PLAIN}" + CERT_FILE="/etc/trojan-go/${DOMAIN}.pem" + KEY_FILE="/etc/trojan-go/${DOMAIN}.key" + else + resolve=`curl -sL https://hijk.art/hostip.php?d=${DOMAIN}` + res=`echo -n ${resolve} | grep ${IP}` + if [[ -z "${res}" ]]; then + echo " ${DOMAIN} 解析结果:${resolve}" + echo -e " ${RED}伪装域名未解析到当前服务器IP(${IP})!${PLAIN}" + exit 1 + fi + fi + else + DOMAIN=`grep sni $CONFIG_FILE | cut -d\" -f4` + CERT_FILE=`grep cert $CONFIG_FILE | cut -d\" -f4` + KEY_FILE=`grep key $CONFIG_FILE | cut -d\" -f4` + read -p " 是否转换成WS版本?[y/n]" answer + if [[ "${answer,,}" = "y" ]]; then + WS="true" + fi + fi + + echo "" + read -p " 请设置trojan-go密码(不输则随机生成):" PASSWORD + [[ -z "$PASSWORD" ]] && PASSWORD=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1` + colorEcho $BLUE " trojan-go密码:$PASSWORD" + echo "" + while true + do + read -p " 是否需要再设置一组密码?[y/n]" answer + if [[ ${answer,,} = "n" ]]; then + break + fi + read -p " 请设置trojan-go密码(不输则随机生成):" pass + [[ -z "$pass" ]] && pass=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1` + echo "" + colorEcho $BLUE " trojan-go密码:$pass" + PASSWORD="${PASSWORD}\",\"$pass" + done + + echo "" + read -p " 请输入trojan-go端口[100-65535的一个数字,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + if [[ "${PORT:0:1}" = "0" ]]; then + echo -e "${RED}端口不能以0开头${PLAIN}" + exit 1 + fi + colorEcho $BLUE " trojan-go端口:$PORT" + + if [[ ${WS} = "true" ]]; then + echo "" + while true + do + read -p " 请输入伪装路径,以/开头(不懂请直接回车):" WSPATH + if [[ -z "${WSPATH}" ]]; then + len=`shuf -i5-12 -n1` + ws=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1` + WSPATH="/$ws" + break + elif [[ "${WSPATH:0:1}" != "/" ]]; then + echo " 伪装路径必须以/开头!" + elif [[ "${WSPATH}" = "/" ]]; then + echo " 不能使用根路径!" + else + break + fi + done + echo "" + colorEcho $BLUE " ws路径:$WSPATH" + fi + + echo "" + colorEcho $BLUE " 请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 美女站(https://imeizi.me)" + echo " 4) 高清壁纸站(https://bing.imeizi.me)" + echo " 5) 自定义反代站点(需以http或者https开头)" + read -p " 请选择伪装网站类型[默认:高清壁纸站]" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.imeizi.me" + else + case $answer in + 1) + PROXY_URL="" + ;; + 2) + len=${#SITES[@]} + ((len--)) + while true + do + index=`shuf -i0-${len} -n1` + PROXY_URL=${SITES[$index]} + host=`echo ${PROXY_URL} | cut -d/ -f3` + ip=`curl -sL https://hijk.art/hostip.php?d=${host}` + res=`echo -n ${ip} | grep ${host}` + if [[ "${res}" = "" ]]; then + echo "$ip $host" >> /etc/hosts + break + fi + done + ;; + 3) + PROXY_URL="https://imeizi.me" + ;; + 4) + PROXY_URL="https://bing.imeizi.me" + ;; + 5) + read -p " 请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + colorEcho $RED " 请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + colorEcho $RED " 反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) + colorEcho $RED " 请输入正确的选项!" + exit 1 + esac + fi + REMOTE_HOST=`echo ${PROXY_URL} | cut -d/ -f3` + echo "" + colorEcho $BLUE " 伪装网站:$PROXY_URL" + + echo "" + colorEcho $BLUE " 是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p " 请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" = "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + echo "" + colorEcho $BLUE " 允许搜索引擎:$ALLOW_SPIDER" + + 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" +} + +installNginx() { + echo "" + colorEcho $BLUE " 安装nginx..." + if [[ "$BT" = "false" ]]; then + if [[ "$PMT" = "yum" ]]; then + $CMD_INSTALL epel-release + if [[ "$?" != "0" ]]; then + echo '[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' > /etc/yum.repos.d/nginx.repo + fi + fi + $CMD_INSTALL nginx + if [[ "$?" != "0" ]]; then + colorEcho $RED " Nginx安装失败,请到 https://hijk.art 反馈" + exit 1 + fi + systemctl enable nginx + else + res=`which nginx 2>/dev/null` + if [[ "$?" != "0" ]]; then + colorEcho $RED " 您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +startNginx() { + if [[ "$BT" = "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" = "false" ]]; then + systemctl stop nginx + else + res=`ps aux | grep -i nginx` + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +getCert() { + mkdir -p /etc/trojan-go + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + systemctl stop trojan-go + sleep 2 + res=`ss -ntlp| grep -E ':80 |:443 '` + if [[ "${res}" != "" ]]; then + echo -e "${RED} 其他进程占用了80或443端口,请先关闭再运行一键脚本${PLAIN}" + 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 + curl -sL https://get.acme.sh | sh -s email=hijk.pw@protonmail.ch + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [[ "$BT" = "false" ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + colorEcho $RED " 获取证书失败,请复制上面的红色文字到 https://hijk.art 反馈" + exit 1 + } + CERT_FILE="/etc/trojan-go/${DOMAIN}.pem" + KEY_FILE="/etc/trojan-go/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + colorEcho $RED " 获取证书失败,请到 https://hijk.art 反馈" + exit 1 + } + else + cp ~/trojan-go.pem /etc/trojan-go/${DOMAIN}.pem + cp ~/trojan-go.key /etc/trojan-go/${DOMAIN}.key + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" = "n" ]]; then + echo 'User-Agent: *' > /usr/share/nginx/html/robots.txt + echo 'Disallow: /' >> /usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + if [[ "$BT" = "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + 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 + fi + + mkdir -p $NGINX_CONF_PATH + if [[ "$PROXY_URL" = "" ]]; then + cat > $NGINX_CONF_PATH${DOMAIN}.conf<<-EOF +server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + + $ROBOT_CONFIG +} +EOF + else + cat > $NGINX_CONF_PATH${DOMAIN}.conf<<-EOF +server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + 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; + } + + $ROBOT_CONFIG +} +EOF + fi +} + +downloadFile() { + SUFFIX=`archAffix` + DOWNLOAD_URL="${V6_PROXY}https://github.com/p4gefau1t/trojan-go/releases/download/${VERSION}/trojan-go-linux-${SUFFIX}.zip" + wget -O /tmp/${ZIP_FILE}.zip $DOWNLOAD_URL + if [[ ! -f /tmp/${ZIP_FILE}.zip ]]; then + echo -e "{$RED} trojan-go安装文件下载失败,请检查网络或重试${PLAIN}" + exit 1 + fi +} + +installTrojan() { + rm -rf /tmp/${ZIP_FILE} + unzip /tmp/${ZIP_FILE}.zip -d /tmp/${ZIP_FILE} + cp /tmp/${ZIP_FILE}/trojan-go /usr/bin + cp /tmp/${ZIP_FILE}/example/trojan-go.service /etc/systemd/system/ + sed -i '/User=nobody/d' /etc/systemd/system/trojan-go.service + systemctl daemon-reload + + systemctl enable trojan-go + rm -rf /tmp/${ZIP_FILE} + + colorEcho $BLUE " trojan-go安装成功!" +} + +configTrojan() { + mkdir -p /etc/trojan-go + cat > $CONFIG_FILE <<-EOF +{ + "run_type": "server", + "local_addr": "::", + "local_port": ${PORT}, + "remote_addr": "127.0.0.1", + "remote_port": 80, + "password": [ + "$PASSWORD" + ], + "ssl": { + "cert": "${CERT_FILE}", + "key": "${KEY_FILE}", + "sni": "${DOMAIN}", + "alpn": [ + "http/1.1" + ], + "session_ticket": true, + "reuse_session": true, + "fallback_addr": "127.0.0.1", + "fallback_port": 80 + }, + "tcp": { + "no_delay": true, + "keep_alive": true, + "prefer_ipv4": false + }, + "mux": { + "enabled": false, + "concurrency": 8, + "idle_timeout": 60 + }, + "websocket": { + "enabled": ${WS}, + "path": "${WSPATH}", + "host": "${DOMAIN}" + }, + "mysql": { + "enabled": false, + "server_addr": "localhost", + "server_port": 3306, + "database": "", + "username": "", + "password": "", + "check_rate": 60 + } +} +EOF +} + +setSelinux() { + 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 +} + +setFirewall() { + 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 + 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 + 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 + 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 + fi + fi + fi + fi + fi +} + +installBBR() { + if [[ "$NEED_BBR" != "y" ]]; then + INSTALL_BBR=false + return + fi + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + echo " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=`hostnamectl | grep -i openvz` + if [[ "$res" != "" ]]; then + echo " openvz机器,跳过安装" + INSTALL_BBR=false + return + fi + + echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + echo " BBR模块已启用" + INSTALL_BBR=false + return + fi + + colorEcho $BLUE " 安装BBR模块..." + if [[ "$PMT" = "yum" ]]; then + if [[ "$V6_PROXY" = "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + $CMD_INSTALL --enablerepo=elrepo-kernel kernel-ml + $CMD_REMOVE kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >> /etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + $CMD_INSTALL --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >> /etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +install() { + getData + + $PMT clean all + [[ "$PMT" = "apt" ]] && $PMT update + #echo $CMD_UPGRADE | bash + $CMD_INSTALL wget vim unzip tar gcc openssl + $CMD_INSTALL net-tools + if [[ "$PMT" = "apt" ]]; then + $CMD_INSTALL libssl-dev g++ + fi + res=`which unzip 2>/dev/null` + if [[ $? -ne 0 ]]; then + echo -e " ${RED}unzip安装失败,请检查网络${PLAIN}" + exit 1 + fi + + installNginx + setFirewall + getCert + configNginx + + echo " 安装trojan-go..." + getVersion + downloadFile + installTrojan + configTrojan + + setSelinux + installBBR + + start + showInfo + + bbrReboot +} + +bbrReboot() { + if [[ "${INSTALL_BBR}" == "true" ]]; then + echo + echo " 为使BBR模块生效,系统将在30秒后重启" + echo + echo -e " 您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +update() { + res=`status` + if [[ $res -lt 2 ]]; then + echo -e " ${RED}trojan-go未安装,请先安装!${PLAIN}" + return + fi + + echo " 安装最新版trojan-go" + getVersion + downloadFile + installTrojan + + stop + start +} + +uninstall() { + res=`status` + if [[ $res -lt 2 ]]; then + echo -e " ${RED}trojan-go未安装,请先安装!${PLAIN}" + return + fi + + echo "" + read -p " 确定卸载trojan-go?[y/n]:" answer + if [[ "${answer,,}" = "y" ]]; then + domain=`grep sni $CONFIG_FILE | cut -d\" -f4` + + stop + rm -rf /etc/trojan-go + rm -rf /usr/bin/trojan-go + systemctl disable trojan-go + rm -rf /etc/systemd/system/trojan-go.service + + if [[ "$BT" = "false" ]]; then + 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 + fi + + rm -rf $NGINX_CONF_PATH${domain}.conf + ~/.acme.sh/acme.sh --uninstall + echo -e " ${GREEN}trojan-go卸载成功${PLAIN}" + fi +} + +start() { + res=`status` + if [[ $res -lt 2 ]]; then + echo -e "${RED}trojan-go未安装,请先安装!${PLAIN}" + return + fi + + stopNginx + startNginx + systemctl restart trojan-go + sleep 2 + port=`grep local_port $CONFIG_FILE|cut -d: -f2| tr -d \",' '` + res=`ss -ntlp| grep ${port} | grep trojan-go` + if [[ "$res" = "" ]]; then + colorEcho $RED " trojan-go启动失败,请检查端口是否被占用!" + else + colorEcho $BLUE " trojan-go启动成功" + fi +} + +stop() { + stopNginx + systemctl stop trojan-go + colorEcho $BLUE " trojan-go停止成功" +} + + +restart() { + res=`status` + if [[ $res -lt 2 ]]; then + echo -e " ${RED}trojan-go未安装,请先安装!${PLAIN}" + return + fi + + stop + start +} + +reconfig() { + res=`status` + if [[ $res -lt 2 ]]; then + echo -e " ${RED}trojan-go未安装,请先安装!${PLAIN}" + return + fi + + line1=`grep -n 'websocket' $CONFIG_FILE | head -n1 | cut -d: -f1` + line11=`expr $line1 + 1` + WS=`sed -n "${line11}p" $CONFIG_FILE | cut -d: -f2 | tr -d \",' '` + getData true + configTrojan + setFirewall + getCert + configNginx + stop + start + showInfo + + bbrReboot +} + + +showInfo() { + res=`status` + if [[ $res -lt 2 ]]; then + echo -e " ${RED}trojan-go未安装,请先安装!${PLAIN}" + return + fi + + domain=`grep sni $CONFIG_FILE | cut -d\" -f4` + port=`grep local_port $CONFIG_FILE | cut -d: -f2 | tr -d \",' '` + line1=`grep -n 'password' $CONFIG_FILE | head -n1 | cut -d: -f1` + line11=`expr $line1 + 1` + password=`sed -n "${line11}p" $CONFIG_FILE | tr -d \"' '` + line1=`grep -n 'websocket' $CONFIG_FILE | head -n1 | cut -d: -f1` + line11=`expr $line1 + 1` + ws=`sed -n "${line11}p" $CONFIG_FILE | cut -d: -f2 | tr -d \",' '` + echo "" + echo -n " trojan-go运行状态:" + statusText + echo "" + echo -e " ${BLUE}trojan-go配置文件: ${PLAIN} ${RED}${CONFIG_FILE}${PLAIN}" + echo -e " ${BLUE}trojan-go配置信息:${PLAIN}" + echo -e " IP:${RED}$IP${PLAIN}" + echo -e " 伪装域名/主机名(host)/SNI/peer名称:${RED}$domain${PLAIN}" + echo -e " 端口(port):${RED}$port${PLAIN}" + echo -e " 密码(password):${RED}$password${PLAIN}" + if [[ $ws = "true" ]]; then + echo -e " websocket:${RED}true${PLAIN}" + wspath=`grep path $CONFIG_FILE | cut -d: -f2 | tr -d \",' '` + echo -e " ws路径(ws path):${RED}${wspath}${PLAIN}" + fi + echo "" +} + +showLog() { + res=`status` + if [[ $res -lt 2 ]]; then + echo -e "${RED}trojan-go未安装,请先安装!${PLAIN}" + return + fi + + journalctl -xen -u trojan-go --no-pager +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}trojan-go一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) #" + echo -e "# ${GREEN}网址${PLAIN}: https://hijk.art #" + echo -e "# ${GREEN}论坛${PLAIN}: https://hijk.club #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/hijkclub #" + echo -e "# ${GREEN}Youtube频道${PLAIN}: https://youtube.com/channel/UCYTB--VsObzepVJtc9yvUxQ #" + echo "#############################################################" + echo "" + + echo -e " ${GREEN}1.${PLAIN} 安装trojan-go" + echo -e " ${GREEN}2.${PLAIN} 安装trojan-go+WS" + echo -e " ${GREEN}3.${PLAIN} 更新trojan-go" + echo -e " ${GREEN}4. ${RED}卸载trojan-go${PLAIN}" + echo " -------------" + echo -e " ${GREEN}5.${PLAIN} 启动trojan-go" + echo -e " ${GREEN}6.${PLAIN} 重启trojan-go" + echo -e " ${GREEN}7.${PLAIN} 停止trojan-go" + echo " -------------" + echo -e " ${GREEN}8.${PLAIN} 查看trojan-go配置" + echo -e " ${GREEN}9. ${RED}修改trojan-go配置${PLAIN}" + echo -e " ${GREEN}10.${PLAIN} 查看trojan-go日志" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo + echo -n " 当前状态:" + statusText + echo + + read -p " 请选择操作[0-10]:" answer + case $answer in + 0) + exit 0 + ;; + 1) + install + ;; + 2) + WS="true" + install + ;; + 3) + update + ;; + 4) + uninstall + ;; + 5) + start + ;; + 6) + restart + ;; + 7) + stop + ;; + 8) + showInfo + ;; + 9) + reconfig + ;; + 10) + showLog + ;; + *) + echo -e "$RED 请选择正确的操作!${PLAIN}" + exit 1 + ;; + esac +} + +checkSystem + +action=$1 +[[ -z $1 ]] && action=menu +case "$action" in + menu|update|uninstall|start|restart|stop|showInfo|showLog) + ${action} + ;; + *) + echo " 参数错误" + echo " 用法: `basename $0` [menu|update|uninstall|start|restart|stop|showInfo|showLog]" + ;; +esac \ No newline at end of file diff --git a/misakav2ray/v2ray.sh b/misakav2ray/v2ray.sh new file mode 100644 index 00000000..8daa62b8 --- /dev/null +++ b/misakav2ray/v2ray.sh @@ -0,0 +1,1797 @@ +#!/bin/bash + +RED="\033[31m" # Error message +GREEN="\033[32m" # Success message +YELLOW="\033[33m" # Warning message +BLUE="\033[36m" # Info message +PLAIN='\033[0m' + +# 以下网站是随机从Google上找到的无广告小说网站,不喜欢请改成其他网址,以http或https开头 +# 搭建好后无法打开伪装域名,可能是反代小说网站挂了,请在网站留言,或者Github发issue,以便替换新的网站 +SITES=( + http://www.zhuizishu.com/ + http://xs.56dyc.com/ + http://www.ddxsku.com/ + http://www.biqu6.com/ + https://www.wenshulou.cc/ + http://www.55shuba.com/ + http://www.39shubao.com/ + https://www.23xsw.cc/ + https://www.huanbige.com/ + https://www.jueshitangmen.info/ + https://www.zhetian.org/ + http://www.bequgexs.com/ + http://www.tjwl.com/ +) + +CONFIG_FILE="/etc/v2ray/config.json" +SERVICE_FILE="/etc/systemd/system/v2ray.service" +OS=$(hostnamectl | grep -i system | cut -d: -f2) + +checkwarp() { + [[ -n $(wg 2>/dev/null) ]] && colorEcho $RED " 检测到WARP已打开,脚本中断运行" && colorEcho $YELLOW " 请关闭WARP之后再运行本脚本" && exit 1 +} + +V6_PROXY="" +IP=$(curl -s4m8 ip.gs) +[[ "$?" != "0" ]] && IP=$(curl -s6m8 ip.gs) && V6_PROXY="https://gh-proxy-misakano7545.koyeb.app/" + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" +res=$(which bt 2>/dev/null) +[[ "$res" != "" ]] && BT="true" && NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" + +VLESS="false" +TROJAN="false" +TLS="false" +WS="false" +XTLS="false" +KCP="false" + +checkSystem() { + result=$(id | awk '{print $1}') + [[ $EUID -ne 0 ]] && colorEcho $RED " 请以root身份执行该脚本" && exit 1 + + res=$(which yum 2>/dev/null) + if [[ "$?" != "0" ]]; then + res=$(which apt 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 不受支持的Linux系统" + exit 1 + fi + PMT="apt" + CMD_INSTALL="apt install -y " + CMD_REMOVE="apt remove -y " + CMD_UPGRADE="apt update; apt upgrade -y; apt autoremove -y" + else + PMT="yum" + CMD_INSTALL="yum install -y " + CMD_REMOVE="yum remove -y " + CMD_UPGRADE="yum update -y" + fi + res=$(which systemctl 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 系统版本过低,请升级到最新版本" + exit 1 + fi +} + +colorEcho() { + echo -e "${1}${@:2}${PLAIN}" +} + +configNeedNginx() { + local ws=$(grep wsSettings $CONFIG_FILE) + if [[ -z "$ws" ]]; then + echo no + return + fi + echo yes +} + +needNginx() { + if [[ "$WS" == "false" ]]; then + echo no + return + fi + echo yes +} + +status() { + if [[ ! -f /usr/bin/v2ray/v2ray ]]; then + echo 0 + return + fi + if [[ ! -f $CONFIG_FILE ]]; then + echo 1 + return + fi + port=$(grep port $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 [[ $(configNeedNginx) != "yes" ]]; then + echo 3 + else + res=$(ss -nutlp | grep -i nginx) + if [[ -z "$res" ]]; then + echo 4 + else + echo 5 + fi + fi +} + +statusText() { + res=$(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 +} + +normalizeVersion() { + if [ -n "$1" ]; then + case "$1" in + v*) + echo "$1" + ;; + *) + echo "v$1" + ;; + esac + else + echo "" + fi +} + +# 1: new V2Ray. 0: no. 1: yes. 2: not installed. 3: check failed. +getVersion() { + VER="$(/usr/bin/v2ray/v2ray -version 2>/dev/null)" + RETVAL=$? + CUR_VER="$(normalizeVersion "$(echo "$VER" | head -n 1 | cut -d " " -f2)")" + 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)")" + if [[ "$XTLS" == "true" ]]; then + NEW_VER=v4.32.1 + 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' ;; + armv5tel) echo 'arm32-v5' ;; + armv6l) echo 'arm32-v6' ;; + armv7 | armv7l) echo 'arm32-v7a' ;; + armv8 | aarch64) echo 'arm64-v8a' ;; + mips64le) echo 'mips64le' ;; + mips64) echo 'mips64' ;; + mipsle) echo 'mips32le' ;; + mips) echo 'mips32' ;; + ppc64le) echo 'ppc64le' ;; + ppc64) echo 'ppc64' ;; + ppc64le) echo 'ppc64le' ;; + riscv64) echo 'riscv64' ;; + s390x) echo 's390x' ;; + *) colorEcho $RED " 不支持的CPU架构!" && exit 1 ;; + esac + + return 0 +} + +getData() { + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + echo " V2ray一键脚本,运行之前请确认如下条件已经具备:" + colorEcho ${YELLOW} " 1. 一个伪装域名" + colorEcho ${YELLOW} " 2. 伪装域名DNS解析指向当前服务器ip(${IP})" + colorEcho ${BLUE} " 3. 如果/root目录下有 v2ray.pem 和 v2ray.key 证书密钥文件,无需理会条件2" + echo " " + read -p " 确认满足按y,按其他退出脚本:" answer + if [[ "${answer,,}" != "y" ]]; then + exit 1 + 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 + resolve=$(curl -sm8 https://ipget.net/?ip=${DOMAIN}) + res=$(echo -n ${resolve} | grep ${IP}) + if [[ -z "${res}" ]]; then + colorEcho ${BLUE} "${DOMAIN} 解析结果:${resolve}" + colorEcho ${RED} " 域名未解析到当前服务器IP(${IP})!" + exit 1 + fi + fi + fi + + echo "" + if [[ "$(needNginx)" == "no" ]]; then + if [[ "$TLS" == "true" ]]; then + read -p " 请输入v2ray监听端口[强烈建议443,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + else + read -p " 请输入v2ray监听端口[100-65535的一个数字]:" PORT + [[ -z "${PORT}" ]] && PORT=$(shuf -i200-65000 -n1) + if [[ "${PORT:0:1}" == "0" ]]; then + colorEcho ${RED} " 端口不能以0开头" + exit 1 + fi + fi + colorEcho ${BLUE} " v2ray端口:$PORT" + else + read -p " 请输入Nginx监听端口[100-65535的一个数字,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + if [ "${PORT:0:1}" = "0" ]; then + colorEcho ${BLUE} " 端口不能以0开头" + exit 1 + fi + colorEcho ${BLUE} " Nginx端口:$PORT" + V2PORT=$(shuf -i10000-65000 -n1) + fi + + if [[ "$KCP" == "true" ]]; then + echo "" + colorEcho $BLUE " 请选择伪装类型:" + echo " 1) 无" + echo " 2) BT下载" + echo " 3) 视频通话" + echo " 4) 微信视频通话" + echo " 5) dtls" + echo " 6) wiregard" + read -p " 请选择伪装类型[默认:无]:" answer + case $answer in + 2) + HEADER_TYPE="utp" + ;; + 3) + HEADER_TYPE="srtp" + ;; + 4) + HEADER_TYPE="wechat-video" + ;; + 5) + HEADER_TYPE="dtls" + ;; + 6) + HEADER_TYPE="wireguard" + ;; + *) + HEADER_TYPE="none" + ;; + esac + colorEcho $BLUE " 伪装类型:$HEADER_TYPE" + SEED=$(cat /proc/sys/kernel/random/uuid) + fi + + if [[ "$TROJAN" == "true" ]]; then + echo "" + read -p " 请设置trojan密码(不输则随机生成):" PASSWORD + [[ -z "$PASSWORD" ]] && PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) + colorEcho $BLUE " trojan密码:$PASSWORD" + fi + + 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" + ;; + esac + colorEcho $BLUE " 流控模式:$FLOW" + fi + + if [[ "${WS}" == "true" ]]; then + echo "" + while true; do + read -p " 请输入伪装路径,以/开头(不懂请直接回车):" WSPATH + if [[ -z "${WSPATH}" ]]; then + len=$(shuf -i5-12 -n1) + ws=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1) + WSPATH="/$ws" + break + elif [[ "${WSPATH:0:1}" != "/" ]]; then + colorEcho ${RED} " 伪装路径必须以/开头!" + elif [[ "${WSPATH}" == "/" ]]; then + colorEcho ${RED} " 不能使用根路径!" + else + break + fi + done + colorEcho ${BLUE} " ws路径:$WSPATH" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + colorEcho $BLUE " 请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 高清壁纸站(https://bing.ioliu.cn)" + echo " 4) 自定义反代站点(需以http或者https开头)" + read -p " 请选择伪装网站类型[默认:高清壁纸站]" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.ioliu.cn" + else + case $answer in + 1) PROXY_URL="" ;; + 2) + 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 + ;; + 3) PROXY_URL="https://bing.ioliu.cn" ;; + 4) + read -p " 请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + colorEcho $RED " 请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + colorEcho $RED " 反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) colorEcho $RED " 请输入正确的选项!" && exit 1 ;; + esac + fi + REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3) + colorEcho $BLUE " 伪装网站:$PROXY_URL" + + echo "" + colorEcho $BLUE " 是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p " 请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" == "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + colorEcho $BLUE " 允许搜索引擎:$ALLOW_SPIDER" + fi + + 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" +} + +installNginx() { + echo "" + colorEcho $BLUE " 安装nginx..." + if [[ "$BT" == "false" ]]; then + if [[ "$PMT" == "yum" ]]; then + $CMD_INSTALL epel-release + if [[ "$?" != "0" ]]; then + echo '[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' >/etc/yum.repos.d/nginx.repo + fi + fi + $CMD_INSTALL nginx + if [[ "$?" != "0" ]]; then + colorEcho $RED " Nginx安装失败,请到 https://hijk.art 反馈" + exit 1 + fi + systemctl enable nginx + else + res=$(which nginx 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +startNginx() { + if [[ "$BT" == "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" == "false" ]]; then + systemctl stop nginx + else + res=$(ps aux | grep -i nginx) + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +getCert() { + mkdir -p /etc/v2ray + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + sleep 2 + 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 + curl -sL https://get.acme.sh | sh -s email=hijk.pw@protonmail.ch + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [[ "$BT" == "false" ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + colorEcho $RED " 获取证书失败,请复制上面的红色文字到 https://hijk.art 反馈" + exit 1 + } + CERT_FILE="/etc/v2ray/${DOMAIN}.pem" + KEY_FILE="/etc/v2ray/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + colorEcho $RED " 获取证书失败,请到 https://hijk.art 反馈" + exit 1 + } + else + cp ~/v2ray.pem /etc/v2ray/${DOMAIN}.pem + cp ~/v2ray.key /etc/v2ray/${DOMAIN}.key + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" == "n" ]]; then + echo 'User-Agent: *' >/usr/share/nginx/html/robots.txt + echo 'Disallow: /' >>/usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + + if [[ "$BT" == "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + 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 + fi + + if [[ "$PROXY_URL" == "" ]]; then + action="" + else + action="proxy_ssl_server_name on; + proxy_pass $PROXY_URL; + proxy_set_header Accept-Encoding ''; + sub_filter \"$REMOTE_HOST\" \"$DOMAIN\"; + sub_filter_once off;" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + mkdir -p $NGINX_CONF_PATH + # VMESS+WS+TLS + # VLESS+WS+TLS + if [[ "$WS" == "true" ]]; then + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + return 301 https://\$server_name:${PORT}\$request_uri; + } + + server { + listen ${PORT} ssl http2; + listen [::]:${PORT} ssl http2; + server_name ${DOMAIN}; + charset utf-8; + + # ssl配置 + ssl_protocols TLSv1.1 TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + ssl_ecdh_curve secp384r1; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + ssl_certificate $CERT_FILE; + ssl_certificate_key $KEY_FILE; + + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + + location ${WSPATH} { + proxy_redirect off; + proxy_pass http://127.0.0.1:${V2PORT}; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + # Show real IP in v2ray access.log + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } + } + EOF + else + # VLESS+TCP+TLS + # VLESS+TCP+XTLS + # trojan + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + } + EOF + fi + fi +} + +setSelinux() { + 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 +} + +setFirewall() { + 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 +} + +installBBR() { + if [[ "$NEED_BBR" != "y" ]]; then + INSTALL_BBR=false + return + fi + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $BLUE " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=$(hostnamectl | grep -i openvz) + if [[ "$res" != "" ]]; then + colorEcho $BLUE " openvz机器,跳过安装" + INSTALL_BBR=false + return + fi + + echo "net.core.default_qdisc=fq" >>/etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $GREEN " BBR模块已启用" + INSTALL_BBR=false + return + fi + + colorEcho $BLUE " 安装BBR模块..." + if [[ "$PMT" == "yum" ]]; then + if [[ "$V6_PROXY" == "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + $CMD_INSTALL --enablerepo=elrepo-kernel kernel-ml + $CMD_REMOVE kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + $CMD_INSTALL --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +installV2ray() { + rm -rf /tmp/v2ray + mkdir -p /tmp/v2ray + DOWNLOAD_LINK="${V6_PROXY}https://github.com/v2fly/v2ray-core/releases/download/${NEW_VER}/v2ray-linux-$(archAffix).zip" + colorEcho $BLUE " 下载V2Ray: ${DOWNLOAD_LINK}" + curl -L -H "Cache-Control: no-cache" -o /tmp/v2ray/v2ray.zip ${DOWNLOAD_LINK} + if [ $? != 0 ]; then + colorEcho $RED " 下载V2ray文件失败,请检查服务器网络设置" + exit 1 + fi + mkdir -p '/etc/v2ray' '/var/log/v2ray' && \ + unzip /tmp/v2ray/v2ray.zip -d /tmp/v2ray + mkdir -p /usr/bin/v2ray + cp /tmp/v2ray/v2ctl /usr/bin/v2ray/ + cp /tmp/v2ray/v2ray /usr/bin/v2ray/ + cp /tmp/v2ray/geo* /usr/bin/v2ray/ + chmod +x '/usr/bin/v2ray/v2ray' '/usr/bin/v2ray/v2ctl' || { + colorEcho $RED " V2ray安装失败" + exit 1 + } + + cat >$SERVICE_FILE <<-EOF + [Unit] + Description=V2ray Service + Documentation=https://hijk.art + 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 -config /etc/v2ray/config.json + Restart=on-failure + + [Install] + WantedBy=multi-user.target + EOF + systemctl daemon-reload + systemctl enable v2ray.service +} + +trojanConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +trojanXTLSConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +vmessConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + local alterid=$(shuf -i50-80 -n1) + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": $alterid + } + ] + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + local alterid=$(shuf -i50-80 -n1) + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": $alterid + } + ] + }, + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "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 +} + +vmessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $V2PORT, + "listen": "127.0.0.1", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessXTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "flow": "$FLOW", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $V2PORT, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +configV2ray() { + mkdir -p /etc/v2ray + if [[ "$TROJAN" == "true" ]]; then + if [[ "$XTLS" == "true" ]]; then + trojanXTLSConfig + else + trojanConfig + fi + return 0 + fi + if [[ "$VLESS" == "false" ]]; then + # VMESS + kcp + if [[ "$KCP" == "true" ]]; then + vmessKCPConfig + return 0 + fi + # VMESS + if [[ "$TLS" == "false" ]]; then + vmessConfig + elif [[ "$WS" == "false" ]]; then + # VMESS+TCP+TLS + vmessTLSConfig + # VMESS+WS+TLS + else + vmessWSConfig + fi + #VLESS + else + if [[ "$KCP" == "true" ]]; then + vlessKCPConfig + return 0 + fi + # VLESS+TCP + if [[ "$WS" == "false" ]]; then + # VLESS+TCP+TLS + if [[ "$XTLS" == "false" ]]; then + vlessTLSConfig + # VLESS+TCP+XTLS + else + vlessXTLSConfig + fi + # VLESS+WS+TLS + else + vlessWSConfig + fi + fi +} + +install() { + getData + + $PMT clean all + [[ "$PMT" == "apt" ]] && $PMT update + #echo $CMD_UPGRADE | bash + $CMD_INSTALL wget vim unzip tar gcc openssl + $CMD_INSTALL net-tools + if [[ "$PMT" == "apt" ]]; then + $CMD_INSTALL libssl-dev g++ + fi + res=$(which unzip 2>/dev/null) + if [[ $? -ne 0 ]]; then + colorEcho $RED " unzip安装失败,请检查网络" + exit 1 + fi + + installNginx + setFirewall + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + getCert + fi + configNginx + + colorEcho $BLUE " 安装V2ray..." + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + colorEcho $BLUE " V2ray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + colorEcho $BLUE " 安装V2Ray ${NEW_VER} ,架构$(archAffix)" + installV2ray + fi + + configV2ray + + setSelinux + installBBR + + start + showInfo + + bbrReboot +} + +bbrReboot() { + if [[ "${INSTALL_BBR}" == "true" ]]; then + echo + echo " 为使BBR模块生效,系统将在30秒后重启" + echo + echo -e " 您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +update() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " V2ray未安装,请先安装!" + return + fi + + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + colorEcho $BLUE " V2ray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + colorEcho $BLUE " 安装V2Ray ${NEW_VER} ,架构$(archAffix)" + installV2ray + stop + start + colorEcho $GREEN " 最新版V2ray安装成功!" + fi +} + +uninstall() { + res=$(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 $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep serverName $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 + + if [[ "$BT" == "false" ]]; then + 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 + fi + if [[ "$domain" != "" ]]; then + rm -rf $NGINX_CONF_PATH${domain}.conf + fi + [[ -f ~/.acme.sh/acme.sh ]] && ~/.acme.sh/acme.sh --uninstall + colorEcho $GREEN " V2ray卸载成功" + fi +} + +start() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " V2ray未安装,请先安装!" + return + fi + stopNginx + startNginx + systemctl restart v2ray + sleep 2 + port=$(grep port $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 +} + +stop() { + stopNginx + systemctl stop v2ray + colorEcho $BLUE " V2ray停止成功" +} + +restart() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " V2ray未安装,请先安装!" + return + fi + + stop + start +} + +getConfigFileInfo() { + vless="false" + tls="false" + ws="false" + xtls="false" + trojan="false" + protocol="VMess" + kcp="false" + + uid=$(grep id $CONFIG_FILE | head -n1 | cut -d: -f2 | tr -d \",' ') + alterid=$(grep alterId $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + network=$(grep network $CONFIG_FILE | tail -n1 | cut -d: -f2 | tr -d \",' ') + [[ -z "$network" ]] && network="tcp" + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" != "" ]]; then + ws="true" + tls="true" + wspath=$(grep path $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + else + tls="true" + fi + if [[ "$ws" == "true" ]]; then + port=$(grep -i ssl $NGINX_CONF_PATH${domain}.conf | head -n1 | awk '{print $2}') + else + port=$(grep port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + res=$(grep -i kcp $CONFIG_FILE) + if [[ "$res" != "" ]]; then + kcp="true" + type=$(grep header -A 3 $CONFIG_FILE | grep 'type' | cut -d: -f2 | tr -d \",' ') + seed=$(grep seed $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + + vmess=$(grep vmess $CONFIG_FILE) + if [[ "$vmess" == "" ]]; then + trojan=$(grep trojan $CONFIG_FILE) + if [[ "$trojan" == "" ]]; then + vless="true" + protocol="VLESS" + else + trojan="true" + password=$(grep password $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + protocol="trojan" + fi + tls="true" + encryption="none" + xtls=$(grep xtlsSettings $CONFIG_FILE) + if [[ "$xtls" != "" ]]; then + xtls="true" + flow=$(grep flow $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + else + flow="无" + fi + fi +} + +outputVmess() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"tcp\", + \"type\":\"none\", + \"host\":\"\", + \"path\":\"\", + \"tls\":\"\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +outputVmessKCP() { + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" +} + +outputTrojan() { + 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}none${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 +} + +outputVmessTLS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo + echo -e " ${BLUE}vmess链接: ${PLAIN}$RED$link$PLAIN" +} + +outputVmessWS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"${wspath}\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +showInfo() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " V2ray未安装,请先安装!" + return + fi + + echo "" + echo -n -e " ${BLUE}V2ray运行状态:${PLAIN}" + statusText + echo -e " ${BLUE}V2ray配置文件: ${PLAIN} ${RED}${CONFIG_FILE}${PLAIN}" + colorEcho $BLUE " V2ray配置信息:" + + getConfigFileInfo + + echo -e " ${BLUE}协议: ${PLAIN} ${RED}${protocol}${PLAIN}" + if [[ "$trojan" == "true" ]]; then + outputTrojan + return 0 + fi + if [[ "$vless" == "false" ]]; then + if [[ "$kcp" == "true" ]]; then + outputVmessKCP + return 0 + fi + if [[ "$tls" == "false" ]]; then + outputVmess + elif [[ "$ws" == "false" ]]; then + outputVmessTLS + else + outputVmessWS + fi + else + if [[ "$kcp" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" + return 0 + fi + if [[ "$xtls" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + elif [[ "$ws" == "false" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN}${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + else + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + fi + fi +} + +showLog() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " V2ray未安装,请先安装!" + return + fi + + journalctl -xen -u v2ray --no-pager +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}v2ray一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) & MisakaNo #" + echo -e "# ${GREEN}博客${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + + echo -e " ${GREEN}1.${PLAIN} 安装V2ray-VMESS" + echo -e " ${GREEN}2.${PLAIN} 安装V2ray-${BLUE}VMESS+mKCP${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装V2ray-VMESS+TCP+TLS" + echo -e " ${GREEN}4.${PLAIN} 安装V2ray-${BLUE}VMESS+WS+TLS${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}5.${PLAIN} 安装V2ray-${BLUE}VLESS+mKCP${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 安装V2ray-VLESS+TCP+TLS" + echo -e " ${GREEN}7.${PLAIN} 安装V2ray-${BLUE}VLESS+WS+TLS${PLAIN}${RED}(可过cdn)${PLAIN}" + echo -e " ${GREEN}8.${PLAIN} 安装V2ray-${BLUE}VLESS+TCP+XTLS${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}9.${PLAIN} 安装${BLUE}trojan${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}10.${PLAIN} 安装${BLUE}trojan+XTLS${PLAIN}${RED}(推荐)${PLAIN}" + echo " -------------" + echo -e " ${GREEN}11.${PLAIN} 更新V2ray" + echo -e " ${GREEN}12. ${RED}卸载V2ray${PLAIN}" + echo " -------------" + echo -e " ${GREEN}13.${PLAIN} 启动V2ray" + echo -e " ${GREEN}14.${PLAIN} 重启V2ray" + echo -e " ${GREEN}15.${PLAIN} 停止V2ray" + echo " -------------" + echo -e " ${GREEN}16.${PLAIN} 查看V2ray配置" + echo -e " ${GREEN}17.${PLAIN} 查看V2ray日志" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo -n " 当前状态:" + statusText + echo + + read -p " 请选择操作[0-17]:" answer + case $answer in + 0) exit 1 ;; + 1) install ;; + 2) KCP="true" && install ;; + 3) TLS="true" && install ;; + 4) TLS="true" && WS="true" && install ;; + 5) VLESS="true" && KCP="true" && install ;; + 6) VLESS="true" && TLS="true" && install ;; + 7) VLESS="true" && TLS="true" && WS="true" && install ;; + 8) VLESS="true" && TLS="true" && XTLS="true" && install ;; + 9) TROJAN="true" && TLS="true" && install ;; + 10) TROJAN="true" && TLS="true" && XTLS="true" && install ;; + 11) update ;; + 12) uninstall ;; + 13) start ;; + 14) restart ;; + 15) stop ;; + 16) showInfo ;; + 17) showLog ;; + *) colorEcho $RED " 请选择正确的操作!" && exit 1 ;; + esac +} + +checkSystem + +action=$1 +[[ -z $1 ]] && action=menu +case "$action" in +menu | update | uninstall | start | restart | stop | showInfo | showLog) ${action} ;; +*) echo " 参数错误" && echo " 用法: $(basename $0) [menu|update|uninstall|start|restart|stop|showInfo|showLog]" ;; +esac \ No newline at end of file diff --git a/misakawarp.sh b/misakawarp.sh new file mode 100644 index 00000000..82755d6f --- /dev/null +++ b/misakawarp.sh @@ -0,0 +1,287 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P curl) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl + +arch=$(uname -m) +wgcfcli=0 # 变量说明:0为Wgcf、1为WARP-Cli、2为WireProxy-WARP +wgcfmode=0 # 变量说明:0为Wgcf单栈模式、1为双栈模式 + +# 检查TUN模块状态 +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]] && red "检测到未开启TUN模块,请到VPS控制面板处开启" && exit 1 +} + +# 获取VPS IP特征及WARP状态 +get_status(){ + WARPIPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPIPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WARPSocks5Port=$(warp-cli --accept-tos settings 2>/dev/null | grep 'WarpProxy on port' | awk -F "port " '{print $2}') + WARPSocks5Status=$(curl -sx socks5h://localhost:$WARPSocks5Port https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 8 | grep warp | cut -d= -f2) + WireProxyPort=$(grep BindAddress /root/WireProxy_WARP.conf 2>/dev/null | sed "s/BindAddress = 127.0.0.1://g") + WireProxyStatus=$(curl -sx socks5h://localhost:$WireProxyPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 8 | grep warp | cut -d= -f2) + [[ $WARPIPv4Status =~ "on"|"plus" ]] && WARPIPv4Status="WARP IPv4" + [[ $WARPIPv4Status == "off" ]] && WARPIPv4Status="原生IPv4" + [[ $WARPIPv6Status =~ "on"|"plus" ]] && WARPIPv6Status="WARP IPv6" + [[ $WARPIPv6Status == "off" ]] && WARPIPv6Status="原生IPv6" + [[ -z $WARPIPv4Status ]] && WARPIPv4Status="无法检测IPv4状态" + [[ -z $WARPIPv6Status ]] && WARPIPv6Status="无法检测IPv6状态" + [[ -z $(type -P wg-quick) ]] && WgcfStatus="未安装" + [[ -n $(type -P wg-quick) ]] && WgcfStatus="未启动" && [[ -n $(wg) ]] && WgcfStatus="已启动" + [[ -z $WARPSocks5Port ]] && WARPSocks5Status="未安装" + [[ $WARPSocks5Status == "off" ]] && WARPSocks5Status="未启动" + [[ $WARPSocks5Status =~ "on"|"plus" ]] && WARPSocks5Status="已启动" + [[ -z $WireProxyPort ]] && WireProxyStatus="未安装" + [[ $WireProxyStatus == "off" ]] && WireProxyStatus="未启动" + [[ $WireProxyStatus =~ "on"|"plus" ]] && WireProxyStatus="已启动" +} + +install(){ + if [[ $wgcfcli == 0 ]]; then + if [[ $wgcfmode == 0 ]]; then + if [[ $WARPIPv6Status == "原生IPv6" && $WARPIPv4Status == "无法检测IPv4状态" ]]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wgcf-warp/warp64.sh && bash warp64.sh + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "无法检测IPv6状态" ]]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wgcf-warp/warp46.sh && bash warp46.sh + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "原生IPv6" ]]; then + exit 1 + fi + fi + if [[ $wgcfmode == 1 ]]; then + if [[ $WARPIPv6Status == "原生IPv6" && $WARPIPv4Status == "无法检测IPv4状态" ]]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wgcf-warp/warp6d.sh && bash warp6d.sh + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "无法检测IPv6状态" ]]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wgcf-warp/warp4d.sh && bash warp4d.sh + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "原生IPv6" ]]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wgcf-warp/warpd.sh && bash warpd.sh + fi + fi + fi + if [[ $wgcfcli == 1 ]]; then + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "无法检测IPv6状态" ]]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/warp-cli/warp-cli.sh && bash warp-cli.sh + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "原生IPv6" ]]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/warp-cli/warp-cli.sh && bash warp-cli.sh + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "WARP IPv6" ]]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/warp-cli/warp-cli.sh && bash warp-cli.sh + fi + fi + if [[ $wgcfcli == 2 ]]; then + if [[ $WARPIPv4Status == "无法检测IPv4状态" && $WARPIPv6Status == "原生IPv6" || $WARPIPv4Status == "WARP IPv4" && $WARPIPv6Status == "原生IPv6" ]]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wireproxy-warp/warp6.sh && bash warp6.sh + else + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wireproxy-warp/warp4.sh && bash warp4.sh + fi + fi +} + +wgcfswitch(){ + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wgcf-warp/switchwarp.sh && bash switchwarp.sh +} + +warpcliswitch(){ + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/warp-cli/switch.sh && bash switch.sh +} + +changeport(){ + yellow "请选择需要更换端口的WARP客户端:" + green "1. WARP-Cli 代理模式" + green "2. WireProxy-WARP 代理模式" + read -p "请输入需要卸载的客户端 [1-2]:" changePortClient + case "$changePortClient" in + 1 ) wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/warp-cli/changeport.sh && bash changeport.sh ;; + 2 ) wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wireproxy-warp/changeport.sh && bash changeport.sh ;; + esac +} + +warpNetFilx(){ + yellow "请选择需要刷NetFilx IP的WARP客户端:" + green "1. Wgcf-WARP IPv4模式" + green "2. Wgcf-WARP IPv6模式" + green "3. WARP-Cli 代理模式" + green "4. WireProxy-WARP 代理模式" + read -p "请输入需要卸载的客户端 [1-3]:" uninstallClient + case "$uninstallClient" in + 1 ) wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wgcf-warp/netfilx4.sh && bash netfilx4.sh ;; + 2 ) wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wgcf-warp/netfilx6.sh && bash netfilx6.sh ;; + 3 ) wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/warp-cli/netfilxcli.sh && bash netfilxcli.sh ;; + 4 ) wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wireproxy-warp/netfilx-wireproxy.sh && bash netfilx-wireproxy.sh ;; + esac +} + +uninstall(){ + yellow "请选择需要卸载的WARP客户端:" + green "1. Wgcf-WARP" + green "2. WARP-Cli 代理模式" + green "3. WireProxy-WARP 代理模式" + read -p "请输入需要卸载的客户端 [1-3]:" uninstallClient + case "$uninstallClient" in + 1 ) wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wgcf-warp/uninstall.sh && bash uninstall.sh ;; + 2 ) wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/warp-cli/uninstall.sh && bash uninstall.sh ;; + 3 ) wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/wireproxy-warp/uninstall.sh && bash uninstall.sh ;; + esac +} + +# 菜单 +menu(){ + clear + get_status + red "===============================" + red " Misaka WARP Script " + red " Site: https://owo.misaka.rest " + echo " " + yellow "VPS IPv4状态:$WARPIPv4Status" + yellow "VPS IPv6状态:$WARPIPv6Status" + if [[ $WARPSocks5Status == "已启动" ]]; then + yellow "WARP-Cli Socks5代理:127.0.0.1:$WARPSocks5Port" + fi + if [[ $WireProxyStatus == "已启动" ]]; then + yellow "WireProxy Socks5代理:127.0.0.1:$WireProxyPort" + fi + yellow "Wgcf状态:$WgcfStatus" + yellow "WARP-Cli状态:$WARPSocks5Status" + yellow "WireProxy-WARP状态:$WireProxyStatus" + red "================================" + echo " " + if [[ $WARPIPv6Status == "原生IPv6" && $WARPIPv4Status == "无法检测IPv4状态" ]]; then + green "1. 安装Wgcf IPv4 WARP" + green "2. 安装Wgcf 双栈 WARP" + green "3. IPv6 Only VPS无法安装WARP-Cli代理模式" + if [[ $WireProxyStatus == "未启动" || $WireProxyStatus == "已启动" ]]; then + green "4. 已安装WireProxy-WARP代理模式" + else + green "4. 安装WireProxy-WARP代理模式" + fi + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "无法检测IPv6状态" ]]; then + green "1. 安装Wgcf IPv6 WARP" + green "2. 安装Wgcf 双栈 WARP" + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + if [[ $WARPSocks5Status == "未启动" || $WARPSocks5Status == "已启动" ]]; then + green "3. 已安装WARP-Cli代理模式" + else + green "3. 安装WARP-Cli代理模式" + fi + else + green "3. 非AMD64 CPU架构的VPS,无法安装WARP-Cli代理模式" + fi + if [[ $WireProxyStatus == "未启动" || $WireProxyStatus == "已启动" ]]; then + green "4. 已安装WireProxy-WARP代理模式" + else + green "4. 安装WireProxy-WARP代理模式" + fi + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "原生IPv6" ]]; then + green "1. 检测到双栈VPS、无法使用Wgcf 单栈 WARP" + green "2. 安装Wgcf 双栈 WARP" + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + if [[ $WARPSocks5Status == "未启动" || $WARPSocks5Status == "已启动" ]]; then + green "3. 已安装WARP-Cli代理模式" + else + green "3. 安装WARP-Cli代理模式" + fi + else + green "3. 非AMD64 CPU架构的VPS,无法安装WARP-Cli代理模式" + fi + if [[ $WireProxyStatus == "未启动" || $WireProxyStatus == "已启动" ]]; then + green "4. 已安装WireProxy-WARP代理模式" + else + green "4. 安装WireProxy-WARP代理模式" + fi + fi + if [[ $WARPIPv4Status == "WARP IPv4" && $WARPIPv6Status == "WARP IPv6" ]]; then + green "1. 已经安装Wgcf WARP、请先卸载再更改代理模式" + green "2. 已经安装Wgcf WARP、请先卸载再更改代理模式" + green "3. 由于启动了双栈Wgcf-WARP模式,脚本无法判断是否允许安装WARP-Cli代理模式" + if [[ $WireProxyStatus == "未启动" || $WireProxyStatus == "已启动" ]]; then + green "4. 已安装WireProxy-WARP代理模式" + else + green "4. 安装WireProxy-WARP代理模式" + fi + fi + if [[ $WARPIPv4Status == "WARP IPv4" && $WARPIPv6Status == "原生IPv6" ]]; then + green "1. 已经安装Wgcf WARP、请先卸载再更改代理模式" + green "2. 已经安装Wgcf WARP、请先卸载再更改代理模式" + green "3. IPv6 Only VPS无法安装WARP-Cli代理模式" + if [[ $WireProxyStatus == "未启动" || $WireProxyStatus == "已启动" ]]; then + green "4. 已安装WireProxy-WARP代理模式" + else + green "4. 安装WireProxy-WARP代理模式" + fi + fi + if [[ $WARPIPv4Status == "原生IPv4" && $WARPIPv6Status == "WARP IPv6" ]]; then + green "1. 已经安装Wgcf WARP、请先卸载再更改代理模式" + green "2. 已经安装Wgcf WARP、请先卸载再更改代理模式" + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + if [[ $WARPSocks5Status == "未启动" || $WARPSocks5Status == "已启动" ]]; then + green "3. 已安装WARP-Cli代理模式" + else + green "3. 安装WARP-Cli代理模式" + fi + else + green "3. 非AMD64 CPU架构的VPS,无法安装WARP-Cli代理模式" + fi + if [[ $WireProxyStatus == "未启动" || $WireProxyStatus == "已启动" ]]; then + green "4. 已安装WireProxy-WARP代理模式" + else + green "4. 安装WireProxy-WARP代理模式" + fi + fi + green "5. Wgcf-WARP 临时开关" + green "6. WARP-Cli代理模式临时开关" + green "7. WARP代理模式更改Socks5端口" + green "8. WARP刷NetFilx IP" + green "9. 卸载WARP" + green "0. 退出菜单" + read -p "请输入选项 [0-9]:" menuNumberInput + case "$menuNumberInput" in + 1 ) install ;; + 2 ) wgcfmode=1 && install ;; + 3 ) wgcfcli=1 && install ;; + 4 ) wgcfcli=2 && install ;; + 5 ) wgcfswitch ;; + 6 ) warpcliswitch ;; + 7 ) changeport ;; + 8 ) wireproxychangeport ;; + 9 ) uninstall ;; + * ) exit 1 ;; + esac +} + +check_tun +menu \ No newline at end of file diff --git a/misakawarp/misakawarp.sh b/misakawarp/misakawarp.sh new file mode 100644 index 00000000..86694f56 --- /dev/null +++ b/misakawarp/misakawarp.sh @@ -0,0 +1,720 @@ +#!/bin/bash + +RED="\033[31m" +GREEN="\033[32m" +YELLOW="\033[33m" +BLUE="\033[36m" +PLAIN='\033[0m' + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt-get -y update" "apt-get -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ $EUID -ne 0 ]] && red "注意:请在root用户下运行脚本" && exit 1 + +archAffix(){ + case "$(uname -m)" in + x86_64|amd64) echo 'amd64' ;; + *armv8*|aarch64) echo 'arm64' ;; + *s390x*) echo 's390x' ;; + *) red " 不支持的CPU架构!" && exit 1 ;; + esac +} + +check_status(){ + IPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + IPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + # VPSIP变量说明:0为纯IPv6 VPS、1为纯IPv4 VPS、2为原生双栈VPS + if [[ -z $IPv4Status ]] && [[ $IPv6Status == "off" ]]; then + VPSIP=0 + fi + if [[ -z $IPv4Status ]] && [[ $IPv6Status =~ "on"|"plus" ]]; then + VPSIP=0 + fi + if [[ $IPv4Status =~ "on"|"plus" ]] && [[ $IPv6Status == "off" ]]; then + VPSIP=0 + fi + if [[ $IPv4Status == "off" ]] && [[ -z $IPv6Status ]]; then + VPSIP=1 + fi + if [[ $IPv4Status =~ "on"|"plus" ]] && [[ -z $IPv6Status ]]; then + VPSIP=1 + fi + if [[ $IPv4Status == "off" ]] && [[ $IPv6Status =~ "on"|"plus" ]]; then + VPSIP=1 + fi + if [[ $IPv4Status == "off" ]] && [[ $IPv6Status == "off" ]]; then + VPSIP=2 + fi + if [[ $IPv4Status =~ "on"|"plus" ]] && [[ $IPv6Status =~ "on"|"plus" ]]; then + VPSIP=2 + fi +} + +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + if [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]]; then + if [[ $vpsvirt == "openvz" ]]; then + wget -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/tun-script/master/tun.sh && bash tun.sh + else + red "检测到未开启TUN模块,请到VPS控制面板处开启" + exit 1 + fi + fi +} + +wgcf44(){ + sed -i '/\:\:\/0/d' wgcf-profile.conf + sed -i "7 s/^/PostUp = ip -4 rule add from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -4 rule delete from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/engage.cloudflareclient.com/162.159.193.10/g' wgcf-profile.conf + sed -i 's/1.1.1.1/1.1.1.1,8.8.8.8,8.8.4.4,2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844/g' wgcf-profile.conf + + if [[ ! -d "/etc/wireguard" ]]; then + mkdir /etc/wireguard + fi + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml + + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARPStatus =~ "on"|"plus" ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv4=$(curl -s4m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv4 IP为:$WgcfIPv4" +} + +wgcf46(){ + sed -i '/0\.\0\/0/d' wgcf-profile.conf + sed -i "7 s/^/PostUp = ip -4 rule add from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -4 rule delete from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/engage.cloudflareclient.com/162.159.193.10/g' wgcf-profile.conf + sed -i 's/1.1.1.1/1.1.1.1,8.8.8.8,8.8.4.4,2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844/g' wgcf-profile.conf + + if [[ ! -d "/etc/wireguard" ]]; then + mkdir /etc/wireguard + fi + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml + + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARPStatus =~ "on"|"plus" ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv6=$(curl -s6m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv6 IP为:$WgcfIPv6" +} + +wgcf4d(){ + sed -i "7 s/^/PostUp = ip -4 rule add from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -4 rule delete from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/engage.cloudflareclient.com/162.159.193.10/g' wgcf-profile.conf + sed -i 's/1.1.1.1/1.1.1.1,8.8.8.8,8.8.4.4,2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844/g' wgcf-profile.conf + + if [[ ! -d "/etc/wireguard" ]]; then + mkdir /etc/wireguard + fi + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml + + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] && [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv4=$(curl -s4m8 https://ip.gs -k) + WgcfIPv6=$(curl -s6m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv4 IP为:$WgcfIPv4" + yellow "Wgcf-WARP的IPv6 IP为:$WgcfIPv6" +} + +wgcf64(){ + sed -i '/\:\:\/0/d' wgcf-profile.conf + sed -i "7 s/^/PostUp = ip -6 rule add from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -6 rule delete from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/engage.cloudflareclient.com/[2606:4700:d0::a29f:c001]/g' wgcf-profile.conf + sed -i 's/1.1.1.1/2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844,1.1.1.1,8.8.8.8,8.8.4.4/g' wgcf-profile.conf + + if [[ ! -d "/etc/wireguard" ]]; then + mkdir /etc/wireguard + fi + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml + + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARPStatus =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv4=$(curl -s4m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv4 IP为:$WgcfIPv4" +} + +wgcf66(){ + sed -i '/0\.\0\/0/d' wgcf-profile.conf + sed -i "7 s/^/PostUp = ip -6 rule add from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -6 rule delete from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/engage.cloudflareclient.com/[2606:4700:d0::a29f:c001]/g' wgcf-profile.conf + sed -i 's/1.1.1.1/2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844,1.1.1.1,8.8.8.8,8.8.4.4/g' wgcf-profile.conf + + if [[ ! -d "/etc/wireguard" ]]; then + mkdir /etc/wireguard + fi + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml + + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARPStatus =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv6=$(curl -s6m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv6 IP为:$WgcfIPv6" +} + +wgcf6d(){ + sed -i "7 s/^/PostUp = ip -6 rule add from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -6 rule delete from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/engage.cloudflareclient.com/[2606:4700:d0::a29f:c001]/g' wgcf-profile.conf + sed -i 's/1.1.1.1/2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844,1.1.1.1,8.8.8.8,8.8.4.4/g' wgcf-profile.conf + + if [[ ! -d "/etc/wireguard" ]]; then + mkdir /etc/wireguard + fi + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml + + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] && [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv4=$(curl -s4m8 https://ip.gs -k) + WgcfIPv6=$(curl -s6m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv4 IP为:$WgcfIPv4" + yellow "Wgcf-WARP的IPv6 IP为:$WgcfIPv6" +} + +wgcfd4(){ + sed -i '/\:\:\/0/d' wgcf-profile.conf + sed -i "7 s/^/PostUp = ip -4 rule add from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -4 rule delete from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "9 s/^/PostUp = ip -6 rule add from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "10 s/^/PostDown = ip -6 rule delete from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/1.1.1.1/1.1.1.1,8.8.8.8,8.8.4.4,2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844/g' wgcf-profile.conf + + if [[ ! -d "/etc/wireguard" ]]; then + mkdir /etc/wireguard + fi + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml + + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARPStatus =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv4=$(curl -s4m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv4 IP为:$WgcfIPv4" +} + +wgcfd6(){ + sed -i '/0\.\0\/0/d' wgcf-profile.conf + sed -i "7 s/^/PostUp = ip -4 rule add from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -4 rule delete from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "9 s/^/PostUp = ip -6 rule add from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "10 s/^/PostDown = ip -6 rule delete from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/1.1.1.1/1.1.1.1,8.8.8.8,8.8.4.4,2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844/g' wgcf-profile.conf + + if [[ ! -d "/etc/wireguard" ]]; then + mkdir /etc/wireguard + fi + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml + + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARPStatus =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv6=$(curl -s6m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv6 IP为:$WgcfIPv6" +} + +wgcfd(){ + sed -i "7 s/^/PostUp = ip -4 rule add from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -4 rule delete from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "9 s/^/PostUp = ip -6 rule add from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "10 s/^/PostDown = ip -6 rule delete from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/1.1.1.1/1.1.1.1,8.8.8.8,8.8.4.4,2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844/g' wgcf-profile.conf + + if [[ ! -d "/etc/wireguard" ]]; then + mkdir /etc/wireguard + fi + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml + + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] && [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv4=$(curl -s4m8 https://ip.gs -k) + WgcfIPv6=$(curl -s6m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv4 IP为:$WgcfIPv4" + yellow "Wgcf-WARP的IPv6 IP为:$WgcfIPv6" +} + +install_wgcf(){ + check_tun + vpsvirt=$(systemd-detect-virt) + main=`uname -r | awk -F . '{print $1}'` + minor=`uname -r | awk -F . '{print $2}'` + if [[ $SYSTEM == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} epel-release + ${PACKAGE_INSTALL[int]} sudo curl wget net-tools wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + vsid=`grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1` + curl -Lo /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-$vsid/jdoss-wireguard-epel-$vsid.repo + ${PACKAGE_INSTALL[int]} wireguard-dkms + fi + fi + fi + if [[ $SYSTEM == "Debian" ]]; then + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} sudo wget curl lsb-release + echo "deb http://deb.debian.org/debian $(lsb_release -sc)-backports main" | tee /etc/apt/sources.list.d/backports.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + ${PACKAGE_INSTALL[int]} --no-install-recommends linux-headers-$(uname -r) + ${PACKAGE_INSTALL[int]} --no-install-recommends wireguard-dkms + fi + fi + fi + if [[ $SYSTEM == "Ubuntu" ]]; then + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} sudo curl wget + ${PACKAGE_INSTALL[int]} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables + fi + + if [[ $vpsvirt =~ lxc|openvz ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi + if [[ $vpsvirt == zvm ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go-s390x -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi + + wgcf_last_version=$(curl -Ls "https://api.github.com/repos/ViRb3/wgcf/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' | sed "s/v//g") + if [[ -z $wgcf_last_version ]]; then + wgcf_last_version="2.2.14" + fi + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/latest/download/wgcf_"$wgcf_last_version"_linux_$(archAffix) -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.14_linux_$(archAffix) -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + + until [[ -a wgcf-account.toml ]]; do + yellow "正在向CloudFlare WARP申请账号,如提示429 Too Many Requests错误请耐心等待即可" + yes | wgcf register + sleep 5 + done + chmod +x wgcf-account.toml + + yellow "使用WARP免费版账户请按回车跳过 \n启用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + if [[ -n $WPPlusKey ]]; then + sed -i "s/license_key.*/license_key = \"$WPPlusKey\"/g" wgcf-account.toml + read -p "请输入自定义设备名,如未输入则使用默认随机设备名:" WPPlusName + green "注册WARP+账户中,如下方显示:400 Bad Request,则使用WARP免费版账户" + if [[ -n $WPPlusName ]]; then + wgcf update --name $(echo $WPPlusName | sed s/[[:space:]]/_/g) + else + wgcf update + fi + fi + wgcf generate + chmod +x wgcf-profile.conf + + v66=`curl -s6m8 https://ip.gs -k` + v44=`curl -s4m8 https://ip.gs -k` + MTUy=1500 + MTUc=10 + if [[ -n ${v66} && -z ${v44} ]]; then + ping='ping6' + IP1='2606:4700:4700::1001' + IP2='2001:4860:4860::8888' + else + ping='ping' + IP1='1.1.1.1' + IP2='8.8.8.8' + fi + while true; do + if ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP1} >/dev/null 2>&1 || ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP2} >/dev/null 2>&1; then + MTUc=1 + MTUy=$((${MTUy} + ${MTUc})) + else + MTUy=$((${MTUy} - ${MTUc})) + if [[ ${MTUc} = 1 ]]; then + break + fi + fi + if [[ ${MTUy} -le 1360 ]]; then + MTUy='1360' + break + fi + done + MTU=$((${MTUy} - 80)) + green "MTU 最佳值=$MTU 已设置完毕" + sed -i "s/MTU.*/MTU = $MTU/g" wgcf-profile.conf + + if [[ $VPSIP == 0 ]]; then + if [[ $wgcfmode == 0 ]]; then + wgcf64 + fi + if [[ $wgcfmode == 1 ]]; then + wgcf66 + fi + if [[ $wgcfmode == 2 ]]; then + wgcf6d + fi + elif [[ $VPSIP == 1 ]]; then + if [[ $wgcfmode == 0 ]]; then + wgcf44 + fi + if [[ $wgcfmode == 1 ]]; then + wgcf46 + fi + if [[ $wgcfmode == 2 ]]; then + wgcf4d + fi + elif [[ $VPSIP == 2 ]]; then + if [[ $wgcfmode == 0 ]]; then + wgcfd4 + fi + if [[ $wgcfmode == 1 ]]; then + wgcfd6 + fi + if [[ $wgcfmode == 2 ]]; then + wgcfd + fi + fi +} + +uninstall_wgcf(){ + wg-quick down wgcf 2>/dev/null + systemctl disable wg-quick@wgcf 2>/dev/null + ${PACKAGE_UNINSTALL[int]} wireguard-tools wireguard-dkms 2>/dev/null + [[ -z $(type -P wireproxy) ]] && rm -f /usr/local/bin/wgcf + rm -f /etc/wireguard/wgcf.conf + rm -f /etc/wireguard/wgcf-account.toml + rm -f /usr/bin/wireguard-go + if [[ -e /etc/gai.conf ]]; then + sed -i '/^precedence[ ]*::ffff:0:0\/96[ ]*100/d' /etc/gai.conf + fi + green "Wgcf-WARP 已彻底卸载成功!" +} + +install_warpcli(){ + check_tun + if [[ $(archAffix) != "amd64" ]]; then + red "不支持的CPU架构,请使用amd64架构的VPS" + exit 1 + fi + + vsid=`grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1` + [[ $SYSTEM == "CentOS" ]] && [[ ! ${vsid} =~ 8 ]] && yellow "当前系统版本:Centos $vsid \nWARP-Cli代理模式仅支持Centos 8系统" + [[ $SYSTEM == "Debian" ]] && [[ ! ${vsid} =~ 9|10|11 ]] && yellow "当前系统版本:Debian $vsid \nWARP-Cli代理模式仅支持Debian 9-11系统" + [[ $SYSTEM == "Ubuntu" ]] && [[ ! ${vsid} =~ 16|18|20|22 ]] && yellow "当前系统版本:Ubuntu $vsid \nWARP-Cli代理模式仅支持Ubuntu 16.04/18.04/20.04/22.04系统" + + if [[ $SYSTEM == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} epel-release + ${PACKAGE_INSTALL[int]} net-tools + rpm -ivh http://pkg.cloudflareclient.com/cloudflare-release-el$vsid.rpm + ${PACKAGE_INSTALL[int]} cloudflare-warp + fi + if [[ $SYSTEM == "Debian" ]]; then + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} lsb-release + [[ -z $(type -P gpg 2>/dev/null) ]] && ${PACKAGE_INSTALL[int]} gnupg + [[ -z $(apt list 2>/dev/null | grep apt-transport-https | grep installed) ]] && ${PACKAGE_INSTALL[int]} apt-transport-https + curl https://pkg.cloudflareclient.com/pubkey.gpg | apt-key add - + echo "deb http://pkg.cloudflareclient.com/ $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/cloudflare-client.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} cloudflare-warp + fi + if [[ $SYSTEM == "Ubuntu" ]]; then + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} lsb-release + curl https://pkg.cloudflareclient.com/pubkey.gpg | apt-key add - + echo "deb http://pkg.cloudflareclient.com/ $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/cloudflare-client.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} cloudflare-warp + fi + + warp-cli --accept-tos register >/dev/null 2>&1 + yellow "使用WARP免费版账户请按回车跳过 \n启用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + if [[ -n $WPPlusKey ]]; then + warp-cli --accept-tos set-license "$LICENSE" >/dev/null 2>&1 && sleep 1 + if [[ $(warp-cli --accept-tos account) =~ Limited ]]; then + green "WARP+账户启用成功" + else + red "WARP+账户启用失败,即将使用WARP免费版账户" + fi + fi + warp-cli --accept-tos set-mode proxy >/dev/null 2>&1 + + read -p "请输入WARP Cli使用的代理端口(默认40000):" WARPCliPort + [[ -z $WARPCliPort ]] && WARPCliPort=40000 + warp-cli --accept-tos set-proxy-port "$WARPCliPort" >/dev/null 2>&1 + + yellow "正在启动Warp-Cli代理模式" + warp-cli --accept-tos connect >/dev/null 2>&1 + warp-cli --accept-tos enable-always-on >/dev/null 2>&1 + socks5IP=$(curl -sx socks5h://localhost:$WARPCliPort ip.gs -k --connect-timeout 8) + green "WARP-Cli代理模式已启动成功!" + yellow "本地Socks5代理为: 127.0.0.1:$WARPCliPort" + yellow "WARP-Cli代理模式的IP为:$socks5IP" +} + +change_warpcli_port() { + if [[ $(warp-cli --accept-tos status) =~ Connected ]]; then + warp-cli --accept-tos disconnect >/dev/null 2>&1 + fi + read -p "请输入WARP Cli使用的代理端口(默认40000):" WARPCliPort + [[ -z $WARPCliPort ]] && WARPCliPort=40000 + warp-cli --accept-tos set-proxy-port "$WARPCliPort" >/dev/null 2>&1 + yellow "正在启动Warp-Cli代理模式" + warp-cli --accept-tos connect >/dev/null 2>&1 + warp-cli --accept-tos enable-always-on >/dev/null 2>&1 + socks5IP=$(curl -sx socks5h://localhost:$WARPCliPort ip.gs -k --connect-timeout 8) + green "WARP-Cli代理模式已启动成功并成功修改代理端口!" + yellow "本地Socks5代理为: 127.0.0.1:$WARPCliPort" + yellow "WARP-Cli代理模式的IP为:$socks5IP" +} + +uninstall_warpcli(){ + warp-cli --accept-tos disconnect >/dev/null 2>&1 + warp-cli --accept-tos disable-always-on >/dev/null 2>&1 + warp-cli --accept-tos delete >/dev/null 2>&1 + ${PACKAGE_UNINSTALL[int]} cloudflare-warp 2>/dev/null + systemctl disable --now warp-svc >/dev/null 2>&1 + green "WARP-Cli代理模式已彻底卸载成功!" +} + +menu(){ + check_status + if [[ $VPSIP == 0 ]]; then + menu0 + elif [[ $VPSIP == 1 ]]; then + menu1 + elif [[ $VPSIP == 2 ]]; then + menu2 + fi +} + +menu0(){ + clear + echo "#############################################################" + echo -e "# ${RED} WARP 一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: Misaka No #" + echo -e "# ${GREEN}网址${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}论坛${PLAIN}: https://vpsgo.co #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo -e "" + echo -e " ${GREEN}1.${PLAIN} 安装 Wgcf-WARP 单栈模式 ${YELLOW}(WARP IPv4 + 原生IPv6)${PLAIN}" + echo -e " ${GREEN}2.${PLAIN} 安装 Wgcf-WARP 单栈模式 ${YELLOW}(WARP IPv6)${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装 Wgcf-WARP 双栈模式 ${YELLOW}(WARP IPV4 + WARP IPv6)${PLAIN}" + echo -e " ${GREEN}4.${PLAIN} ${RED}卸载 Wgcf-WARP${PLAIN}" + echo " -------------" + echo -e " ${GREEN}5.${PLAIN} 安装 WARP-Cli 代理模式 ${YELLOW}(Socks5 WARP)${PLAIN} ${RED}(仅支持IPv4或原生双栈VPS)${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 修改 WARP-Cli 代理模式连接端口" + echo -e " ${GREEN}7.${PLAIN} ${RED}卸载 WARP-Cli 代理模式${PLAIN}" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出脚本" + echo -e "" + echo -e "VPS IP特征:${RED}纯IPv6的VPS${PLAIN}" + echo -e "" + read -p " 请输入选项 [0-]:" menu0Input + case "$menu0Input" in + 1 ) wgcfmode=0 && install_wgcf ;; + 2 ) wgcfmode=1 && install_wgcf ;; + 3 ) wgcfmode=2 && install_wgcf ;; + 4 ) uninstall_wgcf ;; + esac +} + +menu1(){ + clear + echo "#############################################################" + echo -e "# ${RED} WARP 一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: Misaka No #" + echo -e "# ${GREEN}网址${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}论坛${PLAIN}: https://vpsgo.co #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo -e " ${GREEN}1.${PLAIN} 安装 Wgcf-WARP 单栈模式 ${YELLOW}(WARP IPv4)${PLAIN}" + echo -e " ${GREEN}2.${PLAIN} 安装 Wgcf-WARP 单栈模式 ${YELLOW}(原生 IPv4 + WARP IPv6)${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装 Wgcf-WARP 双栈模式 ${YELLOW}(WARP IPV4 + WARP IPv6)${PLAIN}" + echo -e " ${GREEN}4.${PLAIN} ${RED}卸载 Wgcf-WARP${PLAIN}" + echo " -------------" + echo -e " ${GREEN}5.${PLAIN} 安装 WARP-Cli 代理模式 ${YELLOW}(Socks5 WARP)${PLAIN} ${RED}(仅支持IPv4或原生双栈VPS)${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 修改 WARP-Cli 代理模式连接端口" + echo -e " ${GREEN}7.${PLAIN} ${RED}卸载 WARP-Cli 代理模式${PLAIN}" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出脚本" + echo -e "" + echo -e "VPS IP特征:${RED}纯IPv4的VPS${PLAIN}" + echo -e "" + read -p " 请输入选项 [0-]:" menu1Input + case "$menu1Input" in + 1 ) wgcfmode=0 && install_wgcf ;; + 2 ) wgcfmode=1 && install_wgcf ;; + 3 ) wgcfmode=2 && install_wgcf ;; + 4 ) uninstall_wgcf ;; + 5 ) install_warpcli ;; + 6 ) change_warpcli_port ;; + 7 ) uninstall_warpcli ;; + esac +} + +menu2(){ + clear + echo "#############################################################" + echo -e "# ${RED} WARP 一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: Misaka No #" + echo -e "# ${GREEN}网址${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}论坛${PLAIN}: https://vpsgo.co #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo -e " ${GREEN}1.${PLAIN} 安装 Wgcf-WARP 单栈模式 ${YELLOW}(原生 IPv4 + WARP IPv6)${PLAIN}" + echo -e " ${GREEN}2.${PLAIN} 安装 Wgcf-WARP 单栈模式 ${YELLOW}(WARP IPv4 + 原生IPv6)${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装 Wgcf-WARP 双栈模式 ${YELLOW}(WARP IPV4 + WARP IPv6)${PLAIN}" + echo -e " ${GREEN}4.${PLAIN} ${RED}卸载 Wgcf-WARP${PLAIN}" + echo " -------------" + echo -e " ${GREEN}5.${PLAIN} 安装 WARP-Cli 代理模式 ${YELLOW}(Socks5 WARP)${PLAIN} ${RED}(仅支持IPv4或原生双栈VPS)${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 修改 WARP-Cli 代理模式连接端口" + echo -e " ${GREEN}7.${PLAIN} ${RED}卸载 WARP-Cli 代理模式${PLAIN}" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出脚本" + echo -e "" + echo -e "VPS IP特征:${RED}原生IP双栈的VPS${PLAIN}" + echo -e "" + read -p " 请输入选项 [0-]:" menu2Input + case "$menu2Input" in + 1 ) wgcfmode=0 && install_wgcf ;; + 2 ) wgcfmode=1 && install_wgcf ;; + 3 ) wgcfmode=2 && install_wgcf ;; + 4 ) uninstall_wgcf ;; + 5 ) install_warpcli ;; + 6 ) change_warpcli_port ;; + 7 ) uninstall_warpcli ;; + esac +} + +if [[ $# > 0 ]]; then + echo "" +else + menu +fi \ No newline at end of file diff --git a/misakaxray/routing/1.json b/misakaxray/routing/1.json new file mode 100644 index 00000000..2e780b18 --- /dev/null +++ b/misakaxray/routing/1.json @@ -0,0 +1,43 @@ +"outbounds": [{ + "tag": "IP4-out", + "protocol": "freedom", + "settings": {} +}, +{ + "tag": "IP6-out", + "protocol": "freedom", + "settings": { + "domainStrategy": "UseIPv6" + } +}, +{ + "tag": "warp", + "protocol": "socks", + "settings": { + "servers": [{ + "address": "127.0.0.1", + "port": 40000 + }] + } +} +], +"routing": { +"domainStrategy": "AsIs", +"rules": [{ + "type": "field", + "outboundTag": "IP6-out", + "domain": [""] + }, + { + "type": "field", + "outboundTag": "warp", + "domain": [""] + }, + { + "type": "field", + "outboundTag": "IP4-out", + "network": "udp,tcp" + } +] +} +} \ No newline at end of file diff --git a/misakaxray/routing/2.json b/misakaxray/routing/2.json new file mode 100644 index 00000000..b5f11e28 --- /dev/null +++ b/misakaxray/routing/2.json @@ -0,0 +1,67 @@ +{ + "inbounds": [ + { + "port": 47254, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "69a67e87-89e8-40f7-9292-c929e1bc64d3", + "level": 1, + "alterId": 0 + } + ] + } + } + ], + "outbounds": [ + { + "tag": "IP4-out", + "protocol": "freedom", + "settings": { } + }, + { + "tag": "IP6-out", + "protocol": "freedom", + "settings": { + "domainStrategy": "UseIPv6" + } + }, + { + "tag": "socks5-warp", + "protocol": "socks", + "settings": { + "servers": [ + { + "address": "127.0.0.1", + "port": 40000 + } + ] + } + } + ], + "routing": { + "domainStrategy": "AsIs", + "rules": [ + { + "type": "field", + "outboundTag": "IP6-out", + "domain": [ + "" + ] + }, + { + "type": "field", + "outboundTag": "socks5-warp", + "domain": [ + "" + ] + }, + { + "type": "field", + "outboundTag": "IP4-out", + "network": "udp,tcp" + } + ] + } + } \ No newline at end of file diff --git a/misakaxray/routing/vmessconfig.json b/misakaxray/routing/vmessconfig.json new file mode 100644 index 00000000..72b4ae19 --- /dev/null +++ b/misakaxray/routing/vmessconfig.json @@ -0,0 +1,55 @@ +{ + "inbounds": [{ + "port": "$PORT", + "protocol": "vmess", + "settings": { + "clients": [{ + "id": "$uuid", + "level": 1, + "alterId": 0 + }] + } + }], + "outbounds": [{ + "tag": "IP4-out", + "protocol": "freedom", + "settings": {} + }, + { + "tag": "IP6-out", + "protocol": "freedom", + "settings": { + "domainStrategy": "UseIPv6" + } + }, + { + "tag": "socks5-warp", + "protocol": "socks", + "settings": { + "servers": [{ + "address": "127.0.0.1", + "port": 40000 + }] + } + } + ], + "routing": { + "domainStrategy": "AsIs", + "rules": [{ + "type": "field", + "outboundTag": "IP6-out", + "domain": [""] + }, + { + "type": "field", + "outboundTag": "socks5-warp", + "domain": [""] + }, + { + "type": "field", + "outboundTag": "IP4-out", + "network": "udp,tcp" + } + ] + } +} \ No newline at end of file diff --git a/misakaxray/xray.sh b/misakaxray/xray.sh new file mode 100644 index 00000000..4c2a8623 --- /dev/null +++ b/misakaxray/xray.sh @@ -0,0 +1,1704 @@ +#!/bin/bash + +RED="\033[31m" # Error message +GREEN="\033[32m" # Success message +YELLOW="\033[33m" # Warning message +BLUE="\033[36m" # Info message +PLAIN='\033[0m' + +SITES=( + http://www.zhuizishu.com/ + http://xs.56dyc.com/ + http://www.ddxsku.com/ + http://www.biqu6.com/ + https://www.wenshulou.cc/ + http://www.55shuba.com/ + http://www.39shubao.com/ + https://www.23xsw.cc/ + https://www.jueshitangmen.info/ + https://www.zhetian.org/ + http://www.bequgexs.com/ + http://www.tjwl.com/ +) + +CONFIG_FILE="/usr/local/etc/xray/config.json" +OS=$(hostnamectl | grep -i system | cut -d: -f2) + +IP=$(curl -s4m8 ip.sb) || IP=$(curl -s6m8 ip.sb) +if [[ -n $(curl -s6m8 ip.sb | grep ":") ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf +fi + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" +res=$(which bt 2>/dev/null) +[[ "$res" != "" ]] && BT="true" && NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" + +VLESS="false" +TROJAN="false" +TLS="false" +WS="false" +XTLS="false" +KCP="false" + +checkSystem() { + result=$(id | awk '{print $1}') + [[ $EUID -ne 0 ]] && colorEcho $RED " 请以root身份执行该脚本" && exit 1 + + res=$(which yum 2>/dev/null) + if [[ "$?" != "0" ]]; then + res=$(which apt 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 不受支持的Linux系统" + exit 1 + fi + PMT="apt" + CMD_INSTALL="apt install -y " + CMD_REMOVE="apt remove -y " + CMD_UPGRADE="apt update; apt upgrade -y; apt autoremove -y" + else + PMT="yum" + CMD_INSTALL="yum install -y " + CMD_REMOVE="yum remove -y " + CMD_UPGRADE="yum update -y" + fi + res=$(which systemctl 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 系统版本过低,请升级到最新版本" + exit 1 + fi +} + +colorEcho() { + echo -e "${1}${@:2}${PLAIN}" +} + +configNeedNginx() { + local ws=$(grep wsSettings $CONFIG_FILE) + [[ -z "$ws" ]] && echo no && return + echo yes +} + +needNginx() { + [[ "$WS" == "false" ]] && echo no && return + echo yes +} + +status() { + [[ ! -f /usr/local/bin/xray ]] && echo 0 && return + [[ ! -f $CONFIG_FILE ]] && echo 1 && return + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + [[ -z "$res" ]] && echo 2 && return + + if [[ $(configNeedNginx) != "yes" ]]; then + echo 3 + else + res=$(ss -nutlp | grep -i nginx) + if [[ -z "$res" ]]; then + echo 4 + else + echo 5 + fi + fi +} + +statusText() { + res=$(status) + case $res in + 2) echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN} ;; + 3) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN} ;; + 4) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN}, ${RED}Nginx未运行${PLAIN} ;; + 5) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行, Nginx正在运行${PLAIN} ;; + *) echo -e ${RED}未安装${PLAIN} ;; + esac +} + +normalizeVersion() { + if [ -n "$1" ]; then + case "$1" in + v*) echo "$1" ;; + http*) echo "v1.5.4" ;; + *) echo "v$1" ;; + esac + else + echo "" + fi +} + +# 1: new Xray. 0: no. 1: yes. 2: not installed. 3: check failed. +getVersion() { + VER=$(/usr/local/bin/xray version | head -n1 | awk '{print $2}') + RETVAL=$? + CUR_VER="$(normalizeVersion "$(echo "$VER" | head -n 1 | cut -d " " -f2)")" + TAG_URL="https://api.github.com/repos/XTLS/Xray-core/releases/latest" + NEW_VER="$(normalizeVersion "$(curl -s "${TAG_URL}" --connect-timeout 10 | grep 'tag_name' | cut -d\" -f4)")" + + if [[ $? -ne 0 ]] || [[ $NEW_VER == "" ]]; then + colorEcho $RED " 检查Xray版本信息失败,请检查网络" + 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' ;; + armv5tel) echo 'arm32-v5' ;; + armv6l) echo 'arm32-v6' ;; + armv7 | armv7l) echo 'arm32-v7a' ;; + armv8 | aarch64) echo 'arm64-v8a' ;; + mips64le) echo 'mips64le' ;; + mips64) echo 'mips64' ;; + mipsle) echo 'mips32le' ;; + mips) echo 'mips32' ;; + ppc64le) echo 'ppc64le' ;; + ppc64) echo 'ppc64' ;; + ppc64le) echo 'ppc64le' ;; + riscv64) echo 'riscv64' ;; + s390x) echo 's390x' ;; + *) colorEcho $RED " 不支持的CPU架构!" && exit 1;; + esac + + return 0 +} + +getData() { + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + echo " Xray一键脚本,运行之前请确认如下条件已经具备:" + colorEcho ${YELLOW} " 1. 一个伪装域名" + colorEcho ${YELLOW} " 2. 伪装域名DNS解析指向当前服务器ip(${IP})" + colorEcho ${BLUE} " 3. 如果/root目录下有 xray.pem 和 xray.key 证书密钥文件,无需理会条件2" + echo " " + read -p " 确认满足按y,按其他退出脚本:" answer + [[ "${answer,,}" != "y" ]] && exit 1 + echo "" + while true; do + read -p " 请输入伪装域名:" DOMAIN + if [[ -z "${DOMAIN}" ]]; then + colorEcho ${RED} " 域名输入错误,请重新输入!" + else + break + fi + done + DOMAIN=${DOMAIN,,} + colorEcho ${BLUE} " 伪装域名(host):$DOMAIN" + echo "" + if [[ -f ~/xray.pem && -f ~/xray.key ]]; then + colorEcho ${BLUE} " 检测到自有证书,将使用其部署" + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + else + resolve=$(curl -sm8 ipget.net/?ip=${DOMAIN}) + if [ $resolve != $IP ]; then + colorEcho ${BLUE} "${DOMAIN} 解析结果:${resolve}" + colorEcho ${RED} " 域名未解析到当前服务器IP(${IP})!" + exit 1 + fi + fi + fi + echo "" + if [[ "$(needNginx)" == "no" ]]; then + if [[ "$TLS" == "true" ]]; then + read -p " 请输入xray监听端口[强烈建议443,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + else + read -p " 请输入xray监听端口[100-65535的一个数字]:" PORT + [[ -z "${PORT}" ]] && PORT=$(shuf -i200-65000 -n1) + if [[ "${PORT:0:1}" == "0" ]]; then + colorEcho ${RED} " 端口不能以0开头" + exit 1 + fi + fi + colorEcho ${BLUE} " xray端口:$PORT" + else + read -p " 请输入Nginx监听端口[100-65535的一个数字,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + [ "${PORT:0:1}" = "0" ] && colorEcho ${BLUE} " 端口不能以0开头" && exit 1 + colorEcho ${BLUE} " Nginx端口:$PORT" + XPORT=$(shuf -i10000-65000 -n1) + fi + if [[ "$KCP" == "true" ]]; then + echo "" + colorEcho $BLUE " 请选择伪装类型:" + echo " 1) 无" + echo " 2) BT下载" + echo " 3) 视频通话" + echo " 4) 微信视频通话" + echo " 5) dtls" + echo " 6) wiregard" + read -p " 请选择伪装类型[默认:无]:" answer + case $answer in + 2) HEADER_TYPE="utp" ;; + 3) HEADER_TYPE="srtp" ;; + 4) HEADER_TYPE="wechat-video" ;; + 5) HEADER_TYPE="dtls" ;; + 6) HEADER_TYPE="wireguard" ;; + *) HEADER_TYPE="none" ;; + esac + colorEcho $BLUE " 伪装类型:$HEADER_TYPE" + SEED=$(cat /proc/sys/kernel/random/uuid) + fi + if [[ "$TROJAN" == "true" ]]; then + echo "" + read -p " 请设置trojan密码(不输则随机生成):" PASSWORD + [[ -z "$PASSWORD" ]] && PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) + colorEcho $BLUE " trojan密码:$PASSWORD" + fi + 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" ;; + esac + colorEcho $BLUE " 流控模式:$FLOW" + fi + if [[ "${WS}" == "true" ]]; then + echo "" + while true; do + read -p " 请输入伪装路径,以/开头(不懂请直接回车):" WSPATH + if [[ -z "${WSPATH}" ]]; then + len=$(shuf -i5-12 -n1) + ws=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1) + WSPATH="/$ws" + break + elif [[ "${WSPATH:0:1}" != "/" ]]; then + colorEcho ${RED} " 伪装路径必须以/开头!" + elif [[ "${WSPATH}" == "/" ]]; then + colorEcho ${RED} " 不能使用根路径!" + else + break + fi + done + colorEcho ${BLUE} " ws路径:$WSPATH" + fi + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + colorEcho $BLUE " 请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 高清壁纸站(https://bing.ioliu.cn)" + echo " 4) 自定义反代站点(需以http或者https开头)" + read -p " 请选择伪装网站类型[默认:高清壁纸站]" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.ioliu.cn" + else + case $answer in + 1) PROXY_URL="" ;; + 2) + 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 + ;; + 3) PROXY_URL="https://bing.ioliu.cn" ;; + 4) + read -p " 请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + colorEcho $RED " 请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + colorEcho $RED " 反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) colorEcho $RED " 请输入正确的选项!" && exit 1 ;; + esac + fi + REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3) + colorEcho $BLUE " 伪装网站:$PROXY_URL" + echo "" + colorEcho $BLUE " 是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p " 请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" == "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + colorEcho $BLUE " 允许搜索引擎:$ALLOW_SPIDER" + fi + 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" +} + +installNginx() { + echo "" + colorEcho $BLUE " 安装nginx..." + if [[ "$BT" == "false" ]]; then + if [[ "$PMT" == "yum" ]]; then + $CMD_INSTALL epel-release + if [[ "$?" != "0" ]]; then + echo '[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' >/etc/yum.repos.d/nginx.repo + fi + fi + $CMD_INSTALL nginx + if [[ "$?" != "0" ]]; then + colorEcho $RED " Nginx安装失败,请截图到TG群反馈" + exit 1 + fi + systemctl enable nginx + else + res=$(which nginx 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +startNginx() { + if [[ "$BT" == "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" == "false" ]]; then + systemctl stop nginx + else + res=$(ps aux | grep -i nginx) + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +getCert() { + mkdir -p /usr/local/etc/xray + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + systemctl stop xray + 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 + curl -sL https://get.acme.sh | sh -s email=hijk.pw@protonmail.sh + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [[ "$BT" == "false" ]]; then + if [[ -n $(curl -s6m8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + fi + else + if [[ -n $(curl -s6m8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + colorEcho $RED " 获取证书失败,请截图到TG群反馈" + exit 1 + } + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + colorEcho $RED "获取证书失败,请截图到TG群反馈" + exit 1 + } + else + cp ~/xray.pem /usr/local/etc/xray/${DOMAIN}.pem + cp ~/xray.key /usr/local/etc/xray/${DOMAIN}.key + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" == "n" ]]; then + echo 'User-Agent: *' >/usr/share/nginx/html/robots.txt + echo 'Disallow: /' >>/usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + + if [[ "$BT" == "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + 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 + fi + + if [[ "$PROXY_URL" == "" ]]; then + action="" + else + action="proxy_ssl_server_name on; + proxy_pass $PROXY_URL; + proxy_set_header Accept-Encoding ''; + sub_filter \"$REMOTE_HOST\" \"$DOMAIN\"; + sub_filter_once off;" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + mkdir -p ${NGINX_CONF_PATH} + # VMESS+WS+TLS + # VLESS+WS+TLS + if [[ "$WS" == "true" ]]; then + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + return 301 https://\$server_name:${PORT}\$request_uri; + } + + server { + listen ${PORT} ssl http2; + listen [::]:${PORT} ssl http2; + server_name ${DOMAIN}; + charset utf-8; + + # ssl配置 + ssl_protocols TLSv1.1 TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + ssl_ecdh_curve secp384r1; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + ssl_certificate $CERT_FILE; + ssl_certificate_key $KEY_FILE; + + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + + location ${WSPATH} { + proxy_redirect off; + proxy_pass http://127.0.0.1:${XPORT}; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } + } + EOF + else + # VLESS+TCP+TLS + # VLESS+TCP+XTLS + # trojan + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + } + EOF + fi + fi +} + +setSelinux() { + 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 +} + +setFirewall() { + 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 +} + +installBBR() { + if [[ "$NEED_BBR" != "y" ]]; then + INSTALL_BBR=false + return + fi + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $BLUE " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=$(hostnamectl | grep -i openvz) + if [[ "$res" != "" ]]; then + colorEcho $BLUE " openvz机器,跳过安装" + INSTALL_BBR=false + return + fi + echo "net.core.default_qdisc=fq" >>/etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $GREEN " BBR模块已启用" + INSTALL_BBR=false + return + fi + colorEcho $BLUE " 安装BBR模块..." + if [[ "$PMT" == "yum" ]]; then + if [[ "$V6_PROXY" == "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + $CMD_INSTALL --enablerepo=elrepo-kernel kernel-ml + $CMD_REMOVE kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + $CMD_INSTALL --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +installXray() { + rm -rf /tmp/xray + mkdir -p /tmp/xray + DOWNLOAD_LINK="https://github.com/XTLS/Xray-core/releases/download/${NEW_VER}/Xray-linux-$(archAffix).zip" + colorEcho $BLUE " 下载Xray: ${DOWNLOAD_LINK}" + curl -L -H "Cache-Control: no-cache" -o /tmp/xray/xray.zip ${DOWNLOAD_LINK} + if [ $? != 0 ]; then + colorEcho $RED " 下载Xray文件失败,请检查服务器网络设置" + exit 1 + fi + systemctl stop xray + mkdir -p /usr/local/etc/xray /usr/local/share/xray && \ + unzip /tmp/xray/xray.zip -d /tmp/xray + cp /tmp/xray/xray /usr/local/bin + cp /tmp/xray/geo* /usr/local/share/xray + chmod +x /usr/local/bin/xray || { + colorEcho $RED " Xray安装失败" + exit 1 + } + + cat >/etc/systemd/system/xray.service <<-EOF + [Unit] + Description=Xray Service + Documentation=https://github.com/xtls + After=network.target nss-lookup.target + + [Service] + User=root + #User=nobody + #CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + #AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + NoNewPrivileges=true + ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json + Restart=on-failure + RestartPreventExitStatus=23 + + [Install] + WantedBy=multi-user.target + EOF + systemctl daemon-reload + systemctl enable xray.service +} + +trojanConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +trojanXTLSConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +vmessConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + }, + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "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 +} + +vmessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessXTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "flow": "$FLOW", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +configXray() { + mkdir -p /usr/local/xray + if [[ "$TROJAN" == "true" ]]; then + if [[ "$XTLS" == "true" ]]; then + trojanXTLSConfig + else + trojanConfig + fi + return 0 + fi + if [[ "$VLESS" == "false" ]]; then + # VMESS + kcp + if [[ "$KCP" == "true" ]]; then + vmessKCPConfig + return 0 + fi + # VMESS + if [[ "$TLS" == "false" ]]; then + vmessConfig + elif [[ "$WS" == "false" ]]; then + # VMESS+TCP+TLS + vmessTLSConfig + # VMESS+WS+TLS + else + vmessWSConfig + fi + #VLESS + else + if [[ "$KCP" == "true" ]]; then + vlessKCPConfig + return 0 + fi + # VLESS+TCP + if [[ "$WS" == "false" ]]; then + # VLESS+TCP+TLS + if [[ "$XTLS" == "false" ]]; then + vlessTLSConfig + # VLESS+TCP+XTLS + else + vlessXTLSConfig + fi + # VLESS+WS+TLS + else + vlessWSConfig + fi + fi +} + +install() { + getData + $PMT clean all + [[ "$PMT" == "apt" ]] && $PMT update + #echo $CMD_UPGRADE | bash + $CMD_INSTALL wget curl sudo vim unzip tar gcc openssl + $CMD_INSTALL net-tools + if [[ "$PMT" == "apt" ]]; then + $CMD_INSTALL libssl-dev g++ + fi + res=$(which unzip 2>/dev/null) + if [[ $? -ne 0 ]]; then + colorEcho $RED " unzip安装失败,请检查网络" + exit 1 + fi + installNginx + setFirewall + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + getCert + fi + configNginx + colorEcho $BLUE " 安装Xray..." + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + colorEcho $BLUE " Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + colorEcho $BLUE " 安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + fi + configXray + setSelinux + installBBR + start + showInfo + bbrReboot +} + +bbrReboot() { + if [[ "${INSTALL_BBR}" == "true" ]]; then + echo + echo " 为使BBR模块生效,系统将在30秒后重启" + echo + echo -e " 您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +update() { + res=$(status) + [[ $res -lt 2 ]] && colorEcho $RED " Xray未安装,请先安装!" && return + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + colorEcho $BLUE " Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + colorEcho $BLUE " 安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + stop + start + colorEcho $GREEN " 最新版Xray安装成功!" + fi +} + +uninstall() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + echo "" + read -p " 确定卸载Xray?[y/n]:" answer + if [[ "${answer,,}" == "y" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + stop + systemctl disable xray + rm -rf /etc/systemd/system/xray.service + rm -rf /usr/local/bin/xray + rm -rf /usr/local/etc/xray + if [[ "$BT" == "false" ]]; then + 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 + fi + if [[ "$domain" != "" ]]; then + rm -rf ${NGINX_CONF_PATH}${domain}.conf + fi + [[ -f ~/.acme.sh/acme.sh ]] && ~/.acme.sh/acme.sh --uninstall + colorEcho $GREEN " Xray卸载成功" + fi +} + +start() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + stopNginx + startNginx + systemctl restart xray + sleep 2 + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + if [[ "$res" == "" ]]; then + colorEcho $RED " Xray启动失败,请检查日志或查看端口是否被占用!" + else + colorEcho $BLUE " Xray启动成功" + fi +} + +stop() { + stopNginx + systemctl stop xray + colorEcho $BLUE " Xray停止成功" +} + +restart() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + stop + start +} + +getConfigFileInfo() { + vless="false" + tls="false" + ws="false" + xtls="false" + trojan="false" + protocol="VMess" + kcp="false" + uid=$(grep id $CONFIG_FILE | head -n1 | cut -d: -f2 | tr -d \",' ') + alterid=$(grep alterId $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + network=$(grep network $CONFIG_FILE | tail -n1 | cut -d: -f2 | tr -d \",' ') + [[ -z "$network" ]] && network="tcp" + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" != "" ]]; then + ws="true" + tls="true" + wspath=$(grep path $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + else + tls="true" + fi + if [[ "$ws" == "true" ]]; then + port=$(grep -i ssl $NGINX_CONF_PATH${domain}.conf | head -n1 | awk '{print $2}') + else + port=$(grep port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + res=$(grep -i kcp $CONFIG_FILE) + if [[ "$res" != "" ]]; then + kcp="true" + type=$(grep header -A 3 $CONFIG_FILE | grep 'type' | cut -d: -f2 | tr -d \",' ') + seed=$(grep seed $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + vmess=$(grep vmess $CONFIG_FILE) + if [[ "$vmess" == "" ]]; then + trojan=$(grep trojan $CONFIG_FILE) + if [[ "$trojan" == "" ]]; then + vless="true" + protocol="VLESS" + else + trojan="true" + password=$(grep password $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + protocol="trojan" + fi + tls="true" + encryption="none" + xtls=$(grep xtlsSettings $CONFIG_FILE) + if [[ "$xtls" != "" ]]; then + xtls="true" + flow=$(grep flow $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + else + flow="无" + fi + fi +} + +outputVmess() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"tcp\", + \"type\":\"none\", + \"host\":\"\", + \"path\":\"\", + \"tls\":\"\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +outputVmessKCP() { + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" +} + +outputTrojan() { + if [[ "$xtls" == "true" ]]; then + link="trojan://${password}@${domain}:${port}#" + 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}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + else + link="trojan://${password}@${domain}:${port}#" + 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}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + fi +} + +outputVmessTLS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接: ${PLAIN}$RED$link$PLAIN" +} + +outputVmessWS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"${wspath}\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +showInfo() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + + echo "" + echo -n -e " ${BLUE}Xray运行状态:${PLAIN}" + statusText + echo -e " ${BLUE}Xray配置文件: ${PLAIN} ${RED}${CONFIG_FILE}${PLAIN}" + colorEcho $BLUE " Xray配置信息:" + + getConfigFileInfo + + echo -e " ${BLUE}协议: ${PLAIN} ${RED}${protocol}${PLAIN}" + if [[ "$trojan" == "true" ]]; then + outputTrojan + return 0 + fi + if [[ "$vless" == "false" ]]; then + if [[ "$kcp" == "true" ]]; then + outputVmessKCP + return 0 + fi + if [[ "$tls" == "false" ]]; then + outputVmess + elif [[ "$ws" == "false" ]]; then + outputVmessTLS + else + outputVmessWS + fi + else + if [[ "$kcp" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" + return 0 + fi + if [[ "$xtls" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + elif [[ "$ws" == "false" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN}${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + else + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + fi + fi +} + +showLog() { + res=$(status) + [[ $res -lt 2 ]] && colorEcho $RED " Xray未安装,请先安装!" && return + journalctl -xen -u xray --no-pager +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}Xray一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) & MisakaNo #" + echo -e "# ${GREEN}博客${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo -e " " + echo -e " ${GREEN}1.${PLAIN} 安装Xray-VMESS" + echo -e " ${GREEN}2.${PLAIN} 安装Xray-${BLUE}VMESS+mKCP${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装Xray-VMESS+TCP+TLS" + echo -e " ${GREEN}4.${PLAIN} 安装Xray-${BLUE}VMESS+WS+TLS${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}5.${PLAIN} 安装Xray-${BLUE}VLESS+mKCP${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 安装Xray-VLESS+TCP+TLS" + echo -e " ${GREEN}7.${PLAIN} 安装Xray-${BLUE}VLESS+WS+TLS${PLAIN}${RED}(可过cdn)${PLAIN}" + echo -e " ${GREEN}8.${PLAIN} 安装Xray-${BLUE}VLESS+TCP+XTLS${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}9.${PLAIN} 安装${BLUE}Trojan${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}10.${PLAIN} 安装${BLUE}Trojan+XTLS${PLAIN}${RED}(推荐)${PLAIN}" + echo " -------------" + echo -e " ${GREEN}11.${PLAIN} 更新Xray" + echo -e " ${GREEN}12. ${RED}卸载Xray${PLAIN}" + echo " -------------" + echo -e " ${GREEN}13.${PLAIN} 启动Xray" + echo -e " ${GREEN}14.${PLAIN} 重启Xray" + echo -e " ${GREEN}15.${PLAIN} 停止Xray" + echo " -------------" + echo -e " ${GREEN}16.${PLAIN} 查看Xray配置" + echo -e " ${GREEN}17.${PLAIN} 查看Xray日志" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo -n " 当前状态:" + statusText + echo + + read -p " 请选择操作[0-17]:" answer + case $answer in + 0) exit 1 ;; + 1) install ;; + 2) KCP="true" && install ;; + 3) TLS="true" && install ;; + 4) TLS="true" && WS="true" && install ;; + 5) VLESS="true" && KCP="true" && install ;; + 6) VLESS="true" && TLS="true" && install ;; + 7) VLESS="true" && TLS="true" && WS="true" && install ;; + 8) VLESS="true" && TLS="true" && XTLS="true" && install ;; + 9) TROJAN="true" && TLS="true" && install ;; + 10) TROJAN="true" && TLS="true" && XTLS="true" && install ;; + 11) update ;; + 12) uninstall ;; + 13) start ;; + 14) restart ;; + 15) stop ;; + 16) showInfo ;; + 17) showLog ;; + *) colorEcho $RED " 请选择正确的操作!" && exit 1 ;; + esac +} + +checkSystem +checkwarp + +action=$1 +[[ -z $1 ]] && action=menu +case "$action" in + menu | update | uninstall | start | restart | stop | showInfo | showLog) ${action} ;; + *) echo " 参数错误" && echo " 用法: $(basename $0) [menu|update|uninstall|start|restart|stop|showInfo|showLog]" ;; +esac \ No newline at end of file diff --git a/misakaxray/xray1.sh b/misakaxray/xray1.sh new file mode 100644 index 00000000..06e4fddc --- /dev/null +++ b/misakaxray/xray1.sh @@ -0,0 +1,1702 @@ +#!/bin/bash + +RED="\033[31m" # Error message +GREEN="\033[32m" # Success message +YELLOW="\033[33m" # Warning message +BLUE="\033[36m" # Info message +PLAIN='\033[0m' + +SITES=( + http://www.zhuizishu.com/ + http://xs.56dyc.com/ + http://www.ddxsku.com/ + http://www.biqu6.com/ + https://www.wenshulou.cc/ + http://www.55shuba.com/ + http://www.39shubao.com/ + https://www.23xsw.cc/ + https://www.jueshitangmen.info/ + https://www.zhetian.org/ + http://www.bequgexs.com/ + http://www.tjwl.com/ +) + +CONFIG_FILE="/usr/local/etc/xray/config.json" +# OS=$(hostnamectl | grep -i system | cut -d: -f2) + +IP=$(curl -s4m8 ip.sb) || IP=$(curl -s6m8 ip.sb) +if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 >/etc/resolv.conf +fi + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" +res=$(which bt 2>/dev/null) +[[ "$res" != "" ]] && BT="true" && NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" + +VLESS="false" +TROJAN="false" +TLS="false" +WS="false" +XTLS="false" +KCP="false" + +checkSystem() { + [[ $EUID -ne 0 ]] && colorEcho $RED " 请以root身份执行该脚本" && exit 1 + + res=$(which yum 2>/dev/null) + if [[ "$?" != "0" ]]; then + res=$(which apt 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 不受支持的Linux系统" + exit 1 + fi + PMT="apt" + CMD_INSTALL="apt install -y " + CMD_REMOVE="apt remove -y " + CMD_UPGRADE="apt update; apt upgrade -y; apt autoremove -y" + else + PMT="yum" + CMD_INSTALL="yum install -y " + CMD_REMOVE="yum remove -y " + CMD_UPGRADE="yum update -y" + fi + res=$(which systemctl 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 系统版本过低,请升级到最新版本" + exit 1 + fi +} + +colorEcho() { + echo -e "${1}${@:2}${PLAIN}" +} + +configNeedNginx() { + local ws=$(grep wsSettings $CONFIG_FILE) + [[ -z "$ws" ]] && echo no && return + echo yes +} + +needNginx() { + [[ "$WS" == "false" ]] && echo no && return + echo yes +} + +status() { + [[ ! -f /usr/local/bin/xray ]] && echo 0 && return + [[ ! -f $CONFIG_FILE ]] && echo 1 && return + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + [[ -z "$res" ]] && echo 2 && return + + if [[ $(configNeedNginx) != "yes" ]]; then + echo 3 + else + res=$(ss -nutlp | grep -i nginx) + if [[ -z "$res" ]]; then + echo 4 + else + echo 5 + fi + fi +} + +statusText() { + res=$(status) + case $res in + 2) echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN} ;; + 3) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN} ;; + 4) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN}, ${RED}Nginx未运行${PLAIN} ;; + 5) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行, Nginx正在运行${PLAIN} ;; + *) echo -e ${RED}未安装${PLAIN} ;; + esac +} + +normalizeVersion() { + if [ -n "$1" ]; then + case "$1" in + v*) echo "$1" ;; + http*) echo "v1.5.4" ;; + *) echo "v$1" ;; + esac + else + echo "" + fi +} + +# 1: new Xray. 0: no. 1: yes. 2: not installed. 3: check failed. +getVersion() { + VER=$(/usr/local/bin/xray version 2>/dev/null | head -n1 | awk '{print $2}') + RETVAL=$? + CUR_VER="$(normalizeVersion "$(echo "$VER" | head -n 1 | cut -d " " -f2)")" + TAG_URL="https://api.github.com/repos/XTLS/Xray-core/releases/latest" + NEW_VER="$(normalizeVersion "$(curl -s "${TAG_URL}" --connect-timeout 10 | grep 'tag_name' | cut -d\" -f4)")" + + if [[ $? -ne 0 ]] || [[ $NEW_VER == "" ]]; then + colorEcho $RED " 检查Xray版本信息失败,请检查网络" + 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' ;; + armv5tel) echo 'arm32-v5' ;; + armv6l) echo 'arm32-v6' ;; + armv7 | armv7l) echo 'arm32-v7a' ;; + armv8 | aarch64) echo 'arm64-v8a' ;; + mips64le) echo 'mips64le' ;; + mips64) echo 'mips64' ;; + mipsle) echo 'mips32le' ;; + mips) echo 'mips32' ;; + ppc64le) echo 'ppc64le' ;; + ppc64) echo 'ppc64' ;; + ppc64le) echo 'ppc64le' ;; + riscv64) echo 'riscv64' ;; + s390x) echo 's390x' ;; + *) colorEcho $RED " 不支持的CPU架构!" && exit 1 ;; + esac + + return 0 +} + +getData() { + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + echo " Xray一键脚本,运行之前请确认如下条件已经具备:" + colorEcho ${YELLOW} " 1. 一个伪装域名" + colorEcho ${YELLOW} " 2. 伪装域名DNS解析指向当前服务器ip(${IP})" + colorEcho ${BLUE} " 3. 如果/root目录下有 xray.pem 和 xray.key 证书密钥文件,无需理会条件2" + echo " " + read -p " 确认满足按y,按其他退出脚本:" answer + [[ "${answer,,}" != "y" ]] && exit 1 + echo "" + while true; do + read -p " 请输入伪装域名:" DOMAIN + if [[ -z "${DOMAIN}" ]]; then + colorEcho ${RED} " 域名输入错误,请重新输入!" + else + break + fi + done + DOMAIN=${DOMAIN,,} + colorEcho ${BLUE} " 伪装域名(host):$DOMAIN" + echo "" + if [[ -f ~/xray.pem && -f ~/xray.key ]]; then + colorEcho ${BLUE} " 检测到自有证书,将使用其部署" + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + else + resolve=$(curl -sm8 ipget.net/?ip=${DOMAIN}) + if [ $resolve != $IP ]; then + colorEcho ${BLUE} "${DOMAIN} 解析结果:${resolve}" + colorEcho ${RED} " 域名未解析到当前服务器IP(${IP})!" + exit 1 + fi + fi + fi + echo "" + if [[ "$(needNginx)" == "no" ]]; then + if [[ "$TLS" == "true" ]]; then + read -p " 请输入xray监听端口[强烈建议443,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + else + read -p " 请输入xray监听端口[100-65535的一个数字]:" PORT + [[ -z "${PORT}" ]] && PORT=$(shuf -i200-65000 -n1) + if [[ "${PORT:0:1}" == "0" ]]; then + colorEcho ${RED} " 端口不能以0开头" + exit 1 + fi + fi + colorEcho ${BLUE} " xray端口:$PORT" + else + read -p " 请输入Nginx监听端口[100-65535的一个数字,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + [ "${PORT:0:1}" = "0" ] && colorEcho ${BLUE} " 端口不能以0开头" && exit 1 + colorEcho ${BLUE} " Nginx端口:$PORT" + XPORT=$(shuf -i10000-65000 -n1) + fi + if [[ "$KCP" == "true" ]]; then + echo "" + colorEcho $BLUE " 请选择伪装类型:" + echo " 1) 无" + echo " 2) BT下载" + echo " 3) 视频通话" + echo " 4) 微信视频通话" + echo " 5) dtls" + echo " 6) wiregard" + read -p " 请选择伪装类型[默认:无]:" answer + case $answer in + 2) HEADER_TYPE="utp" ;; + 3) HEADER_TYPE="srtp" ;; + 4) HEADER_TYPE="wechat-video" ;; + 5) HEADER_TYPE="dtls" ;; + 6) HEADER_TYPE="wireguard" ;; + *) HEADER_TYPE="none" ;; + esac + colorEcho $BLUE " 伪装类型:$HEADER_TYPE" + SEED=$(cat /proc/sys/kernel/random/uuid) + fi + if [[ "$TROJAN" == "true" ]]; then + echo "" + read -p " 请设置trojan密码(不输则随机生成):" PASSWORD + [[ -z "$PASSWORD" ]] && PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) + colorEcho $BLUE " trojan密码:$PASSWORD" + fi + 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" ;; + esac + colorEcho $BLUE " 流控模式:$FLOW" + fi + if [[ "${WS}" == "true" ]]; then + echo "" + while true; do + read -p " 请输入伪装路径,以/开头(不懂请直接回车):" WSPATH + if [[ -z "${WSPATH}" ]]; then + len=$(shuf -i5-12 -n1) + ws=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1) + WSPATH="/$ws" + break + elif [[ "${WSPATH:0:1}" != "/" ]]; then + colorEcho ${RED} " 伪装路径必须以/开头!" + elif [[ "${WSPATH}" == "/" ]]; then + colorEcho ${RED} " 不能使用根路径!" + else + break + fi + done + colorEcho ${BLUE} " ws路径:$WSPATH" + fi + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + colorEcho $BLUE " 请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 高清壁纸站(https://bing.ioliu.cn)" + echo " 4) 自定义反代站点(需以http或者https开头)" + read -p " 请选择伪装网站类型[默认:高清壁纸站]" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.ioliu.cn" + else + case $answer in + 1) PROXY_URL="" ;; + 2) + 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 + ;; + 3) PROXY_URL="https://bing.ioliu.cn" ;; + 4) + read -p " 请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + colorEcho $RED " 请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + colorEcho $RED " 反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) colorEcho $RED " 请输入正确的选项!" && exit 1 ;; + esac + fi + REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3) + colorEcho $BLUE " 伪装网站:$PROXY_URL" + echo "" + colorEcho $BLUE " 是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p " 请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" == "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + colorEcho $BLUE " 允许搜索引擎:$ALLOW_SPIDER" + fi + 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" +} + +installNginx() { + echo "" + colorEcho $BLUE " 安装nginx..." + if [[ "$BT" == "false" ]]; then + if [[ "$PMT" == "yum" ]]; then + $CMD_INSTALL epel-release + if [[ "$?" != "0" ]]; then + echo '[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' >/etc/yum.repos.d/nginx.repo + fi + fi + $CMD_INSTALL nginx + if [[ "$?" != "0" ]]; then + colorEcho $RED " Nginx安装失败,请截图到TG群反馈" + exit 1 + fi + systemctl enable nginx + else + res=$(which nginx 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +startNginx() { + if [[ "$BT" == "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" == "false" ]]; then + systemctl stop nginx + else + res=$(ps aux | grep -i nginx) + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +getCert() { + mkdir -p /usr/local/etc/xray + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + systemctl stop xray + 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 + curl -sL https://get.acme.sh | sh -s email=hijk.pw@protonmail.sh + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [[ "$BT" == "false" ]]; then + if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + fi + else + if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + colorEcho $RED " 获取证书失败,请截图到TG群反馈" + exit 1 + } + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + colorEcho $RED "获取证书失败,请截图到TG群反馈" + exit 1 + } + else + cp ~/xray.pem /usr/local/etc/xray/${DOMAIN}.pem + cp ~/xray.key /usr/local/etc/xray/${DOMAIN}.key + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" == "n" ]]; then + echo 'User-Agent: *' >/usr/share/nginx/html/robots.txt + echo 'Disallow: /' >>/usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + + if [[ "$BT" == "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + 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 + fi + + if [[ "$PROXY_URL" == "" ]]; then + action="" + else + action="proxy_ssl_server_name on; + proxy_pass $PROXY_URL; + proxy_set_header Accept-Encoding ''; + sub_filter \"$REMOTE_HOST\" \"$DOMAIN\"; + sub_filter_once off;" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + mkdir -p ${NGINX_CONF_PATH} + # VMESS+WS+TLS + # VLESS+WS+TLS + if [[ "$WS" == "true" ]]; then + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + return 301 https://\$server_name:${PORT}\$request_uri; + } + + server { + listen ${PORT} ssl http2; + listen [::]:${PORT} ssl http2; + server_name ${DOMAIN}; + charset utf-8; + + # ssl配置 + ssl_protocols TLSv1.1 TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + ssl_ecdh_curve secp384r1; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + ssl_certificate $CERT_FILE; + ssl_certificate_key $KEY_FILE; + + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + + location ${WSPATH} { + proxy_redirect off; + proxy_pass http://127.0.0.1:${XPORT}; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } + } + EOF + else + # VLESS+TCP+TLS + # VLESS+TCP+XTLS + # trojan + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + } + EOF + fi + fi +} + +setSelinux() { + 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 +} + +setFirewall() { + 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 +} + +installBBR() { + if [[ "$NEED_BBR" != "y" ]]; then + INSTALL_BBR=false + return + fi + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $BLUE " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=$(systemd-detect-virt) + if [[ $res =~ lxc|openvz ]]; then + colorEcho $BLUE " 由于你的VPS为OpenVZ或LXC架构的VPS,跳过安装" + INSTALL_BBR=false + return + fi + echo "net.core.default_qdisc=fq" >>/etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $GREEN " BBR模块已启用" + INSTALL_BBR=false + return + fi + colorEcho $BLUE " 安装BBR模块..." + if [[ "$PMT" == "yum" ]]; then + if [[ "$V6_PROXY" == "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + $CMD_INSTALL --enablerepo=elrepo-kernel kernel-ml + $CMD_REMOVE kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + $CMD_INSTALL --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +installXray() { + rm -rf /tmp/xray + mkdir -p /tmp/xray + DOWNLOAD_LINK="https://github.com/XTLS/Xray-core/releases/download/${NEW_VER}/Xray-linux-$(archAffix).zip" + colorEcho $BLUE " 下载Xray: ${DOWNLOAD_LINK}" + curl -L -H "Cache-Control: no-cache" -o /tmp/xray/xray.zip ${DOWNLOAD_LINK} + if [ $? != 0 ]; then + colorEcho $RED " 下载Xray文件失败,请检查服务器网络设置" + exit 1 + fi + systemctl stop xray + mkdir -p /usr/local/etc/xray /usr/local/share/xray && \ + unzip /tmp/xray/xray.zip -d /tmp/xray + cp /tmp/xray/xray /usr/local/bin + cp /tmp/xray/geo* /usr/local/share/xray + chmod +x /usr/local/bin/xray || { + colorEcho $RED " Xray安装失败" + exit 1 + } + + cat >/etc/systemd/system/xray.service <<-EOF + [Unit] + Description=Xray Service + Documentation=https://github.com/xtls + After=network.target nss-lookup.target + + [Service] + User=root + #User=nobody + #CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + #AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + NoNewPrivileges=true + ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json + Restart=on-failure + RestartPreventExitStatus=23 + + [Install] + WantedBy=multi-user.target + EOF + systemctl daemon-reload + systemctl enable xray.service +} + +trojanConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +trojanXTLSConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +vmessConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + }, + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "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 +} + +vmessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessXTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "flow": "$FLOW", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +configXray() { + mkdir -p /usr/local/xray + if [[ "$TROJAN" == "true" ]]; then + if [[ "$XTLS" == "true" ]]; then + trojanXTLSConfig + else + trojanConfig + fi + return 0 + fi + if [[ "$VLESS" == "false" ]]; then + # VMESS + kcp + if [[ "$KCP" == "true" ]]; then + vmessKCPConfig + return 0 + fi + # VMESS + if [[ "$TLS" == "false" ]]; then + vmessConfig + elif [[ "$WS" == "false" ]]; then + # VMESS+TCP+TLS + vmessTLSConfig + # VMESS+WS+TLS + else + vmessWSConfig + fi + #VLESS + else + if [[ "$KCP" == "true" ]]; then + vlessKCPConfig + return 0 + fi + # VLESS+TCP + if [[ "$WS" == "false" ]]; then + # VLESS+TCP+TLS + if [[ "$XTLS" == "false" ]]; then + vlessTLSConfig + # VLESS+TCP+XTLS + else + vlessXTLSConfig + fi + # VLESS+WS+TLS + else + vlessWSConfig + fi + fi +} + +install() { + getData + $PMT clean all + [[ "$PMT" == "apt" ]] && $PMT update + #echo $CMD_UPGRADE | bash + $CMD_INSTALL wget curl sudo vim unzip tar gcc openssl + $CMD_INSTALL net-tools + if [[ "$PMT" == "apt" ]]; then + $CMD_INSTALL libssl-dev g++ + fi + res=$(which unzip 2>/dev/null) + if [[ $? -ne 0 ]]; then + colorEcho $RED " unzip安装失败,请检查网络" + exit 1 + fi + installNginx + setFirewall + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + getCert + fi + configNginx + colorEcho $BLUE " 安装Xray..." + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + colorEcho $BLUE " Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + colorEcho $BLUE " 安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + fi + configXray + setSelinux + installBBR + start + showInfo + bbrReboot +} + +bbrReboot() { + if [[ "${INSTALL_BBR}" == "true" ]]; then + echo + echo " 为使BBR模块生效,系统将在30秒后重启" + echo + echo -e " 您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +update() { + res=$(status) + [[ $res -lt 2 ]] && colorEcho $RED " Xray未安装,请先安装!" && return + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + colorEcho $BLUE " Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + colorEcho $BLUE " 安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + stop + start + colorEcho $GREEN " 最新版Xray安装成功!" + fi +} + +uninstall() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + echo "" + read -p " 确定卸载Xray?[y/n]:" answer + if [[ "${answer,,}" == "y" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + stop + systemctl disable xray + rm -rf /etc/systemd/system/xray.service + rm -rf /usr/local/bin/xray + rm -rf /usr/local/etc/xray + if [[ "$BT" == "false" ]]; then + 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 + fi + if [[ "$domain" != "" ]]; then + rm -rf ${NGINX_CONF_PATH}${domain}.conf + fi + [[ -f ~/.acme.sh/acme.sh ]] && ~/.acme.sh/acme.sh --uninstall + colorEcho $GREEN " Xray卸载成功" + fi +} + +start() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + stopNginx + startNginx + systemctl restart xray + sleep 2 + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + if [[ "$res" == "" ]]; then + colorEcho $RED " Xray启动失败,请检查日志或查看端口是否被占用!" + else + colorEcho $BLUE " Xray启动成功" + fi +} + +stop() { + stopNginx + systemctl stop xray + colorEcho $BLUE " Xray停止成功" +} + +restart() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + stop + start +} + +getConfigFileInfo() { + vless="false" + tls="false" + ws="false" + xtls="false" + trojan="false" + protocol="VMess" + kcp="false" + uid=$(grep id $CONFIG_FILE | head -n1 | cut -d: -f2 | tr -d \",' ') + alterid=$(grep alterId $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + network=$(grep network $CONFIG_FILE | tail -n1 | cut -d: -f2 | tr -d \",' ') + [[ -z "$network" ]] && network="tcp" + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" != "" ]]; then + ws="true" + tls="true" + wspath=$(grep path $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + else + tls="true" + fi + if [[ "$ws" == "true" ]]; then + port=$(grep -i ssl $NGINX_CONF_PATH${domain}.conf | head -n1 | awk '{print $2}') + else + port=$(grep port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + res=$(grep -i kcp $CONFIG_FILE) + if [[ "$res" != "" ]]; then + kcp="true" + type=$(grep header -A 3 $CONFIG_FILE | grep 'type' | cut -d: -f2 | tr -d \",' ') + seed=$(grep seed $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + vmess=$(grep vmess $CONFIG_FILE) + if [[ "$vmess" == "" ]]; then + trojan=$(grep trojan $CONFIG_FILE) + if [[ "$trojan" == "" ]]; then + vless="true" + protocol="VLESS" + else + trojan="true" + password=$(grep password $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + protocol="trojan" + fi + tls="true" + encryption="none" + xtls=$(grep xtlsSettings $CONFIG_FILE) + if [[ "$xtls" != "" ]]; then + xtls="true" + flow=$(grep flow $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + else + flow="无" + fi + fi +} + +outputVmess() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"tcp\", + \"type\":\"none\", + \"host\":\"\", + \"path\":\"\", + \"tls\":\"\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +outputVmessKCP() { + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" +} + +outputTrojan() { + if [[ "$xtls" == "true" ]]; then + link="trojan://${password}@${domain}:${port}#" + 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}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + else + link="trojan://${password}@${domain}:${port}#" + 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}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + fi +} + +outputVmessTLS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接: ${PLAIN}$RED$link$PLAIN" +} + +outputVmessWS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"${wspath}\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +showInfo() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + + echo "" + echo -n -e " ${BLUE}Xray运行状态:${PLAIN}" + statusText + echo -e " ${BLUE}Xray配置文件: ${PLAIN} ${RED}${CONFIG_FILE}${PLAIN}" + colorEcho $BLUE " Xray配置信息:" + + getConfigFileInfo + + echo -e " ${BLUE}协议: ${PLAIN} ${RED}${protocol}${PLAIN}" + if [[ "$trojan" == "true" ]]; then + outputTrojan + return 0 + fi + if [[ "$vless" == "false" ]]; then + if [[ "$kcp" == "true" ]]; then + outputVmessKCP + return 0 + fi + if [[ "$tls" == "false" ]]; then + outputVmess + elif [[ "$ws" == "false" ]]; then + outputVmessTLS + else + outputVmessWS + fi + else + if [[ "$kcp" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" + return 0 + fi + if [[ "$xtls" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + elif [[ "$ws" == "false" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN}${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + else + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + fi + fi +} + +showLog() { + res=$(status) + [[ $res -lt 2 ]] && colorEcho $RED " Xray未安装,请先安装!" && return + journalctl -xen -u xray --no-pager +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}Xray一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) & MisakaNo #" + echo -e "# ${GREEN}博客${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo -e " " + echo -e " ${GREEN}1.${PLAIN} 安装Xray-VMESS" + echo -e " ${GREEN}2.${PLAIN} 安装Xray-${BLUE}VMESS+mKCP${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装Xray-VMESS+TCP+TLS" + echo -e " ${GREEN}4.${PLAIN} 安装Xray-${BLUE}VMESS+WS+TLS${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}5.${PLAIN} 安装Xray-${BLUE}VLESS+mKCP${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 安装Xray-VLESS+TCP+TLS" + echo -e " ${GREEN}7.${PLAIN} 安装Xray-${BLUE}VLESS+WS+TLS${PLAIN}${RED}(可过cdn)${PLAIN}" + echo -e " ${GREEN}8.${PLAIN} 安装Xray-${BLUE}VLESS+TCP+XTLS${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}9.${PLAIN} 安装${BLUE}Trojan${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}10.${PLAIN} 安装${BLUE}Trojan+XTLS${PLAIN}${RED}(推荐)${PLAIN}" + echo " -------------" + echo -e " ${GREEN}11.${PLAIN} 更新Xray" + echo -e " ${GREEN}12. ${RED}卸载Xray${PLAIN}" + echo " -------------" + echo -e " ${GREEN}13.${PLAIN} 启动Xray" + echo -e " ${GREEN}14.${PLAIN} 重启Xray" + echo -e " ${GREEN}15.${PLAIN} 停止Xray" + echo " -------------" + echo -e " ${GREEN}16.${PLAIN} 查看Xray配置" + echo -e " ${GREEN}17.${PLAIN} 查看Xray日志" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo -n " 当前状态:" + statusText + echo + + read -p " 请选择操作[0-17]:" answer + case $answer in + 0) exit 1 ;; + 1) install ;; + 2) KCP="true" && install ;; + 3) TLS="true" && install ;; + 4) TLS="true" && WS="true" && install ;; + 5) VLESS="true" && KCP="true" && install ;; + 6) VLESS="true" && TLS="true" && install ;; + 7) VLESS="true" && TLS="true" && WS="true" && install ;; + 8) VLESS="true" && TLS="true" && XTLS="true" && install ;; + 9) TROJAN="true" && TLS="true" && install ;; + 10) TROJAN="true" && TLS="true" && XTLS="true" && install ;; + 11) update ;; + 12) uninstall ;; + 13) start ;; + 14) restart ;; + 15) stop ;; + 16) showInfo ;; + 17) showLog ;; + *) colorEcho $RED " 请选择正确的操作!" && exit 1 ;; + esac +} + +checkSystem + +action=$1 +[[ -z $1 ]] && action=menu +case "$action" in +menu | update | uninstall | start | restart | stop | showInfo | showLog) ${action} ;; +*) echo " 参数错误" && echo " 用法: $(basename $0) [menu|update|uninstall|start|restart|stop|showInfo|showLog]" ;; +esac \ No newline at end of file diff --git a/misakaxray/xray2.sh b/misakaxray/xray2.sh new file mode 100644 index 00000000..e8167367 --- /dev/null +++ b/misakaxray/xray2.sh @@ -0,0 +1,1720 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +RED="\033[31m" +GREEN="\033[32m" +YELLOW="\033[33m" +BLUE="\033[36m" +PLAIN='\033[0m' + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 +[[ -z $(type -P curl) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl + +SITES=( + http://www.zhuizishu.com/ + http://xs.56dyc.com/ + http://www.ddxsku.com/ + http://www.biqu6.com/ + https://www.wenshulou.cc/ + http://www.55shuba.com/ + http://www.39shubao.com/ + https://www.23xsw.cc/ + https://www.jueshitangmen.info/ + https://www.zhetian.org/ + http://www.bequgexs.com/ + http://www.tjwl.com/ +) + +CONFIG_FILE="/usr/local/etc/xray/config.json" + +IP=$(curl -s4m8 ip.sb) || IP=$(curl -s6m8 ip.sb) + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" +res=$(which bt 2>/dev/null) +[[ "$res" != "" ]] && BT="true" && NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" + +VLESS="false" +TROJAN="false" +TLS="false" +WS="false" +XTLS="false" +KCP="false" + +configNeedNginx() { + local ws=$(grep wsSettings $CONFIG_FILE) + [[ -z "$ws" ]] && echo no && return + echo yes +} + +needNginx() { + [[ "$WS" == "false" ]] && echo no && return + echo yes +} + +status() { + [[ ! -f /usr/local/bin/xray ]] && echo 0 && return + [[ ! -f $CONFIG_FILE ]] && echo 1 && return + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + [[ -z "$res" ]] && echo 2 && return + + if [[ $(configNeedNginx) != "yes" ]]; then + echo 3 + else + res=$(ss -nutlp | grep -i nginx) + if [[ -z "$res" ]]; then + echo 4 + else + echo 5 + fi + fi +} + +statusText() { + res=$(status) + case $res in + 2) echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN} ;; + 3) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN} ;; + 4) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN}, ${RED}Nginx未运行${PLAIN} ;; + 5) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行, Nginx正在运行${PLAIN} ;; + *) echo -e ${RED}未安装${PLAIN} ;; + esac +} + +normalizeVersion() { + if [ -n "$1" ]; then + case "$1" in + v*) echo "$1" ;; + http*) echo "v1.5.4" ;; + *) echo "v$1" ;; + esac + else + echo "" + fi +} + +# 1: new Xray. 0: no. 1: yes. 2: not installed. 3: check failed. +getVersion() { + VER=$(/usr/local/bin/xray version 2>/dev/null | head -n1 | awk '{print $2}') + RETVAL=$? + CUR_VER="$(normalizeVersion "$(echo "$VER" | head -n 1 | cut -d " " -f2)")" + TAG_URL="https://api.github.com/repos/XTLS/Xray-core/releases/latest" + NEW_VER="$(normalizeVersion "$(curl -s "${TAG_URL}" --connect-timeout 10 | grep 'tag_name' | cut -d\" -f4)")" + + if [[ $? -ne 0 ]] || [[ $NEW_VER == "" ]]; then + red " 检查Xray版本信息失败,请检查网络" + 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' ;; + armv5tel) echo 'arm32-v5' ;; + armv6l) echo 'arm32-v6' ;; + armv7 | armv7l) echo 'arm32-v7a' ;; + armv8 | aarch64) echo 'arm64-v8a' ;; + mips64le) echo 'mips64le' ;; + mips64) echo 'mips64' ;; + mipsle) echo 'mips32le' ;; + mips) echo 'mips32' ;; + ppc64le) echo 'ppc64le' ;; + ppc64) echo 'ppc64' ;; + ppc64le) echo 'ppc64le' ;; + riscv64) echo 'riscv64' ;; + s390x) echo 's390x' ;; + *) red " 不支持的CPU架构!" && exit 1 ;; + esac + + return 0 +} + +getData() { + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + echo "Xray一键脚本,运行之前请确认如下条件已经具备:" + yellow " 1. 一个伪装域名" + yellow " 2. 伪装域名DNS解析指向当前服务器ip(${IP})" + yellow " 3. 如果/root目录下有 xray.pem 和 xray.key 证书密钥文件,无需理会条件2" + echo " " + read -p "确认满足以上条件请按y,按其他键退出脚本:" answer + [[ "${answer,,}" != "y" ]] && exit 1 + echo "" + while true; do + read -p "请输入伪装域名:" DOMAIN + if [[ -z "${DOMAIN}" ]]; then + red " 域名输入错误,请重新输入!" + else + break + fi + done + DOMAIN=${DOMAIN,,} + yellow "伪装域名(host):$DOMAIN" + echo "" + if [[ -f ~/xray.pem && -f ~/xray.key ]]; then + yellow "检测到自有证书,将使用自有证书部署" + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + else + resolve=$(curl -sm8 ipget.net/?ip=${DOMAIN}) + if [[ $resolve != $IP ]]; then + yellow "${DOMAIN} 解析结果:${resolve}" + red "域名未解析到当前服务器IP(${IP})!" + green "建议如下:" + yellow " 1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow " 2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + echo "" + if [[ "$(needNginx)" == "no" ]]; then + if [[ "$TLS" == "true" ]]; then + read -p "请输入xray监听端口 [默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + else + read -p "请输入xray监听端口 [100-65535的一个数字]:" PORT + [[ -z "${PORT}" ]] && PORT=$(shuf -i200-65000 -n1) + if [[ "${PORT:0:1}" == "0" ]]; then + red "端口不能以0开头" + exit 1 + fi + fi + yellow "xray端口:$PORT" + else + read -p "请输入Nginx监听端口[100-65535的一个数字,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + [ "${PORT:0:1}" = "0" ] && red "端口不能以0开头" && exit 1 + yellow " Nginx端口:$PORT" + XPORT=$(shuf -i10000-65000 -n1) + fi + if [[ "$KCP" == "true" ]]; then + echo "" + yellow "请选择伪装类型:" + echo " 1) 无" + echo " 2) BT下载" + echo " 3) 视频通话" + echo " 4) 微信视频通话" + echo " 5) dtls" + echo " 6) wiregard" + read -p "请选择伪装类型[默认:无]:" answer + case $answer in + 2) HEADER_TYPE="utp" ;; + 3) HEADER_TYPE="srtp" ;; + 4) HEADER_TYPE="wechat-video" ;; + 5) HEADER_TYPE="dtls" ;; + 6) HEADER_TYPE="wireguard" ;; + *) HEADER_TYPE="none" ;; + esac + yellow "伪装类型:$HEADER_TYPE" + SEED=$(cat /proc/sys/kernel/random/uuid) + fi + if [[ "$TROJAN" == "true" ]]; then + echo "" + read -p "请设置trojan密码(不输则随机生成):" PASSWORD + [[ -z "$PASSWORD" ]] && PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) + yellow " trojan密码:$PASSWORD" + fi + if [[ "$XTLS" == "true" ]]; then + echo "" + yellow "请选择流控模式:" + 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" ;; + *) red "无效选项,使用默认的xtls-rprx-direct" && FLOW="xtls-rprx-direct" ;; + esac + yellow "流控模式:$FLOW" + fi + if [[ "${WS}" == "true" ]]; then + echo "" + while true; do + read -p "请输入伪装路径,以/开头(不懂请直接回车):" WSPATH + if [[ -z "${WSPATH}" ]]; then + len=$(shuf -i5-12 -n1) + ws=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1) + WSPATH="/$ws" + break + elif [[ "${WSPATH:0:1}" != "/" ]]; then + red "伪装路径必须以/开头!" + elif [[ "${WSPATH}" == "/" ]]; then + red "不能使用根路径!" + else + break + fi + done + yellow "ws路径:$WSPATH" + fi + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + yellow "请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 高清壁纸站(https://bing.ioliu.cn)" + echo " 4) 自定义反代站点(需以http或者https开头)" + read -p "请选择伪装网站类型 [默认:高清壁纸站]:" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.ioliu.cn" + else + case $answer in + 1) PROXY_URL="" ;; + 2) + 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 + ;; + 3) PROXY_URL="https://bing.ioliu.cn" ;; + 4) + read -p "请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + red "请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + red "反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) red "请输入正确的选项!" && exit 1 ;; + esac + fi + REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3) + yellow "伪装网站:$PROXY_URL" + echo "" + yellow "是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p "请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" == "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + yellow "允许搜索引擎:$ALLOW_SPIDER" + fi + echo "" + read -p "是否安装BBR(默认安装)?[y/n]:" NEED_BBR + [[ -z "$NEED_BBR" ]] && NEED_BBR=y + [[ "$NEED_BBR" == "Y" ]] && NEED_BBR=y + yellow "安装BBR:$NEED_BBR" +} + +installNginx() { + echo "" + yellow "正在安装nginx..." + if [[ "$BT" == "false" ]]; then + if [[ $SYSTEM == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} epel-release + if [[ "$?" != "0" ]]; then + echo '[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' >/etc/yum.repos.d/nginx.repo + fi + fi + ${PACKAGE_INSTALL[int]} nginx + if [[ "$?" != "0" ]]; then + red "Nginx安装失败!" + green "建议如下:" + yellow "1. 检查VPS系统的网络设置和软件源设置,强烈建议使用系统官方软件源!" + yellow "2. 你可能用的是CentOS 8操作系统,请重置系统为CentOS 7后再安装本脚本" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + systemctl enable nginx + else + res=$(which nginx 2>/dev/null) + if [[ "$?" != "0" ]]; then + red "您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +startNginx() { + if [[ "$BT" == "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" == "false" ]]; then + systemctl stop nginx + else + res=$(ps aux | grep -i nginx) + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +getCert() { + mkdir -p /usr/local/etc/xray + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + systemctl stop xray + res=$(netstat -ntlp | grep -E ':80 |:443 ') + if [[ "${res}" != "" ]]; then + red "其他进程占用了80或443端口,请先关闭再运行一键脚本" + echo " 端口占用信息如下:" + echo ${res} + exit 1 + fi + ${PACKAGE_INSTALL[int]} socat openssl + if [[ $SYSTEM == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} cronie + systemctl start crond + systemctl enable crond + else + ${PACKAGE_INSTALL[int]} cron + systemctl start cron + systemctl enable cron + fi + curl -sL https://get.acme.sh | sh -s email=hijk.pw@protonmail.sh + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server zerossl + if [[ $BT == "false" ]]; then + if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + fi + else + if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + red "抱歉,证书申请失败" + green "建议如下:" + yellow " 1. 自行检测防火墙是否打开,如防火墙正在开启,请关闭防火墙或放行80端口" + yellow " 2. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + } + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + red "抱歉,证书申请失败" + green "建议如下:" + yellow " 1. 自行检测防火墙是否打开,如防火墙正在开启,请关闭防火墙或放行80端口" + yellow " 2. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + } + else + cp ~/xray.pem /usr/local/etc/xray/${DOMAIN}.pem + cp ~/xray.key /usr/local/etc/xray/${DOMAIN}.key + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" == "n" ]]; then + echo 'User-Agent: *' >/usr/share/nginx/html/robots.txt + echo 'Disallow: /' >>/usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + + if [[ "$BT" == "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + 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 + fi + + if [[ "$PROXY_URL" == "" ]]; then + action="" + else + action="proxy_ssl_server_name on; + proxy_pass $PROXY_URL; + proxy_set_header Accept-Encoding ''; + sub_filter \"$REMOTE_HOST\" \"$DOMAIN\"; + sub_filter_once off;" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + mkdir -p ${NGINX_CONF_PATH} + # VMESS+WS+TLS + # VLESS+WS+TLS + if [[ "$WS" == "true" ]]; then + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + return 301 https://\$server_name:${PORT}\$request_uri; + } + + server { + listen ${PORT} ssl http2; + listen [::]:${PORT} ssl http2; + server_name ${DOMAIN}; + charset utf-8; + + # ssl配置 + ssl_protocols TLSv1.1 TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + ssl_ecdh_curve secp384r1; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + ssl_certificate $CERT_FILE; + ssl_certificate_key $KEY_FILE; + + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + + location ${WSPATH} { + proxy_redirect off; + proxy_pass http://127.0.0.1:${XPORT}; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } + } + EOF + else + # VLESS+TCP+TLS + # VLESS+TCP+XTLS + # trojan + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + } + EOF + fi + fi +} + +setSelinux() { + 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 +} + +setFirewall() { + 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 +} + +installBBR() { + if [[ "$NEED_BBR" != "y" ]]; then + INSTALL_BBR=false + return + fi + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + yellow " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=$(systemd-detect-virt) + if [[ $res =~ lxc|openvz ]]; then + yellow " 由于你的VPS为OpenVZ或LXC架构的VPS,跳过安装" + INSTALL_BBR=false + return + fi + echo "net.core.default_qdisc=fq" >>/etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + green " BBR模块已启用" + INSTALL_BBR=false + return + fi + yellow " 安装BBR模块..." + if [[ $SYSTEM == "CentOS" ]]; then + if [[ "$V6_PROXY" == "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + ${PACKAGE_INSTALL[int]} --enablerepo=elrepo-kernel kernel-ml + ${PACKAGE_UNINSTALL[int]} kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + ${PACKAGE_INSTALL[int]} --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +installXray() { + rm -rf /tmp/xray + mkdir -p /tmp/xray + DOWNLOAD_LINK="https://github.com/XTLS/Xray-core/releases/download/${NEW_VER}/Xray-linux-$(archAffix).zip" + yellow "正在下载Xray文件" + curl -L -H "Cache-Control: no-cache" -o /tmp/xray/xray.zip ${DOWNLOAD_LINK} + if [ $? != 0 ]; then + red "下载Xray文件失败,请检查服务器网络设置" + exit 1 + fi + systemctl stop xray + mkdir -p /usr/local/etc/xray /usr/local/share/xray && \ + unzip /tmp/xray/xray.zip -d /tmp/xray + cp /tmp/xray/xray /usr/local/bin + cp /tmp/xray/geo* /usr/local/share/xray + chmod +x /usr/local/bin/xray || { + red "Xray安装失败" + exit 1 + } + + cat >/etc/systemd/system/xray.service <<-EOF + [Unit] + Description=Xray Service by Misaka-blog + Documentation=https://github.com/Misaka-blog + After=network.target nss-lookup.target + + [Service] + User=root + #User=nobody + #CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + #AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + NoNewPrivileges=true + ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json + Restart=on-failure + RestartPreventExitStatus=23 + + [Install] + WantedBy=multi-user.target + EOF + systemctl daemon-reload + systemctl enable xray.service +} + +trojanConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +trojanXTLSConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +vmessConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + }, + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "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 +} + +vmessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessXTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "flow": "$FLOW", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +configXray() { + mkdir -p /usr/local/xray + if [[ "$TROJAN" == "true" ]]; then + if [[ "$XTLS" == "true" ]]; then + trojanXTLSConfig + else + trojanConfig + fi + return 0 + fi + if [[ "$VLESS" == "false" ]]; then + # VMESS + kcp + if [[ "$KCP" == "true" ]]; then + vmessKCPConfig + return 0 + fi + # VMESS + if [[ "$TLS" == "false" ]]; then + vmessConfig + elif [[ "$WS" == "false" ]]; then + # VMESS+TCP+TLS + vmessTLSConfig + # VMESS+WS+TLS + else + vmessWSConfig + fi + #VLESS + else + if [[ "$KCP" == "true" ]]; then + vlessKCPConfig + return 0 + fi + # VLESS+TCP + if [[ "$WS" == "false" ]]; then + # VLESS+TCP+TLS + if [[ "$XTLS" == "false" ]]; then + vlessTLSConfig + # VLESS+TCP+XTLS + else + vlessXTLSConfig + fi + # VLESS+WS+TLS + else + vlessWSConfig + fi + fi +} + +install() { + getData + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} wget curl sudo vim unzip tar gcc openssl net-tools + if [[ $SYSTEM != "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} libssl-dev g++ + fi + [[ -z $(type -P unzip) ]] && red "unzip安装失败,请检查网络" && exit 1 + [[ $TLS == "true" || $XTLS == "true" ]] && installNginx + setFirewall + [[ $TLS == "true" || $XTLS == "true" ]] && getCert + # configNginx + [[ $TLS == "true" || $XTLS == "true" ]] && configNginx + yellow "安装Xray..." + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + yellow "Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + yellow "安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + fi + configXray + setSelinux + installBBR + start + showInfo + bbrReboot +} + +bbrReboot() { + if [[ "${INSTALL_BBR}" == "true" ]]; then + echo + echo "为使BBR模块生效,系统将在30秒后重启" + echo + echo -e "您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +update() { + res=$(status) + [[ $res -lt 2 ]] && red "Xray未安装,请先安装!" && return + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + yellow "Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + yellow "安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + stop + start + green "最新版Xray安装成功!" + fi +} + +uninstall() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + echo "" + read -p "确定卸载Xray?[y/n]:" answer + if [[ "${answer,,}" == "y" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + stop + systemctl disable xray + rm -rf /etc/systemd/system/xray.service + rm -rf /usr/local/bin/xray + rm -rf /usr/local/etc/xray + if [[ "$BT" == "false" ]]; then + systemctl disable nginx + ${PACKAGE_UNINSTALL[int]} nginx + if [[ "$PMT" == "apt" ]]; then + ${PACKAGE_UNINSTALL[int]} 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 + fi + if [[ "$domain" != "" ]]; then + rm -rf ${NGINX_CONF_PATH}${domain}.conf + fi + [[ -f ~/.acme.sh/acme.sh ]] && ~/.acme.sh/acme.sh --uninstall + green "Xray卸载成功" + fi +} + +start() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + stopNginx + startNginx + systemctl restart xray + sleep 2 + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + if [[ "$res" == "" ]]; then + red "Xray启动失败,请检查日志或查看端口是否被占用!" + else + yellow "Xray启动成功" + fi +} + +stop() { + stopNginx + systemctl stop xray + yellow "Xray停止成功" +} + +restart() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + stop + start +} + +getConfigFileInfo() { + vless="false" + tls="false" + ws="false" + xtls="false" + trojan="false" + protocol="VMess" + kcp="false" + uid=$(grep id $CONFIG_FILE | head -n1 | cut -d: -f2 | tr -d \",' ') + alterid=$(grep alterId $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + network=$(grep network $CONFIG_FILE | tail -n1 | cut -d: -f2 | tr -d \",' ') + [[ -z "$network" ]] && network="tcp" + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" != "" ]]; then + ws="true" + tls="true" + wspath=$(grep path $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + else + tls="true" + fi + if [[ "$ws" == "true" ]]; then + port=$(grep -i ssl $NGINX_CONF_PATH${domain}.conf | head -n1 | awk '{print $2}') + else + port=$(grep port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + res=$(grep -i kcp $CONFIG_FILE) + if [[ "$res" != "" ]]; then + kcp="true" + type=$(grep header -A 3 $CONFIG_FILE | grep 'type' | cut -d: -f2 | tr -d \",' ') + seed=$(grep seed $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + vmess=$(grep vmess $CONFIG_FILE) + if [[ "$vmess" == "" ]]; then + trojan=$(grep trojan $CONFIG_FILE) + if [[ "$trojan" == "" ]]; then + vless="true" + protocol="VLESS" + else + trojan="true" + password=$(grep password $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + protocol="trojan" + fi + tls="true" + encryption="none" + xtls=$(grep xtlsSettings $CONFIG_FILE) + if [[ "$xtls" != "" ]]; then + xtls="true" + flow=$(grep flow $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + else + flow="无" + fi + fi +} + +outputVmess() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"tcp\", + \"type\":\"none\", + \"host\":\"\", + \"path\":\"\", + \"tls\":\"\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +outputVmessKCP() { + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" +} + +outputTrojan() { + if [[ "$xtls" == "true" ]]; then + link="trojan://${password}@${domain}:${port}#" + 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}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + else + link="trojan://${password}@${domain}:${port}#" + 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}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + fi +} + +outputVmessTLS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接: ${PLAIN}$RED$link$PLAIN" +} + +outputVmessWS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"${wspath}\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +showInfo() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + + echo "" + yellow " Xray配置文件: ${CONFIG_FILE}" + yellow " Xray配置信息:" + + getConfigFileInfo + + echo -e " ${BLUE}协议: ${PLAIN} ${RED}${protocol}${PLAIN}" + if [[ "$trojan" == "true" ]]; then + outputTrojan + return 0 + fi + if [[ "$vless" == "false" ]]; then + if [[ "$kcp" == "true" ]]; then + outputVmessKCP + return 0 + fi + if [[ "$tls" == "false" ]]; then + outputVmess + elif [[ "$ws" == "false" ]]; then + outputVmessTLS + else + outputVmessWS + fi + else + if [[ "$kcp" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" + return 0 + fi + if [[ "$xtls" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + elif [[ "$ws" == "false" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN}${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + else + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + fi + fi +} + +showLog() { + res=$(status) + [[ $res -lt 2 ]] && red "Xray未安装,请先安装!" && exit 1 + journalctl -xen -u xray --no-pager +} + +warpmenu(){ + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/misakawarp.sh && bash misakawarp.sh +} + +setdns64(){ + if [[ -n $(curl -s6m8 https://ip.gs) ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + fi +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}Xray一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) & MisakaNo #" + echo -e "# ${GREEN}博客${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo -e " " + echo -e " ${GREEN}1.${PLAIN} 安装Xray-VMESS" + echo -e " ${GREEN}2.${PLAIN} 安装Xray-${BLUE}VMESS+mKCP${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装Xray-VMESS+TCP+TLS" + echo -e " ${GREEN}4.${PLAIN} 安装Xray-${BLUE}VMESS+WS+TLS${PLAIN}${RED}(可过cdn)${PLAIN}" + echo -e " ${GREEN}5.${PLAIN} 安装Xray-${BLUE}VLESS+mKCP${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 安装Xray-VLESS+TCP+TLS" + echo -e " ${GREEN}7.${PLAIN} 安装Xray-${BLUE}VLESS+WS+TLS${PLAIN}${RED}(可过cdn)${PLAIN}" + echo -e " ${GREEN}8.${PLAIN} 安装Xray-${BLUE}VLESS+TCP+XTLS" + echo -e " ${GREEN}9.${PLAIN} 安装${BLUE}Trojan" + echo -e " ${GREEN}10.${PLAIN} 安装${BLUE}Trojan+XTLS" + echo " -------------" + echo -e " ${GREEN}11.${PLAIN} 更新Xray" + echo -e " ${GREEN}12. ${RED}卸载Xray${PLAIN}" + echo " -------------" + echo -e " ${GREEN}13.${PLAIN} 启动Xray" + echo -e " ${GREEN}14.${PLAIN} 重启Xray" + echo -e " ${GREEN}15.${PLAIN} 停止Xray" + echo " -------------" + echo -e " ${GREEN}16.${PLAIN} 查看Xray配置" + echo -e " ${GREEN}17.${PLAIN} 查看Xray日志" + echo " -------------" + echo -e " ${GREEN}18.${PLAIN} 安装并管理WARP" + echo -e " ${GREEN}19.${PLAIN} 设置DNS64服务器" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo -n " 当前状态:" + statusText + echo + + read -p "请选择操作[0-19]:" answer + case $answer in + 0) exit 1 ;; + 1) install ;; + 2) KCP="true" && install ;; + 3) TLS="true" && install ;; + 4) TLS="true" && WS="true" && install ;; + 5) VLESS="true" && KCP="true" && install ;; + 6) VLESS="true" && TLS="true" && install ;; + 7) VLESS="true" && TLS="true" && WS="true" && install ;; + 8) VLESS="true" && TLS="true" && XTLS="true" && install ;; + 9) TROJAN="true" && TLS="true" && install ;; + 10) TROJAN="true" && TLS="true" && XTLS="true" && install ;; + 11) update ;; + 12) uninstall ;; + 13) start ;; + 14) restart ;; + 15) stop ;; + 16) showInfo ;; + 17) showLog ;; + 18) warpmenu ;; + 19) setdns64 ;; + *) red "请选择正确的操作!" && exit 1 ;; + esac +} + +action=$1 +[[ -z $1 ]] && action=menu + +case "$action" in +menu | update | uninstall | start | restart | stop | showInfo | showLog) ${action} ;; +*) echo " 参数错误" && echo " 用法: $(basename $0) [menu|update|uninstall|start|restart|stop|showInfo|showLog]" ;; +esac \ No newline at end of file diff --git a/misakaxray/xray3.sh b/misakaxray/xray3.sh new file mode 100644 index 00000000..6c02fbc7 --- /dev/null +++ b/misakaxray/xray3.sh @@ -0,0 +1,1795 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +RED="\033[31m" +GREEN="\033[32m" +YELLOW="\033[33m" +BLUE="\033[36m" +PLAIN='\033[0m' + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 +[[ -z $(type -P curl) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl + +SITES=( + http://www.zhuizishu.com/ + http://xs.56dyc.com/ + http://www.ddxsku.com/ + http://www.biqu6.com/ + https://www.wenshulou.cc/ + http://www.55shuba.com/ + http://www.39shubao.com/ + https://www.23xsw.cc/ + https://www.jueshitangmen.info/ + https://www.zhetian.org/ + http://www.bequgexs.com/ + http://www.tjwl.com/ +) + +CONFIG_FILE="/usr/local/etc/xray/config.json" + +IP=$(curl -s4m8 ip.sb) || IP=$(curl -s6m8 ip.sb) + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" +res=$(which bt 2>/dev/null) +[[ "$res" != "" ]] && BT="true" && NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" + +VLESS="false" +TROJAN="false" +TLS="false" +WS="false" +XTLS="false" +KCP="false" + +configNeedNginx() { + local ws=$(grep wsSettings $CONFIG_FILE) + [[ -z "$ws" ]] && echo no && return + echo yes +} + +needNginx() { + [[ "$WS" == "false" ]] && echo no && return + echo yes +} + +status() { + [[ ! -f /usr/local/bin/xray ]] && echo 0 && return + [[ ! -f $CONFIG_FILE ]] && echo 1 && return + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + [[ -z "$res" ]] && echo 2 && return + + if [[ $(configNeedNginx) != "yes" ]]; then + echo 3 + else + res=$(ss -nutlp | grep -i nginx) + if [[ -z "$res" ]]; then + echo 4 + else + echo 5 + fi + fi +} + +statusText() { + res=$(status) + case $res in + 2) echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN} ;; + 3) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN} ;; + 4) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN}, ${RED}Nginx未运行${PLAIN} ;; + 5) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行, Nginx正在运行${PLAIN} ;; + *) echo -e ${RED}未安装${PLAIN} ;; + esac +} + +normalizeVersion() { + latestXrayVer=v$(curl -Ls "https://data.jsdelivr.com/v1/package/resolve/gh/XTLS/Xray-core" | grep '"version":' | sed -E 's/.*"([^"]+)".*/\1/') + if [ -n "$1" ]; then + case "$1" in + v*) echo "$1" ;; + http*) echo $latestXrayVer ;; + *) echo "v$1" ;; + esac + else + echo "" + fi +} + +# 1: new Xray. 0: no. 1: yes. 2: not installed. 3: check failed. +getVersion() { + VER=$(/usr/local/bin/xray version 2>/dev/null | head -n1 | awk '{print $2}') + RETVAL=$? + CUR_VER="$(normalizeVersion "$(echo "$VER" | head -n 1 | cut -d " " -f2)")" + TAG_URL="https://data.jsdelivr.com/v1/package/resolve/gh/XTLS/Xray-core" + NEW_VER="$(normalizeVersion "$(curl -s "${TAG_URL}" --connect-timeout 10 | grep 'version' | cut -d\" -f4)")" + + if [[ $? -ne 0 ]] || [[ $NEW_VER == "" ]]; then + red "检测 Xray 版本失败,可能是超出 Github API 限制,请稍后再试" + 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' ;; + armv5tel) echo 'arm32-v5' ;; + armv6l) echo 'arm32-v6' ;; + armv7 | armv7l) echo 'arm32-v7a' ;; + armv8 | aarch64) echo 'arm64-v8a' ;; + mips64le) echo 'mips64le' ;; + mips64) echo 'mips64' ;; + mipsle) echo 'mips32le' ;; + mips) echo 'mips32' ;; + ppc64le) echo 'ppc64le' ;; + ppc64) echo 'ppc64' ;; + ppc64le) echo 'ppc64le' ;; + riscv64) echo 'riscv64' ;; + s390x) echo 's390x' ;; + *) red " 不支持的CPU架构!" && exit 1 ;; + esac + + return 0 +} + +getData() { + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + echo "Xray一键脚本,运行之前请确认如下条件已经具备:" + yellow " 1. 一个伪装域名" + yellow " 2. 伪装域名DNS解析指向当前服务器ip(${IP})" + yellow " 3. 如果/root目录下有 xray.pem 和 xray.key 证书密钥文件,无需理会条件2" + echo " " + read -p "确认满足以上条件请按y,按其他键退出脚本:" answer + [[ "${answer,,}" != "y" ]] && exit 1 + echo "" + while true; do + read -p "请输入伪装域名:" DOMAIN + if [[ -z "${DOMAIN}" ]]; then + red " 域名输入错误,请重新输入!" + else + break + fi + done + DOMAIN=${DOMAIN,,} + yellow "伪装域名(host):$DOMAIN" + echo "" + if [[ -f ~/xray.pem && -f ~/xray.key ]]; then + yellow "检测到自有证书,将使用自有证书部署" + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + else + resolve=$(curl -sm8 ipget.net/?ip=${DOMAIN}) + if [[ $resolve != $IP ]]; then + yellow "${DOMAIN} 解析结果:${resolve}" + red "域名未解析到当前服务器IP(${IP})!" + green "建议如下:" + yellow " 1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow " 2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + echo "" + if [[ "$(needNginx)" == "no" ]]; then + if [[ "$TLS" == "true" ]]; then + read -p "请输入xray监听端口 [默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + else + read -p "请输入xray监听端口 [100-65535的一个数字]:" PORT + [[ -z "${PORT}" ]] && PORT=$(shuf -i200-65000 -n1) + if [[ "${PORT:0:1}" == "0" ]]; then + red "端口不能以0开头" + exit 1 + fi + fi + yellow "xray端口:$PORT" + else + read -p "请输入Nginx监听端口[100-65535的一个数字,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + [ "${PORT:0:1}" = "0" ] && red "端口不能以0开头" && exit 1 + yellow " Nginx端口:$PORT" + XPORT=$(shuf -i10000-65000 -n1) + fi + if [[ "$KCP" == "true" ]]; then + echo "" + yellow "请选择伪装类型:" + echo " 1) 无" + echo " 2) BT下载" + echo " 3) 视频通话" + echo " 4) 微信视频通话" + echo " 5) dtls" + echo " 6) wiregard" + read -p "请选择伪装类型[默认:无]:" answer + case $answer in + 2) HEADER_TYPE="utp" ;; + 3) HEADER_TYPE="srtp" ;; + 4) HEADER_TYPE="wechat-video" ;; + 5) HEADER_TYPE="dtls" ;; + 6) HEADER_TYPE="wireguard" ;; + *) HEADER_TYPE="none" ;; + esac + yellow "伪装类型:$HEADER_TYPE" + SEED=$(cat /proc/sys/kernel/random/uuid) + fi + if [[ "$TROJAN" == "true" ]]; then + echo "" + read -p "请设置trojan密码(不输则随机生成):" PASSWORD + [[ -z "$PASSWORD" ]] && PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) + yellow " trojan密码:$PASSWORD" + fi + if [[ "$XTLS" == "true" ]]; then + echo "" + yellow "请选择流控模式:" + 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" ;; + *) red "无效选项,使用默认的xtls-rprx-direct" && FLOW="xtls-rprx-direct" ;; + esac + yellow "流控模式:$FLOW" + fi + if [[ "${WS}" == "true" ]]; then + echo "" + while true; do + read -p "请输入伪装路径,以/开头(不懂请直接回车):" WSPATH + if [[ -z "${WSPATH}" ]]; then + len=$(shuf -i5-12 -n1) + ws=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1) + WSPATH="/$ws" + break + elif [[ "${WSPATH:0:1}" != "/" ]]; then + red "伪装路径必须以/开头!" + elif [[ "${WSPATH}" == "/" ]]; then + red "不能使用根路径!" + else + break + fi + done + yellow "ws路径:$WSPATH" + fi + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + yellow "请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 高清壁纸站(https://bing.ioliu.cn)" + echo " 4) 自定义反代站点(需以http或者https开头)" + read -p "请选择伪装网站类型 [默认:高清壁纸站]:" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.ioliu.cn" + else + case $answer in + 1) PROXY_URL="" ;; + 2) + 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 + ;; + 3) PROXY_URL="https://bing.ioliu.cn" ;; + 4) + read -p "请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + red "请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + red "反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) red "请输入正确的选项!" && exit 1 ;; + esac + fi + REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3) + yellow "伪装网站:$PROXY_URL" + echo "" + yellow "是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p "请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" == "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + yellow "允许搜索引擎:$ALLOW_SPIDER" + fi + echo "" + read -p "是否安装BBR(默认安装)?[y/n]:" NEED_BBR + [[ -z "$NEED_BBR" ]] && NEED_BBR=y + [[ "$NEED_BBR" == "Y" ]] && NEED_BBR=y + yellow "安装BBR:$NEED_BBR" +} + +installNginx() { + echo "" + yellow "正在安装nginx..." + if [[ "$BT" == "false" ]]; then + if [[ $SYSTEM == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} epel-release + if [[ "$?" != "0" ]]; then + echo '[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' >/etc/yum.repos.d/nginx.repo + fi + fi + ${PACKAGE_INSTALL[int]} nginx + if [[ "$?" != "0" ]]; then + red "Nginx安装失败!" + green "建议如下:" + yellow "1. 检查VPS系统的网络设置和软件源设置,强烈建议使用系统官方软件源!" + yellow "2. 你可能用的是CentOS 8操作系统,请重置系统为CentOS 7后再安装本脚本" + yellow "3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + systemctl enable nginx + else + res=$(which nginx 2>/dev/null) + if [[ "$?" != "0" ]]; then + red "您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +startNginx() { + if [[ "$BT" == "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" == "false" ]]; then + systemctl stop nginx + else + res=$(ps aux | grep -i nginx) + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +getCert() { + mkdir -p /usr/local/etc/xray + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + systemctl stop xray + res=$(netstat -ntlp | grep -E ':80 |:443 ') + if [[ "${res}" != "" ]]; then + red "其他进程占用了80或443端口,请先关闭再运行一键脚本" + echo " 端口占用信息如下:" + echo ${res} + exit 1 + fi + ${PACKAGE_INSTALL[int]} socat openssl + if [[ $SYSTEM == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} cronie + systemctl start crond + systemctl enable crond + else + ${PACKAGE_INSTALL[int]} cron + systemctl start cron + systemctl enable cron + fi + curl -sL https://get.acme.sh | sh -s email=hijk.pw@protonmail.sh + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server zerossl + if [[ $BT == "false" ]]; then + if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + fi + else + if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + red "抱歉,证书申请失败" + green "建议如下:" + yellow " 1. 自行检测防火墙是否打开,如防火墙正在开启,请关闭防火墙或放行80端口" + yellow " 2. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + } + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + red "抱歉,证书申请失败" + green "建议如下:" + yellow " 1. 自行检测防火墙是否打开,如防火墙正在开启,请关闭防火墙或放行80端口" + yellow " 2. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + } + else + cp ~/xray.pem /usr/local/etc/xray/${DOMAIN}.pem + cp ~/xray.key /usr/local/etc/xray/${DOMAIN}.key + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" == "n" ]]; then + echo 'User-Agent: *' >/usr/share/nginx/html/robots.txt + echo 'Disallow: /' >>/usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + + if [[ "$BT" == "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + 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 + fi + + if [[ "$PROXY_URL" == "" ]]; then + action="" + else + action="proxy_ssl_server_name on; + proxy_pass $PROXY_URL; + proxy_set_header Accept-Encoding ''; + sub_filter \"$REMOTE_HOST\" \"$DOMAIN\"; + sub_filter_once off;" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + mkdir -p ${NGINX_CONF_PATH} + # VMESS+WS+TLS + # VLESS+WS+TLS + if [[ "$WS" == "true" ]]; then + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + return 301 https://\$server_name:${PORT}\$request_uri; + } + + server { + listen ${PORT} ssl http2; + listen [::]:${PORT} ssl http2; + server_name ${DOMAIN}; + charset utf-8; + + # ssl配置 + ssl_protocols TLSv1.1 TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + ssl_ecdh_curve secp384r1; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + ssl_certificate $CERT_FILE; + ssl_certificate_key $KEY_FILE; + + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + + location ${WSPATH} { + proxy_redirect off; + proxy_pass http://127.0.0.1:${XPORT}; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } + } + EOF + else + # VLESS+TCP+TLS + # VLESS+TCP+XTLS + # trojan + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + } + EOF + fi + fi +} + +setSelinux() { + 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 +} + +setFirewall() { + 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 +} + +installBBR() { + if [[ "$NEED_BBR" != "y" ]]; then + INSTALL_BBR=false + return + fi + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + yellow " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=$(systemd-detect-virt) + if [[ $res =~ lxc|openvz ]]; then + yellow " 由于你的VPS为OpenVZ或LXC架构的VPS,跳过安装" + INSTALL_BBR=false + return + fi + echo "net.core.default_qdisc=fq" >>/etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + green " BBR模块已启用" + INSTALL_BBR=false + return + fi + yellow " 安装BBR模块..." + if [[ $SYSTEM == "CentOS" ]]; then + if [[ "$V6_PROXY" == "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + ${PACKAGE_INSTALL[int]} --enablerepo=elrepo-kernel kernel-ml + ${PACKAGE_UNINSTALL[int]} kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + ${PACKAGE_INSTALL[int]} --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +installXray() { + rm -rf /tmp/xray + mkdir -p /tmp/xray + DOWNLOAD_LINK="https://github.com/XTLS/Xray-core/releases/download/${NEW_VER}/Xray-linux-$(archAffix).zip" + yellow "正在下载Xray文件" + curl -L -H "Cache-Control: no-cache" -o /tmp/xray/xray.zip ${DOWNLOAD_LINK} + if [ $? != 0 ]; then + red "下载Xray文件失败,请检查服务器网络设置" + exit 1 + fi + systemctl stop xray + mkdir -p /usr/local/etc/xray /usr/local/share/xray && \ + unzip /tmp/xray/xray.zip -d /tmp/xray + cp /tmp/xray/xray /usr/local/bin + cp /tmp/xray/geo* /usr/local/share/xray + chmod +x /usr/local/bin/xray || { + red "Xray安装失败" + exit 1 + } + + cat >/etc/systemd/system/xray.service <<-EOF + [Unit] + Description=Xray Service by Misaka-blog + Documentation=https://github.com/Misaka-blog + After=network.target nss-lookup.target + + [Service] + User=root + #User=nobody + #CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + #AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + NoNewPrivileges=true + ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json + Restart=on-failure + RestartPreventExitStatus=23 + + [Install] + WantedBy=multi-user.target + EOF + systemctl daemon-reload + systemctl enable xray.service +} + +trojanConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +trojanXTLSConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +vmessConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + }, + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "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 +} + +vmessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessXTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "flow": "$FLOW", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +configXray() { + mkdir -p /usr/local/xray + if [[ "$TROJAN" == "true" ]]; then + if [[ "$XTLS" == "true" ]]; then + trojanXTLSConfig + else + trojanConfig + fi + return 0 + fi + if [[ "$VLESS" == "false" ]]; then + # VMESS + kcp + if [[ "$KCP" == "true" ]]; then + vmessKCPConfig + return 0 + fi + # VMESS + if [[ "$TLS" == "false" ]]; then + vmessConfig + elif [[ "$WS" == "false" ]]; then + # VMESS+TCP+TLS + vmessTLSConfig + # VMESS+WS+TLS + else + vmessWSConfig + fi + #VLESS + else + if [[ "$KCP" == "true" ]]; then + vlessKCPConfig + return 0 + fi + # VLESS+TCP + if [[ "$WS" == "false" ]]; then + # VLESS+TCP+TLS + if [[ "$XTLS" == "false" ]]; then + vlessTLSConfig + # VLESS+TCP+XTLS + else + vlessXTLSConfig + fi + # VLESS+WS+TLS + else + vlessWSConfig + fi + fi +} + +install() { + getData + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} wget curl sudo vim unzip tar gcc openssl net-tools + if [[ $SYSTEM != "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} libssl-dev g++ + fi + [[ -z $(type -P unzip) ]] && red "unzip安装失败,请检查网络" && exit 1 + installNginx + setFirewall + [[ $TLS == "true" || $XTLS == "true" ]] && getCert + configNginx + yellow "安装Xray..." + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + yellow "Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + yellow "安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + fi + configXray + setSelinux + installBBR + start + showInfo + bbrReboot +} + +bbrReboot() { + if [[ "${INSTALL_BBR}" == "true" ]]; then + echo + echo "为使BBR模块生效,系统将在30秒后重启" + echo + echo -e "您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +update() { + res=$(status) + [[ $res -lt 2 ]] && red "Xray未安装,请先安装!" && return + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + yellow "Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + yellow "安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + stop + start + green "最新版Xray安装成功!" + fi +} + +uninstall() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + echo "" + read -p "确定卸载Xray?[y/n]:" answer + if [[ "${answer,,}" == "y" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + stop + systemctl disable xray + rm -rf /etc/systemd/system/xray.service + rm -rf /usr/local/bin/xray + rm -rf /usr/local/etc/xray + if [[ "$BT" == "false" ]]; then + systemctl disable nginx + ${PACKAGE_UNINSTALL[int]} nginx + if [[ "$PMT" == "apt" ]]; then + ${PACKAGE_UNINSTALL[int]} 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 + fi + if [[ "$domain" != "" ]]; then + rm -rf ${NGINX_CONF_PATH}${domain}.conf + fi + [[ -f ~/.acme.sh/acme.sh ]] && ~/.acme.sh/acme.sh --uninstall + green "Xray卸载成功" + fi +} + +start() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + stopNginx + startNginx + systemctl restart xray + sleep 2 + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + if [[ "$res" == "" ]]; then + red "Xray启动失败,请检查日志或查看端口是否被占用!" + else + yellow "Xray启动成功" + fi +} + +stop() { + stopNginx + systemctl stop xray + yellow "Xray停止成功" +} + +restart() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + stop + start +} + +getConfigFileInfo() { + vless="false" + tls="false" + ws="false" + xtls="false" + trojan="false" + protocol="VMess" + kcp="false" + uid=$(grep id $CONFIG_FILE | head -n1 | cut -d: -f2 | tr -d \",' ') + alterid=$(grep alterId $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + network=$(grep network $CONFIG_FILE | tail -n1 | cut -d: -f2 | tr -d \",' ') + [[ -z "$network" ]] && network="tcp" + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" != "" ]]; then + ws="true" + tls="true" + wspath=$(grep path $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + else + tls="true" + fi + if [[ "$ws" == "true" ]]; then + port=$(grep -i ssl $NGINX_CONF_PATH${domain}.conf | head -n1 | awk '{print $2}') + else + port=$(grep port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + res=$(grep -i kcp $CONFIG_FILE) + if [[ "$res" != "" ]]; then + kcp="true" + type=$(grep header -A 3 $CONFIG_FILE | grep 'type' | cut -d: -f2 | tr -d \",' ') + seed=$(grep seed $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + vmess=$(grep vmess $CONFIG_FILE) + if [[ "$vmess" == "" ]]; then + trojan=$(grep trojan $CONFIG_FILE) + if [[ "$trojan" == "" ]]; then + vless="true" + protocol="VLESS" + else + trojan="true" + password=$(grep password $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + protocol="trojan" + fi + tls="true" + encryption="none" + xtls=$(grep xtlsSettings $CONFIG_FILE) + if [[ "$xtls" != "" ]]; then + xtls="true" + flow=$(grep flow $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + else + flow="无" + fi + fi +} + +outputVmess() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"tcp\", + \"type\":\"none\", + \"host\":\"\", + \"path\":\"\", + \"tls\":\"\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +outputVmessKCP() { + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" +} + +outputTrojan() { + if [[ "$xtls" == "true" ]]; then + link="trojan://${password}@${domain}:${port}#" + 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}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + else + link="trojan://${password}@${domain}:${port}#" + 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}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + fi +} + +outputVmessTLS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接: ${PLAIN}$RED$link$PLAIN" +} + +outputVmessWS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"${wspath}\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +showInfo() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + + echo "" + yellow " Xray配置文件: ${CONFIG_FILE}" + yellow " Xray配置信息:" + + getConfigFileInfo + + echo -e " ${BLUE}协议: ${PLAIN} ${RED}${protocol}${PLAIN}" + if [[ "$trojan" == "true" ]]; then + outputTrojan + return 0 + fi + if [[ "$vless" == "false" ]]; then + if [[ "$kcp" == "true" ]]; then + outputVmessKCP + return 0 + fi + if [[ "$tls" == "false" ]]; then + outputVmess + elif [[ "$ws" == "false" ]]; then + outputVmessTLS + else + outputVmessWS + fi + else + if [[ "$kcp" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" + return 0 + fi + if [[ "$xtls" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + elif [[ "$ws" == "false" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN}${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + else + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + fi + fi +} + +showLog() { + res=$(status) + [[ $res -lt 2 ]] && red "Xray未安装,请先安装!" && exit 1 + journalctl -xen -u xray --no-pager +} + +warpmenu(){ + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/misakawarp.sh && bash misakawarp.sh +} + +setdns64(){ + if [[ -n $(curl -s6m8 https://ip.gs) ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + fi +} + +system_optimize(){ + if [ ! -f "/etc/sysctl.conf" ]; then + touch /etc/sysctl.conf + fi + sed -i '/net.ipv4.tcp_retries2/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_slow_start_after_idle/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_fastopen/d' /etc/sysctl.conf + sed -i '/fs.file-max/d' /etc/sysctl.conf + sed -i '/fs.inotify.max_user_instances/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_fin_timeout/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_tw_reuse/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_max_syn_backlog/d' /etc/sysctl.conf + sed -i '/net.ipv4.ip_local_port_range/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_max_tw_buckets/d' /etc/sysctl.conf + sed -i '/net.ipv4.route.gc_timeout/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_synack_retries/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_syn_retries/d' /etc/sysctl.conf + sed -i '/net.core.somaxconn/d' /etc/sysctl.conf + sed -i '/net.core.netdev_max_backlog/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_timestamps/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_max_orphans/d' /etc/sysctl.conf + sed -i '/net.ipv4.ip_forward/d' /etc/sysctl.conf + + echo "net.ipv4.tcp_retries2 = 8 + net.ipv4.tcp_slow_start_after_idle = 0 + fs.file-max = 1000000 + fs.inotify.max_user_instances = 8192 + net.ipv4.tcp_syncookies = 1 + net.ipv4.tcp_fin_timeout = 30 + net.ipv4.tcp_tw_reuse = 1 + net.ipv4.ip_local_port_range = 1024 65000 + net.ipv4.tcp_max_syn_backlog = 16384 + net.ipv4.tcp_max_tw_buckets = 6000 + net.ipv4.route.gc_timeout = 100 + net.ipv4.tcp_syn_retries = 1 + net.ipv4.tcp_synack_retries = 1 + net.core.somaxconn = 32768 + net.core.netdev_max_backlog = 32768 + net.ipv4.tcp_timestamps = 0 + net.ipv4.tcp_max_orphans = 32768 + # forward ipv4 + #net.ipv4.ip_forward = 1" >>/etc/sysctl.conf + sysctl -p + echo "* soft nofile 1000000 + * hard nofile 1000000" >/etc/security/limits.conf + echo "ulimit -SHn 1000000" >>/etc/profile + read -p "需要重启VPS,系统优化配置才能生效,是否现在重启? [Y/n] :" yn + [[ -z $yn ]] && yn="y" + if [[ $yn == [Yy] ]]; then + yellow "VPS 重启中..." + reboot + fi +} + +open_ports(){ + systemctl stop firewalld.service + systemctl disable firewalld.service + setenforce 0 + ufw disable + iptables -P INPUT ACCEPT + iptables -P FORWARD ACCEPT + iptables -P OUTPUT ACCEPT + iptables -t nat -F + iptables -t mangle -F + iptables -F + iptables -X + netfilter-persistent save + yellow "VPS中的所有网络端口已开启" +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}Xray一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) & MisakaNo #" + echo -e "# ${GREEN}博客${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo -e " " + echo -e " ${GREEN}1.${PLAIN} 安装Xray-VMESS${PLAIN}${RED}(不推荐)${PLAIN}" + echo -e " ${GREEN}2.${PLAIN} 安装Xray-${BLUE}VMESS+mKCP${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装Xray-VMESS+TCP+TLS" + echo -e " ${GREEN}4.${PLAIN} 安装Xray-${BLUE}VMESS+WS+TLS${PLAIN}${RED}(推荐)(可过支持WebSocket的CDN)${PLAIN}" + echo -e " ${GREEN}5.${PLAIN} 安装Xray-${BLUE}VLESS+mKCP${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 安装Xray-VLESS+TCP+TLS" + echo -e " ${GREEN}7.${PLAIN} 安装Xray-${BLUE}VLESS+WS+TLS${PLAIN}${RED}(推荐)(可过支持WebSocket的CDN)${PLAIN}" + echo -e " ${GREEN}8.${PLAIN} 安装Xray-${BLUE}VLESS+TCP+XTLS" + echo -e " ${GREEN}9.${PLAIN} 安装${BLUE}Trojan" + echo -e " ${GREEN}10.${PLAIN} 安装${BLUE}Trojan+XTLS" + echo " -------------" + echo -e " ${GREEN}11.${PLAIN} 更新Xray" + echo -e " ${GREEN}12. ${RED}卸载Xray${PLAIN}" + echo " -------------" + echo -e " ${GREEN}13.${PLAIN} 启动Xray" + echo -e " ${GREEN}14.${PLAIN} 重启Xray" + echo -e " ${GREEN}15.${PLAIN} 停止Xray" + echo " -------------" + echo -e " ${GREEN}16.${PLAIN} 查看Xray配置" + echo -e " ${GREEN}17.${PLAIN} 查看Xray日志" + echo " -------------" + echo -e " ${GREEN}18.${PLAIN} 安装并管理WARP" + echo -e " ${GREEN}19.${PLAIN} 设置DNS64服务器" + echo -e " ${GREEN}20.${PLAIN} VPS系统优化" + echo -e " ${GREEN}21.${PLAIN} 放开VPS的所有端口" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo -n " 当前Xray状态:" + statusText + echo + + read -p "请选择操作[0-21]:" answer + case $answer in + 0) exit 1 ;; + 1) install ;; + 2) KCP="true" && install ;; + 3) TLS="true" && install ;; + 4) TLS="true" && WS="true" && install ;; + 5) VLESS="true" && KCP="true" && install ;; + 6) VLESS="true" && TLS="true" && install ;; + 7) VLESS="true" && TLS="true" && WS="true" && install ;; + 8) VLESS="true" && TLS="true" && XTLS="true" && install ;; + 9) TROJAN="true" && TLS="true" && install ;; + 10) TROJAN="true" && TLS="true" && XTLS="true" && install ;; + 11) update ;; + 12) uninstall ;; + 13) start ;; + 14) restart ;; + 15) stop ;; + 16) showInfo ;; + 17) showLog ;; + 18) warpmenu ;; + 19) setdns64 ;; + 20) system_optimize ;; + 21) open_ports ;; + *) red "请选择正确的操作!" && exit 1 ;; + esac +} + +action=$1 +[[ -z $1 ]] && action=menu + +case "$action" in + menu | update | uninstall | start | restart | stop | showInfo | showLog) ${action} ;; + *) echo " 参数错误" && echo " 用法: $(basename $0) [menu|update|uninstall|start|restart|stop|showInfo|showLog]" ;; +esac diff --git a/misakaxray/xray4.sh b/misakaxray/xray4.sh new file mode 100644 index 00000000..b5dc6f26 --- /dev/null +++ b/misakaxray/xray4.sh @@ -0,0 +1,1813 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +RED="\033[31m" +GREEN="\033[32m" +YELLOW="\033[33m" +BLUE="\033[36m" +PLAIN='\033[0m' + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 +[[ -z $(type -P curl) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl + +SITES=( + http://www.zhuizishu.com/ + http://xs.56dyc.com/ + http://www.ddxsku.com/ + http://www.biqu6.com/ + https://www.wenshulou.cc/ + http://www.55shuba.com/ + http://www.39shubao.com/ + https://www.23xsw.cc/ + https://www.jueshitangmen.info/ + https://www.zhetian.org/ + http://www.bequgexs.com/ + http://www.tjwl.com/ +) + +CONFIG_FILE="/usr/local/etc/xray/config.json" + +IP=$(curl -s6m8 ip.sb) || IP=$(curl -s4m8 ip.sb) + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" +res=$(which bt 2>/dev/null) +[[ "$res" != "" ]] && BT="true" && NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" + +VLESS="false" +TROJAN="false" +TLS="false" +WS="false" +XTLS="false" +KCP="false" + +checkCentOS8() { + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +configNeedNginx() { + local ws=$(grep wsSettings $CONFIG_FILE) + [[ -z "$ws" ]] && echo no && return + echo yes +} + +needNginx() { + [[ "$WS" == "false" ]] && echo no && return + echo yes +} + +status() { + [[ ! -f /usr/local/bin/xray ]] && echo 0 && return + [[ ! -f $CONFIG_FILE ]] && echo 1 && return + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + [[ -z "$res" ]] && echo 2 && return + + if [[ $(configNeedNginx) != "yes" ]]; then + echo 3 + else + res=$(ss -nutlp | grep -i nginx) + if [[ -z "$res" ]]; then + echo 4 + else + echo 5 + fi + fi +} + +statusText() { + res=$(status) + case $res in + 2) echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN} ;; + 3) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN} ;; + 4) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN}, ${RED}Nginx未运行${PLAIN} ;; + 5) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行, Nginx正在运行${PLAIN} ;; + *) echo -e ${RED}未安装${PLAIN} ;; + esac +} + +normalizeVersion() { + latestXrayVer=v$(curl -Ls "https://data.jsdelivr.com/v1/package/resolve/gh/XTLS/Xray-core" | grep '"version":' | sed -E 's/.*"([^"]+)".*/\1/') + if [ -n "$1" ]; then + case "$1" in + v*) echo "$1" ;; + http*) echo $latestXrayVer ;; + *) echo "v$1" ;; + esac + else + echo "" + fi +} + +# 1: new Xray. 0: no. 1: yes. 2: not installed. 3: check failed. +getVersion() { + VER=$(/usr/local/bin/xray version 2>/dev/null | head -n1 | awk '{print $2}') + RETVAL=$? + CUR_VER="$(normalizeVersion "$(echo "$VER" | head -n 1 | cut -d " " -f2)")" + TAG_URL="https://data.jsdelivr.com/v1/package/resolve/gh/XTLS/Xray-core" + NEW_VER="$(normalizeVersion "$(curl -s "${TAG_URL}" --connect-timeout 10 | grep 'version' | cut -d\" -f4)")" + + if [[ $? -ne 0 ]] || [[ $NEW_VER == "" ]]; then + red "检测 Xray 版本失败,可能是VPS网络错误,请检查后重试" + 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' ;; + armv5tel) echo 'arm32-v5' ;; + armv6l) echo 'arm32-v6' ;; + armv7 | armv7l) echo 'arm32-v7a' ;; + armv8 | aarch64) echo 'arm64-v8a' ;; + mips64le) echo 'mips64le' ;; + mips64) echo 'mips64' ;; + mipsle) echo 'mips32le' ;; + mips) echo 'mips32' ;; + ppc64le) echo 'ppc64le' ;; + ppc64) echo 'ppc64' ;; + ppc64le) echo 'ppc64le' ;; + riscv64) echo 'riscv64' ;; + s390x) echo 's390x' ;; + *) red " 不支持的CPU架构!" && exit 1 ;; + esac + + return 0 +} + +getData() { + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + echo "Xray一键脚本,运行之前请确认如下条件已经具备:" + yellow " 1. 一个伪装域名" + yellow " 2. 伪装域名DNS解析指向当前服务器ip(${IP})" + yellow " 3. 如果/root目录下有 xray.pem 和 xray.key 证书密钥文件,无需理会条件2" + echo " " + read -p "确认满足以上条件请按y,按其他键退出脚本:" answer + [[ "${answer,,}" != "y" ]] && exit 1 + echo "" + while true; do + read -p "请输入伪装域名:" DOMAIN + if [[ -z "${DOMAIN}" ]]; then + red " 域名输入错误,请重新输入!" + else + break + fi + done + DOMAIN=${DOMAIN,,} + yellow "伪装域名(host):$DOMAIN" + echo "" + if [[ -f ~/xray.pem && -f ~/xray.key ]]; then + yellow "检测到自有证书,将使用自有证书部署" + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + else + resolve=$(curl -sm8 ipget.net/?ip=${DOMAIN}) + if [[ $resolve != $IP ]]; then + yellow "${DOMAIN} 解析结果:${resolve}" + red "域名未解析到当前服务器IP(${IP})!" + green "建议如下:" + yellow " 1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow " 2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + echo "" + if [[ "$(needNginx)" == "no" ]]; then + if [[ "$TLS" == "true" ]]; then + read -p "请输入xray监听端口 [默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + else + read -p "请输入xray监听端口 [100-65535的一个数字]:" PORT + [[ -z "${PORT}" ]] && PORT=$(shuf -i200-65000 -n1) + if [[ "${PORT:0:1}" == "0" ]]; then + red "端口不能以0开头" + exit 1 + fi + fi + yellow "xray端口:$PORT" + else + read -p "请输入Nginx监听端口[100-65535的一个数字,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + [ "${PORT:0:1}" = "0" ] && red "端口不能以0开头" && exit 1 + yellow " Nginx端口:$PORT" + XPORT=$(shuf -i10000-65000 -n1) + fi + if [[ "$KCP" == "true" ]]; then + echo "" + yellow "请选择伪装类型:" + echo " 1) 无" + echo " 2) BT下载" + echo " 3) 视频通话" + echo " 4) 微信视频通话" + echo " 5) dtls" + echo " 6) wiregard" + read -p "请选择伪装类型[默认:无]:" answer + case $answer in + 2) HEADER_TYPE="utp" ;; + 3) HEADER_TYPE="srtp" ;; + 4) HEADER_TYPE="wechat-video" ;; + 5) HEADER_TYPE="dtls" ;; + 6) HEADER_TYPE="wireguard" ;; + *) HEADER_TYPE="none" ;; + esac + yellow "伪装类型:$HEADER_TYPE" + SEED=$(cat /proc/sys/kernel/random/uuid) + fi + if [[ "$TROJAN" == "true" ]]; then + echo "" + read -p "请设置trojan密码(不输则随机生成):" PASSWORD + [[ -z "$PASSWORD" ]] && PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) + yellow " trojan密码:$PASSWORD" + fi + if [[ "$XTLS" == "true" ]]; then + echo "" + yellow "请选择流控模式:" + 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" ;; + *) red "无效选项,使用默认的xtls-rprx-direct" && FLOW="xtls-rprx-direct" ;; + esac + yellow "流控模式:$FLOW" + fi + if [[ "${WS}" == "true" ]]; then + echo "" + while true; do + read -p "请输入伪装路径,以/开头(不懂请直接回车):" WSPATH + if [[ -z "${WSPATH}" ]]; then + len=$(shuf -i5-12 -n1) + ws=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1) + WSPATH="/$ws" + break + elif [[ "${WSPATH:0:1}" != "/" ]]; then + red "伪装路径必须以/开头!" + elif [[ "${WSPATH}" == "/" ]]; then + red "不能使用根路径!" + else + break + fi + done + yellow "ws路径:$WSPATH" + fi + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + yellow "请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 高清壁纸站(https://bing.ioliu.cn)" + echo " 4) 自定义反代站点(需以http或者https开头)" + read -p "请选择伪装网站类型 [默认:高清壁纸站]:" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.ioliu.cn" + else + case $answer in + 1) PROXY_URL="" ;; + 2) + 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 + ;; + 3) PROXY_URL="https://bing.ioliu.cn" ;; + 4) + read -p "请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + red "请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + red "反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) red "请输入正确的选项!" && exit 1 ;; + esac + fi + REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3) + yellow "伪装网站:$PROXY_URL" + echo "" + yellow "是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p "请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" == "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + yellow "允许搜索引擎:$ALLOW_SPIDER" + fi + echo "" + read -p "是否安装BBR(默认安装)?[y/n]:" NEED_BBR + [[ -z "$NEED_BBR" ]] && NEED_BBR=y + [[ "$NEED_BBR" == "Y" ]] && NEED_BBR=y + yellow "安装BBR:$NEED_BBR" +} + +installNginx() { + echo "" + yellow "正在安装nginx..." + if [[ "$BT" == "false" ]]; then + if [[ $SYSTEM == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} epel-release + if [[ "$?" != "0" ]]; then + echo '[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' >/etc/yum.repos.d/nginx.repo + fi + fi + ${PACKAGE_INSTALL[int]} nginx + if [[ "$?" != "0" ]]; then + red "Nginx安装失败!" + green "建议如下:" + yellow "1. 检查VPS系统的网络设置和软件源设置,强烈建议使用系统官方软件源!" + yellow "2. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + systemctl enable nginx + else + res=$(which nginx 2>/dev/null) + if [[ "$?" != "0" ]]; then + red "您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +startNginx() { + if [[ "$BT" == "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" == "false" ]]; then + systemctl stop nginx + else + res=$(ps aux | grep -i nginx) + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +getCert() { + mkdir -p /usr/local/etc/xray + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + systemctl stop xray + res=$(netstat -ntlp | grep -E ':80 |:443 ') + if [[ "${res}" != "" ]]; then + red "其他进程占用了80或443端口,请先关闭再运行一键脚本" + echo " 端口占用信息如下:" + echo ${res} + exit 1 + fi + ${PACKAGE_INSTALL[int]} socat openssl + if [[ $SYSTEM == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} cronie + systemctl start crond + systemctl enable crond + else + ${PACKAGE_INSTALL[int]} cron + systemctl start cron + systemctl enable cron + fi + autoEmail=$(date +%s%N | md5sum | cut -c 1-32) + curl -sL https://get.acme.sh | sh -s email=$autoEmail@gmail.com + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [[ $BT == "false" ]]; then + if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + fi + else + if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + red "抱歉,证书申请失败" + green "建议如下:" + yellow " 1. 自行检测防火墙是否打开,如防火墙正在开启,请关闭防火墙或放行80端口" + yellow " 2. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + } + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + red "抱歉,证书申请失败" + green "建议如下:" + yellow " 1. 自行检测防火墙是否打开,如防火墙正在开启,请关闭防火墙或放行80端口" + yellow " 2. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + } + else + cp ~/xray.pem /usr/local/etc/xray/${DOMAIN}.pem + cp ~/xray.key /usr/local/etc/xray/${DOMAIN}.key + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" == "n" ]]; then + echo 'User-Agent: *' >/usr/share/nginx/html/robots.txt + echo 'Disallow: /' >>/usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + + if [[ "$BT" == "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + 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 + fi + + if [[ "$PROXY_URL" == "" ]]; then + action="" + else + action="proxy_ssl_server_name on; + proxy_pass $PROXY_URL; + proxy_set_header Accept-Encoding ''; + sub_filter \"$REMOTE_HOST\" \"$DOMAIN\"; + sub_filter_once off;" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + mkdir -p ${NGINX_CONF_PATH} + # VMESS+WS+TLS + # VLESS+WS+TLS + if [[ "$WS" == "true" ]]; then + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + return 301 https://\$server_name:${PORT}\$request_uri; + } + + server { + listen ${PORT} ssl http2; + listen [::]:${PORT} ssl http2; + server_name ${DOMAIN}; + charset utf-8; + + # ssl配置 + ssl_protocols TLSv1.1 TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + ssl_ecdh_curve secp384r1; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + ssl_certificate $CERT_FILE; + ssl_certificate_key $KEY_FILE; + + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + + location ${WSPATH} { + proxy_redirect off; + proxy_pass http://127.0.0.1:${XPORT}; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } + } + EOF + else + # VLESS+TCP+TLS + # VLESS+TCP+XTLS + # trojan + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + } + EOF + fi + fi +} + +setSelinux() { + 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 +} + +setFirewall() { + 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 +} + +installBBR() { + if [[ "$NEED_BBR" != "y" ]]; then + INSTALL_BBR=false + return + fi + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + yellow " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=$(systemd-detect-virt) + if [[ $res =~ lxc|openvz ]]; then + yellow " 由于你的VPS为OpenVZ或LXC架构的VPS,跳过安装" + INSTALL_BBR=false + return + fi + echo "net.core.default_qdisc=fq" >>/etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + green " BBR模块已启用" + INSTALL_BBR=false + return + fi + yellow " 安装BBR模块..." + if [[ $SYSTEM == "CentOS" ]]; then + if [[ "$V6_PROXY" == "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + ${PACKAGE_INSTALL[int]} --enablerepo=elrepo-kernel kernel-ml + ${PACKAGE_UNINSTALL[int]} kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + ${PACKAGE_INSTALL[int]} --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +installXray() { + rm -rf /tmp/xray + mkdir -p /tmp/xray + DOWNLOAD_LINK="https://github.com/XTLS/Xray-core/releases/download/${NEW_VER}/Xray-linux-$(archAffix).zip" + yellow "正在下载Xray文件" + curl -L -H "Cache-Control: no-cache" -o /tmp/xray/xray.zip ${DOWNLOAD_LINK} + if [ $? != 0 ]; then + red "下载Xray文件失败,请检查服务器网络设置" + exit 1 + fi + systemctl stop xray + mkdir -p /usr/local/etc/xray /usr/local/share/xray && \ + unzip /tmp/xray/xray.zip -d /tmp/xray + cp /tmp/xray/xray /usr/local/bin + cp /tmp/xray/geo* /usr/local/share/xray + chmod +x /usr/local/bin/xray || { + red "Xray安装失败" + exit 1 + } + + cat >/etc/systemd/system/xray.service <<-EOF + [Unit] + Description=Xray Service by Misaka-blog + Documentation=https://github.com/Misaka-blog + After=network.target nss-lookup.target + + [Service] + User=root + #User=nobody + #CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + #AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + NoNewPrivileges=true + ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json + Restart=on-failure + RestartPreventExitStatus=23 + + [Install] + WantedBy=multi-user.target + EOF + systemctl daemon-reload + systemctl enable xray.service +} + +trojanConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +trojanXTLSConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +vmessConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + }, + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "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 +} + +vmessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessXTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "flow": "$FLOW", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +configXray() { + mkdir -p /usr/local/xray + if [[ "$TROJAN" == "true" ]]; then + if [[ "$XTLS" == "true" ]]; then + trojanXTLSConfig + else + trojanConfig + fi + return 0 + fi + if [[ "$VLESS" == "false" ]]; then + # VMESS + kcp + if [[ "$KCP" == "true" ]]; then + vmessKCPConfig + return 0 + fi + # VMESS + if [[ "$TLS" == "false" ]]; then + vmessConfig + elif [[ "$WS" == "false" ]]; then + # VMESS+TCP+TLS + vmessTLSConfig + # VMESS+WS+TLS + else + vmessWSConfig + fi + #VLESS + else + if [[ "$KCP" == "true" ]]; then + vlessKCPConfig + return 0 + fi + # VLESS+TCP + if [[ "$WS" == "false" ]]; then + # VLESS+TCP+TLS + if [[ "$XTLS" == "false" ]]; then + vlessTLSConfig + # VLESS+TCP+XTLS + else + vlessXTLSConfig + fi + # VLESS+WS+TLS + else + vlessWSConfig + fi + fi +} + +install() { + getData + checkCentOS8 + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} wget curl sudo vim unzip tar gcc openssl net-tools + if [[ $SYSTEM != "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} libssl-dev g++ + fi + [[ -z $(type -P unzip) ]] && red "unzip安装失败,请检查网络" && exit 1 + installNginx + setFirewall + [[ $TLS == "true" || $XTLS == "true" ]] && getCert + configNginx + yellow "安装Xray..." + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + yellow "Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + yellow "安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + fi + configXray + setSelinux + installBBR + start + showInfo + bbrReboot +} + +bbrReboot() { + if [[ "${INSTALL_BBR}" == "true" ]]; then + echo + echo "为使BBR模块生效,系统将在30秒后重启" + echo + echo -e "您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +update() { + res=$(status) + [[ $res -lt 2 ]] && red "Xray未安装,请先安装!" && return + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + yellow "Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + yellow "安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + stop + start + green "最新版Xray安装成功!" + fi +} + +uninstall() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + echo "" + read -p "确定卸载Xray?[y/n]:" answer + if [[ "${answer,,}" == "y" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + stop + systemctl disable xray + rm -rf /etc/systemd/system/xray.service + rm -rf /usr/local/bin/xray + rm -rf /usr/local/etc/xray + if [[ "$BT" == "false" ]]; then + systemctl disable nginx + ${PACKAGE_UNINSTALL[int]} nginx + if [[ "$PMT" == "apt" ]]; then + ${PACKAGE_UNINSTALL[int]} 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 + fi + if [[ "$domain" != "" ]]; then + rm -rf ${NGINX_CONF_PATH}${domain}.conf + fi + [[ -f ~/.acme.sh/acme.sh ]] && ~/.acme.sh/acme.sh --uninstall + green "Xray卸载成功" + fi +} + +start() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + stopNginx + startNginx + systemctl restart xray + sleep 2 + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + if [[ "$res" == "" ]]; then + red "Xray启动失败,请检查日志或查看端口是否被占用!" + else + yellow "Xray启动成功" + fi +} + +stop() { + stopNginx + systemctl stop xray + yellow "Xray停止成功" +} + +restart() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + stop + start +} + +getConfigFileInfo() { + vless="false" + tls="false" + ws="false" + xtls="false" + trojan="false" + protocol="VMess" + kcp="false" + uid=$(grep id $CONFIG_FILE | head -n1 | cut -d: -f2 | tr -d \",' ') + alterid=$(grep alterId $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + network=$(grep network $CONFIG_FILE | tail -n1 | cut -d: -f2 | tr -d \",' ') + [[ -z "$network" ]] && network="tcp" + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" != "" ]]; then + ws="true" + tls="true" + wspath=$(grep path $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + else + tls="true" + fi + if [[ "$ws" == "true" ]]; then + port=$(grep -i ssl $NGINX_CONF_PATH${domain}.conf | head -n1 | awk '{print $2}') + else + port=$(grep port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + res=$(grep -i kcp $CONFIG_FILE) + if [[ "$res" != "" ]]; then + kcp="true" + type=$(grep header -A 3 $CONFIG_FILE | grep 'type' | cut -d: -f2 | tr -d \",' ') + seed=$(grep seed $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + vmess=$(grep vmess $CONFIG_FILE) + if [[ "$vmess" == "" ]]; then + trojan=$(grep trojan $CONFIG_FILE) + if [[ "$trojan" == "" ]]; then + vless="true" + protocol="VLESS" + else + trojan="true" + password=$(grep password $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + protocol="trojan" + fi + tls="true" + encryption="none" + xtls=$(grep xtlsSettings $CONFIG_FILE) + if [[ "$xtls" != "" ]]; then + xtls="true" + flow=$(grep flow $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + else + flow="无" + fi + fi +} + +outputVmess() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"tcp\", + \"type\":\"none\", + \"host\":\"\", + \"path\":\"\", + \"tls\":\"\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +outputVmessKCP() { + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" +} + +outputTrojan() { + if [[ "$xtls" == "true" ]]; then + link="trojan://${password}@${domain}:${port}#" + 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}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + else + link="trojan://${password}@${domain}:${port}#" + 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}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + fi +} + +outputVmessTLS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接: ${PLAIN}$RED$link$PLAIN" +} + +outputVmessWS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"${wspath}\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +showInfo() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + + echo "" + yellow " Xray配置文件: ${CONFIG_FILE}" + yellow " Xray配置信息:" + + getConfigFileInfo + + echo -e " ${BLUE}协议: ${PLAIN} ${RED}${protocol}${PLAIN}" + if [[ "$trojan" == "true" ]]; then + outputTrojan + return 0 + fi + if [[ "$vless" == "false" ]]; then + if [[ "$kcp" == "true" ]]; then + outputVmessKCP + return 0 + fi + if [[ "$tls" == "false" ]]; then + outputVmess + elif [[ "$ws" == "false" ]]; then + outputVmessTLS + else + outputVmessWS + fi + else + if [[ "$kcp" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" + return 0 + fi + if [[ "$xtls" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + elif [[ "$ws" == "false" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN}${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + else + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + fi + fi +} + +showLog() { + res=$(status) + [[ $res -lt 2 ]] && red "Xray未安装,请先安装!" && exit 1 + journalctl -xen -u xray --no-pager +} + +warpmenu(){ + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/misakawarp.sh && bash misakawarp.sh +} + +setdns64(){ + if [[ -n $(curl -s6m8 https://ip.gs) ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + fi +} + +system_optimize(){ + if [ ! -f "/etc/sysctl.conf" ]; then + touch /etc/sysctl.conf + fi + sed -i '/net.ipv4.tcp_retries2/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_slow_start_after_idle/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_fastopen/d' /etc/sysctl.conf + sed -i '/fs.file-max/d' /etc/sysctl.conf + sed -i '/fs.inotify.max_user_instances/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_fin_timeout/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_tw_reuse/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_max_syn_backlog/d' /etc/sysctl.conf + sed -i '/net.ipv4.ip_local_port_range/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_max_tw_buckets/d' /etc/sysctl.conf + sed -i '/net.ipv4.route.gc_timeout/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_synack_retries/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_syn_retries/d' /etc/sysctl.conf + sed -i '/net.core.somaxconn/d' /etc/sysctl.conf + sed -i '/net.core.netdev_max_backlog/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_timestamps/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_max_orphans/d' /etc/sysctl.conf + sed -i '/net.ipv4.ip_forward/d' /etc/sysctl.conf + + echo "net.ipv4.tcp_retries2 = 8 + net.ipv4.tcp_slow_start_after_idle = 0 + fs.file-max = 1000000 + fs.inotify.max_user_instances = 8192 + net.ipv4.tcp_syncookies = 1 + net.ipv4.tcp_fin_timeout = 30 + net.ipv4.tcp_tw_reuse = 1 + net.ipv4.ip_local_port_range = 1024 65000 + net.ipv4.tcp_max_syn_backlog = 16384 + net.ipv4.tcp_max_tw_buckets = 6000 + net.ipv4.route.gc_timeout = 100 + net.ipv4.tcp_syn_retries = 1 + net.ipv4.tcp_synack_retries = 1 + net.core.somaxconn = 32768 + net.core.netdev_max_backlog = 32768 + net.ipv4.tcp_timestamps = 0 + net.ipv4.tcp_max_orphans = 32768 + # forward ipv4 + #net.ipv4.ip_forward = 1" >>/etc/sysctl.conf + sysctl -p + echo "* soft nofile 1000000 + * hard nofile 1000000" >/etc/security/limits.conf + echo "ulimit -SHn 1000000" >>/etc/profile + read -p "需要重启VPS,系统优化配置才能生效,是否现在重启? [Y/n] :" yn + [[ -z $yn ]] && yn="y" + if [[ $yn == [Yy] ]]; then + yellow "VPS 重启中..." + reboot + fi +} + +open_ports(){ + systemctl stop firewalld.service + systemctl disable firewalld.service + setenforce 0 + ufw disable + iptables -P INPUT ACCEPT + iptables -P FORWARD ACCEPT + iptables -P OUTPUT ACCEPT + iptables -t nat -F + iptables -t mangle -F + iptables -F + iptables -X + netfilter-persistent save + yellow "VPS中的所有网络端口已开启" +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}Xray一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) & MisakaNo #" + echo -e "# ${GREEN}博客${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo -e " " + echo -e " ${GREEN}1.${PLAIN} 安装Xray-VMESS${PLAIN}${RED}(不推荐)${PLAIN}" + echo -e " ${GREEN}2.${PLAIN} 安装Xray-${BLUE}VMESS+mKCP${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装Xray-VMESS+TCP+TLS" + echo -e " ${GREEN}4.${PLAIN} 安装Xray-${BLUE}VMESS+WS+TLS${PLAIN}${RED}(推荐)(可过支持WebSocket的CDN)${PLAIN}" + echo -e " ${GREEN}5.${PLAIN} 安装Xray-${BLUE}VLESS+mKCP${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 安装Xray-VLESS+TCP+TLS" + echo -e " ${GREEN}7.${PLAIN} 安装Xray-${BLUE}VLESS+WS+TLS${PLAIN}${RED}(推荐)(可过支持WebSocket的CDN)${PLAIN}" + echo -e " ${GREEN}8.${PLAIN} 安装Xray-${BLUE}VLESS+TCP+XTLS${PLAIN}${RED}(不推荐)${PLAIN}" + echo -e " ${GREEN}9.${PLAIN} 安装${BLUE}Trojan${PLAIN}${RED}(推荐)(延迟低)${PLAIN}" + echo -e " ${GREEN}10.${PLAIN} 安装${BLUE}Trojan+XTLS${PLAIN}${RED}(不推荐)${PLAIN}" + echo " -------------" + echo -e " ${GREEN}11.${PLAIN} 更新Xray" + echo -e " ${GREEN}12. ${RED}卸载Xray${PLAIN}" + echo " -------------" + echo -e " ${GREEN}13.${PLAIN} 启动Xray" + echo -e " ${GREEN}14.${PLAIN} 重启Xray" + echo -e " ${GREEN}15.${PLAIN} 停止Xray" + echo " -------------" + echo -e " ${GREEN}16.${PLAIN} 查看Xray配置" + echo -e " ${GREEN}17.${PLAIN} 查看Xray日志" + echo " -------------" + echo -e " ${GREEN}18.${PLAIN} 安装并管理WARP" + echo -e " ${GREEN}19.${PLAIN} 设置DNS64服务器" + echo -e " ${GREEN}20.${PLAIN} VPS系统优化" + echo -e " ${GREEN}21.${PLAIN} 放开VPS的所有端口" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo -n " 当前Xray状态:" + statusText + echo + + read -p "请选择操作[0-21]:" answer + case $answer in + 0) exit 1 ;; + 1) install ;; + 2) KCP="true" && install ;; + 3) TLS="true" && install ;; + 4) TLS="true" && WS="true" && install ;; + 5) VLESS="true" && KCP="true" && install ;; + 6) VLESS="true" && TLS="true" && install ;; + 7) VLESS="true" && TLS="true" && WS="true" && install ;; + 8) VLESS="true" && TLS="true" && XTLS="true" && install ;; + 9) TROJAN="true" && TLS="true" && install ;; + 10) TROJAN="true" && TLS="true" && XTLS="true" && install ;; + 11) update ;; + 12) uninstall ;; + 13) start ;; + 14) restart ;; + 15) stop ;; + 16) showInfo ;; + 17) showLog ;; + 18) warpmenu ;; + 19) setdns64 ;; + 20) system_optimize ;; + 21) open_ports ;; + *) red "请选择正确的操作!" && exit 1 ;; + esac +} + +action=$1 +[[ -z $1 ]] && action=menu + +case "$action" in + menu | update | uninstall | start | restart | stop | showInfo | showLog) ${action} ;; + *) echo " 参数错误" && echo " 用法: $(basename $0) [menu|update|uninstall|start|restart|stop|showInfo|showLog]" ;; +esac \ No newline at end of file diff --git a/misakaxray/xray5.sh b/misakaxray/xray5.sh new file mode 100644 index 00000000..cd3f682b --- /dev/null +++ b/misakaxray/xray5.sh @@ -0,0 +1,1852 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +RED="\033[31m" +GREEN="\033[32m" +YELLOW="\033[33m" +BLUE="\033[36m" +PLAIN='\033[0m' + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 +[[ -z $(type -P curl) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl + +SITES=( + http://www.zhuizishu.com/ + http://xs.56dyc.com/ + http://www.ddxsku.com/ + http://www.biqu6.com/ + https://www.wenshulou.cc/ + http://www.55shuba.com/ + http://www.39shubao.com/ + https://www.23xsw.cc/ + https://www.jueshitangmen.info/ + https://www.zhetian.org/ + http://www.bequgexs.com/ + http://www.tjwl.com/ +) + +CONFIG_FILE="/usr/local/etc/xray/config.json" + +IP=$(curl -s6m8 ip.sb) || IP=$(curl -s4m8 ip.sb) + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" +res=$(which bt 2>/dev/null) +[[ "$res" != "" ]] && BT="true" && NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" + +VLESS="false" +TROJAN="false" +TLS="false" +WS="false" +XTLS="false" +KCP="false" + +checkCentOS8() { + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +configNeedNginx() { + local ws=$(grep wsSettings $CONFIG_FILE) + [[ -z "$ws" ]] && echo no && return + echo yes +} + +needNginx() { + [[ "$WS" == "false" ]] && echo no && return + echo yes +} + +status() { + [[ ! -f /usr/local/bin/xray ]] && echo 0 && return + [[ ! -f $CONFIG_FILE ]] && echo 1 && return + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + [[ -z "$res" ]] && echo 2 && return + + if [[ $(configNeedNginx) != "yes" ]]; then + echo 3 + else + res=$(ss -nutlp | grep -i nginx) + if [[ -z "$res" ]]; then + echo 4 + else + echo 5 + fi + fi +} + +statusText() { + res=$(status) + case $res in + 2) echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN} ;; + 3) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN} ;; + 4) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN}, ${RED}Nginx未运行${PLAIN} ;; + 5) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行, Nginx正在运行${PLAIN} ;; + *) echo -e ${RED}未安装${PLAIN} ;; + esac +} + +normalizeVersion() { + latestXrayVer=v$(curl -Ls "https://data.jsdelivr.com/v1/package/resolve/gh/XTLS/Xray-core" | grep '"version":' | sed -E 's/.*"([^"]+)".*/\1/') + if [ -n "$1" ]; then + case "$1" in + v*) echo "$1" ;; + http*) echo $latestXrayVer ;; + *) echo "v$1" ;; + esac + else + echo "" + fi +} + +# 1: new Xray. 0: no. 1: yes. 2: not installed. 3: check failed. +getVersion() { + VER=$(/usr/local/bin/xray version 2>/dev/null | head -n1 | awk '{print $2}') + RETVAL=$? + CUR_VER="$(normalizeVersion "$(echo "$VER" | head -n 1 | cut -d " " -f2)")" + TAG_URL="https://data.jsdelivr.com/v1/package/resolve/gh/XTLS/Xray-core" + NEW_VER="$(normalizeVersion "$(curl -s "${TAG_URL}" --connect-timeout 10 | grep 'version' | cut -d\" -f4)")" + + if [[ $? -ne 0 ]] || [[ $NEW_VER == "" ]]; then + red "检测 Xray 版本失败,可能是VPS网络错误,请检查后重试" + 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' ;; + armv5tel) echo 'arm32-v5' ;; + armv6l) echo 'arm32-v6' ;; + armv7 | armv7l) echo 'arm32-v7a' ;; + armv8 | aarch64) echo 'arm64-v8a' ;; + mips64le) echo 'mips64le' ;; + mips64) echo 'mips64' ;; + mipsle) echo 'mips32le' ;; + mips) echo 'mips32' ;; + ppc64le) echo 'ppc64le' ;; + ppc64) echo 'ppc64' ;; + ppc64le) echo 'ppc64le' ;; + riscv64) echo 'riscv64' ;; + s390x) echo 's390x' ;; + *) red " 不支持的CPU架构!" && exit 1 ;; + esac + + return 0 +} + +getData() { + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + echo "Xray一键脚本,运行之前请确认如下条件已经具备:" + yellow " 1. 一个伪装域名" + yellow " 2. 伪装域名DNS解析指向当前服务器ip(${IP})" + yellow " 3. 如果/root目录下有 xray.pem 和 xray.key 证书密钥文件,无需理会条件2" + echo " " + read -p "确认满足以上条件请按y,按其他键退出脚本:" answer + [[ "${answer,,}" != "y" ]] && exit 1 + echo "" + while true; do + read -p "请输入伪装域名:" DOMAIN + if [[ -z "${DOMAIN}" ]]; then + red " 域名输入错误,请重新输入!" + else + break + fi + done + DOMAIN=${DOMAIN,,} + yellow "伪装域名(host):$DOMAIN" + echo "" + if [[ -f ~/xray.pem && -f ~/xray.key ]]; then + yellow "检测到自有证书,将使用自有证书部署" + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + else + resolve=$(curl -sm8 ipget.net/?ip=${DOMAIN}) + if [[ $resolve != $IP ]]; then + yellow "${DOMAIN} 解析结果:${resolve}" + red "域名未解析到当前服务器IP(${IP})!" + green "建议如下:" + yellow " 1. 请确保Cloudflare小云朵为关闭状态(仅限DNS),其他域名解析网站设置同理" + yellow " 2. 请检查DNS解析设置的IP是否为VPS的IP" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + fi + fi + echo "" + if [[ "$(needNginx)" == "no" ]]; then + if [[ "$TLS" == "true" ]]; then + read -p "请输入xray监听端口 [默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + else + read -p "请输入xray监听端口 [100-65535的一个数字]:" PORT + [[ -z "${PORT}" ]] && PORT=$(shuf -i200-65000 -n1) + if [[ "${PORT:0:1}" == "0" ]]; then + red "端口不能以0开头" + exit 1 + fi + fi + yellow "xray端口:$PORT" + else + read -p "请输入Nginx监听端口[100-65535的一个数字,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + [ "${PORT:0:1}" = "0" ] && red "端口不能以0开头" && exit 1 + yellow " Nginx端口:$PORT" + XPORT=$(shuf -i10000-65000 -n1) + fi + if [[ "$KCP" == "true" ]]; then + echo "" + yellow "请选择伪装类型:" + echo " 1) 无" + echo " 2) BT下载" + echo " 3) 视频通话" + echo " 4) 微信视频通话" + echo " 5) dtls" + echo " 6) wiregard" + read -p "请选择伪装类型[默认:无]:" answer + case $answer in + 2) HEADER_TYPE="utp" ;; + 3) HEADER_TYPE="srtp" ;; + 4) HEADER_TYPE="wechat-video" ;; + 5) HEADER_TYPE="dtls" ;; + 6) HEADER_TYPE="wireguard" ;; + *) HEADER_TYPE="none" ;; + esac + yellow "伪装类型:$HEADER_TYPE" + SEED=$(cat /proc/sys/kernel/random/uuid) + fi + if [[ "$TROJAN" == "true" ]]; then + echo "" + read -p "请设置trojan密码(不输则随机生成):" PASSWORD + [[ -z "$PASSWORD" ]] && PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) + yellow " trojan密码:$PASSWORD" + fi + if [[ "$XTLS" == "true" ]]; then + echo "" + yellow "请选择流控模式:" + 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" ;; + *) red "无效选项,使用默认的xtls-rprx-direct" && FLOW="xtls-rprx-direct" ;; + esac + yellow "流控模式:$FLOW" + fi + if [[ "${WS}" == "true" ]]; then + echo "" + while true; do + read -p "请输入伪装路径,以/开头(不懂请直接回车):" WSPATH + if [[ -z "${WSPATH}" ]]; then + len=$(shuf -i5-12 -n1) + ws=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1) + WSPATH="/$ws" + break + elif [[ "${WSPATH:0:1}" != "/" ]]; then + red "伪装路径必须以/开头!" + elif [[ "${WSPATH}" == "/" ]]; then + red "不能使用根路径!" + else + break + fi + done + yellow "ws路径:$WSPATH" + fi + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + yellow "请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 高清壁纸站(https://bing.wallpaper.pics)" + echo " 4) 自定义反代站点(需以http或者https开头)" + read -p "请选择伪装网站类型 [默认:高清壁纸站]:" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.wallpaper.pics" + else + case $answer in + 1) PROXY_URL="" ;; + 2) + 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 + ;; + 3) PROXY_URL="https://bing.wallpaper.pics" ;; + 4) + read -p "请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + red "请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + red "反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) red "请输入正确的选项!" && exit 1 ;; + esac + fi + REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3) + yellow "伪装网站:$PROXY_URL" + echo "" + yellow "是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p "请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" == "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + yellow "允许搜索引擎:$ALLOW_SPIDER" + fi + echo "" + read -p "是否安装BBR(默认安装)?[y/n]:" NEED_BBR + [[ -z "$NEED_BBR" ]] && NEED_BBR=y + [[ "$NEED_BBR" == "Y" ]] && NEED_BBR=y + yellow "安装BBR:$NEED_BBR" +} + +installNginx() { + echo "" + yellow "正在安装nginx..." + if [[ "$BT" == "false" ]]; then + if [[ $SYSTEM == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} epel-release + if [[ "$?" != "0" ]]; then + echo '[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' >/etc/yum.repos.d/nginx.repo + fi + fi + ${PACKAGE_INSTALL[int]} nginx + if [[ "$?" != "0" ]]; then + red "Nginx安装失败!" + green "建议如下:" + yellow "1. 检查VPS系统的网络设置和软件源设置,强烈建议使用系统官方软件源!" + yellow "2. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + fi + systemctl enable nginx + else + res=$(which nginx 2>/dev/null) + if [[ "$?" != "0" ]]; then + red "您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +startNginx() { + if [[ "$BT" == "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" == "false" ]]; then + systemctl stop nginx + else + res=$(ps aux | grep -i nginx) + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +getCert() { + mkdir -p /usr/local/etc/xray + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + systemctl stop xray + res=$(netstat -ntlp | grep -E ':80 |:443 ') + if [[ "${res}" != "" ]]; then + red "其他进程占用了80或443端口,请先关闭再运行一键脚本" + echo " 端口占用信息如下:" + echo ${res} + exit 1 + fi + ${PACKAGE_INSTALL[int]} socat openssl + if [[ $SYSTEM == "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} cronie + systemctl start crond + systemctl enable crond + else + ${PACKAGE_INSTALL[int]} cron + systemctl start cron + systemctl enable cron + fi + autoEmail=$(date +%s%N | md5sum | cut -c 1-32) + curl -sL https://get.acme.sh | sh -s email=$autoEmail@gmail.com + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [[ $BT == "false" ]]; then + if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + fi + else + if [[ -n $(curl -sm8 ip.sb | grep ":") ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + red "抱歉,证书申请失败" + green "建议如下:" + yellow " 1. 自行检测防火墙是否打开,如防火墙正在开启,请关闭防火墙或放行80端口" + yellow " 2. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + } + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + red "抱歉,证书申请失败" + green "建议如下:" + yellow " 1. 自行检测防火墙是否打开,如防火墙正在开启,请关闭防火墙或放行80端口" + yellow " 2. 同一域名多次申请触发Acme.sh官方风控,请更换域名或等待7天后再尝试执行脚本" + yellow " 3. 脚本可能跟不上时代,建议截图发布到GitHub Issues或TG群询问" + exit 1 + } + else + cp ~/xray.pem /usr/local/etc/xray/${DOMAIN}.pem + cp ~/xray.key /usr/local/etc/xray/${DOMAIN}.key + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" == "n" ]]; then + echo 'User-Agent: *' >/usr/share/nginx/html/robots.txt + echo 'Disallow: /' >>/usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + + if [[ "$BT" == "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + 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 + fi + + if [[ "$PROXY_URL" == "" ]]; then + action="" + else + action="proxy_ssl_server_name on; + proxy_pass $PROXY_URL; + proxy_set_header Accept-Encoding ''; + sub_filter \"$REMOTE_HOST\" \"$DOMAIN\"; + sub_filter_once off;" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + mkdir -p ${NGINX_CONF_PATH} + # VMESS+WS+TLS + # VLESS+WS+TLS + if [[ "$WS" == "true" ]]; then + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + return 301 https://\$server_name:${PORT}\$request_uri; + } + + server { + listen ${PORT} ssl http2; + listen [::]:${PORT} ssl http2; + server_name ${DOMAIN}; + charset utf-8; + + # ssl配置 + ssl_protocols TLSv1.1 TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + ssl_ecdh_curve secp384r1; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + ssl_certificate $CERT_FILE; + ssl_certificate_key $KEY_FILE; + + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + + location ${WSPATH} { + proxy_redirect off; + proxy_pass http://127.0.0.1:${XPORT}; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } + } + EOF + else + # VLESS+TCP+TLS + # VLESS+TCP+XTLS + # trojan + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + } + EOF + fi + fi +} + +setSelinux() { + 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 +} + +setFirewall() { + 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 +} + +installBBR() { + if [[ "$NEED_BBR" != "y" ]]; then + INSTALL_BBR=false + return + fi + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + yellow " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=$(systemd-detect-virt) + if [[ $res =~ lxc|openvz ]]; then + yellow " 由于你的VPS为OpenVZ或LXC架构的VPS,跳过安装" + INSTALL_BBR=false + return + fi + echo "net.core.default_qdisc=fq" >>/etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + green " BBR模块已启用" + INSTALL_BBR=false + return + fi + yellow " 安装BBR模块..." + if [[ $SYSTEM == "CentOS" ]]; then + if [[ "$V6_PROXY" == "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + ${PACKAGE_INSTALL[int]} --enablerepo=elrepo-kernel kernel-ml + ${PACKAGE_UNINSTALL[int]} kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + ${PACKAGE_INSTALL[int]} --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +installXray() { + rm -rf /tmp/xray + mkdir -p /tmp/xray + DOWNLOAD_LINK="https://github.com/XTLS/Xray-core/releases/download/${NEW_VER}/Xray-linux-$(archAffix).zip" + yellow "正在下载Xray文件" + curl -L -H "Cache-Control: no-cache" -o /tmp/xray/xray.zip ${DOWNLOAD_LINK} + if [ $? != 0 ]; then + red "下载Xray文件失败,请检查服务器网络设置" + exit 1 + fi + systemctl stop xray + mkdir -p /usr/local/etc/xray /usr/local/share/xray && \ + unzip /tmp/xray/xray.zip -d /tmp/xray + cp /tmp/xray/xray /usr/local/bin + cp /tmp/xray/geo* /usr/local/share/xray + chmod +x /usr/local/bin/xray || { + red "Xray安装失败" + exit 1 + } + + cat >/etc/systemd/system/xray.service <<-EOF + [Unit] + Description=Xray Service by Misaka-blog + Documentation=https://github.com/Misaka-blog + After=network.target nss-lookup.target + + [Service] + User=root + #User=nobody + #CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + #AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + NoNewPrivileges=true + ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json + Restart=on-failure + RestartPreventExitStatus=23 + + [Install] + WantedBy=multi-user.target + EOF + systemctl daemon-reload + systemctl enable xray.service +} + +trojanConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +trojanXTLSConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +vmessConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + }, + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "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 +} + +vmessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessXTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "flow": "$FLOW", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +configXray() { + mkdir -p /usr/local/xray + if [[ "$TROJAN" == "true" ]]; then + if [[ "$XTLS" == "true" ]]; then + trojanXTLSConfig + else + trojanConfig + fi + return 0 + fi + if [[ "$VLESS" == "false" ]]; then + # VMESS + kcp + if [[ "$KCP" == "true" ]]; then + vmessKCPConfig + return 0 + fi + # VMESS + if [[ "$TLS" == "false" ]]; then + vmessConfig + elif [[ "$WS" == "false" ]]; then + # VMESS+TCP+TLS + vmessTLSConfig + # VMESS+WS+TLS + else + vmessWSConfig + fi + #VLESS + else + if [[ "$KCP" == "true" ]]; then + vlessKCPConfig + return 0 + fi + # VLESS+TCP + if [[ "$WS" == "false" ]]; then + # VLESS+TCP+TLS + if [[ "$XTLS" == "false" ]]; then + vlessTLSConfig + # VLESS+TCP+XTLS + else + vlessXTLSConfig + fi + # VLESS+WS+TLS + else + vlessWSConfig + fi + fi +} + +install() { + getData + checkCentOS8 + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} wget curl sudo vim unzip tar gcc openssl net-tools + if [[ $SYSTEM != "CentOS" ]]; then + ${PACKAGE_INSTALL[int]} libssl-dev g++ + fi + [[ -z $(type -P unzip) ]] && red "unzip安装失败,请检查网络" && exit 1 + installNginx + setFirewall + [[ $TLS == "true" || $XTLS == "true" ]] && getCert + configNginx + yellow "安装Xray..." + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + yellow "Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + yellow "安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + fi + configXray + setSelinux + installBBR + start + showInfo + bbrReboot +} + +bbrReboot() { + if [[ "${INSTALL_BBR}" == "true" ]]; then + echo + echo "为使BBR模块生效,系统将在30秒后重启" + echo + echo -e "您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +update() { + res=$(status) + [[ $res -lt 2 ]] && red "Xray未安装,请先安装!" && return + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + yellow "Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + yellow "安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + stop + start + green "最新版Xray安装成功!" + fi +} + +uninstall() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + echo "" + read -p "确定卸载Xray?[y/n]:" answer + if [[ "${answer,,}" == "y" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + stop + systemctl disable xray + rm -rf /etc/systemd/system/xray.service + rm -rf /usr/local/bin/xray + rm -rf /usr/local/etc/xray + if [[ "$BT" == "false" ]]; then + systemctl disable nginx + ${PACKAGE_UNINSTALL[int]} nginx + if [[ "$PMT" == "apt" ]]; then + ${PACKAGE_UNINSTALL[int]} 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 + fi + if [[ "$domain" != "" ]]; then + rm -rf ${NGINX_CONF_PATH}${domain}.conf + fi + [[ -f ~/.acme.sh/acme.sh ]] && ~/.acme.sh/acme.sh --uninstall + green "Xray卸载成功" + fi +} + +start() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + stopNginx + startNginx + systemctl restart xray + sleep 2 + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + if [[ "$res" == "" ]]; then + red "Xray启动失败,请检查日志或查看端口是否被占用!" + else + yellow "Xray启动成功" + fi +} + +stop() { + stopNginx + systemctl stop xray + yellow "Xray停止成功" +} + +restart() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + stop + start +} + +getConfigFileInfo() { + vless="false" + tls="false" + ws="false" + xtls="false" + trojan="false" + protocol="VMess" + kcp="false" + uid=$(grep id $CONFIG_FILE | head -n1 | cut -d: -f2 | tr -d \",' ') + alterid=$(grep alterId $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + network=$(grep network $CONFIG_FILE | tail -n1 | cut -d: -f2 | tr -d \",' ') + [[ -z "$network" ]] && network="tcp" + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" != "" ]]; then + ws="true" + tls="true" + wspath=$(grep path $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + else + tls="true" + fi + if [[ "$ws" == "true" ]]; then + port=$(grep -i ssl $NGINX_CONF_PATH${domain}.conf | head -n1 | awk '{print $2}') + else + port=$(grep port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + res=$(grep -i kcp $CONFIG_FILE) + if [[ "$res" != "" ]]; then + kcp="true" + type=$(grep header -A 3 $CONFIG_FILE | grep 'type' | cut -d: -f2 | tr -d \",' ') + seed=$(grep seed $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + vmess=$(grep vmess $CONFIG_FILE) + if [[ "$vmess" == "" ]]; then + trojan=$(grep trojan $CONFIG_FILE) + if [[ "$trojan" == "" ]]; then + vless="true" + protocol="VLESS" + else + trojan="true" + password=$(grep password $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + protocol="trojan" + fi + tls="true" + encryption="none" + xtls=$(grep xtlsSettings $CONFIG_FILE) + if [[ "$xtls" != "" ]]; then + xtls="true" + flow=$(grep flow $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + else + flow="无" + fi + fi +} + +outputVmess() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"tcp\", + \"type\":\"none\", + \"host\":\"\", + \"path\":\"\", + \"tls\":\"\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +outputVmessKCP() { + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" +} + +outputTrojan() { + if [[ "$xtls" == "true" ]]; then + link="trojan://${password}@${domain}:${port}#" + 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}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + else + link="trojan://${password}@${domain}:${port}#" + 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}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + fi +} + +outputVmessTLS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接: ${PLAIN}$RED$link$PLAIN" +} + +outputVmessWS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"${wspath}\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +showInfo() { + res=$(status) + if [[ $res -lt 2 ]]; then + red "Xray未安装,请先安装!" + return + fi + + echo "" + yellow " Xray配置文件: ${CONFIG_FILE}" + yellow " Xray配置信息:" + + getConfigFileInfo + + echo -e " ${BLUE}协议: ${PLAIN} ${RED}${protocol}${PLAIN}" + if [[ "$trojan" == "true" ]]; then + outputTrojan + return 0 + fi + if [[ "$vless" == "false" ]]; then + if [[ "$kcp" == "true" ]]; then + outputVmessKCP + return 0 + fi + if [[ "$tls" == "false" ]]; then + outputVmess + elif [[ "$ws" == "false" ]]; then + outputVmessTLS + else + outputVmessWS + fi + else + if [[ "$kcp" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" + return 0 + fi + if [[ "$xtls" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + elif [[ "$ws" == "false" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN}${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + else + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + fi + fi +} + +showLog() { + res=$(status) + [[ $res -lt 2 ]] && red "Xray未安装,请先安装!" && exit 1 + journalctl -xen -u xray --no-pager +} + +warpmenu() { + wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/misakawarp.sh && bash misakawarp.sh +} + +setdns64() { + if [[ -n $(curl -s6m8 https://ip.gs) ]]; then + echo -e nameserver 2a01:4f8:c2c:123f::1 >/etc/resolv.conf + fi +} + +system_optimize() { + if [ ! -f "/etc/sysctl.conf" ]; then + touch /etc/sysctl.conf + fi + sed -i '/net.ipv4.tcp_retries2/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_slow_start_after_idle/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_fastopen/d' /etc/sysctl.conf + sed -i '/fs.file-max/d' /etc/sysctl.conf + sed -i '/fs.inotify.max_user_instances/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_fin_timeout/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_tw_reuse/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_max_syn_backlog/d' /etc/sysctl.conf + sed -i '/net.ipv4.ip_local_port_range/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_max_tw_buckets/d' /etc/sysctl.conf + sed -i '/net.ipv4.route.gc_timeout/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_synack_retries/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_syn_retries/d' /etc/sysctl.conf + sed -i '/net.core.somaxconn/d' /etc/sysctl.conf + sed -i '/net.core.netdev_max_backlog/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_timestamps/d' /etc/sysctl.conf + sed -i '/net.ipv4.tcp_max_orphans/d' /etc/sysctl.conf + sed -i '/net.ipv4.ip_forward/d' /etc/sysctl.conf + + echo "net.ipv4.tcp_retries2 = 8 + net.ipv4.tcp_slow_start_after_idle = 0 + fs.file-max = 1000000 + fs.inotify.max_user_instances = 8192 + net.ipv4.tcp_syncookies = 1 + net.ipv4.tcp_fin_timeout = 30 + net.ipv4.tcp_tw_reuse = 1 + net.ipv4.ip_local_port_range = 1024 65000 + net.ipv4.tcp_max_syn_backlog = 16384 + net.ipv4.tcp_max_tw_buckets = 6000 + net.ipv4.route.gc_timeout = 100 + net.ipv4.tcp_syn_retries = 1 + net.ipv4.tcp_synack_retries = 1 + net.core.somaxconn = 32768 + net.core.netdev_max_backlog = 32768 + net.ipv4.tcp_timestamps = 0 + net.ipv4.tcp_max_orphans = 32768 + # forward ipv4 + #net.ipv4.ip_forward = 1" >>/etc/sysctl.conf + sysctl -p + echo "* soft nofile 1000000 + * hard nofile 1000000" >/etc/security/limits.conf + echo "ulimit -SHn 1000000" >>/etc/profile + read -p "需要重启VPS,系统优化配置才能生效,是否现在重启? [Y/n] :" yn + [[ -z $yn ]] && yn="y" + if [[ $yn == [Yy] ]]; then + yellow "VPS 重启中..." + reboot + fi +} + +open_ports() { + systemctl stop firewalld.service + systemctl disable firewalld.service + setenforce 0 + ufw disable + iptables -P INPUT ACCEPT + iptables -P FORWARD ACCEPT + iptables -P OUTPUT ACCEPT + iptables -t nat -F + iptables -t mangle -F + iptables -F + iptables -X + netfilter-persistent save + yellow "VPS中的所有网络端口已开启" +} + +#禁用IPv6 +closeipv6() { + clear + sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.lo.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.conf + sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.conf + sed -i '/net.ipv6.conf.lo.disable_ipv6/d' /etc/sysctl.conf + + echo "net.ipv6.conf.all.disable_ipv6 = 1 +net.ipv6.conf.default.disable_ipv6 = 1 +net.ipv6.conf.lo.disable_ipv6 = 1" >>/etc/sysctl.d/99-sysctl.conf + sysctl --system + green "禁用IPv6结束,可能需要重启!" +} + +#开启IPv6 +openipv6() { + clear + sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.lo.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf + sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.conf + sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.conf + sed -i '/net.ipv6.conf.lo.disable_ipv6/d' /etc/sysctl.conf + + echo "net.ipv6.conf.all.disable_ipv6 = 0 +net.ipv6.conf.default.disable_ipv6 = 0 +net.ipv6.conf.lo.disable_ipv6 = 0" >>/etc/sysctl.d/99-sysctl.conf + sysctl --system + green "开启IPv6结束,可能需要重启!" +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}Xray一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) & MisakaNo #" + echo -e "# ${GREEN}博客${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}论坛${PLAIN}: https://vpsgo.co #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo -e " " + echo -e " ${GREEN}1.${PLAIN} 安装Xray-VMESS${PLAIN}${RED}(不推荐)${PLAIN}" + echo -e " ${GREEN}2.${PLAIN} 安装Xray-${BLUE}VMESS+mKCP${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装Xray-VMESS+TCP+TLS" + echo -e " ${GREEN}4.${PLAIN} 安装Xray-${BLUE}VMESS+WS+TLS${PLAIN}${RED}(推荐)(可过支持WebSocket的CDN)${PLAIN}" + echo -e " ${GREEN}5.${PLAIN} 安装Xray-${BLUE}VLESS+mKCP${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 安装Xray-VLESS+TCP+TLS" + echo -e " ${GREEN}7.${PLAIN} 安装Xray-${BLUE}VLESS+WS+TLS${PLAIN}${RED}(推荐)(可过支持WebSocket的CDN)${PLAIN}" + echo -e " ${GREEN}8.${PLAIN} 安装Xray-${BLUE}VLESS+TCP+XTLS${PLAIN}${RED}(不推荐)${PLAIN}" + echo -e " ${GREEN}9.${PLAIN} 安装${BLUE}Trojan${PLAIN}${RED}(推荐)(延迟低)${PLAIN}" + echo -e " ${GREEN}10.${PLAIN} 安装${BLUE}Trojan+XTLS${PLAIN}${RED}(不推荐)${PLAIN}" + echo " -------------" + echo -e " ${GREEN}11.${PLAIN} 更新Xray" + echo -e " ${GREEN}12. ${RED}卸载Xray${PLAIN}" + echo " -------------" + echo -e " ${GREEN}13.${PLAIN} 启动Xray" + echo -e " ${GREEN}14.${PLAIN} 重启Xray" + echo -e " ${GREEN}15.${PLAIN} 停止Xray" + echo " -------------" + echo -e " ${GREEN}16.${PLAIN} 查看Xray配置" + echo -e " ${GREEN}17.${PLAIN} 查看Xray日志" + echo " -------------" + echo -e " ${GREEN}18.${PLAIN} 安装并管理WARP" + echo -e " ${GREEN}19.${PLAIN} 设置DNS64服务器" + echo -e " ${GREEN}20.${PLAIN} VPS系统优化" + echo -e " ${GREEN}21.${PLAIN} 放开VPS的所有端口" + echo -e " ${GREEN}22.${PLAIN} 开启IPv6" + echo -e " ${GREEN}23.${PLAIN} 禁用IPv6" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo -n " 当前Xray状态:" + statusText + echo + + read -p "请选择操作[0-23]:" answer + case $answer in + 0) exit 1 ;; + 1) install ;; + 2) KCP="true" && install ;; + 3) TLS="true" && install ;; + 4) TLS="true" && WS="true" && install ;; + 5) VLESS="true" && KCP="true" && install ;; + 6) VLESS="true" && TLS="true" && install ;; + 7) VLESS="true" && TLS="true" && WS="true" && install ;; + 8) VLESS="true" && TLS="true" && XTLS="true" && install ;; + 9) TROJAN="true" && TLS="true" && install ;; + 10) TROJAN="true" && TLS="true" && XTLS="true" && install ;; + 11) update ;; + 12) uninstall ;; + 13) start ;; + 14) restart ;; + 15) stop ;; + 16) showInfo ;; + 17) showLog ;; + 18) warpmenu ;; + 19) setdns64 ;; + 20) system_optimize ;; + 21) open_ports ;; + 22) openipv6 ;; + 23) closeipv6 ;; + *) red "请选择正确的操作!" && exit 1 ;; + esac +} + +action=$1 +[[ -z $1 ]] && action=menu + +case "$action" in + menu | update | uninstall | start | restart | stop | showInfo | showLog) ${action} ;; + *) echo " 参数错误" && echo " 用法: $(basename $0) [menu|update|uninstall|start|restart|stop|showInfo|showLog]" ;; +esac \ No newline at end of file diff --git a/mtproto-copy.sh b/mtproto-copy.sh new file mode 100644 index 00000000..6c0ebdc8 --- /dev/null +++ b/mtproto-copy.sh @@ -0,0 +1,401 @@ +#!/bin/bash +# MTProto一键安装脚本 +# Author: hijk + +RED="\033[31m" # Error message +GREEN="\033[32m" # Success message +YELLOW="\033[33m" # Warning message +BLUE="\033[36m" # Info message +PLAIN='\033[0m' + +export MTG_CONFIG="${MTG_CONFIG:-$HOME/.config/mtg}" +export MTG_ENV="$MTG_CONFIG/env" +export MTG_SECRET="$MTG_CONFIG/secret" +export MTG_CONTAINER="${MTG_CONTAINER:-mtg}" +export MTG_IMAGENAME="${MTG_IMAGENAME:-nineseconds/mtg:1}" + +DOCKER_CMD="$(command -v docker)" +OSNAME=`hostnamectl | grep -i system | cut -d: -f2` + +IP=`curl -s4m8 ip.gs` + +colorEcho() { + echo -e "${1}${@:2}${PLAIN}" +} + +checkwarp(){ + [[ -n $(wg 2>/dev/null) ]] && colorEcho $RED " 检测到WARP已打开,脚本中断运行" && colorEcho $YELLOW " 请关闭WARP之后再运行本脚本" && exit 1 +} + +checkSystem() { + result=$(id | awk '{print $1}') + if [[ $result != "uid=0(root)" ]]; then + colorEcho $RED " 请以root身份执行该脚本" + exit 1 + fi + + res=`which yum` + if [[ "$?" != "0" ]]; then + res=`which apt` + if [ "$?" != "0" ]; then + colorEcho $RED " 不受支持的Linux系统" + exit 1 + fi + res=`hostnamectl | grep -i ubuntu` + if [[ "${res}" != "" ]]; then + OS="ubuntu" + else + OS="debian" + fi + PMT="apt" + CMD_INSTALL="apt install -y " + CMD_REMOVE="apt remove -y " + else + OS="centos" + PMT="yum" + CMD_INSTALL="yum install -y " + CMD_REMOVE="yum remove -y " + fi + res=`which systemctl` + if [[ "$?" != "0" ]]; then + colorEcho $RED " 系统版本过低,请升级到最新版本" + exit 1 + fi +} + +status() { + if [[ "$DOCKER_CMD" = "" ]]; then + echo 0 + return + elif [[ ! -f $MTG_ENV ]]; then + echo 1 + return + fi + port=`grep MTG_PORT $MTG_ENV|cut -d= -f2` + if [[ -z "$port" ]]; then + echo 2 + return + fi + res=`ss -ntlp| grep ${port} | grep docker` + if [[ -z "$res" ]]; then + echo 3 + else + echo 4 + fi +} + +statusText() { + res=`status` + case $res in + 3) + echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN} + ;; + 4) + echo -e ${GREEN}已安装${PLAIN} ${GREEN}正在运行${PLAIN} + ;; + *) + echo -e ${RED}未安装${PLAIN} + ;; + esac +} + +getData() { + read -p " 请输入MTProto端口[100-65535的一个数字]:" PORT + [[ -z "${PORT}" ]] && { + echo -e " ${RED}请输入MTProto端口!${PLAIN}" + exit 1 + } + if [[ "${PORT:0:1}" = "0" ]]; then + echo -e " ${RED}端口不能以0开头${PLAIN}" + exit 1 + fi + MTG_PORT=$PORT + mkdir -p $MTG_CONFIG + echo "MTG_IMAGENAME=$MTG_IMAGENAME" > "$MTG_ENV" + echo "MTG_PORT=$MTG_PORT" >> "$MTG_ENV" + echo "MTG_CONTAINER=$MTG_CONTAINER" >> "$MTG_ENV" +} + +installDocker() { + if [[ "$DOCKER_CMD" != "" ]]; then + systemctl enable docker + systemctl start docker + selinux + return + fi + + #$CMD_REMOVE docker docker-engine docker.io containerd runc + $PMT clean all + $CMD_INSTALL wget curl + if [[ $PMT = "apt" ]]; then + apt clean all + apt-get -y install \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg-agent \ + software-properties-common + curl -fsSL https://download.docker.com/linux/$OS/gpg | apt-key add - + add-apt-repository \ + "deb [arch=amd64] https://download.docker.com/linux/$OS \ + $(lsb_release -cs) \ + stable" + apt update + else + wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo + yum clean all + fi + $CMD_INSTALL docker-ce docker-ce-cli containerd.io + + DOCKER_CMD="$(command -v docker)" + if [[ "$DOCKER_CMD" = "" ]]; then + echo -e " ${RED}$OSNAME docker安装失败,请到https://hijk.art反馈${PLAIN}" + exit 1 + fi + systemctl enable docker + systemctl start docker + + selinux +} + +pullImage() { + if [[ "$DOCKER_CMD" = "" ]]; then + echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}" + exit 1 + fi + + set -a + source "$MTG_ENV" + set +a + + $DOCKER_CMD pull "$MTG_IMAGENAME" > /dev/null +} + +selinux() { + 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 +} + +firewall() { + port=$1 + systemctl status firewalld > /dev/null 2>&1 + if [[ $? -eq 0 ]];then + firewall-cmd --permanent --add-port=$port/tcp + firewall-cmd --reload + else + nl=`iptables -nL | nl | grep FORWARD | awk '{print $1}'` + if [ "$nl" != "3" ]; then + iptables -I INPUT -p tcp --dport=$port -j ACCEPT + else + res=`ufw status | grep -i inactive` + if [ "$res" = "" ]; then + ufw allow $port/tcp + fi + fi + fi +} + +start() { + res=`status` + if [[ $res -lt 3 ]]; then + echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}" + return + fi + + set -a + source "$MTG_ENV" + set +a + + if [[ ! -f "$MTG_SECRET" ]]; then + $DOCKER_CMD run \ + --rm \ + "$MTG_IMAGENAME" \ + generate-secret tls -c "$(openssl rand -hex 16).com" \ + > "$MTG_SECRET" + fi + + $DOCKER_CMD ps --filter "Name=$MTG_CONTAINER" -aq | xargs -r $DOCKER_CMD rm -fv > /dev/null + $DOCKER_CMD run \ + -d \ + --restart=unless-stopped \ + --name "$MTG_CONTAINER" \ + --ulimit nofile=51200:51200 \ + -p "$MTG_PORT:3128" \ + "$MTG_IMAGENAME" run "$(cat "$MTG_SECRET")" > /dev/null + + sleep 3 + res=`ss -ntlp| grep ${MTG_PORT} | grep docker` + if [[ "$res" = "" ]]; then + docker logs $MTG_CONTAINER | tail + echo -e " ${RED}$OSNAME 启动docker镜像失败,请到 https://hijk.art 反馈${PLAIN}" + exit 1 + else + colorEcho $BLUE " MTProto启动成功!" + fi +} + +stop() { + res=`status` + if [[ $res -lt 3 ]]; then + echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}" + return + fi + + set -a + source "$MTG_ENV" + set +a + + $DOCKER_CMD stop $MTG_CONTAINER >> /dev/null + colorEcho $BLUE " MTProto停止成功!" +} + +showInfo() { + res=`status` + if [[ $res -lt 3 ]]; then + echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}" + return + fi + + SECRET=$(cat "$MTG_SECRET") + set -a + source "$MTG_ENV" + set +a + + echo + echo -e " ${RED}MTProto代理信息:${PLAIN}" + echo + echo -n -e " ${BLUE}当前状态:${PLAIN}" + statusText + echo -e " ${BLUE}IP:${PLAIN}${RED}$IP${PLAIN}" + echo -e " ${BLUE}端口:${PLAIN}${RED}$MTG_PORT${PLAIN}" + echo -e " ${BLUE}密钥:${PLAIN}${RED}$SECRET${PLAIN}" + echo "" + echo -e " 如需获取tg://proxy形式的链接,请打开telegrame关注${GREEN}@MTProxybot${PLAIN}生成" + echo "" +} + +install() { + getData + installDocker + pullImage + start + firewall $MTG_PORT + showInfo +} + +update() { + res=`status` + if [[ $res -lt 2 ]]; then + echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}" + return + fi + + pullImage + stop + start + showInfo +} + +uninstall() { + echo "" + read -p " 确定卸载MTProto?[y/n]:" answer + if [[ "$answer" = "y" ]] || [[ "$answer" = "Y" ]]; then + stop + rm -rf $MTG_CONFIG + docker system prune -af + systemctl stop docker + systemctl disable docker + $CMD_REMOVE docker-ce docker-ce-cli containerd.io + colorEcho $GREEN " 卸载成功" + fi +} + +restart() { + res=`status` + if [[ $res -lt 3 ]]; then + echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}" + return + fi + + stop + start +} + +reconfig() +{ + res=`status` + if [[ $res -lt 2 ]]; then + echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}" + return + fi + + getData + stop + start + firewall $MTG_PORT + showInfo +} + +showLog() { + res=`status` + if [[ $res -lt 3 ]]; then + echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}" + return + fi + + set -a + source "$MTG_ENV" + set +a + + $DOCKER_CMD logs $MTG_CONTAINER | tail +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}MTProto一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) #" + echo -e "# ${GREEN}网址${PLAIN}: https://hijk.art #" + echo -e "# ${GREEN}论坛${PLAIN}: https://hijk.club #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/hijkclub #" + echo -e "# ${GREEN}Youtube频道${PLAIN}: https://youtube.com/channel/UCYTB--VsObzepVJtc9yvUxQ #" + echo "#############################################################" + echo "" + echo -e " ${GREEN}1.${PLAIN} 安装MTProto代理" + echo -e " ${GREEN}2.${PLAIN} 更新MTProto代理" + echo -e " ${GREEN}3.${PLAIN} 卸载MTProto代理" + echo " -------------" + echo -e " ${GREEN}4.${PLAIN} 启动MTProto代理" + echo -e " ${GREEN}5.${PLAIN} 重启MTProto代理" + echo -e " ${GREEN}6.${PLAIN} 停止MTProto代理" + echo " -------------" + echo -e " ${GREEN}7.${PLAIN} 查看MTProto信息" + echo -e " ${GREEN}8.${PLAIN} 修改MTProto配置" + echo -e " ${GREEN}9.${PLAIN} 查看MTProto日志" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo + echo -n " 当前状态:" + statusText + echo + read -p " 请选择操作[0-9]:" answer + case $answer in + 0) exit 1 ;; + 1) install ;; + 2) update ;; + 3) uninstall ;; + 4) start ;; + 5) restart ;; + 6) stop ;; + 7) showInfo ;; + 8) reconfig ;; + 9) showLog ;; + *) echo -e " ${RED}请选择正确的操作!${PLAIN}" && exit 1 ;; + esac +} + +checkSystem +checkwarp +menu diff --git a/mtproto.sh b/mtproto.sh index 24455a34..6c0ebdc8 100644 --- a/mtproto.sh +++ b/mtproto.sh @@ -17,12 +17,16 @@ export MTG_IMAGENAME="${MTG_IMAGENAME:-nineseconds/mtg:1}" DOCKER_CMD="$(command -v docker)" OSNAME=`hostnamectl | grep -i system | cut -d: -f2` -IP=`curl -sL -4 ip.sb` +IP=`curl -s4m8 ip.gs` colorEcho() { echo -e "${1}${@:2}${PLAIN}" } +checkwarp(){ + [[ -n $(wg 2>/dev/null) ]] && colorEcho $RED " 检测到WARP已打开,脚本中断运行" && colorEcho $YELLOW " 请关闭WARP之后再运行本脚本" && exit 1 +} + checkSystem() { result=$(id | awk '{print $1}') if [[ $result != "uid=0(root)" ]]; then @@ -359,7 +363,6 @@ menu() { echo -e "# ${GREEN}Youtube频道${PLAIN}: https://youtube.com/channel/UCYTB--VsObzepVJtc9yvUxQ #" echo "#############################################################" echo "" - echo -e " ${GREEN}1.${PLAIN} 安装MTProto代理" echo -e " ${GREEN}2.${PLAIN} 更新MTProto代理" echo -e " ${GREEN}3.${PLAIN} 卸载MTProto代理" @@ -377,46 +380,22 @@ menu() { echo -n " 当前状态:" statusText echo - read -p " 请选择操作[0-9]:" answer case $answer in - 0) - exit 0 - ;; - 1) - install - ;; - 2) - update - ;; - 3) - uninstall - ;; - 4) - start - ;; - 5) - restart - ;; - 6) - stop - ;; - 7) - showInfo - ;; - 8) - reconfig - ;; - 9) - showLog - ;; - *) - echo -e " ${RED}请选择正确的操作!${PLAIN}" - exit 1 - ;; + 0) exit 1 ;; + 1) install ;; + 2) update ;; + 3) uninstall ;; + 4) start ;; + 5) restart ;; + 6) stop ;; + 7) showInfo ;; + 8) reconfig ;; + 9) showLog ;; + *) echo -e " ${RED}请选择正确的操作!${PLAIN}" && exit 1 ;; esac } checkSystem - +checkwarp menu diff --git a/ngrok1.sh b/ngrok1.sh new file mode 100644 index 00000000..26598a8e --- /dev/null +++ b/ngrok1.sh @@ -0,0 +1,199 @@ +#!/bin/bash + +# 控制台字体 +red(){ + echo -e "\033[31m\033[01m$1\033[0m" +} + +green(){ + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow(){ + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "alpine") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Alpine") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update" "apk update -f") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "apk add -f") + +[[ $EUID -ne 0 ]] && yellow "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持VPS的当前系统,请使用主流操作系统" && exit 1 +[[ -z $(curl 2>/dev/null) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl + +## 统计脚本运行次数 +COUNT=$(curl -sm2 "https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fraw.githubusercontents.com%2FMisaka-blog%2FNgrok-1key%2Fmaster%2Fngrok.sh&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false" 2>&1) && +TODAY=$(expr "$COUNT" : '.*\s\([0-9]\{1,\}\)\s/.*') +TOTAL=$(expr "$COUNT" : '.*/\s\([0-9]\{1,\}\)\s.*') + +archAffix(){ + cpuArch=$(uname -m) + case "$cpuArch" in + i686 | i386) cpuArch='386' ;; + x86_64 | amd64) cpuArch='amd64' ;; + armv5tel | arm6l | armv7 | armv7l) cpuArch='arm' ;; + armv8 | aarch64) cpuArch='arm64' ;; + *) red "不支持的CPU架构!" && exit 1 ;; + esac +} + +checkStatus(){ + [[ -z $(ngrok -help 2>/dev/null) ]] && ngrokStatus="未安装" + [[ -n $(ngrok -help 2>/dev/null) ]] && ngrokStatus="已安装" + [[ -f /root/.ngrok2/ngrok.yml ]] && authStatus="已授权" + [[ ! -f /root/.ngrok2/ngrok.yml ]] && authStatus="未授权" +} + +back2menu(){ + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +getNgrokAddress(){ + if [ $httptcp == "tcp" ]; then + tcpNgrok=$(curl --silent --show-error http://127.0.0.1:4040/api/tunnels | sed -nE 's/.*public_url":"tcp:..([^"]*).*/\1/p') + if [[ -n $tcpNgrok ]]; then + green "隧道启动成功!当前TCP隧道地址为:$tcpNgrok" + else + screen -S screen4ngrok -X quit + screen -USdm screen4ngrok ngrok $httptcp $tunnelPort -region $ngrok_region + fi + fi + if [ $httptcp == "http" ]; then + httpNgrok=$(curl --silent --show-error http://127.0.0.1:4040/api/tunnels | sed -nE 's/.*public_url":"http:..([^"]*).*/\1/p') + httpsNgrok=$(curl --silent --show-error http://127.0.0.1:4040/api/tunnels | sed -nE 's/.*public_url":"https..([^"]*).*/\1/p') + if [[ -n $httpNgrok && -n $httpsNgrok ]]; then + green "隧道启动成功!" + yellow "当前隧道HTTP地址为:http://$httpNgrok" + yellow "当前隧道HTTPS地址为:https://$httpsNgrok" + else + screen -S screen4ngrok -X quit + screen -USdm screen4ngrok ngrok $httptcp $tunnelPort -region $ngrok_region + fi + fi +} + +download_ngrok(){ + [ $ngrokStatus == "已安装" ] && red "检测到已安装Ngrok程序包,无需重复安装!!" && exit 1 + wget -N https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-$cpuArch.tgz + tar -xzvf ngrok-stable-linux-$cpuArch.tgz -C /usr/local/bin + green "Ngrok 程序包已安装成功" + back2menu +} + +ngrok_authtoken(){ + [ $ngrokStatus == "未安装" ] && red "检测到未安装Ngrok程序包,无法执行操作!!" && back2menu + [ $authStatus == "已授权" ] && red "已授权Ngrok程序包,无需重复授权!!!" && back2menu + read -p "请输入Ngrok官方网站的Authtoken(可从 https://dashboard.ngrok.com/get-started/your-authtoken 内获取):" authtoken + [ -z $authtoken ] && red "无输入Authtoken,授权过程中断!" && back2menu + ngrok authtoken $authtoken + green "Ngrok Authtoken授权成功" + back2menu +} + +select_region(){ + echo "1. 美国 (us)" + echo "2. 德国 (eu)" + echo "3. 新加坡 (ap)" + echo "4. 澳大利亚 (au)" + echo "5. 南美洲 (sa)" + echo "6. 日本 (jp)" + echo "7. 印度 (in)" + read -p "请选择Ngrok服务器区域(输入1-7内对应的编号,默认为US):" ngrok_region + case "$ngrok_region" in + 2 ) ngrok_region="eu" ;; + 3 ) ngrok_region="ap" ;; + 4 ) ngrok_region="au" ;; + 5 ) ngrok_region="sa" ;; + 6 ) ngrok_region="jp" ;; + 7 ) ngrok_region="in" ;; + *) ngrok_region="us" ;; + esac +} + +runTunnel(){ + [ $ngrokStatus == "未安装" ] && red "检测到未安装Ngrok程序包,无法执行操作!!" && back2menu + [ $authStatus == "未授权" ] && red "未授权Ngrok程序包,无法执行操作!!!" && back2menu + [[ -z $(screen -help 2>/dev/null) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} screen + select_region + read -p "请输入你所使用的协议(默认HTTP):" httptcp + [ -z $httptcp ] && httptcp="http" + read -p "请输入反代端口(默认80):" tunnelPort + [ -z $tunnelPort ] && tunnelPort=80 + screen -USdm screen4ngrok ngrok $httptcp $tunnelPort -region $ngrok_region + yellow "等待5秒,获取Ngrok的外网地址" + sleep 5 + getNgrokAddress + back2menu +} + +killTunnel(){ + [ $ngrokStatus == "未安装" ] && red "检测到未安装Ngrok程序包,无法执行操作!!" && back2menu + [ $authStatus == "未授权" ] && red "未授权Ngrok程序包,无法执行操作!!!" && back2menu + [[ -z $(screen -help 2>/dev/null) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} screen + screen -S screen4ngrok -X quit + green "隧道停止成功!" +} + +uninstall(){ + [ $ngrokStatus == "未安装" ] && red "检测到未安装Ngrok程序包,无法执行操作!!" && back2menu + rm -f /usr/local/bin/ngrok + green "Ngrok 程序包已卸载成功" + back2menu +} + +menu(){ + clear + checkStatus + red "==================================" + echo " " + red " Ngrok 内网穿透一键脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + yellow "今日运行次数:$TODAY 总共运行次数:$TOTAL" + echo " " + green "Ngrok 客户端状态:$ngrokStatus" + green "账户授权状态:$authStatus" + echo " " + green "1. 下载Ngrok程序包" + green "2. 授权Ngrok账号" + green "3. 启用隧道" + green "4. 停用隧道" + green "5. 卸载Ngrok程序包" + green "6. 更新脚本" + green "0. 退出" + echo " " + read -p "请输入数字:" NumberInput + case "$NumberInput" in + 1) download_ngrok ;; + 2) ngrok_authtoken ;; + 3) runTunnel ;; + 4) killTunnel ;; + 5) uninstall ;; + 6) wget -N https://gitlab.com/misakano7545/Ngrok-1key/-/raw/master/ngrok.sh && bash ngrok.sh ;; + *) exit 1 ;; + esac +} + +archAffix +menu \ No newline at end of file diff --git a/root.sh b/root.sh new file mode 100644 index 00000000..cd726b2e --- /dev/null +++ b/root.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "alpine") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Alpine") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update" "apk update -f") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "apk add -f") +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +green(){ + echo -e "\033[32m\033[01m$1\033[0m" +} + +red(){ + echo -e "\033[31m\033[01m$1\033[0m" +} + +yellow(){ + echo -e "\033[33m\033[01m$1\033[0m" +} + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int=0; int<${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持VPS的当前系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P sudo) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} sudo +[[ ! -f /etc/ssh/sshd_config ]] && sudo ${PACKAGE_UPDATE[int]} && sudo ${PACKAGE_INSTALL[int]} openssh-server +[[ -z $(type -P curl) ]] && sudo ${PACKAGE_UPDATE[int]} && sudo ${PACKAGE_INSTALL[int]} curl + +IP=$(curl -sm8 ip.sb) + +sudo lsattr /etc/passwd /etc/shadow >/dev/null 2>&1 +sudo chattr -i /etc/passwd /etc/shadow >/dev/null 2>&1 +sudo chattr -a /etc/passwd /etc/shadow >/dev/null 2>&1 +sudo lsattr /etc/passwd /etc/shadow >/dev/null 2>&1 + +read -p "输入即将设置的SSH端口(如未输入,默认22):" sshport +[ -z $sshport ] && red "端口未设置,将使用默认22端口" && sshport=22 +read -p "输入即将设置的root密码:" password +[ -z $password ] && red "未检测输入,脚本即将退出" && exit 1 +echo root:$password | sudo chpasswd root + +sudo sed -i "s/^#\?Port.*/Port $sshport/g" /etc/ssh/sshd_config; +sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config; +sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/g' /etc/ssh/sshd_config; + +sudo service ssh restart +sudo service sshd restart + +yellow "VPS root登录信息设置完成!" +green "VPS登录地址:$IP:$sshport" +green "用户名:root" +green "密码:$password" +yellow "请妥善保存好登录信息!然后重启VPS确保设置已保存!" diff --git a/screen.sh b/screen.sh new file mode 100644 index 00000000..d4369a35 --- /dev/null +++ b/screen.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持VPS的当前系统,请使用主流的操作系统" && exit 1 +[[ -z $(type -P screen)]] && sudo ${PACKAGE_UPDATE[int]} && sudo ${PACKAGE_INSTALL[int]} screen + +back(){ + echo "设置完成,请选择接下来的操作" + echo "1. 回到主页" + echo "2. 退出脚本" + read -p "请输入选项:" backInput + case "$backInput" in + 1 ) menu ;; + 2 ) exit 1 ;; + esac +} + +createScreen(){ + read -p "设置screen后台名称:" screenName + screen -S $screenName + back +} + +enterScreen(){ + names=`screen -ls | grep '(Detached)' | awk '{print $1}' | awk -F "." '{print $2}'` + [[ -n $names ]] && green "$names" + read -p "输入进入的screen后台名称:" screenName + screen -r $screenName || red "无执行内容" +} + +deleteScreen(){ + names=`screen -ls | grep '(Detached)' | awk '{print $1}' | awk -F "." '{print $2}'` + [[ -n $names ]] && green "$names" + read -p "输入删除的screen后台名称:" screenName + screen -S $screenName -X quit || red "无执行内容" +} + +killAllScreen(){ + names=`screen -ls | grep '(Detached)' | awk '{print $1}' | awk -F "." '{print $2}'` + screen -wipe + [[ -n $names ]] && screen -ls | grep '(Detached)' | cut -d. -f1 | awk '{print $1}' | xargs kill + green "所有screen后台清除完毕" || red "无执行内容,无须清除" +} + +menu(){ + clear + red "==================================" + echo " " + red " Screen 后台运行管理脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 创建screen后台并设置名称" + green "2. 查看并进入指定screen后台" + green "3. 查看并删除指定screen后台" + green "4. 清除所有screen后台" + green "0. 退出脚本" + read -p "请输入选项:" menuNumberInput + case "$menuNumberInput" in + 1 ) + read -p "设置screen后台名称:" screenName + screen -S $screenName + back;; + 2 ) + names=`screen -ls | grep '(Detached)' | awk '{print $1}' | awk -F "." '{print $2}'` + [[ -n $names ]] && green "$names" && read -p "输入进入的screen后台名称:" screenName && screen -r $screenName || red "无执行内容" + back;; + 3 ) + names=`screen -ls | grep '(Detached)' | awk '{print $1}' | awk -F "." '{print $2}'` + [[ -n $names ]] && green "$names" && read -p "输入删除的screen后台名称:" screenName && screen -S $screenName -X quit || red "无执行内容" + back;; + 4 ) + names=`screen -ls | grep '(Detached)' | awk '{print $1}' | awk -F "." '{print $2}'` + screen -wipe + [[ -n $names ]] && screen -ls | grep '(Detached)' | cut -d. -f1 | awk '{print $1}' | xargs kill && green "所有screen后台清除完毕" || red "无执行内容,无须清除" + back;; + 0 ) exit 0 + esac +} + +menu diff --git a/screen2.sh b/screen2.sh new file mode 100644 index 00000000..d77a1e57 --- /dev/null +++ b/screen2.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 +[[ -z $(type -P screen) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} screen + +back2menu() { + green "所选操作执行完成" + read -p "请输入“y”退出,或按任意键回到主菜单:" back2menuInput + case "$back2menuInput" in + y) exit 1 ;; + *) menu ;; + esac +} + +createScreen(){ + read -p "设置screen后台名称:" screenName + screen -S $screenName + back2menu +} + +enterScreen(){ + screenNames=`screen -ls | grep '(Detached)' | awk '{print $1}' | awk -F "." '{print $2}'` + [[ -n $screenNames ]] && yellow "当前运行的Screen会话如下所示:" && green "$screenNames" + read -p "输入进入的screen后台名称:" screenName + screen -r $screenName || red "没有找到 $screenName 的会话" + back2menu +} + +deleteScreen(){ + screenNames=`screen -ls | grep '(Detached)' | awk '{print $1}' | awk -F "." '{print $2}'` + [[ -n $screenNames ]] && green "$screenNames" + read -p "输入删除的screen后台名称:" screenName + screen -S $screenName -X quit || red "没有找到 $screenName 的会话" + back2menu +} + +killAllScreen(){ + screenNames=`screen -ls | grep '(Detached)' | awk '{print $1}' | awk -F "." '{print $2}'` + screen -wipe + [[ -n $screenNames ]] && screen -ls | grep '(Detached)' | cut -d. -f1 | awk '{print $1}' | xargs kill + green "所有screen后台会话已清除完毕" || red "没有任何screen后台会话" + back2menu +} + +menu(){ + clear + red "==================================" + echo " " + red " Screen 后台运行管理脚本 " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "1. 创建screen后台并设置名称" + green "2. 查看并进入指定screen后台" + green "3. 查看并删除指定screen后台" + green "4. 清除所有screen后台" + green "0. 退出脚本" + read -p "请输入选项:" menuNumberInput + case "$menuNumberInput" in + 1 ) createScreen ;; + 2 ) enterScreen ;; + 3 ) deleteScreen ;; + 4 ) killAllScreen ;; + 0 ) exit 1 ;; + esac +} + +menu \ No newline at end of file diff --git a/socat.sh b/socat.sh new file mode 100644 index 00000000..20b46a7c --- /dev/null +++ b/socat.sh @@ -0,0 +1,166 @@ +#! /bin/bash +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin +export PATH + +Green="\033[32m" +Font="\033[0m" +Blue="\033[33m" + +rootness(){ + if [[ $EUID -ne 0 ]]; then + echo "Error:This script must be run as root!" 1>&2 + exit 1 + fi +} + +checkos(){ + if [[ -f /etc/redhat-release ]];then + OS=CentOS + elif cat /etc/issue | grep -q -E -i "debian";then + OS=Debian + elif cat /etc/issue | grep -q -E -i "ubuntu";then + OS=Ubuntu + elif cat /etc/issue | grep -q -E -i "centos|red hat|redhat";then + OS=CentOS + elif cat /proc/version | grep -q -E -i "debian";then + OS=Debian + elif cat /proc/version | grep -q -E -i "ubuntu";then + OS=Ubuntu + elif cat /proc/version | grep -q -E -i "centos|red hat|redhat";then + OS=CentOS + else + echo "Not supported OS, Please reinstall OS and try again." + exit 1 + fi +} + +disable_selinux(){ + if [ -s /etc/selinux/config ] && grep 'SELINUX=enforcing' /etc/selinux/config; then + sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config + setenforce 0 + fi +} + +disable_iptables(){ + systemctl stop firewalld.service >/dev/null 2>&1 + systemctl disable firewalld.service >/dev/null 2>&1 + service iptables stop >/dev/null 2>&1 + chkconfig iptables off >/dev/null 2>&1 +} + +get_ip(){ + ip=`curl http://whatismyip.akamai.com` +} + +config_socat(){ + echo -e "${Green}请输入Socat配置信息!${Font}" + read -p "请输入本地端口:" port1 + read -p "请输入远程端口:" port2 + read -p "请输入远程IP:" socatip +} + +start_socat(){ + echo -e "${Green}正在配置Socat...${Font}" + nohup socat TCP4-LISTEN:${port1},reuseaddr,fork TCP4:${socatip}:${port2} >> /root/socat.log 2>&1 & + nohup socat -T 600 UDP4-LISTEN:${port1},reuseaddr,fork UDP4:${socatip}:${port2} >> /root/socat.log 2>&1 & + if [ "${OS}" == 'CentOS' ];then + sed -i '/exit/d' /etc/rc.d/rc.local + echo "nohup socat TCP4-LISTEN:${port1},reuseaddr,fork TCP4:${socatip}:${port2} >> /root/socat.log 2>&1 & + nohup socat -T 600 UDP4-LISTEN:${port1},reuseaddr,fork UDP4:${socatip}:${port2} >> /root/socat.log 2>&1 & + " >> /etc/rc.d/rc.local + chmod +x /etc/rc.d/rc.local + elif [ -s /etc/rc.local ]; then + sed -i '/exit/d' /etc/rc.local + echo "nohup socat TCP4-LISTEN:${port1},reuseaddr,fork TCP4:${socatip}:${port2} >> /root/socat.log 2>&1 & + nohup socat -T 600 UDP4-LISTEN:${port1},reuseaddr,fork UDP4:${socatip}:${port2} >> /root/socat.log 2>&1 & + " >> /etc/rc.local + chmod +x /etc/rc.local + else +echo -e "${Green}检测到系统无rc.local自启,正在为其配置... ${Font} " +echo "[Unit] +Description=/etc/rc.local +ConditionPathExists=/etc/rc.local + +[Service] +Type=forking +ExecStart=/etc/rc.local start +TimeoutSec=0 +StandardOutput=tty +RemainAfterExit=yes +SysVStartPriority=99 + +[Install] +WantedBy=multi-user.target +" > /etc/systemd/system/rc-local.service +echo "#!/bin/sh -e +# +# rc.local +# +# This script is executed at the end of each multiuser runlevel. +# Make sure that the script will "exit 0" on success or any other +# value on error. +# +# In order to enable or disable this script just change the execution +# bits. +# +# By default this script does nothing. +" > /etc/rc.local +echo "nohup socat TCP4-LISTEN:${port1},reuseaddr,fork TCP4:${socatip}:${port2} >> /root/socat.log 2>&1 & +nohup socat -T 600 UDP4-LISTEN:${port1},reuseaddr,fork UDP4:${socatip}:${port2} >> /root/socat.log 2>&1 & +" >> /etc/rc.local +chmod +x /etc/rc.local +systemctl enable rc-local >/dev/null 2>&1 +systemctl start rc-local >/dev/null 2>&1 + fi + get_ip + sleep 3 + echo + echo -e "${Green}Socat安装并配置成功!${Font}" + echo -e "${Blue}你的本地端口为:${port1}${Font}" + echo -e "${Blue}你的远程端口为:${port2}${Font}" + echo -e "${Blue}你的本地服务器IP为:${ip}${Font}" + exit 0 +} + +install_socat(){ + echo -e "${Green}即将安装Socat...${Font}" + if [ "${OS}" == 'CentOS' ];then + yum install -y socat + else + apt-get -y update + apt-get install -y socat + fi + if [ -s /usr/bin/socat ]; then + echo -e "${Green}Socat安装完成!${Font}" + fi +} + +status_socat(){ + if [ -s /usr/bin/socat ]; then + echo -e "${Green}检测到Socat已存在,并跳过安装步骤!${Font}" + main_x + else + main_y + fi +} + +main_x(){ +checkos +rootness +disable_selinux +disable_iptables +config_socat +start_socat +} + +main_y(){ +checkos +rootness +disable_selinux +disable_iptables +install_socat +config_socat +start_socat +} + +status_socat diff --git a/ss.sh b/ss.sh index df9b5504..1a566309 100644 --- a/ss.sh +++ b/ss.sh @@ -96,7 +96,7 @@ statusText() { getData() { echo "" read -p " 请设置SS的密码(不输入则随机生成):" PASSWORD - [[ -z "$PASSWORD" ]] && PASSWORD=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1` + [[ -z "$PASSWORD" ]] && PASSWORD=`date +%s%N | md5sum | cut -c 1-16` echo "" colorEcho $BLUE " 密码: $PASSWORD" diff --git a/tool.sh b/tool.sh new file mode 100644 index 00000000..f1d93c5a --- /dev/null +++ b/tool.sh @@ -0,0 +1,515 @@ +#!/bin/bash + +# 全局变量 +ver="2.1.9" +changeLog="新增Misaka魔改版X-ui脚本" +arch=$(uname -m) +virt=$(systemd-detect-virt) +kernelVer=$(uname -r) +TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "alpine") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Alpine") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update" "apk update -f") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "apk add -f") +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +# 控制台字体 +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 必须以root运行脚本 +[[ $(id -u) != 0 ]] && red "请使用“sudo -i”登录root用户后执行工具箱脚本!!!" && exit 1 + +# 判断系统,此部分代码感谢fscarmen的技术指导 +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持VPS的当前系统,请使用主流操作系统" && exit 1 + +# 更新系统及安装依赖,此部分代码感谢fscarmen的技术指导 +${PACKAGE_UPDATE[int]} +${PACKAGE_INSTALL[int]} curl wget sudo + +# 获取IP地址及其信息 +IP4=$(curl -s4m8 https://ip.gs/json) +IP6=$(curl -s6m8 https://ip.gs/json) +WAN4=$(expr "$IP4" : '.*ip\":\"\([^"]*\).*') +WAN6=$(expr "$IP6" : '.*ip\":\"\([^"]*\).*') +COUNTRY4=$(expr "$IP4" : '.*country\":\"\([^"]*\).*') +COUNTRY6=$(expr "$IP6" : '.*country\":\"\([^"]*\).*') +ASNORG4=$(expr "$IP4" : '.*asn_org\":\"\([^"]*\).*') +ASNORG6=$(expr "$IP6" : '.*asn_org\":\"\([^"]*\).*') + +# 判断IP地址状态 +IP4="$WAN4 ($COUNTRY4 $ASNORG4)" +IP6="$WAN6 ($COUNTRY6 $ASNORG6)" +if [ -z $WAN4 ]; then + IP4="当前VPS未检测到IPv4地址" +fi +if [ -z $WAN6 ]; then + IP6="当前VPS未检测到IPv6地址" +fi + +# 获取脚本运行次数 +COUNT=$(curl -sm8 "https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2FMisaka-blog%2FMisakaLinuxToolbox%40master%2FMisakaToolbox.sh&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false" 2>&1) && +TODAY=$(expr "$COUNT" : '.*\s\([0-9]\{1,\}\)\s/.*') +TOTAL=$(expr "$COUNT" : '.*/\s\([0-9]\{1,\}\)\s.*') + +#第一页 +oraclefirewall() { + if [ $SYSTEM = "CentOS" ]; then + systemctl stop oracle-cloud-agent + systemctl disable oracle-cloud-agent + systemctl stop oracle-cloud-agent-updater + systemctl disable oracle-cloud-agent-updater + systemctl stop firewalld.service + systemctl disable firewalld.service + yellow "Oracle Cloud原生系统防火墙禁用成功" + else + iptables -P INPUT ACCEPT + iptables -P FORWARD ACCEPT + iptables -P OUTPUT ACCEPT + iptables -F + apt-get purge netfilter-persistent -y + yellow "Oracle Cloud原生系统防火墙禁用成功" + fi +} + +open_ports() { + systemctl stop firewalld.service + systemctl disable firewalld.service + setenforce 0 + ufw disable + iptables -P INPUT ACCEPT + iptables -P FORWARD ACCEPT + iptables -P OUTPUT ACCEPT + iptables -t nat -F + iptables -t mangle -F + iptables -F + iptables -X + netfilter-persistent save + yellow "VPS中的所有网络端口已开启" +} + +euservDig9() { + echo -e "search blue.kundencontroller.de\noptions rotate\nnameserver 2a02:180:6:5::1c\nnameserver 2a02:180:6:5::4\nnameserver 2a02:180:6:5::1e\nnameserver 2a02:180:6:5::1d" >/etc/resolv.conf +} + +rootLogin() { + wget -N https://raw.githubusercontents.com/Misaka-blog/rootLogin/master/root.sh && bash root.sh +} + +screenManager() { + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/screenManager@master/screen.sh && chmod -R 777 screen.sh && bash screen.sh +} + +bbr() { + if [ ${virt} == "kvm" ]; then + wget -N --no-check-certificate "https://raw.githubusercontents.com/chiakge/Linux-NetSpeed/master/tcp.sh" && chmod +x tcp.sh && ./tcp.sh + fi + if [ ${virt} == "zvm" ]; then + wget -N --no-check-certificate "https://raw.githubusercontents.com/chiakge/Linux-NetSpeed/master/tcp.sh" && chmod +x tcp.sh && ./tcp.sh + fi + if [ ${virt} == "microsoft" ]; then + wget -N --no-check-certificate "https://raw.githubusercontents.com/chiakge/Linux-NetSpeed/master/tcp.sh" && chmod +x tcp.sh && ./tcp.sh + fi + if [ ${virt} == "xen" ]; then + wget -N --no-check-certificate "https://raw.githubusercontents.com/chiakge/Linux-NetSpeed/master/tcp.sh" && chmod +x tcp.sh && ./tcp.sh + fi + if [ ${virt} == "openvz" ]; then + [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]] && red "未开启TUN,请去VPS后台开启" && exit 1 + wget --no-cache -O lkl-haproxy.sh https://raw.githubusercontents.com/mzz2017/lkl-haproxy/master/lkl-haproxy.sh && bash lkl-haproxy.sh + fi + if [ ${virt} == "lxc" ]; then + red "抱歉,你的VPS暂时不支持bbr加速脚本" + fi +} + +warp() { + echo " " + green "请选择你接下来使用的脚本" + echo " " + echo "1. Misaka-WARP" + echo "2. fscarmen" + echo "3. fscarmen-docker" + echo "4. fscarmen warp解锁奈飞流媒体脚本" + echo "5. P3TERX" + echo " " + echo "0. 返回主菜单" + read -p "请输入选项:" warpNumberInput + case "$warpNumberInput" in + 1) wget -N https://raw.githubusercontents.com/Misaka-blog/Misaka-WARP-Script/master/misakawarp.sh && bash misakawarp.sh ;; + 2) wget -N https://cdn.jsdelivr.net/gh/fscarmen/warp/menu.sh && bash menu.sh ;; + 3) wget -N https://cdn.jsdelivr.net/gh/fscarmen/warp/docker.sh && bash docker.sh ;; + 4) bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/warp_unlock/main/unlock.sh) ;; + 5) bash <(curl -fsSL git.io/warp.sh) ;; + 0) menu ;; + esac +} + +dockerInstall() { + curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun +} + +acmesh() { + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/acme-1key@master/acme1key.sh && chmod -R 777 acme1key.sh && bash acme1key.sh +} + +dns64server() { + echo -e "nameserver 2001:67c:2b0::4\nnameserver 2001:67c:2b0::6" >/etc/resolv.conf + yellow "设置DNS64服务器完成" +} + +cfArgoTunnel() { + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/argo-tunnel-script@master/argo.sh && bash argo.sh +} + +ngrokScript() { + wget -N https://raw.githubusercontents.com/Misaka-blog/Ngrok-1key/master/ngrok.sh && bash ngrok.sh +} + +setlanguage(){ + chattr -i /etc/locale.gen + cat > '/etc/locale.gen' << EOF +zh_CN.UTF-8 UTF-8 +zh_TW.UTF-8 UTF-8 +en_US.UTF-8 UTF-8 +ja_JP.UTF-8 UTF-8 +EOF + locale-gen + update-locale + chattr -i /etc/default/locale + cat > '/etc/default/locale' << EOF +LANGUAGE="zh_CN.UTF-8" +LANG="zh_CN.UTF-8" +LC_ALL="zh_CN.UTF-8" +EOF + export LANGUAGE="zh_CN.UTF-8" + export LANG="zh_CN.UTF-8" + export LC_ALL="zh_CN.UTF-8" +} +# 第二页 +bt() { + if [ $SYSTEM = "CentOS" ]; then + yum install -y wget && wget -O install.sh http://www.aapanel.com/script/install_6.0_en.sh && bash install.sh forum + elif [ $SYSTEM = "Debian" ]; then + wget -O install.sh http://www.aapanel.com/script/install-ubuntu_6.0_en.sh && bash install.sh forum + else + wget -O install.sh http://www.aapanel.com/script/install-ubuntu_6.0_en.sh && sudo bash install.sh forum + fi +} + +xui() { + echo " " + green "请选择你接下来使用的X-ui面板版本" + echo " " + echo "1. 使用X-ui官方原版" + echo "2. 使用Misaka魔改版" + echo " " + echo "0. 返回主菜单" + read -p "请输入选项:" xuiNumberInput + case "$page3NumberInput" in + 1) bash <(curl -Ls https://raw.githubusercontents.com/vaxilu/x-ui/master/install.sh) ;; + 2) wget -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/x-ui/master/install.sh && bash install.sh ;; + 0) menu ;; + esac +} + +aria2() { + ${PACKAGE_INSTALL[int]} ca-certificates + wget -N git.io/aria2.sh && chmod +x aria2.sh && bash aria2.sh +} + +cyberpanel() { + sh <(curl https://cyberpanel.net/install.sh || wget -O - https://cyberpanel.net/install.sh) +} + +qlPanel() { + [[ -z $(docker -v 2>/dev/null) ]] && curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun + read -p "请输入将要安装的青龙面板容器名称:" qlPanelName + read -p "请输入外网访问端口:" qlHTTPPort + docker run -dit --name $qlPanelName --hostname $qlPanelName --restart always -p $qlHTTPPort:5700 -v $PWD/QL/config:/ql/config -v $PWD/QL/log:/ql/log -v $PWD/QL/db:/ql/db -v $PWD/QL/scripts:/ql/scripts -v $PWD/QL/jbot:/ql/jbot whyour/qinglong:latest + yellow "青龙面板安装成功!!!" + green "IPv4访问地址为:http://$WAN4:$qlHTTPPort" + green "IPv6访问地址为:http://[$WAN6]:$qlHTTPPort" + yellow "请稍等1-3分钟,等待青龙面板容器启动" +} + +trojanpanel() { + source <(curl -sL https://git.io/trojan-install) +} + +lxcovztun() { + wget -N https://raw.githubusercontents.com/Misaka-blog/tun-script/master/tun.sh && bash tun.sh +} + +# 第三页 +macka() { + wget -P /root -N --no-check-certificate "https://raw.githubusercontents.com/mack-a/v2ray-agent/master/install.sh" && chmod 700 /root/install.sh && /root/install.sh +} + +boy233() { + bash <(curl -s -L https://git.io/v2ray.sh) +} + +misakaXray() { + bash <(curl -sL https://cdn.jsdelivr.net/gh/Misaka-blog/Xray-script@master/xray.sh) +} + +tgMTProxy() { + mkdir /home/mtproxy && cd /home/mtproxy + curl -s -o mtproxy.sh https://raw.githubusercontents.com/sunpma/mtp/master/mtproxy.sh && chmod +x mtproxy.sh && bash mtproxy.sh + bash mtproxy.sh start +} + +shadowsocks() { + wget --no-check-certificate -O shadowsocks-all.sh https://raw.githubusercontents.com/teddysun/shadowsocks_install/master/shadowsocks-all.sh + chmod +x shadowsocks-all.sh + ./shadowsocks-all.sh 2>&1 | tee shadowsocks-all.log +} + +# 第四页 +vpsBench() { + echo " " + green "请选择你接下来使用的脚本" + echo " " + echo "1. 使用misakabench" + echo "2. 使用bench.sh" + echo "3. 使用superbench" + echo "4. 使用lemonbench" + echo " " + echo "0. 返回主菜单" + read -p "请输入选项:" page3NumberInput + case "$page3NumberInput" in + 1) bash <(curl -Lso- https://cdn.jsdelivr.net/gh/Misaka-blog/misakabench@master/misakabench.sh) ;; + 2) wget -qO- bench.sh | bash ;; + 3) wget -qO- --no-check-certificate https://raw.githubusercontents.com/oooldking/script/master/superbench.sh | bash ;; + 4) curl -fsL https://ilemonra.in/LemonBenchIntl | bash -s fast ;; + 0) menu ;; + esac +} + +mediaUnblockTest() { + bash <(curl -L -s https://raw.githubusercontents.com/lmc999/RegionRestrictionCheck/main/check.sh) +} + +speedTest() { + bash <(curl -Lso- https://git.io/superspeed) +} + +# 第五页 +nezha() { + curl -L https://raw.githubusercontents.com/naiba/nezha/master/script/install.sh -o nezha.sh + chmod +x nezha.sh + sudo ./nezha.sh +} + +serverstatus() { + wget -N https://raw.githubusercontents.com/cokemine/ServerStatus-Hotaru/master/status.sh + echo " " + green "请选择你需要安装探针的客户端类型" + echo " " + echo "1. 服务端" + echo "2. 监控端" + echo "0. 返回主页" + echo " " + read -p "请输入选项:" menuNumberInput1 + case "$menuNumberInput1" in + 1) bash status.sh s ;; + 2) bash status.sh c ;; + 0) menu ;; + esac +} + +ddsystem() { + wget --no-check-certificate -O ~/Network-Reinstall-System-Modify.sh 'https://www.cxthhhhh.com/CXT-Library/Network-Reinstall-System-Modify/Network-Reinstall-System-Modify.sh' && chmod +x ~/Network-Reinstall-System-Modify.sh && bash ~/Network-Reinstall-System-Modify.sh -UI_Options +} + +# 菜单 +menu() { + clear + red "==================================" + echo " " + red " Misaka Linux Toolbox " + red " by 小御坂的破站 " + echo " " + red " Site: https://owo.misaka.rest " + echo " " + red "==================================" + echo " " + green "当前工具箱版本:v$ver" + green "更新日志:$changeLog" + green "今日运行次数:$TODAY 总共运行次数:$TOTAL" + echo " " + red "检测到VPS信息如下:" + yellow "处理器架构:$arch" + yellow "虚拟化架构:$virt" + yellow "操作系统:$CMD" + yellow "内核版本:$kernelVer" + yellow "公网IPv4地址:$IP4" + yellow "公网IPv6地址:$IP6" + echo " " + green "下面是脚本分类,请选择对应的分类后进入到相对应的菜单中" + echo " " + echo "1. 系统相关" + echo "2. 面板相关" + echo "3. 节点相关" + echo "4. VPS测试" + echo "5. VPS探针" + [ ${virt} == "kvm" ] && echo "6. 更换VPS系统(DD系统)" + echo " " + echo "9. 更新工具箱" + echo "0. 退出工具箱" + echo " " + read -p "请输入选项:" menuNumberInput + case "$menuNumberInput" in + 1) page1 ;; + 2) page2 ;; + 3) page3 ;; + 4) page4 ;; + 5) page5 ;; + 6) ddsystem ;; + 9) wget -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/MisakaLinuxToolbox/master/MisakaToolbox.sh && chmod -R 777 MisakaToolbox.sh && bash MisakaToolbox.sh ;; + 0) exit 0 ;; + esac +} + +page1() { + echo " " + green "请选择你接下来的操作" + echo " " + echo "1. Oracle Cloud原生系统关闭防火墙" + echo "2. 开启VPS中所有的网络端口" + echo "3. 德鸡DiG9正常访问网络解决方案" + echo "4. 修改登录方式为 root + 密码 登录" + echo "5. Screen 后台任务管理" + echo "6. 开启BBR加速" + echo "7. 设置DNS64服务器" + echo "8. 安装WARP" + echo "9. 安装docker" + echo "10. Acme.sh 证书申请脚本" + echo "11. CloudFlare Argo Tunnel一键脚本" + echo "12. Ngrok 内网穿透一键脚本" + echo "13. LXC/OVZ VPS打开TUN模块" + echo "14. 更换Linux软件源" + echo "15. 更换系统语言为中文" + echo " " + echo "0. 返回主菜单" + read -p "请输入选项:" page1NumberInput + case "$page1NumberInput" in + 1) oraclefirewall ;; + 2) open_ports ;; + 3) euservDig9 ;; + 4) rootLogin ;; + 5) screenManager ;; + 6) bbr ;; + 7) dns64server ;; + 8) warp ;; + 9) dockerInstall ;; + 10) acmesh ;; + 11) cfArgoTunnel ;; + 12) ngrokScript ;; + 13) lxcovztun ;; + 14) bash <(curl -sSL https://cdn.jsdelivr.net/gh/SuperManito/LinuxMirrors@main/ChangeMirrors.sh) ;; + 15) setlanguage ;; + 0) menu ;; + esac +} + +page2() { + echo " " + green "请选择你准备安装的面板" + echo " " + echo "1. 安装aapanel面板" + echo "2. 安装x-ui面板" + echo "3. 安装aria2(面板为远程链接)" + echo "4. 安装CyberPanel面板" + echo "5. 安装青龙面板" + echo "6. 安装Trojan面板" + echo "7. 安装V2ray.Fun面板" + echo " " + echo "0. 返回主菜单" + read -p "请输入选项:" page2NumberInput + case "$page2NumberInput" in + 1) bt ;; + 2) xui ;; + 3) aria2 ;; + 4) cyberpanel ;; + 5) qlPanel ;; + 6) trojanpanel ;; + 7) wget -N --no-check-certificate https://raw.githubusercontents.com/FunctionClub/V2ray.Fun/master/install.sh && bash install.sh ;; + 0) menu ;; + esac +} + +page3() { + echo " " + green "请选择你接下来使用的脚本" + echo " " + echo "1. 使用Mack-a的脚本" + echo "2. 使用233boy的脚本" + echo "3. 使用Misaka Xray的脚本" + echo "4. 搭建Telegram MTProxy代理" + echo "5. 使用Teddysun脚本搭建ShadowSocks" + echo " " + echo "0. 返回主菜单" + read -p "请输入选项:" page3NumberInput + case "$page3NumberInput" in + 1) macka ;; + 2) boy233 ;; + 3) misakaXray ;; + 4) tgMTProxy ;; + 5) shadowsocks ;; + 0) menu ;; + esac +} + +page4() { + echo " " + green "请选择你接下来的操作" + echo " " + echo "1. VPS测试" + echo "2. 流媒体检测" + echo "3. VPS三网测速" + echo " " + echo "0. 返回主菜单" + read -p "请输入选项:" page4NumberInput + case "$page4NumberInput" in + 1) vpsBench ;; + 2) mediaUnblockTest ;; + 3) speedTest ;; + 0) menu ;; + esac +} + +page5() { + echo " " + green "请选择你需要的探针" + echo " " + echo "1. 哪吒面板" + echo "2. 可乐ServerStatus-Horatu" + echo " " + echo "0. 返回主菜单" + read -p "请输入选项:" page5NumberInput + case "$page5NumberInput" in + 1) nezha ;; + 2) serverstatus ;; + 0) menu ;; + esac +} + +menu \ No newline at end of file diff --git a/trojan1.sh b/trojan1.sh new file mode 100644 index 00000000..5203d011 --- /dev/null +++ b/trojan1.sh @@ -0,0 +1,920 @@ +#!/bin/bash + +RED="\033[31m" # Error message +GREEN="\033[32m" # Success message +YELLOW="\033[33m" # Warning message +BLUE="\033[36m" # Info message +PLAIN='\033[0m' + +OS=$(hostnamectl | grep -i system | cut -d: -f2) + +checkwarp() { + [[ -n $(wg 2>/dev/null) ]] && colorEcho $RED " 检测到WARP已打开,脚本中断运行" && colorEcho $YELLOW " 请关闭WARP之后再运行本脚本" && exit 1 +} + +V6_PROXY="" +IP=$(curl -s4m8 https://ip.gs) +[[ "$?" != "0" ]] && IP=$(curl -s6m8 https://ip.gs) && V6_PROXY="https://gh-proxy-misakano7545.koyeb.app/" +[[ $V6_PROXY != "" ]] && echo -e nameserver 2a01:4f8:c2c:123f::1 >/etc/resolv.conf + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" +res=$(which bt 2>/dev/null) +[[ "$res" != "" ]] && BT="true" && NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" + +# 以下网站是随机从Google上找到的无广告小说网站,不喜欢请改成其他网址,以http或https开头 +# 搭建好后无法打开伪装域名,可能是反代小说网站挂了,请在网站留言,或者Github发issue,以便替换新的网站 +SITES=( + http://www.zhuizishu.com/ + http://xs.56dyc.com/ + http://www.ddxsku.com/ + http://www.biqu6.com/ + https://www.wenshulou.cc/ + http://www.55shuba.com/ + http://www.39shubao.com/ + https://www.23xsw.cc/ + https://www.jueshitangmen.info/ + https://www.zhetian.org/ + http://www.bequgexs.com/ + http://www.tjwl.com/ +) + +CONFIG_FILE=/usr/local/etc/trojan/config.json + +colorEcho() { + echo -e "${1}${@:2}${PLAIN}" +} + +function checkSystem() { + result=$(id | awk '{print $1}') + [[ $EUID -ne 0 ]] && colorEcho $RED " 请以root身份执行该脚本" && exit 1 + res=$(which yum 2>/dev/null) + if [ "$?" != "0" ]; then + res=$(which apt 2>/dev/null) + if [ "$?" != "0" ]; then + colorEcho $RED " 不受支持的Linux系统" + exit 1 + fi + PMT=apt + CMD_INSTALL="apt install -y " + CMD_REMOVE="apt remove -y " + CMD_UPGRADE="apt update; apt upgrade -y; apt autoremove -y" + else + PMT=yum + CMD_INSTALL="yum install -y " + CMD_REMOVE="yum remove -y " + CMD_UPGRADE="yum update -y" + fi + res=$(which systemctl 2>/dev/null) + if [ "$?" != "0" ]; then + colorEcho $RED " 系统版本过低,请升级到最新版本" + exit 1 + fi +} + +status() { + if [[ ! -f /usr/local/bin/trojan ]]; then + echo 0 + return + fi + + if [[ ! -f $CONFIG_FILE ]]; then + echo 1 + return + fi + port=$(grep local_port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + res=$(ss -ntlp | grep ${port} | grep trojan) + if [[ -z "$res" ]]; then + echo 2 + else + echo 3 + fi +} + +statusText() { + res=$(status) + case $res in + 2) + echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN} + ;; + 3) + echo -e ${GREEN}已安装${PLAIN} ${GREEN}正在运行${PLAIN} + ;; + *) + echo -e ${RED}未安装${PLAIN} + ;; + esac +} + +function getData() { + echo " " + echo " 本脚本为trojan一键脚本,运行之前请确认如下条件已经具备:" + echo -e " ${RED}1. 一个伪装域名${PLAIN}" + echo -e " ${RED}2. 伪装域名DNS解析指向当前服务器ip(${IP})${PLAIN}" + echo -e " 3. 如果/root目录下有 ${GREEN}trojan.pem${PLAIN} 和 ${GREEN}trojan.key${PLAIN} 证书密钥文件,无需理会条件2" + echo " " + read -p " 确认满足按y,按其他退出脚本:" answer + if [ "${answer}" != "y" ] && [ "${answer}" != "Y" ]; then + exit 1 + fi + + echo "" + while true; do + read -p " 请输入伪装域名:" DOMAIN + if [ -z "${DOMAIN}" ]; then + echo " 域名输入错误,请重新输入!" + else + break + fi + done + DOMAIN=${DOMAIN,,} + colorEcho $BLUE " 伪装域名(host): $DOMAIN" + + echo "" + if [[ -f ~/trojan.pem && -f ~/trojan.key ]]; then + echo -e "${GREEN} 检测到自有证书,将使用其部署${PLAIN}" + echo + CERT_FILE="/usr/local/etc/trojan/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/trojan/${DOMAIN}.key" + else + resolve=$(curl -sm8 ipget.net/?ip=${DOMAIN}) + res=$(echo -n ${resolve} | grep ${IP}) + if [[ -z "${res}" ]]; then + echo " ${DOMAIN} 解析结果:${resolve}" + echo -e " ${RED}域名未解析到当前服务器IP(${IP})!${PLAIN}" + exit 1 + fi + fi + + echo "" + read -p " 请设置trojan密码(不输入则随机生成):" PASSWORD + [ -z "$PASSWORD" ] && PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) + colorEcho $BLUE " 密码: " $PASSWORD + + echo "" + read -p " 请输入trojan端口[100-65535的一个数字,默认443]:" PORT + [ -z "${PORT}" ] && PORT=443 + if [ "${PORT:0:1}" = "0" ]; then + echo -e " ${RED}端口不能以0开头${PLAIN}" + exit 1 + fi + colorEcho $BLUE " trojan端口: " $PORT + + echo "" + colorEcho $BLUE " 请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 美女站(https://imeizi.me)" + echo " 4) 高清壁纸站(https://bing.imeizi.me)" + echo " 5) 自定义反代站点(需以http或者https开头)" + read -p " 请选择伪装网站类型[默认:高清壁纸站]" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.imeizi.me" + else + case $answer in + 1) + PROXY_URL="" + ;; + 2) + len=${#SITES[@]} + ((len--)) + index=$(shuf -i0-${len} -n1) + PROXY_URL=${SITES[$index]} + ;; + 3) + PROXY_URL="https://imeizi.me" + ;; + 4) + PROXY_URL="https://bing.imeizi.me" + ;; + 5) + read -p " 请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + colorEcho $RED " 请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + colorEcho $RED " 反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) + colorEcho $RED " 请输入正确的选项!" + exit 1 + ;; + esac + fi + REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3) + echo "" + colorEcho $BLUE " 伪装域名:$PROXY_URL" + + echo "" + colorEcho $BLUE " 是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p " 请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" == "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + echo "" + colorEcho $BLUE " 允许搜索引擎:$ALLOW_SPIDER" + + 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" +} + +function preinstall() { + $PMT clean all + [[ "$PMT" == "apt" ]] && $PMT update + #colorEcho $BLUE " 更新系统..." + #echo $CMD_UPGRADE | bash + + colorEcho $BLUE " 安装必要软件" + if [[ "$PMT" == "yum" ]]; then + $CMD_INSTALL epel-release + fi + $CMD_INSTALL wget vim unzip tar gcc openssl + $CMD_INSTALL net-tools + if [[ "$PMT" == "apt" ]]; then + $CMD_INSTALL libssl-dev g++ + fi + + 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 +} + +function installTrojan() { + colorEcho $BLUE " 安装最新版trojan..." + rm -rf $CONFIG_FILE + rm -rf /etc/systemd/system/trojan.service + NAME=trojan + VERSION=$(curl -sm8 https://api.github.com/repos/trojan-gfw/trojan/releases/latest | grep tag_name | sed -E 's/.*"v(.*)".*/\1/') + TARBALL="$NAME-$VERSION-linux-amd64.tar.xz" + DOWNLOADURL="${V6_PROXY}https://github.com/trojan-gfw/$NAME/releases/download/v$VERSION/$TARBALL" + TMPDIR="$(mktemp -d)" + INSTALLPREFIX=/usr/local + SYSTEMDPREFIX=/etc/systemd/system + + BINARYPATH="$INSTALLPREFIX/bin/$NAME" + CONFIGPATH="$INSTALLPREFIX/etc/$NAME/config.json" + SYSTEMDPATH="$SYSTEMDPREFIX/$NAME.service" + + echo Entering temp directory $TMPDIR... + cd "$TMPDIR" + + echo Downloading $NAME $VERSION... + curl -LO --progress-bar "$DOWNLOADURL" || wget -q --show-progress "$DOWNLOADURL" + + echo Unpacking $NAME $VERSION... + tar xf "$TARBALL" + cd "$NAME" + + echo Installing $NAME $VERSION to $BINARYPATH... + cp "$NAME" "$BINARYPATH" + chmod 755 "$BINARYPATH" + + mkdir -p $INSTALLPREFIX/etc/$NAME + + echo Installing $NAME systemd service to $SYSTEMDPATH... + cat >"$SYSTEMDPATH" <$CONFIG_FILE <<-EOF + { + "run_type": "server", + "local_addr": "::", + "local_port": ${PORT}, + "remote_addr": "127.0.0.1", + "remote_port": 80, + "password": [ + "$PASSWORD" + ], + "log_level": 1, + "ssl": { + "cert": "$CERT_FILE", + "key": "$KEY_FILE", + "key_password": "", + "sni": "$DOMAIN", + "cipher": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384", + "cipher_tls13": "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384", + "prefer_server_cipher": true, + "alpn": [ + "http/1.1", "h2" + ], + "alpn_port_override": { + "h2": 81 + }, + "reuse_session": true, + "session_ticket": false, + "session_timeout": 600, + "plain_http_response": "", + "curves": "", + "dhparam": "" + }, + "tcp": { + "prefer_ipv4": false, + "no_delay": true, + "keep_alive": true, + "reuse_port": false, + "fast_open": false, + "fast_open_qlen": 20 + }, + "mysql": { + "enabled": false, + "server_addr": "127.0.0.1", + "server_port": 3306, + "database": "trojan", + "username": "trojan", + "password": "", + "key": "", + "cert": "", + "ca": "" + } + } + EOF +} + +getCert() { + mkdir -p /usr/local/etc/trojan + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + 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 + curl -sL https://get.acme.sh | sh -s email=hijk.pw@protonmail.ch + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [[ "$BT" == "false" ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + colorEcho $RED " 获取证书失败,请复制上面的红色文字到 https://hijk.art 反馈" + exit 1 + } + CERT_FILE="/usr/local/etc/trojan/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/trojan/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + colorEcho $RED " 获取证书失败,请到 https://hijk.art 反馈" + exit 1 + } + else + cp ~/trojan.pem /usr/local/etc/trojan/${DOMAIN}.pem + cp ~/trojan.key /usr/local/etc/trojan/${DOMAIN}.key + fi +} + +function installNginx() { + colorEcho $BLUE " 安装nginx..." + if [[ "$BT" == "false" ]]; then + if [[ "$PMT" == "yum" ]]; then + $CMD_INSTALL epel-release + if [[ "$?" != "0" ]]; then + echo '[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' >/etc/yum.repos.d/nginx.repo + fi + fi + $CMD_INSTALL nginx + if [[ "$?" != "0" ]]; then + colorEcho $RED " Nginx安装失败,请到 https://hijk.art 反馈" + exit 1 + fi + systemctl enable nginx + else + res=$(which nginx 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" == "n" ]]; then + echo 'User-Agent: *' >/usr/share/nginx/html/robots.txt + echo 'Disallow: /' >>/usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + + if [[ "$BT" == "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + + 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 + fi + + mkdir -p $NGINX_CONF_PATH + if [[ "$PROXY_URL" == "" ]]; then + cat >$NGINX_CONF_PATH${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + + $ROBOT_CONFIG + } + EOF + else + cat >$NGINX_CONF_PATH${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + 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; + } + + $ROBOT_CONFIG + } + EOF + fi +} + +startNginx() { + if [[ "$BT" == "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" == "false" ]]; then + systemctl stop nginx + else + res=$(ps aux | grep -i nginx) + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +function setFirewall() { + 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 + 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 + 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 + 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 + fi + fi + fi + fi + fi +} + +function installBBR() { + if [ "$NEED_BBR" != "y" ]; then + INSTALL_BBR=false + return + fi + + result=$(lsmod | grep bbr) + if [ "$result" != "" ]; then + colorEcho $YELLOW " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=$(hostnamectl | grep -i openvz) + if [ "$res" != "" ]; then + colorEcho $YELLOW " openvz机器,跳过安装" + INSTALL_BBR=false + return + fi + + echo "net.core.default_qdisc=fq" >>/etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $GREEN " BBR模块已启用" + INSTALL_BBR=false + return + fi + + colorEcho $BLUE " 安装BBR模块..." + if [[ "$PMT" == "yum" ]]; then + if [[ "$V6_PROXY" == "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + $CMD_INSTALL --enablerepo=elrepo-kernel kernel-ml + $CMD_REMOVE kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + $CMD_INSTALL --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +function showInfo() { + res=$(netstat -nltp | grep trojan) + [[ -z "$res" ]] && status="${RED}已停止${PLAIN}" || status="${GREEN}正在运行${PLAIN}" + + domain=$(grep sni $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep -m1 cert $CONFIG_FILE | cut -d/ -f5) + fi + port=$(grep local_port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + line1=$(grep -n 'password' $CONFIG_FILE | head -n1 | cut -d: -f1) + line11=$(expr $line1 + 1) + password=$(sed -n "${line11}p" $CONFIG_FILE | tr -d \",' ') + + res=$(netstat -nltp | grep ${port} | grep nginx) + [[ -z "$res" ]] && ngstatus="${RED}已停止${PLAIN}" || ngstatus="${GREEN}正在运行${PLAIN}" + + echo ============================================ + echo -e " ${BLUE}trojan运行状态:${PLAIN}${status}" + echo "" + echo -e " ${BLUE}trojan配置文件:${PLAIN}${RED}$CONFIG_FILE${PLAIN}" + echo -e " ${BLUE}trojan配置信息:${PLAIN} " + echo -e " ${BLUE}IP/address:${PLAIN} ${RED}$IP${PLAIN}" + echo -e " ${BLUE}域名/SNI/peer名称:${PLAIN} ${RED}${domain}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}密码(password):${PLAIN}${RED}$password${PLAIN}" + echo + echo ============================================ +} + +function bbrReboot() { + if [ "${INSTALL_BBR}" == "true" ]; then + echo "" + colorEcho $BLUE " 为使BBR模块生效,系统将在30秒后重启" + echo + echo -e " 您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +function install() { + getData + preinstall + installBBR + setFirewall + installNginx + getCert + configNginx + installTrojan + configTrojan + + start + showInfo + bbrReboot +} + +reconfig() { + res=$(status) + if [[ $res -lt 2 ]]; then + echo -e " ${RED}trojan未安装,请先安装!${PLAIN}" + return + fi + + getData + setFirewall + getCert + configNginx + configTrojan + restart + showInfo +} + +update() { + res=$(status) + if [[ $res -lt 2 ]]; then + echo -e " ${RED}trojan未安装,请先安装!${PLAIN}" + return + fi + + installTrojan + + stop + start + colorEcho $BLUE " 成功更新到最新版trojan" +} + +start() { + res=$(status) + if [[ $res -lt 2 ]]; then + echo -e "${RED}trojan未安装,请先安装!${PLAIN}" + return + fi + stopNginx + startNginx + systemctl restart trojan + sleep 2 + port=$(grep local_port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + res=$(ss -ntlp | grep ${port} | grep trojan) + if [[ "$res" == "" ]]; then + colorEcho $RED " trojan启动失败,请检查端口是否被占用!" + else + colorEcho $BLUE " trojan启动成功" + fi +} + +stop() { + stopNginx + systemctl stop trojan + colorEcho $BLUE " trojan停止成功" +} + +restart() { + res=$(status) + if [[ $res -lt 2 ]]; then + echo -e " ${RED}trojan未安装,请先安装!${PLAIN}" + return + fi + + stop + start +} + +showLog() { + res=$(status) + if [[ $res -lt 2 ]]; then + echo -e "${RED}trojan未安装,请先安装!${PLAIN}" + return + fi + + journalctl -xen -u trojan --no-pager +} + +function uninstall() { + res=$(status) + if [[ $res -lt 2 ]]; then + echo -e "${RED}trojan未安装,请先安装!${PLAIN}" + return + fi + + echo "" + read -p " 确定卸载trojan?(y/n)" answer + [[ -z ${answer} ]] && answer="n" + + if [[ "${answer}" == "y" ]] || [[ "${answer}" == "Y" ]]; then + domain=$(grep sni $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep -m1 cert $CONFIG_FILE | cut -d/ -f5) + fi + + systemctl stop trojan + systemctl disable trojan + rm -rf /usr/local/bin/trojan + rm -rf /usr/local/etc/trojan + rm -rf /etc/systemd/system/trojan.service + + if [[ "$BT" == "false" ]]; then + $CMD_REMOVE nginx + if [[ "$PMT" == "apt" ]]; then + $CMD_REMOVE nginx-common + fi + if [[ -d /usr/share/nginx/html.bak ]]; then + rm -rf /usr/share/nginx/html + mv /usr/share/nginx/html.bak /usr/share/nginx/html + fi + fi + rm -rf $NGINX_CONF_PATH${domain}.conf + ~/.acme.sh/acme.sh --uninstall + colorEcho $GREEN " trojan卸载成功" + fi +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}trojan一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) & MisakaNo #" + echo -e "# ${GREEN}博客${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo "" + + echo -e " ${GREEN}1.${PLAIN} 安装trojan" + echo -e " ${GREEN}2.${PLAIN} 更新trojan" + echo -e " ${GREEN}3. ${RED}卸载trojan${PLAIN}" + echo " -------------" + echo -e " ${GREEN}4.${PLAIN} 启动trojan" + echo -e " ${GREEN}5.${PLAIN} 重启trojan" + echo -e " ${GREEN}6.${PLAIN} 停止trojan" + echo " -------------" + echo -e " ${GREEN}7.${PLAIN} 查看trojan配置" + echo -e " ${GREEN}8. ${RED}修改trojan配置${PLAIN}" + echo -e " ${GREEN}9.${PLAIN} 查看trojan日志" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo + echo -n " 当前状态:" + statusText + echo + + read -p " 请选择操作[0-10]:" answer + case $answer in + 0) + exit 1 + ;; + 1) + install + ;; + 2) + update + ;; + 3) + uninstall + ;; + 4) + start + ;; + 5) + restart + ;; + 6) + stop + ;; + 7) + showInfo + ;; + 8) + reconfig + ;; + 9) + showLog + ;; + *) + echo -e "$RED 请选择正确的操作!${PLAIN}" + exit 1 + ;; + esac +} + +checkSystem + +action=$1 +[[ -z $1 ]] && action=menu +case "$action" in + menu | install | update | uninstall | start | restart | stop | showInfo | showLog) + ${action} + ;; + *) + echo " 参数错误" + echo " 用法: $(basename $0) [menu|install|update|uninstall|start|restart|stop|showInfo|showLog]" + ;; +esac \ No newline at end of file diff --git a/v2ray1.sh b/v2ray1.sh new file mode 100644 index 00000000..e736a1bd --- /dev/null +++ b/v2ray1.sh @@ -0,0 +1,1860 @@ +#!/bin/bash + +RED="\033[31m" # Error message +GREEN="\033[32m" # Success message +YELLOW="\033[33m" # Warning message +BLUE="\033[36m" # Info message +PLAIN='\033[0m' + +# 以下网站是随机从Google上找到的无广告小说网站,不喜欢请改成其他网址,以http或https开头 +# 搭建好后无法打开伪装域名,可能是反代小说网站挂了,请在网站留言,或者Github发issue,以便替换新的网站 +SITES=( + http://www.zhuizishu.com/ + http://xs.56dyc.com/ + http://www.ddxsku.com/ + http://www.biqu6.com/ + https://www.wenshulou.cc/ + http://www.55shuba.com/ + http://www.39shubao.com/ + https://www.23xsw.cc/ + https://www.huanbige.com/ + https://www.jueshitangmen.info/ + https://www.zhetian.org/ + http://www.bequgexs.com/ + http://www.tjwl.com/ +) + +CONFIG_FILE="/etc/v2ray/config.json" +SERVICE_FILE="/etc/systemd/system/v2ray.service" +OS=$(hostnamectl | grep -i system | cut -d: -f2) + +checkwarp(){ + [[ -n $(wg 2>/dev/null) ]] && colorEcho $RED " 检测到WARP已打开,脚本中断运行" && colorEcho $YELLOW " 请关闭WARP之后再运行本脚本" && exit 1 +} + +V6_PROXY="" +IP=$(curl -s4m8 ip.gs) +[[ "$?" != "0" ]] && IP=$(curl -s6m8 ip.gs) && V6_PROXY="https://gh-proxy-misakano7545.koyeb.app/" + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" +res=$(which bt 2>/dev/null) +[[ "$res" != "" ]] && BT="true" && NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" + +VLESS="false" +TROJAN="false" +TLS="false" +WS="false" +XTLS="false" +KCP="false" + +checkSystem() { + result=$(id | awk '{print $1}') + [[ $EUID -ne 0 ]] && colorEcho $RED " 请以root身份执行该脚本" && exit 1 + + res=$(which yum 2>/dev/null) + if [[ "$?" != "0" ]]; then + res=$(which apt 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 不受支持的Linux系统" + exit 1 + fi + PMT="apt" + CMD_INSTALL="apt install -y " + CMD_REMOVE="apt remove -y " + CMD_UPGRADE="apt update; apt upgrade -y; apt autoremove -y" + else + PMT="yum" + CMD_INSTALL="yum install -y " + CMD_REMOVE="yum remove -y " + CMD_UPGRADE="yum update -y" + fi + res=$(which systemctl 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 系统版本过低,请升级到最新版本" + exit 1 + fi +} + +colorEcho() { + echo -e "${1}${@:2}${PLAIN}" +} + +configNeedNginx() { + local ws=$(grep wsSettings $CONFIG_FILE) + if [[ -z "$ws" ]]; then + echo no + return + fi + echo yes +} + +needNginx() { + if [[ "$WS" == "false" ]]; then + echo no + return + fi + echo yes +} + +status() { + if [[ ! -f /usr/bin/v2ray/v2ray ]]; then + echo 0 + return + fi + if [[ ! -f $CONFIG_FILE ]]; then + echo 1 + return + fi + port=$(grep port $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 [[ $(configNeedNginx) != "yes" ]]; then + echo 3 + else + res=$(ss -nutlp | grep -i nginx) + if [[ -z "$res" ]]; then + echo 4 + else + echo 5 + fi + fi +} + +statusText() { + res=$(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 +} + +normalizeVersion() { + if [ -n "$1" ]; then + case "$1" in + v*) + echo "$1" + ;; + *) + echo "v$1" + ;; + esac + else + echo "" + fi +} + +# 1: new V2Ray. 0: no. 1: yes. 2: not installed. 3: check failed. +getVersion() { + VER="$(/usr/bin/v2ray/v2ray -version 2>/dev/null)" + RETVAL=$? + CUR_VER="$(normalizeVersion "$(echo "$VER" | head -n 1 | cut -d " " -f2)")" + 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)")" + if [[ "$XTLS" == "true" ]]; then + NEW_VER=v4.32.1 + 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' ;; + armv5tel) echo 'arm32-v5' ;; + armv6l) echo 'arm32-v6' ;; + armv7 | armv7l) echo 'arm32-v7a' ;; + armv8 | aarch64) echo 'arm64-v8a' ;; + mips64le) echo 'mips64le' ;; + mips64) echo 'mips64' ;; + mipsle) echo 'mips32le' ;; + mips) echo 'mips32' ;; + ppc64le) echo 'ppc64le' ;; + ppc64) echo 'ppc64' ;; + ppc64le) echo 'ppc64le' ;; + riscv64) echo 'riscv64' ;; + s390x) echo 's390x' ;; + *) colorEcho $RED " 不支持的CPU架构!" && exit 1;; + esac + + return 0 +} + +getData() { + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + echo " V2ray一键脚本,运行之前请确认如下条件已经具备:" + colorEcho ${YELLOW} " 1. 一个伪装域名" + colorEcho ${YELLOW} " 2. 伪装域名DNS解析指向当前服务器ip(${IP})" + colorEcho ${BLUE} " 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 + resolve=$(curl -sm8 https://ipget.net/?ip=${DOMAIN}) + res=$(echo -n ${resolve} | grep ${IP}) + if [[ -z "${res}" ]]; then + colorEcho ${BLUE} "${DOMAIN} 解析结果:${resolve}" + colorEcho ${RED} " 域名未解析到当前服务器IP(${IP})!" + exit 1 + fi + fi + fi + + echo "" + if [[ "$(needNginx)" == "no" ]]; then + if [[ "$TLS" == "true" ]]; then + read -p " 请输入v2ray监听端口[强烈建议443,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + else + read -p " 请输入v2ray监听端口[100-65535的一个数字]:" PORT + [[ -z "${PORT}" ]] && PORT=$(shuf -i200-65000 -n1) + if [[ "${PORT:0:1}" == "0" ]]; then + colorEcho ${RED} " 端口不能以0开头" + exit 1 + fi + fi + colorEcho ${BLUE} " v2ray端口:$PORT" + else + read -p " 请输入Nginx监听端口[100-65535的一个数字,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + if [ "${PORT:0:1}" = "0" ]; then + colorEcho ${BLUE} " 端口不能以0开头" + exit 1 + fi + colorEcho ${BLUE} " Nginx端口:$PORT" + V2PORT=$(shuf -i10000-65000 -n1) + fi + + if [[ "$KCP" == "true" ]]; then + echo "" + colorEcho $BLUE " 请选择伪装类型:" + echo " 1) 无" + echo " 2) BT下载" + echo " 3) 视频通话" + echo " 4) 微信视频通话" + echo " 5) dtls" + echo " 6) wiregard" + read -p " 请选择伪装类型[默认:无]:" answer + case $answer in + 2) + HEADER_TYPE="utp" + ;; + 3) + HEADER_TYPE="srtp" + ;; + 4) + HEADER_TYPE="wechat-video" + ;; + 5) + HEADER_TYPE="dtls" + ;; + 6) + HEADER_TYPE="wireguard" + ;; + *) + HEADER_TYPE="none" + ;; + esac + colorEcho $BLUE " 伪装类型:$HEADER_TYPE" + SEED=$(cat /proc/sys/kernel/random/uuid) + fi + + if [[ "$TROJAN" == "true" ]]; then + echo "" + read -p " 请设置trojan密码(不输则随机生成):" PASSWORD + [[ -z "$PASSWORD" ]] && PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) + colorEcho $BLUE " trojan密码:$PASSWORD" + fi + + 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" + ;; + esac + colorEcho $BLUE " 流控模式:$FLOW" + fi + + if [[ "${WS}" == "true" ]]; then + echo "" + while true; do + read -p " 请输入伪装路径,以/开头(不懂请直接回车):" WSPATH + if [[ -z "${WSPATH}" ]]; then + len=$(shuf -i5-12 -n1) + ws=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1) + WSPATH="/$ws" + break + elif [[ "${WSPATH:0:1}" != "/" ]]; then + colorEcho ${RED} " 伪装路径必须以/开头!" + elif [[ "${WSPATH}" == "/" ]]; then + colorEcho ${RED} " 不能使用根路径!" + else + break + fi + done + colorEcho ${BLUE} " ws路径:$WSPATH" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + colorEcho $BLUE " 请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 高清壁纸站(https://bing.ioliu.cn)" + echo " 4) 自定义反代站点(需以http或者https开头)" + read -p " 请选择伪装网站类型[默认:高清壁纸站]" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.ioliu.cn" + else + case $answer in + 1) PROXY_URL="" ;; + 2) + 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 + ;; + 3) PROXY_URL="https://bing.ioliu.cn" ;; + 4) + read -p " 请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + colorEcho $RED " 请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + colorEcho $RED " 反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) colorEcho $RED " 请输入正确的选项!" && exit 1 ;; + esac + fi + REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3) + colorEcho $BLUE " 伪装网站:$PROXY_URL" + + echo "" + colorEcho $BLUE " 是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p " 请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" == "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + colorEcho $BLUE " 允许搜索引擎:$ALLOW_SPIDER" + fi + + 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" +} + +installNginx() { + echo "" + colorEcho $BLUE " 安装nginx..." + if [[ "$BT" == "false" ]]; then + if [[ "$PMT" == "yum" ]]; then + $CMD_INSTALL epel-release + if [[ "$?" != "0" ]]; then + echo '[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' >/etc/yum.repos.d/nginx.repo + fi + fi + $CMD_INSTALL nginx + if [[ "$?" != "0" ]]; then + colorEcho $RED " Nginx安装失败,请到 https://hijk.art 反馈" + exit 1 + fi + systemctl enable nginx + else + res=$(which nginx 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +startNginx() { + if [[ "$BT" == "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" == "false" ]]; then + systemctl stop nginx + else + res=$(ps aux | grep -i nginx) + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +getCert() { + mkdir -p /etc/v2ray + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + sleep 2 + 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 + curl -sL https://get.acme.sh | sh -s email=hijk.pw@protonmail.ch + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [[ "$BT" == "false" ]]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + colorEcho $RED " 获取证书失败,请复制上面的红色文字到 https://hijk.art 反馈" + exit 1 + } + CERT_FILE="/etc/v2ray/${DOMAIN}.pem" + KEY_FILE="/etc/v2ray/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + colorEcho $RED " 获取证书失败,请到 https://hijk.art 反馈" + exit 1 + } + else + cp ~/v2ray.pem /etc/v2ray/${DOMAIN}.pem + cp ~/v2ray.key /etc/v2ray/${DOMAIN}.key + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" == "n" ]]; then + echo 'User-Agent: *' >/usr/share/nginx/html/robots.txt + echo 'Disallow: /' >>/usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + + if [[ "$BT" == "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + 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 + fi + + if [[ "$PROXY_URL" == "" ]]; then + action="" + else + action="proxy_ssl_server_name on; + proxy_pass $PROXY_URL; + proxy_set_header Accept-Encoding ''; + sub_filter \"$REMOTE_HOST\" \"$DOMAIN\"; + sub_filter_once off;" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + mkdir -p $NGINX_CONF_PATH + # VMESS+WS+TLS + # VLESS+WS+TLS + if [[ "$WS" == "true" ]]; then + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + return 301 https://\$server_name:${PORT}\$request_uri; + } + + server { + listen ${PORT} ssl http2; + listen [::]:${PORT} ssl http2; + server_name ${DOMAIN}; + charset utf-8; + + # ssl配置 + ssl_protocols TLSv1.1 TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + ssl_ecdh_curve secp384r1; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + ssl_certificate $CERT_FILE; + ssl_certificate_key $KEY_FILE; + + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + + location ${WSPATH} { + proxy_redirect off; + proxy_pass http://127.0.0.1:${V2PORT}; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + # Show real IP in v2ray access.log + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } + } + EOF + else + # VLESS+TCP+TLS + # VLESS+TCP+XTLS + # trojan + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + } + EOF + fi + fi +} + +setSelinux() { + 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 +} + +setFirewall() { + 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 +} + +installBBR() { + if [[ "$NEED_BBR" != "y" ]]; then + INSTALL_BBR=false + return + fi + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $BLUE " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=$(hostnamectl | grep -i openvz) + if [[ "$res" != "" ]]; then + colorEcho $BLUE " openvz机器,跳过安装" + INSTALL_BBR=false + return + fi + + echo "net.core.default_qdisc=fq" >>/etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $GREEN " BBR模块已启用" + INSTALL_BBR=false + return + fi + + colorEcho $BLUE " 安装BBR模块..." + if [[ "$PMT" == "yum" ]]; then + if [[ "$V6_PROXY" == "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + $CMD_INSTALL --enablerepo=elrepo-kernel kernel-ml + $CMD_REMOVE kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + $CMD_INSTALL --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +installV2ray() { + rm -rf /tmp/v2ray + mkdir -p /tmp/v2ray + DOWNLOAD_LINK="${V6_PROXY}https://github.com/v2fly/v2ray-core/releases/download/${NEW_VER}/v2ray-linux-$(archAffix).zip" + colorEcho $BLUE " 下载V2Ray: ${DOWNLOAD_LINK}" + curl -L -H "Cache-Control: no-cache" -o /tmp/v2ray/v2ray.zip ${DOWNLOAD_LINK} + if [ $? != 0 ]; then + colorEcho $RED " 下载V2ray文件失败,请检查服务器网络设置" + exit 1 + fi + mkdir -p '/etc/v2ray' '/var/log/v2ray' && \ + unzip /tmp/v2ray/v2ray.zip -d /tmp/v2ray + mkdir -p /usr/bin/v2ray + cp /tmp/v2ray/v2ctl /usr/bin/v2ray/ + cp /tmp/v2ray/v2ray /usr/bin/v2ray/ + cp /tmp/v2ray/geo* /usr/bin/v2ray/ + chmod +x '/usr/bin/v2ray/v2ray' '/usr/bin/v2ray/v2ctl' || { + colorEcho $RED " V2ray安装失败" + exit 1 + } + + cat >$SERVICE_FILE <<-EOF + [Unit] + Description=V2ray Service + Documentation=https://hijk.art + 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 -config /etc/v2ray/config.json + Restart=on-failure + + [Install] + WantedBy=multi-user.target + EOF + systemctl daemon-reload + systemctl enable v2ray.service +} + +trojanConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +trojanXTLSConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +vmessConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + local alterid=$(shuf -i50-80 -n1) + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": $alterid + } + ] + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + local alterid=$(shuf -i50-80 -n1) + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": $alterid + } + ] + }, + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "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 +} + +vmessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $V2PORT, + "listen": "127.0.0.1", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessXTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "flow": "$FLOW", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $V2PORT, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +configV2ray() { + mkdir -p /etc/v2ray + if [[ "$TROJAN" == "true" ]]; then + if [[ "$XTLS" == "true" ]]; then + trojanXTLSConfig + else + trojanConfig + fi + return 0 + fi + if [[ "$VLESS" == "false" ]]; then + # VMESS + kcp + if [[ "$KCP" == "true" ]]; then + vmessKCPConfig + return 0 + fi + # VMESS + if [[ "$TLS" == "false" ]]; then + vmessConfig + elif [[ "$WS" == "false" ]]; then + # VMESS+TCP+TLS + vmessTLSConfig + # VMESS+WS+TLS + else + vmessWSConfig + fi + #VLESS + else + if [[ "$KCP" == "true" ]]; then + vlessKCPConfig + return 0 + fi + # VLESS+TCP + if [[ "$WS" == "false" ]]; then + # VLESS+TCP+TLS + if [[ "$XTLS" == "false" ]]; then + vlessTLSConfig + # VLESS+TCP+XTLS + else + vlessXTLSConfig + fi + # VLESS+WS+TLS + else + vlessWSConfig + fi + fi +} + +install() { + getData + + $PMT clean all + [[ "$PMT" == "apt" ]] && $PMT update + #echo $CMD_UPGRADE | bash + $CMD_INSTALL wget vim unzip tar gcc openssl + $CMD_INSTALL net-tools + if [[ "$PMT" == "apt" ]]; then + $CMD_INSTALL libssl-dev g++ + fi + res=$(which unzip 2>/dev/null) + if [[ $? -ne 0 ]]; then + colorEcho $RED " unzip安装失败,请检查网络" + exit 1 + fi + + installNginx + setFirewall + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + getCert + fi + configNginx + + colorEcho $BLUE " 安装V2ray..." + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + colorEcho $BLUE " V2ray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + colorEcho $BLUE " 安装V2Ray ${NEW_VER} ,架构$(archAffix)" + installV2ray + fi + + configV2ray + + setSelinux + installBBR + + start + showInfo + + bbrReboot +} + +bbrReboot() { + if [[ "${INSTALL_BBR}" == "true" ]]; then + echo + echo " 为使BBR模块生效,系统将在30秒后重启" + echo + echo -e " 您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +update() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " V2ray未安装,请先安装!" + return + fi + + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + colorEcho $BLUE " V2ray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + colorEcho $BLUE " 安装V2Ray ${NEW_VER} ,架构$(archAffix)" + installV2ray + stop + start + colorEcho $GREEN " 最新版V2ray安装成功!" + fi +} + +uninstall() { + res=$(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 $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep serverName $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 + + if [[ "$BT" == "false" ]]; then + 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 + fi + if [[ "$domain" != "" ]]; then + rm -rf $NGINX_CONF_PATH${domain}.conf + fi + [[ -f ~/.acme.sh/acme.sh ]] && ~/.acme.sh/acme.sh --uninstall + colorEcho $GREEN " V2ray卸载成功" + fi +} + +start() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " V2ray未安装,请先安装!" + return + fi + stopNginx + startNginx + systemctl restart v2ray + sleep 2 + port=$(grep port $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 +} + +stop() { + stopNginx + systemctl stop v2ray + colorEcho $BLUE " V2ray停止成功" +} + +restart() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " V2ray未安装,请先安装!" + return + fi + + stop + start +} + +getConfigFileInfo() { + vless="false" + tls="false" + ws="false" + xtls="false" + trojan="false" + protocol="VMess" + kcp="false" + + uid=$(grep id $CONFIG_FILE | head -n1 | cut -d: -f2 | tr -d \",' ') + alterid=$(grep alterId $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + network=$(grep network $CONFIG_FILE | tail -n1 | cut -d: -f2 | tr -d \",' ') + [[ -z "$network" ]] && network="tcp" + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" != "" ]]; then + ws="true" + tls="true" + wspath=$(grep path $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + else + tls="true" + fi + if [[ "$ws" == "true" ]]; then + port=$(grep -i ssl $NGINX_CONF_PATH${domain}.conf | head -n1 | awk '{print $2}') + else + port=$(grep port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + res=$(grep -i kcp $CONFIG_FILE) + if [[ "$res" != "" ]]; then + kcp="true" + type=$(grep header -A 3 $CONFIG_FILE | grep 'type' | cut -d: -f2 | tr -d \",' ') + seed=$(grep seed $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + + vmess=$(grep vmess $CONFIG_FILE) + if [[ "$vmess" == "" ]]; then + trojan=$(grep trojan $CONFIG_FILE) + if [[ "$trojan" == "" ]]; then + vless="true" + protocol="VLESS" + else + trojan="true" + password=$(grep password $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + protocol="trojan" + fi + tls="true" + encryption="none" + xtls=$(grep xtlsSettings $CONFIG_FILE) + if [[ "$xtls" != "" ]]; then + xtls="true" + flow=$(grep flow $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + else + flow="无" + fi + fi +} + +outputVmess() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"tcp\", + \"type\":\"none\", + \"host\":\"\", + \"path\":\"\", + \"tls\":\"\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +outputVmessKCP() { + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" +} + +outputTrojan() { + 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}none${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 +} + +outputVmessTLS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo + echo -e " ${BLUE}vmess链接: ${PLAIN}$RED$link$PLAIN" +} + +outputVmessWS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"${wspath}\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +showInfo() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " V2ray未安装,请先安装!" + return + fi + + echo "" + echo -n -e " ${BLUE}V2ray运行状态:${PLAIN}" + statusText + echo -e " ${BLUE}V2ray配置文件: ${PLAIN} ${RED}${CONFIG_FILE}${PLAIN}" + colorEcho $BLUE " V2ray配置信息:" + + getConfigFileInfo + + echo -e " ${BLUE}协议: ${PLAIN} ${RED}${protocol}${PLAIN}" + if [[ "$trojan" == "true" ]]; then + outputTrojan + return 0 + fi + if [[ "$vless" == "false" ]]; then + if [[ "$kcp" == "true" ]]; then + outputVmessKCP + return 0 + fi + if [[ "$tls" == "false" ]]; then + outputVmess + elif [[ "$ws" == "false" ]]; then + outputVmessTLS + else + outputVmessWS + fi + else + if [[ "$kcp" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" + return 0 + fi + if [[ "$xtls" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + elif [[ "$ws" == "false" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN}${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + else + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + fi + fi +} + +showLog() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " V2ray未安装,请先安装!" + return + fi + + journalctl -xen -u v2ray --no-pager +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}v2ray一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) & MisakaNo #" + echo -e "# ${GREEN}博客${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + + echo -e " ${GREEN}1.${PLAIN} 安装V2ray-VMESS" + echo -e " ${GREEN}2.${PLAIN} 安装V2ray-${BLUE}VMESS+mKCP${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装V2ray-VMESS+TCP+TLS" + echo -e " ${GREEN}4.${PLAIN} 安装V2ray-${BLUE}VMESS+WS+TLS${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}5.${PLAIN} 安装V2ray-${BLUE}VLESS+mKCP${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 安装V2ray-VLESS+TCP+TLS" + echo -e " ${GREEN}7.${PLAIN} 安装V2ray-${BLUE}VLESS+WS+TLS${PLAIN}${RED}(可过cdn)${PLAIN}" + echo -e " ${GREEN}8.${PLAIN} 安装V2ray-${BLUE}VLESS+TCP+XTLS${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}9.${PLAIN} 安装${BLUE}trojan${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}10.${PLAIN} 安装${BLUE}trojan+XTLS${PLAIN}${RED}(推荐)${PLAIN}" + echo " -------------" + echo -e " ${GREEN}11.${PLAIN} 更新V2ray" + echo -e " ${GREEN}12. ${RED}卸载V2ray${PLAIN}" + echo " -------------" + echo -e " ${GREEN}13.${PLAIN} 启动V2ray" + echo -e " ${GREEN}14.${PLAIN} 重启V2ray" + echo -e " ${GREEN}15.${PLAIN} 停止V2ray" + echo " -------------" + echo -e " ${GREEN}16.${PLAIN} 查看V2ray配置" + echo -e " ${GREEN}17.${PLAIN} 查看V2ray日志" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo -n " 当前状态:" + statusText + echo + + read -p " 请选择操作[0-17]:" answer + case $answer in + 0) + exit 0 + ;; + 1) + install + ;; + 2) + KCP="true" + install + ;; + 3) + TLS="true" + install + ;; + 4) + TLS="true" + WS="true" + install + ;; + 5) + VLESS="true" + KCP="true" + install + ;; + 6) + VLESS="true" + TLS="true" + install + ;; + 7) + VLESS="true" + TLS="true" + WS="true" + install + ;; + 8) + VLESS="true" + TLS="true" + XTLS="true" + install + ;; + 9) + TROJAN="true" + TLS="true" + install + ;; + 10) + TROJAN="true" + TLS="true" + XTLS="true" + install + ;; + 11) + update + ;; + 12) + uninstall + ;; + 13) + start + ;; + 14) + restart + ;; + 15) + stop + ;; + 16) + showInfo + ;; + 17) + showLog + ;; + *) + colorEcho $RED " 请选择正确的操作!" + exit 1 + ;; + esac +} + +checkSystem + +action=$1 +[[ -z $1 ]] && action=menu +case "$action" in +menu | update | uninstall | start | restart | stop | showInfo | showLog) + ${action} + ;; +*) + echo " 参数错误" + echo " 用法: $(basename $0) [menu|update|uninstall|start|restart|stop|showInfo|showLog]" + ;; +esac diff --git a/warp.sh b/warp.sh new file mode 100644 index 00000000..7ec10e27 --- /dev/null +++ b/warp.sh @@ -0,0 +1,1206 @@ +#!/usr/bin/env bash + +shVersion='beta38' + +FontColor_Red="\033[31m" +FontColor_Red_Bold="\033[1;31m" +FontColor_Green="\033[32m" +FontColor_Green_Bold="\033[1;32m" +FontColor_Yellow="\033[33m" +FontColor_Yellow_Bold="\033[1;33m" +FontColor_Purple="\033[35m" +FontColor_Purple_Bold="\033[1;35m" +FontColor_Suffix="\033[0m" + +log() { + local LEVEL="$1" + local MSG="$2" + case "${LEVEL}" in + INFO) + local LEVEL="[${FontColor_Green}${LEVEL}${FontColor_Suffix}]" + local MSG="${LEVEL} ${MSG}" + ;; + WARN) + local LEVEL="[${FontColor_Yellow}${LEVEL}${FontColor_Suffix}]" + local MSG="${LEVEL} ${MSG}" + ;; + ERROR) + local LEVEL="[${FontColor_Red}${LEVEL}${FontColor_Suffix}]" + local MSG="${LEVEL} ${MSG}" + ;; + *) ;; + esac + echo -e "${MSG}" +} + +if [[ $(uname -s) != Linux ]]; then + log ERROR "This operating system is not supported." + exit 1 +fi + +if [[ $(id -u) != 0 ]]; then + log ERROR "This script must be run as root." + exit 1 +fi + +if [[ -z $(command -v curl) ]]; then + log ERROR "cURL is not installed." + exit 1 +fi + +WGCF_Profile='wgcf-profile.conf' +WGCF_ProfileDir="/etc/warp" +WGCF_ProfilePath="${WGCF_ProfileDir}/${WGCF_Profile}" + +WireGuard_Interface='wgcf' +WireGuard_ConfPath="/etc/wireguard/${WireGuard_Interface}.conf" + +WireGuard_Interface_DNS_IPv4='8.8.8.8,8.8.4.4' +WireGuard_Interface_DNS_IPv6='2001:4860:4860::8888,2001:4860:4860::8844' +WireGuard_Interface_DNS_46="${WireGuard_Interface_DNS_IPv4},${WireGuard_Interface_DNS_IPv6}" +WireGuard_Interface_DNS_64="${WireGuard_Interface_DNS_IPv6},${WireGuard_Interface_DNS_IPv4}" +WireGuard_Interface_Rule_table='51888' +WireGuard_Interface_Rule_fwmark='51888' +WireGuard_Interface_MTU='1280' + +WireGuard_Peer_Endpoint_IP4='162.159.192.1' +WireGuard_Peer_Endpoint_IP6='2606:4700:d0::a29f:c001' +WireGuard_Peer_Endpoint_IPv4="${WireGuard_Peer_Endpoint_IP4}:2408" +WireGuard_Peer_Endpoint_IPv6="[${WireGuard_Peer_Endpoint_IP6}]:2408" +WireGuard_Peer_Endpoint_Domain='engage.cloudflareclient.com:2408' +WireGuard_Peer_AllowedIPs_IPv4='0.0.0.0/0' +WireGuard_Peer_AllowedIPs_IPv6='::/0' +WireGuard_Peer_AllowedIPs_DualStack='0.0.0.0/0,::/0' + +TestIPv4_1='1.0.0.1' +TestIPv4_2='9.9.9.9' +TestIPv6_1='2606:4700:4700::1001' +TestIPv6_2='2620:fe::fe' +CF_Trace_URL='https://www.cloudflare.com/cdn-cgi/trace' + +Get_System_Info() { + source /etc/os-release + SysInfo_OS_CodeName="${VERSION_CODENAME}" + SysInfo_OS_Name_lowercase="${ID}" + SysInfo_OS_Name_Full="${PRETTY_NAME}" + SysInfo_RelatedOS="${ID_LIKE}" + SysInfo_Kernel="$(uname -r)" + SysInfo_Kernel_Ver_major="$(uname -r | awk -F . '{print $1}')" + SysInfo_Kernel_Ver_minor="$(uname -r | awk -F . '{print $2}')" + SysInfo_Arch="$(uname -m)" + SysInfo_Virt="$(systemd-detect-virt)" + case ${SysInfo_RelatedOS} in + *fedora* | *rhel*) + SysInfo_OS_Ver_major="$(rpm -E '%{rhel}')" + ;; + *) + SysInfo_OS_Ver_major="$(echo ${VERSION_ID} | cut -d. -f1)" + ;; + esac +} + +Print_System_Info() { + echo -e " +System Information +--------------------------------------------------- + Operating System: ${SysInfo_OS_Name_Full} + Linux Kernel: ${SysInfo_Kernel} + Architecture: ${SysInfo_Arch} + Virtualization: ${SysInfo_Virt} +--------------------------------------------------- +" +} + +Install_Requirements_Debian() { + if [[ ! $(command -v gpg) ]]; then + apt update + apt install gnupg -y + fi + if [[ ! $(apt list 2>/dev/null | grep apt-transport-https | grep installed) ]]; then + apt update + apt install apt-transport-https -y + fi +} + +Install_WARP_Client_Debian() { + if [[ ${SysInfo_OS_Name_lowercase} == ubuntu ]]; then + OS_CodeName='focal' + elif [[ ${SysInfo_OS_Name_lowercase} == debian ]]; then + case ${SysInfo_OS_Ver_major} in + 11) + OS_CodeName='bullseye' + ;; + 10) + OS_CodeName='buster' + ;; + *) + log ERROR "This operating system is not supported." + exit 1 + ;; + esac + elif [[ ${SysInfo_RelatedOS} == *debian* ]]; then + OS_CodeName='buster' + else + OS_CodeName="${SysInfo_OS_CodeName}" + fi + Install_Requirements_Debian + curl https://pkg.cloudflareclient.com/pubkey.gpg | gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg + echo "deb [arch=amd64 signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ ${OS_CodeName} main" | tee /etc/apt/sources.list.d/cloudflare-client.list + apt update + apt install cloudflare-warp -y +} + +Install_WARP_Client_CentOS() { + if [[ ${SysInfo_OS_Ver_major} == 8 ]]; then + rpm -ivh http://pkg.cloudflareclient.com/cloudflare-release-el8.rpm + yum install cloudflare-warp -y + else + log ERROR "This operating system is not supported." + exit 1 + fi +} + +Check_WARP_Client() { + WARP_Client_Status=$(systemctl is-active warp-svc) + WARP_Client_SelfStart=$(systemctl is-enabled warp-svc 2>/dev/null) +} + +Install_WARP_Client() { + Print_System_Info + log INFO "Installing Cloudflare WARP Client..." + if [[ ${SysInfo_Arch} != x86_64 ]]; then + log ERROR "This CPU architecture is not supported: ${SysInfo_Arch}" + exit 1 + fi + case ${SysInfo_OS_Name_lowercase} in + *debian* | *ubuntu*) + Install_WARP_Client_Debian + ;; + *centos* | *rhel*) + Install_WARP_Client_CentOS + ;; + *) + if [[ ${SysInfo_RelatedOS} == *debian* ]]; then + Install_WARP_Client_Debian + elif [[ ${SysInfo_RelatedOS} == *rhel* || ${SysInfo_RelatedOS} == *fedora* ]]; then + Install_WARP_Client_CentOS + else + log ERROR "This operating system is not supported." + exit 1 + fi + ;; + esac + Check_WARP_Client + if [[ ${WARP_Client_Status} == active ]]; then + log INFO "Cloudflare WARP Client installed successfully!" + else + log ERROR "warp-svc failure to run!" + journalctl -u warp-svc --no-pager + exit 1 + fi +} + +Uninstall_WARP_Client() { + log INFO "Uninstalling Cloudflare WARP Client..." + case ${SysInfo_OS_Name_lowercase} in + *debian* | *ubuntu*) + apt purge cloudflare-warp -y + rm -f /etc/apt/sources.list.d/cloudflare-client.list /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg + ;; + *centos* | *rhel*) + yum remove cloudflare-warp -y + ;; + *) + if [[ ${SysInfo_RelatedOS} == *rhel* || ${SysInfo_RelatedOS} == *fedora* ]]; then + yum remove cloudflare-warp -y + else + log ERROR "This operating system is not supported." + exit 1 + fi + ;; + esac +} + +Restart_WARP_Client() { + log INFO "Restarting Cloudflare WARP Client..." + systemctl restart warp-svc + Check_WARP_Client + if [[ ${WARP_Client_Status} == active ]]; then + log INFO "Cloudflare WARP Client has been restarted." + else + log ERROR "Cloudflare WARP Client failure to run!" + journalctl -u warp-svc --no-pager + exit 1 + fi +} + +Init_WARP_Client() { + Check_WARP_Client + if [[ ${WARP_Client_SelfStart} != enabled || ${WARP_Client_Status} != active ]]; then + Install_WARP_Client + fi + if [[ $(warp-cli --accept-tos account) == *Missing* ]]; then + log INFO "Cloudflare WARP Account Registration in progress..." + warp-cli --accept-tos register + fi +} + +Connect_WARP() { + log INFO "Connecting to WARP..." + warp-cli --accept-tos connect + log INFO "Enable WARP Always-On..." + warp-cli --accept-tos enable-always-on +} + +Disconnect_WARP() { + log INFO "Disable WARP Always-On..." + warp-cli --accept-tos disable-always-on + log INFO "Disconnect from WARP..." + warp-cli --accept-tos disconnect +} + +Set_WARP_Mode_Proxy() { + log INFO "Setting up WARP Proxy Mode..." + warp-cli --accept-tos set-mode proxy +} + +Enable_WARP_Client_Proxy() { + Init_WARP_Client + Set_WARP_Mode_Proxy + Connect_WARP + Print_WARP_Client_Status +} + +Get_WARP_Proxy_Port() { + WARP_Proxy_Port='40000' +} + +Print_Delimiter() { + printf '=%.0s' $(seq $(tput cols)) + echo +} + +Install_wgcf() { + curl -fsSL git.io/wgcf.sh | bash +} + +Uninstall_wgcf() { + rm -f /usr/local/bin/wgcf +} + +Register_WARP_Account() { + while [[ ! -f wgcf-account.toml ]]; do + Install_wgcf + log INFO "Cloudflare WARP Account registration in progress..." + yes | wgcf register + sleep 5 + done +} + +Generate_WGCF_Profile() { + while [[ ! -f ${WGCF_Profile} ]]; do + Register_WARP_Account + log INFO "WARP WireGuard profile (wgcf-profile.conf) generation in progress..." + wgcf generate + done + Uninstall_wgcf +} + +Backup_WGCF_Profile() { + mkdir -p ${WGCF_ProfileDir} + mv -f wgcf* ${WGCF_ProfileDir} +} + +Read_WGCF_Profile() { + WireGuard_Interface_PrivateKey=$(cat ${WGCF_ProfilePath} | grep ^PrivateKey | cut -d= -f2- | awk '$1=$1') + WireGuard_Interface_Address=$(cat ${WGCF_ProfilePath} | grep ^Address | cut -d= -f2- | awk '$1=$1' | sed ":a;N;s/\n/,/g;ta") + WireGuard_Peer_PublicKey=$(cat ${WGCF_ProfilePath} | grep ^PublicKey | cut -d= -f2- | awk '$1=$1') + WireGuard_Interface_Address_IPv4=$(echo ${WireGuard_Interface_Address} | cut -d, -f1 | cut -d'/' -f1) + WireGuard_Interface_Address_IPv6=$(echo ${WireGuard_Interface_Address} | cut -d, -f2 | cut -d'/' -f1) +} + +Load_WGCF_Profile() { + if [[ -f ${WGCF_Profile} ]]; then + Backup_WGCF_Profile + Read_WGCF_Profile + elif [[ -f ${WGCF_ProfilePath} ]]; then + Read_WGCF_Profile + else + Generate_WGCF_Profile + Backup_WGCF_Profile + Read_WGCF_Profile + fi +} + +Install_WireGuardTools_Debian() { + case ${SysInfo_OS_Ver_major} in + 10) + if [[ -z $(grep "^deb.*buster-backports.*main" /etc/apt/sources.list{,.d/*}) ]]; then + echo "deb http://deb.debian.org/debian buster-backports main" | tee /etc/apt/sources.list.d/backports.list + fi + ;; + *) + if [[ ${SysInfo_OS_Ver_major} -lt 10 ]]; then + log ERROR "This operating system is not supported." + exit 1 + fi + ;; + esac + apt update + apt install iproute2 openresolv -y + apt install wireguard-tools --no-install-recommends -y +} + +Install_WireGuardTools_Ubuntu() { + apt update + apt install iproute2 openresolv -y + apt install wireguard-tools --no-install-recommends -y +} + +Install_WireGuardTools_CentOS() { + yum install epel-release -y || yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-${SysInfo_OS_Ver_major}.noarch.rpm -y + yum install iproute iptables wireguard-tools -y +} + +Install_WireGuardTools_Fedora() { + dnf install iproute iptables wireguard-tools -y +} + +Install_WireGuardTools_Arch() { + pacman -Sy iproute2 openresolv wireguard-tools --noconfirm +} + +Install_WireGuardTools() { + log INFO "Installing wireguard-tools..." + case ${SysInfo_OS_Name_lowercase} in + *debian*) + Install_WireGuardTools_Debian + ;; + *ubuntu*) + Install_WireGuardTools_Ubuntu + ;; + *centos* | *rhel*) + Install_WireGuardTools_CentOS + ;; + *fedora*) + Install_WireGuardTools_Fedora + ;; + *arch*) + Install_WireGuardTools_Arch + ;; + *) + if [[ ${SysInfo_RelatedOS} == *rhel* || ${SysInfo_RelatedOS} == *fedora* ]]; then + Install_WireGuardTools_CentOS + else + log ERROR "This operating system is not supported." + exit 1 + fi + ;; + esac +} + +Install_WireGuardGo() { + case ${SysInfo_Virt} in + openvz | lxc*) + curl -fsSL git.io/wireguard-go.sh | bash + ;; + *) + if [[ ${SysInfo_Kernel_Ver_major} -lt 5 || ${SysInfo_Kernel_Ver_minor} -lt 6 ]]; then + curl -fsSL git.io/wireguard-go.sh | bash + fi + ;; + esac +} + +Check_WireGuard() { + WireGuard_Status=$(systemctl is-active wg-quick@${WireGuard_Interface}) + WireGuard_SelfStart=$(systemctl is-enabled wg-quick@${WireGuard_Interface} 2>/dev/null) +} + +Install_WireGuard() { + Print_System_Info + Check_WireGuard + if [[ ${WireGuard_SelfStart} != enabled || ${WireGuard_Status} != active ]]; then + Install_WireGuardTools + Install_WireGuardGo + else + log INFO "WireGuard is installed and running." + fi +} + +Start_WireGuard() { + Check_WARP_Client + log INFO "Starting WireGuard..." + if [[ ${WARP_Client_Status} == active ]]; then + systemctl stop warp-svc + systemctl enable wg-quick@${WireGuard_Interface} --now + systemctl start warp-svc + else + systemctl enable wg-quick@${WireGuard_Interface} --now + fi + Check_WireGuard + if [[ ${WireGuard_Status} == active ]]; then + log INFO "WireGuard is running." + else + log ERROR "WireGuard failure to run!" + journalctl -u wg-quick@${WireGuard_Interface} --no-pager + exit 1 + fi +} + +Restart_WireGuard() { + Check_WARP_Client + log INFO "Restarting WireGuard..." + if [[ ${WARP_Client_Status} == active ]]; then + systemctl stop warp-svc + systemctl restart wg-quick@${WireGuard_Interface} + systemctl start warp-svc + else + systemctl restart wg-quick@${WireGuard_Interface} + fi + Check_WireGuard + if [[ ${WireGuard_Status} == active ]]; then + log INFO "WireGuard has been restarted." + else + log ERROR "WireGuard failure to run!" + journalctl -u wg-quick@${WireGuard_Interface} --no-pager + exit 1 + fi +} + +Enable_IPv6_Support() { + if [[ $(sysctl -a | grep 'disable_ipv6.*=.*1') || $(cat /etc/sysctl.{conf,d/*} | grep 'disable_ipv6.*=.*1') ]]; then + sed -i '/disable_ipv6/d' /etc/sysctl.{conf,d/*} + echo 'net.ipv6.conf.all.disable_ipv6 = 0' >/etc/sysctl.d/ipv6.conf + sysctl -w net.ipv6.conf.all.disable_ipv6=0 + fi +} + +Enable_WireGuard() { + Enable_IPv6_Support + Check_WireGuard + if [[ ${WireGuard_SelfStart} == enabled ]]; then + Restart_WireGuard + else + Start_WireGuard + fi +} + +Stop_WireGuard() { + Check_WARP_Client + if [[ ${WireGuard_Status} == active ]]; then + log INFO "Stoping WireGuard..." + if [[ ${WARP_Client_Status} == active ]]; then + systemctl stop warp-svc + systemctl stop wg-quick@${WireGuard_Interface} + systemctl start warp-svc + else + systemctl stop wg-quick@${WireGuard_Interface} + fi + Check_WireGuard + if [[ ${WireGuard_Status} != active ]]; then + log INFO "WireGuard has been stopped." + else + log ERROR "WireGuard stop failure!" + fi + else + log INFO "WireGuard is stopped." + fi +} + +Disable_WireGuard() { + Check_WARP_Client + Check_WireGuard + if [[ ${WireGuard_SelfStart} == enabled || ${WireGuard_Status} == active ]]; then + log INFO "Disabling WireGuard..." + if [[ ${WARP_Client_Status} == active ]]; then + systemctl stop warp-svc + systemctl disable wg-quick@${WireGuard_Interface} --now + systemctl start warp-svc + else + systemctl disable wg-quick@${WireGuard_Interface} --now + fi + Check_WireGuard + if [[ ${WireGuard_SelfStart} != enabled && ${WireGuard_Status} != active ]]; then + log INFO "WireGuard has been disabled." + else + log ERROR "WireGuard disable failure!" + fi + else + log INFO "WireGuard is disabled." + fi +} + +Print_WireGuard_Log() { + journalctl -u wg-quick@${WireGuard_Interface} -f +} + +Check_Network_Status_IPv4() { + if ping -c1 -W1 ${TestIPv4_1} >/dev/null 2>&1 || ping -c1 -W1 ${TestIPv4_2} >/dev/null 2>&1; then + IPv4Status='on' + else + IPv4Status='off' + fi +} + +Check_Network_Status_IPv6() { + if ping6 -c1 -W1 ${TestIPv6_1} >/dev/null 2>&1 || ping6 -c1 -W1 ${TestIPv6_2} >/dev/null 2>&1; then + IPv6Status='on' + else + IPv6Status='off' + fi +} + +Check_Network_Status() { + Disable_WireGuard + Check_Network_Status_IPv4 + Check_Network_Status_IPv6 +} + +Check_IPv4_addr() { + IPv4_addr=$( + ip route get ${TestIPv4_1} 2>/dev/null | grep -oP 'src \K\S+' || + ip route get ${TestIPv4_2} 2>/dev/null | grep -oP 'src \K\S+' + ) +} + +Check_IPv6_addr() { + IPv6_addr=$( + ip route get ${TestIPv6_1} 2>/dev/null | grep -oP 'src \K\S+' || + ip route get ${TestIPv6_2} 2>/dev/null | grep -oP 'src \K\S+' + ) +} + +Get_IP_addr() { + Check_Network_Status + if [[ ${IPv4Status} == on ]]; then + log INFO "Getting the network interface IPv4 address..." + Check_IPv4_addr + if [[ ${IPv4_addr} ]]; then + log INFO "IPv4 Address: ${IPv4_addr}" + else + log WARN "Network interface IPv4 address not obtained." + fi + fi + if [[ ${IPv6Status} == on ]]; then + log INFO "Getting the network interface IPv6 address..." + Check_IPv6_addr + if [[ ${IPv6_addr} ]]; then + log INFO "IPv6 Address: ${IPv6_addr}" + else + log WARN "Network interface IPv6 address not obtained." + fi + fi +} + +Get_WireGuard_Interface_MTU() { + log INFO "Getting the best MTU value for WireGuard..." + MTU_Preset=1500 + MTU_Increment=10 + if [[ ${IPv4Status} == off && ${IPv6Status} == on ]]; then + CMD_ping='ping6' + MTU_TestIP_1="${TestIPv6_1}" + MTU_TestIP_2="${TestIPv6_2}" + else + CMD_ping='ping' + MTU_TestIP_1="${TestIPv4_1}" + MTU_TestIP_2="${TestIPv4_2}" + fi + while true; do + if ${CMD_ping} -c1 -W1 -s$((${MTU_Preset} - 28)) -Mdo ${MTU_TestIP_1} >/dev/null 2>&1 || ${CMD_ping} -c1 -W1 -s$((${MTU_Preset} - 28)) -Mdo ${MTU_TestIP_2} >/dev/null 2>&1; then + MTU_Increment=1 + MTU_Preset=$((${MTU_Preset} + ${MTU_Increment})) + else + MTU_Preset=$((${MTU_Preset} - ${MTU_Increment})) + if [[ ${MTU_Increment} == 1 ]]; then + break + fi + fi + if [[ ${MTU_Preset} -le 1360 ]]; then + log WARN "MTU is set to the lowest value." + MTU_Preset='1360' + break + fi + done + WireGuard_Interface_MTU=$((${MTU_Preset} - 80)) + log INFO "WireGuard MTU: ${WireGuard_Interface_MTU}" +} + +Generate_WireGuardProfile_Interface() { + Get_WireGuard_Interface_MTU + log INFO "WireGuard profile (${WireGuard_ConfPath}) generation in progress..." + cat <${WireGuard_ConfPath} +# Generated by P3TERX/warp.sh +# Visit https://github.com/P3TERX/warp.sh for more information + +[Interface] +PrivateKey = ${WireGuard_Interface_PrivateKey} +Address = ${WireGuard_Interface_Address} +DNS = ${WireGuard_Interface_DNS} +MTU = ${WireGuard_Interface_MTU} +EOF +} + +Generate_WireGuardProfile_Interface_Rule_TableOff() { + cat <>${WireGuard_ConfPath} +Table = off +EOF +} + +Generate_WireGuardProfile_Interface_Rule_IPv4_nonGlobal() { + cat <>${WireGuard_ConfPath} +PostUP = ip -4 route add default dev ${WireGuard_Interface} table ${WireGuard_Interface_Rule_table} +PostUP = ip -4 rule add from ${WireGuard_Interface_Address_IPv4} lookup ${WireGuard_Interface_Rule_table} +PostDown = ip -4 rule delete from ${WireGuard_Interface_Address_IPv4} lookup ${WireGuard_Interface_Rule_table} +PostUP = ip -4 rule add fwmark ${WireGuard_Interface_Rule_fwmark} lookup ${WireGuard_Interface_Rule_table} +PostDown = ip -4 rule delete fwmark ${WireGuard_Interface_Rule_fwmark} lookup ${WireGuard_Interface_Rule_table} +PostUP = ip -4 rule add table main suppress_prefixlength 0 +PostDown = ip -4 rule delete table main suppress_prefixlength 0 +EOF +} + +Generate_WireGuardProfile_Interface_Rule_IPv6_nonGlobal() { + cat <>${WireGuard_ConfPath} +PostUP = ip -6 route add default dev ${WireGuard_Interface} table ${WireGuard_Interface_Rule_table} +PostUP = ip -6 rule add from ${WireGuard_Interface_Address_IPv6} lookup ${WireGuard_Interface_Rule_table} +PostDown = ip -6 rule delete from ${WireGuard_Interface_Address_IPv6} lookup ${WireGuard_Interface_Rule_table} +PostUP = ip -6 rule add fwmark ${WireGuard_Interface_Rule_fwmark} lookup ${WireGuard_Interface_Rule_table} +PostDown = ip -6 rule delete fwmark ${WireGuard_Interface_Rule_fwmark} lookup ${WireGuard_Interface_Rule_table} +PostUP = ip -6 rule add table main suppress_prefixlength 0 +PostDown = ip -6 rule delete table main suppress_prefixlength 0 +EOF +} + +Generate_WireGuardProfile_Interface_Rule_DualStack_nonGlobal() { + Generate_WireGuardProfile_Interface_Rule_TableOff + Generate_WireGuardProfile_Interface_Rule_IPv4_nonGlobal + Generate_WireGuardProfile_Interface_Rule_IPv6_nonGlobal +} + +Generate_WireGuardProfile_Interface_Rule_IPv4_Global_srcIP() { + cat <>${WireGuard_ConfPath} +PostUp = ip -4 rule add from ${IPv4_addr} lookup main prio 18 +PostDown = ip -4 rule delete from ${IPv4_addr} lookup main prio 18 +EOF +} + +Generate_WireGuardProfile_Interface_Rule_IPv6_Global_srcIP() { + cat <>${WireGuard_ConfPath} +PostUp = ip -6 rule add from ${IPv6_addr} lookup main prio 18 +PostDown = ip -6 rule delete from ${IPv6_addr} lookup main prio 18 +EOF +} + +Generate_WireGuardProfile_Peer() { + cat <>${WireGuard_ConfPath} + +[Peer] +PublicKey = ${WireGuard_Peer_PublicKey} +AllowedIPs = ${WireGuard_Peer_AllowedIPs} +Endpoint = ${WireGuard_Peer_Endpoint} +EOF +} + +Check_WARP_Client_Status() { + Check_WARP_Client + case ${WARP_Client_Status} in + active) + WARP_Client_Status_en="${FontColor_Green}Running${FontColor_Suffix}" + WARP_Client_Status_zh="${FontColor_Green}运行中${FontColor_Suffix}" + ;; + *) + WARP_Client_Status_en="${FontColor_Red}Stopped${FontColor_Suffix}" + WARP_Client_Status_zh="${FontColor_Red}未运行${FontColor_Suffix}" + ;; + esac +} + +Check_WARP_Proxy_Status() { + Check_WARP_Client + if [[ ${WARP_Client_Status} == active ]]; then + Get_WARP_Proxy_Port + WARP_Proxy_Status=$(curl -sx "socks5h://127.0.0.1:${WARP_Proxy_Port}" ${CF_Trace_URL} --connect-timeout 2 | grep warp | cut -d= -f2) + else + unset WARP_Proxy_Status + fi + case ${WARP_Proxy_Status} in + on) + WARP_Proxy_Status_en="${FontColor_Green}${WARP_Proxy_Port}${FontColor_Suffix}" + WARP_Proxy_Status_zh="${WARP_Proxy_Status_en}" + ;; + plus) + WARP_Proxy_Status_en="${FontColor_Green}${WARP_Proxy_Port}(WARP+)${FontColor_Suffix}" + WARP_Proxy_Status_zh="${WARP_Proxy_Status_en}" + ;; + *) + WARP_Proxy_Status_en="${FontColor_Red}Off${FontColor_Suffix}" + WARP_Proxy_Status_zh="${FontColor_Red}未开启${FontColor_Suffix}" + ;; + esac +} + +Check_WireGuard_Status() { + Check_WireGuard + case ${WireGuard_Status} in + active) + WireGuard_Status_en="${FontColor_Green}Running${FontColor_Suffix}" + WireGuard_Status_zh="${FontColor_Green}运行中${FontColor_Suffix}" + ;; + *) + WireGuard_Status_en="${FontColor_Red}Stopped${FontColor_Suffix}" + WireGuard_Status_zh="${FontColor_Red}未运行${FontColor_Suffix}" + ;; + esac +} + +Check_WARP_WireGuard_Status() { + Check_Network_Status_IPv4 + if [[ ${IPv4Status} == on ]]; then + WARP_IPv4_Status=$(curl -s4 ${CF_Trace_URL} --connect-timeout 2 | grep warp | cut -d= -f2) + else + unset WARP_IPv4_Status + fi + case ${WARP_IPv4_Status} in + on) + WARP_IPv4_Status_en="${FontColor_Green}WARP${FontColor_Suffix}" + WARP_IPv4_Status_zh="${WARP_IPv4_Status_en}" + ;; + plus) + WARP_IPv4_Status_en="${FontColor_Green}WARP+${FontColor_Suffix}" + WARP_IPv4_Status_zh="${WARP_IPv4_Status_en}" + ;; + off) + WARP_IPv4_Status_en="Normal" + WARP_IPv4_Status_zh="正常" + ;; + *) + Check_Network_Status_IPv4 + if [[ ${IPv4Status} == on ]]; then + WARP_IPv4_Status_en="Normal" + WARP_IPv4_Status_zh="正常" + else + WARP_IPv4_Status_en="${FontColor_Red}Unconnected${FontColor_Suffix}" + WARP_IPv4_Status_zh="${FontColor_Red}未连接${FontColor_Suffix}" + fi + ;; + esac + Check_Network_Status_IPv6 + if [[ ${IPv6Status} == on ]]; then + WARP_IPv6_Status=$(curl -s6 ${CF_Trace_URL} --connect-timeout 2 | grep warp | cut -d= -f2) + else + unset WARP_IPv6_Status + fi + case ${WARP_IPv6_Status} in + on) + WARP_IPv6_Status_en="${FontColor_Green}WARP${FontColor_Suffix}" + WARP_IPv6_Status_zh="${WARP_IPv6_Status_en}" + ;; + plus) + WARP_IPv6_Status_en="${FontColor_Green}WARP+${FontColor_Suffix}" + WARP_IPv6_Status_zh="${WARP_IPv6_Status_en}" + ;; + off) + WARP_IPv6_Status_en="Normal" + WARP_IPv6_Status_zh="正常" + ;; + *) + Check_Network_Status_IPv6 + if [[ ${IPv6Status} == on ]]; then + WARP_IPv6_Status_en="Normal" + WARP_IPv6_Status_zh="正常" + else + WARP_IPv6_Status_en="${FontColor_Red}Unconnected${FontColor_Suffix}" + WARP_IPv6_Status_zh="${FontColor_Red}未连接${FontColor_Suffix}" + fi + ;; + esac + if [[ ${IPv4Status} == off && ${IPv6Status} == off ]]; then + log ERROR "Cloudflare WARP network anomaly, WireGuard tunnel established failed." + Disable_WireGuard + exit 1 + fi +} + +Check_ALL_Status() { + Check_WARP_Client_Status + Check_WARP_Proxy_Status + Check_WireGuard_Status + Check_WARP_WireGuard_Status +} + +Print_WARP_Client_Status() { + log INFO "Status check in progress..." + sleep 3 + Check_WARP_Client_Status + Check_WARP_Proxy_Status + echo -e " + ---------------------------- + WARP Client\t: ${WARP_Client_Status_en} + SOCKS5 Port\t: ${WARP_Proxy_Status_en} + ---------------------------- +" + log INFO "Done." +} + +Print_WARP_WireGuard_Status() { + log INFO "Status check in progress..." + Check_WireGuard_Status + Check_WARP_WireGuard_Status + echo -e " + ---------------------------- + WireGuard\t: ${WireGuard_Status_en} + IPv4 Network\t: ${WARP_IPv4_Status_en} + IPv6 Network\t: ${WARP_IPv6_Status_en} + ---------------------------- +" + log INFO "Done." +} + +Print_ALL_Status() { + log INFO "Status check in progress..." + Check_ALL_Status + echo -e " + ---------------------------- + WARP Client\t: ${WARP_Client_Status_en} + SOCKS5 Port\t: ${WARP_Proxy_Status_en} + ---------------------------- + WireGuard\t: ${WireGuard_Status_en} + IPv4 Network\t: ${WARP_IPv4_Status_en} + IPv6 Network\t: ${WARP_IPv6_Status_en} + ---------------------------- +" +} + +View_WireGuard_Profile() { + Print_Delimiter + cat ${WireGuard_ConfPath} + Print_Delimiter +} + +Check_WireGuard_Peer_Endpoint() { + if ping -c1 -W1 ${WireGuard_Peer_Endpoint_IP4} >/dev/null 2>&1; then + WireGuard_Peer_Endpoint="${WireGuard_Peer_Endpoint_IPv4}" + elif ping6 -c1 -W1 ${WireGuard_Peer_Endpoint_IP6} >/dev/null 2>&1; then + WireGuard_Peer_Endpoint="${WireGuard_Peer_Endpoint_IPv6}" + else + WireGuard_Peer_Endpoint="${WireGuard_Peer_Endpoint_Domain}" + fi +} + +Set_WARP_IPv4() { + Install_WireGuard + Get_IP_addr + Load_WGCF_Profile + if [[ ${IPv4Status} == off && ${IPv6Status} == on ]]; then + WireGuard_Interface_DNS="${WireGuard_Interface_DNS_64}" + else + WireGuard_Interface_DNS="${WireGuard_Interface_DNS_46}" + fi + WireGuard_Peer_AllowedIPs="${WireGuard_Peer_AllowedIPs_IPv4}" + Check_WireGuard_Peer_Endpoint + Generate_WireGuardProfile_Interface + if [[ -n ${IPv4_addr} ]]; then + Generate_WireGuardProfile_Interface_Rule_IPv4_Global_srcIP + fi + Generate_WireGuardProfile_Peer + View_WireGuard_Profile + Enable_WireGuard + Print_WARP_WireGuard_Status +} + +Set_WARP_IPv6() { + Install_WireGuard + Get_IP_addr + Load_WGCF_Profile + if [[ ${IPv4Status} == off && ${IPv6Status} == on ]]; then + WireGuard_Interface_DNS="${WireGuard_Interface_DNS_64}" + else + WireGuard_Interface_DNS="${WireGuard_Interface_DNS_46}" + fi + WireGuard_Peer_AllowedIPs="${WireGuard_Peer_AllowedIPs_IPv6}" + Check_WireGuard_Peer_Endpoint + Generate_WireGuardProfile_Interface + if [[ -n ${IPv6_addr} ]]; then + Generate_WireGuardProfile_Interface_Rule_IPv6_Global_srcIP + fi + Generate_WireGuardProfile_Peer + View_WireGuard_Profile + Enable_WireGuard + Print_WARP_WireGuard_Status +} + +Set_WARP_DualStack() { + Install_WireGuard + Get_IP_addr + Load_WGCF_Profile + WireGuard_Interface_DNS="${WireGuard_Interface_DNS_46}" + WireGuard_Peer_AllowedIPs="${WireGuard_Peer_AllowedIPs_DualStack}" + Check_WireGuard_Peer_Endpoint + Generate_WireGuardProfile_Interface + if [[ -n ${IPv4_addr} ]]; then + Generate_WireGuardProfile_Interface_Rule_IPv4_Global_srcIP + fi + if [[ -n ${IPv6_addr} ]]; then + Generate_WireGuardProfile_Interface_Rule_IPv6_Global_srcIP + fi + Generate_WireGuardProfile_Peer + View_WireGuard_Profile + Enable_WireGuard + Print_WARP_WireGuard_Status +} + +Set_WARP_DualStack_nonGlobal() { + Install_WireGuard + Get_IP_addr + Load_WGCF_Profile + WireGuard_Interface_DNS="${WireGuard_Interface_DNS_46}" + WireGuard_Peer_AllowedIPs="${WireGuard_Peer_AllowedIPs_DualStack}" + Check_WireGuard_Peer_Endpoint + Generate_WireGuardProfile_Interface + Generate_WireGuardProfile_Interface_Rule_DualStack_nonGlobal + Generate_WireGuardProfile_Peer + View_WireGuard_Profile + Enable_WireGuard + Print_WARP_WireGuard_Status +} + +Menu_Title="${FontColor_Yellow_Bold}Cloudflare WARP 一键安装脚本${FontColor_Suffix} ${FontColor_Red}[${shVersion}]${FontColor_Suffix} by ${FontColor_Purple_Bold}P3TERX.COM${FontColor_Suffix}" + +Menu_WARP_Client() { + clear + echo -e " +${Menu_Title} + + ------------------------- + WARP 客户端状态 : ${WARP_Client_Status_zh} + SOCKS5 代理端口 : ${WARP_Proxy_Status_zh} + ------------------------- + +管理 WARP 官方客户端: + + ${FontColor_Green_Bold}0${FontColor_Suffix}. 返回主菜单 + - + ${FontColor_Green_Bold}1${FontColor_Suffix}. 开启 SOCKS5 代理 + ${FontColor_Green_Bold}2${FontColor_Suffix}. 关闭 SOCKS5 代理 + ${FontColor_Green_Bold}3${FontColor_Suffix}. 重启 WARP 官方客户端 + ${FontColor_Green_Bold}4${FontColor_Suffix}. 卸载 WARP 官方客户端 +" + unset MenuNumber + read -p "请输入选项: " MenuNumber + echo + case ${MenuNumber} in + 0) + Start_Menu + ;; + 1) + Enable_WARP_Client_Proxy + ;; + 2) + Disconnect_WARP + ;; + 3) + Restart_WARP_Client + ;; + 4) + Uninstall_WARP_Client + ;; + *) + log ERROR "无效输入!" + sleep 2s + Menu_WARP_Client + ;; + esac +} + +Menu_WARP_WireGuard() { + clear + echo -e " +${Menu_Title} + + ------------------------- + WireGuard 状态 : ${WireGuard_Status_zh} + IPv4 网络状态 : ${WARP_IPv4_Status_zh} + IPv6 网络状态 : ${WARP_IPv6_Status_zh} + ------------------------- + +管理 WARP WireGuard: + + ${FontColor_Green_Bold}0${FontColor_Suffix}. 返回主菜单 + - + ${FontColor_Green_Bold}1${FontColor_Suffix}. 查看 WARP WireGuard 日志 + ${FontColor_Green_Bold}2${FontColor_Suffix}. 重启 WARP WireGuard 服务 + ${FontColor_Green_Bold}3${FontColor_Suffix}. 关闭 WARP WireGuard 网络 +" + unset MenuNumber + read -p "请输入选项: " MenuNumber + echo + case ${MenuNumber} in + 0) + Start_Menu + ;; + 1) + Print_WireGuard_Log + ;; + 2) + Restart_WireGuard + ;; + 3) + Disable_WireGuard + ;; + *) + log ERROR "无效输入!" + sleep 2s + Menu_Other + ;; + esac +} + +Start_Menu() { + log INFO "正在检查状态..." + Check_ALL_Status + clear + echo -e " +${Menu_Title} + + ------------------------- + WARP 客户端状态 : ${WARP_Client_Status_zh} + SOCKS5 代理端口 : ${WARP_Proxy_Status_zh} + ------------------------- + WireGuard 状态 : ${WireGuard_Status_zh} + IPv4 网络状态 : ${WARP_IPv4_Status_zh} + IPv6 网络状态 : ${WARP_IPv6_Status_zh} + ------------------------- + + ${FontColor_Green_Bold}1${FontColor_Suffix}. 安装 Cloudflare WARP 官方客户端 + ${FontColor_Green_Bold}2${FontColor_Suffix}. 自动配置 WARP 客户端 SOCKS5 代理 + ${FontColor_Green_Bold}3${FontColor_Suffix}. 管理 Cloudflare WARP 官方客户端 + - + ${FontColor_Green_Bold}4${FontColor_Suffix}. 安装 WireGuard 相关组件 + ${FontColor_Green_Bold}5${FontColor_Suffix}. 自动配置 WARP WireGuard IPv4 网络 + ${FontColor_Green_Bold}6${FontColor_Suffix}. 自动配置 WARP WireGuard IPv6 网络 + ${FontColor_Green_Bold}7${FontColor_Suffix}. 自动配置 WARP WireGuard 双栈全局网络 + ${FontColor_Green_Bold}8${FontColor_Suffix}. 管理 WARP WireGuard 网络 +" + unset MenuNumber + read -p "请输入选项: " MenuNumber + echo + case ${MenuNumber} in + 1) + Install_WARP_Client + ;; + 2) + Enable_WARP_Client_Proxy + ;; + 3) + Menu_WARP_Client + ;; + 4) + Install_WireGuard + ;; + 5) + Set_WARP_IPv4 + ;; + 6) + Set_WARP_IPv6 + ;; + 7) + Set_WARP_DualStack + ;; + 8) + Menu_WARP_WireGuard + ;; + *) + log ERROR "无效输入!" + sleep 2s + Start_Menu + ;; + esac +} + +Print_Usage() { + echo -e " +Cloudflare WARP Installer [${shVersion}] + +USAGE: + bash <(curl -fsSL git.io/warp.sh) [SUBCOMMAND] + +SUBCOMMANDS: + install Install Cloudflare WARP Official Linux Client + uninstall uninstall Cloudflare WARP Official Linux Client + restart Restart Cloudflare WARP Official Linux Client + proxy Enable WARP Client Proxy Mode (default SOCKS5 port: 40000) + unproxy Disable WARP Client Proxy Mode + wg Install WireGuard and related components + wg4 Configuration WARP IPv4 Global Network (with WireGuard), all IPv4 outbound data over the WARP network + wg6 Configuration WARP IPv6 Global Network (with WireGuard), all IPv6 outbound data over the WARP network + wgd Configuration WARP Dual Stack Global Network (with WireGuard), all outbound data over the WARP network + wgx Configuration WARP Non-Global Network (with WireGuard), set fwmark or interface IP Address to use the WARP network + rwg Restart WARP WireGuard service + dwg Disable WARP WireGuard service + status Prints status information + version Prints version information + help Prints this message or the help of the given subcommand(s) + menu Chinese special features menu +" +} + +if [ $# -ge 1 ]; then + Get_System_Info + case ${1} in + install) + Install_WARP_Client + ;; + uninstall) + Uninstall_WARP_Client + ;; + restart) + Restart_WARP_Client + ;; + proxy | socks5 | s5) + Enable_WARP_Client_Proxy + ;; + unproxy | unsocks5 | uns5) + Disconnect_WARP + ;; + wg) + Install_WireGuard + ;; + wg4 | 4) + Set_WARP_IPv4 + ;; + wg6 | 6) + Set_WARP_IPv6 + ;; + wgd | d) + Set_WARP_DualStack + ;; + wgx | x) + Set_WARP_DualStack_nonGlobal + ;; + rwg) + Restart_WireGuard + ;; + dwg) + Disable_WireGuard + ;; + status) + Print_ALL_Status + ;; + help) + Print_Usage + ;; + version) + echo "${shVersion}" + ;; + menu) + Start_Menu + ;; + *) + log ERROR "Invalid Parameters: $*" + Print_Usage + exit 1 + ;; + esac +else + Print_Usage +fi \ No newline at end of file diff --git a/warp_cli/changeport.sh b/warp_cli/changeport.sh new file mode 100644 index 00000000..b61cb882 --- /dev/null +++ b/warp_cli/changeport.sh @@ -0,0 +1,56 @@ +#!/bin/bash +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P warp-cli) ]] && red "WARP-Cli代理模式未安装,脚本即将退出!" && rm -f changeport.sh && exit 1 + +changeport(){ + if [[ $(warp-cli --accept-tos status) =~ Connected ]]; then + warp-cli --accept-tos disconnect + fi + read -p "请输入WARP Cli使用的代理端口(默认40000):" WARPCliPort + [[ -z $WARPCliPort ]] && WARPCliPort=40000 + warp-cli --accept-tos set-proxy-port "$WARPCliPort" >/dev/null 2>&1 + yellow "正在启动Warp-Cli代理模式" + warp-cli --accept-tos connect >/dev/null 2>&1 + socks5Status=$(curl -sx socks5h://localhost:$WARPCliPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 2 | grep warp | cut -d= -f2) + until [[ $socks5Status =~ on|plus ]]; do + red "启动Warp-Cli代理模式失败,正在尝试重启" + warp-cli --accept-tos disconnect >/dev/null 2>&1 + warp-cli --accept-tos connect >/dev/null 2>&1 + socks5Status=$(curl -sx socks5h://localhost:$WARPCliPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 2 | grep warp | cut -d= -f2) + sleep 5 + done + warp-cli --accept-tos enable-always-on >/dev/null 2>&1 + green "WARP-Cli代理模式已启动成功并成功修改代理端口!" + yellow "本地Socks5代理为: 127.0.0.1:$WARPCliPort" + rm -f changeport.sh +} + +changeport \ No newline at end of file diff --git a/warp_cli/netfilxcli.sh b/warp_cli/netfilxcli.sh new file mode 100644 index 00000000..61413f42 --- /dev/null +++ b/warp_cli/netfilxcli.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P warp-cli) ]] && red "WireProxy-WARP代理模式未安装,脚本即将退出!" && rm -f wireproxy-netfilx.sh && exit 1 + +WARPCliPort=$(warp-cli --accept-tos settings 2>/dev/null | grep 'WarpProxy on port' | awk -F "port " '{print $2}') + +check(){ + NetfilxStatus=$(curl -sx socks5h://localhost:$WARPCliPort -fsL --write-out %{http_code} --output /dev/null --max-time 10 "https://www.netflix.com/title/81215567" 2>&1) + if [[ $NetfilxStatus == "200" ]]; then + success + fi + if [[ $NetfilxStatus =~ "403"|"404" ]]; then + failed + fi + if [[ -z $NetfilxStatus ]] || [[ $NetfilxStatus == "000" ]]; then + retry + fi +} + +retry(){ + warp-cli --accept-tos disconnect >/dev/null 2>&1 + warp-cli --accept-tos connect >/dev/null 2>&1 + check +} + +success(){ + WARPCliIP=$(curl -sx socks5h://localhost:$WARPCliPort https://ip.gs -k --connect-timeout 8) + green "当前WireProxy-WARP的IP:$WARPCliIP 已解锁Netfilx" + yellow "等待1小时后,脚本将会自动重新检查Netfilx解锁状态" + sleep 1h + check +} + +failed(){ + WARPCliIP=$(curl -sx socks5h://localhost:$WARPCliPort https://ip.gs -k --connect-timeout 8) + red "当前WireProxy-WARP的IP:$WARPCliIP 未解锁Netfilx,脚本将在15秒后重新测试Netfilx解锁情况" + sleep 15 + warp-cli --accept-tos disconnect >/dev/null 2>&1 + warp-cli --accept-tos connect >/dev/null 2>&1 + check +} + +check \ No newline at end of file diff --git a/warp_cli/switch.sh b/warp_cli/switch.sh new file mode 100644 index 00000000..71fa7f41 --- /dev/null +++ b/warp_cli/switch.sh @@ -0,0 +1,58 @@ +#!/bin/bash +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P warp-cli) ]] && red "WARP-Cli代理模式未安装,脚本即将退出!" && exit 1 + +switch(){ + if [[ $(warp-cli --accept-tos status) =~ Connected ]]; then + warp-cli --accept-tos disconnect + green "WARP-Cli代理模式关闭成功!" + rm -f switch.sh + exit 1 + fi + if [[ $(warp-cli --accept-tos status) =~ Disconnected ]]; then + yellow "正在启动Warp-Cli代理模式" + warp-cli --accept-tos connect >/dev/null 2>&1 + until [[ $(warp-cli --accept-tos status) =~ Connected ]]; do + red "启动Warp-Cli代理模式失败,正在尝试重启" + warp-cli --accept-tos disconnect >/dev/null 2>&1 + warp-cli --accept-tos connect >/dev/null 2>&1 + sleep 5 + done + warp-cli --accept-tos enable-always-on >/dev/null 2>&1 + WARPCliPort=$(warp-cli --accept-tos settings 2>/dev/null | grep 'WarpProxy on port' | awk -F "port " '{print $2}') + green "WARP-Cli代理模式启动成功!" + yellow "本地Socks5代理为:127.0.0.1:$WARPCliPort" + rm -f switch.sh + exit 1 + fi +} + +switch \ No newline at end of file diff --git a/warp_cli/uninstall.sh b/warp_cli/uninstall.sh new file mode 100644 index 00000000..dac9469c --- /dev/null +++ b/warp_cli/uninstall.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P warp-cli) ]] && red "WARP-Cli代理模式未安装,脚本即将退出" && rm -f uninstall.sh && exit 1 + +uninstall(){ + warp-cli --accept-tos disconnect >/dev/null 2>&1 + warp-cli --accept-tos disable-always-on >/dev/null 2>&1 + warp-cli --accept-tos delete >/dev/null 2>&1 + ${PACKAGE_UNINSTALL[int]} cloudflare-warp 2>/dev/null + systemctl disable --now warp-svc >/dev/null 2>&1 + green "WARP-Cli代理模式已彻底卸载成功!" + rm -f uninstall.sh +} + +uninstall \ No newline at end of file diff --git a/warp_cli/warp-cli.sh b/warp_cli/warp-cli.sh new file mode 100644 index 00000000..10c8c6e3 --- /dev/null +++ b/warp_cli/warp-cli.sh @@ -0,0 +1,148 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -n $(type -P warp-cli) ]] && red "WARP-Cli代理模式已经安装,脚本即将退出" && rm -f warp-cli.sh && exit 1 + +arch=`uname -m` +vsid=`grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1` + +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]] && red "检测到未开启TUN模块,请到VPS控制面板处开启" && exit 1 +} + +checkCentOS8(){ + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +install_warpcli_centos(){ + ${PACKAGE_INSTALL[int]} epel-release + ${PACKAGE_INSTALL[int]} net-tools + rpm -ivh http://pkg.cloudflareclient.com/cloudflare-release-el$vsid.rpm + ${PACKAGE_INSTALL[int]} cloudflare-warp +} + +install_warpcli_debian(){ + ${PACKAGE_INSTALL[int]} lsb-release + [[ -z $(type -P gpg 2>/dev/null) ]] && ${PACKAGE_INSTALL[int]} gnupg + [[ -z $(apt list 2>/dev/null | grep apt-transport-https | grep installed) ]] && ${PACKAGE_INSTALL[int]} apt-transport-https + curl https://pkg.cloudflareclient.com/pubkey.gpg | apt-key add - + echo "deb http://pkg.cloudflareclient.com/ $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/cloudflare-client.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} cloudflare-warp +} + +install_warpcli_ubuntu(){ + ${PACKAGE_INSTALL[int]} lsb-release + curl https://pkg.cloudflareclient.com/pubkey.gpg | apt-key add - + echo "deb http://pkg.cloudflareclient.com/ $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/cloudflare-client.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL[int]} cloudflare-warp +} + +register_warpcli(){ + warp-cli --accept-tos register >/dev/null 2>&1 + yellow "使用WARP免费版账户请按回车跳过 \n启用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + if [[ -n $WPPlusKey ]]; then + warp-cli --accept-tos set-license "$LICENSE" >/dev/null 2>&1 && sleep 1 + if [[ $(warp-cli --accept-tos account) =~ Limited ]]; then + green "WARP+账户启用成功" + else + red "WARP+账户启用失败,即将使用WARP免费版账户" + fi + fi + warp-cli --accept-tos set-mode proxy >/dev/null 2>&1 +} + +set_proxy_port(){ + read -p "请输入WARP Cli使用的代理端口(默认40000):" WARPCliPort + [[ -z $WARPCliPort ]] && WARPCliPort=40000 + warp-cli --accept-tos set-proxy-port "$WARPCliPort" >/dev/null 2>&1 +} + +start_warpcli(){ + yellow "正在启动Warp-Cli代理模式" + warp-cli --accept-tos connect >/dev/null 2>&1 + socks5Status=$(curl -sx socks5h://localhost:$WARPCliPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 2 | grep warp | cut -d= -f2) + until [[ $socks5Status =~ on|plus ]]; do + red "启动Warp-Cli代理模式失败,正在尝试重启" + warp-cli --accept-tos disconnect >/dev/null 2>&1 + warp-cli --accept-tos connect >/dev/null 2>&1 + socks5Status=$(curl -sx socks5h://localhost:$WARPCliPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 2 | grep warp | cut -d= -f2) + sleep 8 + done + warp-cli --accept-tos enable-always-on >/dev/null 2>&1 + socks5IP=$(curl -sx socks5h://localhost:$WARPCliPort ip.gs -k --connect-timeout 8) + green "WARP-Cli代理模式已启动成功!" + yellow "本地Socks5代理为: 127.0.0.1:$WARPCliPort" + yellow "WARP-Cli代理模式的IP为:$socks5IP" + rm -f warp-cli.sh +} + +install(){ + [[ -z $(curl -s4m8 ip.gs ) ]] && red "WARP-Cli代理模式目前不支持IPv6 Only的VPS,脚本退出" && exit 1 + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + [[ $SYSTEM == "CentOS" ]] && [[ ! ${vsid} =~ 8 ]] && yellow "当前系统版本:Centos $vsid \nWARP-Cli代理模式仅支持Centos 8系统" + [[ $SYSTEM == "Debian" ]] && [[ ! ${vsid} =~ 9|10|11 ]] && yellow "当前系统版本:Debian $vsid \nWARP-Cli代理模式仅支持Debian 9-11系统" + [[ $SYSTEM == "Ubuntu" ]] && [[ ! ${vsid} =~ 16|20 ]] && yellow "当前系统版本:Ubuntu $vsid \nWARP-Cli代理模式仅支持Ubuntu 16.04/20.04系统" + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P sudo) ]] && ${PACKAGE_INSTALL[int]} sudo + [[ $SYSTEM == "CentOS" ]] && install_warpcli_centos + [[ $SYSTEM == "Debian" ]] && install_warpcli_debian + [[ $SYSTEM == "Ubuntu" ]] && install_warpcli_ubuntu + register_warpcli + set_proxy_port + start_warpcli + else + red "不支持的CPU架构!脚本即将退出" + fi +} + +check_tun +checkCentOS8 +install \ No newline at end of file diff --git a/warpplus.py b/warpplus.py new file mode 100644 index 00000000..7896cee2 --- /dev/null +++ b/warpplus.py @@ -0,0 +1,76 @@ +import urllib.request +import json +import datetime +import random +import string +import time +import os +import sys +import telegram + +referrer = input("请输入WARP应用内的设备ID:") +chat_id = input("请输入你的Telegram ID(可在 @userinfobot 查看):") +tg_bot_token = input("请输入Telegram bot API Token (可在 @botfather 获取)") + +bot = telegram.Bot(token=tg_bot_token) + +def genString(stringLength): + try: + letters = string.ascii_letters + string.digits + return ''.join(random.choice(letters) for i in range(stringLength)) + except Exception as error: + print(error) +def digitString(stringLength): + try: + digit = string.digits + return ''.join((random.choice(digit) for i in range(stringLength))) + except Exception as error: + print(error) +url = f'https://api.cloudflareclient.com/v0a{digitString(3)}/reg' +def run(): + try: + install_id = genString(22) + body = {"key": "{}=".format(genString(43)), + "install_id": install_id, + "fcm_token": "{}:APA91b{}".format(install_id, genString(134)), + "referrer": referrer, + "warp_enabled": False, + "tos": datetime.datetime.now().isoformat()[:-3] + "+02:00", + "type": "Android", + "locale": "es_ES"} + data = json.dumps(body).encode('utf8') + headers = {'Content-Type': 'application/json; charset=UTF-8', + 'Host': 'api.cloudflareclient.com', + 'Connection': 'Keep-Alive', + 'Accept-Encoding': 'gzip', + 'User-Agent': 'okhttp/3.12.1' + } + req = urllib.request.Request(url, data, headers) + response = urllib.request.urlopen(req) + status_code = response.getcode() + return status_code + except Exception as error: + print(error) + +g = 0 +b = 0 +while True: + result = run() + if result == 200: + g = g + 1 + os.system('cls' if os.name == 'nt' else 'clear') + animation = ["[■□□□□□□□□□] 10%","[■■□□□□□□□□] 20%", "[■■■□□□□□□□] 30%", "[■■■■□□□□□□] 40%", "[■■■■■□□□□□] 50%", "[■■■■■■□□□□] 60%", "[■■■■■■■□□□] 70%", "[■■■■■■■■□□] 80%", "[■■■■■■■■■□] 90%", "[■■■■■■■■■■] 100%"] + for i in range(len(animation)): + time.sleep(0.5) + sys.stdout.write("\r[+] 准备中... " + animation[i % len(animation)] + "\n") + sys.stdout.flush() + print(f"[:)] {g}GB流量已成功添加到你的账户!") + print(f"[#] {g}次成功 {b}次失败") + print("[*] 等待18秒,下一个请求即将发出") + bot.send_message(chat_id=chat_id, text=f"恭喜🎉 \n1GB流量已成功添加到{referrer}账户!\n{g}次成功 {b}次失败\nScript by @ALIILAPRO modified by @Misaka-blog") + time.sleep(18) + else: + b = b + 1 + os.system('cls' if os.name == 'nt' else 'clear') + print("[:(] 我们无法连接到CloudFlare服务器,请稍后重试") + print(f"[#] {g} 次成功 {b} 次失败") diff --git a/warpplus.sh b/warpplus.sh new file mode 100644 index 00000000..ab80e59a --- /dev/null +++ b/warpplus.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# 控制台字体 +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Alpine") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "apk add -f") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") + +# 判断是否为root用户 +[[ $EUID -ne 0 ]] && yellow "请在root用户下运行脚本" && exit 1 + +# 检测系统,本部分代码感谢fscarmen的指导 +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持VPS的当前系统,请使用主流的操作系统" && exit 1 + +# 判断依赖是否安装,如未安装则自动安装 +[[ -z $(type -P curl) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl +[[ -z $(type -P screen) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} screen +[[ -z $(type -P python3) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} python3 + +# 安装py依赖 +pip3 install python3-telegram-bot + +# 运行脚本 +python3 warpplus.py & diff --git a/wgcf_warp/netfilx4.sh b/wgcf_warp/netfilx4.sh new file mode 100644 index 00000000..19a65de0 --- /dev/null +++ b/wgcf_warp/netfilx4.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P wireproxy) ]] && red "WireProxy-WARP代理模式未安装,脚本即将退出!" && rm -f wireproxy-netfilx.sh && exit 1 + +check(){ + NetfilxStatus=$(curl -4 --user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.39" -fsL --write-out %{http_code} --output /dev/null --max-time 10 "https://www.netflix.com/title/81215567" 2>&1) + if [[ $NetfilxStatus == "200" ]]; then + success + fi + if [[ $NetfilxStatus =~ "403"|"404" ]]; then + failed + fi + if [[ -z $NetfilxStatus ]] || [[ $NetfilxStatus == "000" ]]; then + retry + fi +} + +retry(){ + wg-quick down wgcf + wg-quick up wgcf + check +} + +success(){ + WgcfWARPIP=$(curl -s4m8 https://ip.gs -k) + green "当前Wgcf-WARP的IP:$WgcfWARPIP 已解锁Netfilx" + yellow "等待1小时后,脚本将会自动重新检查Netfilx解锁状态" + sleep 1h + check +} + +failed(){ + WgcfWARPIP=$(curl -s4m8 https://ip.gs -k) + red "当前WireProxy-WARP的IP:$WgcfWARPIP 未解锁Netfilx,脚本将在15秒后重新测试Netfilx解锁情况" + sleep 15 + wg-quick down wgcf + wg-quick up wgcf + check +} + +check diff --git a/wgcf_warp/netfilx6.sh b/wgcf_warp/netfilx6.sh new file mode 100644 index 00000000..0632bfd5 --- /dev/null +++ b/wgcf_warp/netfilx6.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P wireproxy) ]] && red "WireProxy-WARP代理模式未安装,脚本即将退出!" && rm -f wireproxy-netfilx.sh && exit 1 + +check(){ + NetfilxStatus=$(curl -6 --user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.39" -fsL --write-out %{http_code} --output /dev/null --max-time 10 "https://www.netflix.com/title/81215567" 2>&1) + if [[ $NetfilxStatus == "200" ]]; then + success + fi + if [[ $NetfilxStatus =~ "403"|"404" ]]; then + failed + fi + if [[ -z $NetfilxStatus ]] || [[ $NetfilxStatus == "000" ]]; then + retry + fi +} + +retry(){ + wg-quick down wgcf + wg-quick up wgcf + check +} + +success(){ + WireProxyIP=$(curl -sx socks5h://localhost:$WireProxyPort https://ip.gs -k --connect-timeout 8) + green "当前WireProxy-WARP的IP:$WireProxyIP 已解锁Netfilx" + yellow "等待1小时后,脚本将会自动重新检查Netfilx解锁状态" + sleep 1h + check +} + +failed(){ + WireProxyIP=$(curl -sx socks5h://localhost:$WireProxyPort https://ip.gs -k --connect-timeout 8) + red "当前WireProxy-WARP的IP:$WireProxyIP 未解锁Netfilx,脚本将在15秒后重新测试Netfilx解锁情况" + sleep 15 + wg-quick down wgcf + wg-quick up wgcf + check +} + +check diff --git a/wgcf_warp/selectregion.sh b/wgcf_warp/selectregion.sh new file mode 100644 index 00000000..dce9edf1 --- /dev/null +++ b/wgcf_warp/selectregion.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P wg-quick) ]] && red "未安装Wgcf-WARP,脚本即将退出" && rm -f selectregion.sh && exit 1 + +IP4_Region=$(curl -s4m8 https://ip.gs/country-iso) +IP6_Region=$(curl -s6m8 https://ip.gs/country-iso) \ No newline at end of file diff --git a/wgcf_warp/switchwarp.sh b/wgcf_warp/switchwarp.sh new file mode 100644 index 00000000..b15e304a --- /dev/null +++ b/wgcf_warp/switchwarp.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P wg-quick) ]] && red "未安装Wgcf-WARP,脚本即将退出" && rm -f switch.sh && exit 1 + +WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) +WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + +if [[ $WgcfWARP4Status =~ on|plus ]] || [[ $WgcfWARP6Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + green "Wgcf-WARP关闭成功!" + exit 1 +fi + +if [[ $WgcfWARP4Status == off ]] || [[ $WgcfWARP6Status == off ]]; then + systemctl restart wg-quick@wgcf >/dev/null 2>&1 + green "Wgcf-WARP启动成功!" + exit 1 +fi \ No newline at end of file diff --git a/wgcf_warp/uninstall.sh b/wgcf_warp/uninstall.sh new file mode 100644 index 00000000..d02a7b82 --- /dev/null +++ b/wgcf_warp/uninstall.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P wg-quick) ]] && red "Wgcf-WARP未安装,脚本即将退出" && rm -f uninstall.sh && exit 1 + +uninstall(){ + wg-quick down wgcf 2>/dev/null + systemctl disable wg-quick@wgcf 2>/dev/null + ${PACKAGE_UNINSTALL[int]} wireguard-tools wireguard-dkms 2>/dev/null + [[ -z $(type -P wireproxy) ]] && rm -f /usr/local/bin/wgcf + rm -f /etc/wireguard/wgcf.conf + rm -f /etc/wireguard/wgcf-account.toml + rm -f /usr/bin/wireguard-go + if [[ -e /etc/gai.conf ]]; then + sed -i '/^precedence[ ]*::ffff:0:0\/96[ ]*100/d' /etc/gai.conf + fi + green "Wgcf-WARP 已彻底卸载成功!" + rm -f uninstall.sh +} + +uninstall diff --git a/wgcf_warp/updown-account.sh b/wgcf_warp/updown-account.sh new file mode 100644 index 00000000..20956af9 --- /dev/null +++ b/wgcf_warp/updown-account.sh @@ -0,0 +1,174 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P wg-quick) ]] && red "未安装Wgcf-WARP,脚本即将退出" && rm -f switch.sh && exit 1 + +WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) +WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + +downwpfree(){ + cd /etc/wireguard + rm -f wgcf-account.toml + yellow "正在注册WARP 免费版账户" + until [[ -a wgcf-account.toml ]]; do + yes | wgcf register + sleep 5 + done + chmod +x wgcf-account.toml + wgcf generate + chmod +x wgcf-profile.conf + if [[ $WgcfWARP6Status =~ on|plus || $WgcfWARP4Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + fi + wpfreepublickey=$(grep PublicKey wgcf-profile.conf | sed "s/PublicKey = //g") + wpfreeprivatekey=$(grep PrivateKey wgcf-profile.conf | sed "s/PrivateKey = //g") + sed -i "s#PublicKey.*#PublicKey = $wpfreepublickey#g" /etc/wireguard/wgcf.conf; + sed -i "s#PrivateKey.*#PrivateKey = $wpfreeprivatekey#g" /etc/wireguard/wgcf.conf; + rm -f wgcf-profile.conf + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP6Status =~ on|plus || $WgcfWARP4Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + green "Wgcf-WARP 已启动成功" + systemctl enable wg-quick@wgcf >/dev/null 2>&1 +} + +upwpplus(){ + cd /etc/wireguard + if [[ ! -f wgcf-account.toml ]]; then + until [[ -a wgcf-account.toml ]]; do + yes | wgcf register + sleep 5 + done + fi + chmod +x wgcf-account.toml + yellow "使用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + [[ -z $WPPlusKey ]] && red "未输入许可证密钥,取消升级WARP+账户,脚本即将退出!" && exit 1 + sed -i "s/license_key.*/license_key = \"$WPPlusKey\"/g" wgcf-account.toml + read -p "请输入自定义设备名,如未输入则使用默认随机设备名:" WPPlusName + green "注册WARP+账户中,如下方显示:400 Bad Request,则使用WARP免费版账户" + if [[ -n $WPPlusName ]]; then + wgcf update --name $(echo $WPPlusName | sed s/[[:space:]]/_/g) + else + wgcf update + fi + wgcf generate + chmod +x wgcf-profile.conf + if [[ $WgcfWARP6Status =~ on|plus || $WgcfWARP4Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + fi + wppluspublickey=$(grep PublicKey wgcf-profile.conf | sed "s/PublicKey = //g") + wpplusprivatekey=$(grep PrivateKey wgcf-profile.conf | sed "s/PrivateKey = //g") + sed -i "s#PublicKey.*#PublicKey = $wppluspublickey#g" /etc/wireguard/wgcf.conf; + sed -i "s#PrivateKey.*#PrivateKey = $wpplusprivatekey#g" /etc/wireguard/wgcf.conf; + rm -f wgcf-profile.conf + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP6Status =~ on|plus || $WgcfWARP4Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + green "Wgcf-WARP 已启动成功" + systemctl enable wg-quick@wgcf >/dev/null 2>&1 +} + +upgradeTeam(){ + read -p "请输入WARP Teams PublicKey:" wpteampublickey + read -p "请输入WARP Teams PrivateKey:" wpteamprivatekey + read -p "请输入WARP Teams IPv4地址:" wpteamv4address + read -p "请输入WARP Teams IPv6地址:" wpteamv6address + read -p "请输入WARP Teams EndPoint:" wpteamendpoint + echo "" + yellow "请确认WARP Teams信息是否正确:" + green "PublicKey: $wpteampublickey" + green "PrivateKey: $wpteamprivatekey" + green "IPv4 地址: $wpteamv4address" + green "IPv6 地址: $wpteamv6address" + green "EndPoint: $wpteamendpoint" + read -p "确认以上信息正确请输入y,其他按键退出升级过程:" wpteamconfirm + if [ $wpteamconfirm == "y" ]; then + if [[ $WgcfWARP4Status =~ on|plus || $WgcfWARP6Status =~ on|plus ]]; then + wg-quick down wgcf >/dev/null 2>&1 + fi + sed -i "s#PublicKey.*#PublicKey = $wpteampublickey#g" /etc/wireguard/wgcf.conf; + sed -i "s#PrivateKey.*#PrivateKey = $wpteamprivatekey#g" /etc/wireguard/wgcf.conf; + sed -i "s#Address.*32#Address = $wpteamv4address/32#g" /etc/wireguard/wgcf.conf; + sed -i "s#Address.*128#Address = $wpteamv6address/128#g" /etc/wireguard/wgcf.conf; + sed -i "s#EndPoint.*#Address = $wpteamendpoint#g" /etc/wireguard/wgcf.conf; + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP6Status =~ on|plus || $WgcfWARP4Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + green "Wgcf-WARP 已启动成功" + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + fi +} + +menu(){ + yellow "请输入你想要切换的Wgcf-WARP账号类型:" + green "1. WARP 免费版账户" + green "2. WARP+" + green "3. WARP Teams" + read -p "请输入选项 [1-3]:" menuNumberInput + case "$menuNumberInput" in + 1 ) downwpfree ;; + 2 ) upwpplus ;; + 3 ) upgradeTeam ;; + * ) red "输入无效!脚本即将退出" && exit 1 ;; + esac +} + +menu diff --git a/wgcf_warp/warp46.sh b/wgcf_warp/warp46.sh new file mode 100644 index 00000000..57292c7f --- /dev/null +++ b/wgcf_warp/warp46.sh @@ -0,0 +1,230 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -n $(type -P wg-quick) ]] && red "Wgcf-WARP已经安装,脚本即将退出" && rm -f warp46.sh && exit 1 + +arch=`uname -m` +main=`uname -r | awk -F . '{print $1}'` +minor=`uname -r | awk -F . '{print $2}'` +vpsvirt=`systemd-detect-virt` + +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + if [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]]; then + if [[ $vpsvirt == "openvz" ]]; then + wget -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/tun-script/master/tun.sh && bash tun.sh + else + red "检测到未开启TUN模块,请到VPS控制面板处开启" + exit 1 + fi + fi +} + +checkCentOS8(){ + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +install_wireguard_centos(){ + ${PACKAGE_INSTALL[int]} epel-release + ${PACKAGE_INSTALL[int]} net-tools wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + vsid=`grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1` + curl -Lo /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-$vsid/jdoss-wireguard-epel-$vsid.repo + yum -y install epel-release wireguard-dkms + fi + fi +} + +install_wireguard_debian(){ + ${PACKAGE_INSTALL[int]} lsb-release + echo "deb http://deb.debian.org/debian $(lsb_release -sc)-backports main" | tee /etc/apt/sources.list.d/backports.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + ${PACKAGE_INSTALL} --no-install-recommends linux-headers-$(uname -r);apt -y --no-install-recommends install wireguard-dkms + fi + fi +} + +install_wireguard_ubuntu(){ + ${PACKAGE_INSTALL[int]} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables +} + +install_wireguard(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P sudo) ]] && ${PACKAGE_INSTALL[int]} sudo + [[ $SYSTEM == CentOS ]] && install_wireguard_centos + [[ $SYSTEM == Debian ]] && install_wireguard_debian + [[ $SYSTEM == Ubuntu ]] && install_wireguard_ubuntu + if [[ $vpsvirt =~ lxc|openvz ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi + if [[ $vpsvirt == zvm ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go-s390x -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi +} + +install_wgcf(){ + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "armv8" || $arch == "arm64" || $arch == "aarch64" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "s390x" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi +} + +register_wgcf(){ + rm -f wgcf-account.toml + until [[ -a wgcf-account.toml ]]; do + yellow "正在向CloudFlare WARP申请账号,如提示429 Too Many Requests错误请耐心等待即可" + yes | wgcf register + sleep 5 + done + chmod +x wgcf-account.toml +} + +generate_wgcf_config(){ + yellow "使用WARP免费版账户请按回车跳过 \n启用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + if [[ -n $WPPlusKey ]]; then + sed -i "s/license_key.*/license_key = \"$WPPlusKey\"/g" wgcf-account.toml + read -p "请输入自定义设备名,如未输入则使用默认随机设备名:" WPPlusName + green "注册WARP+账户中,如下方显示:400 Bad Request,则使用WARP免费版账户" + if [[ -n $WPPlusName ]]; then + wgcf update --name $(echo $WPPlusName | sed s/[[:space:]]/_/g) + else + wgcf update + fi + fi + wgcf generate + chmod +x wgcf-profile.conf + sed -i '/0\.\0\/0/d' wgcf-profile.conf + sed -i 's/engage.cloudflareclient.com/162.159.193.10/g' wgcf-profile.conf + sed -i 's/1.1.1.1/1.1.1.1,8.8.8.8,8.8.4.4,2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844/g' wgcf-profile.conf +} + +get_best_mtu(){ + v66=`curl -s6m8 https://ip.gs -k` + v44=`curl -s4m8 https://ip.gs -k` + MTUy=1500 + MTUc=10 + if [[ -n ${v66} && -z ${v44} ]]; then + ping='ping6' + IP1='2606:4700:4700::1001' + IP2='2001:4860:4860::8888' + else + ping='ping' + IP1='1.1.1.1' + IP2='8.8.8.8' + fi + while true; do + if ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP1} >/dev/null 2>&1 || ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP2} >/dev/null 2>&1; then + MTUc=1 + MTUy=$((${MTUy} + ${MTUc})) + else + MTUy=$((${MTUy} - ${MTUc})) + if [[ ${MTUc} = 1 ]]; then + break + fi + fi + if [[ ${MTUy} -le 1360 ]]; then + MTUy='1360' + break + fi + done + MTU=$((${MTUy} - 80)) + green "MTU最佳值=$MTU 已设置完毕" + sed -i "s/MTU.*/MTU = $MTU/g" wgcf-profile.conf +} + +cpto_wireguard(){ + [[ $SYSTEM == "CentOS" ]] && mkdir /etc/wireguard >/dev/null 2>&1 + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml +} + +start_wgcf(){ + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARPStatus =~ "on"|"plus" ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv6=$(curl -s6m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv6 IP为:$WgcfIPv6" + rm -f warp46.sh +} + +install(){ + install_wireguard + [[ -z $(type -P wgcf) ]] && install_wgcf + register_wgcf + generate_wgcf_config + get_best_mtu + cpto_wireguard + start_wgcf +} + +check_tun +checkCentOS8 +install \ No newline at end of file diff --git a/wgcf_warp/warp4d.sh b/wgcf_warp/warp4d.sh new file mode 100644 index 00000000..b3ab0e6f --- /dev/null +++ b/wgcf_warp/warp4d.sh @@ -0,0 +1,235 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -n $(type -P wg-quick) ]] && red "Wgcf-WARP已经安装,脚本即将退出" && rm -f warp4d.sh && exit 1 + +arch=`uname -m` +main=`uname -r | awk -F . '{print $1}'` +minor=`uname -r | awk -F . '{print $2}'` +vpsvirt=`systemd-detect-virt` + +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + if [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]]; then + if [[ $vpsvirt == "openvz" ]]; then + wget -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/tun-script/master/tun.sh && bash tun.sh + else + red "检测到未开启TUN模块,请到VPS控制面板处开启" + exit 1 + fi + fi +} + +checkCentOS8(){ + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +install_wireguard_centos(){ + ${PACKAGE_INSTALL[int]} epel-release + ${PACKAGE_INSTALL[int]} net-tools wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + vsid=`grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1` + curl -Lo /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-$vsid/jdoss-wireguard-epel-$vsid.repo + yum -y install epel-release wireguard-dkms + fi + fi +} + +install_wireguard_debian(){ + ${PACKAGE_INSTALL[int]} lsb-release + echo "deb http://deb.debian.org/debian $(lsb_release -sc)-backports main" | tee /etc/apt/sources.list.d/backports.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + ${PACKAGE_INSTALL} --no-install-recommends linux-headers-$(uname -r);apt -y --no-install-recommends install wireguard-dkms + fi + fi +} + +install_wireguard_ubuntu(){ + ${PACKAGE_INSTALL[int]} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables +} + +install_wireguard(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P sudo) ]] && ${PACKAGE_INSTALL[int]} sudo + [[ $SYSTEM == CentOS ]] && install_wireguard_centos + [[ $SYSTEM == Debian ]] && install_wireguard_debian + [[ $SYSTEM == Ubuntu ]] && install_wireguard_ubuntu + if [[ $vpsvirt =~ lxc|openvz ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi + if [[ $vpsvirt == zvm ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go-s390x -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi +} + +install_wgcf(){ + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "armv8" || $arch == "arm64" || $arch == "aarch64" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "s390x" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi +} + +register_wgcf(){ + rm -f wgcf-account.toml + until [[ -a wgcf-account.toml ]]; do + yellow "正在向CloudFlare WARP申请账号,如提示429 Too Many Requests错误请耐心等待即可" + yes | wgcf register + sleep 5 + done + chmod +x wgcf-account.toml +} + +generate_wgcf_config(){ + yellow "使用WARP免费版账户请按回车跳过 \n启用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + if [[ -n $WPPlusKey ]]; then + sed -i "s/license_key.*/license_key = \"$WPPlusKey\"/g" wgcf-account.toml + read -p "请输入自定义设备名,如未输入则使用默认随机设备名:" WPPlusName + green "注册WARP+账户中,如下方显示:400 Bad Request,则使用WARP免费版账户" + if [[ -n $WPPlusName ]]; then + wgcf update --name $(echo $WPPlusName | sed s/[[:space:]]/_/g) + else + wgcf update + fi + fi + wgcf generate + chmod +x wgcf-profile.conf + sed -i "7 s/^/PostUp = ip -4 rule add from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -4 rule delete from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/engage.cloudflareclient.com/162.159.193.10/g' wgcf-profile.conf + sed -i 's/1.1.1.1/1.1.1.1,8.8.8.8,8.8.4.4,2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844/g' wgcf-profile.conf +} + +get_best_mtu(){ + v66=`curl -s6m8 https://ip.gs -k` + v44=`curl -s4m8 https://ip.gs -k` + MTUy=1500 + MTUc=10 + if [[ -n ${v66} && -z ${v44} ]]; then + ping='ping6' + IP1='2606:4700:4700::1001' + IP2='2001:4860:4860::8888' + else + ping='ping' + IP1='1.1.1.1' + IP2='8.8.8.8' + fi + while true; do + if ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP1} >/dev/null 2>&1 || ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP2} >/dev/null 2>&1; then + MTUc=1 + MTUy=$((${MTUy} + ${MTUc})) + else + MTUy=$((${MTUy} - ${MTUc})) + if [[ ${MTUc} = 1 ]]; then + break + fi + fi + if [[ ${MTUy} -le 1360 ]]; then + MTUy='1360' + break + fi + done + MTU=$((${MTUy} - 80)) + green "MTU最佳值=$MTU 已设置完毕" + sed -i "s/MTU.*/MTU = $MTU/g" wgcf-profile.conf +} + +cpto_wireguard(){ + [[ $SYSTEM == "CentOS" ]] && mkdir /etc/wireguard >/dev/null 2>&1 + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml +} + +start_wgcf(){ + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] && [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv4=$(curl -s4m8 https://ip.gs -k) + WgcfIPv6=$(curl -s6m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv4 IP为:$WgcfIPv4" + yellow "Wgcf-WARP的IPv6 IP为:$WgcfIPv6" + rm -f warp4d.sh +} + +install(){ + install_wireguard + [[ -z $(type -P wgcf) ]] && install_wgcf + register_wgcf + generate_wgcf_config + get_best_mtu + cpto_wireguard + start_wgcf +} + +check_tun +checkCentOS8 +install \ No newline at end of file diff --git a/wgcf_warp/warp64.sh b/wgcf_warp/warp64.sh new file mode 100644 index 00000000..a9bee255 --- /dev/null +++ b/wgcf_warp/warp64.sh @@ -0,0 +1,230 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -n $(type -P wg-quick) ]] && red "Wgcf-WARP已经安装,脚本即将退出" && rm -f warp64.sh && exit 1 + +arch=`uname -m` +main=`uname -r | awk -F . '{print $1}'` +minor=`uname -r | awk -F . '{print $2}'` +vpsvirt=`systemd-detect-virt` + +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + if [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]]; then + if [[ $vpsvirt == "openvz" ]]; then + wget -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/tun-script/master/tun.sh && bash tun.sh + else + red "检测到未开启TUN模块,请到VPS控制面板处开启" + exit 1 + fi + fi +} + +checkCentOS8(){ + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +install_wireguard_centos(){ + ${PACKAGE_INSTALL[int]} epel-release + ${PACKAGE_INSTALL[int]} net-tools wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + vsid=`grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1` + curl -Lo /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-$vsid/jdoss-wireguard-epel-$vsid.repo + yum -y install epel-release wireguard-dkms + fi + fi +} + +install_wireguard_debian(){ + ${PACKAGE_INSTALL[int]} lsb-release + echo "deb http://deb.debian.org/debian $(lsb_release -sc)-backports main" | tee /etc/apt/sources.list.d/backports.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + ${PACKAGE_INSTALL} --no-install-recommends linux-headers-$(uname -r);apt -y --no-install-recommends install wireguard-dkms + fi + fi +} + +install_wireguard_ubuntu(){ + ${PACKAGE_INSTALL[int]} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables +} + +install_wireguard(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P sudo) ]] && ${PACKAGE_INSTALL[int]} sudo + [[ $SYSTEM == CentOS ]] && install_wireguard_centos + [[ $SYSTEM == Debian ]] && install_wireguard_debian + [[ $SYSTEM == Ubuntu ]] && install_wireguard_ubuntu + if [[ $vpsvirt =~ lxc|openvz ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi + if [[ $vpsvirt == zvm ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go-s390x -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi +} + +install_wgcf(){ + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "armv8" || $arch == "arm64" || $arch == "aarch64" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "s390x" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi +} + +register_wgcf(){ + rm -f wgcf-account.toml + until [[ -a wgcf-account.toml ]]; do + yellow "正在向CloudFlare WARP申请账号,如提示429 Too Many Requests错误请耐心等待即可" + yes | wgcf register + sleep 5 + done + chmod +x wgcf-account.toml +} + +generate_wgcf_config(){ + yellow "使用WARP免费版账户请按回车跳过 \n启用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + if [[ -n $WPPlusKey ]]; then + sed -i "s/license_key.*/license_key = \"$WPPlusKey\"/g" wgcf-account.toml + read -p "请输入自定义设备名,如未输入则使用默认随机设备名:" WPPlusName + green "注册WARP+账户中,如下方显示:400 Bad Request,则使用WARP免费版账户" + if [[ -n $WPPlusName ]]; then + wgcf update --name $(echo $WPPlusName | sed s/[[:space:]]/_/g) + else + wgcf update + fi + fi + wgcf generate + chmod +x wgcf-profile.conf + sed -i '/\:\:\/0/d' wgcf-profile.conf + sed -i 's/engage.cloudflareclient.com/[2606:4700:d0::a29f:c001]/g' wgcf-profile.conf + sed -i 's/1.1.1.1/2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844,1.1.1.1,8.8.8.8,8.8.4.4/g' wgcf-profile.conf +} + +get_best_mtu(){ + v66=`curl -s6m8 https://ip.gs -k` + v44=`curl -s4m8 https://ip.gs -k` + MTUy=1500 + MTUc=10 + if [[ -n ${v66} && -z ${v44} ]]; then + ping='ping6' + IP1='2606:4700:4700::1001' + IP2='2001:4860:4860::8888' + else + ping='ping' + IP1='1.1.1.1' + IP2='8.8.8.8' + fi + while true; do + if ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP1} >/dev/null 2>&1 || ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP2} >/dev/null 2>&1; then + MTUc=1 + MTUy=$((${MTUy} + ${MTUc})) + else + MTUy=$((${MTUy} - ${MTUc})) + if [[ ${MTUc} = 1 ]]; then + break + fi + fi + if [[ ${MTUy} -le 1360 ]]; then + MTUy='1360' + break + fi + done + MTU=$((${MTUy} - 80)) + green "MTU最佳值=$MTU 已设置完毕" + sed -i "s/MTU.*/MTU = $MTU/g" wgcf-profile.conf +} + +cpto_wireguard(){ + [[ $SYSTEM == "CentOS" ]] && mkdir /etc/wireguard >/dev/null 2>&1 + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml +} + +start_wgcf(){ + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARPStatus =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARPStatus=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv4=$(curl -s4m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv4 IP为:$WgcfIPv4" + rm -f warp64.sh +} + +install(){ + install_wireguard + [[ -z $(type -P wgcf) ]] && install_wgcf + register_wgcf + generate_wgcf_config + get_best_mtu + cpto_wireguard + start_wgcf +} + +check_tun +checkCentOS8 +install \ No newline at end of file diff --git a/wgcf_warp/warp6d.sh b/wgcf_warp/warp6d.sh new file mode 100644 index 00000000..761c19ac --- /dev/null +++ b/wgcf_warp/warp6d.sh @@ -0,0 +1,235 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -n $(type -P wg-quick) ]] && red "Wgcf-WARP已经安装,脚本即将退出" && rm -f warp6d.sh && exit 1 + +arch=`uname -m` +main=`uname -r | awk -F . '{print $1}'` +minor=`uname -r | awk -F . '{print $2}'` +vpsvirt=`systemd-detect-virt` + +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + if [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]]; then + if [[ $vpsvirt == "openvz" ]]; then + wget -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/tun-script/master/tun.sh && bash tun.sh + else + red "检测到未开启TUN模块,请到VPS控制面板处开启" + exit 1 + fi + fi +} + +checkCentOS8(){ + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +install_wireguard_centos(){ + ${PACKAGE_INSTALL[int]} epel-release + ${PACKAGE_INSTALL[int]} net-tools wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + vsid=`grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1` + curl -Lo /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-$vsid/jdoss-wireguard-epel-$vsid.repo + yum -y install epel-release wireguard-dkms + fi + fi +} + +install_wireguard_debian(){ + ${PACKAGE_INSTALL[int]} lsb-release + echo "deb http://deb.debian.org/debian $(lsb_release -sc)-backports main" | tee /etc/apt/sources.list.d/backports.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + ${PACKAGE_INSTALL} --no-install-recommends linux-headers-$(uname -r);apt -y --no-install-recommends install wireguard-dkms + fi + fi +} + +install_wireguard_ubuntu(){ + ${PACKAGE_INSTALL[int]} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables +} + +install_wireguard(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P sudo) ]] && ${PACKAGE_INSTALL[int]} sudo + [[ $SYSTEM == CentOS ]] && install_wireguard_centos + [[ $SYSTEM == Debian ]] && install_wireguard_debian + [[ $SYSTEM == Ubuntu ]] && install_wireguard_ubuntu + if [[ $vpsvirt =~ lxc|openvz ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi + if [[ $vpsvirt == zvm ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go-s390x -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi +} + +install_wgcf(){ + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "armv8" || $arch == "arm64" || $arch == "aarch64" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "s390x" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi +} + +register_wgcf(){ + rm -f wgcf-account.toml + until [[ -a wgcf-account.toml ]]; do + yellow "正在向CloudFlare WARP申请账号,如提示429 Too Many Requests错误请耐心等待即可" + yes | wgcf register + sleep 5 + done + chmod +x wgcf-account.toml +} + +generate_wgcf_config(){ + yellow "使用WARP免费版账户请按回车跳过 \n启用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + if [[ -n $WPPlusKey ]]; then + sed -i "s/license_key.*/license_key = \"$WPPlusKey\"/g" wgcf-account.toml + read -p "请输入自定义设备名,如未输入则使用默认随机设备名:" WPPlusName + green "注册WARP+账户中,如下方显示:400 Bad Request,则使用WARP免费版账户" + if [[ -n $WPPlusName ]]; then + wgcf update --name $(echo $WPPlusName | sed s/[[:space:]]/_/g) + else + wgcf update + fi + fi + wgcf generate + chmod +x wgcf-profile.conf + sed -i "7 s/^/PostUp = ip -6 rule add from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -6 rule delete from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/engage.cloudflareclient.com/[2606:4700:d0::a29f:c001]/g' wgcf-profile.conf + sed -i 's/1.1.1.1/2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844,1.1.1.1,8.8.8.8,8.8.4.4/g' wgcf-profile.conf +} + +get_best_mtu(){ + v66=`curl -s6m8 https://ip.gs -k` + v44=`curl -s4m8 https://ip.gs -k` + MTUy=1500 + MTUc=10 + if [[ -n ${v66} && -z ${v44} ]]; then + ping='ping6' + IP1='2606:4700:4700::1001' + IP2='2001:4860:4860::8888' + else + ping='ping' + IP1='1.1.1.1' + IP2='8.8.8.8' + fi + while true; do + if ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP1} >/dev/null 2>&1 || ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP2} >/dev/null 2>&1; then + MTUc=1 + MTUy=$((${MTUy} + ${MTUc})) + else + MTUy=$((${MTUy} - ${MTUc})) + if [[ ${MTUc} = 1 ]]; then + break + fi + fi + if [[ ${MTUy} -le 1360 ]]; then + MTUy='1360' + break + fi + done + MTU=$((${MTUy} - 80)) + green "MTU最佳值=$MTU 已设置完毕" + sed -i "s/MTU.*/MTU = $MTU/g" wgcf-profile.conf +} + +cpto_wireguard(){ + [[ $SYSTEM == "CentOS" ]] && mkdir /etc/wireguard >/dev/null 2>&1 + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml +} + +start_wgcf(){ + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] && [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv4=$(curl -s4m8 https://ip.gs -k) + WgcfIPv6=$(curl -s6m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv4 IP为:$WgcfIPv4" + yellow "Wgcf-WARP的IPv6 IP为:$WgcfIPv6" + rm -f warp6d.sh +} + +install(){ + install_wireguard + [[ -z $(type -P wgcf) ]] && install_wgcf + register_wgcf + generate_wgcf_config + get_best_mtu + cpto_wireguard + start_wgcf +} + +check_tun +checkCentOS8 +install \ No newline at end of file diff --git a/wgcf_warp/warpd.sh b/wgcf_warp/warpd.sh new file mode 100644 index 00000000..41b6358b --- /dev/null +++ b/wgcf_warp/warpd.sh @@ -0,0 +1,236 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -n $(type -P wg-quick) ]] && red "Wgcf-WARP已经安装,脚本即将退出" && rm -f warpd.sh && exit 1 + +arch=`uname -m` +main=`uname -r | awk -F . '{print $1}'` +minor=`uname -r | awk -F . '{print $2}'` +vpsvirt=`systemd-detect-virt` + +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + if [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]]; then + if [[ $vpsvirt == "openvz" ]]; then + wget -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/tun-script/master/tun.sh && bash tun.sh + else + red "检测到未开启TUN模块,请到VPS控制面板处开启" + exit 1 + fi + fi +} + +checkCentOS8(){ + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +install_wireguard_centos(){ + ${PACKAGE_INSTALL[int]} epel-release + ${PACKAGE_INSTALL[int]} net-tools wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + vsid=`grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1` + curl -Lo /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-$vsid/jdoss-wireguard-epel-$vsid.repo + yum -y install epel-release wireguard-dkms + fi + fi +} + +install_wireguard_debian(){ + ${PACKAGE_INSTALL[int]} lsb-release + echo "deb http://deb.debian.org/debian $(lsb_release -sc)-backports main" | tee /etc/apt/sources.list.d/backports.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + ${PACKAGE_INSTALL} --no-install-recommends linux-headers-$(uname -r);apt -y --no-install-recommends install wireguard-dkms + fi + fi +} + +install_wireguard_ubuntu(){ + ${PACKAGE_INSTALL[int]} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables +} + +install_wireguard(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P sudo) ]] && ${PACKAGE_INSTALL[int]} sudo + [[ $SYSTEM == CentOS ]] && install_wireguard_centos + [[ $SYSTEM == Debian ]] && install_wireguard_debian + [[ $SYSTEM == Ubuntu ]] && install_wireguard_ubuntu + if [[ $vpsvirt =~ lxc|openvz ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi + if [[ $vpsvirt == zvm ]]; then + wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireguard-go-s390x -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi +} + +install_wgcf(){ + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "armv8" || $arch == "arm64" || $arch == "aarch64" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "s390x" ]]; then + wget -N --no-check-certificate https://github.com/ViRb3/wgcf/releases/download/v2.2.13/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf || wget -N --no-check-certificate https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi +} + +register_wgcf(){ + rm -f wgcf-account.toml + until [[ -a wgcf-account.toml ]]; do + yellow "正在向CloudFlare WARP申请账号,如提示429 Too Many Requests错误请耐心等待即可" + yes | wgcf register + sleep 5 + done + chmod +x wgcf-account.toml +} + +generate_wgcf_config(){ + yellow "使用WARP免费版账户请按回车跳过 \n启用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + if [[ -n $WPPlusKey ]]; then + sed -i "s/license_key.*/license_key = \"$WPPlusKey\"/g" wgcf-account.toml + read -p "请输入自定义设备名,如未输入则使用默认随机设备名:" WPPlusName + green "注册WARP+账户中,如下方显示:400 Bad Request,则使用WARP免费版账户" + if [[ -n $WPPlusName ]]; then + wgcf update --name $(echo $WPPlusName | sed s/[[:space:]]/_/g) + else + wgcf update + fi + fi + wgcf generate + chmod +x wgcf-profile.conf + sed -i "7 s/^/PostUp = ip -4 rule add from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "8 s/^/PostDown = ip -4 rule delete from $(ip route get 114.114.114.114 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "9 s/^/PostUp = ip -6 rule add from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i "10 s/^/PostDown = ip -6 rule delete from $(ip route get 2400:3200::1 | grep -oP 'src \K\S+') lookup main\n/" wgcf-profile.conf + sed -i 's/1.1.1.1/1.1.1.1,8.8.8.8,8.8.4.4,2606:4700:4700::1001,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844/g' wgcf-profile.conf +} + +get_best_mtu(){ + v66=`curl -s6m8 https://ip.gs -k` + v44=`curl -s4m8 https://ip.gs -k` + MTUy=1500 + MTUc=10 + if [[ -n ${v66} && -z ${v44} ]]; then + ping='ping6' + IP1='2606:4700:4700::1001' + IP2='2001:4860:4860::8888' + else + ping='ping' + IP1='1.1.1.1' + IP2='8.8.8.8' + fi + while true; do + if ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP1} >/dev/null 2>&1 || ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP2} >/dev/null 2>&1; then + MTUc=1 + MTUy=$((${MTUy} + ${MTUc})) + else + MTUy=$((${MTUy} - ${MTUc})) + if [[ ${MTUc} = 1 ]]; then + break + fi + fi + if [[ ${MTUy} -le 1360 ]]; then + MTUy='1360' + break + fi + done + MTU=$((${MTUy} - 80)) + green "MTU最佳值=$MTU 已设置完毕" + sed -i "s/MTU.*/MTU = $MTU/g" wgcf-profile.conf +} + +cpto_wireguard(){ + [[ $SYSTEM == "CentOS" ]] && mkdir /etc/wireguard >/dev/null 2>&1 + mv -f wgcf-profile.conf /etc/wireguard/wgcf.conf + mv -f wgcf-account.toml /etc/wireguard/wgcf-account.toml +} + +start_wgcf(){ + yellow "正在启动 Wgcf-WARP" + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + until [[ $WgcfWARP4Status =~ on|plus ]] && [[ $WgcfWARP6Status =~ on|plus ]]; do + red "无法启动Wgcf-WARP,正在尝试重启" + wg-quick down wgcf >/dev/null 2>&1 + wg-quick up wgcf >/dev/null 2>&1 + WgcfWARP4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + WgcfWARP6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wg-quick@wgcf >/dev/null 2>&1 + WgcfIPv4=$(curl -s4m8 https://ip.gs -k) + WgcfIPv6=$(curl -s6m8 https://ip.gs -k) + green "Wgcf-WARP 已启动成功" + yellow "Wgcf-WARP的IPv4 IP为:$WgcfIPv4" + yellow "Wgcf-WARP的IPv6 IP为:$WgcfIPv6" + rm -f warpd.sh +} + +install(){ + install_wireguard + [[ -z $(type -P wgcf) ]] && install_wgcf + register_wgcf + generate_wgcf_config + get_best_mtu + cpto_wireguard + start_wgcf +} + +check_tun +checkCentOS8 +install \ No newline at end of file diff --git a/wgs.sh b/wgs.sh new file mode 100644 index 00000000..1b19b01b --- /dev/null +++ b/wgs.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 + +check_tun(){ + TUN=$(cat /dev/net/tun 2>&1 | tr '[:upper:]' '[:lower:]') + if [[ ! $TUN =~ 'in bad state' ]] && [[ ! $TUN =~ '处于错误状态' ]] && [[ ! $TUN =~ 'Die Dateizugriffsnummer ist in schlechter Verfassung' ]]; then + if [[ $vpsvirt == "openvz" ]]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/tun-script/master/tun.sh && bash tun.sh + else + red "检测到未开启TUN模块,请到VPS控制面板处开启" + exit 1 + fi + fi +} + +checkCentOS8(){ + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +install_wireguard_centos(){ + ${PACKAGE_INSTALL[int]} epel-release + ${PACKAGE_INSTALL[int]} net-tools wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + vsid=`grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1` + curl -Lo /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-$vsid/jdoss-wireguard-epel-$vsid.repo + yum -y install epel-release wireguard-dkms + fi + fi +} + +install_wireguard_debian(){ + ${PACKAGE_INSTALL[int]} lsb-release + echo "deb http://deb.debian.org/debian $(lsb_release -sc)-backports main" | tee /etc/apt/sources.list.d/backports.list + ${PACKAGE_UPDATE[int]} + ${PACKAGE_INSTALL} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables + if [ "$main" -lt 5 ] || [ "$minor" -lt 6 ]; then + if [[ ${vpsvirt} == "kvm" || ${vpsvirt} == "xen" || ${vpsvirt} == "microsoft" ]]; then + ${PACKAGE_INSTALL} --no-install-recommends linux-headers-$(uname -r);apt -y --no-install-recommends install wireguard-dkms + fi + fi +} + +install_wireguard_ubuntu(){ + ${PACKAGE_INSTALL[int]} --no-install-recommends net-tools iproute2 openresolv dnsutils wireguard-tools iptables +} + +install_wireguard(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P sudo) ]] && ${PACKAGE_INSTALL[int]} sudo + [[ $SYSTEM == CentOS ]] && install_wireguard_centos + [[ $SYSTEM == Debian ]] && install_wireguard_debian + [[ $SYSTEM == Ubuntu ]] && install_wireguard_ubuntu + if [[ $vpsvirt =~ lxc|openvz ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/wireguard-go -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi + if [[ $vpsvirt == zvm ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/wireguard-go-s390x -O /usr/bin/wireguard-go + chmod +x /usr/bin/wireguard-go + fi +} \ No newline at end of file diff --git a/wireproxy_wgcf/1.conf b/wireproxy_wgcf/1.conf new file mode 100644 index 00000000..9e0ab51e --- /dev/null +++ b/wireproxy_wgcf/1.conf @@ -0,0 +1,8 @@ +SelfSecretKey = yPXRdwUvtiFhIN38PuHF3C1proIjPG+GWzyAvmeiemw= +SelfEndpoint = 172.16.0.2 +PeerPublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo= +PeerEndpoint = 162.159.192.1:2408 +DNS = 1.1.1.1,8.8.8.8,8.8.4.4 + +[Socks5] +BindAddress = 127.0.0.1:25344 \ No newline at end of file diff --git a/wireproxy_wgcf/changeport.sh b/wireproxy_wgcf/changeport.sh new file mode 100644 index 00000000..8c6ecb6f --- /dev/null +++ b/wireproxy_wgcf/changeport.sh @@ -0,0 +1,55 @@ +#!/bin/bash +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P wireproxy) ]] && red "WireProxy-WARP代理模式未安装,脚本即将退出!" && rm -f changeport.sh && exit 1 + +changeport(){ + systemctl stop wireproxy-warp + read -p "请输入WARP Cli使用的代理端口(默认40000):" WireProxyPort + [[ -z $WireProxyPort ]] && WireProxyPort=40000 + CurrentPort=$(grep BindAddress /root/WireProxy_WARP.conf) + sed -i "s/$CurrentPort/BindAddress = 127.0.0.1:$WireProxyPort/g" /root/WireProxy_WARP.conf + yellow "正在启动WireProxy-WARP代理模式" + systemctl start wireproxy-warp + socks5Status=$(curl -sx socks5h://localhost:$WireProxyPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 8 | grep warp | cut -d= -f2) + until [[ $socks5Status =~ on|plus ]]; do + red "启动WireProxy-WARP代理模式失败,正在尝试重启" + systemctl stop wireproxy-warp + systemctl start wireproxy-warp + socks5Status=$(curl -sx socks5h://localhost:$WireProxyPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 8 | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wireproxy-warp + green "WireProxy-WARP代理模式已启动成功!" + yellow "本地Socks5代理为: 127.0.0.1:$WireProxyPort" + rm -f changeport.sh +} + +changeport \ No newline at end of file diff --git a/wireproxy_wgcf/netfilx-wireproxy.sh b/wireproxy_wgcf/netfilx-wireproxy.sh new file mode 100644 index 00000000..af44a3f4 --- /dev/null +++ b/wireproxy_wgcf/netfilx-wireproxy.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P wireproxy) ]] && red "WireProxy-WARP代理模式未安装,脚本即将退出!" && rm -f wireproxy-netfilx.sh && exit 1 + +WireProxyPort=$(grep BindAddress /root/WireProxy_WARP.conf 2>/dev/null | sed "s/BindAddress = 127.0.0.1://g") + +check(){ + NetfilxStatus=$(curl -sx socks5h://localhost:$WireProxyPort -fsL --write-out %{http_code} --output /dev/null --max-time 10 "https://www.netflix.com/title/81215567" 2>&1) + if [[ $NetfilxStatus == "200" ]]; then + success + fi + if [[ $NetfilxStatus =~ "403"|"404" ]]; then + failed + fi + if [[ -z $NetfilxStatus ]] || [[ $NetfilxStatus == "000" ]]; then + retry + fi +} + +retry(){ + systemctl stop wireproxy-warp + systemctl start wireproxy-warp + check +} + +success(){ + WireProxyIP=$(curl -sx socks5h://localhost:$WireProxyPort https://ip.gs -k --connect-timeout 8) + green "当前WireProxy-WARP的IP:$WireProxyIP 已解锁Netfilx" + yellow "等待1小时后,脚本将会自动重新检查Netfilx解锁状态" + sleep 1h + check +} + +failed(){ + WireProxyIP=$(curl -sx socks5h://localhost:$WireProxyPort https://ip.gs -k --connect-timeout 8) + red "当前WireProxy-WARP的IP:$WireProxyIP 未解锁Netfilx,脚本将在15秒后重新测试Netfilx解锁情况" + sleep 15 + systemctl stop wireproxy-warp + systemctl start wireproxy-warp + check +} + +check diff --git a/wireproxy_wgcf/uninstall.sh b/wireproxy_wgcf/uninstall.sh new file mode 100644 index 00000000..9ec172bd --- /dev/null +++ b/wireproxy_wgcf/uninstall.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -z $(type -P wireproxy) ]] && red "WireProxy-WARP代理模式未安装,脚本即将退出" && rm -f uninstall.sh && exit 1 + +uninstall(){ + systemctl stop wireproxy-warp + systemctl disable wireproxy-warp + rm -f /etc/systemd/system/wireproxy-warp.service + rm -f /usr/local/bin/wireproxy + [[ ! -f /etc/wireguard/wgcf.conf ]] && rm -f /usr/local/bin/wgcf + green "WARP-Cli代理模式已彻底卸载成功!" + rm -f uninstall.sh +} + +uninstall diff --git a/wireproxy_wgcf/warp4.sh b/wireproxy_wgcf/warp4.sh new file mode 100644 index 00000000..1ceaff15 --- /dev/null +++ b/wireproxy_wgcf/warp4.sh @@ -0,0 +1,202 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -n $(type -P wireproxy) ]] && red "WireProxy-WARP代理模式已经安装,脚本即将退出" && rm -f warp4d.sh && exit 1 + +arch=`uname -m` +main=`uname -r | awk -F . '{print $1}'` +minor=`uname -r | awk -F . '{print $2}'` +vpsvirt=`systemd-detect-virt` + +install_wgcf(){ + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "armv8" || $arch == "arm64" || $arch == "aarch64" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "s390x" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi +} + +register_wgcf(){ + rm -f wgcf-account.toml + until [[ -a wgcf-account.toml ]]; do + yellow "正在向CloudFlare WARP申请账号,如提示429 Too Many Requests错误请耐心等待即可" + yes | wgcf register + sleep 5 + done + chmod +x wgcf-account.toml +} + +generate_wgcf_config(){ + yellow "使用WARP免费版账户请按回车跳过 \n启用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + if [[ -n $WPPlusKey ]]; then + sed -i "s/license_key.*/license_key = \"$WPPlusKey\"/g" wgcf-account.toml + read -p "请输入自定义设备名,如未输入则使用默认随机设备名:" WPPlusName + green "注册WARP+账户中,如下方显示:400 Bad Request,则使用WARP免费版账户" + if [[ -n $WPPlusName ]]; then + wgcf update --name $(echo $WPPlusName | sed s/[[:space:]]/_/g) + else + wgcf update + fi + fi + wgcf generate + chmod +x wgcf-profile.conf +} + +get_best_mtu(){ + v66=`curl -s6m8 https://ip.gs -k` + v44=`curl -s4m8 https://ip.gs -k` + MTUy=1500 + MTUc=10 + if [[ -n ${v66} && -z ${v44} ]]; then + ping='ping6' + IP1='2606:4700:4700::1001' + IP2='2001:4860:4860::8888' + else + ping='ping' + IP1='1.1.1.1' + IP2='8.8.8.8' + fi + while true; do + if ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP1} >/dev/null 2>&1 || ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP2} >/dev/null 2>&1; then + MTUc=1 + MTUy=$((${MTUy} + ${MTUc})) + else + MTUy=$((${MTUy} - ${MTUc})) + if [[ ${MTUc} = 1 ]]; then + break + fi + fi + if [[ ${MTUy} -le 1360 ]]; then + MTUy='1360' + break + fi + done + MTU=$((${MTUy} - 80)) + green "MTU最佳值=$MTU 已设置完毕" + sed -i "s/MTU.*/MTU = $MTU/g" wgcf-profile.conf +} + +make_wireproxy_file(){ + read -p "请输入将要设置的Socks5端口(默认40000):" WireProxyPort + [[ -z $WireProxyPort ]] && WireProxyPort=40000 + WgcfPrivateKey=$(grep PrivateKey wgcf-profile.conf | sed "s/PrivateKey = //g") + WgcfPublicKey=$(grep PublicKey wgcf-profile.conf | sed "s/PublicKey = //g") + cat < ~/WireProxy_WARP.conf +[Interface] +Address = 172.16.0.2/32 +MTU = $MTU +PrivateKey = $WgcfPrivateKey +DNS = 1.1.1.1,8.8.8.8,8.8.4.4 + +[Peer] +PublicKey = $WgcfPublicKey +Endpoint = 162.159.193.10:2408 + +[Socks5] +BindAddress = 127.0.0.1:$WireProxyPort +EOF + green "WireProxy-WARP代理模式配置文件已生成成功!" + yellow "已保存到 /root/WireProxy_WARP.conf" + cat <<'TEXT' > /etc/systemd/system/wireproxy-warp.service +[Unit] +Description=CloudFlare WARP based for WireProxy, script by owo.misaka.rest +After=network.target +[Install] +WantedBy=multi-user.target +[Service] +Type=simple +WorkingDirectory=/root +ExecStart=/usr/local/bin/wireproxy -c /root/WireProxy_WARP.conf +Restart=always +TEXT + green "Systemd 系统守护服务设置成功!" + rm -f wgcf-profile.conf + rm -f wgcf-account.toml +} + +download_wireproxy(){ + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireproxy-amd64 -O /usr/local/bin/wireproxy + chmod +x /usr/local/bin/wireproxy + fi + if [[ $arch == "armv8" || $arch == "arm64" || $arch == "aarch64" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireproxy-arm64 -O /usr/local/bin/wireproxy + chmod +x /usr/local/bin/wireproxy + fi + if [[ $arch == "s390x" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireproxy-s390x -O /usr/local/bin/wireproxy + chmod +x /usr/local/bin/wireproxy + fi +} + +start_wireproxy_warp(){ + yellow "正在启动WireProxy-WARP代理模式" + systemctl start wireproxy-warp + socks5Status=$(curl -sx socks5h://localhost:$WireProxyPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 8 | grep warp | cut -d= -f2) + until [[ $socks5Status =~ on|plus ]]; do + red "启动WireProxy-WARP代理模式失败,正在尝试重启" + systemctl stop wireproxy-warp + systemctl start wireproxy-warp + socks5Status=$(curl -sx socks5h://localhost:$WireProxyPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 8 | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wireproxy-warp + socks5IP=$(curl -sx socks5h://localhost:$WireProxyPort https://ip.gs -k --connect-timeout 8) + green "WireProxy-WARP代理模式已启动成功!" + yellow "本地Socks5代理为: 127.0.0.1:$WireProxyPort" + yellow "WireProxy-WARP代理模式的IP为:$socks5IP" + rm -f warp4.sh +} + +install(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P sudo) ]] && ${PACKAGE_INSTALL[int]} sudo + [[ -z $(type -P wgcf) ]] && install_wgcf + register_wgcf + generate_wgcf_config + get_best_mtu + make_wireproxy_file + download_wireproxy + start_wireproxy_warp +} + +install diff --git a/wireproxy_wgcf/warp6.sh b/wireproxy_wgcf/warp6.sh new file mode 100644 index 00000000..fcb3a142 --- /dev/null +++ b/wireproxy_wgcf/warp6.sh @@ -0,0 +1,202 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS的系统,请使用主流操作系统" && exit 1 +[[ -n $(type -P wireproxy) ]] && red "WireProxy-WARP代理模式已经安装,脚本即将退出" && rm -f warp4d.sh && exit 1 + +arch=`uname -m` +main=`uname -r | awk -F . '{print $1}'` +minor=`uname -r | awk -F . '{print $2}'` +vpsvirt=`systemd-detect-virt` + +install_wgcf(){ + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_amd64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "armv8" || $arch == "arm64" || $arch == "aarch64" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_arm64 -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi + if [[ $arch == "s390x" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wgcf_2.2.13_linux_s390x -O /usr/local/bin/wgcf + chmod +x /usr/local/bin/wgcf + fi +} + +register_wgcf(){ + rm -f wgcf-account.toml + until [[ -a wgcf-account.toml ]]; do + yellow "正在向CloudFlare WARP申请账号,如提示429 Too Many Requests错误请耐心等待即可" + yes | wgcf register + sleep 5 + done + chmod +x wgcf-account.toml +} + +generate_wgcf_config(){ + yellow "使用WARP免费版账户请按回车跳过 \n启用WARP+账户,请复制WARP+的许可证密钥(26个字符)后回车" + read -p "按键许可证密钥(26个字符):" WPPlusKey + if [[ -n $WPPlusKey ]]; then + sed -i "s/license_key.*/license_key = \"$WPPlusKey\"/g" wgcf-account.toml + read -p "请输入自定义设备名,如未输入则使用默认随机设备名:" WPPlusName + green "注册WARP+账户中,如下方显示:400 Bad Request,则使用WARP免费版账户" + if [[ -n $WPPlusName ]]; then + wgcf update --name $(echo $WPPlusName | sed s/[[:space:]]/_/g) + else + wgcf update + fi + fi + wgcf generate + chmod +x wgcf-profile.conf +} + +get_best_mtu(){ + v66=`curl -s6m8 https://ip.gs -k` + v44=`curl -s4m8 https://ip.gs -k` + MTUy=1500 + MTUc=10 + if [[ -n ${v66} && -z ${v44} ]]; then + ping='ping6' + IP1='2606:4700:4700::1001' + IP2='2001:4860:4860::8888' + else + ping='ping' + IP1='1.1.1.1' + IP2='8.8.8.8' + fi + while true; do + if ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP1} >/dev/null 2>&1 || ${ping} -c1 -W1 -s$((${MTUy} - 28)) -Mdo ${IP2} >/dev/null 2>&1; then + MTUc=1 + MTUy=$((${MTUy} + ${MTUc})) + else + MTUy=$((${MTUy} - ${MTUc})) + if [[ ${MTUc} = 1 ]]; then + break + fi + fi + if [[ ${MTUy} -le 1360 ]]; then + MTUy='1360' + break + fi + done + MTU=$((${MTUy} - 80)) + green "MTU最佳值=$MTU 已设置完毕" + sed -i "s/MTU.*/MTU = $MTU/g" wgcf-profile.conf +} + +make_wireproxy_file(){ + read -p "请输入将要设置的Socks5端口(默认40000):" WireProxyPort + [[ -z $WireProxyPort ]] && WireProxyPort=40000 + WgcfPrivateKey=$(grep PrivateKey wgcf-profile.conf | sed "s/PrivateKey = //g") + WgcfPublicKey=$(grep PublicKey wgcf-profile.conf | sed "s/PublicKey = //g") + cat < ~/WireProxy_WARP.conf +[Interface] +Address = 172.16.0.2/32 +MTU = $MTU +PrivateKey = $WgcfPrivateKey +DNS = 1.1.1.1,8.8.8.8,8.8.4.4 + +[Peer] +PublicKey = $WgcfPublicKey +Endpoint = [2606:4700:d0::a29f:c001]:2408 + +[Socks5] +BindAddress = 127.0.0.1:$WireProxyPort +EOF + green "WireProxy-WARP代理模式配置文件已生成成功!" + yellow "已保存到 /root/WireProxy_WARP.conf" + cat <<'TEXT' > /etc/systemd/system/wireproxy-warp.service +[Unit] +Description=CloudFlare WARP based for WireProxy, script by owo.misaka.rest +After=network.target +[Install] +WantedBy=multi-user.target +[Service] +Type=simple +WorkingDirectory=/root +ExecStart=/usr/local/bin/wireproxy -c /root/WireProxy_WARP.conf +Restart=always +TEXT + green "Systemd 系统守护服务设置成功!" + rm -f wgcf-profile.conf + rm -f wgcf-account.toml +} + +download_wireproxy(){ + if [[ $arch == "amd64" || $arch == "x86_64" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireproxy-amd64 -O /usr/local/bin/wireproxy + chmod +x /usr/local/bin/wireproxy + fi + if [[ $arch == "armv8" || $arch == "arm64" || $arch == "aarch64" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireproxy-arm64 -O /usr/local/bin/wireproxy + chmod +x /usr/local/bin/wireproxy + fi + if [[ $arch == "s390x" ]]; then + wget -N https://cdn.jsdelivr.net/gh/Misaka-blog/Misaka-WARP-Script/files/wireproxy-s390x -O /usr/local/bin/wireproxy + chmod +x /usr/local/bin/wireproxy + fi +} + +start_wireproxy_warp(){ + yellow "正在启动WireProxy-WARP代理模式" + systemctl start wireproxy-warp + socks5Status=$(curl -sx socks5h://localhost:$WireProxyPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 8 | grep warp | cut -d= -f2) + until [[ $socks5Status =~ on|plus ]]; do + red "启动WireProxy-WARP代理模式失败,正在尝试重启" + systemctl stop wireproxy-warp + systemctl start wireproxy-warp + socks5Status=$(curl -sx socks5h://localhost:$WireProxyPort https://www.cloudflare.com/cdn-cgi/trace -k --connect-timeout 8 | grep warp | cut -d= -f2) + sleep 8 + done + systemctl enable wireproxy-warp + socks5IP=$(curl -sx socks5h://localhost:$WireProxyPort ip.gs -k --connect-timeout 8) + green "WireProxy-WARP代理模式已启动成功!" + yellow "本地Socks5代理为: 127.0.0.1:$WireProxyPort" + yellow "WireProxy-WARP代理模式的IP为:$socks5IP" + rm -f warp6.sh +} + +install(){ + ${PACKAGE_UPDATE[int]} + [[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P sudo) ]] && ${PACKAGE_INSTALL[int]} sudo + [[ -z $(type -P wgcf) ]] && install_wgcf + register_wgcf + generate_wgcf_config + get_best_mtu + make_wireproxy_file + download_wireproxy + start_wireproxy_warp +} + +install diff --git a/x-ui/install.sh b/x-ui/install.sh new file mode 100644 index 00000000..e1975d2e --- /dev/null +++ b/x-ui/install.sh @@ -0,0 +1,188 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +arch=$(arch) +os_version=$(grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1) + +if [[ $arch == "x86_64" || $arch == "x64" || $arch == "amd64" ]]; then + arch="amd64" +elif [[ $arch == "aarch64" || $arch == "arm64" ]]; then + arch="arm64" +elif [[ $arch == "s390x" ]]; then + arch="s390x" +else + echo -e "不支持的CPU架构!脚本将自动退出!" + rm -f install.sh + exit 1 +fi + +if [ $(getconf WORD_BIT) != '32' ] && [ $(getconf LONG_BIT) != '64' ]; then + echo "X-ui面板不支持 32 位系统(x86),请使用 64 位系统(x86_64),如果检测有误,请联系作者" + rm -f install.sh + exit -1 +fi + +if [[ $SYSTEM == "CentOS" ]]; then + if [[ ${os_version} -le 6 ]]; then + echo -e "请使用 CentOS 7 或更高版本的系统!\n" && exit 1 + fi +elif [[ $SYSTEM == "Ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + echo -e "请使用 Ubuntu 16 或更高版本的系统!\n" && exit 1 + fi +elif [[ $SYSTEM == "Debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + echo -e "请使用 Debian 8 或更高版本的系统!\n" && exit 1 + fi +fi + +${PACKAGE_UPDATE[int]} +[[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl +[[ -z $(type -P tar) ]] && ${PACKAGE_INSTALL[int]} tar + +checkCentOS8(){ + if [[ -n $(cat /etc/os-release | grep "CentOS Linux 8") ]]; then + yellow "检测到当前VPS系统为CentOS 8,是否升级为CentOS Stream 8以确保软件包正常安装?" + read -p "请输入选项 [y/n]:" comfirmCentOSStream + if [[ $comfirmCentOSStream == "y" ]]; then + yellow "正在为你升级到CentOS Stream 8,大概需要10-30分钟的时间" + sleep 1 + sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-* + yum clean all && yum makecache + dnf swap centos-linux-repos centos-stream-repos distro-sync -y + else + red "已取消升级过程,脚本即将退出!" + exit 1 + fi + fi +} + +config_after_install() { + yellow "出于安全考虑,安装/更新完成后需要强制修改端口与账户密码" + read -p "确认是否继续?[y/n]": config_confirm + if [[ x"${config_confirm}" == x"y" || x"${config_confirm}" == x"Y" ]]; then + read -p "请设置您的账户名:" config_account + read -p "请设置您的账户密码:" config_password + read -p "请设置面板访问端口:" config_port + yellow "请核对面板登录信息是否正确:" + green "您的账户名将设定为:${config_account}" + green "您的账户密码将设定为:${config_password}" + green "您的面板访问端口将设定为:${config_port}" + read -p "确认设定完成?[y/n]": config_confirm + if [[ x"${config_confirm}" == x"y" || x"${config_confirm}" == x"Y" ]]; then + yellow "确认设定,正在设定中" + /usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} + /usr/local/x-ui/x-ui setting -port ${config_port} + else + red "已取消,所有设置项均为默认设置,请及时修改" + fi + else + red "已取消,所有设置项均为默认设置,请及时修改" + fi +} + +download_x-ui(){ + if [ $# == 0 ]; then + last_version=$(curl -Ls "https://api.github.com/repos/Misaka-blog/x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + if [[ ! -n "$last_version" ]]; then + red "检测 x-ui 版本失败,可能是超出 Github API 限制,请稍后再试,或手动指定 x-ui 版本安装" + rm -f install.sh + exit 1 + fi + yellow "检测到 x-ui 最新版本:${last_version},开始安装" + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz https://github.com/Misaka-blog/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz + if [[ $? -ne 0 ]]; then + red "下载 x-ui 失败,请确保你的服务器能够连接并下载 Github 的文件" + rm -f install.sh + exit 1 + fi + else + last_version=$1 + url="https://github.com/Misaka-blog/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz" + yellow "开始安装 x-ui v$1" + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz ${url} + if [[ $? -ne 0 ]]; then + red "下载 x-ui v$1 失败,请确保此版本存在" + rm -f install.sh + exit 1 + fi + fi +} + +install_x-ui() { + systemctl stop x-ui + if [[ -e /usr/local/x-ui/ ]]; then + rm -rf /usr/local/x-ui/ + fi + download_x-ui + cd /usr/local/ + tar zxvf x-ui-linux-${arch}.tar.gz + rm x-ui-linux-${arch}.tar.gz -f + cd x-ui + chmod +x x-ui bin/xray-linux-${arch} + cp -f x-ui.service /etc/systemd/system/ + wget --no-check-certificate -O /usr/bin/x-ui https://raw.githubusercontents.com/Misaka-blog/x-ui/main/x-ui.sh + chmod +x /usr/local/x-ui/x-ui.sh + chmod +x /usr/bin/x-ui + config_after_install + systemctl daemon-reload + systemctl enable x-ui + systemctl start x-ui + cd /root + rm -f install.sh + showInfo +} + +showInfo(){ + green "x-ui v${last_version} 安装完成,面板已启动" + echo -e "" + echo -e "x-ui 管理脚本使用方法: " + echo -e "----------------------------------------------" + echo -e "x-ui - 显示管理菜单 (功能更多)" + echo -e "x-ui start - 启动 x-ui 面板" + echo -e "x-ui stop - 停止 x-ui 面板" + echo -e "x-ui restart - 重启 x-ui 面板" + echo -e "x-ui status - 查看 x-ui 状态" + echo -e "x-ui enable - 设置 x-ui 开机自启" + echo -e "x-ui disable - 取消 x-ui 开机自启" + echo -e "x-ui log - 查看 x-ui 日志" + echo -e "x-ui v2-ui - 迁移本机器的 v2-ui 账号数据至 x-ui" + echo -e "x-ui update - 更新 x-ui 面板" + echo -e "x-ui install - 安装 x-ui 面板" + echo -e "x-ui uninstall - 卸载 x-ui 面板" + echo -e "----------------------------------------------" +} + +checkCentOS8 +install_x-ui $1 \ No newline at end of file diff --git a/x-ui/install1.sh b/x-ui/install1.sh new file mode 100644 index 00000000..bcc2c0f3 --- /dev/null +++ b/x-ui/install1.sh @@ -0,0 +1,181 @@ +#!/bin/bash + +red='\033[0;31m' +green='\033[0;32m' +yellow='\033[0;33m' +plain='\033[0m' + +cur_dir=$(pwd) + +# check root +[[ $EUID -ne 0 ]] && echo -e "${red}错误:${plain} 必须使用root用户运行此脚本!\n" && exit 1 + +# check os +if [[ -f /etc/redhat-release ]]; then + release="centos" +elif cat /etc/issue | grep -Eqi "debian"; then + release="debian" +elif cat /etc/issue | grep -Eqi "ubuntu"; then + release="ubuntu" +elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then + release="centos" +elif cat /proc/version | grep -Eqi "debian"; then + release="debian" +elif cat /proc/version | grep -Eqi "ubuntu"; then + release="ubuntu" +elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then + release="centos" +else + echo -e "${red}未检测到系统版本,请联系脚本作者!${plain}\n" && exit 1 +fi + +arch=$(arch) + +if [[ $arch == "x86_64" || $arch == "x64" || $arch == "amd64" ]]; then + arch="amd64" +elif [[ $arch == "aarch64" || $arch == "arm64" ]]; then + arch="arm64" +elif [[ $arch == "s390x" ]]; then + arch="s390x" +else + echo -e "${red}不支持的CPU架构!脚本将自动退出 ${arch}${plain}" + rm -f install.sh + exit 1 +fi + +echo "架构: ${arch}" + +if [ $(getconf WORD_BIT) != '32' ] && [ $(getconf LONG_BIT) != '64' ]; then + echo "本软件不支持 32 位系统(x86),请使用 64 位系统(x86_64),如果检测有误,请联系作者" + rm -f install.sh + exit -1 +fi + +os_version="" + +# os version +if [[ -f /etc/os-release ]]; then + os_version=$(awk -F'[= ."]' '/VERSION_ID/{print $3}' /etc/os-release) +fi +if [[ -z "$os_version" && -f /etc/lsb-release ]]; then + os_version=$(awk -F'[= ."]+' '/DISTRIB_RELEASE/{print $2}' /etc/lsb-release) +fi + +if [[ x"${release}" == x"centos" ]]; then + if [[ ${os_version} -le 6 ]]; then + echo -e "${red}请使用 CentOS 7 或更高版本的系统!${plain}\n" && exit 1 + fi +elif [[ x"${release}" == x"ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + echo -e "${red}请使用 Ubuntu 16 或更高版本的系统!${plain}\n" && exit 1 + fi +elif [[ x"${release}" == x"debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + echo -e "${red}请使用 Debian 8 或更高版本的系统!${plain}\n" && exit 1 + fi +fi + +install_base() { + if [[ x"${release}" == x"centos" ]]; then + yum install wget curl tar -y + else + apt install wget curl tar -y + fi +} + +#This function will be called when user installed x-ui out of sercurity +config_after_install() { + echo -e "${yellow}出于安全考虑,安装完成后需要强制修改端口与账户密码${plain}" + read -p "请设置您的账户名:" config_account + echo -e "${yellow}您的账户名将设定为:${config_account}${plain}" + read -p "请设置您的账户密码:" config_password + echo -e "${yellow}您的账户密码将设定为:${config_password}${plain}" + read -p "请设置面板访问端口:" config_port + echo -e "${yellow}您的面板访问端口将设定为:${config_port}${plain}" + read -p "确认设定完成?[y/n]": config_confirm + if [[ x"${config_confirm}" == x"y" || x"${config_confirm}" == x"Y" ]]; then + echo -e "${yellow}确认设定,设定中${plain}" + /usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} + echo -e "${yellow}账户密码设定完成${plain}" + /usr/local/x-ui/x-ui setting -port ${config_port} + echo -e "${yellow}面板端口设定完成${plain}" + else + echo -e "${red}已取消,所有设置项均为默认设置,请及时修改${plain}" + fi +} + +install_x-ui() { + systemctl stop x-ui + cd /usr/local/ + + if [ $# == 0 ]; then + last_version=$(curl -Ls "https://api.github.com/repos/Misaka-blog/x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + if [[ ! -n "$last_version" ]]; then + echo -e "${red}检测 x-ui 版本失败,可能是超出 Github API 限制,请稍后再试,或手动指定 x-ui 版本安装${plain}" + rm -f install.sh + exit 1 + fi + echo -e "检测到 x-ui 最新版本:${last_version},开始安装" + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz https://github.com/Misaka-blog/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz + if [[ $? -ne 0 ]]; then + echo -e "${red}下载 x-ui 失败,请确保你的服务器能够下载 Github 的文件${plain}" + rm -f install.sh + exit 1 + fi + else + last_version=$1 + url="https://github.com/Misaka-blog/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz" + echo -e "开始安装 x-ui v$1" + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz ${url} + if [[ $? -ne 0 ]]; then + echo -e "${red}下载 x-ui v$1 失败,请确保此版本存在${plain}" + rm -f install.sh + exit 1 + fi + fi + + if [[ -e /usr/local/x-ui/ ]]; then + rm /usr/local/x-ui/ -rf + fi + + tar zxvf x-ui-linux-${arch}.tar.gz + rm x-ui-linux-${arch}.tar.gz -f + cd x-ui + chmod +x x-ui bin/xray-linux-${arch} + cp -f x-ui.service /etc/systemd/system/ + wget --no-check-certificate -O /usr/bin/x-ui https://raw.githubusercontent.com/Misaka-blog/x-ui/main/x-ui.sh + chmod +x /usr/local/x-ui/x-ui.sh + chmod +x /usr/bin/x-ui + config_after_install + #echo -e "如果是全新安装,默认网页端口为 ${green}54321${plain},用户名和密码默认都是 ${green}admin${plain}" + #echo -e "请自行确保此端口没有被其他程序占用,${yellow}并且确保 54321 端口已放行${plain}" + # echo -e "若想将 54321 修改为其它端口,输入 x-ui 命令进行修改,同样也要确保你修改的端口也是放行的" + #echo -e "" + #echo -e "如果是更新面板,则按你之前的方式访问面板" + #echo -e "" + systemctl daemon-reload + systemctl enable x-ui + systemctl start x-ui + echo -e "${green}x-ui v${last_version}${plain} 安装完成,面板已启动," + echo -e "" + echo -e "x-ui 管理脚本使用方法: " + echo -e "----------------------------------------------" + echo -e "x-ui - 显示管理菜单 (功能更多)" + echo -e "x-ui start - 启动 x-ui 面板" + echo -e "x-ui stop - 停止 x-ui 面板" + echo -e "x-ui restart - 重启 x-ui 面板" + echo -e "x-ui status - 查看 x-ui 状态" + echo -e "x-ui enable - 设置 x-ui 开机自启" + echo -e "x-ui disable - 取消 x-ui 开机自启" + echo -e "x-ui log - 查看 x-ui 日志" + echo -e "x-ui v2-ui - 迁移本机器的 v2-ui 账号数据至 x-ui" + echo -e "x-ui update - 更新 x-ui 面板" + echo -e "x-ui install - 安装 x-ui 面板" + echo -e "x-ui uninstall - 卸载 x-ui 面板" + echo -e "----------------------------------------------" + rm -f install.sh +} + +echo -e "${green}开始安装${plain}" +install_base +install_x-ui $1 \ No newline at end of file diff --git a/x-ui/install2.sh b/x-ui/install2.sh new file mode 100644 index 00000000..026eedda --- /dev/null +++ b/x-ui/install2.sh @@ -0,0 +1,164 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +arch=$(arch) +os_version=$(grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1) + +if [[ $arch == "x86_64" || $arch == "x64" || $arch == "amd64" ]]; then + arch="amd64" +elif [[ $arch == "aarch64" || $arch == "arm64" ]]; then + arch="arm64" +elif [[ $arch == "s390x" ]]; then + arch="s390x" +else + echo -e "不支持的CPU架构!脚本将自动退出!" + rm -f install.sh + exit 1 +fi + +echo "CPU架构: ${arch}" + +if [ $(getconf WORD_BIT) != '32' ] && [ $(getconf LONG_BIT) != '64' ]; then + echo "X-ui面板不支持 32 位系统(x86),请使用 64 位系统(x86_64),如果检测有误,请联系作者" + rm -f install.sh + exit -1 +fi + +if [[ $SYSTEM == "CentOS" ]]; then + if [[ ${os_version} -le 6 ]]; then + echo -e "请使用 CentOS 7 或更高版本的系统!\n" && exit 1 + fi +elif [[ $SYSTEM == "Ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + echo -e "请使用 Ubuntu 16 或更高版本的系统!\n" && exit 1 + fi +elif [[ $SYSTEM == "Debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + echo -e "请使用 Debian 8 或更高版本的系统!\n" && exit 1 + fi +fi + +${PACKAGE_UPDATE[int]} +[[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl +[[ -z $(type -P tar) ]] && ${PACKAGE_INSTALL[int]} tar + +#This function will be called when user installed x-ui out of sercurity +config_after_install() { + yellow "出于安全考虑,安装完成后需要强制修改端口与账户密码" + read -p "请设置您的账户名:" config_account + read -p "请设置您的账户密码:" config_password + read -p "请设置面板访问端口:" config_port + yellow "请核对面板登录信息是否正确:" + yellow "您的账户名将设定为:${config_account}" + yellow "您的账户密码将设定为:${config_password}" + yellow "您的面板访问端口将设定为:${config_port}" + read -p "确认设定完成?[y/n]": config_confirm + if [[ x"${config_confirm}" == x"y" || x"${config_confirm}" == x"Y" ]]; then + yellow "确认设定,设定中" + /usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} + green "账户密码设定完成" + /usr/local/x-ui/x-ui setting -port ${config_port} + green "面板端口设定完成" + else + red "已取消,所有设置项均为默认设置,请及时修改" + fi +} + +install_x-ui() { + systemctl stop x-ui + cd /usr/local/ + if [ $# == 0 ]; then + last_version=$(curl -Ls "https://api.github.com/repos/Misaka-blog/x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + if [[ ! -n "$last_version" ]]; then + red "检测 x-ui 版本失败,可能是超出 Github API 限制,请稍后再试,或手动指定 x-ui 版本安装" + rm -f install.sh + exit 1 + fi + yellow "检测到 x-ui 最新版本:${last_version},开始安装" + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz https://github.com/Misaka-blog/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz + if [[ $? -ne 0 ]]; then + red "下载 x-ui 失败,请确保你的服务器能够下载 Github 的文件" + rm -f install.sh + exit 1 + fi + else + last_version=$1 + url="https://github.com/Misaka-blog/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz" + yellow "开始安装 x-ui v$1" + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz ${url} + if [[ $? -ne 0 ]]; then + red "下载 x-ui v$1 失败,请确保此版本存在" + rm -f install.sh + exit 1 + fi + fi + + if [[ -e /usr/local/x-ui/ ]]; then + rm /usr/local/x-ui/ -rf + fi + + tar zxvf x-ui-linux-${arch}.tar.gz + rm x-ui-linux-${arch}.tar.gz -f + cd x-ui + chmod +x x-ui bin/xray-linux-${arch} + cp -f x-ui.service /etc/systemd/system/ + wget --no-check-certificate -O /usr/bin/x-ui https://raw.githubusercontent.com/Misaka-blog/x-ui/main/x-ui.sh + chmod +x /usr/local/x-ui/x-ui.sh + chmod +x /usr/bin/x-ui + config_after_install + systemctl daemon-reload + systemctl enable x-ui + systemctl start x-ui + green "x-ui v${last_version} 安装完成,面板已启动" + echo -e "" + echo -e "x-ui 管理脚本使用方法: " + echo -e "----------------------------------------------" + echo -e "x-ui - 显示管理菜单 (功能更多)" + echo -e "x-ui start - 启动 x-ui 面板" + echo -e "x-ui stop - 停止 x-ui 面板" + echo -e "x-ui restart - 重启 x-ui 面板" + echo -e "x-ui status - 查看 x-ui 状态" + echo -e "x-ui enable - 设置 x-ui 开机自启" + echo -e "x-ui disable - 取消 x-ui 开机自启" + echo -e "x-ui log - 查看 x-ui 日志" + echo -e "x-ui v2-ui - 迁移本机器的 v2-ui 账号数据至 x-ui" + echo -e "x-ui update - 更新 x-ui 面板" + echo -e "x-ui install - 安装 x-ui 面板" + echo -e "x-ui uninstall - 卸载 x-ui 面板" + echo -e "----------------------------------------------" + rm -f install.sh +} + +yellow "开始安装X-ui面板" +install_x-ui $1 \ No newline at end of file diff --git a/x-ui/install3.sh b/x-ui/install3.sh new file mode 100644 index 00000000..7a26b800 --- /dev/null +++ b/x-ui/install3.sh @@ -0,0 +1,164 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +arch=$(arch) +os_version=$(grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1) + +if [[ $arch == "x86_64" || $arch == "x64" || $arch == "amd64" ]]; then + arch="amd64" +elif [[ $arch == "aarch64" || $arch == "arm64" ]]; then + arch="arm64" +elif [[ $arch == "s390x" ]]; then + arch="s390x" +else + echo -e "不支持的CPU架构!脚本将自动退出!" + rm -f install.sh + exit 1 +fi + +echo "CPU架构: ${arch}" + +if [ $(getconf WORD_BIT) != '32' ] && [ $(getconf LONG_BIT) != '64' ]; then + echo "X-ui面板不支持 32 位系统(x86),请使用 64 位系统(x86_64),如果检测有误,请联系作者" + rm -f install.sh + exit -1 +fi + +if [[ $SYSTEM == "CentOS" ]]; then + if [[ ${os_version} -le 6 ]]; then + echo -e "请使用 CentOS 7 或更高版本的系统!\n" && exit 1 + fi +elif [[ $SYSTEM == "Ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + echo -e "请使用 Ubuntu 16 或更高版本的系统!\n" && exit 1 + fi +elif [[ $SYSTEM == "Debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + echo -e "请使用 Debian 8 或更高版本的系统!\n" && exit 1 + fi +fi + +${PACKAGE_UPDATE[int]} +[[ -z $(type -P curl) ]] && ${PACKAGE_INSTALL[int]} curl +[[ -z $(type -P tar) ]] && ${PACKAGE_INSTALL[int]} tar + +#This function will be called when user installed x-ui out of sercurity +config_after_install() { + yellow "出于安全考虑,安装完成后需要强制修改端口与账户密码" + read -p "请设置您的账户名:" config_account + read -p "请设置您的账户密码:" config_password + read -p "请设置面板访问端口:" config_port + yellow "请核对面板登录信息是否正确:" + yellow "您的账户名将设定为:${config_account}" + yellow "您的账户密码将设定为:${config_password}" + yellow "您的面板访问端口将设定为:${config_port}" + read -p "确认设定完成?[y/n]": config_confirm + if [[ x"${config_confirm}" == x"y" || x"${config_confirm}" == x"Y" ]]; then + yellow "确认设定,设定中" + /usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} + green "账户密码设定完成" + /usr/local/x-ui/x-ui setting -port ${config_port} + green "面板端口设定完成" + else + red "已取消,所有设置项均为默认设置,请及时修改" + fi +} + +install_x-ui() { + systemctl stop x-ui + cd /usr/local/ + if [ $# == 0 ]; then + last_version=$(curl -Ls "https://api.github.com/repos/Misaka-blog/x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + if [[ ! -n "$last_version" ]]; then + red "检测 x-ui 版本失败,可能是超出 Github API 限制,正在使用备用 Jsdelivr API 获取 X-ui 最新版本" + rm -f install.sh + exit 1 + fi + yellow "检测到 x-ui 最新版本:${last_version},开始安装" + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz https://github.com/Misaka-blog/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz + if [[ $? -ne 0 ]]; then + red "下载 x-ui 失败,请确保你的服务器能够下载 Github 的文件" + rm -f install.sh + exit 1 + fi + else + last_version=$1 + url="https://github.com/Misaka-blog/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz" + yellow "开始安装 x-ui v$1" + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz ${url} + if [[ $? -ne 0 ]]; then + red "下载 x-ui v$1 失败,请确保此版本存在" + rm -f install.sh + exit 1 + fi + fi + + if [[ -e /usr/local/x-ui/ ]]; then + rm /usr/local/x-ui/ -rf + fi + + tar zxvf x-ui-linux-${arch}.tar.gz + rm x-ui-linux-${arch}.tar.gz -f + cd x-ui + chmod +x x-ui bin/xray-linux-${arch} + cp -f x-ui.service /etc/systemd/system/ + wget --no-check-certificate -O /usr/bin/x-ui https://raw.githubusercontent.com/Misaka-blog/x-ui/main/x-ui.sh + chmod +x /usr/local/x-ui/x-ui.sh + chmod +x /usr/bin/x-ui + config_after_install + systemctl daemon-reload + systemctl enable x-ui + systemctl start x-ui + green "x-ui v${last_version} 安装完成,面板已启动" + echo -e "" + echo -e "x-ui 管理脚本使用方法: " + echo -e "----------------------------------------------" + echo -e "x-ui - 显示管理菜单 (功能更多)" + echo -e "x-ui start - 启动 x-ui 面板" + echo -e "x-ui stop - 停止 x-ui 面板" + echo -e "x-ui restart - 重启 x-ui 面板" + echo -e "x-ui status - 查看 x-ui 状态" + echo -e "x-ui enable - 设置 x-ui 开机自启" + echo -e "x-ui disable - 取消 x-ui 开机自启" + echo -e "x-ui log - 查看 x-ui 日志" + echo -e "x-ui v2-ui - 迁移本机器的 v2-ui 账号数据至 x-ui" + echo -e "x-ui update - 更新 x-ui 面板" + echo -e "x-ui install - 安装 x-ui 面板" + echo -e "x-ui uninstall - 卸载 x-ui 面板" + echo -e "----------------------------------------------" + rm -f install.sh +} + +yellow "正在开始安装X-ui面板" +install_x-ui $1 diff --git a/x-ui/x-ui.sh b/x-ui/x-ui.sh new file mode 100644 index 00000000..4df25f89 --- /dev/null +++ b/x-ui/x-ui.sh @@ -0,0 +1,569 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +PLAIN='\033[0m' + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +os_version=$(grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1) + +if [[ $SYSTEM == "CentOS" ]]; then + if [[ ${os_version} -le 6 ]]; then + red "请使用 CentOS 7 或更高版本的系统!\n" && exit 1 + fi +elif [[ $SYSTEM == "Ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + red "请使用 Ubuntu 16 或更高版本的系统!\n" && exit 1 + fi +elif [[ $SYSTEM == "Debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + red "请使用 Debian 8 或更高版本的系统!\n" && exit 1 + fi +fi + +confirm() { + if [[ $# > 1 ]]; then + echo && read -p "$1 [默认$2]: " temp + if [[ x"${temp}" == x"" ]]; then + temp=$2 + fi + else + read -p "$1 [y/n]: " temp + fi + if [[ x"${temp}" == x"y" || x"${temp}" == x"Y" ]]; then + return 0 + else + return 1 + fi +} + +confirm_restart() { + confirm "是否重启X-ui面板,重启面板也会重启xray" "y" + if [[ $? == 0 ]]; then + restart + else + show_menu + fi +} + +before_show_menu() { + echo && echo -n -e "${YELLOW}按回车键返回主菜单: ${PLAIN}" && read temp + show_menu +} + +install() { + bash <(curl -Ls https://raw.githubusercontents.com/Misaka-blog/x-ui/master/install.sh) + if [[ $? == 0 ]]; then + if [[ $# == 0 ]]; then + start + else + start 0 + fi + fi +} + +update() { + confirm "本功能会强制重装当前最新版X-ui面板,数据不会丢失,是否继续?" "n" + if [[ $? != 0 ]]; then + red "已取消" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 0 + fi + bash <(curl -Ls https://raw.githubusercontents.com/Misaka-blog/x-ui/master/install.sh) + if [[ $? == 0 ]]; then + green "更新完成,已自动重启面板 " + exit 0 + fi +} + +uninstall() { + confirm "确定要卸载X-ui面板吗,xray 也会卸载?" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + systemctl stop x-ui + systemctl disable x-ui + rm /etc/systemd/system/x-ui.service -f + systemctl daemon-reload + systemctl reset-failed + rm /etc/x-ui/ -rf + rm /usr/local/x-ui/ -rf + + echo "" + echo -e "卸载X-ui面板成功" + echo "" + rm /usr/bin/x-ui -f + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +reset_user() { + confirm "确定要将面板用户名和密码重置为 admin 吗" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + /usr/local/x-ui/x-ui setting -username admin -password admin + echo -e "面板用户名和密码已重置为 ${GREEN}admin${PLAIN},现在请重启面板" + confirm_restart +} + +reset_config() { + confirm "确定要重置所有设置吗,账号数据不会丢失,用户名和密码不会改变" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + /usr/local/x-ui/x-ui setting -reset + echo -e "所有面板设置已重置为默认值,请重启面板并使用默认的 ${GREEN}54321${PLAIN} 端口访问面板" + confirm_restart +} + +set_port() { + echo && echo -n -e "输入端口号[1-65535]: " && read port + if [[ -z "${port}" ]]; then + yellow "已取消" + before_show_menu + else + /usr/local/x-ui/x-ui setting -port ${port} + echo -e "设置端口完毕,请重启面板并使用新设置的端口 ${GREEN}${port}${PLAIN} 访问面板" + confirm_restart + fi +} + +start() { + check_status + if [[ $? == 0 ]]; then + echo "" + green "X-ui面板已运行,无需再次启动,如需重启请选择重启" + else + systemctl start x-ui + sleep 2 + check_status + if [[ $? == 0 ]]; then + green "X-ui 面板启动成功" + else + red "X-ui 面板启动失败,可能是因为启动时间超过了两秒,请稍后查看日志信息" + fi + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +stop() { + check_status + if [[ $? == 1 ]]; then + echo "" + green "X-ui 面板已停止,无需再次停止" + else + systemctl stop x-ui + sleep 2 + check_status + if [[ $? == 1 ]]; then + green "X-ui 与 xray 停止成功" + else + red "X-ui 面板停止失败,可能是因为停止时间超过了两秒,请稍后查看日志信息" + fi + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +restart() { + systemctl restart x-ui + sleep 2 + check_status + if [[ $? == 0 ]]; then + green "X-ui 与 xray 重启成功" + else + red "X-ui 面板重启失败,可能是因为启动时间超过了两秒,请稍后查看日志信息" + fi + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +status() { + systemctl status x-ui -l + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +enable_xui() { + systemctl enable x-ui + if [[ $? == 0 ]]; then + green "X-ui 设置开机自启成功" + else + red "X-ui 设置开机自启失败" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +disable_xui() { + systemctl disable x-ui + if [[ $? == 0 ]]; then + green "X-ui 取消开机自启成功" + else + red "X-ui 取消开机自启失败" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +show_log() { + journalctl -u x-ui.service -e --no-pager -f + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +migrate_v2_ui() { + /usr/local/x-ui/x-ui v2-ui + + before_show_menu +} + +install_bbr() { + # temporary workaround for installing bbr + bash <(curl -L -s https://raw.githubusercontents.com/teddysun/across/master/bbr.sh) + echo "" + before_show_menu +} + +update_shell() { + wget -O /usr/bin/x-ui -N --no-check-certificate https://github.com/Misaka-blog/x-ui/raw/master/x-ui.sh + if [[ $? != 0 ]]; then + echo "" + red "下载脚本失败,请检查本机能否连接 Github" + before_show_menu + else + chmod +x /usr/bin/x-ui + green "升级脚本成功,请重新运行脚本" && exit 0 + fi +} + +# 0: running, 1: not running, 2: not installed +check_status() { + if [[ ! -f /etc/systemd/system/x-ui.service ]]; then + return 2 + fi + temp=$(systemctl status x-ui | grep Active | awk '{print $3}' | cut -d "(" -f2 | cut -d ")" -f1) + if [[ x"${temp}" == x"running" ]]; then + return 0 + else + return 1 + fi +} + +check_enabled() { + temp=$(systemctl is-enabled x-ui) + if [[ x"${temp}" == x"enabled" ]]; then + return 0 + else + return 1 + fi +} + +check_uninstall() { + check_status + if [[ $? != 2 ]]; then + echo "" + red "X-ui 面板已安装,请不要重复安装" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +check_install() { + check_status + if [[ $? == 2 ]]; then + echo "" + red "请先安装 X-ui 面板" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +show_status() { + check_status + case $? in + 0) + echo -e "面板状态: ${GREEN}已运行${PLAIN}" + show_enable_status + ;; + 1) + echo -e "面板状态: ${YELLOW}未运行${PLAIN}" + show_enable_status + ;; + 2) + echo -e "面板状态: ${RED}未安装${PLAIN}" + ;; + esac + show_xray_status +} + +show_enable_status() { + check_enabled + if [[ $? == 0 ]]; then + echo -e "是否开机自启: ${GREEN}是${PLAIN}" + else + echo -e "是否开机自启: ${RED}否${PLAIN}" + fi +} + +check_xray_status() { + count=$(ps -ef | grep "xray-linux" | grep -v "grep" | wc -l) + if [[ count -ne 0 ]]; then + return 0 + else + return 1 + fi +} + +show_xray_status() { + check_xray_status + if [[ $? == 0 ]]; then + echo -e "xray 状态: ${GREEN}运行${PLAIN}" + else + echo -e "xray 状态: ${RED}未运行${PLAIN}" + fi +} + +set_telegram_bot() { + echo -E "" + yellow "设置Telegram Bot需要知晓Bot的Token与ChatId" + yellow "使用方法请参考博客https://coderfan.net" + read -P "我已确认以上内容[y/n]" confirmTGBot + if [ $confirmTGBot == "n" ]; then + show_menu + else + read -p "请输入Telegram Bot Token:" TG_BOT_TOKEN + yellow "你设置的Telegram Bot Token:$TG_BOT_TOKEN" + read -p "请输入Telegram Bot Chat Id:" TG_BOT_CHATID + yellow "你设置的Telegram Bot Chat Id:$TG_BOT_CHATID" + read -p "请输入Telegram Bot运行周期:" TG_BOT_RUNTIME + yellow "你设置的Telegram Bot运行周期:$TG_BOT_RUNTIME" + info=$(/usr/local/x-ui/x-ui setting -tgbottoken ${TG_BOT_TOKEN} -tgbotchatid ${TG_BOT_CHATID} -tgbotRuntime "$TG_BOT_RUNTIME") + if [ $? != 0 ]; then + yellow "$info" + red "设置Telegram Bot失败" + exit 1 + else + green "设置Telegram Bot成功" + show_menu + fi + fi +} + +enable_telegram_bot() { + echo -E "" + yellow "该功能会开启Telegram Bot通知" + yellow "通知内容包括:" + green "1.流量使用情况" + green "2.节点到期提醒,待实现(规划中)" + green "3.面板登录提醒,待完善(规划中)" + read -p "我已确认以上内容[y/n]" confirmTGBot + if [ $confirmTGBot == "y" ]; then + info=$(/usr/local/x-ui/x-ui setting -enabletgbot=true) + if [ $? == 0 ]; then + green "开启成功,重启X-UI生效,重启中...." + restart + else + red "开启失败,即将退出..." + exit 1 + fi + else + show_menu + fi +} + +disable_telegram_bot() { + read -P "确认是否关闭Telegram Bot[y/n]" confirmTGBot + if [ $confirmTGBot == "y" ]; then + info=$(/usr/local/x-ui/x-ui setting -enabletgbot=false) + if [ $? == 0 ]; then + green "关闭成功,重启X-UI生效,重启中...." + restart + else + red "关闭失败,请检查日志..." + exit 1 + fi + else + show_menu + fi +} + +ssl_cert_issue() { + wget -N https://raw.githubusercontents.com/Misaka-blog/acme-1key/master/acme1key.sh && bash acme1key.sh +} + +open_ports(){ + systemctl stop firewalld.service + systemctl disable firewalld.service + setenforce 0 + ufw disable + iptables -P INPUT ACCEPT + iptables -P FORWARD ACCEPT + iptables -P OUTPUT ACCEPT + iptables -t nat -F + iptables -t mangle -F + iptables -F + iptables -X + netfilter-persistent save + yellow "VPS中的所有网络端口已开启" +} + +show_usage() { + echo "x-ui 管理脚本使用方法: " + echo "------------------------------------------" + echo "x-ui - 显示管理菜单 (功能更多)" + echo "x-ui start - 启动 x-ui 面板" + echo "x-ui stop - 停止 x-ui 面板" + echo "x-ui restart - 重启 x-ui 面板" + echo "x-ui status - 查看 x-ui 状态" + echo "x-ui enable - 设置 x-ui 开机自启" + echo "x-ui disable - 取消 x-ui 开机自启" + echo "x-ui log - 查看 x-ui 日志" + echo "x-ui v2-ui - 迁移本机器的 v2-ui 账号数据至 x-ui" + echo "x-ui update - 更新 x-ui 面板" + echo "x-ui install - 安装 x-ui 面板" + echo "x-ui uninstall - 卸载 x-ui 面板" + echo "------------------------------------------" +} + +show_menu() { + echo -e " + ${GREEN}x-ui 面板管理脚本${PLAIN} + ${GREEN}0.${PLAIN} 退出脚本 +———————————————— + ${GREEN}1.${PLAIN} 安装 x-ui + ${GREEN}2.${PLAIN} 更新 x-ui + ${GREEN}3.${PLAIN} 卸载 x-ui +———————————————— + ${GREEN}4.${PLAIN} 重置用户名密码 + ${GREEN}5.${PLAIN} 重置面板设置 + ${GREEN}6.${PLAIN} 设置面板端口 +———————————————— + ${GREEN}7.${PLAIN} 启动 x-ui + ${GREEN}8.${PLAIN} 停止 x-ui + ${GREEN}9.${PLAIN} 重启 x-ui + ${GREEN}10.${PLAIN} 查看 x-ui 状态 + ${GREEN}11.${PLAIN} 查看 x-ui 日志 +———————————————— + ${GREEN}12.${PLAIN} 设置 x-ui 开机自启 + ${GREEN}13.${PLAIN} 取消 x-ui 开机自启 +———————————————— + ${GREEN}14.${PLAIN} 一键安装 bbr (最新内核) + ${GREEN}15.${PLAIN} 一键申请SSL证书(acme申请) + ${GREEN}16.${PLAIN} VPS防火墙放开所有网络端口 + ${green}17.${plain} 开启Telegram通知(TgBot) + ${green}18.${plain} 关闭Telegram通知(TgBot) + ${green}19.${plain} 设置TelegramBot + " + show_status + echo && read -p "请输入选择 [0-19]: " num + + case "${num}" in + 0) exit 0 ;; + 1) check_uninstall && install ;; + 2) check_install && update ;; + 3) check_install && uninstall ;; + 4) check_install && reset_user ;; + 5) check_install && reset_config ;; + 6) check_install && set_port ;; + 7) check_install && start ;; + 8) check_install && stop ;; + 9) check_install && restart ;; + 10) check_install && status ;; + 11) check_install && show_log ;; + 12) check_install && enable_xui ;; + 13) check_install && disable_xui ;; + 14) install_bbr ;; + 15) ssl_cert_issue ;; + 16) open_ports ;; + 17) enable_telegram_bot ;; + 18) disable_telegram_bot ;; + 19) set_telegram_bot ;; + *) red "请输入正确的数字 [0-15]" ;; + esac +} + +if [[ $# > 0 ]]; then + case $1 in + "start") check_install 0 && start 0 ;; + "stop") check_install 0 && stop 0 ;; + "restart") check_install 0 && restart 0 ;; + "status") check_install 0 && status 0 ;; + "enable") check_install 0 && enable_xui 0 ;; + "disable") check_install 0 && disable_xui 0 ;; + "log") check_install 0 && show_log 0 ;; + "v2-ui") check_install 0 && migrate_v2_ui 0 ;; + "update") check_install 0 && update 0 ;; + "install") check_uninstall 0 && install 0 ;; + "uninstall") check_install 0 && uninstall 0 ;; + *) show_usage ;; + esac +else + show_menu +fi \ No newline at end of file diff --git a/x-ui/x-ui1.sh b/x-ui/x-ui1.sh new file mode 100644 index 00000000..ec279b00 --- /dev/null +++ b/x-ui/x-ui1.sh @@ -0,0 +1,558 @@ +#!/bin/bash + +red='\033[0;31m' +green='\033[0;32m' +yellow='\033[0;33m' +plain='\033[0m' + +#Add some basic function here +function LOGD() { + echo -e "${yellow}[DEG] $* ${plain}" +} + +function LOGE() { + echo -e "${red}[ERR] $* ${plain}" +} + +function LOGI() { + echo -e "${green}[INF] $* ${plain}" +} +# check root +[[ $EUID -ne 0 ]] && LOGE "错误: 必须使用root用户运行此脚本!\n" && exit 1 + +# check os +if [[ -f /etc/redhat-release ]]; then + release="centos" +elif cat /etc/issue | grep -Eqi "debian"; then + release="debian" +elif cat /etc/issue | grep -Eqi "ubuntu"; then + release="ubuntu" +elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then + release="centos" +elif cat /proc/version | grep -Eqi "debian"; then + release="debian" +elif cat /proc/version | grep -Eqi "ubuntu"; then + release="ubuntu" +elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then + release="centos" +else + LOGE "未检测到系统版本,请联系脚本作者!\n" && exit 1 +fi + +os_version="" + +# os version +if [[ -f /etc/os-release ]]; then + os_version=$(awk -F'[= ."]' '/VERSION_ID/{print $3}' /etc/os-release) +fi +if [[ -z "$os_version" && -f /etc/lsb-release ]]; then + os_version=$(awk -F'[= ."]+' '/DISTRIB_RELEASE/{print $2}' /etc/lsb-release) +fi + +if [[ x"${release}" == x"centos" ]]; then + if [[ ${os_version} -le 6 ]]; then + LOGE "请使用 CentOS 7 或更高版本的系统!\n" && exit 1 + fi +elif [[ x"${release}" == x"ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + LOGE "请使用 Ubuntu 16 或更高版本的系统!\n" && exit 1 + fi +elif [[ x"${release}" == x"debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + LOGE "请使用 Debian 8 或更高版本的系统!\n" && exit 1 + fi +fi + +confirm() { + if [[ $# > 1 ]]; then + echo && read -p "$1 [默认$2]: " temp + if [[ x"${temp}" == x"" ]]; then + temp=$2 + fi + else + read -p "$1 [y/n]: " temp + fi + if [[ x"${temp}" == x"y" || x"${temp}" == x"Y" ]]; then + return 0 + else + return 1 + fi +} + +confirm_restart() { + confirm "是否重启面板,重启面板也会重启 xray" "y" + if [[ $? == 0 ]]; then + restart + else + show_menu + fi +} + +before_show_menu() { + echo && echo -n -e "${yellow}按回车返回主菜单: ${plain}" && read temp + show_menu +} + +install() { + bash <(curl -Ls https://raw.githubusercontent.com/Misaka-blog/x-ui/master/install.sh) + if [[ $? == 0 ]]; then + if [[ $# == 0 ]]; then + start + else + start 0 + fi + fi +} + +update() { + confirm "本功能会强制重装当前最新版,数据不会丢失,是否继续?" "n" + if [[ $? != 0 ]]; then + LOGE "已取消" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 0 + fi + bash <(curl -Ls https://raw.githubusercontent.com/Misaka-blog/x-ui/master/install.sh) + if [[ $? == 0 ]]; then + LOGI "更新完成,已自动重启面板 " + exit 0 + fi +} + +uninstall() { + confirm "确定要卸载面板吗,xray 也会卸载?" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + systemctl stop x-ui + systemctl disable x-ui + rm /etc/systemd/system/x-ui.service -f + systemctl daemon-reload + systemctl reset-failed + rm /etc/x-ui/ -rf + rm /usr/local/x-ui/ -rf + + echo "" + echo -e "卸载成功,如果你想删除此脚本,则退出脚本后运行 ${green}rm /usr/bin/x-ui -f${plain} 进行删除" + echo "" + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +reset_user() { + confirm "确定要将用户名和密码重置为 admin 吗" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + /usr/local/x-ui/x-ui setting -username admin -password admin + echo -e "用户名和密码已重置为 ${green}admin${plain},现在请重启面板" + confirm_restart +} + +reset_config() { + confirm "确定要重置所有面板设置吗,账号数据不会丢失,用户名和密码不会改变" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + /usr/local/x-ui/x-ui setting -reset + echo -e "所有面板设置已重置为默认值,现在请重启面板,并使用默认的 ${green}54321${plain} 端口访问面板" + confirm_restart +} + +set_port() { + echo && echo -n -e "输入端口号[1-65535]: " && read port + if [[ -z "${port}" ]]; then + LOGD "已取消" + before_show_menu + else + /usr/local/x-ui/x-ui setting -port ${port} + echo -e "设置端口完毕,现在请重启面板,并使用新设置的端口 ${green}${port}${plain} 访问面板" + confirm_restart + fi +} + +start() { + check_status + if [[ $? == 0 ]]; then + echo "" + LOGI "面板已运行,无需再次启动,如需重启请选择重启" + else + systemctl start x-ui + sleep 2 + check_status + if [[ $? == 0 ]]; then + LOGI "x-ui 启动成功" + else + LOGE "面板启动失败,可能是因为启动时间超过了两秒,请稍后查看日志信息" + fi + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +stop() { + check_status + if [[ $? == 1 ]]; then + echo "" + LOGI "面板已停止,无需再次停止" + else + systemctl stop x-ui + sleep 2 + check_status + if [[ $? == 1 ]]; then + LOGI "x-ui 与 xray 停止成功" + else + LOGE "面板停止失败,可能是因为停止时间超过了两秒,请稍后查看日志信息" + fi + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +restart() { + systemctl restart x-ui + sleep 2 + check_status + if [[ $? == 0 ]]; then + LOGI "x-ui 与 xray 重启成功" + else + LOGE "面板重启失败,可能是因为启动时间超过了两秒,请稍后查看日志信息" + fi + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +status() { + systemctl status x-ui -l + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +enable() { + systemctl enable x-ui + if [[ $? == 0 ]]; then + LOGI "x-ui 设置开机自启成功" + else + LOGE "x-ui 设置开机自启失败" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +disable() { + systemctl disable x-ui + if [[ $? == 0 ]]; then + LOGI "x-ui 取消开机自启成功" + else + LOGE "x-ui 取消开机自启失败" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +show_log() { + journalctl -u x-ui.service -e --no-pager -f + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +migrate_v2_ui() { + /usr/local/x-ui/x-ui v2-ui + + before_show_menu +} + +install_bbr() { + # temporary workaround for installing bbr + bash <(curl -L -s https://raw.githubusercontent.com/teddysun/across/master/bbr.sh) + echo "" + before_show_menu +} + +update_shell() { + wget -O /usr/bin/x-ui -N --no-check-certificate https://github.com/Misaka-blog/x-ui/raw/master/x-ui.sh + if [[ $? != 0 ]]; then + echo "" + LOGE "下载脚本失败,请检查本机能否连接 Github" + before_show_menu + else + chmod +x /usr/bin/x-ui + LOGI "升级脚本成功,请重新运行脚本" && exit 0 + fi +} + +# 0: running, 1: not running, 2: not installed +check_status() { + if [[ ! -f /etc/systemd/system/x-ui.service ]]; then + return 2 + fi + temp=$(systemctl status x-ui | grep Active | awk '{print $3}' | cut -d "(" -f2 | cut -d ")" -f1) + if [[ x"${temp}" == x"running" ]]; then + return 0 + else + return 1 + fi +} + +check_enabled() { + temp=$(systemctl is-enabled x-ui) + if [[ x"${temp}" == x"enabled" ]]; then + return 0 + else + return 1 + fi +} + +check_uninstall() { + check_status + if [[ $? != 2 ]]; then + echo "" + LOGE "面板已安装,请不要重复安装" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +check_install() { + check_status + if [[ $? == 2 ]]; then + echo "" + LOGE "请先安装面板" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +show_status() { + check_status + case $? in + 0) + echo -e "面板状态: ${green}已运行${plain}" + show_enable_status + ;; + 1) + echo -e "面板状态: ${yellow}未运行${plain}" + show_enable_status + ;; + 2) + echo -e "面板状态: ${red}未安装${plain}" + ;; + esac + show_xray_status +} + +show_enable_status() { + check_enabled + if [[ $? == 0 ]]; then + echo -e "是否开机自启: ${green}是${plain}" + else + echo -e "是否开机自启: ${red}否${plain}" + fi +} + +check_xray_status() { + count=$(ps -ef | grep "xray-linux" | grep -v "grep" | wc -l) + if [[ count -ne 0 ]]; then + return 0 + else + return 1 + fi +} + +show_xray_status() { + check_xray_status + if [[ $? == 0 ]]; then + echo -e "xray 状态: ${green}运行${plain}" + else + echo -e "xray 状态: ${red}未运行${plain}" + fi +} + +ssl_cert_issue() { + echo -E "" + LOGD "******使用说明******" + LOGI "该脚本将使用Acme脚本申请证书,使用时需保证:" + LOGI "1.知晓Cloudflare 注册邮箱" + LOGI "2.知晓Cloudflare Global API Key" + LOGI "3.域名已通过Cloudflare进行解析到当前服务器" + LOGI "4.该脚本申请证书默认安装路径为/root/cert目录" + confirm "我已确认以上内容[y/n]" "y" + if [ $? -eq 0 ]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/acme-1key/master/acme1key.sh && bash acme1key.sh + else + show_menu + fi +} + +show_usage() { + echo "x-ui 管理脚本使用方法: " + echo "------------------------------------------" + echo "x-ui - 显示管理菜单 (功能更多)" + echo "x-ui start - 启动 x-ui 面板" + echo "x-ui stop - 停止 x-ui 面板" + echo "x-ui restart - 重启 x-ui 面板" + echo "x-ui status - 查看 x-ui 状态" + echo "x-ui enable - 设置 x-ui 开机自启" + echo "x-ui disable - 取消 x-ui 开机自启" + echo "x-ui log - 查看 x-ui 日志" + echo "x-ui v2-ui - 迁移本机器的 v2-ui 账号数据至 x-ui" + echo "x-ui update - 更新 x-ui 面板" + echo "x-ui install - 安装 x-ui 面板" + echo "x-ui uninstall - 卸载 x-ui 面板" + echo "------------------------------------------" +} + +show_menu() { + echo -e " + ${green}x-ui 面板管理脚本${plain} + ${green}0.${plain} 退出脚本 +———————————————— + ${green}1.${plain} 安装 x-ui + ${green}2.${plain} 更新 x-ui + ${green}3.${plain} 卸载 x-ui +———————————————— + ${green}4.${plain} 重置用户名密码 + ${green}5.${plain} 重置面板设置 + ${green}6.${plain} 设置面板端口 +———————————————— + ${green}7.${plain} 启动 x-ui + ${green}8.${plain} 停止 x-ui + ${green}9.${plain} 重启 x-ui + ${green}10.${plain} 查看 x-ui 状态 + ${green}11.${plain} 查看 x-ui 日志 +———————————————— + ${green}12.${plain} 设置 x-ui 开机自启 + ${green}13.${plain} 取消 x-ui 开机自启 +———————————————— + ${green}14.${plain} 一键安装 bbr (最新内核) + ${green}15.${plain} 一键申请SSL证书(acme申请) + " + show_status + echo && read -p "请输入选择 [0-14]: " num + + case "${num}" in + 0) + exit 0 + ;; + 1) + check_uninstall && install + ;; + 2) + check_install && update + ;; + 3) + check_install && uninstall + ;; + 4) + check_install && reset_user + ;; + 5) + check_install && reset_config + ;; + 6) + check_install && set_port + ;; + 7) + check_install && start + ;; + 8) + check_install && stop + ;; + 9) + check_install && restart + ;; + 10) + check_install && status + ;; + 11) + check_install && show_log + ;; + 12) + check_install && enable + ;; + 13) + check_install && disable + ;; + 14) + install_bbr + ;; + 15) + ssl_cert_issue + ;; + *) + LOGE "请输入正确的数字 [0-14]" + ;; + esac +} + +if [[ $# > 0 ]]; then + case $1 in + "start") + check_install 0 && start 0 + ;; + "stop") + check_install 0 && stop 0 + ;; + "restart") + check_install 0 && restart 0 + ;; + "status") + check_install 0 && status 0 + ;; + "enable") + check_install 0 && enable 0 + ;; + "disable") + check_install 0 && disable 0 + ;; + "log") + check_install 0 && show_log 0 + ;; + "v2-ui") + check_install 0 && migrate_v2_ui 0 + ;; + "update") + check_install 0 && update 0 + ;; + "install") + check_uninstall 0 && install 0 + ;; + "uninstall") + check_install 0 && uninstall 0 + ;; + *) show_usage ;; + esac +else + show_menu +fi \ No newline at end of file diff --git a/x-ui/x-ui2.sh b/x-ui/x-ui2.sh new file mode 100644 index 00000000..6f0c73bb --- /dev/null +++ b/x-ui/x-ui2.sh @@ -0,0 +1,511 @@ +#!/bin/bash + +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +PLAIN='\033[0m' + +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install") +PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove") + +[[ $EUID -ne 0 ]] && red "请在root用户下运行脚本" && exit 1 + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持当前VPS系统,请使用主流的操作系统" && exit 1 + +os_version=$(grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1) + +if [[ $SYSTEM == "CentOS" ]]; then + if [[ ${os_version} -le 6 ]]; then + red "请使用 CentOS 7 或更高版本的系统!\n" && exit 1 + fi +elif [[ $SYSTEM == "Ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + red "请使用 Ubuntu 16 或更高版本的系统!\n" && exit 1 + fi +elif [[ $SYSTEM == "Debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + red "请使用 Debian 8 或更高版本的系统!\n" && exit 1 + fi +fi + +confirm() { + if [[ $# > 1 ]]; then + echo && read -p "$1 [默认$2]: " temp + if [[ x"${temp}" == x"" ]]; then + temp=$2 + fi + else + read -p "$1 [y/n]: " temp + fi + if [[ x"${temp}" == x"y" || x"${temp}" == x"Y" ]]; then + return 0 + else + return 1 + fi +} + +confirm_restart() { + confirm "是否重启X-ui面板,重启面板也会重启xray" "y" + if [[ $? == 0 ]]; then + restart + else + show_menu + fi +} + +before_show_menu() { + echo && echo -n -e "${YELLOW}按回车键返回主菜单: ${PLAIN}" && read temp + show_menu +} + +install() { + bash <(curl -Ls https://raw.githubusercontent.com/Misaka-blog/x-ui/master/install.sh) + if [[ $? == 0 ]]; then + if [[ $# == 0 ]]; then + start + else + start 0 + fi + fi +} + +update() { + confirm "本功能会强制重装当前最新版X-ui面板,数据不会丢失,是否继续?" "n" + if [[ $? != 0 ]]; then + red "已取消" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 0 + fi + bash <(curl -Ls https://raw.githubusercontent.com/Misaka-blog/x-ui/master/install.sh) + if [[ $? == 0 ]]; then + green "更新完成,已自动重启面板 " + exit 0 + fi +} + +uninstall() { + confirm "确定要卸载X-ui面板吗,xray 也会卸载?" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + systemctl stop x-ui + systemctl disable x-ui + rm /etc/systemd/system/x-ui.service -f + systemctl daemon-reload + systemctl reset-failed + rm /etc/x-ui/ -rf + rm /usr/local/x-ui/ -rf + + echo "" + echo -e "卸载X-ui面板成功" + echo "" + rm /usr/bin/x-ui -f + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +reset_user() { + confirm "确定要将面板用户名和密码重置为 admin 吗" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + /usr/local/x-ui/x-ui setting -username admin -password admin + echo -e "面板用户名和密码已重置为 ${GREEN}admin${PLAIN},现在请重启面板" + confirm_restart +} + +reset_config() { + confirm "确定要重置所有设置吗,账号数据不会丢失,用户名和密码不会改变" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + /usr/local/x-ui/x-ui setting -reset + echo -e "所有面板设置已重置为默认值,请重启面板并使用默认的 ${GREEN}54321${PLAIN} 端口访问面板" + confirm_restart +} + +set_port() { + echo && echo -n -e "输入端口号[1-65535]: " && read port + if [[ -z "${port}" ]]; then + yellow "已取消" + before_show_menu + else + /usr/local/x-ui/x-ui setting -port ${port} + echo -e "设置端口完毕,请重启面板并使用新设置的端口 ${GREEN}${port}${PLAIN} 访问面板" + confirm_restart + fi +} + +start() { + check_status + if [[ $? == 0 ]]; then + echo "" + green "X-ui面板已运行,无需再次启动,如需重启请选择重启" + else + systemctl start x-ui + sleep 2 + check_status + if [[ $? == 0 ]]; then + green "X-ui 面板启动成功" + else + red "X-ui 面板启动失败,可能是因为启动时间超过了两秒,请稍后查看日志信息" + fi + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +stop() { + check_status + if [[ $? == 1 ]]; then + echo "" + green "X-ui 面板已停止,无需再次停止" + else + systemctl stop x-ui + sleep 2 + check_status + if [[ $? == 1 ]]; then + green "X-ui 与 xray 停止成功" + else + red "X-ui 面板停止失败,可能是因为停止时间超过了两秒,请稍后查看日志信息" + fi + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +restart() { + systemctl restart x-ui + sleep 2 + check_status + if [[ $? == 0 ]]; then + green "X-ui 与 xray 重启成功" + else + red "X-ui 面板重启失败,可能是因为启动时间超过了两秒,请稍后查看日志信息" + fi + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +status() { + systemctl status x-ui -l + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +enable_xui() { + systemctl enable x-ui + if [[ $? == 0 ]]; then + green "X-ui 设置开机自启成功" + else + red "X-ui 设置开机自启失败" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +disable_xui() { + systemctl disable x-ui + if [[ $? == 0 ]]; then + green "X-ui 取消开机自启成功" + else + red "X-ui 取消开机自启失败" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +show_log() { + journalctl -u x-ui.service -e --no-pager -f + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +migrate_v2_ui() { + /usr/local/x-ui/x-ui v2-ui + + before_show_menu +} + +install_bbr() { + # temporary workaround for installing bbr + bash <(curl -L -s https://raw.githubusercontent.com/teddysun/across/master/bbr.sh) + echo "" + before_show_menu +} + +update_shell() { + wget -O /usr/bin/x-ui -N --no-check-certificate https://github.com/Misaka-blog/x-ui/raw/master/x-ui.sh + if [[ $? != 0 ]]; then + echo "" + red "下载脚本失败,请检查本机能否连接 Github" + before_show_menu + else + chmod +x /usr/bin/x-ui + green "升级脚本成功,请重新运行脚本" && exit 0 + fi +} + +# 0: running, 1: not running, 2: not installed +check_status() { + if [[ ! -f /etc/systemd/system/x-ui.service ]]; then + return 2 + fi + temp=$(systemctl status x-ui | grep Active | awk '{print $3}' | cut -d "(" -f2 | cut -d ")" -f1) + if [[ x"${temp}" == x"running" ]]; then + return 0 + else + return 1 + fi +} + +check_enabled() { + temp=$(systemctl is-enabled x-ui) + if [[ x"${temp}" == x"enabled" ]]; then + return 0 + else + return 1 + fi +} + +check_uninstall() { + check_status + if [[ $? != 2 ]]; then + echo "" + red "X-ui 面板已安装,请不要重复安装" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +check_install() { + check_status + if [[ $? == 2 ]]; then + echo "" + red "请先安装 X-ui 面板" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +show_status() { + check_status + case $? in + 0) + echo -e "面板状态: ${GREEN}已运行${PLAIN}" + show_enable_status + ;; + 1) + echo -e "面板状态: ${YELLOW}未运行${PLAIN}" + show_enable_status + ;; + 2) + echo -e "面板状态: ${RED}未安装${PLAIN}" + ;; + esac + show_xray_status +} + +show_enable_status() { + check_enabled + if [[ $? == 0 ]]; then + echo -e "是否开机自启: ${GREEN}是${PLAIN}" + else + echo -e "是否开机自启: ${RED}否${PLAIN}" + fi +} + +check_xray_status() { + count=$(ps -ef | grep "xray-linux" | grep -v "grep" | wc -l) + if [[ count -ne 0 ]]; then + return 0 + else + return 1 + fi +} + +show_xray_status() { + check_xray_status + if [[ $? == 0 ]]; then + echo -e "xray 状态: ${GREEN}运行${PLAIN}" + else + echo -e "xray 状态: ${RED}未运行${PLAIN}" + fi +} + +ssl_cert_issue() { + echo -E "" + yellow "******使用说明******" + yellow "该脚本将使用Acme脚本申请证书,使用时需保证:" + yellow "1.准备一个 Cloudflare 注册邮箱" + yellow "2.准备一个 Cloudflare Global API Key" + yellow "3.域名已通过 Cloudflare 进行解析到当前服务器" + yellow "4.该脚本申请证书默认安装路径为 /root 目录" + confirm "我已确认以上内容[y/n]" "y" + if [ $? -eq 0 ]; then + wget -N https://raw.githubusercontents.com/Misaka-blog/acme-1key/master/acme1key.sh && bash acme1key.sh + else + show_menu + fi +} + +open_ports(){ + systemctl stop firewalld.service + systemctl disable firewalld.service + setenforce 0 + ufw disable + iptables -P INPUT ACCEPT + iptables -P FORWARD ACCEPT + iptables -P OUTPUT ACCEPT + iptables -t nat -F + iptables -t mangle -F + iptables -F + iptables -X + netfilter-persistent save + yellow "VPS中的所有网络端口已开启" +} + +show_usage() { + echo "x-ui 管理脚本使用方法: " + echo "------------------------------------------" + echo "x-ui - 显示管理菜单 (功能更多)" + echo "x-ui start - 启动 x-ui 面板" + echo "x-ui stop - 停止 x-ui 面板" + echo "x-ui restart - 重启 x-ui 面板" + echo "x-ui status - 查看 x-ui 状态" + echo "x-ui enable - 设置 x-ui 开机自启" + echo "x-ui disable - 取消 x-ui 开机自启" + echo "x-ui log - 查看 x-ui 日志" + echo "x-ui v2-ui - 迁移本机器的 v2-ui 账号数据至 x-ui" + echo "x-ui update - 更新 x-ui 面板" + echo "x-ui install - 安装 x-ui 面板" + echo "x-ui uninstall - 卸载 x-ui 面板" + echo "------------------------------------------" +} + +show_menu() { + echo -e " + ${GREEN}x-ui 面板管理脚本${PLAIN} + ${GREEN}0.${PLAIN} 退出脚本 +———————————————— + ${GREEN}1.${PLAIN} 安装 x-ui + ${GREEN}2.${PLAIN} 更新 x-ui + ${GREEN}3.${PLAIN} 卸载 x-ui +———————————————— + ${GREEN}4.${PLAIN} 重置用户名密码 + ${GREEN}5.${PLAIN} 重置面板设置 + ${GREEN}6.${PLAIN} 设置面板端口 +———————————————— + ${GREEN}7.${PLAIN} 启动 x-ui + ${GREEN}8.${PLAIN} 停止 x-ui + ${GREEN}9.${PLAIN} 重启 x-ui + ${GREEN}10.${PLAIN} 查看 x-ui 状态 + ${GREEN}11.${PLAIN} 查看 x-ui 日志 +———————————————— + ${GREEN}12.${PLAIN} 设置 x-ui 开机自启 + ${GREEN}13.${PLAIN} 取消 x-ui 开机自启 +———————————————— + ${GREEN}14.${PLAIN} 一键安装 bbr (最新内核) + ${GREEN}15.${PLAIN} 一键申请SSL证书(acme申请) + ${GREEN}16.${PLAIN} VPS防火墙放开所有网络端口 + " + show_status + echo && read -p "请输入选择 [0-16]: " num + + case "${num}" in + 0) exit 0 ;; + 1) check_uninstall && install ;; + 2) check_install && update ;; + 3) check_install && uninstall ;; + 4) check_install && reset_user ;; + 5) check_install && reset_config ;; + 6) check_install && set_port ;; + 7) check_install && start ;; + 8) check_install && stop ;; + 9) check_install && restart ;; + 10) check_install && status ;; + 11) check_install && show_log ;; + 12) check_install && enable_xui ;; + 13) check_install && disable_xui ;; + 14) install_bbr ;; + 15) ssl_cert_issue ;; + 16) open_ports ;; + *) red "请输入正确的数字 [0-15]" ;; + esac +} + +if [[ $# > 0 ]]; then + case $1 in + "start") check_install 0 && start 0 ;; + "stop") check_install 0 && stop 0 ;; + "restart") check_install 0 && restart 0 ;; + "status") check_install 0 && status 0 ;; + "enable") check_install 0 && enable_xui 0 ;; + "disable") check_install 0 && disable_xui 0 ;; + "log") check_install 0 && show_log 0 ;; + "v2-ui") check_install 0 && migrate_v2_ui 0 ;; + "update") check_install 0 && update 0 ;; + "install") check_uninstall 0 && install 0 ;; + "uninstall") check_install 0 && uninstall 0 ;; + *) show_usage ;; + esac +else + show_menu +fi \ No newline at end of file diff --git a/xray17.sh b/xray17.sh new file mode 100644 index 00000000..85f6a504 --- /dev/null +++ b/xray17.sh @@ -0,0 +1,1704 @@ +#!/bin/bash + +RED="\033[31m" # Error message +GREEN="\033[32m" # Success message +YELLOW="\033[33m" # Warning message +BLUE="\033[36m" # Info message +PLAIN='\033[0m' + +SITES=( + http://www.zhuizishu.com/ + http://xs.56dyc.com/ + http://www.ddxsku.com/ + http://www.biqu6.com/ + https://www.wenshulou.cc/ + http://www.55shuba.com/ + http://www.39shubao.com/ + https://www.23xsw.cc/ + https://www.jueshitangmen.info/ + https://www.zhetian.org/ + http://www.bequgexs.com/ + http://www.tjwl.com/ +) + +CONFIG_FILE="/usr/local/etc/xray/config.json" +OS=$(hostnamectl | grep -i system | cut -d: -f2) + +checkwarp(){ + [[ -n $(wg 2>/dev/null) ]] && colorEcho $RED " 检测到WARP已打开,脚本中断运行" && colorEcho $YELLOW " 请关闭WARP之后再运行本脚本" && exit 1 +} + +V6_PROXY="" +IP=$(curl -s4m8 https://ip.gs) +[[ "$?" != "0" ]] && IP=$(curl -s6m8 https://ip.gs) && V6_PROXY="https://gh-proxy-misakano7545.koyeb.app/" +[[ $V6_PROXY != "" ]] && echo -e nameserver 2a01:4f8:c2c:123f::1 > /etc/resolv.conf + +BT="false" +NGINX_CONF_PATH="/etc/nginx/conf.d/" +res=$(which bt 2>/dev/null) +[[ "$res" != "" ]] && BT="true" && NGINX_CONF_PATH="/www/server/panel/vhost/nginx/" + +VLESS="false" +TROJAN="false" +TLS="false" +WS="false" +XTLS="false" +KCP="false" + +checkSystem() { + result=$(id | awk '{print $1}') + [[ $EUID -ne 0 ]] && colorEcho $RED " 请以root身份执行该脚本" && exit 1 + + res=$(which yum 2>/dev/null) + if [[ "$?" != "0" ]]; then + res=$(which apt 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 不受支持的Linux系统" + exit 1 + fi + PMT="apt" + CMD_INSTALL="apt install -y " + CMD_REMOVE="apt remove -y " + CMD_UPGRADE="apt update; apt upgrade -y; apt autoremove -y" + else + PMT="yum" + CMD_INSTALL="yum install -y " + CMD_REMOVE="yum remove -y " + CMD_UPGRADE="yum update -y" + fi + res=$(which systemctl 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 系统版本过低,请升级到最新版本" + exit 1 + fi +} + +colorEcho() { + echo -e "${1}${@:2}${PLAIN}" +} + +configNeedNginx() { + local ws=$(grep wsSettings $CONFIG_FILE) + [[ -z "$ws" ]] && echo no && return + echo yes +} + +needNginx() { + [[ "$WS" == "false" ]] && echo no && return + echo yes +} + +status() { + [[ ! -f /usr/local/bin/xray ]] && echo 0 && return + [[ ! -f $CONFIG_FILE ]] && echo 1 && return + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + [[ -z "$res" ]] && echo 2 && return + + if [[ $(configNeedNginx) != "yes" ]]; then + echo 3 + else + res=$(ss -nutlp | grep -i nginx) + if [[ -z "$res" ]]; then + echo 4 + else + echo 5 + fi + fi +} + +statusText() { + res=$(status) + case $res in + 2) echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN} ;; + 3) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN} ;; + 4) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行${PLAIN}, ${RED}Nginx未运行${PLAIN} ;; + 5) echo -e ${GREEN}已安装${PLAIN} ${GREEN}Xray正在运行, Nginx正在运行${PLAIN} ;; + *) echo -e ${RED}未安装${PLAIN} ;; + esac +} + +normalizeVersion() { + if [ -n "$1" ]; then + case "$1" in + v*) echo "$1" ;; + http*) echo "v1.5.3" ;; + *) echo "v$1" ;; + esac + else + echo "" + fi +} + +# 1: new Xray. 0: no. 1: yes. 2: not installed. 3: check failed. +getVersion() { + VER=$(/usr/local/bin/xray version | head -n1 | awk '{print $2}') + RETVAL=$? + CUR_VER="$(normalizeVersion "$(echo "$VER" | head -n 1 | cut -d " " -f2)")" + TAG_URL="https://api.github.com/repos/XTLS/Xray-core/releases/latest" + NEW_VER="$(normalizeVersion "$(curl -s "${TAG_URL}" --connect-timeout 10 | grep 'tag_name' | cut -d\" -f4)")" + + if [[ $? -ne 0 ]] || [[ $NEW_VER == "" ]]; then + colorEcho $RED " 检查Xray版本信息失败,请检查网络" + 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' ;; + armv5tel) echo 'arm32-v5' ;; + armv6l) echo 'arm32-v6' ;; + armv7 | armv7l) echo 'arm32-v7a' ;; + armv8 | aarch64) echo 'arm64-v8a' ;; + mips64le) echo 'mips64le' ;; + mips64) echo 'mips64' ;; + mipsle) echo 'mips32le' ;; + mips) echo 'mips32' ;; + ppc64le) echo 'ppc64le' ;; + ppc64) echo 'ppc64' ;; + ppc64le) echo 'ppc64le' ;; + riscv64) echo 'riscv64' ;; + s390x) echo 's390x' ;; + *) colorEcho $RED " 不支持的CPU架构!" && exit 1;; + esac + + return 0 +} + +getData() { + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + echo " Xray一键脚本,运行之前请确认如下条件已经具备:" + colorEcho ${YELLOW} " 1. 一个伪装域名" + colorEcho ${YELLOW} " 2. 伪装域名DNS解析指向当前服务器ip(${IP})" + colorEcho ${BLUE} " 3. 如果/root目录下有 xray.pem 和 xray.key 证书密钥文件,无需理会条件2" + echo " " + read -p " 确认满足按y,按其他退出脚本:" answer + [[ "${answer,,}" != "y" ]] && exit 1 + echo "" + while true; do + read -p " 请输入伪装域名:" DOMAIN + if [[ -z "${DOMAIN}" ]]; then + colorEcho ${RED} " 域名输入错误,请重新输入!" + else + break + fi + done + DOMAIN=${DOMAIN,,} + colorEcho ${BLUE} " 伪装域名(host):$DOMAIN" + echo "" + if [[ -f ~/xray.pem && -f ~/xray.key ]]; then + colorEcho ${BLUE} " 检测到自有证书,将使用其部署" + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + else + resolve=$(curl -sm8 ipget.net/?ip=${DOMAIN}) + if [ $resolve != $IP ]; then + colorEcho ${BLUE} "${DOMAIN} 解析结果:${resolve}" + colorEcho ${RED} " 域名未解析到当前服务器IP(${IP})!" + exit 1 + fi + fi + fi + echo "" + if [[ "$(needNginx)" == "no" ]]; then + if [[ "$TLS" == "true" ]]; then + read -p " 请输入xray监听端口[强烈建议443,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + else + read -p " 请输入xray监听端口[100-65535的一个数字]:" PORT + [[ -z "${PORT}" ]] && PORT=$(shuf -i200-65000 -n1) + if [[ "${PORT:0:1}" == "0" ]]; then + colorEcho ${RED} " 端口不能以0开头" + exit 1 + fi + fi + colorEcho ${BLUE} " xray端口:$PORT" + else + read -p " 请输入Nginx监听端口[100-65535的一个数字,默认443]:" PORT + [[ -z "${PORT}" ]] && PORT=443 + [ "${PORT:0:1}" = "0" ] && colorEcho ${BLUE} " 端口不能以0开头" && exit 1 + colorEcho ${BLUE} " Nginx端口:$PORT" + XPORT=$(shuf -i10000-65000 -n1) + fi + if [[ "$KCP" == "true" ]]; then + echo "" + colorEcho $BLUE " 请选择伪装类型:" + echo " 1) 无" + echo " 2) BT下载" + echo " 3) 视频通话" + echo " 4) 微信视频通话" + echo " 5) dtls" + echo " 6) wiregard" + read -p " 请选择伪装类型[默认:无]:" answer + case $answer in + 2) HEADER_TYPE="utp" ;; + 3) HEADER_TYPE="srtp" ;; + 4) HEADER_TYPE="wechat-video" ;; + 5) HEADER_TYPE="dtls" ;; + 6) HEADER_TYPE="wireguard" ;; + *) HEADER_TYPE="none" ;; + esac + colorEcho $BLUE " 伪装类型:$HEADER_TYPE" + SEED=$(cat /proc/sys/kernel/random/uuid) + fi + if [[ "$TROJAN" == "true" ]]; then + echo "" + read -p " 请设置trojan密码(不输则随机生成):" PASSWORD + [[ -z "$PASSWORD" ]] && PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) + colorEcho $BLUE " trojan密码:$PASSWORD" + fi + 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" ;; + esac + colorEcho $BLUE " 流控模式:$FLOW" + fi + if [[ "${WS}" == "true" ]]; then + echo "" + while true; do + read -p " 请输入伪装路径,以/开头(不懂请直接回车):" WSPATH + if [[ -z "${WSPATH}" ]]; then + len=$(shuf -i5-12 -n1) + ws=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1) + WSPATH="/$ws" + break + elif [[ "${WSPATH:0:1}" != "/" ]]; then + colorEcho ${RED} " 伪装路径必须以/开头!" + elif [[ "${WSPATH}" == "/" ]]; then + colorEcho ${RED} " 不能使用根路径!" + else + break + fi + done + colorEcho ${BLUE} " ws路径:$WSPATH" + fi + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + echo "" + colorEcho $BLUE " 请选择伪装站类型:" + echo " 1) 静态网站(位于/usr/share/nginx/html)" + echo " 2) 小说站(随机选择)" + echo " 3) 高清壁纸站(https://bing.ioliu.cn)" + echo " 4) 自定义反代站点(需以http或者https开头)" + read -p " 请选择伪装网站类型[默认:高清壁纸站]" answer + if [[ -z "$answer" ]]; then + PROXY_URL="https://bing.ioliu.cn" + else + case $answer in + 1) PROXY_URL="" ;; + 2) + 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 + ;; + 3) PROXY_URL="https://bing.ioliu.cn" ;; + 4) + read -p " 请输入反代站点(以http或者https开头):" PROXY_URL + if [[ -z "$PROXY_URL" ]]; then + colorEcho $RED " 请输入反代网站!" + exit 1 + elif [[ "${PROXY_URL:0:4}" != "http" ]]; then + colorEcho $RED " 反代网站必须以http或https开头!" + exit 1 + fi + ;; + *) colorEcho $RED " 请输入正确的选项!" && exit 1 ;; + esac + fi + REMOTE_HOST=$(echo ${PROXY_URL} | cut -d/ -f3) + colorEcho $BLUE " 伪装网站:$PROXY_URL" + echo "" + colorEcho $BLUE " 是否允许搜索引擎爬取网站?[默认:不允许]" + echo " y)允许,会有更多ip请求网站,但会消耗一些流量,vps流量充足情况下推荐使用" + echo " n)不允许,爬虫不会访问网站,访问ip比较单一,但能节省vps流量" + read -p " 请选择:[y/n]" answer + if [[ -z "$answer" ]]; then + ALLOW_SPIDER="n" + elif [[ "${answer,,}" == "y" ]]; then + ALLOW_SPIDER="y" + else + ALLOW_SPIDER="n" + fi + colorEcho $BLUE " 允许搜索引擎:$ALLOW_SPIDER" + fi + 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" +} + +installNginx() { + echo "" + colorEcho $BLUE " 安装nginx..." + if [[ "$BT" == "false" ]]; then + if [[ "$PMT" == "yum" ]]; then + $CMD_INSTALL epel-release + if [[ "$?" != "0" ]]; then + echo '[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' >/etc/yum.repos.d/nginx.repo + fi + fi + $CMD_INSTALL nginx + if [[ "$?" != "0" ]]; then + colorEcho $RED " Nginx安装失败,请截图到TG群反馈" + exit 1 + fi + systemctl enable nginx + else + res=$(which nginx 2>/dev/null) + if [[ "$?" != "0" ]]; then + colorEcho $RED " 您安装了宝塔,请在宝塔后台安装nginx后再运行本脚本" + exit 1 + fi + fi +} + +startNginx() { + if [[ "$BT" == "false" ]]; then + systemctl start nginx + else + nginx -c /www/server/nginx/conf/nginx.conf + fi +} + +stopNginx() { + if [[ "$BT" == "false" ]]; then + systemctl stop nginx + else + res=$(ps aux | grep -i nginx) + if [[ "$res" != "" ]]; then + nginx -s stop + fi + fi +} + +getCert() { + mkdir -p /usr/local/etc/xray + if [[ -z ${CERT_FILE+x} ]]; then + stopNginx + systemctl stop xray + 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 + curl -sL https://get.acme.sh | sh -s email=hijk.pw@protonmail.sh + source ~/.bashrc + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [[ "$BT" == "false" ]]; then + if [ -n $V6_PROXY ]; then + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone --listen-v6 + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "systemctl stop nginx" --post-hook "systemctl restart nginx" --standalone + fi + else + ~/.acme.sh/acme.sh --issue -d $DOMAIN --keylength ec-256 --pre-hook "nginx -s stop || { echo -n ''; }" --post-hook "nginx -c /www/server/nginx/conf/nginx.conf || { echo -n ''; }" --standalone + fi + [[ -f ~/.acme.sh/${DOMAIN}_ecc/ca.cer ]] || { + colorEcho $RED " 获取证书失败,请截图到TG群反馈" + exit 1 + } + CERT_FILE="/usr/local/etc/xray/${DOMAIN}.pem" + KEY_FILE="/usr/local/etc/xray/${DOMAIN}.key" + ~/.acme.sh/acme.sh --install-cert -d $DOMAIN --ecc \ + --key-file $KEY_FILE \ + --fullchain-file $CERT_FILE \ + --reloadcmd "service nginx force-reload" + [[ -f $CERT_FILE && -f $KEY_FILE ]] || { + colorEcho $RED " 获取证书失败,请截图到TG群反馈" + exit 1 + } + else + cp ~/xray.pem /usr/local/etc/xray/${DOMAIN}.pem + cp ~/xray.key /usr/local/etc/xray/${DOMAIN}.key + fi +} + +configNginx() { + mkdir -p /usr/share/nginx/html + if [[ "$ALLOW_SPIDER" == "n" ]]; then + echo 'User-Agent: *' >/usr/share/nginx/html/robots.txt + echo 'Disallow: /' >>/usr/share/nginx/html/robots.txt + ROBOT_CONFIG=" location = /robots.txt {}" + else + ROBOT_CONFIG="" + fi + + if [[ "$BT" == "false" ]]; then + 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 [[ "$?" != "0" ]]; then + user="www-data" + else + user="nginx" + fi + 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"'; + + access_log /var/log/nginx/access.log main; + 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 + fi + + if [[ "$PROXY_URL" == "" ]]; then + action="" + else + action="proxy_ssl_server_name on; + proxy_pass $PROXY_URL; + proxy_set_header Accept-Encoding ''; + sub_filter \"$REMOTE_HOST\" \"$DOMAIN\"; + sub_filter_once off;" + fi + + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + mkdir -p ${NGINX_CONF_PATH} + # VMESS+WS+TLS + # VLESS+WS+TLS + if [[ "$WS" == "true" ]]; then + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + server_name ${DOMAIN}; + return 301 https://\$server_name:${PORT}\$request_uri; + } + + server { + listen ${PORT} ssl http2; + listen [::]:${PORT} ssl http2; + server_name ${DOMAIN}; + charset utf-8; + + # ssl配置 + ssl_protocols TLSv1.1 TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + ssl_ecdh_curve secp384r1; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + ssl_certificate $CERT_FILE; + ssl_certificate_key $KEY_FILE; + + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + + location ${WSPATH} { + proxy_redirect off; + proxy_pass http://127.0.0.1:${XPORT}; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } + } + EOF + else + # VLESS+TCP+TLS + # VLESS+TCP+XTLS + # trojan + cat >${NGINX_CONF_PATH}${DOMAIN}.conf <<-EOF + server { + listen 80; + listen [::]:80; + listen 81 http2; + server_name ${DOMAIN}; + root /usr/share/nginx/html; + location / { + $action + } + $ROBOT_CONFIG + } + EOF + fi + fi +} + +setSelinux() { + 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 +} + +setFirewall() { + 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 +} + +installBBR() { + if [[ "$NEED_BBR" != "y" ]]; then + INSTALL_BBR=false + return + fi + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $BLUE " BBR模块已安装" + INSTALL_BBR=false + return + fi + res=$(hostnamectl | grep -i openvz) + if [[ "$res" != "" ]]; then + colorEcho $BLUE " openvz机器,跳过安装" + INSTALL_BBR=false + return + fi + echo "net.core.default_qdisc=fq" >>/etc/sysctl.conf + echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf + sysctl -p + result=$(lsmod | grep bbr) + if [[ "$result" != "" ]]; then + colorEcho $GREEN " BBR模块已启用" + INSTALL_BBR=false + return + fi + colorEcho $BLUE " 安装BBR模块..." + if [[ "$PMT" == "yum" ]]; then + if [[ "$V6_PROXY" == "" ]]; then + rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm + $CMD_INSTALL --enablerepo=elrepo-kernel kernel-ml + $CMD_REMOVE kernel-3.* + grub2-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi + else + $CMD_INSTALL --install-recommends linux-generic-hwe-16.04 + grub-set-default 0 + echo "tcp_bbr" >>/etc/modules-load.d/modules.conf + INSTALL_BBR=true + fi +} + +installXray() { + rm -rf /tmp/xray + mkdir -p /tmp/xray + DOWNLOAD_LINK="${V6_PROXY}https://github.com/XTLS/Xray-core/releases/download/${NEW_VER}/Xray-linux-$(archAffix).zip" + colorEcho $BLUE " 下载Xray: ${DOWNLOAD_LINK}" + curl -L -H "Cache-Control: no-cache" -o /tmp/xray/xray.zip ${DOWNLOAD_LINK} + if [ $? != 0 ]; then + colorEcho $RED " 下载Xray文件失败,请检查服务器网络设置" + exit 1 + fi + systemctl stop xray + mkdir -p /usr/local/etc/xray /usr/local/share/xray && \ + unzip /tmp/xray/xray.zip -d /tmp/xray + cp /tmp/xray/xray /usr/local/bin + cp /tmp/xray/geo* /usr/local/share/xray + chmod +x /usr/local/bin/xray || { + colorEcho $RED " Xray安装失败" + exit 1 + } + + cat >/etc/systemd/system/xray.service <<-EOF + [Unit] + Description=Xray Service + Documentation=https://github.com/xtls + After=network.target nss-lookup.target + + [Service] + User=root + #User=nobody + #CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + #AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + NoNewPrivileges=true + ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json + Restart=on-failure + RestartPreventExitStatus=23 + + [Install] + WantedBy=multi-user.target + EOF + systemctl daemon-reload + systemctl enable xray.service +} + +trojanConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +trojanXTLSConfig() { + cat >$CONFIG_FILE <<-EOF + { + "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 +} + +vmessConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ] + }, + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vmessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "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 +} + +vmessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 1, + "alterId": 0 + } + ], + "disableInsecureEncryption": false + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessXTLSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "flow": "$FLOW", + "level": 0 + } + ], + "decryption": "none", + "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 +} + +vlessWSConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $XPORT, + "listen": "127.0.0.1", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "path": "$WSPATH", + "headers": { + "Host": "$DOMAIN" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +vlessKCPConfig() { + local uuid="$(cat '/proc/sys/kernel/random/uuid')" + cat >$CONFIG_FILE <<-EOF + { + "inbounds": [{ + "port": $PORT, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "$uuid", + "level": 0 + } + ], + "decryption": "none" + }, + "streamSettings": { + "streamSettings": { + "network": "mkcp", + "kcpSettings": { + "uplinkCapacity": 100, + "downlinkCapacity": 100, + "congestion": true, + "header": { + "type": "$HEADER_TYPE" + }, + "seed": "$SEED" + } + } + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }] + } + EOF +} + +configXray() { + mkdir -p /usr/local/xray + if [[ "$TROJAN" == "true" ]]; then + if [[ "$XTLS" == "true" ]]; then + trojanXTLSConfig + else + trojanConfig + fi + return 0 + fi + if [[ "$VLESS" == "false" ]]; then + # VMESS + kcp + if [[ "$KCP" == "true" ]]; then + vmessKCPConfig + return 0 + fi + # VMESS + if [[ "$TLS" == "false" ]]; then + vmessConfig + elif [[ "$WS" == "false" ]]; then + # VMESS+TCP+TLS + vmessTLSConfig + # VMESS+WS+TLS + else + vmessWSConfig + fi + #VLESS + else + if [[ "$KCP" == "true" ]]; then + vlessKCPConfig + return 0 + fi + # VLESS+TCP + if [[ "$WS" == "false" ]]; then + # VLESS+TCP+TLS + if [[ "$XTLS" == "false" ]]; then + vlessTLSConfig + # VLESS+TCP+XTLS + else + vlessXTLSConfig + fi + # VLESS+WS+TLS + else + vlessWSConfig + fi + fi +} + +install() { + getData + $PMT clean all + [[ "$PMT" == "apt" ]] && $PMT update + #echo $CMD_UPGRADE | bash + $CMD_INSTALL wget curl sudo vim unzip tar gcc openssl + $CMD_INSTALL net-tools + if [[ "$PMT" == "apt" ]]; then + $CMD_INSTALL libssl-dev g++ + fi + res=$(which unzip 2>/dev/null) + if [[ $? -ne 0 ]]; then + colorEcho $RED " unzip安装失败,请检查网络" + exit 1 + fi + installNginx + setFirewall + if [[ "$TLS" == "true" || "$XTLS" == "true" ]]; then + getCert + fi + configNginx + colorEcho $BLUE " 安装Xray..." + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + colorEcho $BLUE " Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + colorEcho $BLUE " 安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + fi + configXray + setSelinux + installBBR + start + showInfo + bbrReboot +} + +bbrReboot() { + if [[ "${INSTALL_BBR}" == "true" ]]; then + echo + echo " 为使BBR模块生效,系统将在30秒后重启" + echo + echo -e " 您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统" + sleep 30 + reboot + fi +} + +update() { + res=$(status) + [[ $res -lt 2 ]] && colorEcho $RED " Xray未安装,请先安装!" && return + getVersion + RETVAL="$?" + if [[ $RETVAL == 0 ]]; then + colorEcho $BLUE " Xray最新版 ${CUR_VER} 已经安装" + elif [[ $RETVAL == 3 ]]; then + exit 1 + else + colorEcho $BLUE " 安装Xray ${NEW_VER} ,架构$(archAffix)" + installXray + stop + start + colorEcho $GREEN " 最新版Xray安装成功!" + fi +} + +uninstall() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + echo "" + read -p " 确定卸载Xray?[y/n]:" answer + if [[ "${answer,,}" == "y" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + stop + systemctl disable xray + rm -rf /etc/systemd/system/xray.service + rm -rf /usr/local/bin/xray + rm -rf /usr/local/etc/xray + if [[ "$BT" == "false" ]]; then + 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 + fi + if [[ "$domain" != "" ]]; then + rm -rf ${NGINX_CONF_PATH}${domain}.conf + fi + [[ -f ~/.acme.sh/acme.sh ]] && ~/.acme.sh/acme.sh --uninstall + colorEcho $GREEN " Xray卸载成功" + fi +} + +start() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + stopNginx + startNginx + systemctl restart xray + sleep 2 + port=$(grep port $CONFIG_FILE | head -n 1 | cut -d: -f2 | tr -d \",' ') + res=$(ss -nutlp | grep ${port} | grep -i xray) + if [[ "$res" == "" ]]; then + colorEcho $RED " Xray启动失败,请检查日志或查看端口是否被占用!" + else + colorEcho $BLUE " Xray启动成功" + fi +} + +stop() { + stopNginx + systemctl stop xray + colorEcho $BLUE " Xray停止成功" +} + +restart() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + stop + start +} + +getConfigFileInfo() { + vless="false" + tls="false" + ws="false" + xtls="false" + trojan="false" + protocol="VMess" + kcp="false" + uid=$(grep id $CONFIG_FILE | head -n1 | cut -d: -f2 | tr -d \",' ') + alterid=$(grep alterId $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + network=$(grep network $CONFIG_FILE | tail -n1 | cut -d: -f2 | tr -d \",' ') + [[ -z "$network" ]] && network="tcp" + domain=$(grep serverName $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" == "" ]]; then + domain=$(grep Host $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + if [[ "$domain" != "" ]]; then + ws="true" + tls="true" + wspath=$(grep path $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + else + tls="true" + fi + if [[ "$ws" == "true" ]]; then + port=$(grep -i ssl $NGINX_CONF_PATH${domain}.conf | head -n1 | awk '{print $2}') + else + port=$(grep port $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + res=$(grep -i kcp $CONFIG_FILE) + if [[ "$res" != "" ]]; then + kcp="true" + type=$(grep header -A 3 $CONFIG_FILE | grep 'type' | cut -d: -f2 | tr -d \",' ') + seed=$(grep seed $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + fi + vmess=$(grep vmess $CONFIG_FILE) + if [[ "$vmess" == "" ]]; then + trojan=$(grep trojan $CONFIG_FILE) + if [[ "$trojan" == "" ]]; then + vless="true" + protocol="VLESS" + else + trojan="true" + password=$(grep password $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + protocol="trojan" + fi + tls="true" + encryption="none" + xtls=$(grep xtlsSettings $CONFIG_FILE) + if [[ "$xtls" != "" ]]; then + xtls="true" + flow=$(grep flow $CONFIG_FILE | cut -d: -f2 | tr -d \",' ') + else + flow="无" + fi + fi +} + +outputVmess() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"tcp\", + \"type\":\"none\", + \"host\":\"\", + \"path\":\"\", + \"tls\":\"\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +outputVmessKCP() { + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}auto${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" +} + +outputTrojan() { + if [[ "$xtls" == "true" ]]; then + link="trojan://${password}@${domain}:${port}#" + 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}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + else + link="trojan://${password}@${domain}:${port}#" + 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}" + echo -e " ${BLUE}Trojan链接:${PLAIN} $RED$link$PLAIN" + fi +} + +outputVmessTLS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接: ${PLAIN}$RED$link$PLAIN" +} + +outputVmessWS() { + raw="{ + \"v\":\"2\", + \"ps\":\"\", + \"add\":\"$IP\", + \"port\":\"${port}\", + \"id\":\"${uid}\", + \"aid\":\"$alterid\", + \"net\":\"${network}\", + \"type\":\"none\", + \"host\":\"${domain}\", + \"path\":\"${wspath}\", + \"tls\":\"tls\" +}" + link=$(echo -n ${raw} | base64 -w 0) + link="vmess://${link}" + + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}额外id(alterid):${PLAIN} ${RED}${alterid}${PLAIN}" + echo -e " ${BLUE}加密方式(security):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + echo -e " ${BLUE}vmess链接:${PLAIN} $RED$link$PLAIN" +} + +showInfo() { + res=$(status) + if [[ $res -lt 2 ]]; then + colorEcho $RED " Xray未安装,请先安装!" + return + fi + + echo "" + echo -n -e " ${BLUE}Xray运行状态:${PLAIN}" + statusText + echo -e " ${BLUE}Xray配置文件: ${PLAIN} ${RED}${CONFIG_FILE}${PLAIN}" + colorEcho $BLUE " Xray配置信息:" + + getConfigFileInfo + + echo -e " ${BLUE}协议: ${PLAIN} ${RED}${protocol}${PLAIN}" + if [[ "$trojan" == "true" ]]; then + outputTrojan + return 0 + fi + if [[ "$vless" == "false" ]]; then + if [[ "$kcp" == "true" ]]; then + outputVmessKCP + return 0 + fi + if [[ "$tls" == "false" ]]; then + outputVmess + elif [[ "$ws" == "false" ]]; then + outputVmessTLS + else + outputVmessWS + fi + else + if [[ "$kcp" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN} ${RED}${type}${PLAIN}" + echo -e " ${BLUE}mkcp seed:${PLAIN} ${RED}${seed}${PLAIN}" + return 0 + fi + if [[ "$xtls" == "true" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}XTLS${PLAIN}" + elif [[ "$ws" == "false" ]]; then + echo -e " ${BLUE}IP(address): ${PLAIN}${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + else + echo -e " ${BLUE}IP(address): ${PLAIN} ${RED}${IP}${PLAIN}" + echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}" + echo -e " ${BLUE}id(uuid):${PLAIN}${RED}${uid}${PLAIN}" + echo -e " ${BLUE}流控(flow):${PLAIN}$RED$flow${PLAIN}" + echo -e " ${BLUE}加密(encryption):${PLAIN} ${RED}none${PLAIN}" + echo -e " ${BLUE}传输协议(network):${PLAIN} ${RED}${network}${PLAIN}" + echo -e " ${BLUE}伪装类型(type):${PLAIN}${RED}none$PLAIN" + echo -e " ${BLUE}伪装域名/主机名(host)/SNI/peer名称:${PLAIN}${RED}${domain}${PLAIN}" + echo -e " ${BLUE}路径(path):${PLAIN}${RED}${wspath}${PLAIN}" + echo -e " ${BLUE}底层安全传输(tls):${PLAIN}${RED}TLS${PLAIN}" + fi + fi +} + +showLog() { + res=$(status) + [[ $res -lt 2 ]] && colorEcho $RED " Xray未安装,请先安装!" && return + journalctl -xen -u xray --no-pager +} + +menu() { + clear + echo "#############################################################" + echo -e "# ${RED}Xray一键安装脚本${PLAIN} #" + echo -e "# ${GREEN}作者${PLAIN}: 网络跳越(hijk) & MisakaNo #" + echo -e "# ${GREEN}博客${PLAIN}: https://owo.misaka.rest #" + echo -e "# ${GREEN}TG群${PLAIN}: https://t.me/misakanetcn #" + echo "#############################################################" + echo -e " " + echo -e " ${GREEN}1.${PLAIN} 安装Xray-VMESS" + echo -e " ${GREEN}2.${PLAIN} 安装Xray-${BLUE}VMESS+mKCP${PLAIN}" + echo -e " ${GREEN}3.${PLAIN} 安装Xray-VMESS+TCP+TLS" + echo -e " ${GREEN}4.${PLAIN} 安装Xray-${BLUE}VMESS+WS+TLS${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}5.${PLAIN} 安装Xray-${BLUE}VLESS+mKCP${PLAIN}" + echo -e " ${GREEN}6.${PLAIN} 安装Xray-VLESS+TCP+TLS" + echo -e " ${GREEN}7.${PLAIN} 安装Xray-${BLUE}VLESS+WS+TLS${PLAIN}${RED}(可过cdn)${PLAIN}" + echo -e " ${GREEN}8.${PLAIN} 安装Xray-${BLUE}VLESS+TCP+XTLS${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}9.${PLAIN} 安装${BLUE}Trojan${PLAIN}${RED}(推荐)${PLAIN}" + echo -e " ${GREEN}10.${PLAIN} 安装${BLUE}Trojan+XTLS${PLAIN}${RED}(推荐)${PLAIN}" + echo " -------------" + echo -e " ${GREEN}11.${PLAIN} 更新Xray" + echo -e " ${GREEN}12. ${RED}卸载Xray${PLAIN}" + echo " -------------" + echo -e " ${GREEN}13.${PLAIN} 启动Xray" + echo -e " ${GREEN}14.${PLAIN} 重启Xray" + echo -e " ${GREEN}15.${PLAIN} 停止Xray" + echo " -------------" + echo -e " ${GREEN}16.${PLAIN} 查看Xray配置" + echo -e " ${GREEN}17.${PLAIN} 查看Xray日志" + echo " -------------" + echo -e " ${GREEN}0.${PLAIN} 退出" + echo -n " 当前状态:" + statusText + echo + + read -p " 请选择操作[0-17]:" answer + case $answer in + 0) exit 1 ;; + 1) install ;; + 2) KCP="true" && install ;; + 3) TLS="true" && install ;; + 4) TLS="true" && WS="true" && install ;; + 5) VLESS="true" && KCP="true" && install ;; + 6) VLESS="true" && TLS="true" && install ;; + 7) VLESS="true" && TLS="true" && WS="true" && install ;; + 8) VLESS="true" && TLS="true" && XTLS="true" && install ;; + 9) TROJAN="true" && TLS="true" && install ;; + 10) TROJAN="true" && TLS="true" && XTLS="true" && install ;; + 11) update ;; + 12) uninstall ;; + 13) start ;; + 14) restart ;; + 15) stop ;; + 16) showInfo ;; + 17) showLog ;; + *) colorEcho $RED " 请选择正确的操作!" && exit 1 ;; + esac +} + +checkSystem +checkwarp + +action=$1 +[[ -z $1 ]] && action=menu +case "$action" in + menu | update | uninstall | start | restart | stop | showInfo | showLog) ${action} ;; + *) echo " 参数错误" && echo " 用法: $(basename $0) [menu|update|uninstall|start|restart|stop|showInfo|showLog]" ;; +esac diff --git a/xrayr-vmess.sh b/xrayr-vmess.sh new file mode 100644 index 00000000..203f1ba2 --- /dev/null +++ b/xrayr-vmess.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +# 控制台字体 +red() { + echo -e "\033[31m\033[01m$1\033[0m" +} + +green() { + echo -e "\033[32m\033[01m$1\033[0m" +} + +yellow() { + echo -e "\033[33m\033[01m$1\033[0m" +} + +# 判断系统及定义系统安装依赖方式 +REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'") +RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Alpine") +PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "yum -y update") +PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "apk add -f") +PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove") + +CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") + +for i in "${CMD[@]}"; do + SYS="$i" && [[ -n $SYS ]] && break +done + +for ((int = 0; int < ${#REGEX[@]}; int++)); do + [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break +done + +[[ -z $SYSTEM ]] && red "不支持VPS的当前系统,请使用主流的操作系统" && exit 1 + +archAffix() { + case "$(uname -m)" in + x86_64 | x64 | amd64) return 0 ;; + aarch64 | arm64) return 0 ;; + *) red "不支持的CPU架构,脚本即将退出!" ;; + esac + + return 0 +} + +install() { + install_XrayR + makeConfig +} + +install_XrayR() { + [[ -z $(type -P curl) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} curl + [[ -z $(type -P socat) ]] && ${PACKAGE_UPDATE[int]} && ${PACKAGE_INSTALL[int]} socat + bash <(curl -Ls https://raw.githubusercontent.com/XrayR-project/XrayR-release/master/install.sh) +} + +makeConfig() { + read -p "请输入对接机场面板:" airPanel + read -p "请输入机场网站:" airWebsite + read -p "请输入机场的API Key:" airAPIKey + read -p "请输入节点ID:" makeNodeID + read -p "请输入将要使用的节点域名:" nodeDomain + rm -f /etc/XrayR/config.yml + if [[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]]; then + curl https://get.acme.sh | sh -s email=script@github.com + source ~/.bashrc + bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade + fi + bash ~/.acme.sh/acme.sh --issue -d ${nodeDomain} --standalone -k ec-256 --server letsencrypt --force + bash ~/.acme.sh/acme.sh --install-cert -d ${nodeDomain} --key-file /etc/XrayR/cert/$nodeDomain.key --fullchain-file /etc/XrayR/cert/$nodeDomain.cert --ecc + cat cat </etc/XrayR/config.yml +Log: + Level: none # Log level: none, error, warning, info, debug + AccessPath: # /etc/XrayR/access.Log + ErrorPath: # /etc/XrayR/error.log +DnsConfigPath: # /etc/XrayR/dns.json # Path to dns config, check https://xtls.github.io/config/dns.html for help +RouteConfigPath: # /etc/XrayR/route.json # Path to route config, check https://xtls.github.io/config/routing.html for help +InboundConfigPath: # /etc/XrayR/custom_inbound.json # Path to custom inbound config, check https://xtls.github.io/config/inbound.html for help +OutboundConfigPath: # /etc/XrayR/custom_outbound.json # Path to custom outbound config, check https://xtls.github.io/config/outbound.html for help +ConnetionConfig: + Handshake: 4 # Handshake time limit, Second + ConnIdle: 10 # Connection idle time limit, Second + UplinkOnly: 2 # Time limit when the connection downstream is closed, Second + DownlinkOnly: 4 # Time limit when the connection is closed after the uplink is closed, Second + BufferSize: 64 # The internal cache size of each connection, kB +Nodes: + - + PanelType: "$airPanel" # Panel type: SSpanel, V2board, PMpanel, Proxypanel + ApiConfig: + ApiHost: "$airWebsite" + ApiKey: "$airAPIKey" + NodeID: $makeNodeID + NodeType: V2ray # Node type: V2ray, Trojan, Shadowsocks, Shadowsocks-Plugin + Timeout: 30 # Timeout for the api request + EnableVless: false # Enable Vless for V2ray Type + EnableXTLS: false # Enable XTLS for V2ray and Trojan + SpeedLimit: 0 # Mbps, Local settings will replace remote settings, 0 means disable + DeviceLimit: 0 # Local settings will replace remote settings, 0 means disable + RuleListPath: # /etc/XrayR/rulelist Path to local rulelist file + ControllerConfig: + ListenIP: 0.0.0.0 # IP address you want to listen + SendIP: 0.0.0.0 # IP address you want to send pacakage + UpdatePeriodic: 60 # Time to update the nodeinfo, how many sec. + EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well + DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy + DisableUploadTraffic: false # Disable Upload Traffic to the panel + DisableGetRule: false # Disable Get Rule from the panel + DisableIVCheck: false # Disable the anti-reply protection for Shadowsocks + DisableSniffing: false # Disable domain sniffing + EnableProxyProtocol: false # Only works for WebSocket and TCP + EnableFallback: false # Only support for Trojan and Vless + FallBackConfigs: # Support multiple fallbacks + - + SNI: # TLS SNI(Server Name Indication), Empty for any + Path: # HTTP PATH, Empty for any + Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/fallback/ for details. + ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for dsable + CertConfig: + CertMode: file # Option about how to get certificate: none, file, http, dns. Choose "none" will forcedly disable the tls config. + CertDomain: "$nodeDomain" # Domain to cert + CertFile: /etc/XrayR/cert/$nodeDomain.cert # Provided if the CertMode is file + KeyFile: /etc/XrayR/cert/$nodeDomain.key + Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/ + Email: test@me.com + DNSEnv: # DNS ENV option used by DNS provider + ALICLOUD_ACCESS_KEY: aaa + ALICLOUD_SECRET_KEY: bbb +EOF + xrayr restart + green "XrayR安装完成并对接机场面板成功!" + exit 1 +} + +install diff --git a/xrayr/XrayR copy.sh b/xrayr/XrayR copy.sh new file mode 100644 index 00000000..22d63b82 --- /dev/null +++ b/xrayr/XrayR copy.sh @@ -0,0 +1,542 @@ +#!/bin/bash + +red='\033[0;31m' +green='\033[0;32m' +yellow='\033[0;33m' +plain='\033[0m' + +version="v1.0.0" + +# check root +[[ $EUID -ne 0 ]] && echo -e "${red}错误: ${plain} 必须使用root用户运行此脚本!\n" && exit 1 + +# check os +if [[ -f /etc/redhat-release ]]; then + release="centos" +elif cat /etc/issue | grep -Eqi "debian"; then + release="debian" +elif cat /etc/issue | grep -Eqi "ubuntu"; then + release="ubuntu" +elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then + release="centos" +elif cat /proc/version | grep -Eqi "debian"; then + release="debian" +elif cat /proc/version | grep -Eqi "ubuntu"; then + release="ubuntu" +elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then + release="centos" +else + echo -e "${red}未检测到系统版本,请联系脚本作者!${plain}\n" && exit 1 +fi + +os_version="" + +# os version +if [[ -f /etc/os-release ]]; then + os_version=$(awk -F'[= ."]' '/VERSION_ID/{print $3}' /etc/os-release) +fi +if [[ -z "$os_version" && -f /etc/lsb-release ]]; then + os_version=$(awk -F'[= ."]+' '/DISTRIB_RELEASE/{print $2}' /etc/lsb-release) +fi + +if [[ x"${release}" == x"centos" ]]; then + if [[ ${os_version} -le 6 ]]; then + echo -e "${red}请使用 CentOS 7 或更高版本的系统!${plain}\n" && exit 1 + fi +elif [[ x"${release}" == x"ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + echo -e "${red}请使用 Ubuntu 16 或更高版本的系统!${plain}\n" && exit 1 + fi +elif [[ x"${release}" == x"debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + echo -e "${red}请使用 Debian 8 或更高版本的系统!${plain}\n" && exit 1 + fi +fi + +confirm() { + if [[ $# > 1 ]]; then + echo && read -p "$1 [默认$2]: " temp + if [[ x"${temp}" == x"" ]]; then + temp=$2 + fi + else + read -p "$1 [y/n]: " temp + fi + if [[ x"${temp}" == x"y" || x"${temp}" == x"Y" ]]; then + return 0 + else + return 1 + fi +} + +confirm_restart() { + confirm "是否重启XrayR" "y" + if [[ $? == 0 ]]; then + restart + else + show_menu + fi +} + +before_show_menu() { + echo && echo -n -e "${yellow}按回车返回主菜单: ${plain}" && read temp + show_menu +} + +install() { + bash <(curl -Ls https://raw.githubusercontents.com/Misaka-blog/XrayR-script/master/install.sh) + if [[ $? == 0 ]]; then + if [[ $# == 0 ]]; then + start + else + start 0 + fi + fi +} + +update() { + if [[ $# == 0 ]]; then + echo && echo -n -e "输入指定版本(默认最新版): " && read version + else + version=$2 + fi + bash <(curl -Ls https://raw.githubusercontents.com/Misaka-blog/XrayR-script/master/install.sh) $version + if [[ $? == 0 ]]; then + echo -e "${green}更新完成,已自动重启 XrayR,请使用 XrayR log 查看运行日志${plain}" + exit + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +config() { + echo "XrayR在修改配置后会自动尝试重启" + vi /etc/XrayR/config.yml + sleep 2 + check_status + case $? in + 0) + echo -e "XrayR状态: ${green}已运行${plain}" + ;; + 1) + echo -e "检测到您未启动XrayR或XrayR自动重启失败,是否查看日志?[Y/n]" && echo + read -e -p "(默认: y):" yn + [[ -z ${yn} ]] && yn="y" + if [[ ${yn} == [Yy] ]]; then + show_log + fi + ;; + 2) + echo -e "XrayR状态: ${red}未安装${plain}" + esac +} + +uninstall() { + confirm "确定要卸载 XrayR 吗?" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + systemctl stop XrayR + systemctl disable XrayR + rm /etc/systemd/system/XrayR.service -f + systemctl daemon-reload + systemctl reset-failed + rm /etc/XrayR/ -rf + rm /usr/local/XrayR/ -rf + + echo "" + echo -e "卸载成功,如果你想删除此脚本,则退出脚本后运行 ${green}rm /usr/bin/XrayR -f${plain} 进行删除" + echo "" + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +start() { + check_status + if [[ $? == 0 ]]; then + echo "" + echo -e "${green}XrayR已运行,无需再次启动,如需重启请选择重启${plain}" + else + systemctl start XrayR + sleep 2 + check_status + if [[ $? == 0 ]]; then + echo -e "${green}XrayR 启动成功,请使用 XrayR log 查看运行日志${plain}" + else + echo -e "${red}XrayR可能启动失败,请稍后使用 XrayR log 查看日志信息${plain}" + fi + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +stop() { + systemctl stop XrayR + sleep 2 + check_status + if [[ $? == 1 ]]; then + echo -e "${green}XrayR 停止成功${plain}" + else + echo -e "${red}XrayR停止失败,可能是因为停止时间超过了两秒,请稍后查看日志信息${plain}" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +restart() { + systemctl restart XrayR + sleep 2 + check_status + if [[ $? == 0 ]]; then + echo -e "${green}XrayR 重启成功,请使用 XrayR log 查看运行日志${plain}" + else + echo -e "${red}XrayR可能启动失败,请稍后使用 XrayR log 查看日志信息${plain}" + fi + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +status() { + systemctl status XrayR --no-pager -l + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +enable() { + systemctl enable XrayR + if [[ $? == 0 ]]; then + echo -e "${green}XrayR 设置开机自启成功${plain}" + else + echo -e "${red}XrayR 设置开机自启失败${plain}" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +disable() { + systemctl disable XrayR + if [[ $? == 0 ]]; then + echo -e "${green}XrayR 取消开机自启成功${plain}" + else + echo -e "${red}XrayR 取消开机自启失败${plain}" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +show_log() { + journalctl -u XrayR.service -e --no-pager -f + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +install_bbr() { + bash <(curl -L -s https://raw.githubusercontents.com/chiakge/Linux-NetSpeed/master/tcp.sh) +} + +update_shell() { + wget -O /usr/bin/XrayR -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/XrayR-script/master/XrayR.sh + if [[ $? != 0 ]]; then + echo "" + echo -e "${red}下载脚本失败,请检查本机能否连接 Github${plain}" + before_show_menu + else + chmod +x /usr/bin/XrayR + echo -e "${green}升级脚本成功,请重新运行脚本${plain}" && exit 0 + fi +} + +# 0: running, 1: not running, 2: not installed +check_status() { + if [[ ! -f /etc/systemd/system/XrayR.service ]]; then + return 2 + fi + temp=$(systemctl status XrayR | grep Active | awk '{print $3}' | cut -d "(" -f2 | cut -d ")" -f1) + if [[ x"${temp}" == x"running" ]]; then + return 0 + else + return 1 + fi +} + +check_enabled() { + temp=$(systemctl is-enabled XrayR) + if [[ x"${temp}" == x"enabled" ]]; then + return 0 + else + return 1; + fi +} + +check_uninstall() { + check_status + if [[ $? != 2 ]]; then + echo "" + echo -e "${red}XrayR已安装,请不要重复安装${plain}" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +check_install() { + check_status + if [[ $? == 2 ]]; then + echo "" + echo -e "${red}请先安装XrayR${plain}" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +show_status() { + check_status + case $? in + 0) + echo -e "XrayR状态: ${green}已运行${plain}" + show_enable_status + ;; + 1) + echo -e "XrayR状态: ${yellow}未运行${plain}" + show_enable_status + ;; + 2) + echo -e "XrayR状态: ${red}未安装${plain}" + esac +} + +show_enable_status() { + check_enabled + if [[ $? == 0 ]]; then + echo -e "是否开机自启: ${green}是${plain}" + else + echo -e "是否开机自启: ${red}否${plain}" + fi +} + +show_XrayR_version() { + echo -n "XrayR 版本:" + /usr/local/XrayR/XrayR -version + echo "" + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +generate_config_file() { + echo -e "${yellow}XrayR 配置文件生成向导${plain}" + echo -e "${red}请阅读以下注意事项:${plain}" + echo -e "${red}1. 目前该功能正处测试阶段${plain}" + echo -e "${red}2. 生成的配置文件保存到 /etc/XrayR/config.yml${plain}" + echo -e "${red}3. 原来的配置文件会保存到 /etc/XrayR/config.yml.bak${plain}" + read -p "是否继续生成配置文件?(y/n)" generate_config_file_continue + if [[ $generate_config_file_continue =~ "y"|"Y" ]]; then + echo -e "${yellow}请选择你的机场面板,如未列出则不支持:${plain}" + echo -e "${green}1. SSpanel ${plain}" + echo -e "${green}2. V2board ${plain}" + echo -e "${green}3. PMpanel ${plain}" + echo -e "${green}4. Proxypanel ${plain}" + read -p "请输入机场面板 [1-4,默认1]:" PanelType + case "$PanelType" in + 1 ) PanelType="SSpanel" ;; + 2 ) PanelType="V2board" ;; + 3 ) PanelType="PMpanel" ;; + 4 ) PanelType="Proxypanel" ;; + * ) PanelType="SSpanel" ;; + esac + read -p "请输入机场网址:" ApiHost + read -p "请输入面板对接API Key:" ApiKey + read -p "请输入节点Node ID:" NodeID + echo -e "${yellow}请选择节点传输协议,如未列出则不支持:${plain}" + echo -e "${green}1. Shadowsocks ${plain}" + echo -e "${green}2. Shadowsocks-Plugin ${plain}" + echo -e "${green}3. V2ray ${plain}" + echo -e "${green}4. Trojan ${plain}" + read -p "请输入机场传输协议 [1-4,默认1]:" NodeType + case "$NodeType" in + 1 ) NodeType="Shadowsocks" ;; + 2 ) NodeType="Shadowsocks-Plugin" ;; + 3 ) NodeType="V2ray" ;; + 4 ) NodeType="Trojan" ;; + * ) NodeType="Shadowsocks" ;; + esac + cd /etc/XrayR + mv config.yml config.yml.bak + cat < /etc/XrayR/config.yml +Log: + Level: warning # Log level: none, error, warning, info, debug + AccessPath: # /etc/XrayR/access.Log + ErrorPath: # /etc/XrayR/error.log +DnsConfigPath: # /etc/XrayR/dns.json # Path to dns config, check https://xtls.github.io/config/base/dns/ for help +InboundConfigPath: # /etc/XrayR/custom_inbound.json # Path to custom inbound config, check https://xtls.github.io/config/inbound.html for help +RouteConfigPath: # /etc/XrayR/route.json # Path to route config, check https://xtls.github.io/config/base/route/ for help +OutboundConfigPath: # /etc/XrayR/custom_outbound.json # Path to custom outbound config, check https://xtls.github.io/config/base/outbound/ for help +ConnetionConfig: + Handshake: 4 # Handshake time limit, Second + ConnIdle: 30 # Connection idle time limit, Second + UplinkOnly: 2 # Time limit when the connection downstream is closed, Second + DownlinkOnly: 4 # Time limit when the connection is closed after the uplink is closed, Second + BufferSize: 64 # The internal cache size of each connection, kB +Nodes: + - + PanelType: "$PanelType" # Panel type: SSpanel, V2board, PMpanel, Proxypanel + ApiConfig: + ApiHost: "$ApiHost" + ApiKey: "$ApiKey" + NodeID: $NodeID + NodeType: $NodeType # Node type: V2ray, Shadowsocks, Trojan, Shadowsocks-Plugin + Timeout: 30 # Timeout for the api request + EnableVless: false # Enable Vless for V2ray Type + EnableXTLS: false # Enable XTLS for V2ray and Trojan + SpeedLimit: 0 # Mbps, Local settings will replace remote settings, 0 means disable + DeviceLimit: 0 # Local settings will replace remote settings, 0 means disable + RuleListPath: # /etc/XrayR/rulelist Path to local rulelist file + ControllerConfig: + ListenIP: 0.0.0.0 # IP address you want to listen + SendIP: 0.0.0.0 # IP address you want to send pacakage + UpdatePeriodic: 60 # Time to update the nodeinfo, how many sec. + EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well + DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy + EnableProxyProtocol: false # Only works for WebSocket and TCP + EnableFallback: false # Only support for Trojan and Vless + FallBackConfigs: # Support multiple fallbacks + - + SNI: # TLS SNI(Server Name Indication), Empty for any + Path: # HTTP PATH, Empty for any + Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/fallback/ for details. + ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for dsable + CertConfig: + CertMode: dns # Option about how to get certificate: none, file, http, dns. Choose "none" will forcedly disable the tls config. + CertDomain: "node1.test.com" # Domain to cert + CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file + KeyFile: /etc/XrayR/cert/node1.test.com.key + Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/ + Email: $CF_API_EMAIL # Email for cert + DNSEnv: # DNS ENV option used by DNS provider + CF_API_EMAIL: $CF_API_EMAIL + CF_API_KEY: $CF_API_KEY + CF_DNS_API_TOKEN: $CF_DNS_API_TOKEN + CF_ZONE_API_TOKEN: $CF_ZONE_API_TOKEN +EOF + echo -e "${green}配置文件生成完成,正在重新启动 XrayR 服务${plain}" + xrayr restart + before_show_menu + else + echo -e "${red}已取消配置文件生成${plain}" + before_show_menu + fi +} + +show_usage() { + echo "XrayR 管理脚本使用方法: " + echo "------------------------------------------" + echo "XrayR - 显示管理菜单 (功能更多)" + echo "XrayR start - 启动 XrayR" + echo "XrayR stop - 停止 XrayR" + echo "XrayR restart - 重启 XrayR" + echo "XrayR status - 查看 XrayR 状态" + echo "XrayR enable - 设置 XrayR 开机自启" + echo "XrayR disable - 取消 XrayR 开机自启" + echo "XrayR log - 查看 XrayR 日志" + echo "XrayR update - 更新 XrayR" + echo "XrayR update x.x.x - 更新 XrayR 指定版本" + echo "XrayR install - 安装 XrayR" + echo "XrayR uninstall - 卸载 XrayR" + echo "XrayR version - 查看 XrayR 版本" + echo "------------------------------------------" +} + +show_menu() { + echo -e " + ${green}XrayR 后端管理脚本,${plain}${red}不适用于docker${plain} +--- https://github.com/Misaka-blog/XrayR --- + ${green}0.${plain} 修改配置 +———————————————— + ${green}1.${plain} 安装 XrayR + ${green}2.${plain} 更新 XrayR + ${green}3.${plain} 卸载 XrayR +———————————————— + ${green}4.${plain} 启动 XrayR + ${green}5.${plain} 停止 XrayR + ${green}6.${plain} 重启 XrayR + ${green}7.${plain} 查看 XrayR 状态 + ${green}8.${plain} 查看 XrayR 日志 +———————————————— + ${green}9.${plain} 设置 XrayR 开机自启 + ${green}10.${plain} 取消 XrayR 开机自启 +———————————————— + ${green}11.${plain} 一键安装 bbr (最新内核) + ${green}12.${plain} 查看 XrayR 版本 + ${green}13.${plain} 升级维护脚本 + ${green}14.${plain} 生成 XrayR 配置文件 + " + #后续更新可加入上方字符串中 + show_status + echo && read -p "请输入选择 [0-14]: " num + + case "${num}" in + 0) config ;; + 1) check_uninstall && install ;; + 2) check_install && update ;; + 3) check_install && uninstall ;; + 4) check_install && start ;; + 5) check_install && stop ;; + 6) check_install && restart ;; + 7) check_install && status ;; + 8) check_install && show_log ;; + 9) check_install && enable ;; + 10) check_install && disable ;; + 11) install_bbr ;; + 12) check_install && show_XrayR_version ;; + 13) update_shell ;; + 14) generate_config_file ;; + *) echo -e "${red}请输入正确的数字 [0-14]${plain}" ;; + esac +} + + +if [[ $# > 0 ]]; then + case $1 in + "start") check_install 0 && start 0 ;; + "stop") check_install 0 && stop 0 ;; + "restart") check_install 0 && restart 0 ;; + "status") check_install 0 && status 0 ;; + "enable") check_install 0 && enable 0 ;; + "disable") check_install 0 && disable 0 ;; + "log") check_install 0 && show_log 0 ;; + "update") check_install 0 && update 0 $2 ;; + "config") config $* ;; + "install") check_uninstall 0 && install 0 ;; + "uninstall") check_install 0 && uninstall 0 ;; + "version") check_install 0 && show_XrayR_version 0 ;; + "update_shell") update_shell ;; + *) show_usage + esac +else + show_menu +fi diff --git a/xrayr/XrayR.sh b/xrayr/XrayR.sh new file mode 100644 index 00000000..b0c3c874 --- /dev/null +++ b/xrayr/XrayR.sh @@ -0,0 +1,516 @@ +#!/bin/bash + +red='\033[0;31m' +green='\033[0;32m' +yellow='\033[0;33m' +plain='\033[0m' + +version="v1.0.0" + +# check root +[[ $EUID -ne 0 ]] && echo -e "${red}错误: ${plain} 必须使用root用户运行此脚本!\n" && exit 1 + +# check os +if [[ -f /etc/redhat-release ]]; then + release="centos" +elif cat /etc/issue | grep -Eqi "debian"; then + release="debian" +elif cat /etc/issue | grep -Eqi "ubuntu"; then + release="ubuntu" +elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then + release="centos" +elif cat /proc/version | grep -Eqi "debian"; then + release="debian" +elif cat /proc/version | grep -Eqi "ubuntu"; then + release="ubuntu" +elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then + release="centos" +else + echo -e "${red}未检测到系统版本,请联系脚本作者!${plain}\n" && exit 1 +fi + +os_version="" + +# os version +if [[ -f /etc/os-release ]]; then + os_version=$(awk -F'[= ."]' '/VERSION_ID/{print $3}' /etc/os-release) +fi +if [[ -z "$os_version" && -f /etc/lsb-release ]]; then + os_version=$(awk -F'[= ."]+' '/DISTRIB_RELEASE/{print $2}' /etc/lsb-release) +fi + +if [[ x"${release}" == x"centos" ]]; then + if [[ ${os_version} -le 6 ]]; then + echo -e "${red}请使用 CentOS 7 或更高版本的系统!${plain}\n" && exit 1 + fi +elif [[ x"${release}" == x"ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + echo -e "${red}请使用 Ubuntu 16 或更高版本的系统!${plain}\n" && exit 1 + fi +elif [[ x"${release}" == x"debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + echo -e "${red}请使用 Debian 8 或更高版本的系统!${plain}\n" && exit 1 + fi +fi + +confirm() { + if [[ $# > 1 ]]; then + echo && read -p "$1 [默认$2]: " temp + if [[ x"${temp}" == x"" ]]; then + temp=$2 + fi + else + read -p "$1 [y/n]: " temp + fi + if [[ x"${temp}" == x"y" || x"${temp}" == x"Y" ]]; then + return 0 + else + return 1 + fi +} + +confirm_restart() { + confirm "是否重启XrayR" "y" + if [[ $? == 0 ]]; then + restart + else + show_menu + fi +} + +before_show_menu() { + echo && echo -n -e "${yellow}按回车返回主菜单: ${plain}" && read temp + show_menu +} + +install() { + bash <(curl -Ls https://raw.githubusercontents.com/Misaka-blog/XrayR-script/master/install.sh) + if [[ $? == 0 ]]; then + if [[ $# == 0 ]]; then + start + else + start 0 + fi + fi +} + +update() { + if [[ $# == 0 ]]; then + echo && echo -n -e "输入指定版本(默认最新版): " && read version + else + version=$2 + fi + bash <(curl -Ls https://raw.githubusercontents.com/Misaka-blog/XrayR-script/master/install.sh) $version + if [[ $? == 0 ]]; then + echo -e "${green}更新完成,已自动重启 XrayR,请使用 XrayR log 查看运行日志${plain}" + exit + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +config() { + echo "XrayR在修改配置后会自动尝试重启" + vi /etc/XrayR/config.yml + sleep 2 + check_status + case $? in + 0) + echo -e "XrayR状态: ${green}已运行${plain}" + ;; + 1) + echo -e "检测到您未启动XrayR或XrayR自动重启失败,是否查看日志?[Y/n]" && echo + read -e -p "(默认: y):" yn + [[ -z ${yn} ]] && yn="y" + if [[ ${yn} == [Yy] ]]; then + show_log + fi + ;; + 2) + echo -e "XrayR状态: ${red}未安装${plain}" + esac +} + +uninstall() { + confirm "确定要卸载 XrayR 吗?" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + systemctl stop XrayR + systemctl disable XrayR + rm /etc/systemd/system/XrayR.service -f + systemctl daemon-reload + systemctl reset-failed + rm /etc/XrayR/ -rf + rm /usr/local/XrayR/ -rf + + echo "" + echo -e "卸载成功,如果你想删除此脚本,则退出脚本后运行 ${green}rm /usr/bin/XrayR -f${plain} 进行删除" + echo "" + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +start() { + check_status + if [[ $? == 0 ]]; then + echo "" + echo -e "${green}XrayR已运行,无需再次启动,如需重启请选择重启${plain}" + else + systemctl start XrayR + sleep 2 + check_status + if [[ $? == 0 ]]; then + echo -e "${green}XrayR 启动成功,请使用 XrayR log 查看运行日志${plain}" + else + echo -e "${red}XrayR可能启动失败,请稍后使用 XrayR log 查看日志信息${plain}" + fi + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +stop() { + systemctl stop XrayR + sleep 2 + check_status + if [[ $? == 1 ]]; then + echo -e "${green}XrayR 停止成功${plain}" + else + echo -e "${red}XrayR停止失败,可能是因为停止时间超过了两秒,请稍后查看日志信息${plain}" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +restart() { + systemctl restart XrayR + sleep 2 + check_status + if [[ $? == 0 ]]; then + echo -e "${green}XrayR 重启成功,请使用 XrayR log 查看运行日志${plain}" + else + echo -e "${red}XrayR可能启动失败,请稍后使用 XrayR log 查看日志信息${plain}" + fi + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +status() { + systemctl status XrayR --no-pager -l + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +enable() { + systemctl enable XrayR + if [[ $? == 0 ]]; then + echo -e "${green}XrayR 设置开机自启成功${plain}" + else + echo -e "${red}XrayR 设置开机自启失败${plain}" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +disable() { + systemctl disable XrayR + if [[ $? == 0 ]]; then + echo -e "${green}XrayR 取消开机自启成功${plain}" + else + echo -e "${red}XrayR 取消开机自启失败${plain}" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +show_log() { + journalctl -u XrayR.service -e --no-pager -f + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +install_bbr() { + bash <(curl -L -s https://raw.githubusercontents.com/chiakge/Linux-NetSpeed/master/tcp.sh) +} + +update_shell() { + wget -O /usr/bin/XrayR -N --no-check-certificate https://raw.githubusercontents.com/Misaka-blog/XrayR-script/master/XrayR.sh + if [[ $? != 0 ]]; then + echo "" + echo -e "${red}下载脚本失败,请检查本机能否连接 Github${plain}" + before_show_menu + else + chmod +x /usr/bin/XrayR + echo -e "${green}升级脚本成功,请重新运行脚本${plain}" && exit 0 + fi +} + +# 0: running, 1: not running, 2: not installed +check_status() { + if [[ ! -f /etc/systemd/system/XrayR.service ]]; then + return 2 + fi + temp=$(systemctl status XrayR | grep Active | awk '{print $3}' | cut -d "(" -f2 | cut -d ")" -f1) + if [[ x"${temp}" == x"running" ]]; then + return 0 + else + return 1 + fi +} + +check_enabled() { + temp=$(systemctl is-enabled XrayR) + if [[ x"${temp}" == x"enabled" ]]; then + return 0 + else + return 1; + fi +} + +check_uninstall() { + check_status + if [[ $? != 2 ]]; then + echo "" + echo -e "${red}XrayR已安装,请不要重复安装${plain}" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +check_install() { + check_status + if [[ $? == 2 ]]; then + echo "" + echo -e "${red}请先安装XrayR${plain}" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +show_status() { + check_status + case $? in + 0) + echo -e "XrayR状态: ${green}已运行${plain}" + show_enable_status + ;; + 1) + echo -e "XrayR状态: ${yellow}未运行${plain}" + show_enable_status + ;; + 2) + echo -e "XrayR状态: ${red}未安装${plain}" + esac +} + +show_enable_status() { + check_enabled + if [[ $? == 0 ]]; then + echo -e "是否开机自启: ${green}是${plain}" + else + echo -e "是否开机自启: ${red}否${plain}" + fi +} + +show_XrayR_version() { + echo -n "XrayR 版本:" + /usr/local/XrayR/XrayR -version + echo "" + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +generate_config_file() { + echo -e "${yellow}XrayR 配置文件生成向导${plain}" + echo -e "${red}请阅读以下注意事项:${plain}" + echo -e "${red}1. 目前该功能正处测试阶段${plain}" + echo -e "${red}2. 生成的配置文件保存到 /etc/XrayR/config.yml${plain}" + echo -e "${red}3. 原来的配置文件会保存到 /etc/XrayR/config.yml.bak${plain}" + read -p "是否继续生成配置文件?(y/n)" generate_config_file_continue + if [[ $generate_config_file_continue =~ "y"|"Y" ]]; then + read -p "请输入机场面板:" PanelType + read -p "请输入机场网址:" ApiHost + read -p "请输入面板对接API Key:" ApiKey + read -p "请输入节点Node ID:" NodeID + read -p "请输入节点类型:" NodeType + cd /etc/XrayR + mv config.yml config.yml.bak + cat < /etc/XrayR/config.yml +Log: + Level: warning # Log level: none, error, warning, info, debug + AccessPath: # /etc/XrayR/access.Log + ErrorPath: # /etc/XrayR/error.log +DnsConfigPath: # /etc/XrayR/dns.json # Path to dns config, check https://xtls.github.io/config/base/dns/ for help +InboundConfigPath: # /etc/XrayR/custom_inbound.json # Path to custom inbound config, check https://xtls.github.io/config/inbound.html for help +RouteConfigPath: # /etc/XrayR/route.json # Path to route config, check https://xtls.github.io/config/base/route/ for help +OutboundConfigPath: # /etc/XrayR/custom_outbound.json # Path to custom outbound config, check https://xtls.github.io/config/base/outbound/ for help +ConnetionConfig: + Handshake: 4 # Handshake time limit, Second + ConnIdle: 30 # Connection idle time limit, Second + UplinkOnly: 2 # Time limit when the connection downstream is closed, Second + DownlinkOnly: 4 # Time limit when the connection is closed after the uplink is closed, Second + BufferSize: 64 # The internal cache size of each connection, kB +Nodes: + - + PanelType: "$PanelType" # Panel type: SSpanel, V2board, PMpanel, Proxypanel + ApiConfig: + ApiHost: "$ApiHost" + ApiKey: "$ApiKey" + NodeID: $NodeID + NodeType: $NodeType # Node type: V2ray, Shadowsocks, Trojan, Shadowsocks-Plugin + Timeout: 30 # Timeout for the api request + EnableVless: false # Enable Vless for V2ray Type + EnableXTLS: false # Enable XTLS for V2ray and Trojan + SpeedLimit: 0 # Mbps, Local settings will replace remote settings, 0 means disable + DeviceLimit: 0 # Local settings will replace remote settings, 0 means disable + RuleListPath: # /etc/XrayR/rulelist Path to local rulelist file + ControllerConfig: + ListenIP: 0.0.0.0 # IP address you want to listen + SendIP: 0.0.0.0 # IP address you want to send pacakage + UpdatePeriodic: 60 # Time to update the nodeinfo, how many sec. + EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well + DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy + EnableProxyProtocol: false # Only works for WebSocket and TCP + EnableFallback: false # Only support for Trojan and Vless + FallBackConfigs: # Support multiple fallbacks + - + SNI: # TLS SNI(Server Name Indication), Empty for any + Path: # HTTP PATH, Empty for any + Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/fallback/ for details. + ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for dsable + CertConfig: + CertMode: dns # Option about how to get certificate: none, file, http, dns. Choose "none" will forcedly disable the tls config. + CertDomain: "node1.test.com" # Domain to cert + CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file + KeyFile: /etc/XrayR/cert/node1.test.com.key + Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/ + Email: test@me.com + DNSEnv: # DNS ENV option used by DNS provider + ALICLOUD_ACCESS_KEY: aaa + ALICLOUD_SECRET_KEY: bbb +EOF + echo -e "${green}配置文件生成完成,正在重新启动 XrayR 服务${plain}" + xrayr restart + before_show_menu + else + echo -e "${red}已取消配置文件生成${plain}" + before_show_menu + fi +} + +show_usage() { + echo "XrayR 管理脚本使用方法: " + echo "------------------------------------------" + echo "XrayR - 显示管理菜单 (功能更多)" + echo "XrayR start - 启动 XrayR" + echo "XrayR stop - 停止 XrayR" + echo "XrayR restart - 重启 XrayR" + echo "XrayR status - 查看 XrayR 状态" + echo "XrayR enable - 设置 XrayR 开机自启" + echo "XrayR disable - 取消 XrayR 开机自启" + echo "XrayR log - 查看 XrayR 日志" + echo "XrayR update - 更新 XrayR" + echo "XrayR update x.x.x - 更新 XrayR 指定版本" + echo "XrayR install - 安装 XrayR" + echo "XrayR uninstall - 卸载 XrayR" + echo "XrayR version - 查看 XrayR 版本" + echo "------------------------------------------" +} + +show_menu() { + echo -e " + ${green}XrayR 后端管理脚本,${plain}${red}不适用于docker${plain} +--- https://github.com/Misaka-blog/XrayR --- + ${green}0.${plain} 修改配置 +———————————————— + ${green}1.${plain} 安装 XrayR + ${green}2.${plain} 更新 XrayR + ${green}3.${plain} 卸载 XrayR +———————————————— + ${green}4.${plain} 启动 XrayR + ${green}5.${plain} 停止 XrayR + ${green}6.${plain} 重启 XrayR + ${green}7.${plain} 查看 XrayR 状态 + ${green}8.${plain} 查看 XrayR 日志 +———————————————— + ${green}9.${plain} 设置 XrayR 开机自启 + ${green}10.${plain} 取消 XrayR 开机自启 +———————————————— + ${green}11.${plain} 一键安装 bbr (最新内核) + ${green}12.${plain} 查看 XrayR 版本 + ${green}13.${plain} 升级维护脚本 + ${green}14.${plain} 生成 XrayR 配置文件 + " + #后续更新可加入上方字符串中 + show_status + echo && read -p "请输入选择 [0-14]: " num + + case "${num}" in + 0) config ;; + 1) check_uninstall && install ;; + 2) check_install && update ;; + 3) check_install && uninstall ;; + 4) check_install && start ;; + 5) check_install && stop ;; + 6) check_install && restart ;; + 7) check_install && status ;; + 8) check_install && show_log ;; + 9) check_install && enable ;; + 10) check_install && disable ;; + 11) install_bbr ;; + 12) check_install && show_XrayR_version ;; + 13) update_shell ;; + 14) generate_config ;; + *) echo -e "${red}请输入正确的数字 [0-14]${plain}" ;; + esac +} + + +if [[ $# > 0 ]]; then + case $1 in + "start") check_install 0 && start 0 ;; + "stop") check_install 0 && stop 0 ;; + "restart") check_install 0 && restart 0 ;; + "status") check_install 0 && status 0 ;; + "enable") check_install 0 && enable 0 ;; + "disable") check_install 0 && disable 0 ;; + "log") check_install 0 && show_log 0 ;; + "update") check_install 0 && update 0 $2 ;; + "config") config $* ;; + "install") check_uninstall 0 && install 0 ;; + "uninstall") check_install 0 && uninstall 0 ;; + "version") check_install 0 && show_XrayR_version 0 ;; + "update_shell") update_shell ;; + *) show_usage + esac +else + show_menu +fi diff --git a/xrayr/config.yml b/xrayr/config.yml new file mode 100644 index 00000000..5e1f3a86 --- /dev/null +++ b/xrayr/config.yml @@ -0,0 +1,78 @@ +Log: + Level: warning # Log level: none, error, warning, info, debug + AccessPath: # /etc/XrayR/access.Log + ErrorPath: # /etc/XrayR/error.log +DnsConfigPath: # /etc/XrayR/dns.json # Path to dns config, check https://xtls.github.io/config/base/dns/ for help +InboundConfigPath: # /etc/XrayR/custom_inbound.json # Path to custom inbound config, check https://xtls.github.io/config/inbound.html for help +RouteConfigPath: # /etc/XrayR/route.json # Path to route config, check https://xtls.github.io/config/base/route/ for help +OutboundConfigPath: # /etc/XrayR/custom_outbound.json # Path to custom outbound config, check https://xtls.github.io/config/base/outbound/ for help +ConnetionConfig: + Handshake: 4 # Handshake time limit, Second + ConnIdle: 30 # Connection idle time limit, Second + UplinkOnly: 2 # Time limit when the connection downstream is closed, Second + DownlinkOnly: 4 # Time limit when the connection is closed after the uplink is closed, Second + BufferSize: 64 # The internal cache size of each connection, kB +Nodes: + - + PanelType: "SSpanel" # Panel type: SSpanel, V2board, PMpanel, Proxypanel + ApiConfig: + ApiHost: "http://127.0.0.1:667" + ApiKey: "123" + NodeID: 41 + NodeType: V2ray # Node type: V2ray, Shadowsocks, Trojan, Shadowsocks-Plugin + Timeout: 30 # Timeout for the api request + EnableVless: false # Enable Vless for V2ray Type + EnableXTLS: false # Enable XTLS for V2ray and Trojan + SpeedLimit: 0 # Mbps, Local settings will replace remote settings, 0 means disable + DeviceLimit: 0 # Local settings will replace remote settings, 0 means disable + RuleListPath: # /etc/XrayR/rulelist Path to local rulelist file + ControllerConfig: + ListenIP: 0.0.0.0 # IP address you want to listen + SendIP: 0.0.0.0 # IP address you want to send pacakage + UpdatePeriodic: 60 # Time to update the nodeinfo, how many sec. + EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well + DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy + EnableProxyProtocol: false # Only works for WebSocket and TCP + EnableFallback: false # Only support for Trojan and Vless + FallBackConfigs: # Support multiple fallbacks + - + SNI: # TLS SNI(Server Name Indication), Empty for any + Path: # HTTP PATH, Empty for any + Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/fallback/ for details. + ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for dsable + CertConfig: + CertMode: dns # Option about how to get certificate: none, file, http, dns. Choose "none" will forcedly disable the tls config. + CertDomain: "node1.test.com" # Domain to cert + CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file + KeyFile: /etc/XrayR/cert/node1.test.com.key + Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/ + Email: test@me.com + DNSEnv: # DNS ENV option used by DNS provider + ALICLOUD_ACCESS_KEY: aaa + ALICLOUD_SECRET_KEY: bbb + # - + # PanelType: "V2board" # Panel type: SSpanel, V2board + # ApiConfig: + # ApiHost: "http://127.0.0.1:668" + # ApiKey: "123" + # NodeID: 4 + # NodeType: Shadowsocks # Node type: V2ray, Shadowsocks, Trojan + # Timeout: 30 # Timeout for the api request + # EnableVless: false # Enable Vless for V2ray Type + # EnableXTLS: false # Enable XTLS for V2ray and Trojan + # SpeedLimit: 0 # Mbps, Local settings will replace remote settings + # DeviceLimit: 0 # Local settings will replace remote settings + # ControllerConfig: + # ListenIP: 0.0.0.0 # IP address you want to listen + # UpdatePeriodic: 10 # Time to update the nodeinfo, how many sec. + # EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well + # CertConfig: + # CertMode: dns # Option about how to get certificate: none, file, http, dns + # CertDomain: "node1.test.com" # Domain to cert + # CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file + # KeyFile: /etc/XrayR/cert/node1.test.com.pem + # Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/ + # Email: test@me.com + # DNSEnv: # DNS ENV option used by DNS provider + # ALICLOUD_ACCESS_KEY: aaa + # ALICLOUD_SECRET_KEY: bbb diff --git a/xrayr/generate.sh b/xrayr/generate.sh new file mode 100644 index 00000000..af475bf5 --- /dev/null +++ b/xrayr/generate.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# XrayR generate config beta 0.1 + +read -p "请输入机场面板:" PanelType +read -p "请输入机场网址:" ApiHost +read -p "请输入面板对接API Key:" ApiKey +read -p "请输入节点Node ID:" NodeID +read -p "请输入节点类型:" NodeType +cd /etc/XrayR +mv config.yml config.yml.bak +cat < /etc/XrayR/config.yml +Log: + Level: warning # Log level: none, error, warning, info, debug + AccessPath: # /etc/XrayR/access.Log + ErrorPath: # /etc/XrayR/error.log +DnsConfigPath: # /etc/XrayR/dns.json # Path to dns config, check https://xtls.github.io/config/base/dns/ for help +InboundConfigPath: # /etc/XrayR/custom_inbound.json # Path to custom inbound config, check https://xtls.github.io/config/inbound.html for help +RouteConfigPath: # /etc/XrayR/route.json # Path to route config, check https://xtls.github.io/config/base/route/ for help +OutboundConfigPath: # /etc/XrayR/custom_outbound.json # Path to custom outbound config, check https://xtls.github.io/config/base/outbound/ for help +ConnetionConfig: + Handshake: 4 # Handshake time limit, Second + ConnIdle: 30 # Connection idle time limit, Second + UplinkOnly: 2 # Time limit when the connection downstream is closed, Second + DownlinkOnly: 4 # Time limit when the connection is closed after the uplink is closed, Second + BufferSize: 64 # The internal cache size of each connection, kB +Nodes: + - + PanelType: "$PanelType" # Panel type: SSpanel, V2board, PMpanel, Proxypanel + ApiConfig: + ApiHost: "$ApiHost" + ApiKey: "$ApiKey" + NodeID: $NodeID + NodeType: $NodeType # Node type: V2ray, Shadowsocks, Trojan, Shadowsocks-Plugin + Timeout: 30 # Timeout for the api request + EnableVless: false # Enable Vless for V2ray Type + EnableXTLS: false # Enable XTLS for V2ray and Trojan + SpeedLimit: 0 # Mbps, Local settings will replace remote settings, 0 means disable + DeviceLimit: 0 # Local settings will replace remote settings, 0 means disable + RuleListPath: # /etc/XrayR/rulelist Path to local rulelist file + ControllerConfig: + ListenIP: 0.0.0.0 # IP address you want to listen + SendIP: 0.0.0.0 # IP address you want to send pacakage + UpdatePeriodic: 60 # Time to update the nodeinfo, how many sec. + EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well + DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy + EnableProxyProtocol: false # Only works for WebSocket and TCP + EnableFallback: false # Only support for Trojan and Vless + FallBackConfigs: # Support multiple fallbacks + - + SNI: # TLS SNI(Server Name Indication), Empty for any + Path: # HTTP PATH, Empty for any + Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/fallback/ for details. + ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for dsable + CertConfig: + CertMode: dns # Option about how to get certificate: none, file, http, dns. Choose "none" will forcedly disable the tls config. + CertDomain: "node1.test.com" # Domain to cert + CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file + KeyFile: /etc/XrayR/cert/node1.test.com.key + Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/ + Email: test@me.com + DNSEnv: # DNS ENV option used by DNS provider + ALICLOUD_ACCESS_KEY: aaa + ALICLOUD_SECRET_KEY: bbb +EOF \ No newline at end of file