#!/usr/bin/env bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

sh_ver="1.9.0"
sh_url="dl.nmm.li"

Update_Shell(){
	echo -e "当前版本为 [ ${sh_ver} ]，开始检测最新版本..."
	sh_new_ver=$(wget --no-check-certificate -qO- "https://${sh_url}/vnet/vnet.sh"|grep 'sh_ver="'|awk -F "=" '{print $NF}'|sed 's/\"//g'|head -1)
	[[ -z ${sh_new_ver} ]] && echo -e "${Error} 检测最新版本失败 !" && vnetxl
	if [[ ${sh_new_ver} != ${sh_ver} ]]; then
		echo -e "发现新版本[ ${sh_new_ver} ]，是否更新？[Y/n]"
		read -p "(默认: y):" yn
		[[ -z "${yn}" ]] && yn="y"
		if [[ ${yn} == [Yy] ]]; then
			wget -N --no-check-certificate https://${sh_url}/vnet/vnet.sh && chmod +x vnet.sh
			echo -e "脚本已更新为最新版本[ ${sh_new_ver} ] !"
		else
			echo && echo "	已取消..." && echo
		fi
	else
		echo -e "当前已是最新版本[ ${sh_new_ver} ] !"
		sleep 3s
	fi
	exit 0
}

check_sys(){
	if [[ -f /etc/redhat-release ]]; then
		release="centos"
	elif cat /etc/issue | grep -q -E -i "debian"; then
		release="debian"
	elif cat /etc/issue | grep -q -E -i "ubuntu"; then
		release="ubuntu"
	elif cat /etc/issue | grep -q -E -i "centos|red hat|redhat"; then
		release="centos"
	elif cat /proc/version | grep -q -E -i "debian"; then
		release="debian"
	elif cat /proc/version | grep -q -E -i "ubuntu"; then
		release="ubuntu"
	elif cat /proc/version | grep -q -E -i "centos|red hat|redhat"; then
		release="centos"
    fi
}

check_version(){
	if [[ -s /etc/redhat-release ]]; then
		version=`grep -oE  "[0-9.]+" /etc/redhat-release | cut -d . -f 1`
	else
		version=`grep -oE  "[0-9.]+" /etc/issue | cut -d . -f 1`
	fi
	bit=`uname -m`
	if [[ ${bit} = "x86_64" ]]; then
		bit="x64"
	else
		bit="x32"
	fi
}

optimizesystem(){
    echo "--------------------------------------------------"
    echo "                  正在更新系统中                  "
    echo "--------------------------------------------------"
    if [[ ${release} == "centos" ]]; then
        yum makecache
        yum install epel-release curl -y
        yum update -y
    else
        apt update -y
        apt dist-upgrade -y
        apt --fix-broken install -y
        apt install curl -y
    fi
	
	echo "--------------------------------------------------"
    echo "            正在安装 haveged 增强性能中           "
    echo "--------------------------------------------------"
    if [[ ${release} == "centos" ]]; then
        yum install haveged -y
    else
        apt install haveged -y
    fi
    
    echo "--------------------------------------------------"
    echo "            正在配置 haveged 增强性能中           "
    echo "--------------------------------------------------"
    systemctl disable haveged
    systemctl enable haveged
    systemctl restart haveged
    
    echo "--------------------------------------------------"
    echo "               正在优化系统内核参数中             "
    echo "--------------------------------------------------"
    echo "fs.file-max = 65535" >/etc/sysctl.conf
    echo "fs.inotify.max_user_instances = 8192" >>/etc/sysctl.conf
    echo "net.core.rmem_max = 67108864" >>/etc/sysctl.conf
    echo "net.core.wmem_max = 67108864" >>/etc/sysctl.conf
    echo "net.core.netdev_max_backlog = 250000" >>/etc/sysctl.conf
    echo "net.core.somaxconn = 65535" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_syncookies = 1" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_syn_retries = 1" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_synack_retries = 1" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_tw_reuse = 1" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_timestamps = 0" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_fin_timeout = 30" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_keepalive_time = 1200" >>/etc/sysctl.conf
    echo "net.ipv4.ip_local_port_range = 10000 65000" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_max_syn_backlog = 8192" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_max_tw_buckets = 6000" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_max_orphans = 32768" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_fastopen = 3" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_rmem = 4096 87380 67108864" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_wmem = 4096 65536 67108864" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_mtu_probing = 1" >>/etc/sysctl.conf
    echo "net.ipv4.route.gc_timeout = 100" >>/etc/sysctl.conf
    echo "net.ipv4.ip_forward = 1" >>/etc/sysctl.conf
    echo "net.core.default_qdisc = fq" >>/etc/sysctl.conf
    echo "net.ipv4.tcp_congestion_control = bbr" >>/etc/sysctl.conf
    echo "* soft nofile 65535" >/etc/security/limits.conf
    echo "* hard nofile 65535" >>/etc/security/limits.conf
    echo "* soft nproc 65535" >>/etc/security/limits.conf
    echo "* hard nproc 65535" >>/etc/security/limits.conf
    echo "ulimit -SHn 1000000">>/etc/profile
    sysctl -p
}

restart_to_take_effect(){
    read -p "需要重启VPS后，才能生效系统优化配置，是否现在重启 ? [Y/n] :" yn
	[ -z "${yn}" ] && yn="y"
	if [[ $yn == [Yy] ]]; then
		echo -e " VPS 重启中..."
		reboot
	fi
}

error_tip(){
    echo 输入错误，请重新操作！
    exit 1
}

vnetxl(){
echo " Vnet魔改优化版 一键脚本 [v${sh_ver}]
	1，安装Vnet
	2，添加客户端配置
	3，添加服务端配置
	4，列出/删除客户端配置
	5，列出/删除服务端配置
	6，启用Vnet客户端（安装后启动一次即可）
	7，启用Vnet服务端（安装后启动一次即可）
	8，加载客户端配置文件
	9，加载服务端配置文件
	10，查看所有日志
	11，最新使用说明
	12，完整删除Vnet
	00，检查脚本更新
	注意！！！不要在web端操作
	"
read -p "请选择（数字）：" vnet_num1
case "$vnet_num1" in
	1)
	echo "--------------------------------------------------"
    echo "               正在安装常用程序                   "
    echo "--------------------------------------------------"
    if [[ ${release} == "centos" ]]; then
        yum install unzip jq -y
    else
        apt install unzip jq -y
    fi
    optimizesystem
	echo "--------------------------------------------------"
    echo "                 正在安装Vnet                     "
    echo "--------------------------------------------------"
    rm -f tunnel.zip
    wget http://${sh_url}/vnet/tunnel.zip
    mkdir /root/vnettunnel
	mv tunnel.zip /root/vnettunnel/tunnel.zip
	cd /root/vnettunnel
	unzip -o tunnel.zip
	chmod -R +x ./*
	echo "--------------------------------------------------"
    echo "                 Vnet安装完成                     "
    echo "--------------------------------------------------"
    restart_to_take_effect
	;;
	2)
	read -p "本地域名或IP（默认 0.0.0.0）：" yn2
		[[ -z "${yn2}" ]] && yn2="0.0.0.0"
		if [[ ${yn2} != [0.0.0.0] ]]; then
		    hostpz=${yn2}
		else
			hostpz="0.0.0.0"
		fi
	read -p "本地端口：" portpz
	[[ "$portpz" -le 65535 ]] && [[ "$portpz" -gt 0 ]] || error_tip
	read -p "启用TLS？ y/n(默认: n):" yn1
		[[ -z "${yn1}" ]] && yn1="n"
		if [[ ${yn1} == [Yy] ]]; then
		    tlspz="true"
		else
			tlspz="false"
		fi
	read -p "伪装域名（可选）：" domainpz
	read -p "远程域名或IP：" host2pz
	read -p "远程端口：" port2pz
	[[ "$port2pz" -le 65535 ]] && [[ "$port2pz" -gt 0 ]] || error_tip
	if [[ ${portpz} == ${port2pz} ]]; then
		    echo "错误！！远程端口不能与监听端口一致"
		    exit 1
		fi
	read -p "远程路径（默认 tunnel）：" yn3
		[[ -z "${yn3}" ]] && yn3="tunnel"
		if [[ ${yn3} != [tunnel] ]]; then
		    pathpz=${yn3}
		else
			pathpz="tunnel"
		fi
	echo '{"local":{"host":"'${hostpz}'","port":'${portpz}'},"remote":{"tls":'${tlspz}',"host":"'${host2pz}'","domain":"'${domainpz}'","port":'${port2pz}',"path":"'${pathpz}'"}}' >>/root/vnettunnel/vnet_client_config
	echo '{"local":{"host":"'${hostpz}'","port":'${portpz}'},"remote":{"tls":'${tlspz}',"host":"'${host2pz}'","domain":"'${domainpz}'","port":'${port2pz}',"path":"'${pathpz}'"}}' >/root/vnettunnel/vnetnew_config
	vnetnew_config=$(cat /root/vnettunnel/vnetnew_config)
	curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d $vnetnew_config http://127.0.0.1:8080/client/add
	;;
	3)
	read -p "启用TLS？ y/n(默认: n):" yn1
		[[ -z "${yn1}" ]] && yn1="n"
		if [[ ${yn1} == [Yy] ]]; then
		    tlspz="true"
		else
			tlspz="false"
		fi
	read -p "本地域名或IP（默认 0.0.0.0）：" yn2
		[[ -z "${yn2}" ]] && yn2="0.0.0.0"
		if [[ ${yn2} != [0.0.0.0] ]]; then
		    hostpz=${yn2}
		else
			hostpz="0.0.0.0"
		fi
	read -p "本地端口：" portpz
	[[ "$portpz" -le 65535 ]] && [[ "$portpz" -gt 0 ]] || error_tip
	read -p "本地路径（默认 tunnel）：" yn3
		[[ -z "${yn3}" ]] && yn3="tunnel"
		if [[ ${yn3} != [tunnel] ]]; then
		    pathpz=${yn3}
		else
			pathpz="tunnel"
		fi
	read -p "远程域名或IP：" host2pz
	read -p "远程端口：" port2pz
	[[ "$port2pz" -le 65535 ]] && [[ "$port2pz" -gt 0 ]] || error_tip
	if [[ ${portpz} == ${port2pz} ]]; then
		    echo "错误！！远程端口不能与监听端口一致"
		    exit 1
		fi
	echo '{"local":{"tls":'${tlspz}',"host":"'${hostpz}'","port":'${portpz}',"path":"'${pathpz}'"},"remote":{"host":"'${host2pz}'","port":'${port2pz}'}}' >>/root/vnettunnel/vnet_server_config
	echo '{"local":{"tls":'${tlspz}',"host":"'${hostpz}'","port":'${portpz}',"path":"'${pathpz}'"},"remote":{"host":"'${host2pz}'","port":'${port2pz}'}}' >/root/vnettunnel/vnetnew_config
	vnetnew_config=$(cat /root/vnettunnel/vnetnew_config)
	curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d $vnetnew_config http://127.0.0.1:8081/server/add
	;;
	4)
	zonghangshu=$(cat /root/vnettunnel/vnet_client_config |wc -l)
	i=1; while (( $i <= $zonghangshu )); do a123=$(sed -n "${i}p" /root/vnettunnel/vnet_client_config)&&echo $a123; ((i=$i+1)); done;
	read -p "是否要删除规则？ y/n(默认: n):" yn1
		[[ -z "${yn1}" ]] && yn1="n"
		if [[ ${yn1} == [Yy] ]]; then
		    curl -s http://127.0.0.1:8080/client/list | jq '.'
		    curl -s http://127.0.0.1:8080/client/list | jq '.[].id' >/root/vnettunnel/vnet_del
		    read -p "请输入你要删除的规则的id：" del_id1
		    del_id2=$(grep -n "$del_id1" /root/vnettunnel/vnet_del)
		    echo "删除第${del_id2%:*}行规则完成"
		    sed -i "${del_id2%:*}d" /root/vnettunnel/vnet_client_config
		    curl -H "Accept: application/json" -H "Content-type: application/json" -X POST http://127.0.0.1:8080/client/del/${del_id1}
		else
			exit 0
		fi
	;;
	5)
	zonghangshu=$(cat /root/vnettunnel/vnet_server_config |wc -l)
	i=1; while (( $i <= $zonghangshu )); do a123=$(sed -n "${i}p" /root/vnettunnel/vnet_server_config)&&echo $a123; ((i=$i+1)); done;
	read -p "是否要删除规则？ y/n(默认: n):" yn1
		[[ -z "${yn1}" ]] && yn1="n"
		if [[ ${yn1} == [Yy] ]]; then
		    curl -s http://127.0.0.1:8081/server/list | jq '.'
		    curl -s http://127.0.0.1:8081/server/list | jq '.[].id' >/root/vnettunnel/vnet_del
		    read -p "请输入你要删除的规则的id：" del_id1
		    del_id2=$(grep -n "$del_id1" /root/vnettunnel/vnet_del)
		    echo "删除第${del_id2%:*}行规则完成"
		    sed -i "${del_id2%:*}d" /root/vnettunnel/vnet_server_config
		    curl -H "Accept: application/json" -H "Content-type: application/json" -X POST http://127.0.0.1:8081/server/del/${del_id1}
		else
			exit 0
		fi
	;;
	6)
	echo "--------------------------------------------------"
    echo "                 写入自启文件                     "
    echo "--------------------------------------------------"
	echo '#!/usr/bin/env bash' >/root/vnettunnel/vnet_crontab.sh
	echo 'PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin' >>/root/vnettunnel/vnet_crontab.sh
	echo 'export PATH' >>/root/vnettunnel/vnet_crontab.sh
	echo 'cd /root/vnettunnel' >>/root/vnettunnel/vnet_crontab.sh
	echo 'nohup ./client > /root/vnettunnel/vnet_log 2>&1 &' >>/root/vnettunnel/vnet_crontab.sh
	echo 'sleep 5s' >>/root/vnettunnel/vnet_crontab.sh
	echo 'zonghangshu=$(cat /root/vnettunnel/vnet_client_config |wc -l)' >>/root/vnettunnel/vnet_crontab.sh
	echo 'i=1; while (( $i <= $zonghangshu )); do a123=$(sed -n "${i}p" /root/vnettunnel/vnet_client_config)&&curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d $a123 http://127.0.0.1:8080/client/add; ((i=$i+1)); done;' >>/root/vnettunnel/vnet_crontab.sh
	sed -i "/vnet_crontab.sh/d" /etc/crontab
	echo "@reboot root ~/vnettunnel/vnet_crontab.sh" >> /etc/crontab
	chmod +x /root/vnettunnel/vnet_crontab.sh
	echo "--------------------------------------------------"
    echo "                 10s后启动Vnet                    "
    echo "--------------------------------------------------"
	bash /root/vnettunnel/vnet_crontab.sh
	echo "--------------------------------------------------"
    echo "                   Vnet已启动                     "
    echo "--------------------------------------------------"
	;;
	7)
	echo "--------------------------------------------------"
    echo "                 写入自启文件                     "
    echo "--------------------------------------------------"
	echo '#!/usr/bin/env bash' >/root/vnettunnel/vnet_crontab.sh
	echo 'PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin' >>/root/vnettunnel/vnet_crontab.sh
	echo 'export PATH' >>/root/vnettunnel/vnet_crontab.sh
	echo 'cd /root/vnettunnel' >>/root/vnettunnel/vnet_crontab.sh
	echo 'nohup ./server > /root/vnettunnel/vnet_log 2>&1 &' >>/root/vnettunnel/vnet_crontab.sh
	echo 'sleep 10s' >>/root/vnettunnel/vnet_crontab.sh
	echo 'zonghangshu=$(cat /root/vnettunnel/vnet_server_config |wc -l)' >>/root/vnettunnel/vnet_crontab.sh
	echo 'i=1; while (( $i <= $zonghangshu )); do a123=$(sed -n "${i}p" /root/vnettunnel/vnet_server_config)&&curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d $a123 http://127.0.0.1:8081/server/add; ((i=$i+1)); done;' >>/root/vnettunnel/vnet_crontab.sh
	sed -i "/vnet_crontab.sh/d" /etc/crontab
	echo "@reboot root ~/vnettunnel/vnet_crontab.sh" >> /etc/crontab
	chmod +x /root/vnettunnel/vnet_crontab.sh
	echo "--------------------------------------------------"
    echo "                 10s后启动Vnet                    "
    echo "--------------------------------------------------"
	bash /root/vnettunnel/vnet_crontab.sh
	echo "--------------------------------------------------"
    echo "                   Vnet已启动                     "
    echo "--------------------------------------------------"
	;;
	8)
	zonghangshu=$(cat /root/vnettunnel/vnet_client_config |wc -l)
	i=1; while (( $i <= $zonghangshu )); do a123=$(sed -n "${i}p" /root/vnettunnel/vnet_client_config)&&curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d $a123 http://127.0.0.1:8080/client/add&&echo $i; ((i=$i+1)); done;
	;;
	9)
	zonghangshu=$(cat /root/vnettunnel/vnet_server_config |wc -l)
	i=1; while (( $i <= $zonghangshu )); do a123=$(sed -n "${i}p" /root/vnettunnel/vnet_server_config)&&curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d $a123 http://127.0.0.1:8081/server/add&&echo $i; ((i=$i+1)); done;
	;;
	10)
	vnet_cat_log
	;;
	11)
	wget -O /root/readme.txt http://${sh_url}/vnet/readme.txt
	cat /root/readme.txt
	sleep 3s
	vnetxl
	;;
	12)
	rm -rf /root/vnettunnel
	sed -i "/vnet_crontab.sh/d" /etc/crontab
	echo "重启服务器后将完全删除，如需重装Vnet，请重启服务器"
	exit 0
	;;
	00)
	Update_Shell
	;;
	*)
	echo "请重新选择！"
	sleep 3s
	clear
	vnetxl
	;;
esac
}

vnet_cat_log(){
	cat /root/vnettunnel/vnet_log
    read -p "是否继续刷新日志 y/n (默认: y):" yn1
	[[ -z "${yn1}" ]] && yn1="y"
	if [[ ${yn1} == [Yy] ]]; then
	    vnet_cat_log
	else
		exit 0
	fi
}

clear
vnetxl