From 5f9058c84f6a46a2233f323dcdac8281975accc0 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Fri, 26 Jan 2024 16:50:22 +0330 Subject: [PATCH 01/27] fix downloaded log format Co-Authored-By: Alireza Ahmadi --- web/html/xui/index.html | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/web/html/xui/index.html b/web/html/xui/index.html index 3c01a29f..258d4154 100644 --- a/web/html/xui/index.html +++ b/web/html/xui/index.html @@ -299,12 +299,12 @@ + :href="'data:application/text;charset=utf-8,' + encodeURIComponent(logModal.logs.join('\n'))" download="x-ui.log"> {{ i18n "download" }} x-ui.log -
+
0 ? this.formatLogs(logs) : "No Record..."; }, formatLogs(logs) { let formattedLogs = ''; From 98384ac2365cabe6a4a200062a90b59f6ce5ad72 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Fri, 26 Jan 2024 16:50:35 +0330 Subject: [PATCH 02/27] fix - direct tag --- web/service/config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/web/service/config.json b/web/service/config.json index c846d590..82f7dddf 100644 --- a/web/service/config.json +++ b/web/service/config.json @@ -24,6 +24,7 @@ ], "outbounds": [ { + "tag": "direct", "protocol": "freedom", "settings": {} }, From 08e259327b8a7b606b95e3b145fe1959b426d7c4 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Fri, 26 Jan 2024 17:06:54 +0330 Subject: [PATCH 03/27] unnecessary use of fmt.Sprintf --- web/service/xray_setting.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/service/xray_setting.go b/web/service/xray_setting.go index 1d2e696e..86bb1d7b 100644 --- a/web/service/xray_setting.go +++ b/web/service/xray_setting.go @@ -80,7 +80,7 @@ func (s *XraySettingService) RegWarp(secretKey string, publicKey string) (string hostName, _ := os.Hostname() data := fmt.Sprintf(`{"key":"%s","tos":"%s","type": "PC","model": "x-ui", "name": "%s"}`, publicKey, tos, hostName) - url := fmt.Sprintf("https://api.cloudflareclient.com/v0a2158/reg") + url := "https://api.cloudflareclient.com/v0a2158/reg" req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(data))) if err != nil { From ec88053df0f2619bdb6285bcd2085675efbc8ca8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Jan 2024 20:15:07 +0330 Subject: [PATCH 04/27] Bump gorm.io/gorm from 1.25.5 to 1.25.6 (#1683) Bumps [gorm.io/gorm](https://github.com/go-gorm/gorm) from 1.25.5 to 1.25.6. - [Release notes](https://github.com/go-gorm/gorm/releases) - [Commits](https://github.com/go-gorm/gorm/compare/v1.25.5...v1.25.6) --- updated-dependencies: - dependency-name: gorm.io/gorm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 80fd416a..d46ed1fe 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( golang.org/x/text v0.14.0 google.golang.org/grpc v1.61.0 gorm.io/driver/sqlite v1.5.4 - gorm.io/gorm v1.25.5 + gorm.io/gorm v1.25.6 ) require ( diff --git a/go.sum b/go.sum index 1663fce7..8b6465d7 100644 --- a/go.sum +++ b/go.sum @@ -437,8 +437,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/sqlite v1.5.4 h1:IqXwXi8M/ZlPzH/947tn5uik3aYQslP9BVveoax0nV0= gorm.io/driver/sqlite v1.5.4/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4= -gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= -gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.6 h1:V92+vVda1wEISSOMtodHVRcUIOPYa2tgQtyF+DfFx+A= +gorm.io/gorm v1.25.6/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= gvisor.dev/gvisor v0.0.0-20231104011432-48a6d7d5bd0b h1:yqkg3pTifuKukuWanp8spDsL4irJkHF5WI0J47hU87o= gvisor.dev/gvisor v0.0.0-20231104011432-48a6d7d5bd0b/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk= From daa43540477e18ae5c6e19e887733b793c17ad72 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Fri, 26 Jan 2024 21:57:46 +0330 Subject: [PATCH 05/27] ipv6 for familyProtect and some changes --- web/assets/js/model/outbound.js | 4 ++-- web/assets/js/model/xray.js | 2 +- web/html/xui/warp_modal.html | 1 + web/html/xui/xray.html | 6 ++++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index 0191c4a4..42fb50a1 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -915,7 +915,7 @@ Outbound.HttpSettings = class extends CommonClass { Outbound.WireguardSettings = class extends CommonClass { constructor( mtu=1420, secretKey=Wireguard.generateKeypair().privateKey, - address='', workers=2, domainStrategy='', reserved='', + address=[''], workers=2, domainStrategy='ForceIPv6v4', reserved='', peers=[new Outbound.WireguardSettings.Peer()], kernelMode=false) { super(); this.mtu = mtu; @@ -965,7 +965,7 @@ Outbound.WireguardSettings = class extends CommonClass { }; Outbound.WireguardSettings.Peer = class extends CommonClass { - constructor(publicKey='', psk='', allowedIPs=['0.0.0.0/0','::/0'], endpoint='', keepAlive=0) { + constructor(publicKey=Wireguard.generateKeypair().publicKey, psk='', allowedIPs=['0.0.0.0/0','::/0'], endpoint='', keepAlive=0) { super(); this.publicKey = publicKey; this.psk = psk; diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index b2c8a2e5..e9676252 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -2297,7 +2297,7 @@ Inbound.WireguardSettings = class extends XrayCommonClass { }; Inbound.WireguardSettings.Peer = class extends XrayCommonClass { - constructor(publicKey='', psk='', allowedIPs=['0.0.0.0/0','::/0'], keepAlive=0) { + constructor(publicKey=Wireguard.generateKeypair().publicKey, psk='', allowedIPs=['0.0.0.0/0','::/0'], keepAlive=0) { super(); this.publicKey = publicKey; this.psk = psk; diff --git a/web/html/xui/warp_modal.html b/web/html/xui/warp_modal.html index d1663df0..4e6dd4fa 100644 --- a/web/html/xui/warp_modal.html +++ b/web/html/xui/warp_modal.html @@ -140,6 +140,7 @@ mtu: 1420, secretKey: warpModal.warpData.private_key, address: Object.values(config.interface.addresses), + domainStrategy: 'ForceIPv6v4', peers: [{ publicKey: peer.public_key, endpoint: peer.endpoint.host, diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html index 05f5f178..d6f0c0f8 100644 --- a/web/html/xui/xray.html +++ b/web/html/xui/xray.html @@ -569,9 +569,11 @@ familyProtectDNS: { "servers": [ "1.1.1.3", // https://developers.cloudflare.com/1.1.1.1/setup/ - "1.0.0.3" + "1.0.0.3", + "2606:4700:4700::1113", + "2606:4700:4700::1003" ], - "queryStrategy": "UseIPv4" + "queryStrategy": "UseIP" }, } }, From 9fba92d879767394535f70ba83f0a58d6b063a7d Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Fri, 26 Jan 2024 22:07:15 +0330 Subject: [PATCH 06/27] v2.1.2 revert #1650 #1661 #1664 #1670 made panel full of bug --- .github/workflows/docker.yml | 2 +- README.md | 4 +- config/version | 2 +- web/assets/js/util/utils.js | 35 ------ web/controller/inbound.go | 111 +++--------------- web/html/common/qrcode_modal.html | 17 +-- web/html/xui/client_modal.html | 154 +++---------------------- web/html/xui/form/client.html | 16 +-- web/html/xui/inbound_modal.html | 4 - web/html/xui/inbounds.html | 82 +++---------- web/translation/translate.en_US.toml | 3 - web/translation/translate.es_ES.toml | 3 - web/translation/translate.fa_IR.toml | 3 - web/translation/translate.ru_RU.toml | 3 - web/translation/translate.vi_VN.toml | 3 - web/translation/translate.zh_Hans.toml | 3 - 16 files changed, 57 insertions(+), 388 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6afe8618..1115de37 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -36,6 +36,6 @@ jobs: with: context: . push: ${{ github.event_name != 'pull_request' }} - platforms: linux/amd64, linux/arm64/v8, linux/arm/v7, linux/arm/v6, linux/386, linux/arm/v5 + platforms: linux/amd64, linux/arm64/v8, linux/arm/v7, linux/arm/v6, linux/386 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/README.md b/README.md index 6b0beab7..389d6d1d 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install. ## Install Custom Version -To install your desired version, add the version to the end of the installation command. e.g., ver `v2.1.1`: +To install your desired version, add the version to the end of the installation command. e.g., ver `v2.1.2`: ``` -bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.1.1 +bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.1.2 ``` ## Manual Install & Upgrade diff --git a/config/version b/config/version index 7c327287..8f9174b4 100644 --- a/config/version +++ b/config/version @@ -1 +1 @@ -2.1.1 \ No newline at end of file +2.1.2 \ No newline at end of file diff --git a/web/assets/js/util/utils.js b/web/assets/js/util/utils.js index 48ff237d..61b322bd 100644 --- a/web/assets/js/util/utils.js +++ b/web/assets/js/util/utils.js @@ -83,41 +83,6 @@ class HttpUtil { } return msg; } - - static async jsonPost(url, data) { - let msg; - try { - const requestOptions = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - }; - const resp = await fetch(url, requestOptions); - const response = await resp.json(); - - msg = this._respToMsg({data : response}); - } catch (e) { - msg = new Msg(false, e.toString()); - } - this._handleMsg(msg); - return msg; - } - - static async postWithModalJson(url, data, modal) { - if (modal) { - modal.loading(true); - } - const msg = await this.jsonPost(url, data); - if (modal) { - modal.loading(false); - if (msg instanceof Msg && msg.success) { - modal.close(); - } - } - return msg; - } } class PromiseUtil { diff --git a/web/controller/inbound.go b/web/controller/inbound.go index 0aa2e2df..86da9813 100644 --- a/web/controller/inbound.go +++ b/web/controller/inbound.go @@ -1,7 +1,6 @@ package controller import ( - "errors" "encoding/json" "fmt" "strconv" @@ -33,9 +32,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) { g.POST("/clientIps/:email", a.getClientIps) g.POST("/clearClientIps/:email", a.clearClientIps) g.POST("/addClient", a.addInboundClient) - g.POST("/addGroupClient", a.addGroupInboundClient) g.POST("/:id/delClient/:clientId", a.delInboundClient) - g.POST("/updateClients", a.updateGroupInboundClient) g.POST("/updateClient/:clientId", a.updateInboundClient) g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic) g.POST("/resetAllTraffics", a.resetAllTraffics) @@ -163,51 +160,23 @@ func (a *InboundController) clearClientIps(c *gin.Context) { func (a *InboundController) addInboundClient(c *gin.Context) { data := &model.Inbound{} - err := c.ShouldBind(data) - if err != nil { - jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) - return - } + err := c.ShouldBind(data) + if err != nil { + jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) + return + } - needRestart := true - - needRestart, err = a.inboundService.AddInboundClient(data) - if err != nil { - jsonMsg(c, "Something went wrong!", err) - return - } - jsonMsg(c, "Client(s) added", nil) - if err == nil && needRestart { - a.xrayService.SetToNeedRestart() - } -} - -func (a *InboundController) addGroupInboundClient(c *gin.Context) { - var requestData []model.Inbound - - err := c.ShouldBindJSON(&requestData) - - if err != nil { - jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) - return - } - - needRestart := true - - for _, data := range requestData { - - needRestart, err = a.inboundService.AddInboundClient(&data) - if err != nil { - jsonMsg(c, "Something went wrong!", err) - return - } - } - - jsonMsg(c, "Client(s) added", nil) - if err == nil && needRestart { - a.xrayService.SetToNeedRestart() - } + needRestart := true + needRestart, err = a.inboundService.AddInboundClient(data) + if err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } + jsonMsg(c, "Client(s) added", nil) + if err == nil && needRestart { + a.xrayService.SetToNeedRestart() + } } func (a *InboundController) delInboundClient(c *gin.Context) { @@ -254,56 +223,6 @@ func (a *InboundController) updateInboundClient(c *gin.Context) { } } -func (a *InboundController) updateGroupInboundClient(c *gin.Context) { - var requestData []map[string]interface{} - - if err := c.ShouldBindJSON(&requestData); err != nil { - jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) - return - } - - needRestart := false - - for _, item := range requestData { - - inboundMap, ok := item["inbound"].(map[string]interface{}) - if !ok { - jsonMsg(c, "Something went wrong!", errors.New("Failed to convert 'inbound' to map")) - return - } - - clientId, ok := item["clientId"].(string) - if !ok { - jsonMsg(c, "Something went wrong!", errors.New("Failed to convert 'clientId' to string")) - return - } - - inboundJSON, err := json.Marshal(inboundMap) - if err != nil { - jsonMsg(c, "Something went wrong!", err) - return - } - - var inboundModel model.Inbound - if err := json.Unmarshal(inboundJSON, &inboundModel); err != nil { - jsonMsg(c, "Something went wrong!", err) - return - } - - if restart, err := a.inboundService.UpdateInboundClient(&inboundModel, clientId); err != nil { - jsonMsg(c, "Something went wrong!", err) - return - } else { - needRestart = needRestart || restart - } - } - - jsonMsg(c, "Client updated", nil) - if needRestart { - a.xrayService.SetToNeedRestart() - } -} - func (a *InboundController) resetClientTraffic(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { diff --git a/web/html/common/qrcode_modal.html b/web/html/common/qrcode_modal.html index 31b3450c..3c4fd929 100644 --- a/web/html/common/qrcode_modal.html +++ b/web/html/common/qrcode_modal.html @@ -11,12 +11,10 @@ Subscription
- {{ i18n "pages.inbounds.client" }} - @@ -377,7 +373,7 @@

[[ clientEmail ]]

[[ clientCount[dbInbound.id].online.length ]] - + @@ -744,9 +740,6 @@ case "delDepletedClients": this.delDepletedClients(-1) break; - case "addGroupClient": - this.openGroupAddClient() - break; } }, clickAction(action, dbInbound) { @@ -890,20 +883,6 @@ await this.submit(`/panel/inbound/update/${dbInbound.id}`, data, inModal); }, - openGroupAddClient() { - clientModal.show({ - title: '{{ i18n "pages.client.groupAdd"}}', - okText: '{{ i18n "pages.client.submitAdd"}}', - dbInbounds: this.dbInbounds, - confirm: async (clients, dbInboundIds) => { - clientModal.loading(); - await this.addGroupClient(clients, dbInboundIds); - clientModal.close(); - await this.showQrcode(dbInboundIds[0],clients[0], true) - }, - isEdit: false - }); - }, openAddClient(dbInboundId) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); clientModal.show({ @@ -914,7 +893,6 @@ clientModal.loading(); await this.addClient(clients, dbInboundId); clientModal.close(); - await this.showQrcode(dbInboundId,clients) }, isEdit: false }); @@ -939,7 +917,6 @@ clientModal.show({ title: '{{ i18n "pages.client.edit"}}', okText: '{{ i18n "pages.client.submitEdit"}}', - dbInbounds: this.dbInbounds, dbInbound: dbInbound, index: index, confirm: async (client, dbInboundId, clientId) => { @@ -963,41 +940,14 @@ id: dbInboundId, settings: '{"clients": [' + clients.toString() + ']}', }; - - await this.submit(`/panel/inbound/addClient`, data) - }, - - async addGroupClient(clients, dbInboundIds) { - const data = [] - dbInboundIds.forEach((dbInboundId, index) => { - data.push({ - id: dbInboundId, - settings: '{"clients": [' + clients[index].toString() + ']}', - }) - }) - - await this.submit(`/panel/inbound/addGroupClient`, data, true) + await this.submit(`/panel/inbound/addClient`, data); }, async updateClient(client, dbInboundId, clientId) { - if (Array.isArray(client) && Array.isArray(dbInboundId) && Array.isArray(clientId)){ - const data = [] - client.forEach((client, index) => { - data.push({ - clientId: clientId[index], - inbound: { - id: dbInboundId[index], - settings: '{"clients": [' + client.toString() + ']}', - } - }) - }) - await this.submit(`/panel/inbound/updateClients`, data, true); - }else{ - const data = { - id: dbInboundId, - settings: '{"clients": [' + client.toString() + ']}', - }; - await this.submit(`/panel/inbound/updateClient/${clientId}`, data); - } + const data = { + id: dbInboundId, + settings: '{"clients": [' + client.toString() + ']}', + }; + await this.submit(`/panel/inbound/updateClient/${clientId}`, data); }, resetTraffic(dbInboundId) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); @@ -1051,8 +1001,8 @@ checkFallback(dbInbound) { newDbInbound = new DBInbound(dbInbound); if (dbInbound.listen.startsWith("@")){ - rootInbound = this.inbounds.find((i) => - i.isTcp && + rootInbound = this.inbounds.find((i) => + i.isTcp && ['trojan','vless'].includes(i.protocol) && i.settings.fallbacks.find(f => f.dest === dbInbound.listen) ); @@ -1068,10 +1018,10 @@ } return newDbInbound; }, - showQrcode(dbInboundId, client, isJustSub = false) { + showQrcode(dbInboundId, client) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); newDbInbound = this.checkFallback(dbInbound); - qrModal.show('{{ i18n "qrCode"}}', newDbInbound, client, isJustSub); + qrModal.show('{{ i18n "qrCode"}}', newDbInbound, client); }, showInfo(dbInboundId, client) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); @@ -1100,8 +1050,8 @@ await this.updateClient(clients[index], dbInboundId, clientId); this.loading(false); }, - async submit(url, data, isJson = false) { - const msg = isJson ? await HttpUtil.postWithModalJson(url, data) : await HttpUtil.postWithModal(url, data); + async submit(url, data) { + const msg = await HttpUtil.postWithModal(url, data); if (msg.success) { await this.getDBInbounds(); } @@ -1243,7 +1193,7 @@ value: '', okText: '{{ i18n "pages.inbounds.import" }}', confirm: async (dbInboundText) => { - await this.submit('/panel/inbound/import', {data: dbInboundText}); + await this.submit('/panel/inbound/import', {data: dbInboundText}, promptModal); promptModal.close(); }, }); diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index 0b7ac5b2..7e0f26c5 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -181,12 +181,9 @@ "exportInbound" = "Export Inbound" "import" = "Import" "importInbound" = "Import an Inbound" -"isGroupEdit" = "Group editing" -"isGroupEditDesc" = "All clients with the same subscription are edited" [pages.client] "add" = "Add Client" -"groupAdd" = "Add subscription user" "edit" = "Edit Client" "submitAdd" = "Add Client" "submitEdit" = "Save Changes" diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index 926325cf..6c817a30 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -181,12 +181,9 @@ "exportInbound" = "Exportación entrante" "import" = "Importar" "importInbound" = "Importar un entrante" -"isGroupEdit" = "Edición de grupo" -"isGroupEditDesc" = "Se editan todos los usuarios con la misma suscripción" [pages.client] "add" = "Agregar Cliente" -"groupAdd" = "Agregar usuario de suscripción" "edit" = "Editar Cliente" "submitAdd" = "Agregar Cliente" "submitEdit" = "Guardar Cambios" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index 17e6facc..11b66788 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -181,12 +181,9 @@ "exportInbound" = "استخراج ورودی" "import" = "افزودن" "importInbound" = "افزودن یک ورودی" -"isGroupEdit" = "ویرایش گروهی" -"isGroupEditDesc" = "تمامی کاربران با سابسکریپشن یکسان ویرایش می‌شوند" [pages.client] "add" = "کاربر جدید" -"groupAdd" = "کاربر جدید سابسکریپشن" "edit" = "ویرایش کاربر" "submitAdd" = "اضافه کردن" "submitEdit" = "ذخیره تغییرات" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index c567f38b..2e663e4c 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -181,12 +181,9 @@ "exportInbound" = "Экспорт входящих" "import" = "Импортировать" "importInbound" = "Импортировать входящее сообщение" -"isGroupEdit" = "Редактирование группы" -"isGroupEditDesc" = "Редактируются все пользователи с одной подпиской" [pages.client] "add" = "Добавить пользователя" -"groupAdd" = "Добавить пользователя подписки" "edit" = "Редактировать пользователя" "submitAdd" = "Добавить пользователя" "submitEdit" = "Сохранить изменения" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index 5876a5b4..4c40adca 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -181,12 +181,9 @@ "exportInbound" = "Xuất nhập khẩu" "import" = "Nhập" "importInbound" = "Nhập inbound" -"isGroupEdit" = "Chỉnh sửa nhóm" -"isGroupEditDesc" = "Tất cả người dùng có cùng đăng ký đều được chỉnh sửa" [pages.client] "add" = "Thêm người dùng" -"groupAdd" = "Thêm người dùng đăng ký" "edit" = "Chỉnh sửa người dùng" "submitAdd" = "Thêm" "submitEdit" = "Lưu thay đổi" diff --git a/web/translation/translate.zh_Hans.toml b/web/translation/translate.zh_Hans.toml index 29dc8f4c..a8cd3aff 100644 --- a/web/translation/translate.zh_Hans.toml +++ b/web/translation/translate.zh_Hans.toml @@ -181,12 +181,9 @@ "exportInbound" = "出口 入境" "import"="导入" "importInbound" = "导入入站" -"isGroupEdit" = "分组编辑" -"isGroupEditDesc" = "编辑具有相同订阅的所有用户" [pages.client] "add" = "添加客户端" -"groupAdd" = "添加订阅用户" "edit" = "编辑客户端" "submitAdd" = "添加客户端" "submitEdit" = "保存修改" From a6742f395aa65201d56b456f97e9db39c82910ce Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 27 Jan 2024 12:56:10 +0330 Subject: [PATCH 07/27] remove multi protocol script --- DockerInit.sh | 10 +--------- Dockerfile | 14 +++++++------ README.md | 17 ++++++++++++---- install.sh | 4 ++-- x-ui.sh | 54 +++++++++++---------------------------------------- 5 files changed, 35 insertions(+), 64 deletions(-) diff --git a/DockerInit.sh b/DockerInit.sh index bbfcb04e..a2224999 100755 --- a/DockerInit.sh +++ b/DockerInit.sh @@ -1,5 +1,4 @@ #!/bin/sh - case $1 in amd64) ARCH="64" @@ -21,28 +20,21 @@ case $1 in ARCH="arm32-v6" FNAME="armv6" ;; - armv5) - ARCH="arm32-v5" - FNAME="armv5" - ;; *) ARCH="64" FNAME="amd64" ;; esac - - mkdir -p build/bin cd build/bin - wget "https://github.com/XTLS/Xray-core/releases/download/v1.8.7/Xray-linux-${ARCH}.zip" unzip "Xray-linux-${ARCH}.zip" rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat mv xray "xray-linux-${FNAME}" - wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat wget -O geoip_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat wget -O geosite_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat wget -O geoip_VN.dat https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geoip.dat wget -O geosite_VN.dat https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geosite.dat +cd ../../ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 951d463b..7c3e64b2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,6 @@ FROM --platform=$BUILDPLATFORM golang:1.21-alpine AS builder WORKDIR /app ARG TARGETARCH -ENV CGO_ENABLED=1 -ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE" RUN apk --no-cache --update add \ build-base \ @@ -15,6 +13,8 @@ RUN apk --no-cache --update add \ COPY . . +ENV CGO_ENABLED=1 +ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE" RUN go build -o build/x-ui main.go RUN ./DockerInit.sh "$TARGETARCH" @@ -28,11 +28,12 @@ WORKDIR /app RUN apk add --no-cache --update \ ca-certificates \ tzdata \ - fail2ban + fail2ban \ + bash -COPY --from=builder /app/build/ /app/ -COPY --from=builder /app/DockerEntrypoint.sh /app/ -COPY --from=builder /app/x-ui.sh /usr/bin/x-ui +COPY --from=builder /app/build/ /app/ +COPY --from=builder /app/DockerEntrypoint.sh /app/ +COPY --from=builder /app/x-ui /usr/bin/x-ui # Configure fail2ban RUN rm -f /etc/fail2ban/jail.d/alpine-ssh.conf \ @@ -47,4 +48,5 @@ RUN chmod +x \ /usr/bin/x-ui VOLUME [ "/etc/x-ui" ] +CMD [ "./x-ui" ] ENTRYPOINT [ "/app/DockerEntrypoint.sh" ] diff --git a/README.md b/README.md index 389d6d1d..ec1e5a15 100644 --- a/README.md +++ b/README.md @@ -106,10 +106,19 @@ systemctl restart x-ui update to latest version ```sh - cd 3x-ui - docker compose down - docker compose pull 3x-ui - docker compose up -d + cd 3x-ui + docker compose down + docker compose pull 3x-ui + docker compose up -d + ``` + +remove 3x-ui from docker + + ```sh + docker stop 3x-ui + docker rm 3x-ui + cd -- + rm -r 3x-ui ``` diff --git a/install.sh b/install.sh index ae489c2a..9f46d4df 100644 --- a/install.sh +++ b/install.sh @@ -123,9 +123,9 @@ config_after_install() { echo -e "${green}username:${usernameTemp}${plain}" echo -e "${green}password:${passwordTemp}${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}" + echo -e "${red}if you forgot your login info,you can type x-ui and then type 8 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}" + 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 8 to check${plain}" fi fi /usr/local/x-ui/x-ui migrate diff --git a/x-ui.sh b/x-ui.sh index c7331e6d..ffb20f06 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -806,34 +806,6 @@ warp_cloudflare() { esac } -multi_protocol() { - echo "This script only supports Vless and Vmess. if you use another protocols, DON'T INSTALL or get backup first! " - echo -e "${green}\t1.${plain} Install Multi Protocol Script" - echo -e "${green}\t2.${plain} Uninstall" - echo -e "${green}\t3.${plain} Start Service" - echo -e "${green}\t4.${plain} Stop Service" - echo -e "${green}\t0.${plain} Back to Main Menu" - read -p "Choose an option: " choice - case "$choice" in - 0) - show_menu - ;; - 1) - bash <(curl -Ls https://raw.githubusercontent.com/M4mmad/3xui-multi-protocol/master/install.sh --ipv4) - ;; - 2) - bash <(curl -Ls https://raw.githubusercontent.com/M4mmad/3xui-multi-protocol/master/unistall.sh --ipv4) - ;; - 3) - systemctl start 3xui-multi-protocol - ;; - 4) - systemctl stop 3xui-multi-protocol - ;; - *) echo "Invalid choice" ;; - esac -} - run_speedtest() { # Check if Speedtest is already installed if ! command -v speedtest &>/dev/null; then @@ -1145,22 +1117,21 @@ show_menu() { ${green}12.${plain} Check Status ${green}13.${plain} Check Logs ———————————————— - ${green}14.${plain} Enable x-ui On System Startup - ${green}15.${plain} Disable x-ui On System Startup + ${green}14.${plain} Enable Autostart + ${green}15.${plain} Disable Autostart ———————————————— ${green}16.${plain} SSL Certificate Management ${green}17.${plain} Cloudflare SSL Certificate ${green}18.${plain} IP Limit Management ${green}19.${plain} WARP Management - ${green}20.${plain} Multi Protocol Management ———————————————— - ${green}21.${plain} Enable BBR - ${green}22.${plain} Update Geo Files - ${green}23.${plain} Active Firewall and open ports - ${green}24.${plain} Speedtest by Ookla + ${green}20.${plain} Enable BBR + ${green}21.${plain} Update Geo Files + ${green}22.${plain} Active Firewall and open ports + ${green}23.${plain} Speedtest by Ookla " show_status - echo && read -p "Please enter your selection [0-24]: " num + echo && read -p "Please enter your selection [0-23]: " num case "${num}" in 0) @@ -1224,22 +1195,19 @@ show_menu() { warp_cloudflare ;; 20) - multi_protocol - ;; - 21) enable_bbr ;; - 22) + 21) update_geo ;; - 23) + 22) open_ports ;; - 24) + 23) run_speedtest ;; *) - LOGE "Please enter the correct number [0-24]" + LOGE "Please enter the correct number [0-23]" ;; esac } From e04283c1fb3e56867c7922bab5f3d7edb29fe13c Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 27 Jan 2024 12:56:10 +0330 Subject: [PATCH 08/27] remove multi protocol script --- .github/workflows/docker.yml | 4 +-- DockerInit.sh | 10 +------ Dockerfile | 12 ++++---- README.md | 17 +++++++++--- install.sh | 4 +-- x-ui.sh | 54 ++++++++---------------------------- 6 files changed, 35 insertions(+), 66 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 1115de37..a7a8c790 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -18,7 +18,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.0.0 - - name: Log in to GitHub Container Registry + - name: Login to GHCR uses: docker/login-action@v3.0.0 with: registry: ghcr.io @@ -38,4 +38,4 @@ jobs: push: ${{ github.event_name != 'pull_request' }} platforms: linux/amd64, linux/arm64/v8, linux/arm/v7, linux/arm/v6, linux/386 tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/DockerInit.sh b/DockerInit.sh index bbfcb04e..a2224999 100755 --- a/DockerInit.sh +++ b/DockerInit.sh @@ -1,5 +1,4 @@ #!/bin/sh - case $1 in amd64) ARCH="64" @@ -21,28 +20,21 @@ case $1 in ARCH="arm32-v6" FNAME="armv6" ;; - armv5) - ARCH="arm32-v5" - FNAME="armv5" - ;; *) ARCH="64" FNAME="amd64" ;; esac - - mkdir -p build/bin cd build/bin - wget "https://github.com/XTLS/Xray-core/releases/download/v1.8.7/Xray-linux-${ARCH}.zip" unzip "Xray-linux-${ARCH}.zip" rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat mv xray "xray-linux-${FNAME}" - wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat wget -O geoip_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat wget -O geosite_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat wget -O geoip_VN.dat https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geoip.dat wget -O geosite_VN.dat https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geosite.dat +cd ../../ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 951d463b..7db1a175 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,9 @@ # ======================================================== # Stage: Builder # ======================================================== -FROM --platform=$BUILDPLATFORM golang:1.21-alpine AS builder +FROM golang:1.21-alpine AS builder WORKDIR /app ARG TARGETARCH -ENV CGO_ENABLED=1 -ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE" RUN apk --no-cache --update add \ build-base \ @@ -15,6 +13,8 @@ RUN apk --no-cache --update add \ COPY . . +ENV CGO_ENABLED=1 +ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE" RUN go build -o build/x-ui main.go RUN ./DockerInit.sh "$TARGETARCH" @@ -30,9 +30,9 @@ RUN apk add --no-cache --update \ tzdata \ fail2ban -COPY --from=builder /app/build/ /app/ -COPY --from=builder /app/DockerEntrypoint.sh /app/ -COPY --from=builder /app/x-ui.sh /usr/bin/x-ui +COPY --from=builder /app/build/ /app/ +COPY --from=builder /app/DockerEntrypoint.sh /app/ +COPY --from=builder /app/x-ui.sh /usr/bin/x-ui # Configure fail2ban RUN rm -f /etc/fail2ban/jail.d/alpine-ssh.conf \ diff --git a/README.md b/README.md index 389d6d1d..ec1e5a15 100644 --- a/README.md +++ b/README.md @@ -106,10 +106,19 @@ systemctl restart x-ui update to latest version ```sh - cd 3x-ui - docker compose down - docker compose pull 3x-ui - docker compose up -d + cd 3x-ui + docker compose down + docker compose pull 3x-ui + docker compose up -d + ``` + +remove 3x-ui from docker + + ```sh + docker stop 3x-ui + docker rm 3x-ui + cd -- + rm -r 3x-ui ``` diff --git a/install.sh b/install.sh index ae489c2a..9f46d4df 100644 --- a/install.sh +++ b/install.sh @@ -123,9 +123,9 @@ config_after_install() { echo -e "${green}username:${usernameTemp}${plain}" echo -e "${green}password:${passwordTemp}${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}" + echo -e "${red}if you forgot your login info,you can type x-ui and then type 8 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}" + 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 8 to check${plain}" fi fi /usr/local/x-ui/x-ui migrate diff --git a/x-ui.sh b/x-ui.sh index c7331e6d..ffb20f06 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -806,34 +806,6 @@ warp_cloudflare() { esac } -multi_protocol() { - echo "This script only supports Vless and Vmess. if you use another protocols, DON'T INSTALL or get backup first! " - echo -e "${green}\t1.${plain} Install Multi Protocol Script" - echo -e "${green}\t2.${plain} Uninstall" - echo -e "${green}\t3.${plain} Start Service" - echo -e "${green}\t4.${plain} Stop Service" - echo -e "${green}\t0.${plain} Back to Main Menu" - read -p "Choose an option: " choice - case "$choice" in - 0) - show_menu - ;; - 1) - bash <(curl -Ls https://raw.githubusercontent.com/M4mmad/3xui-multi-protocol/master/install.sh --ipv4) - ;; - 2) - bash <(curl -Ls https://raw.githubusercontent.com/M4mmad/3xui-multi-protocol/master/unistall.sh --ipv4) - ;; - 3) - systemctl start 3xui-multi-protocol - ;; - 4) - systemctl stop 3xui-multi-protocol - ;; - *) echo "Invalid choice" ;; - esac -} - run_speedtest() { # Check if Speedtest is already installed if ! command -v speedtest &>/dev/null; then @@ -1145,22 +1117,21 @@ show_menu() { ${green}12.${plain} Check Status ${green}13.${plain} Check Logs ———————————————— - ${green}14.${plain} Enable x-ui On System Startup - ${green}15.${plain} Disable x-ui On System Startup + ${green}14.${plain} Enable Autostart + ${green}15.${plain} Disable Autostart ———————————————— ${green}16.${plain} SSL Certificate Management ${green}17.${plain} Cloudflare SSL Certificate ${green}18.${plain} IP Limit Management ${green}19.${plain} WARP Management - ${green}20.${plain} Multi Protocol Management ———————————————— - ${green}21.${plain} Enable BBR - ${green}22.${plain} Update Geo Files - ${green}23.${plain} Active Firewall and open ports - ${green}24.${plain} Speedtest by Ookla + ${green}20.${plain} Enable BBR + ${green}21.${plain} Update Geo Files + ${green}22.${plain} Active Firewall and open ports + ${green}23.${plain} Speedtest by Ookla " show_status - echo && read -p "Please enter your selection [0-24]: " num + echo && read -p "Please enter your selection [0-23]: " num case "${num}" in 0) @@ -1224,22 +1195,19 @@ show_menu() { warp_cloudflare ;; 20) - multi_protocol - ;; - 21) enable_bbr ;; - 22) + 21) update_geo ;; - 23) + 22) open_ports ;; - 24) + 23) run_speedtest ;; *) - LOGE "Please enter the correct number [0-24]" + LOGE "Please enter the correct number [0-23]" ;; esac } From 78e1194ebb32652908aa5e74dabffba9bdb3307f Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Mon, 29 Jan 2024 23:36:03 +0330 Subject: [PATCH 09/27] bug fix - traffic limit tbbot --- web/service/tgbot.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/web/service/tgbot.go b/web/service/tgbot.go index fdb5d312..4ffa7bb4 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -6,9 +6,9 @@ import ( "net" "net/url" "os" + "slices" "strconv" "strings" - "slices" "time" "x-ui/config" "x-ui/database" @@ -260,7 +260,7 @@ func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin boo msg += t.I18nBot("tgbot.commands.unknown") } - if msg != ""{ + if msg != "" { if onlyMessage { t.SendMsgToTgbot(chatId, msg) return @@ -346,7 +346,7 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool tu.InlineKeyboardButton("40 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 40")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton("50 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 60")), + tu.InlineKeyboardButton("50 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 50")), tu.InlineKeyboardButton("60 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 60")), tu.InlineKeyboardButton("80 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 80")), ), @@ -1022,7 +1022,7 @@ func (t *Tgbot) getInboundUsages() string { } func (t *Tgbot) clientInfoMsg(traffic *xray.ClientTraffic, printEnabled bool, printOnline bool, printActive bool, - printDate bool, printTraffic bool, printRefreshed bool) string { + printDate bool, printTraffic bool, printRefreshed bool) string { now := time.Now().Unix() expiryTime := "" @@ -1380,7 +1380,6 @@ func (t *Tgbot) getExhausted(chatId int64) { output += t.I18nBot("tgbot.messages.exhaustedCount", "Type=="+t.I18nBot("tgbot.clients")) output += t.I18nBot("tgbot.messages.disabled", "Disabled=="+strconv.Itoa(len(disabledClients))) output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+strconv.Itoa(exhaustedCC)) - if exhaustedCC > 0 { output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+t.I18nBot("tgbot.clients")) @@ -1490,7 +1489,6 @@ func (t *Tgbot) onlineClients(chatId int64, messageID ...int) { output := t.I18nBot("tgbot.messages.onlinesCount", "Count=="+fmt.Sprint(onlinesCount)) keyboard := tu.InlineKeyboard(tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.refresh")).WithCallbackData(t.encodeQuery("onlines_refresh")))) - if onlinesCount > 0 { var buttons []telego.InlineKeyboardButton From 9f904f8f473bb3e167c5e37b0b2eff4fb5feeb92 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Mon, 29 Jan 2024 23:36:21 +0330 Subject: [PATCH 10/27] warp - ForceIP ForceIPv6v4 to ForceIP --- web/assets/js/model/outbound.js | 2 +- web/html/xui/warp_modal.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index 42fb50a1..7207561e 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -915,7 +915,7 @@ Outbound.HttpSettings = class extends CommonClass { Outbound.WireguardSettings = class extends CommonClass { constructor( mtu=1420, secretKey=Wireguard.generateKeypair().privateKey, - address=[''], workers=2, domainStrategy='ForceIPv6v4', reserved='', + address=[''], workers=2, domainStrategy='ForceIP', reserved='', peers=[new Outbound.WireguardSettings.Peer()], kernelMode=false) { super(); this.mtu = mtu; diff --git a/web/html/xui/warp_modal.html b/web/html/xui/warp_modal.html index 4e6dd4fa..38310a69 100644 --- a/web/html/xui/warp_modal.html +++ b/web/html/xui/warp_modal.html @@ -140,7 +140,7 @@ mtu: 1420, secretKey: warpModal.warpData.private_key, address: Object.values(config.interface.addresses), - domainStrategy: 'ForceIPv6v4', + domainStrategy: 'ForceIP', peers: [{ publicKey: peer.public_key, endpoint: peer.endpoint.host, From fd75cca266ce5fde64cb7500bb27ba387fcc1a9c Mon Sep 17 00:00:00 2001 From: Saeid <43953720+surbiks@users.noreply.github.com> Date: Tue, 30 Jan 2024 00:02:58 +0330 Subject: [PATCH 11/27] fix bug in edit SOCKS and HTTP outbound (#1704) --- web/assets/js/model/outbound.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index 7207561e..7724cf89 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -861,13 +861,13 @@ Outbound.SocksSettings = class extends CommonClass { } static fromJson(json={}) { - servers = json.servers; + let servers = json.servers; if(ObjectUtil.isArrEmpty(servers)) servers=[{users: [{}]}]; return new Outbound.SocksSettings( servers[0].address, servers[0].port, ObjectUtil.isArrEmpty(servers[0].users) ? '' : servers[0].users[0].user, - ObjectUtil.isArrEmpty(servers[0].pass) ? '' : servers[0].users[0].pass, + ObjectUtil.isArrEmpty(servers[0].users) ? '' : servers[0].users[0].pass, ); } @@ -891,13 +891,13 @@ Outbound.HttpSettings = class extends CommonClass { } static fromJson(json={}) { - servers = json.servers; + let servers = json.servers; if(ObjectUtil.isArrEmpty(servers)) servers=[{users: [{}]}]; return new Outbound.HttpSettings( servers[0].address, servers[0].port, ObjectUtil.isArrEmpty(servers[0].users) ? '' : servers[0].users[0].user, - ObjectUtil.isArrEmpty(servers[0].pass) ? '' : servers[0].users[0].pass, + ObjectUtil.isArrEmpty(servers[0].users) ? '' : servers[0].users[0].pass, ); } From 9fbaede59f87dd9d8b77479a3fb295c3c882630e Mon Sep 17 00:00:00 2001 From: emirjorge <117597846+emirjorge@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:33:51 -0500 Subject: [PATCH 12/27] Fix Spanish Translation in Main tittle (#1699) * Add files via upload * Update translate.es_ES.toml --- web/translation/translate.es_ES.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index 6c817a30..ac9de9a4 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -57,7 +57,7 @@ "dashboard" = "Estado del Sistema" "inbounds" = "Entradas" "settings" = "Configuraciones" -"xray" = "Configuración Xray" +"xray" = "Ajustes Xray" "logout" = "Cerrar Sesión" "link" = "Gestionar" From 6c0775b12055e4546cb0fd86e1d8d569d886eefa Mon Sep 17 00:00:00 2001 From: Saeid <43953720+surbiks@users.noreply.github.com> Date: Tue, 30 Jan 2024 00:07:20 +0330 Subject: [PATCH 13/27] Show outbound traffic in outbounds table (#1711) * store outbound traffic in database * show outbound traffic in outbounds table * add refresh button --- database/db.go | 5 +++ database/model/model.go | 9 ++++ web/controller/xray_setting.go | 11 +++++ web/html/xui/xray.html | 48 +++++++++++++++++++- web/job/xray_traffic_job.go | 15 ++++--- web/service/inbound.go | 4 +- web/service/outbound.go | 80 ++++++++++++++++++++++++++++++++++ xray/api.go | 6 ++- xray/traffic.go | 9 ++-- 9 files changed, 172 insertions(+), 15 deletions(-) create mode 100644 web/service/outbound.go diff --git a/database/db.go b/database/db.go index 8bd0fb49..c75953f0 100644 --- a/database/db.go +++ b/database/db.go @@ -21,6 +21,7 @@ var db *gorm.DB var initializers = []func() error{ initUser, initInbound, + initOutbound, initSetting, initInboundClientIps, initClientTraffic, @@ -51,6 +52,10 @@ func initInbound() error { return db.AutoMigrate(&model.Inbound{}) } +func initOutbound() error { + return db.AutoMigrate(&model.OutboundTraffics{}) +} + func initSetting() error { return db.AutoMigrate(&model.Setting{}) } diff --git a/database/model/model.go b/database/model/model.go index e2d54436..32ab255f 100644 --- a/database/model/model.go +++ b/database/model/model.go @@ -44,6 +44,15 @@ type Inbound struct { Tag string `json:"tag" form:"tag" gorm:"unique"` Sniffing string `json:"sniffing" form:"sniffing"` } + +type OutboundTraffics struct { + Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"` + Tag string `json:"tag" form:"tag" gorm:"unique"` + Up int64 `json:"up" form:"up" gorm:"default:0"` + Down int64 `json:"down" form:"down" gorm:"default:0"` + Total int64 `json:"total" form:"total" gorm:"default:0"` +} + type InboundClientIps struct { Id int `json:"id" gorm:"primaryKey;autoIncrement"` ClientEmail string `json:"clientEmail" form:"clientEmail" gorm:"unique"` diff --git a/web/controller/xray_setting.go b/web/controller/xray_setting.go index 09e9115f..430cc77b 100644 --- a/web/controller/xray_setting.go +++ b/web/controller/xray_setting.go @@ -10,6 +10,7 @@ type XraySettingController struct { XraySettingService service.XraySettingService SettingService service.SettingService InboundService service.InboundService + OutboundService service.OutboundService XrayService service.XrayService } @@ -27,6 +28,7 @@ func (a *XraySettingController) initRouter(g *gin.RouterGroup) { g.GET("/getXrayResult", a.getXrayResult) g.GET("/getDefaultJsonConfig", a.getDefaultXrayConfig) g.POST("/warp/:action", a.warp) + g.GET("/getOutboundsTraffic", a.getOutboundsTraffic) } func (a *XraySettingController) getXraySetting(c *gin.Context) { @@ -84,3 +86,12 @@ func (a *XraySettingController) warp(c *gin.Context) { jsonObj(c, resp, err) } + +func (a *XraySettingController) getOutboundsTraffic(c *gin.Context) { + outboundsTraffic, err := a.OutboundService.GetOutboundsTraffic() + if err != nil { + jsonMsg(c, "Error getting traffics", err) + return + } + jsonObj(c, outboundsTraffic, nil) +} diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html index d6f0c0f8..d00b73cc 100644 --- a/web/html/xui/xray.html +++ b/web/html/xui/xray.html @@ -341,8 +341,15 @@ - {{ i18n "pages.xray.outbound.addOutbound" }} - WARP + + + {{ i18n "pages.xray.outbound.addOutbound" }} + WARP + + + + + reality + @@ -463,6 +473,7 @@ { title: '{{ i18n "pages.xray.outbound.tag"}}', dataIndex: 'tag', align: 'center', width: 50 }, { title: '{{ i18n "protocol"}}', align: 'center', width: 50, scopedSlots: { customRender: 'protocol' } }, { title: '{{ i18n "pages.xray.outbound.address"}}', align: 'center', width: 50, scopedSlots: { customRender: 'address' } }, + { title: '{{ i18n "pages.inbounds.traffic" }}', align: 'center', width: 50, scopedSlots: { customRender: 'traffic' } }, ]; const reverseColumns = [ @@ -483,7 +494,9 @@ oldXraySetting: '', xraySetting: '', inboundTags: [], + outboundsTraffic: [], saveBtnDisable: true, + refreshing: false, restartResult: '', isMobile: window.innerWidth <= 768, advSettings: 'xraySetting', @@ -581,6 +594,12 @@ loading(spinning = true) { this.spinning = spinning; }, + async getOutboundsTraffic() { + const msg = await HttpUtil.get("/panel/xray/getOutboundsTraffic"); + if (msg.success) { + this.outboundsTraffic = msg.obj; + } + }, async getXraySetting() { this.loading(true); const msg = await HttpUtil.post("/panel/xray/"); @@ -759,6 +778,14 @@ } return true; }, + findOutboundTraffic(o) { + for (const otraffic of this.outboundsTraffic) { + if (otraffic.tag == o.tag) { + return sizeFormat(otraffic.up) + ' / ' + sizeFormat(otraffic.down); + } + } + return sizeFormat(0) + ' / ' + sizeFormat(0); + }, findOutboundAddress(o) { serverObj = null; switch(o.protocol){ @@ -816,6 +843,22 @@ outbounds.splice(index,1); this.outboundSettings = JSON.stringify(outbounds); }, + async refreshOutboundTraffic() { + if (!this.refreshing) { + this.refreshing = true; + await this.getOutboundsTraffic(); + + data = [] + if (this.templateSettings != null) { + this.templateSettings.outbounds.forEach((o, index) => { + data.push({'key': index, ...o}); + }); + } + + this.outboundData = data; + this.refreshing = false; + } + }, addReverse(){ reverseModal.show({ title: '{{ i18n "pages.xray.outbound.addReverse"}}', @@ -949,6 +992,7 @@ async mounted() { await this.getXraySetting(); await this.getXrayResult(); + await this.getOutboundsTraffic(); while (true) { await PromiseUtil.sleep(800); this.saveBtnDisable = this.oldXraySetting === this.xraySetting; diff --git a/web/job/xray_traffic_job.go b/web/job/xray_traffic_job.go index 158930a4..c0de4428 100644 --- a/web/job/xray_traffic_job.go +++ b/web/job/xray_traffic_job.go @@ -6,8 +6,9 @@ import ( ) type XrayTrafficJob struct { - xrayService service.XrayService - inboundService service.InboundService + xrayService service.XrayService + inboundService service.InboundService + outboundService service.OutboundService } func NewXrayTrafficJob() *XrayTrafficJob { @@ -24,11 +25,15 @@ func (j *XrayTrafficJob) Run() { logger.Warning("get xray traffic failed:", err) return } - err, needRestart := j.inboundService.AddTraffic(traffics, clientTraffics) + err, needRestart0 := j.inboundService.AddTraffic(traffics, clientTraffics) if err != nil { - logger.Warning("add traffic failed:", err) + logger.Warning("add inbound traffic failed:", err) } - if needRestart { + err, needRestart1 := j.outboundService.AddTraffic(traffics, clientTraffics) + if err != nil { + logger.Warning("add outbound traffic failed:", err) + } + if needRestart0 || needRestart1 { j.xrayService.SetToNeedRestart() } diff --git a/web/service/inbound.go b/web/service/inbound.go index f3445101..291c0dee 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -682,7 +682,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin return needRestart, tx.Save(oldInbound).Error } -func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraffics []*xray.ClientTraffic) (error, bool) { +func (s *InboundService) AddTraffic(traffics []*xray.Traffic, clientTraffics []*xray.ClientTraffic) (error, bool) { var err error db := database.GetDB() tx := db.Begin() @@ -694,7 +694,7 @@ func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraff tx.Commit() } }() - err = s.addInboundTraffic(tx, inboundTraffics) + err = s.addInboundTraffic(tx, traffics) if err != nil { return err, false } diff --git a/web/service/outbound.go b/web/service/outbound.go new file mode 100644 index 00000000..dc0e0742 --- /dev/null +++ b/web/service/outbound.go @@ -0,0 +1,80 @@ +package service + +import ( + "x-ui/database" + "x-ui/database/model" + "x-ui/logger" + "x-ui/xray" + + "gorm.io/gorm" +) + +type OutboundService struct { + xrayApi xray.XrayAPI +} + +func (s *OutboundService) AddTraffic(traffics []*xray.Traffic, clientTraffics []*xray.ClientTraffic) (error, bool) { + var err error + db := database.GetDB() + tx := db.Begin() + + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + + err = s.addOutboundTraffic(tx, traffics) + if err != nil { + return err, false + } + + return nil, false +} + +func (s *OutboundService) addOutboundTraffic(tx *gorm.DB, traffics []*xray.Traffic) error { + if len(traffics) == 0 { + return nil + } + + var err error + + for _, traffic := range traffics { + if traffic.IsOutbound { + + var outbound model.OutboundTraffics + + err = tx.Model(&model.OutboundTraffics{}).Where("tag = ?", traffic.Tag). + FirstOrCreate(&outbound).Error + if err != nil { + return err + } + + outbound.Tag = traffic.Tag + outbound.Up = outbound.Up + traffic.Up + outbound.Down = outbound.Down + traffic.Down + outbound.Total = outbound.Up + outbound.Down + + err = tx.Save(&outbound).Error + if err != nil { + return err + } + } + } + return nil +} + +func (s *OutboundService) GetOutboundsTraffic() ([]*model.OutboundTraffics, error) { + db := database.GetDB() + var traffics []*model.OutboundTraffics + + err := db.Model(model.OutboundTraffics{}).Find(&traffics).Error + if err != nil { + logger.Warning(err) + return nil, err + } + + return traffics, nil +} diff --git a/xray/api.go b/xray/api.go index 36b19875..1ce5afa1 100644 --- a/xray/api.go +++ b/xray/api.go @@ -213,6 +213,7 @@ func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) { continue } isInbound := matchs[1] == "inbound" + isOutbound := matchs[1] == "outbound" tag := matchs[2] isDown := matchs[3] == "downlink" if tag == "api" { @@ -221,8 +222,9 @@ func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) { traffic, ok := tagTrafficMap[tag] if !ok { traffic = &Traffic{ - IsInbound: isInbound, - Tag: tag, + IsInbound: isInbound, + IsOutbound: isOutbound, + Tag: tag, } tagTrafficMap[tag] = traffic traffics = append(traffics, traffic) diff --git a/xray/traffic.go b/xray/traffic.go index a1ef5186..7b907bae 100644 --- a/xray/traffic.go +++ b/xray/traffic.go @@ -1,8 +1,9 @@ package xray type Traffic struct { - IsInbound bool - Tag string - Up int64 - Down int64 + IsInbound bool + IsOutbound bool + Tag string + Up int64 + Down int64 } From e4567a2b247106bd375487889fe64cd5e660aa36 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Tue, 30 Jan 2024 00:15:20 +0330 Subject: [PATCH 14/27] host name for ws header req --- README.md | 56 ++++++++++++------------- web/assets/js/model/outbound.js | 6 +-- web/html/xui/form/stream/stream_ws.html | 2 +- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index ec1e5a15..b554353d 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,34 @@ To install your desired version, add the version to the end of the installation ``` bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.1.2 ``` + +## SSL Certificate + +
+ Click for SSL Certificate + +### Cloudflare + +The Management script has a built-in SSL certificate application for Cloudflare. To use this script to apply for a certificate, you need the following: + +- Cloudflare registered email +- Cloudflare Global API Key +- The domain name has been resolved to the current server through cloudflare + +**1:** Run the`x-ui`command on the terminal, then choose `Cloudflare SSL Certificate`. + + +### Certbot +``` +apt-get install certbot -y +certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com +certbot renew --dry-run +``` + +***Tip:*** *Certbot is also built into the Management script. You can run the `x-ui` command, then choose `SSL Certificate Management`.* + +
+ ## Manual Install & Upgrade
@@ -201,34 +229,6 @@ Supports a variety of different architectures and devices. Here are some of the
- -## SSL Certificate - -
- Click for SSL Certificate - -### Cloudflare - -The Management script has a built-in SSL certificate application for Cloudflare. To use this script to apply for a certificate, you need the following: - -- Cloudflare registered email -- Cloudflare Global API Key -- The domain name has been resolved to the current server through cloudflare - -**1:** Run the`x-ui`command on the terminal, then choose `Cloudflare SSL Certificate`. - - -### Certbot -``` -apt-get install certbot -y -certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com -certbot renew --dry-run -``` - -***Tip:*** *Certbot is also built into the Management script. You can run the `x-ui` command, then choose `SSL Certificate Management`.* - -
- ## [WARP Configuration](https://gitlab.com/fscarmen/warp)
diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index 7724cf89..dc02d91b 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -914,8 +914,8 @@ Outbound.HttpSettings = class extends CommonClass { Outbound.WireguardSettings = class extends CommonClass { constructor( - mtu=1420, secretKey=Wireguard.generateKeypair().privateKey, - address=[''], workers=2, domainStrategy='ForceIP', reserved='', + mtu=1420, secretKey='', + address=[''], workers=2, domainStrategy='', reserved='', peers=[new Outbound.WireguardSettings.Peer()], kernelMode=false) { super(); this.mtu = mtu; @@ -965,7 +965,7 @@ Outbound.WireguardSettings = class extends CommonClass { }; Outbound.WireguardSettings.Peer = class extends CommonClass { - constructor(publicKey=Wireguard.generateKeypair().publicKey, psk='', allowedIPs=['0.0.0.0/0','::/0'], endpoint='', keepAlive=0) { + constructor(publicKey='', psk='', allowedIPs=['0.0.0.0/0','::/0'], endpoint='', keepAlive=0) { super(); this.publicKey = publicKey; this.psk = psk; diff --git a/web/html/xui/form/stream/stream_ws.html b/web/html/xui/form/stream/stream_ws.html index 1222124c..00b64167 100644 --- a/web/html/xui/form/stream/stream_ws.html +++ b/web/html/xui/form/stream/stream_ws.html @@ -7,7 +7,7 @@ - + + + From 012775833a2d4e88ce534790e6ade9dd81def298 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Jan 2024 22:56:57 +0330 Subject: [PATCH 15/27] Bump github.com/nicksnyder/go-i18n/v2 from 2.3.0 to 2.4.0 (#1721) Bumps [github.com/nicksnyder/go-i18n/v2](https://github.com/nicksnyder/go-i18n) from 2.3.0 to 2.4.0. - [Release notes](https://github.com/nicksnyder/go-i18n/releases) - [Changelog](https://github.com/nicksnyder/go-i18n/blob/main/CHANGELOG.md) - [Commits](https://github.com/nicksnyder/go-i18n/compare/v2.3.0...v2.4.0) --- updated-dependencies: - dependency-name: github.com/nicksnyder/go-i18n/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d46ed1fe..41105d28 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/gin-gonic/gin v1.9.1 github.com/goccy/go-json v0.10.2 github.com/mymmrac/telego v0.28.0 - github.com/nicksnyder/go-i18n/v2 v2.3.0 + github.com/nicksnyder/go-i18n/v2 v2.4.0 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pelletier/go-toml/v2 v2.1.1 github.com/robfig/cron/v3 v3.0.1 diff --git a/go.sum b/go.sum index 8b6465d7..aa726d4a 100644 --- a/go.sum +++ b/go.sum @@ -179,8 +179,8 @@ github.com/mymmrac/telego v0.28.0 h1:DNXaYISeZw1J9oB81vCNdskLow8gCRRUJxufqLuH3XE github.com/mymmrac/telego v0.28.0/go.mod h1:oRperySNzJq8dRTl24+uBF1Uy7tlQGIjid/JQtHDsZg= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/nicksnyder/go-i18n/v2 v2.3.0 h1:2NPsCsNFCVd7i+Su0xYsBrIhS3bE2XMv5gNTft2O+PQ= -github.com/nicksnyder/go-i18n/v2 v2.3.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4= +github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM= +github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4= github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs= github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= From 68a16ef0e2385b57425c7959c425a8c02bef4a11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:15:17 +0330 Subject: [PATCH 16/27] Bump docker/metadata-action from 5.5.0 to 5.5.1 (#1726) Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.5.0 to 5.5.1. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/v5.5.0...v5.5.1) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a7a8c790..00ac9169 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -27,7 +27,7 @@ jobs: - name: Docker meta id: meta - uses: docker/metadata-action@v5.5.0 + uses: docker/metadata-action@v5.5.1 with: images: ghcr.io/${{ github.repository }} From f0e9aa0b8f1b81aef76246fb7ea449dc9236deba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:15:41 +0330 Subject: [PATCH 17/27] Bump github.com/shirou/gopsutil/v3 from 3.23.12 to 3.24.1 (#1725) Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.12 to 3.24.1. - [Release notes](https://github.com/shirou/gopsutil/releases) - [Commits](https://github.com/shirou/gopsutil/compare/v3.23.12...v3.24.1) --- updated-dependencies: - dependency-name: github.com/shirou/gopsutil/v3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 41105d28..76d5f8eb 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pelletier/go-toml/v2 v2.1.1 github.com/robfig/cron/v3 v3.0.1 - github.com/shirou/gopsutil/v3 v3.23.12 + github.com/shirou/gopsutil/v3 v3.24.1 github.com/valyala/fasthttp v1.51.0 github.com/xtls/xray-core v1.8.7 go.uber.org/atomic v1.11.0 diff --git a/go.sum b/go.sum index aa726d4a..8e8b0db6 100644 --- a/go.sum +++ b/go.sum @@ -230,8 +230,8 @@ github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJ github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U= github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= -github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -369,7 +369,6 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= From 98dd6bb9493c989d2947dce3beda030a331805ec Mon Sep 17 00:00:00 2001 From: Mehdi Khodayari Date: Sat, 3 Feb 2024 14:11:57 +0330 Subject: [PATCH 18/27] This modification uses a Scanner to read the file line by line, which can be more memory-efficient for large files. (#1736) --- web/job/check_client_ip_job.go | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/web/job/check_client_ip_job.go b/web/job/check_client_ip_job.go index b393e68d..ecfd5abb 100644 --- a/web/job/check_client_ip_job.go +++ b/web/job/check_client_ip_job.go @@ -1,7 +1,9 @@ package job import ( + "bufio" "encoding/json" + "io" "log" "os" "os/exec" @@ -97,12 +99,16 @@ func (j *CheckClientIpJob) processLogFile() { return } - data, err := os.ReadFile(accessLogPath) - InboundClientIps := make(map[string][]string) + file, err := os.Open(accessLogPath) j.checkError(err) + defer file.Close() + + InboundClientIps := make(map[string][]string) + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() - lines := strings.Split(string(data), "\n") - for _, line := range lines { ipRegx, _ := regexp.Compile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`) emailRegx, _ := regexp.Compile(`email:.+`) @@ -131,6 +137,8 @@ func (j *CheckClientIpJob) processLogFile() { } } + j.checkError(scanner.Err()) + shouldCleanLog := false for clientEmail, ips := range InboundClientIps { @@ -141,7 +149,6 @@ func (j *CheckClientIpJob) processLogFile() { } else { shouldCleanLog = j.updateInboundClientIps(inboundClientIps, clientEmail, ips) } - } // added delay before cleaning logs to reduce chance of logging IP that already has been banned @@ -151,13 +158,17 @@ func (j *CheckClientIpJob) processLogFile() { // copy access log to persistent file logAccessP, err := os.OpenFile(xray.GetAccessPersistentLogPath(), os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644) j.checkError(err) - input, err := os.ReadFile(accessLogPath) - j.checkError(err) - if _, err := logAccessP.Write(input); err != nil { - j.checkError(err) - } defer logAccessP.Close() + // reopen the access log file for reading + file, err := os.Open(accessLogPath) + j.checkError(err) + defer file.Close() + + // copy access log content to persistent file + _, err = io.Copy(logAccessP, file) + j.checkError(err) + // clean access log if err := os.Truncate(xray.GetAccessLogPath(), 0); err != nil { j.checkError(err) From 6804facabc27a5dc72a8db22bbaaf2c245161323 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 3 Feb 2024 15:24:39 +0330 Subject: [PATCH 19/27] bug fix log_writer + notice log level Co-Authored-By: Alireza Ahmadi --- logger/logger.go | 10 ++++++++++ xray/log_writer.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/logger/logger.go b/logger/logger.go index a1386b05..ca047cbc 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -65,6 +65,16 @@ func Infof(format string, args ...interface{}) { addToBuffer("INFO", fmt.Sprintf(format, args...)) } +func Notice(args ...interface{}) { + logger.Notice(args...) + addToBuffer("NOTICE", fmt.Sprint(args...)) +} + +func Noticef(format string, args ...interface{}) { + logger.Noticef(format, args...) + addToBuffer("NOTICE", fmt.Sprintf(format, args...)) +} + func Warning(args ...interface{}) { logger.Warning(args...) addToBuffer("WARNING", fmt.Sprint(args...)) diff --git a/xray/log_writer.go b/xray/log_writer.go index 5fc6b3d1..53358ca2 100644 --- a/xray/log_writer.go +++ b/xray/log_writer.go @@ -31,7 +31,7 @@ func (lw *LogWriter) Write(m []byte) (n int, err error) { // Find level in [] startIndex := strings.Index(messageBody, "[") endIndex := strings.Index(messageBody, "]") - if startIndex != -1 && endIndex != -1 { + if startIndex != -1 && endIndex != -1 && startIndex < endIndex { level := strings.TrimSpace(messageBody[startIndex+1 : endIndex]) msgBody := "XRAY: " + strings.TrimSpace(messageBody[endIndex+1:]) From 618a5662837b0c70a88782ccb47e1cb634241bb3 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 3 Feb 2024 17:54:04 +0330 Subject: [PATCH 20/27] new - select option for loglevel & access log --- web/html/xui/xray.html | 58 ++++++++++++++++++++++++++ web/job/check_client_ip_job.go | 8 +++- web/service/config.json | 5 ++- web/translation/translate.en_US.toml | 8 +++- web/translation/translate.es_ES.toml | 4 ++ web/translation/translate.fa_IR.toml | 4 ++ web/translation/translate.ru_RU.toml | 4 ++ web/translation/translate.vi_VN.toml | 4 ++ web/translation/translate.zh_Hans.toml | 4 ++ 9 files changed, 94 insertions(+), 5 deletions(-) diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html index d00b73cc..267103cb 100644 --- a/web/html/xui/xray.html +++ b/web/html/xui/xray.html @@ -147,6 +147,40 @@ + + + + + + + + + + + + + + + + @@ -534,6 +568,8 @@ protocol: "freedom" }, routingDomainStrategies: ["AsIs", "IPIfNonMatch", "IPOnDemand"], + logLevel: ["none" , "debug" , "info" , "warning", "error"], + access: ["none" , "./access.log" ], settingsData: { protocols: { bittorrent: ["bittorrent"], @@ -1109,6 +1145,28 @@ this.templateSettings = newTemplateSettings; } }, + setLogLevel: { + get: function () { + if (!this.templateSettings || !this.templateSettings.log || !this.templateSettings.log.loglevel) return "warning"; + return this.templateSettings.log.loglevel; + }, + set: function (newValue) { + newTemplateSettings = this.templateSettings; + newTemplateSettings.log.loglevel = newValue; + this.templateSettings = newTemplateSettings; + } + }, + setAccessLog: { + get: function () { + if (!this.templateSettings || !this.templateSettings.log || !this.templateSettings.log.access) return "none"; + return this.templateSettings.log.access; + }, + set: function (newValue) { + newTemplateSettings = this.templateSettings; + newTemplateSettings.log.access = newValue; + this.templateSettings = newTemplateSettings; + } + }, blockedIPs: { get: function () { return this.templateRuleGetter({ outboundTag: "blocked", property: "ip" }); diff --git a/web/job/check_client_ip_job.go b/web/job/check_client_ip_job.go index ecfd5abb..77cbe256 100644 --- a/web/job/check_client_ip_job.go +++ b/web/job/check_client_ip_job.go @@ -94,8 +94,14 @@ func (j *CheckClientIpJob) checkFail2BanInstalled() { func (j *CheckClientIpJob) processLogFile() { accessLogPath := xray.GetAccessLogPath() + + if accessLogPath == "none" { + logger.Warning("Access log is set to 'none' check your Xray Configs") + return + } + if accessLogPath == "" { - logger.Warning("access.log doesn't exist in your config.json") + logger.Warning("Access log doesn't exist in your Xray Configs") return } diff --git a/web/service/config.json b/web/service/config.json index 82f7dddf..5c25ed92 100644 --- a/web/service/config.json +++ b/web/service/config.json @@ -1,7 +1,8 @@ { "log": { - "loglevel": "warning", - "error": "./error.log" + "access": "none", + "dnsLog": false, + "loglevel": "warning" }, "api": { "tag": "api", diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index 7e0f26c5..6295bf15 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -309,8 +309,8 @@ "restart" = "Restart Xray" "basicTemplate" = "Basics" "advancedTemplate" = "Advanced" -"generalConfigs" = "General Strategy" -"generalConfigsDesc" = "These options will determine general strategy adjustments." +"generalConfigs" = "General" +"generalConfigsDesc" = "These options will determine general adjustments." "blockConfigs" = "Protection Shield" "blockConfigsDesc" = "These options will block traffic based on specific requested protocols and websites." "blockCountryConfigs" = "Block Country" @@ -392,6 +392,10 @@ "Routings" = "Routing Rules" "RoutingsDesc" = "The priority of each rule is important!" "completeTemplate" = "All" +"logLevel" = "Log Level" +"logLevelDesc" = "The log level for error logs, indicating the information that needs to be recorded." +"accessLog" = "Access Log" +"accessLogDesc" = "The file path for the access log. The special value 'none' disabled access logs" [pages.xray.rules] "first" = "First" diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index ac9de9a4..b21fe252 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -392,6 +392,10 @@ "Routings" = "Reglas de enrutamiento" "RoutingsDesc" = "¡La prioridad de cada regla es importante!" "completeTemplate" = "Todos" +"logLevel" = "Nivel de registro" +"logLevelDesc" = "El nivel de registro para registros de errores, que indica la información que debe registrarse." +"accessLog" = "Registro de acceso" +"accessLogDesc" = "La ruta del archivo para el registro de acceso. El valor especial 'ninguno' deshabilita los registros de acceso" [pages.xray.rules] "first" = "Primero" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index 11b66788..e737c79b 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -392,6 +392,10 @@ "Routings" = "قوانین مسیریابی" "RoutingsDesc" = "اولویت هر قانون مهم است" "completeTemplate" = "کامل" +"logLevel" = "سطح گزارش" +"logLevelDesc" = "سطح گزارش برای گزارش های خطا، نشان دهنده اطلاعاتی است که باید ثبت شوند." +"accessLog" = "مسیر گزارش" +"accessLogDesc" = "مسیر فایل برای گزارش دسترسی. مقدار ویژه «هیچ» گزارش‌های دسترسی را غیرفعال میکند." [pages.xray.rules] "first" = "اولین" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index 2e663e4c..cbd1d4f9 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -392,6 +392,10 @@ "Routings" = "Правила маршрутизации" "RoutingsDesc" = "Важен приоритет каждого правила!" "completeTemplate" = "Все" +"logLevel" = "Уровень журнала" +"logLevelDesc" = "Уровень журнала для журналов ошибок, указывающий информацию, которую необходимо записать." +"accessLog" = "Журнал доступа" +"accessLogDesc" = "Путь к файлу журнала доступа. Специальное значение «none» отключило журналы доступа." [pages.xray.rules] "first" = "Первый" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index 4c40adca..f94b56b0 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -392,6 +392,10 @@ "Routings" = "Quy tắc định tuyến" "RoutingsDesc" = "Mức độ ưu tiên của mỗi quy tắc đều quan trọng!" "completeTemplate" = "All" +"logLevel" = "Mức đăng nhập" +"logLevelDesc" = "Cấp độ nhật ký cho nhật ký lỗi, cho biết thông tin cần được ghi lại." +"accessLog" = "Nhật ký truy cập" +"accessLogDesc" = "Đường dẫn tệp cho nhật ký truy cập. Nhật ký truy cập bị vô hiệu hóa có giá trị đặc biệt 'không'" [pages.xray.rules] "first" = "Đầu tiên" diff --git a/web/translation/translate.zh_Hans.toml b/web/translation/translate.zh_Hans.toml index a8cd3aff..d64e1331 100644 --- a/web/translation/translate.zh_Hans.toml +++ b/web/translation/translate.zh_Hans.toml @@ -392,6 +392,10 @@ "Routings" = "路由规则" "RoutingsDesc" = "每条规则的优先级都很重要" "completeTemplate" = "全部" +"logLevel" = "日志级别" +"logLevelDesc" = "错误日志的日志级别,表示需要记录的信息。" +"accessLog" = "访问日志" +"accessLogDesc" = "访问日志的文件路径。 特殊值“none”禁用访问日志" [pages.xray.rules] "first" = "第一个" From 9d724d34e1cf0c6cf118fb092d737d2f84d67a60 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 3 Feb 2024 18:15:47 +0330 Subject: [PATCH 21/27] fix tgbot - no warning for empty socks5 --- web/service/tgbot.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 4ffa7bb4..0b5a8158 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -115,14 +115,19 @@ func (t *Tgbot) Start(i18nFS embed.FS) error { } func (t *Tgbot) NewBot(token string, proxyUrl string) (*telego.Bot, error) { - if proxyUrl == "" || !strings.HasPrefix(proxyUrl, "socks5://") { - logger.Warning("invalid socks5 url, start with default") + if proxyUrl == "" { + // No proxy URL provided, use default instance + return telego.NewBot(token) + } + + if !strings.HasPrefix(proxyUrl, "socks5://") { + logger.Warning("Invalid socks5 URL, starting with default") return telego.NewBot(token) } _, err := url.Parse(proxyUrl) if err != nil { - logger.Warning("cant parse proxy url, use default instance for tgbot:", err) + logger.Warning("Can't parse proxy URL, using default instance for tgbot:", err) return telego.NewBot(token) } From 2a2bf531eef9ca0fdc0894e4e740ff0a613ea350 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 4 Feb 2024 01:50:14 +0330 Subject: [PATCH 22/27] Fix tgbot - document upload issue for empty ban logs --- web/service/tgbot.go | 46 +++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 0b5a8158..7bd6a179 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -1568,30 +1568,44 @@ func (t *Tgbot) sendBanLogs(chatId int64, dt bool) { file, err := os.Open(xray.GetIPLimitBannedPrevLogPath()) if err == nil { - document := tu.Document( - tu.ID(chatId), - tu.File(file), - ) - _, err = bot.SendDocument(document) - if err != nil { - logger.Error("Error in uploading backup: ", err) + // Check if the file is non-empty before attempting to upload + fileInfo, _ := file.Stat() + if fileInfo.Size() > 0 { + document := tu.Document( + tu.ID(chatId), + tu.File(file), + ) + _, err = bot.SendDocument(document) + if err != nil { + logger.Error("Error in uploading IPLimitBannedPrevLog: ", err) + } + } else { + logger.Warning("IPLimitBannedPrevLog file is empty, not uploading.") } + file.Close() } else { - logger.Error("Error in opening db file for backup: ", err) + logger.Error("Error in opening IPLimitBannedPrevLog file for backup: ", err) } file, err = os.Open(xray.GetIPLimitBannedLogPath()) if err == nil { - document := tu.Document( - tu.ID(chatId), - tu.File(file), - ) - _, err = bot.SendDocument(document) - if err != nil { - logger.Error("Error in uploading config.json: ", err) + // Check if the file is non-empty before attempting to upload + fileInfo, _ := file.Stat() + if fileInfo.Size() > 0 { + document := tu.Document( + tu.ID(chatId), + tu.File(file), + ) + _, err = bot.SendDocument(document) + if err != nil { + logger.Error("Error in uploading IPLimitBannedLog: ", err) + } + } else { + logger.Warning("IPLimitBannedLog file is empty, not uploading.") } + file.Close() } else { - logger.Error("Error in opening config.json file for backup: ", err) + logger.Error("Error in opening IPLimitBannedLog file for backup: ", err) } } From 12075014056d5288e845b11a46855d6cea1c578b Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 4 Feb 2024 01:51:01 +0330 Subject: [PATCH 23/27] tgbot - improve translate --- web/translation/translate.en_US.toml | 2 +- web/translation/translate.fa_IR.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index 6295bf15..78c545f6 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -456,7 +456,7 @@ "wentWrong" = "❌ Something went wrong!" "noIpRecord" = "❗ No IP Record!" "noInbounds" = "❗ No inbound found!" -"unlimited" = "♾ Unlimited" +"unlimited" = "♾ Unlimited(Reset)" "add" = "Add" "month" = "Month" "months" = "Months" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index e737c79b..7abaf973 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -456,7 +456,7 @@ "wentWrong" = "❌ مشکلی رخ داده است!" "noIpRecord" = "❗ رکورد IP یافت نشد!" "noInbounds" = "❗ هیچ ورودی یافت نشد!" -"unlimited" = "♾ نامحدود" +"unlimited" = "♾ - نامحدود(ریست)" "add" = "اضافه کردن" "month" = "ماه" "months" = "ماه‌ها" From d17185025576a81bae641a0488b876ac143826df Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 4 Feb 2024 01:51:31 +0330 Subject: [PATCH 24/27] IPLimit - IPv4 Extraction Simplification --- web/job/check_client_ip_job.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/web/job/check_client_ip_job.go b/web/job/check_client_ip_job.go index 77cbe256..905a8cc7 100644 --- a/web/job/check_client_ip_job.go +++ b/web/job/check_client_ip_job.go @@ -115,13 +115,13 @@ func (j *CheckClientIpJob) processLogFile() { for scanner.Scan() { line := scanner.Text() - ipRegx, _ := regexp.Compile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`) + ipRegx, _ := regexp.Compile(`(\d+\.\d+\.\d+\.\d+).* accepted`) emailRegx, _ := regexp.Compile(`email:.+`) - matchesIp := ipRegx.FindString(line) - if len(matchesIp) > 0 { - ip := string(matchesIp) - if ip == "127.0.0.1" || ip == "1.1.1.1" { + matches := ipRegx.FindStringSubmatch(line) + if len(matches) > 1 { + ip := matches[1] + if ip == "127.0.0.1" || ip == "[::1]" { continue } @@ -136,7 +136,6 @@ func (j *CheckClientIpJob) processLogFile() { continue } InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail], ip) - } else { InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail], ip) } From bb7b66746763f694baea981549d311320136cb1b Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 4 Feb 2024 01:51:43 +0330 Subject: [PATCH 25/27] v2.1.3 --- README.md | 11 ++++++----- config/version | 2 +- web/service/xray.go | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b554353d..6809bc2a 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install. ## Install Custom Version -To install your desired version, add the version to the end of the installation command. e.g., ver `v2.1.2`: +To install your desired version, add the version to the end of the installation command. e.g., ver `v2.1.3`: ``` -bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.1.2 +bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.1.3 ``` ## SSL Certificate @@ -281,13 +281,14 @@ If you want to use routing to WARP before v2.1.0 follow steps as below: 2. Select `IP Limit Management`. 3. Choose the appropriate options based on your needs. - - make sure you have access.log on your Xray Configuration + - make sure you have ./access.log on your Xray Configuration after v2.1.3 we have an option for it ```sh "log": { - "loglevel": "warning", "access": "./access.log", - "error": "./error.log" + "dnsLog": false, + "error": "./error.log", + "loglevel": "warning" }, ``` diff --git a/config/version b/config/version index 8f9174b4..abae0d9a 100644 --- a/config/version +++ b/config/version @@ -1 +1 @@ -2.1.2 \ No newline at end of file +2.1.3 \ No newline at end of file diff --git a/web/service/xray.go b/web/service/xray.go index 82d1cc3f..7cd1612c 100644 --- a/web/service/xray.go +++ b/web/service/xray.go @@ -95,7 +95,7 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) { if !clientTraffic.Enable { clients = RemoveIndex(clients, index-indexDecrease) indexDecrease++ - logger.Info("Remove Inbound User", c["email"], "due the expire or traffic limit") + logger.Info("Remove Inbound User ", c["email"], " due the expire or traffic limit") } From dc49304aa5d959767f771b8b161e23b5d8cd6ec4 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 4 Feb 2024 02:01:55 +0330 Subject: [PATCH 26/27] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 6809bc2a..a1c902e2 100644 --- a/README.md +++ b/README.md @@ -287,7 +287,6 @@ If you want to use routing to WARP before v2.1.0 follow steps as below: "log": { "access": "./access.log", "dnsLog": false, - "error": "./error.log", "loglevel": "warning" }, ``` From c9ba393ce7bd7050b4d2dc8d4e3c019641a5f087 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 4 Feb 2024 13:02:28 +0330 Subject: [PATCH 27/27] xray config - statsOutbound --- web/service/config.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/service/config.json b/web/service/config.json index 5c25ed92..6cf6c3a6 100644 --- a/web/service/config.json +++ b/web/service/config.json @@ -44,7 +44,9 @@ }, "system": { "statsInboundDownlink": true, - "statsInboundUplink": true + "statsInboundUplink": true, + "statsOutboundDownlink": true, + "statsOutboundUplink": true } }, "routing": {