diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1dd0e5eb34..9634488a26 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,7 +42,7 @@ jobs: mv xui-release x-ui mkdir bin cd bin - wget https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-64.zip + wget https://github.com/hossinasaadi/Xray-core/releases/latest/download/Xray-linux-64.zip unzip Xray-linux-64.zip rm -f Xray-linux-64.zip geoip.dat geosite.dat wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat @@ -84,7 +84,7 @@ jobs: mv xui-release x-ui mkdir bin cd bin - wget https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-arm64-v8a.zip + wget https://github.com/hossinasaadi/Xray-core/releases/latest/download/Xray-linux-arm64-v8a.zip unzip Xray-linux-arm64-v8a.zip rm -f Xray-linux-arm64-v8a.zip geoip.dat geosite.dat wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat @@ -126,7 +126,7 @@ jobs: mv xui-release x-ui mkdir bin cd bin - wget https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-s390x.zip + wget https://github.com/hossinasaadi/Xray-core/releases/latest/download/Xray-linux-s390x.zip unzip Xray-linux-s390x.zip rm -f Xray-linux-s390x.zip geoip.dat geosite.dat wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat @@ -144,4 +144,4 @@ jobs: upload_url: ${{ needs.release.outputs.upload_url }} asset_path: x-ui-linux-s390x.tar.gz asset_name: x-ui-linux-s390x.tar.gz - asset_content_type: application/gzip \ No newline at end of file + asset_content_type: application/gzip diff --git a/.gitignore b/.gitignore index 1b5f0069ca..63ca6b69bc 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ x-ui-*.tar.gz /release.sh .sync* main +release/ +access.log +.cache diff --git a/README.md b/README.md index 80a9e302df..5f65d2636e 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,45 @@ # x-ui -支持多协议多用户的 xray 面板 +xray panel supporting multi-protocol multi-user + +# Features + +- System Status Monitoring +- Support multi-user multi-protocol, web page visualization operation +- Supported protocols: vmess, vless, trojan, shadowsocks, dokodemo-door, socks, http +- Support for configuring more transport configurations +- Traffic statistics, limit traffic, limit expiration time +- Customizable xray configuration templates +- Support https access panel (self-provided domain name + ssl certificate) +- Support one-click SSL certificate application and automatic renewal +- For more advanced configuration items, please refer to the panel + +# Enable IP Restrictions Per Inbound +1 - open panel settings and tab xray related settings put this to first of json : + ``` + { + "log": { + "loglevel": "warning", + "access": "./access.log" + }, -# 功能介绍 +``` +- change access log path as you want -- 系统状态监控 -- 支持多用户多协议,网页可视化操作 -- 支持的协议:vmess、vless、trojan、shadowsocks、dokodemo-door、socks、http -- 支持配置更多传输配置 -- 流量统计,限制流量,限制到期时间 -- 可自定义 xray 配置模板 -- 支持 https 访问面板(自备域名 + ssl 证书) -- 支持一键SSL证书申请且自动续签 -- 更多高级配置项,详见面板 +2 - add **IP limit and Email** for inbound(vmess & vless) -# 安装&升级 +# Install & Upgrade ``` -bash <(curl -Ls https://raw.githubusercontent.com/vaxilu/x-ui/master/install.sh) +bash <(curl -Ls https://raw.githubusercontent.com/hossinasaadi/x-ui/master/install.sh) ``` -## 手动安装&升级 +## Manual install & upgrade -1. 首先从 https://github.com/vaxilu/x-ui/releases 下载最新的压缩包,一般选择 `amd64`架构 -2. 然后将这个压缩包上传到服务器的 `/root/`目录下,并使用 `root`用户登录服务器 +1. First download the latest compressed package from https://github.com/hossinasaadi/x-ui/releases , generally choose Architecture `amd64` +2. Then upload the compressed package to the server's `/root/` directory and `root` rootlog in to the server with user -> 如果你的服务器 cpu 架构不是 `amd64`,自行将命令中的 `amd64`替换为其他架构 +> If your server cpu architecture is not `amd64` replace another architecture ``` cd /root/ @@ -40,17 +54,17 @@ systemctl enable x-ui systemctl restart x-ui ``` -## 使用docker安装 +## Install using docker -> 此 docker 教程与 docker 镜像由[Chasing66](https://github.com/Chasing66)提供 +> This docker tutorial and docker image are provided by [Chasing66](https://github.com/Chasing66) -1. 安装docker +1. install docker ```shell curl -fsSL https://get.docker.com | sh ``` -2. 安装x-ui +2. install x-ui ```shell mkdir x-ui && cd x-ui @@ -61,83 +75,82 @@ docker run -itd --network=host \ enwaiax/x-ui:latest ``` -> Build 自己的镜像 +> Build your own image ```shell docker build -t x-ui . ``` -## SSL证书申请 +## SSL certificate application -> 此功能与教程由[FranzKafkaYu](https://github.com/FranzKafkaYu)提供 +> This feature and tutorial are provided by [FranzKafkaYu](https://github.com/FranzKafkaYu) -脚本内置SSL证书申请功能,使用该脚本申请证书,需满足以下条件: +The script has a built-in SSL certificate application function. To use this script to apply for a certificate, the following conditions must be met: -- 知晓Cloudflare 注册邮箱 -- 知晓Cloudflare Global API Key -- 域名已通过cloudflare进行解析到当前服务器 +- Know the Cloudflare registered email +- Know the Cloudflare Global API Key +- The domain name has been resolved to the current server through cloudflare -获取Cloudflare Global API Key的方法: +How to get the Cloudflare Global API Key: ![](media/bda84fbc2ede834deaba1c173a932223.png) ![](media/d13ffd6a73f938d1037d0708e31433bf.png) -使用时只需输入 `域名`, `邮箱`, `API KEY`即可,示意图如下: +When using, just enter `email`, `domain`, `API KEY` and the schematic diagram is as follows: ![](media/2022-04-04_141259.png) -注意事项: +Precautions: + +- The script uses DNS API for certificate request +- By default, Let'sEncrypt is used as the CA party +- The certificate installation directory is the /root/cert directory +- The certificates applied for by this script are all generic domain name certificates + +## Tg robot use (under development, temporarily unavailable) + +> This feature and tutorial are provided by [FranzKafkaYu](https://github.com/FranzKafkaYu) -- 该脚本使用DNS API进行证书申请 -- 默认使用Let'sEncrypt作为CA方 -- 证书安装目录为/root/cert目录 -- 本脚本申请证书均为泛域名证书 +X-UI supports daily traffic notification, panel login reminder and other functions through the Tg robot. To use the Tg robot, you need to apply for the specific application tutorial. You can refer to the [blog](https://coderfan.net/how-to-use-telegram-bot-to-alarm-you-when-someone-login-into-your-vps.html) +Set the robot-related parameters in the panel background, including: -## Tg机器人使用(开发中,暂不可使用) +- Tg Robot Token +- Tg Robot ChatId +- Tg robot cycle runtime, in crontab syntax -> 此功能与教程由[FranzKafkaYu](https://github.com/FranzKafkaYu)提供 -X-UI支持通过Tg机器人实现每日流量通知,面板登录提醒等功能,使用Tg机器人,需要自行申请 -具体申请教程可以参考[博客链接](https://coderfan.net/how-to-use-telegram-bot-to-alarm-you-when-someone-login-into-your-vps.html) -使用说明:在面板后台设置机器人相关参数,具体包括 +Reference syntax: -- Tg机器人Token -- Tg机器人ChatId -- Tg机器人周期运行时间,采用crontab语法 +- 30 * * * * * //Notify at the 30s of each point +- @hourly // hourly notification +- @daily // Daily notification (00:00 in the morning) +- @every 8h // notify every 8 hours +- TG notification content: -参考语法: -- 30 * * * * * //每一分的第30s进行通知 -- @hourly //每小时通知 -- @daily //每天通知(凌晨零点整) -- @every 8h //每8小时通知 +- Node traffic usage +- Panel login reminder +- Node expiration reminder +- Traffic warning reminder -TG通知内容: -- 节点流量使用 -- 面板登录提醒 -- 节点到期提醒 -- 流量预警提醒 +More features are planned... -更多功能规划中... -## 建议系统 + +## suggestion system - CentOS 7+ - Ubuntu 16+ - Debian 8+ -# 常见问题 +# common problem -## 从 v2-ui 迁移 +## Migrating from v2-ui -首先在安装了 v2-ui 的服务器上安装最新版 x-ui,然后使用以下命令进行迁移,将迁移本机 v2-ui 的 `所有 inbound 账号数据`至 x-ui,`面板设置和用户名密码不会迁移` +First install the latest version of x-ui on the server where v2-ui is installed, and then use the following command to migrate, which will migrate the native v2-ui `All inbound account data` to x-ui,`Panel settings and username passwords are not migrated` -> 迁移成功后请 `关闭 v2-ui`并且 `重启 x-ui`,否则 v2-ui 的 inbound 会与 x-ui 的 inbound 会产生 `端口冲突` +> Please `Close v2-ui` and `restart x-ui`, otherwise the inbound of v2-ui will cause a `port conflict with the inbound of x-ui` ``` x-ui v2-ui ``` -## issue 关闭 - -各种小白问题看得血压很高 - ## Stargazers over time -[![Stargazers over time](https://starchart.cc/vaxilu/x-ui.svg)](https://starchart.cc/vaxilu/x-ui) +[![Stargazers over time](https://starchart.cc/hossinasaadi/x-ui.svg)](https://starchart.cc/hossinasaadi/x-ui) diff --git a/database/db.go b/database/db.go index 3273874ad8..ef5bf2f3d7 100644 --- a/database/db.go +++ b/database/db.go @@ -40,6 +40,9 @@ func initInbound() error { func initSetting() error { return db.AutoMigrate(&model.Setting{}) } +func initInboundClientIps() error { + return db.AutoMigrate(&model.InboundClientIps{}) +} func InitDB(dbPath string) error { dir := path.Dir(dbPath) @@ -76,6 +79,10 @@ func InitDB(dbPath string) error { if err != nil { return err } + err = initInboundClientIps() + if err != nil { + return err + } return nil } diff --git a/database/model/model.go b/database/model/model.go index bc19444598..b71421575f 100644 --- a/database/model/model.go +++ b/database/model/model.go @@ -42,6 +42,11 @@ type Inbound struct { Tag string `json:"tag" form:"tag" gorm:"unique"` Sniffing string `json:"sniffing" form:"sniffing"` } +type InboundClientIps struct { + Id int `json:"id" gorm:"primaryKey;autoIncrement"` + ClientEmail string `json:"clientEmail" form:"clientEmail" gorm:"unique"` + Ips string `json:"ips" form:"ips"` +} func (i *Inbound) GenXrayInboundConfig() *xray.InboundConfig { listen := i.Listen diff --git a/go.mod b/go.mod index 44b6570b6f..0342d7d24e 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/Workiva/go-datastructures v1.0.53 github.com/gin-contrib/sessions v0.0.3 github.com/gin-gonic/gin v1.7.1 + github.com/go-cmd/cmd v1.4.1 // indirect github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 github.com/nicksnyder/go-i18n/v2 v2.1.2 diff --git a/go.sum b/go.sum index c8ed240f17..9b808dd80f 100644 --- a/go.sum +++ b/go.sum @@ -57,6 +57,8 @@ github.com/gin-gonic/gin v1.7.1 h1:qC89GU3p8TvKWMAVhEpmpB2CIb1hnqt2UdKZaP93mS8= github.com/gin-gonic/gin v1.7.1/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-cmd/cmd v1.4.1 h1:JUcEIE84v8DSy02XTZpUDeGKExk2oW3DA10hTjbQwmc= +github.com/go-cmd/cmd v1.4.1/go.mod h1:tbBenttXtZU4c5djS1o7PWL5pd2xAr5sIqH1kGdNiRc= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -72,6 +74,7 @@ github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7a github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc= github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8= +github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= diff --git a/install.sh b/install.sh index d6ffd104e3..7dd07ed977 100755 --- a/install.sh +++ b/install.sh @@ -107,20 +107,20 @@ install_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/') + last_version=$(curl -Ls "https://api.github.com/repos/hossinasaadi/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/hossinasaadi/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/hossinasaadi/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 @@ -138,7 +138,7 @@ 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/hossinasaadi/x-ui/main/x-ui.sh chmod +x /usr/local/x-ui/x-ui.sh chmod +x /usr/bin/x-ui config_after_install diff --git a/web/assets/js/langs.js b/web/assets/js/langs.js new file mode 100644 index 0000000000..be7dd164ba --- /dev/null +++ b/web/assets/js/langs.js @@ -0,0 +1,79 @@ +supportLangs = [ + { + name : "English", + value : "en-US", + icon : "🇺🇸" + }, + { + name : "汉语", + value : "zh-Hans", + icon : "🇨🇳" + }, +] + +function getLang(){ + let lang = getCookie('lang') + + if (! lang){ + if (window.navigator){ + lang = window.navigator.language || window.navigator.userLanguage; + + if (isSupportLang(lang)){ + setCookie('lang' , lang , 150) + }else{ + setCookie('lang' , 'en-US' , 150) + window.location.reload(); + } + }else{ + setCookie('lang' , 'en-US' , 150) + window.location.reload(); + } + } + + return lang; +} + +function setLang(lang){ + + if (!isSupportLang(lang)){ + lang = 'en-US'; + } + + setCookie('lang' , lang , 150) + window.location.reload(); +} + +function isSupportLang(lang){ + for (l of supportLangs){ + if (l.value === lang){ + return true; + } + } + + return false; +} + + + +function getCookie(cname) { + let name = cname + "="; + let decodedCookie = decodeURIComponent(document.cookie); + let ca = decodedCookie.split(';'); + for(let i = 0; i - {{.title}} + {{ i18n .title}} {{end}} \ No newline at end of file diff --git a/web/html/common/js.html b/web/html/common/js.html index b8ee57b2f8..d400196b03 100644 --- a/web/html/common/js.html +++ b/web/html/common/js.html @@ -14,6 +14,7 @@ + diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index 85321eded4..3c5aafb508 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -27,15 +27,15 @@ - 总上传 / 下载: + {{ i18n "pages.inbounds.totalDownUp" }}: [[ sizeFormat(total.up) ]] / [[ sizeFormat(total.down) ]] - 总用量: + {{ i18n "pages.inbounds.totalUsage" }}: [[ sizeFormat(total.up + total.down) ]] - 入站数量: + {{ i18n "pages.inbounds.inboundCount" }}: [[ dbInbounds.length ]] @@ -55,20 +55,22 @@ @change="() => getDBInbounds()"> - 无限制 + {{ i18n "unlimited" }} - 无限期 + {{ i18n "indefinitely" }} @@ -121,52 +123,52 @@