From 9f6957ef3f5625db00d5dc22efd99bc8af06cba2 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 17 Feb 2024 21:37:58 +0330 Subject: [PATCH 01/61] [logs] new bug-free log_writer Co-Authored-By: Alireza Ahmadi --- web/assets/js/model/xray.js | 2 +- xray/log_writer.go | 19 ++++++------------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index e9676252..7018fb75 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -1557,7 +1557,7 @@ class Inbound extends XrayCommonClass { const orderChars = remarkModel.slice(1); let orders = { 'i': remark, - 'e': client ? client.email : '', + 'e': email, 'o': '', }; if(ObjectUtil.isArrEmpty(this.stream.externalProxy)){ diff --git a/xray/log_writer.go b/xray/log_writer.go index 53358ca2..2d208326 100644 --- a/xray/log_writer.go +++ b/xray/log_writer.go @@ -1,6 +1,7 @@ package xray import ( + "regexp" "strings" "x-ui/logger" ) @@ -14,26 +15,18 @@ type LogWriter struct { } func (lw *LogWriter) Write(m []byte) (n int, err error) { + regex := regexp.MustCompile(`^(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}) \[([^\]]+)\] (.+)$`) // Convert the data to a string message := strings.TrimSpace(string(m)) messages := strings.Split(message, "\n") lw.lastLine = messages[len(messages)-1] for _, msg := range messages { - messageBody := msg + matches := regex.FindStringSubmatch(msg) - // Remove timestamp - splittedMsg := strings.SplitN(msg, " ", 3) - if len(splittedMsg) > 2 { - messageBody = strings.TrimSpace(strings.SplitN(msg, " ", 3)[2]) - } - - // Find level in [] - startIndex := strings.Index(messageBody, "[") - endIndex := strings.Index(messageBody, "]") - if startIndex != -1 && endIndex != -1 && startIndex < endIndex { - level := strings.TrimSpace(messageBody[startIndex+1 : endIndex]) - msgBody := "XRAY: " + strings.TrimSpace(messageBody[endIndex+1:]) + if len(matches) > 3 { + level := matches[2] + msgBody := matches[3] // Map the level to the appropriate logger function switch level { From fb76b2d5001311ad66515861d4f2be57951c4c6e Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 17 Feb 2024 21:38:22 +0330 Subject: [PATCH 02/61] [feature] export subs Co-Authored-By: Alireza Ahmadi --- web/html/xui/inbounds.html | 61 +++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index c986e3fd..aab05462 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -133,6 +133,10 @@ {{ i18n "pages.inbounds.export" }} + + + {{ i18n "pages.inbounds.export" }} - {{ i18n "pages.settings.subSettings" }} + {{ i18n "pages.inbounds.resetAllTraffic" }} @@ -141,7 +145,7 @@ {{ i18n "pages.inbounds.resetAllClientTraffics" }} - + {{ i18n "pages.inbounds.delDepletedClients" }} @@ -217,7 +221,11 @@ {{ i18n "pages.inbounds.export"}} - + + + {{ i18n "pages.inbounds.export"}} - {{ i18n "pages.settings.subSettings" }} + + {{ i18n "pages.inbounds.delDepletedClients" }} @@ -578,6 +586,7 @@ this.refreshing = false; return; } + await this.getOnlineUsers(); this.setInbounds(msg.obj); setTimeout(() => { @@ -642,8 +651,12 @@ clientCount = clients.length; if (dbInbound.enable) { clients.forEach(client => { - client.enable ? active.push(client.email) : deactive.push(client.email); - if(this.isClientOnline(client.email)) online.push(client.email); + if (client.enable && this.isClientOnline(client.email)) { + active.push(client.email); + online.push(client.email); + } else { + deactive.push(client.email); + } }); clientStats.forEach(client => { if (!client.enable) { @@ -668,6 +681,7 @@ online: online, }; }, + searchInbounds(key) { if (ObjectUtil.isEmpty(key)) { this.searchedInbounds = this.dbInbounds.slice(); @@ -731,6 +745,9 @@ case "export": this.exportAllLinks(); break; + case "subs": + this.exportAllSubs(); + break; case "resetInbounds": this.resetAllTraffic(); break; @@ -762,6 +779,9 @@ case "export": this.inboundLinks(dbInbound.id); break; + case "subs": + this.exportSubs(dbInbound.id); + break; case "clipboard": this.copyToClipboard(dbInbound.id); break; @@ -1186,6 +1206,22 @@ newDbInbound = this.checkFallback(dbInbound); txtModal.show('{{ i18n "pages.inbounds.export"}}', newDbInbound.genInboundLinks(), newDbInbound.remark); }, + exportSubs(dbInboundId) { + const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); + const clients = this.getInboundClients(dbInbound); + let subLinks = [] + if (clients != null){ + clients.forEach(c => { + if (c.subId && c.subId.length>0){ + subLinks.push(this.subSettings.subURI + c.subId + "?name=" + c.subId) + } + }) + } + txtModal.show( + '{{ i18n "pages.inbounds.export"}} - {{ i18n "pages.settings.subSettings" }}', + [...new Set(subLinks)].join('\n'), + dbInbound.remark + "-Subs"); + }, importInbound() { promptModal.open({ title: '{{ i18n "pages.inbounds.importInbound" }}', @@ -1198,6 +1234,23 @@ }, }); }, + exportAllSubs() { + let subLinks = [] + for (const dbInbound of this.dbInbounds) { + const clients = this.getInboundClients(dbInbound); + if (clients != null){ + clients.forEach(c => { + if (c.subId && c.subId.length>0){ + subLinks.push(this.subSettings.subURI + c.subId + "?name=" + c.subId) + } + }) + } + } + txtModal.show( + '{{ i18n "pages.inbounds.export"}} - {{ i18n "pages.settings.subSettings" }}', + [...new Set(subLinks)].join('\r\n'), + 'All-Inbounds-Subs'); + }, exportAllLinks() { let copyText = []; for (const dbInbound of this.dbInbounds) { From 4621933e5bad743aafd2b15bd72ed99069df99ad Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 17 Feb 2024 21:40:25 +0330 Subject: [PATCH 03/61] [outbound] set master outbound Co-Authored-By: Alireza Ahmadi --- web/html/xui/xray.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html index 871631e0..10beaa43 100644 --- a/web/html/xui/xray.html +++ b/web/html/xui/xray.html @@ -406,6 +406,10 @@ + + + {{ i18n "pages.xray.rules.first"}} + {{ i18n "edit" }} @@ -938,6 +942,11 @@ outbounds.splice(index,1); this.outboundSettings = JSON.stringify(outbounds); }, + setFirstOutbound(index){ + outbounds = this.templateSettings.outbounds; + outbounds.splice(0, 0, outbounds.splice(index, 1)[0]); + this.outboundSettings = JSON.stringify(outbounds); + }, async refreshOutboundTraffic() { if (!this.refreshing) { this.refreshing = true; From 61489077d7d5740250702c68846abae6a3598c6f Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 18 Feb 2024 00:46:49 +0330 Subject: [PATCH 04/61] [wg] auto multi-peer and qrcode Co-Authored-By: Alireza Ahmadi --- web/assets/js/model/xray.js | 40 ++++++++++++++++++- web/html/common/qrcode_modal.html | 19 ++++++--- web/html/xui/form/outbound.html | 35 +++++------------ web/html/xui/form/protocol/wireguard.html | 12 ++++-- web/html/xui/inbound_info_modal.html | 48 +++++++++++++++++------ web/html/xui/inbounds.html | 2 +- 6 files changed, 108 insertions(+), 48 deletions(-) diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index 7018fb75..d7d1fa0d 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -1534,6 +1534,28 @@ class Inbound extends XrayCommonClass { return url.toString(); } + getWireguardLink(address, port, remark, peerId) { + let txt = `[Interface]\n` + txt += `PrivateKey = ${this.settings.peers[peerId].privateKey}\n` + txt += `Address = ${this.settings.peers[peerId].allowedIPs[0]}\n` + txt += `DNS = 1.1.1.1, 1.0.0.1\n` + if (this.settings.mtu) { + txt += `MTU = ${this.settings.mtu}\n` + } + txt += `\n# ${remark}\n` + txt += `[Peer]\n` + txt += `PublicKey = ${this.settings.pubKey}\n` + txt += `AllowedIPs = 0.0.0.0/0, ::/0\n` + txt += `Endpoint = ${address}:${port}` + if (this.settings.peers[peerId].psk) { + txt += `\nPresharedKey = ${this.settings.peers[peerId].psk}` + } + if (this.settings.peers[peerId].keepAlive) { + txt += `\nPersistentKeepalive = ${this.settings.peers[peerId].keepAlive}\n` + } + return txt; + } + genLink(address='', port=this.port, forceTls='same', remark='', client) { switch (this.protocol) { case Protocols.VMESS: @@ -1580,6 +1602,7 @@ class Inbound extends XrayCommonClass { } genInboundLinks(remark = '', remarkModel = '-ieo') { + let addr = !ObjectUtil.isEmpty(this.listen) && this.listen !== "0.0.0.0" ? this.listen : location.hostname; if(this.clients){ let links = []; this.clients.forEach((client) => { @@ -1589,7 +1612,14 @@ class Inbound extends XrayCommonClass { }); return links.join('\r\n'); } else { - if(this.protocol == Protocols.SHADOWSOCKS && !this.isSSMultiUser) return this.genSSLink(this.listen, this.port, 'same', remark); + if(this.protocol == Protocols.SHADOWSOCKS && !this.isSSMultiUser) return this.genSSLink(addr, this.port, 'same', remark); + if(this.protocol == Protocols.WIREGUARD) { + let links = []; + this.settings.peers.forEach((p,index) => { + links.push(this.getWireguardLink(addr,this.port,remark + remarkModel.charAt(0) + (index+1),index)); + }); + return links.join('\r\n'); + } return ''; } } @@ -2297,9 +2327,13 @@ Inbound.WireguardSettings = class extends XrayCommonClass { }; Inbound.WireguardSettings.Peer = class extends XrayCommonClass { - constructor(publicKey=Wireguard.generateKeypair().publicKey, psk='', allowedIPs=['0.0.0.0/0','::/0'], keepAlive=0) { + constructor(privateKey, publicKey, psk='', allowedIPs=['10.0.0.0/24'], keepAlive=0) { super(); + this.privateKey = privateKey this.publicKey = publicKey; + if (!this.publicKey){ + [this.publicKey, this.privateKey] = Object.values(Wireguard.generateKeypair()) + } this.psk = psk; this.allowedIPs = allowedIPs; this.keepAlive = keepAlive; @@ -2307,6 +2341,7 @@ Inbound.WireguardSettings.Peer = class extends XrayCommonClass { static fromJson(json={}){ return new Inbound.WireguardSettings.Peer( + json.privateKey, json.publicKey, json.preSharedKey, json.allowedIPs, @@ -2316,6 +2351,7 @@ Inbound.WireguardSettings.Peer = class extends XrayCommonClass { toJson() { return { + privateKey: this.privateKey, publicKey: this.publicKey, preSharedKey: this.psk.length>0 ? this.psk : undefined, allowedIPs: this.allowedIPs, diff --git a/web/html/common/qrcode_modal.html b/web/html/common/qrcode_modal.html index 3c4fd929..3bda4c29 100644 --- a/web/html/common/qrcode_modal.html +++ b/web/html/common/qrcode_modal.html @@ -35,12 +35,21 @@ this.client = client; this.subId = ''; this.qrcodes = []; - this.inbound.genAllLinks(this.dbInbound.remark, app.remarkModel, client).forEach(l => { - this.qrcodes.push({ - remark: l.remark, - link: l.link + if (this.inbound.protocol == Protocols.WIREGUARD){ + this.inbound.genInboundLinks(dbInbound.remark).split('\r\n').forEach((l,index) =>{ + this.qrcodes.push({ + remark: "Peer " + (index+1), + link: l + }); }); - }); + } else { + this.inbound.genAllLinks(this.dbInbound.remark, app.remarkModel, client).forEach(l => { + this.qrcodes.push({ + remark: l.remark, + link: l.link + }); + }); + } this.visible = true; }, close: function () { diff --git a/web/html/xui/form/outbound.html b/web/html/xui/form/outbound.html index fb6a7af7..469c42b9 100644 --- a/web/html/xui/form/outbound.html +++ b/web/html/xui/form/outbound.html @@ -134,28 +134,10 @@ - - + - - + @@ -189,7 +171,6 @@ - - - {{ i18n "pages.xray.wireguard.psk" }} - + diff --git a/web/html/xui/inbound_info_modal.html b/web/html/xui/inbound_info_modal.html index cdcabad9..23f8bd47 100644 --- a/web/html/xui/inbound_info_modal.html +++ b/web/html/xui/inbound_info_modal.html @@ -179,10 +179,10 @@ @@ -319,7 +345,6 @@ index: null, isExpired: false, subLink: '', - tgLink: '', show(dbInbound, index) { this.index = index; this.inbound = dbInbound.toInbound(); @@ -327,14 +352,15 @@ this.clientSettings = this.inbound.clients ? this.inbound.clients[index] : null; this.isExpired = this.inbound.clients ? this.inbound.isExpiry(index): this.dbInbound.isExpiry; this.clientStats = this.inbound.clients ? this.dbInbound.clientStats.find(row => row.email === this.clientSettings.email) : []; - this.links = this.inbound.genAllLinks(this.dbInbound.remark, app.remarkModel, this.clientSettings); + if (this.inbound.protocol == Protocols.WIREGUARD){ + this.links = this.inbound.genInboundLinks(dbInbound.remark).split('\r\n') + } else { + this.links = this.inbound.genAllLinks(this.dbInbound.remark, app.remarkModel, this.clientSettings); + } if (this.clientSettings) { if (this.clientSettings.subId) { this.subLink = this.genSubLink(this.clientSettings.subId); } - if (this.clientSettings.tgId) { - this.tgLink = "https://t.me/" + this.clientSettings.tgId; - } } this.visible = true; }, diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index aab05462..93f25730 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -200,7 +200,7 @@ {{ i18n "edit" }} - + {{ i18n "qrCode" }} From 57029b1a402acd3034723e956c76536f1e1ade66 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 18 Feb 2024 01:06:15 +0330 Subject: [PATCH 05/61] prerequisite - tzdata --- install.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/install.sh b/install.sh index 9f46d4df..a9b6711b 100644 --- a/install.sh +++ b/install.sh @@ -82,16 +82,16 @@ fi install_base() { case "${release}" in centos | almalinux | rocky) - yum -y update && yum install -y -q wget curl tar + yum -y update && yum install -y -q wget curl tar tzdata ;; fedora) - dnf -y update && dnf install -y -q wget curl tar + dnf -y update && dnf install -y -q wget curl tar tzdata ;; arch | manjaro) - pacman -Syu && pacman -Syu --noconfirm wget curl tar + pacman -Syu && pacman -Syu --noconfirm wget curl tar tzdata ;; *) - apt-get update && apt install -y -q wget curl tar + apt-get update && apt install -y -q wget curl tar tzdata ;; esac } From 2b4d6160c40d55cd8e9a7ffad4cc1524c19c4591 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 18 Feb 2024 01:06:40 +0330 Subject: [PATCH 06/61] minor changes --- util/random/random.go | 7 ++++--- web/job/check_client_ip_job.go | 6 +++--- web/service/outbound.go | 1 - 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/util/random/random.go b/util/random/random.go index b1dd2e09..1dd47ec9 100644 --- a/util/random/random.go +++ b/util/random/random.go @@ -2,7 +2,6 @@ package random import ( "math/rand" - "time" ) var numSeq [10]rune @@ -13,8 +12,6 @@ var numUpperSeq [36]rune var allSeq [62]rune func init() { - rand.Seed(time.Now().UnixNano()) - for i := 0; i < 10; i++ { numSeq[i] = rune('0' + i) } @@ -41,3 +38,7 @@ func Seq(n int) string { } return string(runes) } + +func Num(n int) int { + return rand.Intn(n) +} diff --git a/web/job/check_client_ip_job.go b/web/job/check_client_ip_job.go index 51a09db8..d48bc8eb 100644 --- a/web/job/check_client_ip_job.go +++ b/web/job/check_client_ip_job.go @@ -118,7 +118,7 @@ func (j *CheckClientIpJob) checkFail2BanInstalled() { err := exec.Command(cmd, args...).Run() if err != nil { - logger.Error("fail2ban is not installed. IP limiting may not work properly.") + logger.Warning("fail2ban is not installed. IP limiting may not work properly.") } } @@ -126,12 +126,12 @@ func (j *CheckClientIpJob) processLogFile() { accessLogPath := xray.GetAccessLogPath() if accessLogPath == "none" { - logger.Error("Access log is set to 'none' check your Xray Configs") + logger.Warning("Access log is set to 'none' check your Xray Configs") return } if accessLogPath == "" { - logger.Error("Access log doesn't exist in your Xray Configs") + logger.Warning("Access log doesn't exist in your Xray Configs") return } diff --git a/web/service/outbound.go b/web/service/outbound.go index 244d7a14..05791f69 100644 --- a/web/service/outbound.go +++ b/web/service/outbound.go @@ -10,7 +10,6 @@ import ( ) type OutboundService struct { - xrayApi xray.XrayAPI } func (s *OutboundService) AddTraffic(traffics []*xray.Traffic, clientTraffics []*xray.ClientTraffic) (error, bool) { From fe00cfb09bc7810943a5e777f969a68d3740031c Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 18 Feb 2024 01:13:39 +0330 Subject: [PATCH 07/61] [xray] option error log --- web/html/xui/xray.html | 80 ++++++++++++++++---------- web/service/config.json | 1 + web/translation/translate.en_US.toml | 4 ++ web/translation/translate.es_ES.toml | 4 ++ web/translation/translate.fa_IR.toml | 4 ++ web/translation/translate.id_ID.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, 80 insertions(+), 29 deletions(-) diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html index 10beaa43..3e6cf851 100644 --- a/web/html/xui/xray.html +++ b/web/html/xui/xray.html @@ -114,15 +114,12 @@ - +