diff options
30 files changed, 404 insertions, 121 deletions
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 1115de37..00ac9169 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 @@ -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 }} @@ -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 @@ -1,7 +1,7 @@ # ======================================================== # Stage: Builder # ======================================================== -FROM --platform=$BUILDPLATFORM golang:1.21-alpine AS builder +FROM golang:1.21-alpine AS builder WORKDIR /app ARG TARGETARCH @@ -33,7 +33,8 @@ RUN apk add --no-cache --update \ COPY --from=builder /app/build/ /app/ COPY --from=builder /app/DockerEntrypoint.sh /app/ -COPY --from=builder /app/x-ui /usr/bin/x-ui +COPY --from=builder /app/x-ui.sh /usr/bin/x-ui + # Configure fail2ban RUN rm -f /etc/fail2ban/jail.d/alpine-ssh.conf \ @@ -25,11 +25,39 @@ 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 + +<details> + <summary>Click for SSL Certificate</summary> + +### 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`.* + +</details> + ## Manual Install & Upgrade <details> @@ -201,34 +229,6 @@ Supports a variety of different architectures and devices. Here are some of the </details> - -## SSL Certificate - -<details> - <summary>Click for SSL Certificate</summary> - -### 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`.* - -</details> - ## [WARP Configuration](https://gitlab.com/fscarmen/warp) <details> @@ -281,13 +281,13 @@ 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, + "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/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"` @@ -8,11 +8,11 @@ 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 - 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 @@ -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= @@ -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= 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/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index 42fb50a1..dc02d91b 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, ); } @@ -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='ForceIPv6v4', 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/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/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 @@ <a-input v-model.trim="inbound.stream.ws.path"></a-input> </a-form-item> <a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'> - <a-button size="small" @click="inbound.stream.ws.addHeader()">+</a-button> + <a-button size="small" @click="inbound.stream.ws.addHeader('host', '')">+</a-button> </a-form-item> <a-form-item :wrapper-col="{span:24}"> <a-input-group compact v-for="(header, index) in inbound.stream.ws.headers"> 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, diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html index d6f0c0f8..267103cb 100644 --- a/web/html/xui/xray.html +++ b/web/html/xui/xray.html @@ -147,6 +147,40 @@ </template> </a-col> </a-row> + <a-row style="padding: 20px"> + <a-col :lg="24" :xl="12"> + <a-list-item-meta + title='{{ i18n "pages.xray.logLevel" }}' + description='{{ i18n "pages.xray.logLevelDesc" }}'/> + </a-col> + <a-col :lg="24" :xl="12"> + <template> + <a-select + v-model="setLogLevel" + :dropdown-class-name="themeSwitcher.currentTheme" + style="width: 100%"> + <a-select-option v-for="s in logLevel" :value="s">[[ s ]]</a-select-option> + </a-select> + </template> + </a-col> + </a-row> + <a-row style="padding: 20px"> + <a-col :lg="24" :xl="12"> + <a-list-item-meta + title='{{ i18n "pages.xray.accessLog" }}' + description='{{ i18n "pages.xray.accessLogDesc" }}'/> + </a-col> + <a-col :lg="24" :xl="12"> + <template> + <a-select + v-model="setAccessLog" + :dropdown-class-name="themeSwitcher.currentTheme" + style="width: 100%"> + <a-select-option v-for="s in access" :value="s">[[ s ]]</a-select-option> + </a-select> + </template> + </a-col> + </a-row> </a-list-item> </a-collapse-panel> <a-collapse-panel header='{{ i18n "pages.xray.blockConfigs"}}'> @@ -341,8 +375,15 @@ </a-table> </a-tab-pane> <a-tab-pane key="tpl-3" tab='{{ i18n "pages.xray.Outbounds"}}' style="padding-top: 20px;" force-render="true"> - <a-button type="primary" icon="plus" @click="addOutbound()" style="margin-bottom: 10px;">{{ i18n "pages.xray.outbound.addOutbound" }}</a-button> - <a-button type="primary" @click="showWarp()" style="margin-bottom: 10px;">WARP</a-button> + <a-row> + <a-col :xs="12" :sm="12" :lg="12"> + <a-button type="primary" icon="plus" @click="addOutbound()" style="margin-bottom: 10px;">{{ i18n "pages.xray.outbound.addOutbound" }}</a-button> + <a-button type="primary" @click="showWarp()" style="margin-bottom: 10px;">WARP</a-button> + </a-col> + <a-col :xs="12" :sm="12" :lg="12" style="text-align: right;"> + <a-icon type="sync" :spin="refreshing" @click="refreshOutboundTraffic()" style="margin: 0 5px;"/> + </a-col> + </a-row> <a-table :columns="outboundColumns" bordered :row-key="r => r.key" :data-source="outboundData" @@ -378,6 +419,9 @@ <a-tag style="margin:0;" v-if="outbound.streamSettings.security=='reality'" color="green">reality</a-tag> </template> </template> + <template slot="traffic" slot-scope="text, outbound, index"> + <a-tag color="green">[[ findOutboundTraffic(outbound) ]]</a-tag> + </template> </a-table> </a-tab-pane> <a-tab-pane key="tpl-4" tab='{{ i18n "pages.xray.outbound.reverse"}}' style="padding-top: 20px;" force-render="true"> @@ -463,6 +507,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 +528,9 @@ oldXraySetting: '', xraySetting: '', inboundTags: [], + outboundsTraffic: [], saveBtnDisable: true, + refreshing: false, restartResult: '', isMobile: window.innerWidth <= 768, advSettings: 'xraySetting', @@ -521,6 +568,8 @@ protocol: "freedom" }, routingDomainStrategies: ["AsIs", "IPIfNonMatch", "IPOnDemand"], + logLevel: ["none" , "debug" , "info" , "warning", "error"], + access: ["none" , "./access.log" ], settingsData: { protocols: { bittorrent: ["bittorrent"], @@ -581,6 +630,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 +814,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 +879,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 +1028,7 @@ async mounted() { await this.getXraySetting(); await this.getXrayResult(); + await this.getOutboundsTraffic(); while (true) { await PromiseUtil.sleep(800); this.saveBtnDisable = this.oldXraySetting === this.xraySetting; @@ -1065,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 b393e68d..905a8cc7 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" @@ -92,24 +94,34 @@ 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 } - data, err := os.ReadFile(accessLogPath) - InboundClientIps := make(map[string][]string) + file, err := os.Open(accessLogPath) j.checkError(err) + defer file.Close() - lines := strings.Split(string(data), "\n") - for _, line := range lines { - ipRegx, _ := regexp.Compile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`) + InboundClientIps := make(map[string][]string) + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + + 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 } @@ -124,13 +136,14 @@ func (j *CheckClientIpJob) processLo
|
