diff --git a/.github/ISSUE_TEMPLATE/------.md b/.github/ISSUE_TEMPLATE/------.md deleted file mode 100644 index f1ccef8b4e..0000000000 --- a/.github/ISSUE_TEMPLATE/------.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: 提问题点这里 -about: issue 模板 -title: '' -labels: '' -assignees: '' - ---- - -任何由于自己的配置错误导致的情况,请自行解决,issues 只用于解决面板自身的 bug - -如果你确定面板的功能实现有 bug,请尽可能提供更多更精确的描述信息、复现方法与复现结果等等,而不是草草一句话了事,这对于问题的解决没有帮助 - -提问的艺术: https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..39acf241a0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,57 @@ +name: Issue Report +description: "Create a report to help us improve." +body: + - type: checkboxes + id: terms + attributes: + label: Welcome + options: + - label: Yes, I'm using the latest major release. Only such installations are supported. + required: true + - label: Yes, I'm using the supported system. Only such systems are supported. + required: true + - label: Yes, I have read all WIKI document,nothing can help me in my problem. + required: true + - label: Yes, I've searched similar issues on GitHub and didn't find any. + required: true + - label: Yes, I've included all information below (version, config, log, etc). + required: true + + - type: textarea + id: problem + attributes: + label: Description of the problem,screencshot would be good + placeholder: Your problem description + validations: + required: true + + - type: textarea + id: version + attributes: + label: Version of x-ui + value: |- +
+ + ```console + $ x-ui version + # Paste output here + ``` + +
+ validations: + required: true + + - type: textarea + id: log + attributes: + label: x-ui log or xray log + value: |- +
+ + ```console + # paste log here + ``` + +
+ validations: + required: true diff --git a/README.md b/README.md index cc1b9d9a97..b2d7cbaa14 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,221 @@ -# x-ui -支持多协议多用户的 xray 面板 - -# 功能介绍 -- 系统状态监控 -- 支持多用户多协议,网页可视化操作 -- 支持的协议:vmess、vless、trojan、shadowsocks、dokodemo-door、socks、http -- 支持配置更多传输配置 -- 流量统计,限制流量,限制到期时间 -- 可自定义 xray 配置模板 -- 支持 https 访问面板(自备域名 + ssl 证书) -- 更多高级配置项,详见面板 - -# 安装&升级 -``` -bash <(curl -Ls https://raw.githubusercontent.com/vaxilu/x-ui/master/install.sh) -``` - -## 手动安装&升级 -1. 首先从 https://github.com/vaxilu/x-ui/releases 下载最新的压缩包,一般选择`amd64`架构 -2. 然后将这个压缩包上传到服务器的`/root/`目录下,并使用`root`用户登录服务器 - -> 如果你的服务器 cpu 架构不是`amd64`,自行将命令中的`amd64`替换为其他架构 - -``` -cd /root/ -rm x-ui/ /usr/local/x-ui/ /usr/bin/x-ui -rf -tar zxvf x-ui-linux-amd64.tar.gz -chmod +x x-ui/x-ui x-ui/bin/xray-linux-* x-ui/x-ui.sh -cp x-ui/x-ui.sh /usr/bin/x-ui -cp -f x-ui/x-ui.service /etc/systemd/system/ -mv x-ui/ /usr/local/ -systemctl daemon-reload -systemctl enable x-ui -systemctl restart x-ui -``` - -## 使用docker安装 - -> 此 docker 教程与 docker 镜像由[Chasing66](https://github.com/Chasing66)提供 - -1. 安装docker -```shell -curl -fsSL https://get.docker.com | sh -``` -2. 安装x-ui -```shell -mkdir x-ui && cd x-ui -docker run -itd --network=host \ - -v $PWD/db/:/etc/x-ui/ \ - -v $PWD/cert/:/root/cert/ \ - --name x-ui --restart=unless-stopped \ - enwaiax/x-ui:latest -``` ->Build 自己的镜像 -```shell -docker build -t x-ui . -``` - -## 建议系统 -- CentOS 7+ -- Ubuntu 16+ -- Debian 8+ - -# 常见问题 - -## 从 v2-ui 迁移 -首先在安装了 v2-ui 的服务器上安装最新版 x-ui,然后使用以下命令进行迁移,将迁移本机 v2-ui 的`所有 inbound 账号数据`至 x-ui,`面板设置和用户名密码不会迁移` -> 迁移成功后请`关闭 v2-ui`并且`重启 x-ui`,否则 v2-ui 的 inbound 会与 x-ui 的 inbound 会产生`端口冲突` -``` -x-ui v2-ui -``` - -## issue 关闭 -各种小白问题看得血压很高 - -## Stargazers over time - -[![Stargazers over time](https://starchart.cc/vaxilu/x-ui.svg)](https://starchart.cc/vaxilu/x-ui) +# X-UI +简体中文|[ENGLISH](./README_EN.md) + +> 声明:该项目仅供个人学习、交流,请遵守当地法律法规,勿用于非法用途;请勿用于生产环境 +> 声明:该项目已闭源,介意者请勿使用;如您需要开源代码,请附上您的Github Profile邮箱联系 + +支持单端口多用户、多协议的 xray 面板,究极缝合怪 +通过免费的Telegram bot方便快捷地进行监控、管理你的代理服务 +⚡`xtls-rprx-vision`与`reality`快速入手请看[这里](https://github.com/FranzKafkaYu/x-ui/wiki/%E8%8A%82%E7%82%B9%E9%85%8D%E7%BD%AE) +欢迎大家使用并反馈意见或提交Pr,帮助项目更好的改善 +如果您觉得本项目对您有所帮助,不妨给个star:star2:支持我 +或者你恰巧有购买服务器的需求,可以通过文末的赞助部分支持我~ + +# 文档目录 +- [功能介绍](#功能介绍) +- [一键安装](#一键安装) +- [效果预览](#效果预览) +- [快捷方式](#快捷方式) +- [变更记录](#变更记录) + +# 功能介绍 + +- 系统状态监控 +- 支持单端口多用户、多协议,网页可视化操作 +- 支持的协议:vmess、vless、trojan、shadowsocks、shadowsocks 2022、dokodemo-door、socks、http +- 支持配置更多传输配置:http、tcp、ws、grpc、kcp、quic +- 流量统计,限制流量,限制到期时间,一键重置与设备监控 +- 可自定义 xray 配置模板 +- 支持 https 访问面板(自备域名 + ssl 证书) +- 支持一键SSL证书申请且自动续签 +- Telegram bot通知、控制功能 +- 更多高级配置项,详见面板 + +:bulb:具体**使用、配置细节以及问题排查**请点击这里:point_right:[WIKI](https://github.com/FranzKafkaYu/x-ui/wiki):point_left: + Specific **Usages、Configurations and Debug** please refer to [WIKI](https://github.com/FranzKafkaYu/x-ui/wiki) +# 一键安装 +在安装前请确保你的系统支持`bash`环境,且系统网络正常 + +⚡从原版升级也可使用该命令,数据不会丢失⚡ + +``` +bash <(curl -Ls https://raw.githubusercontent.com/FranzKafkaYu/x-ui/master/install.sh) +``` +For English Users,please use the following command to install English supported version: +``` +bash <(curl -Ls https://raw.githubusercontent.com/FranzKafkaYu/x-ui/master/install_en.sh) +``` +如需安装指定的版本,可以在上述命令中指定版本号,如指定版本为`0.3.4.4`,安装命令如下: +``` +bash <(curl -Ls https://raw.githubusercontent.com/FranzKafkaYu/x-ui/master/install.sh) 0.3.4.4 +``` + +# 效果预览 +`面板使用`: +
+点击查看效果预览 + +![image](https://user-images.githubusercontent.com/38254177/180629631-f76a05c8-ecf0-4685-bbc7-a7058747d213.png) +![image](https://user-images.githubusercontent.com/38254177/180629662-b7a325fc-1ebb-47c9-992c-1e7c758a326b.png) + + +
+ +`Bot使用`: +
+点击查看效果预览 + +![image](https://user-images.githubusercontent.com/38254177/178551055-893936b7-b75f-4ee8-a773-eee7c6f43f51.png) + +
+ +`流量提醒`: +
+点击查看效果预览 + +![image](https://user-images.githubusercontent.com/38254177/180039760-dc987a30-e21c-49a3-8e03-19666566a822.png) + +
+ +`SSH提醒`: +
+点击查看效果预览 + +![image](https://user-images.githubusercontent.com/38254177/180040129-2ec1a7c0-abd3-41dc-aab0-8cd22415c943.png) + +
+ +`限额提醒`: +
+点击查看效果预览 + +![image](https://user-images.githubusercontent.com/38254177/180040521-af6e9ef8-d7e5-44e8-834e-25b3b8e3e1b5.png) + +
+ +`到期提醒`: +
+点击查看效果预览 + +![image](https://user-images.githubusercontent.com/38254177/180041690-90ca4b1f-3a2d-470b-bc0c-eca9261a739a.png) + +
+ +`登录提醒`: +
+点击查看效果预览 + +![image](https://user-images.githubusercontent.com/38254177/180040913-b8bf2fe1-6fc1-43ab-a683-ae23db1866b2.png) +![image](https://user-images.githubusercontent.com/38254177/180041179-a5f4cd52-a1ba-4aa9-abb2-b94e36722385.png) + +
+ +`用户速览`: +
+点击查看效果预览 + +![image](https://user-images.githubusercontent.com/38254177/230761101-20431dd7-5bce-489e-9139-0ceb9ab9a2dc.png) + +
+ +`用户查询`: +
+点击查看效果预览 + +![image](https://user-images.githubusercontent.com/38254177/230761252-c283c02d-82a4-46ce-a180-dfab4048180d.png) + +
+ + + +# 快捷方式 +安装成功后,通过键入`x-ui`进入控制选项菜单,目前菜单内容: +``` + x-ui 面板管理脚本 + 0. 退出脚本 +———————————————— + 1. 安装 x-ui + 2. 更新 x-ui + 3. 卸载 x-ui +———————————————— + 4. 重置用户名密码 + 5. 重置面板设置 + 6. 设置面板端口 + 7. 查看当前面板设置 +———————————————— + 8. 启动 x-ui + 9. 停止 x-ui + 10. 重启 x-ui + 11. 查看 x-ui 状态 + 12. 查看 x-ui 日志 +———————————————— + 13. 设置 x-ui 开机自启 + 14. 取消 x-ui 开机自启 +———————————————— + 15. 一键安装 bbr (最新内核) + 16. 一键申请SSL证书(acme申请) + +面板状态: 已运行 +是否开机自启: 是 +xray 状态: 运行 + +请输入选择 [0-16]: +``` +# 配置要求 +## 内存 +- 128MB minimal/256MB+ recommend +## OS +- CentOS 7+ +- Ubuntu 16+ +- Debian 8+ + +# 变更记录 +- 2023.07.18:随机生成Reality dest与serverNames,去除微软域名;细化sniffing配置 +- 2023.06.10:开启TLS时自动复用面板证书与域名;增加证书热重载设定;优化设备限制功能 +- 2023.04.09:支持Reality;支持新的telegram bot控制指令 +- 2023.03.05:支持用户到期时间限制;随机用户名、密码与端口生成 +- 2023.02.09:支持单端口内用户流量限制与统计;支持VLESS utls配置与分享链接导出 +- 2022.12.07:添加设备并发限制;细化tls配置,支持minVersion、maxVersion与cipherSuites选择 +- 2022.11.14:添加xtls-rprx-vision流控选项;定时自动更新geo与清除日志 +- 2022.10.23:实现全英文支持;增加批量导出分享链接功能;优化页面细节与Telegram通知 +- 2022.08.11:实现Vmess/Vless/Trojan单端口多用户;增加CPU使用超限提醒 +- 2022.07.28:增加acme standalone模式申请证书;增加x-ui自动保活机制;优化编译选项以适配更多系统 +- 2022.07.24:增加自动生成面板根路径,节点流量自动重置功能,设备IP接入变化通知功能 +- 2022.07.21:增加节点IP接入变化提醒,Web面板增加停止/重启xray功能,优化部分翻译 +- 2022.07.11:增加节点到期提醒、流量预警策略,增加Telegram bot节点复制、获取分享链接等 +- 2022.07.03:重构Telegram bot功能,指令控制不再需要键盘输入;增加Trojan底层传输配置 +- 2022.06.19:增加Shadowsocs2022新的Cipher,增加节点搜索、一键清除流量功能 +- 2022.05.14:增加Telegram bot Command控制功能,支持关闭/开启/删除节点等 +- 2022.04.25:增加SSH登录提醒、面板登录提醒 +- 2022.04.23:增加更多Telegram bot提醒功能 +- 2022.04.16:增加面板设置Telegram bot功能 +- 2022.04.12:优化Telegram Bot通知提醒 +- 2022.04.06:优化安装/更新流程,增加证书签发功能,添加Telegram bot机器人推送功能 +# Telegram + +[订阅频道](https://t.me/CoderfanBaby) +[讨论群组](https://t.me/franzkafayu) + +# 致谢 + +- [vaxilu/x-ui](https://github.com/vaxilu/x-ui) +- [XTLS/Xray-core](https://github.com/XTLS/Xray-core) +- [telegram-bot-api](https://github.com/go-telegram-bot-api/telegram-bot-api) + +# 广告赞助 + +如果你觉得本项目对你有用,而且你也恰巧有这方面的需求,你也可以选择通过我的购买链接赞助我 +- [搬瓦工GIA高端线路](https://bandwagonhost.com/aff.php?aff=65703),仅推荐购买GIA套餐 +- [Cloudcone性价比主机提供商](https://app.cloudcone.com/?ref=7536) +- [Spartan三网4837性价比主机](https://billing.spartanhost.net/aff.php?aff=1875) + + +如果你希望购买一些现成的代理服务,可选择下述代理服务 +- [搬瓦工关联机场](https://justmysocks.net/members/aff.php?aff=18177) +- [高端奶昔机场](https://nxboom.com/signupbyemail.aspx?MemberCode=2fd79885e45549049c66698f1eea154620230921234746) + +VPS推送可关注电报[频道](https://t.me/VpsReStockAlert) + +## Stargazers over time + +[![Stargazers over time](https://starchart.cc/FranzKafkaYu/x-ui.svg)](https://starchart.cc/FranzKafkaYu/x-ui) diff --git a/README_EN.md b/README_EN.md new file mode 100644 index 0000000000..a5ac37dc3f --- /dev/null +++ b/README_EN.md @@ -0,0 +1,120 @@ +# X-UI + +[简体中文](./README.md)| ENGLISH +X-UI is a webUI panel based on Xray-core which supports multi protocols and multi users +This project is a fork of [vaxilu's project](https://github.com/vaxilu/x-ui),and it is a experiental project which used by myself for learning golang +If you need more language options ,please open a issue and let me know that + +# Changes +- 2023.07.18:Random Reality dest and serverNames;more detailed sniffing settings available +- 2023.06.10:Enable TLS will reuse panel's certs and domain;add setting for ocspStapling;refactor device limit +- 2023.04.09:Support REALITY for now +- 2023.03.05:User expiry time limit for each user +- 2023.02.09:User traffic limit for each user,support utls sharing link +- 2022.12.07:Add device limit and more tls configuration +- 2022.11.15:Add xtls-rprx-vision flow option;cron job for geo update and log clear +- 2022.10.23:Fully support for English,add export links,add CPU cores display +- 2022.08.11:Support multi users on the same port;add CPU limit exceed alert +- 2022.07.28:Add acme standalone mode for cert issue;add mechanism to keep X-UI alive even there exist crashes +- 2022.07.24:Add base path auto generate feature for security;add traffice reset automatically;add device alert +- 2022.07.21:Add more translations;add restart/stop xray service in Web panel +- 2022.07.11:Add time expiration notify for each inbound;add traffic limit notify for each inbound;add get url link command/inbound copy command in telegram bot +- 2022.07.03:Add transport options in Trojan protocol;restruct Telegram bot for convenience +- 2022.06.19:Add shadowsocks 2022 Ciphers,add inbounds search,traffic clear function in WebUI +- 2022.05.14:Add Telegram bot commands,support enable/disable/delete/status check +- 2022.04.25:Add SSH login notify +- 2022.04.23:Add WebUi login notify +- 2022.04.16:Add Telegram bot set up in WebUi pannel +- 2022.04.12:Optimize Telegram bot notify,more human friendly +- 2022.04.06:Add cert issue function,optimize installation/update and add telegram bot notify + +# Basics + +- support system status info check +- support multi protocols and multi users +- support protocols:vmess、vless、trojan、shadowsocks、dokodemo-door、socks、http +- support many transport method including tcp、udp、ws、kcp etc +- traffic counting,traffic restrict and time restrcit +- support custom configuration template +- support https access fot WebUI +- support SSL cert issue by Acme +- support telegram bot notify and control +- more functions in control menu + +for more detailed usages,plz see [WIKI](https://github.com/FranzKafkaYu/x-ui/wiki) + +# Installation +Make sure your system `bash` and `curl` and `network` are ready,here we go + +``` +bash <(curl -Ls https://raw.githubusercontent.com/FranzKafkaYu/x-ui/master/install.sh) +``` +For English Users,please use the following command to install English supported version: +``` +bash <(curl -Ls https://raw.githubusercontent.com/FranzKafkaYu/x-ui/master/install_en.sh) +``` + +## Shortcut +After Installation,you can input `x-ui`to enter control menu,current menu details: +``` + + x-ui control menu + 0. exit +———————————————— + 1. install x-ui + 2. update x-ui + 3. uninstall x-ui +———————————————— + 4. reset username + 5. reset panel + 6. reset panel port + 7. check panel info +———————————————— + 8. start x-ui + 9. stop x-ui + 10. restart x-ui + 11. check x-ui status + 12. check x-ui logs +———————————————— + 13. enable x-ui on sysyem startup + 14. disabel x-ui on sysyem startup +———————————————— + 15. enable bbr + 16. issuse certs + +x-ui status: running +enable on system startup: yes +xray status: running + +please input a legal number[0-16]: +``` + +# System requirements: +## MEM +- 128MB minimal/256MB+ recommend +## OS +- CentOS 7+ +- Ubuntu 16+ +- Debian 8+ + +# Telegram + +[Channel](https://t.me/CoderfanBaby) +[Group](https://t.me/franzkafayu) + +# Credits +- [vaxilu/x-ui](https://github.com/vaxilu/x-ui) +- [XTLS/Xray-core](https://github.com/XTLS/Xray-core) +- [telegram-bot-api](https://github.com/go-telegram-bot-api/telegram-bot-api) + +# Sponsor + +if you want to purchase some virtual servers,you can purchase by my aff link: +- [BandwagonHost](https://bandwagonhost.com/aff.php?aff=65703) +- [Cloudcone](https://app.cloudcone.com/?ref=7536) +- [SpartanHost](https://billing.spartanhost.net/aff.php?aff=1875) + + +## Stargazers over time + +[![Stargazers over time](https://starchart.cc/FranzKafkaYu/x-ui.svg)](https://starchart.cc/FranzKafkaYu/x-ui) diff --git a/install.sh b/install.sh index 205cffde43..ae2e43907f 100644 --- a/install.sh +++ b/install.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash red='\033[0;31m' green='\033[0;32m' @@ -31,18 +31,18 @@ fi arch=$(arch) -if [[ $arch == "x86_64" || $arch == "x64" || $arch == "amd64" ]]; then - arch="amd64" +if [[ $arch == "x86_64" || $arch == "x64" || $arch == "s390x" || $arch == "amd64" ]]; then + arch="amd64" elif [[ $arch == "aarch64" || $arch == "arm64" ]]; then - arch="arm64" + arch="arm64" else - arch="amd64" - echo -e "${red}检测架构失败,使用默认架构: ${arch}${plain}" + arch="amd64" + echo -e "${red}检测架构失败,使用默认架构: ${arch}${plain}" fi echo "架构: ${arch}" -if [ $(getconf WORD_BIT) != '32' ] && [ $(getconf LONG_BIT) != '64' ] ; then +if [ $(getconf WORD_BIT) != '32' ] && [ $(getconf LONG_BIT) != '64' ]; then echo "本软件不支持 32 位系统(x86),请使用 64 位系统(x86_64),如果检测有误,请联系作者" exit -1 fi @@ -73,9 +73,46 @@ fi install_base() { if [[ x"${release}" == x"centos" ]]; then - yum install wget curl tar -y + yum install wget curl tar jq -y else - apt install wget curl tar -y + apt install wget curl tar jq -y + fi +} + +#This function will be called when user installed x-ui out of sercurity +config_after_install() { + echo -e "${yellow}出于安全考虑,安装/更新完成后需要强制修改端口与账户密码${plain}" + read -p "确认是否继续,如选择n则跳过本次端口与账户密码设定[y/n]": config_confirm + if [[ x"${config_confirm}" == x"y" || x"${config_confirm}" == x"Y" ]]; then + 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}" + 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}" + if [[ ! -f "/etc/x-ui/x-ui.db" ]]; then + local usernameTemp=$(head -c 6 /dev/urandom | base64) + local passwordTemp=$(head -c 6 /dev/urandom | base64) + local portTemp=$(echo $RANDOM) + /usr/local/x-ui/x-ui setting -username ${usernameTemp} -password ${passwordTemp} + /usr/local/x-ui/x-ui setting -port ${portTemp} + echo -e "检测到您属于全新安装,出于安全考虑已自动为您生成随机用户与端口:" + echo -e "###############################################" + echo -e "${green}面板登录用户名:${usernameTemp}${plain}" + echo -e "${green}面板登录用户密码:${passwordTemp}${plain}" + echo -e "${red}面板登录端口:${portTemp}${plain}" + echo -e "###############################################" + echo -e "${red}如您遗忘了面板登录相关信息,可在安装完成后输入x-ui,输入选项7查看面板登录信息${plain}" + else + echo -e "${red}当前属于版本升级,保留之前设置项,登录方式保持不变,可输入x-ui后键入数字7查看面板登录信息${plain}" + fi fi } @@ -83,21 +120,21 @@ install_x-ui() { systemctl stop x-ui cd /usr/local/ - if [ $# == 0 ] ;then - last_version=$(curl -Ls "https://api.github.com/repos/vaxilu/x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + if [ $# == 0 ]; then + last_version=$(curl -Lsk "https://api.github.com/repos/FranzKafkaYu/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}" 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/vaxilu/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz https://github.com/FranzKafkaYu/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz if [[ $? -ne 0 ]]; then echo -e "${red}下载 x-ui 失败,请确保你的服务器能够下载 Github 的文件${plain}" exit 1 fi else last_version=$1 - url="https://github.com/vaxilu/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz" + url="https://github.com/FranzKafkaYu/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 @@ -115,19 +152,21 @@ install_x-ui() { 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/vaxilu/x-ui/main/x-ui.sh + wget --no-check-certificate -O /usr/bin/x-ui https://raw.githubusercontent.com/FranzKafkaYu/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 "如果是全新安装,默认网页端口为 ${green}54321${plain},用户名和密码默认都是 ${green}admin${plain}" - echo -e "请自行确保此端口没有被其他程序占用,${yellow}并且确保 54321 端口已放行${plain}" -# echo -e "若想将 54321 修改为其它端口,输入 x-ui 命令进行修改,同样也要确保你修改的端口也是放行的" - echo -e "" - echo -e "如果是更新面板,则按你之前的方式访问面板" - echo -e "" echo -e "x-ui 管理脚本使用方法: " echo -e "----------------------------------------------" echo -e "x-ui - 显示管理菜单 (功能更多)" @@ -142,6 +181,7 @@ install_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 "x-ui geo - 更新 geo 数据" echo -e "----------------------------------------------" } diff --git a/install_en.sh b/install_en.sh new file mode 100644 index 0000000000..cc532d04e5 --- /dev/null +++ b/install_en.sh @@ -0,0 +1,183 @@ +#!/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}Fatal error:${plain}please run this script with root privilege\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}check system os failed,please contact with author!${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" +else + arch="amd64" + echo -e "${red}fail to check system arch,will use default arch here: ${arch}${plain}" +fi + +echo "架构: ${arch}" + +if [ $(getconf WORD_BIT) != '32' ] && [ $(getconf LONG_BIT) != '64' ]; then + echo "x-ui dosen't support 32bit(x86) system,please use 64 bit operating system(x86_64) instead,if there is something wrong,plz let me know" + 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}please use CentOS 7 or higher version${plain}\n" && exit 1 + fi +elif [[ x"${release}" == x"ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + echo -e "${red}please use Ubuntu 16 or higher version${plain}\n" && exit 1 + fi +elif [[ x"${release}" == x"debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + echo -e "${red}please use Debian 8 or higher version${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}Install/update finished need to modify panel settings out of security${plain}" + read -p "are you continue,if you type n will skip this at this time[y/n]": config_confirm + if [[ x"${config_confirm}" == x"y" || x"${config_confirm}" == x"Y" ]]; then + read -p "please set up your username:" config_account + echo -e "${yellow}your username will be:${config_account}${plain}" + read -p "please set up your password:" config_password + echo -e "${yellow}your password will be:${config_password}${plain}" + read -p "please set up the panel port:" config_port + echo -e "${yellow}your panel port is:${config_port}${plain}" + echo -e "${yellow}initializing,wait some time here...${plain}" + /usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} + echo -e "${yellow}account name and password set down!${plain}" + /usr/local/x-ui/x-ui setting -port ${config_port} + echo -e "${yellow}panel port set down!${plain}" + else + echo -e "${red}cancel...${plain}" + if [[ ! -f "/etc/x-ui/x-ui.db" ]]; then + local usernameTemp=$(head -c 6 /dev/urandom | base64) + local passwordTemp=$(head -c 6 /dev/urandom | base64) + local portTemp=$(echo $RANDOM) + /usr/local/x-ui/x-ui setting -username ${usernameTemp} -password ${passwordTemp} + /usr/local/x-ui/x-ui setting -port ${portTemp} + echo -e "this is a fresh installation,will generate random login info for security concerns:" + echo -e "###############################################" + echo -e "${green}user name:${usernameTemp}${plain}" + echo -e "${green}user password:${passwordTemp}${plain}" + echo -e "${red}web port:${portTemp}${plain}" + echo -e "###############################################" + echo -e "${red}if you forgot your login info,you can type x-ui and then type 7 to check after installation${plain}" + else + echo -e "${red} this is your upgrade,will keep old settings,if you forgot your login info,you can type x-ui and then type 7 to check${plain}" + fi + fi +} + +install_x-ui() { + systemctl stop x-ui + cd /usr/local/ + + if [ $# == 0 ]; then + last_version=$(curl -Ls "https://api.github.com/repos/FranzKafkaYu/x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + if [[ ! -n "$last_version" ]]; then + echo -e "${red}refresh x-ui version failed,it may due to Github API restriction,please try it later${plain}" + exit 1 + fi + echo -e "get x-ui latest version succeed:${last_version},begin to install..." + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}-english.tar.gz https://github.com/FranzKafkaYu/x-ui/releases/download/${last_version}/x-ui-linux-${arch}-english.tar.gz + if [[ $? -ne 0 ]]; then + echo -e "${red}dowanload x-ui failed,please be sure that your server can access Github{plain}" + exit 1 + fi + else + last_version=$1 + url="https://github.com/FranzKafkaYu/x-ui/releases/download/${last_version}/x-ui-linux-${arch}-english.tar.gz" + echo -e "begin to install x-ui v$1 ..." + wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}-english.tar.gz ${url} + if [[ $? -ne 0 ]]; then + echo -e "${red}dowanload x-ui v$1 failed,please check the verison exists${plain}" + exit 1 + fi + fi + + if [[ -e /usr/local/x-ui/ ]]; then + rm /usr/local/x-ui/ -rf + fi + + tar zxvf x-ui-linux-${arch}-english.tar.gz + rm x-ui-linux-${arch}-english.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/FranzKafkaYu/x-ui/main/x-ui_en.sh + chmod +x /usr/local/x-ui/x-ui_en.sh + chmod +x /usr/bin/x-ui + config_after_install + systemctl daemon-reload + systemctl enable x-ui + systemctl start x-ui + echo -e "${green}x-ui v${last_version}${plain} install finished,it is working now..." + echo -e "" + echo -e "x-ui control menu usages: " + echo -e "----------------------------------------------" + echo -e "x-ui - Enter control menu" + echo -e "x-ui start - Start x-ui " + echo -e "x-ui stop - Stop x-ui " + echo -e "x-ui restart - Restart x-ui " + echo -e "x-ui status - Show x-ui status" + echo -e "x-ui enable - Enable x-ui on system startup" + echo -e "x-ui disable - Disable x-ui on system startup" + echo -e "x-ui log - Check x-ui logs" + echo -e "x-ui update - Update x-ui " + echo -e "x-ui install - Install x-ui " + echo -e "x-ui uninstall - Uninstall x-ui " + echo -e "x-ui geo - Update geo data" + echo -e "----------------------------------------------" +} + +echo -e "${green}excuting...${plain}" +install_base +install_x-ui $1 diff --git a/media/2022-04-04_141259.png b/media/2022-04-04_141259.png new file mode 100644 index 0000000000..aaa4664431 Binary files /dev/null and b/media/2022-04-04_141259.png differ diff --git a/media/bda84fbc2ede834deaba1c173a932223.png b/media/bda84fbc2ede834deaba1c173a932223.png new file mode 100644 index 0000000000..9cc3c380d0 Binary files /dev/null and b/media/bda84fbc2ede834deaba1c173a932223.png differ diff --git a/media/d13ffd6a73f938d1037d0708e31433bf.png b/media/d13ffd6a73f938d1037d0708e31433bf.png new file mode 100644 index 0000000000..b08277aaf5 Binary files /dev/null and b/media/d13ffd6a73f938d1037d0708e31433bf.png differ diff --git a/x-ui.sh b/x-ui.sh index dad3f8b031..914c068a02 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -5,8 +5,30 @@ green='\033[0;32m' yellow='\033[0;33m' plain='\033[0m' +#consts for log check and clear,unit:M +declare -r DEFAULT_LOG_FILE_DELETE_TRIGGER=35 + +# consts for geo update +PATH_FOR_GEO_IP='/usr/local/x-ui/bin/geoip.dat' +PATH_FOR_CONFIG='/usr/local/x-ui/bin/config.json' +PATH_FOR_GEO_SITE='/usr/local/x-ui/bin/geosite.dat' +URL_FOR_GEO_IP='https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat' +URL_FOR_GEO_SITE='https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat' + +#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 ]] && echo -e "${red}错误: ${plain} 必须使用root用户运行此脚本!\n" && exit 1 +[[ $EUID -ne 0 ]] && LOGE "错误: 必须使用root用户运行此脚本!\n" && exit 1 # check os if [[ -f /etc/redhat-release ]]; then @@ -24,7 +46,7 @@ elif cat /proc/version | grep -Eqi "ubuntu"; then elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then release="centos" else - echo -e "${red}未检测到系统版本,请联系脚本作者!${plain}\n" && exit 1 + LOGE "未检测到系统版本,请联系脚本作者!\n" && exit 1 fi os_version="" @@ -39,15 +61,15 @@ fi if [[ x"${release}" == x"centos" ]]; then if [[ ${os_version} -le 6 ]]; then - echo -e "${red}请使用 CentOS 7 或更高版本的系统!${plain}\n" && exit 1 + LOGE "请使用 CentOS 7 或更高版本的系统!\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 + LOGE "请使用 Ubuntu 16 或更高版本的系统!\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 + LOGE "请使用 Debian 8 或更高版本的系统!\n" && exit 1 fi fi @@ -82,7 +104,7 @@ before_show_menu() { } install() { - bash <(curl -Ls https://raw.githubusercontent.com/vaxilu/x-ui/master/install.sh) + bash <(curl -Ls https://raw.githubusercontent.com/FranzKafkaYu/x-ui/master/install.sh) if [[ $? == 0 ]]; then if [[ $# == 0 ]]; then start @@ -95,21 +117,21 @@ install() { update() { confirm "本功能会强制重装当前最新版,数据不会丢失,是否继续?" "n" if [[ $? != 0 ]]; then - echo -e "${red}已取消${plain}" + LOGE "已取消" if [[ $# == 0 ]]; then before_show_menu fi return 0 fi - bash <(curl -Ls https://raw.githubusercontent.com/vaxilu/x-ui/master/install.sh) + bash <(curl -Ls https://raw.githubusercontent.com/FranzKafkaYu/x-ui/master/install.sh) if [[ $? == 0 ]]; then - echo -e "${green}更新完成,已自动重启面板${plain}" + LOGI "更新完成,已自动重启面板 " exit 0 fi } uninstall() { - confirm "确定要卸载面板吗,xray 也会卸载?" "n" + confirm "确定要卸载面板吗,xray 也会卸载?" "n" if [[ $? != 0 ]]; then if [[ $# == 0 ]]; then show_menu @@ -159,10 +181,19 @@ reset_config() { confirm_restart } +check_config() { + info=$(/usr/local/x-ui/x-ui setting -show true) + if [[ $? != 0 ]]; then + LOGE "get current settings error,please check logs" + show_menu + fi + LOGI "${info}" +} + set_port() { echo && echo -n -e "输入端口号[1-65535]: " && read port if [[ -z "${port}" ]]; then - echo -e "${yellow}已取消${plain}" + LOGD "已取消" before_show_menu else /usr/local/x-ui/x-ui setting -port ${port} @@ -175,15 +206,15 @@ start() { check_status if [[ $? == 0 ]]; then echo "" - echo -e "${green}面板已运行,无需再次启动,如需重启请选择重启${plain}" + LOGI "面板已运行,无需再次启动,如需重启请选择重启" else systemctl start x-ui sleep 2 check_status if [[ $? == 0 ]]; then - echo -e "${green}x-ui 启动成功${plain}" + LOGI "x-ui 启动成功" else - echo -e "${red}面板启动失败,可能是因为启动时间超过了两秒,请稍后查看日志信息${plain}" + LOGE "面板启动失败,可能是因为启动时间超过了两秒,请稍后查看日志信息" fi fi @@ -196,15 +227,15 @@ stop() { check_status if [[ $? == 1 ]]; then echo "" - echo -e "${green}面板已停止,无需再次停止${plain}" + LOGI "面板已停止,无需再次停止" else systemctl stop x-ui sleep 2 check_status if [[ $? == 1 ]]; then - echo -e "${green}x-ui 与 xray 停止成功${plain}" + LOGI "x-ui 与 xray 停止成功" else - echo -e "${red}面板停止失败,可能是因为停止时间超过了两秒,请稍后查看日志信息${plain}" + LOGE "面板停止失败,可能是因为停止时间超过了两秒,请稍后查看日志信息" fi fi @@ -218,9 +249,9 @@ restart() { sleep 2 check_status if [[ $? == 0 ]]; then - echo -e "${green}x-ui 与 xray 重启成功${plain}" + LOGI "x-ui 与 xray 重启成功" else - echo -e "${red}面板重启失败,可能是因为启动时间超过了两秒,请稍后查看日志信息${plain}" + LOGE "面板重启失败,可能是因为启动时间超过了两秒,请稍后查看日志信息" fi if [[ $# == 0 ]]; then before_show_menu @@ -237,9 +268,9 @@ status() { enable() { systemctl enable x-ui if [[ $? == 0 ]]; then - echo -e "${green}x-ui 设置开机自启成功${plain}" + LOGI "x-ui 设置开机自启成功" else - echo -e "${red}x-ui 设置开机自启失败${plain}" + LOGE "x-ui 设置开机自启失败" fi if [[ $# == 0 ]]; then @@ -250,9 +281,9 @@ enable() { disable() { systemctl disable x-ui if [[ $? == 0 ]]; then - echo -e "${green}x-ui 取消开机自启成功${plain}" + LOGI "x-ui 取消开机自启成功" else - echo -e "${red}x-ui 取消开机自启失败${plain}" + LOGE "x-ui 取消开机自启失败" fi if [[ $# == 0 ]]; then @@ -281,14 +312,14 @@ install_bbr() { } update_shell() { - wget -O /usr/bin/x-ui -N --no-check-certificate https://github.com/vaxilu/x-ui/raw/master/x-ui.sh + wget -O /usr/bin/x-ui -N --no-check-certificate https://github.com/FranzKafkaYu/x-ui/raw/master/x-ui.sh if [[ $? != 0 ]]; then echo "" - echo -e "${red}下载脚本失败,请检查本机能否连接 Github${plain}" + LOGE "下载脚本失败,请检查本机能否连接 Github" before_show_menu else chmod +x /usr/bin/x-ui - echo -e "${green}升级脚本成功,请重新运行脚本${plain}" && exit 0 + LOGI "升级脚本成功,请重新运行脚本" && exit 0 fi } @@ -310,7 +341,7 @@ check_enabled() { if [[ x"${temp}" == x"enabled" ]]; then return 0 else - return 1; + return 1 fi } @@ -318,7 +349,7 @@ check_uninstall() { check_status if [[ $? != 2 ]]; then echo "" - echo -e "${red}面板已安装,请不要重复安装${plain}" + LOGE "面板已安装,请不要重复安装" if [[ $# == 0 ]]; then before_show_menu fi @@ -332,7 +363,7 @@ check_install() { check_status if [[ $? == 2 ]]; then echo "" - echo -e "${red}请先安装面板${plain}" + LOGE "请先安装面板" if [[ $# == 0 ]]; then before_show_menu fi @@ -345,16 +376,17 @@ check_install() { 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}" + 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 } @@ -386,6 +418,362 @@ show_xray_status() { fi } +#this will be an entrance for ssl cert issue +#here we can provide two different methods to issue cert +#first.standalone mode second.DNS API mode +ssl_cert_issue() { + local method="" + echo -E "" + LOGD "******使用说明******" + LOGI "该脚本提供两种方式实现证书签发,证书安装路径均为/root/cert" + LOGI "方式1:acme standalone mode,需要保持端口开放" + LOGI "方式2:acme DNS API mode,需要提供Cloudflare Global API Key" + LOGI "如域名属于免费域名,则推荐使用方式1进行申请" + LOGI "如域名非免费域名且使用Cloudflare进行解析使用方式2进行申请" + read -p "请选择你想使用的方式,输入数字1或者2后回车": method + LOGI "你所使用的方式为${method}" + + if [ "${method}" == "1" ]; then + ssl_cert_issue_standalone + elif [ "${method}" == "2" ]; then + ssl_cert_issue_by_cloudflare + else + LOGE "输入无效,请检查你的输入,脚本将退出..." + exit 1 + fi +} + +install_acme() { + cd ~ + LOGI "开始安装acme脚本..." + curl https://get.acme.sh | sh + if [ $? -ne 0 ]; then + LOGE "acme安装失败" + return 1 + else + LOGI "acme安装成功" + fi + return 0 +} + +#method for standalone mode +ssl_cert_issue_standalone() { + #check for acme.sh first + if ! command -v ~/.acme.sh/acme.sh &>/dev/null; then + install_acme + if [ $? -ne 0 ]; then + LOGE "安装 acme 失败,请检查日志" + exit 1 + fi + fi + #install socat second + if [[ x"${release}" == x"centos" ]]; then + yum install socat -y + else + apt install socat -y + fi + if [ $? -ne 0 ]; then + LOGE "无法安装socat,请检查错误日志" + exit 1 + else + LOGI "socat安装成功..." + fi + #creat a directory for install cert + certPath=/root/cert + if [ ! -d "$certPath" ]; then + mkdir $certPath + fi + #get the domain here,and we need verify it + local domain="" + read -p "请输入你的域名:" domain + LOGD "你输入的域名为:${domain},正在进行域名合法性校验..." + #here we need to judge whether there exists cert already + local currentCert=$(~/.acme.sh/acme.sh --list | grep ${domain} | wc -l) + if [ ${currentCert} -ne 0 ]; then + local certInfo=$(~/.acme.sh/acme.sh --list) + LOGE "域名合法性校验失败,当前环境已有对应域名证书,不可重复申请,当前证书详情:" + LOGI "$certInfo" + exit 1 + else + LOGI "域名合法性校验通过..." + fi + #get needed port here + local WebPort=80 + read -p "请输入你所希望使用的端口,如回车将使用默认80端口:" WebPort + if [[ ${WebPort} -gt 65535 || ${WebPort} -lt 1 ]]; then + LOGE "你所选择的端口${WebPort}为无效值,将使用默认80端口进行申请" + fi + LOGI "将会使用${WebPort}进行证书申请,请确保端口处于开放状态..." + #NOTE:This should be handled by user + #open the port and kill the occupied progress + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + ~/.acme.sh/acme.sh --issue -d ${domain} --standalone --httpport ${WebPort} + if [ $? -ne 0 ]; then + LOGE "证书申请失败,原因请参见报错信息" + rm -rf ~/.acme.sh/${domain} + exit 1 + else + LOGI "证书申请成功,开始安装证书..." + fi + #install cert + ~/.acme.sh/acme.sh --installcert -d ${domain} --ca-file /root/cert/ca.cer \ + --cert-file /root/cert/${domain}.cer --key-file /root/cert/${domain}.key \ + --fullchain-file /root/cert/fullchain.cer + + if [ $? -ne 0 ]; then + LOGE "证书安装失败,脚本退出" + rm -rf ~/.acme.sh/${domain} + exit 1 + else + LOGI "证书安装成功,开启自动更新..." + fi + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [ $? -ne 0 ]; then + LOGE "自动更新设置失败,脚本退出" + ls -lah cert + chmod 755 $certPath + exit 1 + else + LOGI "证书已安装且已开启自动更新,具体信息如下" + ls -lah cert + chmod 755 $certPath + fi + +} + +#method for DNS API mode +ssl_cert_issue_by_cloudflare() { + 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 + install_acme + if [ $? -ne 0 ]; then + LOGE "无法安装acme,请检查错误日志" + exit 1 + fi + CF_Domain="" + CF_GlobalKey="" + CF_AccountEmail="" + certPath=/root/cert + if [ ! -d "$certPath" ]; then + mkdir $certPath + fi + LOGD "请设置域名:" + read -p "Input your domain here:" CF_Domain + LOGD "你的域名设置为:${CF_Domain},正在进行域名合法性校验..." + #here we need to judge whether there exists cert already + local currentCert=$(~/.acme.sh/acme.sh --list | grep ${CF_Domain} | wc -l) + if [ ${currentCert} -ne 0 ]; then + local certInfo=$(~/.acme.sh/acme.sh --list) + LOGE "域名合法性校验失败,当前环境已有对应域名证书,不可重复申请,当前证书详情:" + LOGI "$certInfo" + exit 1 + else + LOGI "域名合法性校验通过..." + fi + LOGD "请设置API密钥:" + read -p "Input your key here:" CF_GlobalKey + LOGD "你的API密钥为:${CF_GlobalKey}" + LOGD "请设置注册邮箱:" + read -p "Input your email here:" CF_AccountEmail + LOGD "你的注册邮箱为:${CF_AccountEmail}" + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [ $? -ne 0 ]; then + LOGE "修改默认CA为Lets'Encrypt失败,脚本退出" + exit 1 + fi + export CF_Key="${CF_GlobalKey}" + export CF_Email=${CF_AccountEmail} + ~/.acme.sh/acme.sh --issue --dns dns_cf -d ${CF_Domain} -d *.${CF_Domain} --log + if [ $? -ne 0 ]; then + LOGE "证书签发失败,脚本退出" + rm -rf ~/.acme.sh/${CF_Domain} + exit 1 + else + LOGI "证书签发成功,安装中..." + fi + ~/.acme.sh/acme.sh --installcert -d ${CF_Domain} -d *.${CF_Domain} --ca-file /root/cert/ca.cer \ + --cert-file /root/cert/${CF_Domain}.cer --key-file /root/cert/${CF_Domain}.key \ + --fullchain-file /root/cert/fullchain.cer + if [ $? -ne 0 ]; then + LOGE "证书安装失败,脚本退出" + rm -rf ~/.acme.sh/${CF_Domain} + exit 1 + else + LOGI "证书安装成功,开启自动更新..." + fi + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [ $? -ne 0 ]; then + LOGE "自动更新设置失败,脚本退出" + ls -lah cert + chmod 755 $certPath + exit 1 + else + LOGI "证书已安装且已开启自动更新,具体信息如下" + ls -lah cert + chmod 755 $certPath + fi + else + show_menu + fi +} + +#add for cron jobs,including sync geo data,check logs and restart x-ui +cron_jobs() { + clear + echo -e " + ${green}定时任务管理${plain} + ${green}0.${plain} 返回主菜单 + ${green}1.${plain} 开启定时更新geo + ${green}2.${plain} 关闭定时更新geo + ${green}3.${plain} 开启定时删除xray日志 + ${green}4.${plain} 关闭定时删除xray日志 + " + echo && read -p "请输入选择 [0-4]: " num + case "${num}" in + 0) + show_menu + ;; + 1) + enable_auto_update_geo + ;; + 2) + disable_auto_update_geo + ;; + 3) + enable_auto_clear_log + ;; + 4) + disable_auto_clear_log + ;; + *) + LOGE "请输入正确的数字 [0-4]" + ;; + esac +} + +#update geo data +update_geo() { + #back up first + mv ${PATH_FOR_GEO_IP} ${PATH_FOR_GEO_IP}.bak + #update data + curl -s -L -o ${PATH_FOR_GEO_IP} ${URL_FOR_GEO_IP} + if [[ $? -ne 0 ]]; then + echo "update geoip.dat failed" + mv ${PATH_FOR_GEO_IP}.bak ${PATH_FOR_GEO_IP} + else + echo "update geoip.dat succeed" + rm -f ${PATH_FOR_GEO_IP}.bak + fi + mv ${PATH_FOR_GEO_SITE} ${PATH_FOR_GEO_SITE}.bak + curl -s -L -o ${PATH_FOR_GEO_SITE} ${URL_FOR_GEO_SITE} + if [[ $? -ne 0 ]]; then + echo "update geosite.dat failed" + mv ${PATH_FOR_GEO_SITE}.bak ${PATH_FOR_GEO_SITE} + else + echo "update geosite.dat succeed" + rm -f ${PATH_FOR_GEO_SITE}.bak + fi + #restart x-ui + systemctl restart x-ui +} + +enable_auto_update_geo() { + LOGI "正在开启自动更新geo数据..." + crontab -l >/tmp/crontabTask.tmp + echo "00 4 */2 * * x-ui geo > /dev/null" >>/tmp/crontabTask.tmp + crontab /tmp/crontabTask.tmp + rm /tmp/crontabTask.tmp + LOGI "开启自动更新geo数据成功" +} + +disable_auto_update_geo() { + crontab -l | grep -v "x-ui geo" | crontab - + if [[ $? -ne 0 ]]; then + LOGI "取消x-ui 自动更新geo数据失败" + else + LOGI "取消x-ui 自动更新geo数据成功" + fi +} + +#clear xray log,need enable log in config template +#here we need input an absolute path for log +clear_log() { + LOGI "清除xray日志中..." + local filePath='' + if [[ $# -gt 0 ]]; then + filePath=$1 + else + LOGE "未输入有效文件路径,脚本退出" + exit 1 + fi + LOGI "日志路径为:${filePath}" + if [[ ! -f ${filePath} ]]; then + LOGE "清除xray日志文件失败,${filePath}不存在,请确认" + exit 1 + fi + fileSize=$(ls -la ${filePath} --block-size=M | awk '{print $5}' | awk -F 'M' '{print$1}') + if [[ ${fileSize} -gt ${DEFAULT_LOG_FILE_DELETE_TRIGGER} ]]; then + rm $1 + if [[ $? -ne 0 ]]; then + LOGE "清除xray日志文件:${filePath}失败" + else + LOGI "清除xray日志文件:${filePath}成功" + systemctl restart x-ui + fi + else + LOGI "当前日志大小为${fileSize}M,小于${DEFAULT_LOG_FILE_DELETE_TRIGGER}M,将不会清除" + fi +} + +#enable auto delete log,need file path as +enable_auto_clear_log() { + LOGI "设置定时清除xray日志..." + local accessfilePath='' + local errorfilePath='' + accessfilePath=$(cat ${PATH_FOR_CONFIG} | jq .log.access | tr -d '"') + errorfilePath=$(cat ${PATH_FOR_CONFIG} | jq .log.error | tr -d '"') + if [[ ! -n ${accessfilePath} && ! -n ${errorfilePath} ]]; then + LOGI "配置文件中的日志文件路径无效,脚本退出" + exit 1 + fi + if [[ -f ${accessfilePath} ]]; then + crontab -l >/tmp/crontabTask.tmp + echo "30 4 */2 * * x-ui clear ${accessfilePath} > /dev/null" >>/tmp/crontabTask.tmp + crontab /tmp/crontabTask.tmp + rm /tmp/crontabTask.tmp + LOGI "设置定时清除xray日志:${accessfilePath}成功" + else + LOGE "accesslog不存在,将不会为其设置定时清除" + fi + + if [[ -f ${errorfilePath} ]]; then + crontab -l >/tmp/crontabTask.tmp + echo "30 4 */2 * * x-ui clear ${errorfilePath} > /dev/null" >>/tmp/crontabTask.tmp + crontab /tmp/crontabTask.tmp + rm /tmp/crontabTask.tmp + LOGI "设置定时清除xray日志:${errorfilePath}成功" + else + LOGE "errorlog不存在,将不会为其设置定时清除" + fi +} + +#disable auto dlete log +disable_auto_clear_log() { + crontab -l | grep -v "x-ui clear" | crontab - + if [[ $? -ne 0 ]]; then + LOGI "取消 定时清除xray日志失败" + else + LOGI "取消 定时清除xray日志成功" + fi +} + show_usage() { echo "x-ui 管理脚本使用方法: " echo "------------------------------------------" @@ -401,6 +789,9 @@ show_usage() { echo "x-ui update - 更新 x-ui 面板" echo "x-ui install - 安装 x-ui 面板" echo "x-ui uninstall - 卸载 x-ui 面板" + echo "x-ui clear - 清除 x-ui 日志" + echo "x-ui geo - 更新 x-ui geo数据" + echo "x-ui cron - 配置 x-ui 定时任务" echo "------------------------------------------" } @@ -416,83 +807,130 @@ show_menu() { ${green}4.${plain} 重置用户名密码 ${green}5.${plain} 重置面板设置 ${green}6.${plain} 设置面板端口 + ${green}7.${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}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}12.${plain} 设置 x-ui 开机自启 - ${green}13.${plain} 取消 x-ui 开机自启 + ${green}13.${plain} 设置 x-ui 开机自启 + ${green}14.${plain} 取消 x-ui 开机自启 ———————————————— - ${green}14.${plain} 一键安装 bbr (最新内核) + ${green}15.${plain} 一键安装 bbr (最新内核) + ${green}16.${plain} 一键申请SSL证书(acme申请) + ${green}17.${plain} 配置x-ui定时任务 " show_status - echo && read -p "请输入选择 [0-14]: " num + echo && read -p "请输入选择 [0-17],查看面板登录信息请输入数字7:" num case "${num}" in - 0) exit 0 + 0) + exit 0 + ;; + 1) + check_uninstall && install ;; - 1) check_uninstall && install + 2) + check_install && update ;; - 2) check_install && update + 3) + check_install && uninstall ;; - 3) check_install && uninstall + 4) + check_install && reset_user ;; - 4) check_install && reset_user + 5) + check_install && reset_config ;; - 5) check_install && reset_config + 6) + check_install && set_port ;; - 6) check_install && set_port + 7) + check_install && check_config ;; - 7) check_install && start + 8) + check_install && start ;; - 8) check_install && stop + 9) + check_install && stop ;; - 9) check_install && restart + 10) + check_install && restart ;; - 10) check_install && status + 11) + check_install && status ;; - 11) check_install && show_log + 12) + check_install && show_log ;; - 12) check_install && enable + 13) + check_install && enable ;; - 13) check_install && disable + 14) + check_install && disable ;; - 14) install_bbr + 15) + install_bbr ;; - *) echo -e "${red}请输入正确的数字 [0-14]${plain}" + 16) + ssl_cert_issue + ;; + 17) + check_install && cron_jobs + ;; + *) + LOGE "请输入正确的数字 [0-17],查看面板登录信息请输入数字7" ;; esac } - if [[ $# > 0 ]]; then case $1 in - "start") check_install 0 && start 0 + "start") + check_install 0 && start 0 + ;; + "stop") + check_install 0 && stop 0 + ;; + "restart") + check_install 0 && restart 0 + ;; + "status") + check_install 0 && status 0 ;; - "stop") check_install 0 && stop 0 + "enable") + check_install 0 && enable 0 ;; - "restart") check_install 0 && restart 0 + "disable") + check_install 0 && disable 0 ;; - "status") check_install 0 && status 0 + "log") + check_install 0 && show_log 0 ;; - "enable") check_install 0 && enable 0 + "v2-ui") + check_install 0 && migrate_v2_ui 0 ;; - "disable") check_install 0 && disable 0 + "update") + check_install 0 && update 0 ;; - "log") check_install 0 && show_log 0 + "install") + check_uninstall 0 && install 0 ;; - "v2-ui") check_install 0 && migrate_v2_ui 0 + "uninstall") + check_install 0 && uninstall 0 ;; - "update") check_install 0 && update 0 + "geo") + check_install 0 && update_geo ;; - "install") check_uninstall 0 && install 0 + "clear") + check_install 0 && clear_log $2 ;; - "uninstall") check_install 0 && uninstall 0 + "cron") + check_install && cron_jobs ;; - *) show_usage + *) show_usage ;; esac else show_menu diff --git a/x-ui_en.sh b/x-ui_en.sh new file mode 100644 index 0000000000..ee5376649d --- /dev/null +++ b/x-ui_en.sh @@ -0,0 +1,935 @@ +#!/bin/bash + +red='\033[0;31m' +green='\033[0;32m' +yellow='\033[0;33m' +plain='\033[0m' + +#consts for log check and clear,unit:M +declare -r DEFAULT_LOG_FILE_DELETE_TRIGGER=35 + +# consts for geo update +PATH_FOR_GEO_IP='/usr/local/x-ui/bin/geoip.dat' +PATH_FOR_CONFIG='/usr/local/x-ui/bin/config.json' +PATH_FOR_GEO_SITE='/usr/local/x-ui/bin/geosite.dat' +URL_FOR_GEO_IP='https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat' +URL_FOR_GEO_SITE='https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat' + +#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 "${red}fatal error:please run this script with root privilege${plain}\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 "check system os failed,please contact with author!\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 "${red}please use CentOS 7 or higher version${plain}\n" && exit 1 + fi +elif [[ x"${release}" == x"ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + LOGE "${red}please use Ubuntu 16 or higher version${plain}\n" && exit 1 + fi +elif [[ x"${release}" == x"debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + LOGE "${red}please use Debian 8 or higher version${plain}\n" && exit 1 + fi +fi + +confirm() { + if [[ $# > 1 ]]; then + echo && read -p "$1 [default:$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 "confirm to restart x-ui,xray service will be restart" "y" + if [[ $? == 0 ]]; then + restart + else + show_menu + fi +} + +before_show_menu() { + echo && echo -n -e "${yellow}enter to return to the control menu: ${plain}" && read temp + show_menu +} + +install() { + bash <(curl -Ls https://raw.githubusercontent.com/FranzKafkaYu/x-ui/master/install_en.sh) + if [[ $? == 0 ]]; then + if [[ $# == 0 ]]; then + start + else + start 0 + fi + fi +} + +update() { + confirm "will upgrade to the latest,continue?" "n" + if [[ $? != 0 ]]; then + LOGE "cancelled..." + if [[ $# == 0 ]]; then + before_show_menu + fi + return 0 + fi + bash <(curl -Ls https://raw.githubusercontent.com/FranzKafkaYu/x-ui/master/install_en.sh) + if [[ $? == 0 ]]; then + LOGI "upgrade finished,restart completed" + exit 0 + fi +} + +uninstall() { + confirm "sure you want to uninstall x-ui?" "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 "uninstall x-ui succeed,you can delete this script by ${green}rm /usr/bin/x-ui -f${plain}" + echo "" + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +reset_user() { + confirm "are you sure you want to reset the username and password to ${green}admin${plain} ?" "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 "your username and password are reset to ${green}admin${plain},restart x-ui to take effect" + confirm_restart +} + +reset_config() { + confirm "are you sure you want to reset all settings,user data will not be lost" "n" + if [[ $? != 0 ]]; then + if [[ $# == 0 ]]; then + show_menu + fi + return 0 + fi + /usr/local/x-ui/x-ui setting -reset + echo -e "all settings are reset to default,please restart x-ui,and use default port ${green}54321${plain} to access panel" + confirm_restart +} + +check_config() { + info=$(/usr/local/x-ui/x-ui setting -show true) + if [[ $? != 0 ]]; then + LOGE "get current settings error,please check logs" + show_menu + fi + LOGI "${info}" +} + +set_port() { + echo && echo -n -e "please set a port[1-65535]: " && read port + if [[ -z "${port}" ]]; then + LOGD "cancelled..." + before_show_menu + else + /usr/local/x-ui/x-ui setting -port ${port} + echo -e "set port done,please restart x-ui,and use this new port ${green}${port}${plain} to access panel" + confirm_restart + fi +} + +start() { + check_status + if [[ $? == 0 ]]; then + echo "" + LOGI "x-ui is running,no need to start agin" + else + systemctl start x-ui + sleep 2 + check_status + if [[ $? == 0 ]]; then + LOGI "start x-ui succeed" + else + LOGE "start x-ui failed,please check logs" + fi + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +stop() { + check_status + if [[ $? == 1 ]]; then + echo "" + LOGI "x-ui is stopped,no need to stop again" + else + systemctl stop x-ui + sleep 2 + check_status + if [[ $? == 1 ]]; then + LOGI "stop x-ui succeed" + else + LOGE "stop x-ui failed,please check logs" + fi + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +restart() { + systemctl restart x-ui + sleep 2 + check_status + if [[ $? == 0 ]]; then + LOGI "restart x-ui succeed" + else + LOGE "stop x-ui failed,please check logs" + 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 "enable x-ui on system startup succeed" + else + LOGE "enable x-ui on system startup failed" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +disable() { + systemctl disable x-ui + if [[ $? == 0 ]]; then + LOGI "disable x-ui on system startup succeed" + else + LOGE "disable x-ui on system startup failed" + 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/FranzKafkaYu/x-ui/raw/master/x-ui_en.sh + if [[ $? != 0 ]]; then + echo "" + LOGE "update shell script failed,please check whether your server can access github" + before_show_menu + else + chmod +x /usr/bin/x-ui + LOGI "update shell script succeed" && 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 "x-ui is installed already" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +check_install() { + check_status + if [[ $? == 2 ]]; then + echo "" + LOGE "please install x-ui first" + if [[ $# == 0 ]]; then + before_show_menu + fi + return 1 + else + return 0 + fi +} + +show_status() { + check_status + case $? in + 0) + echo -e "x-ui status: ${green}running${plain}" + show_enable_status + ;; + 1) + echo -e "x-ui status: ${yellow}stopped${plain}" + show_enable_status + ;; + 2) + echo -e "x-ui status: ${red}not installed${plain}" + ;; + esac + show_xray_status +} + +show_enable_status() { + check_enabled + if [[ $? == 0 ]]; then + echo -e "enable on system startup: ${green}yes${plain}" + else + echo -e "enable on system startup: ${red}no${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 status: ${green}running${plain}" + else + echo -e "xray status: ${red}stopped${plain}" + fi +} + +#this will be an entrance for ssl cert issue +#here we can provide two different methods to issue cert +#first.standalone mode second.DNS API mode +ssl_cert_issue() { + local method="" + echo -E "" + LOGD "********Usage********" + LOGI "this shell script will use acme to help issue certs." + LOGI "here we provide two methods for issuing certs:" + LOGI "method 1:acme standalone mode,need to keep port:80 open" + LOGI "method 2:acme DNS API mode,need provide Cloudflare Global API Key" + LOGI "recommend method 2 first,if it fails,you can try method 1." + LOGI "certs will be installed in /root/cert directory" + read -p "please choose which method do you want,type 1 or 2": method + LOGI "you choosed method:${method}" + + if [ "${method}" == "1" ]; then + ssl_cert_issue_standalone + elif [ "${method}" == "2" ]; then + ssl_cert_issue_by_cloudflare + else + LOGE "invalid input,please check it..." + exit 1 + fi +} + +install_acme() { + cd ~ + LOGI "install acme..." + curl https://get.acme.sh | sh + if [ $? -ne 0 ]; then + LOGE "install acme failed" + return 1 + else + LOGI "install acme succeed" + fi + return 0 +} + +#method for standalone mode +ssl_cert_issue_standalone() { + #check for acme.sh first + if ! command -v ~/.acme.sh/acme.sh &>/dev/null; then + echo "acme.sh could not be found. we will install it" + install_acme + if [ $? -ne 0 ]; then + LOGE "install acme failed, please check logs" + exit 1 + fi + fi + #install socat second + if [[ x"${release}" == x"centos" ]]; then + yum install socat -y + else + apt install socat -y + fi + if [ $? -ne 0 ]; then + LOGE "install socat failed, please check logs" + exit 1 + else + LOGI "install socat succeed..." + fi + #creat a directory for install cert + certPath=/root/cert + if [ ! -d "$certPath" ]; then + mkdir $certPath + fi + #get the domain here,and we need verify it + local domain="" + read -p "please input your domain:" domain + LOGD "your domain is:${domain},check it..." + #here we need to judge whether there exists cert already + local currentCert=$(~/.acme.sh/acme.sh --list | grep ${domain} | wc -l) + if [ ${currentCert} -ne 0 ]; then + local certInfo=$(~/.acme.sh/acme.sh --list) + LOGE "system already have certs here,can not issue again,current certs details:" + LOGI "$certInfo" + exit 1 + else + LOGI "your domain is ready for issuing cert now..." + fi + #get needed port here + local WebPort=80 + read -p "please choose which port do you use,default will be 80 port:" WebPort + if [[ ${WebPort} -gt 65535 || ${WebPort} -lt 1 ]]; then + LOGE "your input ${WebPort} is invalid,will use default port" + fi + LOGI "will use port:${WebPort} to issue certs,please make sure this port is open..." + #NOTE:This should be handled by user + #open the port and kill the occupied progress + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + ~/.acme.sh/acme.sh --issue -d ${domain} --standalone --httpport ${WebPort} + if [ $? -ne 0 ]; then + LOGE "issue certs failed,please check logs" + rm -rf ~/.acme.sh/${domain} + exit 1 + else + LOGE "issue certs succeed,installing certs..." + fi + #install cert + ~/.acme.sh/acme.sh --installcert -d ${domain} --ca-file /root/cert/ca.cer \ + --cert-file /root/cert/${domain}.cer --key-file /root/cert/${domain}.key \ + --fullchain-file /root/cert/fullchain.cer + + if [ $? -ne 0 ]; then + LOGE "install certs failed,exit" + rm -rf ~/.acme.sh/${domain} + exit 1 + else + LOGI "install certs succeed,enable auto renew..." + fi + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [ $? -ne 0 ]; then + LOGE "auto renew failed,certs details:" + ls -lah cert + chmod 755 $certPath + exit 1 + else + LOGI "auto renew succeed,certs details:" + ls -lah cert + chmod 755 $certPath + fi + +} + +#method for DNS API mode +ssl_cert_issue_by_cloudflare() { + echo -E "" + LOGD "******Preconditions******" + LOGI "1.need Cloudflare account associated email" + LOGI "2.need Cloudflare Global API Key" + LOGI "3.your domain use Cloudflare as resolver" + confirm "I have confirmed all these info above[y/n]" "y" + if [ $? -eq 0 ]; then + install_acme + if [ $? -ne 0 ]; then + LOGE "install acme failed,please check logs" + exit 1 + fi + CF_Domain="" + CF_GlobalKey="" + CF_AccountEmail="" + certPath=/root/cert + if [ ! -d "$certPath" ]; then + mkdir $certPath + fi + LOGD "please input your domain:" + read -p "Input your domain here:" CF_Domain + LOGD "your domain is:${CF_Domain},check it..." + #here we need to judge whether there exists cert already + local currentCert=$(~/.acme.sh/acme.sh --list | grep ${CF_Domain} | wc -l) + if [ ${currentCert} -ne 0 ]; then + local certInfo=$(~/.acme.sh/acme.sh --list) + LOGE "system already have certs here,can not issue again,current certs details:" + LOGI "$certInfo" + exit 1 + else + LOGI "your domain is ready for issuing cert now..." + fi + LOGD "please inout your cloudflare global API key:" + read -p "Input your key here:" CF_GlobalKey + LOGD "your cloudflare global API key is:${CF_GlobalKey}" + LOGD "please input your cloudflare account email:" + read -p "Input your email here:" CF_AccountEmail + LOGD "your cloudflare account email:${CF_AccountEmail}" + ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt + if [ $? -ne 0 ]; then + LOGE "change the default CA to Lets'Encrypt failed,exit" + exit 1 + fi + export CF_Key="${CF_GlobalKey}" + export CF_Email=${CF_AccountEmail} + ~/.acme.sh/acme.sh --issue --dns dns_cf -d ${CF_Domain} -d *.${CF_Domain} --log + if [ $? -ne 0 ]; then + LOGE "issue cert failed,exit" + rm -rf ~/.acme.sh/${CF_Domain} + exit 1 + else + LOGI "issue cert succeed,installing..." + fi + ~/.acme.sh/acme.sh --installcert -d ${CF_Domain} -d *.${CF_Domain} --ca-file /root/cert/ca.cer \ + --cert-file /root/cert/${CF_Domain}.cer --key-file /root/cert/${CF_Domain}.key \ + --fullchain-file /root/cert/fullchain.cer + if [ $? -ne 0 ]; then + LOGE "install cert failed,exit" + rm -rf ~/.acme.sh/${CF_Domain} + exit 1 + else + LOGI "install cert succeed,enable auto renew..." + fi + ~/.acme.sh/acme.sh --upgrade --auto-upgrade + if [ $? -ne 0 ]; then + LOGE "enable auto renew failed,exit" + ls -lah cert + chmod 755 $certPath + exit 1 + else + LOGI "enable auto renew succeed,cert details:" + ls -lah cert + chmod 755 $certPath + fi + else + show_menu + fi +} + +#add for cron jobs,including sync geo data,check logs and restart x-ui +cron_jobs() { + clear + echo -e " + ${green}x-ui cron jobs${plain} + ${green}0.${plain} return main menu + ${green}1.${plain} enable automatically update geo data + ${green}2.${plain} disable automatically update geo data + ${green}3.${plain} enable automatically clear xray log + ${green}4.${plain} disable automatically clear xray log + " + echo && read -p "plz input your choice [0-4]: " num + case "${num}" in + 0) + show_menu + ;; + 1) + enable_auto_update_geo + ;; + 2) + disable_auto_update_geo + ;; + 3) + enable_auto_clear_log + ;; + 4) + disable_auto_clear_log + ;; + *) + LOGE "plz input a valid choice [0-4]" + ;; + esac +} + +#update geo data +update_geo() { + #back up first + mv ${PATH_FOR_GEO_IP} ${PATH_FOR_GEO_IP}.bak + #update data + curl -s -L -o ${PATH_FOR_GEO_IP} ${URL_FOR_GEO_IP} + if [[ $? -ne 0 ]]; then + echo "update geoip.dat failed" + mv ${PATH_FOR_GEO_IP}.bak ${PATH_FOR_GEO_IP} + else + echo "update geoip.dat succeed" + rm -f ${PATH_FOR_GEO_IP}.bak + fi + mv ${PATH_FOR_GEO_SITE} ${PATH_FOR_GEO_SITE}.bak + curl -s -L -o ${PATH_FOR_GEO_SITE} ${URL_FOR_GEO_SITE} + if [[ $? -ne 0 ]]; then + echo "update geosite.dat failed" + mv ${PATH_FOR_GEO_SITE}.bak ${PATH_FOR_GEO_SITE} + else + echo "update geosite.dat succeed" + rm -f ${PATH_FOR_GEO_SITE}.bak + fi + #restart x-ui + systemctl restart x-ui +} + +enable_auto_update_geo() { + LOGI "enable automatically update geo data..." + crontab -l >/tmp/crontabTask.tmp + echo "00 4 */2 * * x-ui geo > /dev/null" >>/tmp/crontabTask.tmp + crontab /tmp/crontabTask.tmp + rm /tmp/crontabTask.tmp + LOGI "enable automatically update geo data succeed" +} + +disable_auto_update_geo() { + crontab -l | grep -v "x-ui geo" | crontab - + if [[ $? -ne 0 ]]; then + LOGI "cancel x-ui automatically update geo data failed" + else + LOGI "cancel x-ui automatically update geo data succeed" + fi +} + +#clear xray log,need enable log in config template +#here we need input an absolute path for log +clear_log() { + LOGI "clear xray logs..." + local filePath='' + if [[ $# -gt 0 ]]; then + filePath=$1 + else + LOGE "invalid file path,will exit" + exit 1 + fi + LOGI "log file:${filePath}" + if [[ ! -f ${filePath} ]]; then + LOGE "clear xray log failed,${filePath} didn't exist,plz check it" + exit 1 + fi + fileSize=$(ls -la ${filePath} --block-size=M | awk '{print $5}' | awk -F 'M' '{print$1}') + if [[ ${fileSize} -gt ${DEFAULT_LOG_FILE_DELETE_TRIGGER} ]]; then + rm $1 + if [[ $? -ne 0 ]]; then + LOGE "clear xray log :${filePath} failed" + else + LOGI "clear xray log :${filePath} succeed" + systemctl restart x-ui + fi + else + LOGI "current size of xray log is:${fileSize}M,smaller that ${DEFAULT_LOG_FILE_DELETE_TRIGGER}M,won't clear" + fi +} + +#enable auto delete log,need file path as +enable_auto_clear_log() { + LOGI "enable automatically clear xray logs..." + local accessfilePath='' + local errorfilePath='' + accessfilePath=$(cat ${PATH_FOR_CONFIG} | jq .log.access | tr -d '"') + errorfilePath=$(cat ${PATH_FOR_CONFIG} | jq .log.error | tr -d '"') + if [[ ! -n ${accessfilePath} && ! -n ${errorfilePath} ]]; then + LOGI "current configuration didn't set valid logs,will exited" + exit 1 + fi + if [[ -f ${accessfilePath} ]]; then + crontab -l >/tmp/crontabTask.tmp + echo "30 4 */2 * * x-ui clear ${accessfilePath} > /dev/null" >>/tmp/crontabTask.tmp + crontab /tmp/crontabTask.tmp + rm /tmp/crontabTask.tmp + LOGI "enable automatically clear xray log:${accessfilePath} succeed" + else + LOGE "accesslog didn't existed,won't automatically clear it" + fi + + if [[ -f ${errorfilePath} ]]; then + crontab -l >/tmp/crontabTask.tmp + echo "30 4 */2 * * x-ui clear ${errorfilePath} > /dev/null" >>/tmp/crontabTask.tmp + crontab /tmp/crontabTask.tmp + rm /tmp/crontabTask.tmp + LOGI "enable automatically clear xray log:${errorfilePath} succeed" + else + LOGE "errorlog didn't existed,won't automatically clear it" + fi +} + +#disable auto dlete log +disable_auto_clear_log() { + crontab -l | grep -v "x-ui clear" | crontab - + if [[ $? -ne 0 ]]; then + LOGI "cancel automatically clear xray logs failed" + else + LOGI "cancel automatically clear xray logs succeed" + fi +} + +show_usage() { + echo "x-ui control menu usages: " + echo "------------------------------------------" + echo -e "x-ui - Enter control menu" + echo -e "x-ui start - Start x-ui " + echo -e "x-ui stop - Stop x-ui " + echo -e "x-ui restart - Restart x-ui " + echo -e "x-ui status - Show x-ui status" + echo -e "x-ui enable - Enable x-ui on system startup" + echo -e "x-ui disable - Disable x-ui on system startup" + echo -e "x-ui log - Check x-ui logs" + echo -e "x-ui update - Update x-ui " + echo -e "x-ui install - Install x-ui " + echo -e "x-ui uninstall - Uninstall x-ui " + echo "x-ui geo - Update x-ui geo " + echo "x-ui cron - Cron x-ui jobs" + echo "------------------------------------------" +} + +show_menu() { + echo -e " + ${green}x-ui control menu${plain} + ${green}0.${plain} exit +———————————————— + ${green}1.${plain} install x-ui + ${green}2.${plain} update x-ui + ${green}3.${plain} uninstall x-ui +———————————————— + ${green}4.${plain} reset username + ${green}5.${plain} reset panel + ${green}6.${plain} reset panel port + ${green}7.${plain} check panel info +———————————————— + ${green}8.${plain} start x-ui + ${green}9.${plain} stop x-ui + ${green}10.${plain} restart x-ui + ${green}11.${plain} check x-ui status + ${green}12.${plain} check x-ui logs +———————————————— + ${green}13.${plain} enable x-ui on system startup + ${green}14.${plain} disable x-ui on system startup +———————————————— + ${green}15.${plain} enable bbr + ${green}16.${plain} issuse certs + ${green}17.${plain} x-ui cron jobs + " + show_status + echo && read -p "please input a legal number[0-16],input 7 for checking login info:" 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 && check_config + ;; + 8) + check_install && start + ;; + 9) + check_install && stop + ;; + 10) + check_install && restart + ;; + 11) + check_install && status + ;; + 12) + check_install && show_log + ;; + 13) + check_install && enable + ;; + 14) + check_install && disable + ;; + 15) + install_bbr + ;; + 16) + ssl_cert_issue + ;; + 17) + check_install && cron_jobs + ;; + *) + LOGE "please input a legal number[0-17],input 7 for checking login info" + ;; + 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 + ;; + "geo") + check_install 0 && update_geo + ;; + "clear") + check_install 0 && clear_log $2 + ;; + "cron") + check_install && cron_jobs + ;; + *) show_usage ;; + esac +else + show_menu +fi