Compare commits

...

48 Commits

Author SHA1 Message Date
MHSanaei
195effd177 v2.4.11 2024-12-27 21:49:45 +01:00
MHSanaei
747ad3b9c8 bug fix - outbound xhttp link 2024-12-27 21:30:51 +01:00
mhsanaei
cf879f9527 bug fix - vmess tls 2024-12-27 17:59:59 +01:00
mhsanaei
04c658f1a0 Client: Comment
now you can add Comment and write anything you want to remember
2024-12-27 13:48:07 +01:00
mhsanaei
2ab1a174db moment v2.30.1 2024-12-25 20:27:48 +01:00
mhsanaei
dfca2af997 axios v1.7.9 2024-12-25 19:09:54 +01:00
Baton34
0a7d15b48c RU: translation fix (#2620) 2024-12-22 14:10:06 +01:00
mhsanaei
518bc72f90 media - telebot 2024-12-21 14:00:21 +01:00
mhsanaei
3c65209ce9 Stargazers over Time - variant=adaptive 2024-12-21 13:52:05 +01:00
LoST
174535b05d unnecessary sudo removed (#2619)
All the commands do not work exactly, but since we already work in the beginning on behalf of root, then sudo is not necessary at the beginning. Is that right? 

P.S. when selected in the menu, it says that "command not found".
2024-12-20 23:48:10 +01:00
Tara Rostami
fff54fe7f3 fix bug (#2618) 2024-12-20 19:06:19 +01:00
LoST
0859d230b0 Firewall management: improved (#2614)
* fix permissions

* Update install func + add/edit func open/close ports + status firewall

* hotfix

* subport
2024-12-20 18:43:47 +01:00
KiselevAlexander
02998c5467 Added ip limit data and controls to client info modal (#2617) 2024-12-20 18:34:30 +01:00
Tara Rostami
3f38c42852 fail2ban: better ipv6 validation (#2615) 2024-12-20 18:33:27 +01:00
mhsanaei
49295661fd fail2ban - unban fix
sorry for my mistake
2024-12-19 23:24:10 +01:00
mhsanaei
e4301f8d93 fail2ban - allports 2024-12-19 22:49:25 +01:00
mhsanaei
c6586f8df2 fix typo 2024-12-19 14:53:09 +01:00
mhsanaei
8e81008cdc v2.4.10 2024-12-19 10:54:17 +01:00
mhsanaei
e33ad809d6 Xray Core v24.12.18 2024-12-19 10:48:43 +01:00
mhsanaei
d804043a18 fail2ban - bantime 30min 2024-12-18 13:23:32 +01:00
mhsanaei
0fb0df7056 fail2ban - ipv4 & 6 2024-12-18 12:31:05 +01:00
mhsanaei
73e90e0eaa TLS, REALITY : fingerprint set default to chrome 2024-12-17 23:25:54 +01:00
mhsanaei
44ef1ac9a6 remove insecure cipher suites list 2024-12-17 23:18:16 +01:00
mhsanaei
aeac7f2c8b UTLS: unsafe 2024-12-17 23:17:12 +01:00
mhsanaei
39ef172b87 fail2ban - ban and unban an IP Address 2024-12-17 17:59:04 +01:00
mhsanaei
0df85cc3d9 XHTTP: server & client
Remove scMinPostsIntervalMs, xmux, noGRPCHeader from the server side and add them to the client side.

Before you could have them on sub json but I decided to remove them.
2024-12-17 10:39:37 +01:00
MHSanaei
f0f4f082ae improve iplimit 2024-12-16 14:26:47 +01:00
MHSanaei
b29bd993d4 fix session
twice  set-cookie bug fixed
2024-12-16 14:24:59 +01:00
MHSanaei
127eaf69b6 fail2ban - unban all without restart 2024-12-16 13:28:53 +01:00
mhsanaei
36b0289bc6 XHTTP: Add "scMaxBufferedPosts" 2024-12-16 11:20:38 +01:00
MHSanaei
0abd0be725 v2.4.9 2024-12-16 10:13:40 +01:00
MHSanaei
918a2b1533 XHTTP: Add "hMaxRequestTimes, hKeepAlivePeriod" 2024-12-16 10:13:01 +01:00
MHSanaei
88a17cd227 Xray core v24.12.15 2024-12-16 10:00:15 +01:00
mhsanaei
b60387accb XHTTP: Add "keepAlivePeriod" 2024-12-11 17:05:47 +01:00
mhsanaei
049177024b Xray core buggy version removed
accept >= v24.11.30 or v1.8.24
2024-12-05 20:17:47 +01:00
mhsanaei
9c63638af1 xhttp - default settings 2024-12-05 20:15:19 +01:00
mhsanaei
67dfe664a6 GO v1.23.4 + update dependencies 2024-12-05 20:14:56 +01:00
mhsanaei
4efcdb3e01 Transport: Remove HTTP
Migrated to XHTTP "stream-one" mode.
2024-12-04 13:49:43 +01:00
Sanaei
ddc2cfacb9 Delete .github/dependabot.yml 2024-12-03 23:15:02 +01:00
mhsanaei
337729529a Xray Core v24.11.21 2024-12-03 23:09:38 +01:00
mhsanaei
4c4cc362b3 fix crash report
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
2024-12-03 23:07:24 +01:00
mhsanaei
4e0aca16c2 [warp] report error in change license
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
2024-12-03 23:01:32 +01:00
lexnake3
749a426a71 show IP on warning log when user pass is not correct (#2607) 2024-12-03 22:41:14 +01:00
mhsanaei
b859327b8a splithttp to xhttp 2024-12-03 22:24:34 +01:00
mhsanaei
3e8fc59213 WebSocket: Add heartbeatPeriod 2024-12-03 22:07:58 +01:00
mhsanaei
462e02140d XHTTP: Add "stream-one" 2024-12-03 21:57:44 +01:00
mhsanaei
6b41df2d89 update dependencies 2024-12-03 21:33:01 +01:00
Tara Rostami
eb5ed5c0dd readme update (#2604) 2024-11-21 20:48:30 +03:30
57 changed files with 744 additions and 615 deletions

View File

@@ -1,10 +0,0 @@
version: 2
updates:
- package-ecosystem: "gomod" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

View File

@@ -83,7 +83,7 @@ jobs:
cd x-ui/bin cd x-ui/bin
# Download dependencies # Download dependencies
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v24.11.21/" Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v24.12.18/"
if [ "${{ matrix.platform }}" == "amd64" ]; then if [ "${{ matrix.platform }}" == "amd64" ]; then
wget ${Xray_URL}Xray-linux-64.zip wget ${Xray_URL}Xray-linux-64.zip
unzip Xray-linux-64.zip unzip Xray-linux-64.zip

View File

@@ -27,7 +27,7 @@ case $1 in
esac esac
mkdir -p build/bin mkdir -p build/bin
cd build/bin cd build/bin
wget "https://github.com/XTLS/Xray-core/releases/download/v24.11.21/Xray-linux-${ARCH}.zip" wget "https://github.com/XTLS/Xray-core/releases/download/v24.12.18/Xray-linux-${ARCH}.zip"
unzip "Xray-linux-${ARCH}.zip" unzip "Xray-linux-${ARCH}.zip"
rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat
mv xray "xray-linux-${FNAME}" mv xray "xray-linux-${FNAME}"

View File

@@ -1,6 +1,11 @@
[English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md) [English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p> <p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/3x-ui-dark.png">
<img alt="3x-ui" src="./media/3x-ui-light.png">
</picture>
</p>
**Un Panel Web Avanzado • Construido sobre Xray Core** **Un Panel Web Avanzado • Construido sobre Xray Core**
@@ -539,13 +544,34 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## Vista previa ## Vista previa
![1](./media/1.png) <picture>
![2](./media/2.png) <source media="(prefers-color-scheme: dark)" srcset="./media/01-overview-dark.png">
![3](./media/3.png) <img alt="3x-ui" src="./media/01-overview-light.png">
![4](./media/4.png) </picture>
![5](./media/5.png) <picture>
![6](./media/6.png) <source media="(prefers-color-scheme: dark)" srcset="./media/02-inbounds-dark.png">
![7](./media/7.png) <img alt="3x-ui" src="./media/02-inbounds-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/03-add-inbound-dark.png">
<img alt="3x-ui" src="./media/03-add-inbound-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/04-add-client-dark.png">
<img alt="3x-ui" src="./media/04-add-client-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/05-settings-dark.png">
<img alt="3x-ui" src="./media/05-settings-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/06-configs-dark.png">
<img alt="3x-ui" src="./media/06-configs-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/07-bot-dark.png">
<img alt="3x-ui" src="./media/07-bot-light.png">
</picture>
## Un agradecimiento especial a ## Un agradecimiento especial a
@@ -558,4 +584,4 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## Estrellas a lo largo del tiempo ## Estrellas a lo largo del tiempo
[![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg)](https://starchart.cc/MHSanaei/3x-ui) [![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg?variant=adaptive)](https://starchart.cc/MHSanaei/3x-ui)

View File

@@ -1,6 +1,11 @@
[English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md) [English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p> <p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/3x-ui-dark.png">
<img alt="3x-ui" src="./media/3x-ui-light.png">
</picture>
</p>
**An Advanced Web Panel • Built on Xray Core** **An Advanced Web Panel • Built on Xray Core**
@@ -548,13 +553,34 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## Preview ## Preview
![1](./media/1.png) <picture>
![2](./media/2.png) <source media="(prefers-color-scheme: dark)" srcset="./media/01-overview-dark.png">
![3](./media/3.png) <img alt="3x-ui" src="./media/01-overview-light.png">
![4](./media/4.png) </picture>
![5](./media/5.png) <picture>
![6](./media/6.png) <source media="(prefers-color-scheme: dark)" srcset="./media/02-inbounds-dark.png">
![7](./media/7.png) <img alt="3x-ui" src="./media/02-inbounds-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/03-add-inbound-dark.png">
<img alt="3x-ui" src="./media/03-add-inbound-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/04-add-client-dark.png">
<img alt="3x-ui" src="./media/04-add-client-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/05-settings-dark.png">
<img alt="3x-ui" src="./media/05-settings-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/06-configs-dark.png">
<img alt="3x-ui" src="./media/06-configs-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/07-bot-dark.png">
<img alt="3x-ui" src="./media/07-bot-light.png">
</picture>
## A Special Thanks to ## A Special Thanks to
@@ -567,4 +593,4 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## Stargazers over Time ## Stargazers over Time
[![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg)](https://starchart.cc/MHSanaei/3x-ui) [![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg?variant=adaptive)](https://starchart.cc/MHSanaei/3x-ui)

View File

@@ -1,6 +1,11 @@
[English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md) [English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p> <p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/3x-ui-dark.png">
<img alt="3x-ui" src="./media/3x-ui-light.png">
</picture>
</p>
**Продвинутая веб-панель • Построена на основе Xray Core** **Продвинутая веб-панель • Построена на основе Xray Core**
@@ -546,13 +551,34 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## Предварительный Просмотр ## Предварительный Просмотр
![1](./media/1.png) <picture>
![2](./media/2.png) <source media="(prefers-color-scheme: dark)" srcset="./media/01-overview-dark.png">
![3](./media/3.png) <img alt="3x-ui" src="./media/01-overview-light.png">
![4](./media/4.png) </picture>
![5](./media/5.png) <picture>
![6](./media/6.png) <source media="(prefers-color-scheme: dark)" srcset="./media/02-inbounds-dark.png">
![7](./media/7.png) <img alt="3x-ui" src="./media/02-inbounds-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/03-add-inbound-dark.png">
<img alt="3x-ui" src="./media/03-add-inbound-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/04-add-client-dark.png">
<img alt="3x-ui" src="./media/04-add-client-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/05-settings-dark.png">
<img alt="3x-ui" src="./media/05-settings-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/06-configs-dark.png">
<img alt="3x-ui" src="./media/06-configs-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/07-bot-dark.png">
<img alt="3x-ui" src="./media/07-bot-light.png">
</picture>
## Особая благодарность ## Особая благодарность
@@ -565,4 +591,4 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## Число звёзд со временем ## Число звёзд со временем
[![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg)](https://starchart.cc/MHSanaei/3x-ui) [![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg?variant=adaptive)](https://starchart.cc/MHSanaei/3x-ui)

View File

@@ -1,6 +1,11 @@
[English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md) [English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p> <p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/3x-ui-dark.png">
<img alt="3x-ui" src="./media/3x-ui-light.png">
</picture>
</p>
**一个更好的面板 • 基于Xray Core构建** **一个更好的面板 • 基于Xray Core构建**
@@ -539,13 +544,34 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## 预览 ## 预览
![1](./media/1.png) <picture>
![2](./media/2.png) <source media="(prefers-color-scheme: dark)" srcset="./media/01-overview-dark.png">
![3](./media/3.png) <img alt="3x-ui" src="./media/01-overview-light.png">
![4](./media/4.png) </picture>
![5](./media/5.png) <picture>
![6](./media/6.png) <source media="(prefers-color-scheme: dark)" srcset="./media/02-inbounds-dark.png">
![7](./media/7.png) <img alt="3x-ui" src="./media/02-inbounds-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/03-add-inbound-dark.png">
<img alt="3x-ui" src="./media/03-add-inbound-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/04-add-client-dark.png">
<img alt="3x-ui" src="./media/04-add-client-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/05-settings-dark.png">
<img alt="3x-ui" src="./media/05-settings-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/06-configs-dark.png">
<img alt="3x-ui" src="./media/06-configs-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/07-bot-dark.png">
<img alt="3x-ui" src="./media/07-bot-light.png">
</picture>
## 特别感谢 ## 特别感谢
@@ -558,4 +584,4 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## Star趋势 ## Star趋势
[![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg)](https://starchart.cc/MHSanaei/3x-ui) [![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg?variant=adaptive)](https://starchart.cc/MHSanaei/3x-ui)

View File

@@ -1 +1 @@
2.4.8 2.4.11

View File

@@ -98,5 +98,6 @@ type Client struct {
Enable bool `json:"enable" form:"enable"` Enable bool `json:"enable" form:"enable"`
TgID int64 `json:"tgId" form:"tgId"` TgID int64 `json:"tgId" form:"tgId"`
SubID string `json:"subId" form:"subId"` SubID string `json:"subId" form:"subId"`
Comment string `json:"comment" form:"comment"`
Reset int `json:"reset" form:"reset"` Reset int `json:"reset" form:"reset"`
} }

42
go.mod
View File

@@ -1,37 +1,37 @@
module x-ui module x-ui
go 1.23.3 go 1.23.4
require ( require (
github.com/gin-contrib/gzip v1.0.1 github.com/gin-contrib/gzip v1.0.1
github.com/gin-contrib/sessions v1.0.1 github.com/gin-contrib/sessions v1.0.1
github.com/gin-gonic/gin v1.10.0 github.com/gin-gonic/gin v1.10.0
github.com/goccy/go-json v0.10.3 github.com/goccy/go-json v0.10.4
github.com/mymmrac/telego v0.31.4 github.com/mymmrac/telego v0.31.4
github.com/nicksnyder/go-i18n/v2 v2.4.1 github.com/nicksnyder/go-i18n/v2 v2.4.1
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pelletier/go-toml/v2 v2.2.3 github.com/pelletier/go-toml/v2 v2.2.3
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v4 v4.24.10 github.com/shirou/gopsutil/v4 v4.24.11
github.com/valyala/fasthttp v1.57.0 github.com/valyala/fasthttp v1.58.0
github.com/xtls/xray-core v1.8.25-0.20241121054707-513f18bf531e github.com/xtls/xray-core v1.8.25-0.20241218133935-cab2fdefd321
go.uber.org/atomic v1.11.0 go.uber.org/atomic v1.11.0
golang.org/x/text v0.20.0 golang.org/x/text v0.21.0
google.golang.org/grpc v1.68.0 google.golang.org/grpc v1.69.2
gorm.io/driver/sqlite v1.5.6 gorm.io/driver/sqlite v1.5.7
gorm.io/gorm v1.25.12 gorm.io/gorm v1.25.12
) )
require ( require (
github.com/andybalholm/brotli v1.1.1 // indirect github.com/andybalholm/brotli v1.1.1 // indirect
github.com/bytedance/sonic v1.12.4 // indirect github.com/bytedance/sonic v1.12.6 // indirect
github.com/bytedance/sonic/loader v0.2.1 // indirect github.com/bytedance/sonic/loader v0.2.1 // indirect
github.com/cloudflare/circl v1.5.0 // indirect github.com/cloudflare/circl v1.5.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect github.com/cloudwego/iasm v0.2.0 // indirect
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/ebitengine/purego v0.8.1 // indirect github.com/ebitengine/purego v0.8.1 // indirect
github.com/fasthttp/router v1.5.2 // indirect github.com/fasthttp/router v1.5.3 // indirect
github.com/gabriel-vasile/mimetype v1.4.7 // indirect github.com/gabriel-vasile/mimetype v1.4.7 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
@@ -40,7 +40,7 @@ require (
github.com/go-playground/validator/v10 v10.23.0 // indirect github.com/go-playground/validator/v10 v10.23.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/google/btree v1.1.3 // indirect github.com/google/btree v1.1.3 // indirect
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 // indirect github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/gorilla/context v1.1.2 // indirect github.com/gorilla/context v1.1.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gorilla/sessions v1.4.0 // indirect github.com/gorilla/sessions v1.4.0 // indirect
@@ -58,11 +58,11 @@ require (
github.com/mattn/go-sqlite3 v1.14.24 // indirect github.com/mattn/go-sqlite3 v1.14.24 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/onsi/ginkgo/v2 v2.21.0 // indirect github.com/onsi/ginkgo/v2 v2.22.0 // indirect
github.com/pires/go-proxyproto v0.8.0 // indirect github.com/pires/go-proxyproto v0.8.0 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.48.1 // indirect github.com/quic-go/quic-go v0.48.2 // indirect
github.com/refraction-networking/utls v1.6.7 // indirect github.com/refraction-networking/utls v1.6.7 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect
@@ -84,18 +84,18 @@ require (
go.uber.org/mock v0.5.0 // indirect go.uber.org/mock v0.5.0 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/arch v0.12.0 // indirect golang.org/x/arch v0.12.0 // indirect
golang.org/x/crypto v0.29.0 // indirect golang.org/x/crypto v0.31.0 // indirect
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect
golang.org/x/mod v0.22.0 // indirect golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.31.0 // indirect golang.org/x/net v0.33.0 // indirect
golang.org/x/sync v0.9.0 // indirect golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.27.0 // indirect golang.org/x/sys v0.28.0 // indirect
golang.org/x/time v0.8.0 // indirect golang.org/x/time v0.8.0 // indirect
golang.org/x/tools v0.27.0 // indirect golang.org/x/tools v0.28.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 // indirect
google.golang.org/protobuf v1.35.2 // indirect google.golang.org/protobuf v1.36.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 // indirect gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 // indirect
lukechampine.com/blake3 v1.3.0 // indirect lukechampine.com/blake3 v1.3.0 // indirect

98
go.sum
View File

@@ -4,8 +4,8 @@ github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJS
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM= github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM=
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
github.com/bytedance/sonic v1.12.4 h1:9Csb3c9ZJhfUWeMtpCDCq6BUoH5ogfDFLUgQ/jG+R0k= github.com/bytedance/sonic v1.12.6 h1:/isNmCUF2x3Sh8RAp/4mh4ZGkcFAX/hLrzrK3AvpRzk=
github.com/bytedance/sonic v1.12.4/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic v1.12.6/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.1 h1:1GgorWTqf12TA8mma4DDSbaQigE2wOgQo7iCjjJv3+E= github.com/bytedance/sonic/loader v0.2.1 h1:1GgorWTqf12TA8mma4DDSbaQigE2wOgQo7iCjjJv3+E=
github.com/bytedance/sonic/loader v0.2.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.2.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
@@ -24,8 +24,8 @@ github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFP
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE= github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE=
github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/fasthttp/router v1.5.2 h1:ckJCCdV7hWkkrMeId3WfEhz+4Gyyf6QPwxi/RHIMZ6I= github.com/fasthttp/router v1.5.3 h1:BFWXqa3e4thRI3MgPKTNtz0Oiq6UYN2OsEtb+YQ5TMI=
github.com/fasthttp/router v1.5.2/go.mod h1:C8EY53ozOwpONyevc/V7Gr8pqnEjwnkFFqPo1alAGs0= github.com/fasthttp/router v1.5.3/go.mod h1:b864KkDIapOYh77AVG/SNkwfRZ6k6ecWvD+ZRXmP5pw=
github.com/gabriel-vasile/mimetype v1.4.7 h1:SKFKl7kD0RiPdbht0s7hFtjl489WcQ1VyPW8ZzUMYCA= github.com/gabriel-vasile/mimetype v1.4.7 h1:SKFKl7kD0RiPdbht0s7hFtjl489WcQ1VyPW8ZzUMYCA=
github.com/gabriel-vasile/mimetype v1.4.7/go.mod h1:GDlAgAyIRT27BhFl53XNAFtfjzOkLaF35JdEG0P7LtU= github.com/gabriel-vasile/mimetype v1.4.7/go.mod h1:GDlAgAyIRT27BhFl53XNAFtfjzOkLaF35JdEG0P7LtU=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
@@ -40,6 +40,8 @@ github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
@@ -53,8 +55,8 @@ github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U= github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs= github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
@@ -66,8 +68,10 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 h1:sAGdeJj0bnMgUNVeUpp6AYlVdCt3/GdI3pGRqsNSQLs= github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o= github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o=
github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM= github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
@@ -113,8 +117,8 @@ github.com/mymmrac/telego v0.31.4 h1:NpiNl0P/8eydknka/k6XaaaWVj5BKMlM3Ibba63QTBU
github.com/mymmrac/telego v0.31.4/go.mod h1:T12js1PgbYDYznvoN05MSMuPMfWTYo7D9LKl5cPFWiI= github.com/mymmrac/telego v0.31.4/go.mod h1:T12js1PgbYDYznvoN05MSMuPMfWTYo7D9LKl5cPFWiI=
github.com/nicksnyder/go-i18n/v2 v2.4.1 h1:zwzjtX4uYyiaU02K5Ia3zSkpJZrByARkRB4V3YPrr0g= github.com/nicksnyder/go-i18n/v2 v2.4.1 h1:zwzjtX4uYyiaU02K5Ia3zSkpJZrByARkRB4V3YPrr0g=
github.com/nicksnyder/go-i18n/v2 v2.4.1/go.mod h1:++Pl70FR6Cki7hdzZRnEEqdc2dJt+SAGotyFg/SvZMk= github.com/nicksnyder/go-i18n/v2 v2.4.1/go.mod h1:++Pl70FR6Cki7hdzZRnEEqdc2dJt+SAGotyFg/SvZMk=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
@@ -131,8 +135,8 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.48.1 h1:y/8xmfWI9qmGTc+lBr4jKRUWLGSlSigv847ULJ4hYXA= github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
github.com/quic-go/quic-go v0.48.1/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
@@ -149,8 +153,8 @@ github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 h1:D0vL7YNisV2yqE55
github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg= github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg=
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4= github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4=
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/shirou/gopsutil/v4 v4.24.10 h1:7VOzPtfw/5YDU+jLEoBwXwxJbQetULywoSV4RYY7HkM= github.com/shirou/gopsutil/v4 v4.24.11 h1:WaU9xqGFKvFfsUv94SXcUPD7rCkU0vr/asVdQOBZNj8=
github.com/shirou/gopsutil/v4 v4.24.10/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8= github.com/shirou/gopsutil/v4 v4.24.11/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -160,8 +164,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo= github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo=
@@ -174,8 +178,8 @@ github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU= github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.57.0 h1:Xw8SjWGEP/+wAAgyy5XTvgrWlOD1+TxbbvNADYCm1Tg= github.com/valyala/fasthttp v1.58.0 h1:GGB2dWxSbEprU9j0iMJHgdKYJVDyjrOwF9RE59PbRuE=
github.com/valyala/fasthttp v1.57.0/go.mod h1:h6ZBaPRlzpZ6O3H5t2gEk1Qi33+TmLvfwgLLp0t9CpE= github.com/valyala/fasthttp v1.58.0/go.mod h1:SYXvHHaFp7QZHGKSHmoMipInhrI5StHrhDTYVEjK/Kw=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
@@ -185,12 +189,22 @@ github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zd
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463 h1:g1Cj7d+my6k/HHxLAyxPwyX8i7FGRr6ulBDMkBzg2BM= github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463 h1:g1Cj7d+my6k/HHxLAyxPwyX8i7FGRr6ulBDMkBzg2BM=
github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463/go.mod h1:BjIOLmkEEtAgloAiVUcYj0Mt+YU00JARZw8AEU0IwAg= github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463/go.mod h1:BjIOLmkEEtAgloAiVUcYj0Mt+YU00JARZw8AEU0IwAg=
github.com/xtls/xray-core v1.8.25-0.20241121054707-513f18bf531e h1:J5sTv0Sw+BonaI+rBh4Jkw9BfBqDjfAts81/HbIaqNg= github.com/xtls/xray-core v1.8.25-0.20241218133935-cab2fdefd321 h1:vk+n1RmfhFCj5xSi4I6C3USpcUQ48H3lt/QrtARVz1M=
github.com/xtls/xray-core v1.8.25-0.20241121054707-513f18bf531e/go.mod h1:wByClH1yrH8I611sREjG62gxbP5hFtdAWYJfydQF/zI= github.com/xtls/xray-core v1.8.25-0.20241218133935-cab2fdefd321/go.mod h1:DCaUwrBk1RIC7hWg/wGoAynE69g3ptua1sEr8i0BWxA=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE=
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY=
go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
@@ -199,40 +213,40 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg= golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg=
golang.org/x/arch v0.12.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/arch v0.12.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4= golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA= golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 h1:LWZqQOEjDyONlF1H6afSWpAL/znlREo2tHfLoe+8LMA= google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 h1:Z7FRVJPSMaHQxD0uXU8WdgFh8PseLM8Q8NzhnpMrBhQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ=
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -242,8 +256,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE= gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE= gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE=

View File

@@ -2,6 +2,7 @@
red='\033[0;31m' red='\033[0;31m'
green='\033[0;32m' green='\033[0;32m'
blue='\033[0;34m'
yellow='\033[0;33m' yellow='\033[0;33m'
plain='\033[0m' plain='\033[0m'
@@ -260,24 +261,24 @@ install_x-ui() {
systemctl start x-ui systemctl start x-ui
echo -e "${green}x-ui ${tag_version}${plain} installation finished, it is running now..." echo -e "${green}x-ui ${tag_version}${plain} installation finished, it is running now..."
echo -e "" echo -e ""
echo -e "x-ui control menu usages: " echo -e "┌───────────────────────────────────────────────────────┐
echo -e "----------------------------------------------" ${blue}x-ui control menu usages (subcommands):${plain}
echo -e "SUBCOMMANDS:" │ │
echo -e "x-ui - Admin Management Script" ${blue}x-ui${plain} - Admin Management Script
echo -e "x-ui start - Start" ${blue}x-ui start${plain} - Start │
echo -e "x-ui stop - Stop" ${blue}x-ui stop${plain} - Stop │
echo -e "x-ui restart - Restart" ${blue}x-ui restart${plain} - Restart │
echo -e "x-ui status - Current Status" ${blue}x-ui status${plain} - Current Status
echo -e "x-ui settings - Current Settings" ${blue}x-ui settings${plain} - Current Settings
echo -e "x-ui enable - Enable Autostart on OS Startup" ${blue}x-ui enable${plain} - Enable Autostart on OS Startup
echo -e "x-ui disable - Disable Autostart on OS Startup" ${blue}x-ui disable${plain} - Disable Autostart on OS Startup
echo -e "x-ui log - Check logs" ${blue}x-ui log${plain} - Check logs │
echo -e "x-ui banlog - Check Fail2ban ban logs" ${blue}x-ui banlog${plain} - Check Fail2ban ban logs
echo -e "x-ui update - Update" ${blue}x-ui update${plain} - Update │
echo -e "x-ui legacy - legacy version" ${blue}x-ui legacy${plain} - legacy version
echo -e "x-ui install - Install" ${blue}x-ui install${plain} - Install │
echo -e "x-ui uninstall - Uninstall" ${blue}x-ui uninstall${plain} - Uninstall │
echo -e "----------------------------------------------" └───────────────────────────────────────────────────────┘"
} }
echo -e "${green}Running...${plain}" echo -e "${green}Running...${plain}"

BIN
media/01-overview-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

BIN
media/01-overview-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
media/02-inbounds-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

BIN
media/02-inbounds-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
media/05-settings-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
media/05-settings-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
media/06-configs-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
media/06-configs-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
media/07-bot-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
media/07-bot-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 226 KiB

After

Width:  |  Height:  |  Size: 226 KiB

BIN
media/3x-ui-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

View File

@@ -208,11 +208,6 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
headers, _ := ws["headers"].(map[string]interface{}) headers, _ := ws["headers"].(map[string]interface{})
obj["host"] = searchHost(headers) obj["host"] = searchHost(headers)
} }
case "http":
obj["net"] = "h2"
http, _ := stream["httpSettings"].(map[string]interface{})
obj["path"], _ = http["path"].(string)
obj["host"] = searchHost(http)
case "grpc": case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{}) grpc, _ := stream["grpcSettings"].(map[string]interface{})
obj["path"] = grpc["serviceName"].(string) obj["path"] = grpc["serviceName"].(string)
@@ -229,16 +224,16 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
headers, _ := httpupgrade["headers"].(map[string]interface{}) headers, _ := httpupgrade["headers"].(map[string]interface{})
obj["host"] = searchHost(headers) obj["host"] = searchHost(headers)
} }
case "splithttp": case "xhttp":
splithttp, _ := stream["splithttpSettings"].(map[string]interface{}) xhttp, _ := stream["xhttpSettings"].(map[string]interface{})
obj["path"] = splithttp["path"].(string) obj["path"] = xhttp["path"].(string)
if host, ok := splithttp["host"].(string); ok && len(host) > 0 { if host, ok := xhttp["host"].(string); ok && len(host) > 0 {
obj["host"] = host obj["host"] = host
} else { } else {
headers, _ := splithttp["headers"].(map[string]interface{}) headers, _ := xhttp["headers"].(map[string]interface{})
obj["host"] = searchHost(headers) obj["host"] = searchHost(headers)
} }
obj["mode"] = splithttp["mode"].(string) obj["mode"] = xhttp["mode"].(string)
} }
security, _ := stream["security"].(string) security, _ := stream["security"].(string)
obj["tls"] = security obj["tls"] = security
@@ -361,10 +356,6 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
headers, _ := ws["headers"].(map[string]interface{}) headers, _ := ws["headers"].(map[string]interface{})
params["host"] = searchHost(headers) params["host"] = searchHost(headers)
} }
case "http":
http, _ := stream["httpSettings"].(map[string]interface{})
params["path"] = http["path"].(string)
params["host"] = searchHost(http)
case "grpc": case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{}) grpc, _ := stream["grpcSettings"].(map[string]interface{})
params["serviceName"] = grpc["serviceName"].(string) params["serviceName"] = grpc["serviceName"].(string)
@@ -381,16 +372,16 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
headers, _ := httpupgrade["headers"].(map[string]interface{}) headers, _ := httpupgrade["headers"].(map[string]interface{})
params["host"] = searchHost(headers) params["host"] = searchHost(headers)
} }
case "splithttp": case "xhttp":
splithttp, _ := stream["splithttpSettings"].(map[string]interface{}) xhttp, _ := stream["xhttpSettings"].(map[string]interface{})
params["path"] = splithttp["path"].(string) params["path"] = xhttp["path"].(string)
if host, ok := splithttp["host"].(string); ok && len(host) > 0 { if host, ok := xhttp["host"].(string); ok && len(host) > 0 {
params["host"] = host params["host"] = host
} else { } else {
headers, _ := splithttp["headers"].(map[string]interface{}) headers, _ := xhttp["headers"].(map[string]interface{})
params["host"] = searchHost(headers) params["host"] = searchHost(headers)
} }
params["mode"] = splithttp["mode"].(string) params["mode"] = xhttp["mode"].(string)
} }
security, _ := stream["security"].(string) security, _ := stream["security"].(string)
if security == "tls" { if security == "tls" {
@@ -559,10 +550,6 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
headers, _ := ws["headers"].(map[string]interface{}) headers, _ := ws["headers"].(map[string]interface{})
params["host"] = searchHost(headers) params["host"] = searchHost(headers)
} }
case "http":
http, _ := stream["httpSettings"].(map[string]interface{})
params["path"] = http["path"].(string)
params["host"] = searchHost(http)
case "grpc": case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{}) grpc, _ := stream["grpcSettings"].(map[string]interface{})
params["serviceName"] = grpc["serviceName"].(string) params["serviceName"] = grpc["serviceName"].(string)
@@ -579,16 +566,16 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
headers, _ := httpupgrade["headers"].(map[string]interface{}) headers, _ := httpupgrade["headers"].(map[string]interface{})
params["host"] = searchHost(headers) params["host"] = searchHost(headers)
} }
case "splithttp": case "xhttp":
splithttp, _ := stream["splithttpSettings"].(map[string]interface{}) xhttp, _ := stream["xhttpSettings"].(map[string]interface{})
params["path"] = splithttp["path"].(string) params["path"] = xhttp["path"].(string)
if host, ok := splithttp["host"].(string); ok && len(host) > 0 { if host, ok := xhttp["host"].(string); ok && len(host) > 0 {
params["host"] = host params["host"] = host
} else { } else {
headers, _ := splithttp["headers"].(map[string]interface{}) headers, _ := xhttp["headers"].(map[string]interface{})
params["host"] = searchHost(headers) params["host"] = searchHost(headers)
} }
params["mode"] = splithttp["mode"].(string) params["mode"] = xhttp["mode"].(string)
} }
security, _ := stream["security"].(string) security, _ := stream["security"].(string)
if security == "tls" { if security == "tls" {
@@ -757,10 +744,6 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
headers, _ := ws["headers"].(map[string]interface{}) headers, _ := ws["headers"].(map[string]interface{})
params["host"] = searchHost(headers) params["host"] = searchHost(headers)
} }
case "http":
http, _ := stream["httpSettings"].(map[string]interface{})
params["path"] = http["path"].(string)
params["host"] = searchHost(http)
case "grpc": case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{}) grpc, _ := stream["grpcSettings"].(map[string]interface{})
params["serviceName"] = grpc["serviceName"].(string) params["serviceName"] = grpc["serviceName"].(string)
@@ -777,16 +760,16 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
headers, _ := httpupgrade["headers"].(map[string]interface{}) headers, _ := httpupgrade["headers"].(map[string]interface{})
params["host"] = searchHost(headers) params["host"] = searchHost(headers)
} }
case "splithttp": case "xhttp":
splithttp, _ := stream["splithttpSettings"].(map[string]interface{}) xhttp, _ := stream["xhttpSettings"].(map[string]interface{})
params["path"] = splithttp["path"].(string) params["path"] = xhttp["path"].(string)
if host, ok := splithttp["host"].(string); ok && len(host) > 0 { if host, ok := xhttp["host"].(string); ok && len(host) > 0 {
params["host"] = host params["host"] = host
} else { } else {
headers, _ := splithttp["headers"].(map[string]interface{}) headers, _ := xhttp["headers"].(map[string]interface{})
params["host"] = searchHost(headers) params["host"] = searchHost(headers)
} }
params["mode"] = splithttp["mode"].(string) params["mode"] = xhttp["mode"].(string)
} }
security, _ := stream["security"].(string) security, _ := stream["security"].(string)

File diff suppressed because one or more lines are too long

View File

@@ -34,10 +34,6 @@ const TLS_VERSION_OPTION = {
}; };
const TLS_CIPHER_OPTION = { const TLS_CIPHER_OPTION = {
RSA_AES_128_CBC: "TLS_RSA_WITH_AES_128_CBC_SHA",
RSA_AES_256_CBC: "TLS_RSA_WITH_AES_256_CBC_SHA",
RSA_AES_128_GCM: "TLS_RSA_WITH_AES_128_GCM_SHA256",
RSA_AES_256_GCM: "TLS_RSA_WITH_AES_256_GCM_SHA384",
AES_128_GCM: "TLS_AES_128_GCM_SHA256", AES_128_GCM: "TLS_AES_128_GCM_SHA256",
AES_256_GCM: "TLS_AES_256_GCM_SHA384", AES_256_GCM: "TLS_AES_256_GCM_SHA384",
CHACHA20_POLY1305: "TLS_CHACHA20_POLY1305_SHA256", CHACHA20_POLY1305: "TLS_CHACHA20_POLY1305_SHA256",
@@ -64,6 +60,7 @@ const UTLS_FINGERPRINT = {
UTLS_QQ: "qq", UTLS_QQ: "qq",
UTLS_RANDOM: "random", UTLS_RANDOM: "random",
UTLS_RANDOMIZED: "randomized", UTLS_RANDOMIZED: "randomized",
UTLS_UNSAFE: "unsafe",
}; };
const ALPN_OPTION = { const ALPN_OPTION = {
@@ -117,6 +114,7 @@ const MODE_OPTION = {
AUTO: "auto", AUTO: "auto",
PACKET_UP: "packet-up", PACKET_UP: "packet-up",
STREAM_UP: "stream-up", STREAM_UP: "stream-up",
STREAM_ONE: "stream-one",
}; };
Object.freeze(Protocols); Object.freeze(Protocols);
@@ -378,13 +376,15 @@ class WsStreamSettings extends XrayCommonClass {
acceptProxyProtocol = false, acceptProxyProtocol = false,
path = '/', path = '/',
host = '', host = '',
headers = [] headers = [],
heartbeatPeriod = 0,
) { ) {
super(); super();
this.acceptProxyProtocol = acceptProxyProtocol; this.acceptProxyProtocol = acceptProxyProtocol;
this.path = path; this.path = path;
this.host = host; this.host = host;
this.headers = headers; this.headers = headers;
this.heartbeatPeriod = heartbeatPeriod;
} }
addHeader(name, value) { addHeader(name, value) {
@@ -401,6 +401,7 @@ class WsStreamSettings extends XrayCommonClass {
json.path, json.path,
json.host, json.host,
XrayCommonClass.toHeaders(json.headers), XrayCommonClass.toHeaders(json.headers),
json.heartbeatPeriod,
); );
} }
@@ -410,46 +411,11 @@ class WsStreamSettings extends XrayCommonClass {
path: this.path, path: this.path,
host: this.host, host: this.host,
headers: XrayCommonClass.toV2Headers(this.headers, false), headers: XrayCommonClass.toV2Headers(this.headers, false),
heartbeatPeriod: this.heartbeatPeriod,
}; };
} }
} }
class HttpStreamSettings extends XrayCommonClass {
constructor(
path = '/',
host = [''],
) {
super();
this.path = path;
this.host = host.length === 0 ? [''] : host;
}
addHost(host) {
this.host.push(host);
}
removeHost(index) {
this.host.splice(index, 1);
}
static fromJson(json = {}) {
return new HttpStreamSettings(json.path, json.host);
}
toJson() {
let host = [];
for (let i = 0; i < this.host.length; ++i) {
if (!ObjectUtil.isEmpty(this.host[i])) {
host.push(this.host[i]);
}
}
return {
path: this.path,
host: host,
}
}
}
class GrpcStreamSettings extends XrayCommonClass { class GrpcStreamSettings extends XrayCommonClass {
constructor( constructor(
serviceName = "", serviceName = "",
@@ -520,37 +486,26 @@ class HTTPUpgradeStreamSettings extends XrayCommonClass {
} }
} }
class SplitHTTPStreamSettings extends XrayCommonClass { class xHTTPStreamSettings extends XrayCommonClass {
constructor( constructor(
path = '/', path = '/',
host = '', host = '',
headers = [], headers = [],
scMaxConcurrentPosts = "100-200", scMaxBufferedPosts = 30,
scMaxEachPostBytes = "1000000-2000000", scMaxEachPostBytes = "1000000",
scMinPostsIntervalMs = "10-50",
noSSEHeader = false, noSSEHeader = false,
xPaddingBytes = "100-1000", xPaddingBytes = "100-1000",
xmux = {
maxConcurrency: "16-32",
maxConnections: 0,
cMaxReuseTimes: "64-128",
cMaxLifetimeMs: 0
},
mode = MODE_OPTION.AUTO, mode = MODE_OPTION.AUTO,
noGRPCHeader = false,
) { ) {
super(); super();
this.path = path; this.path = path;
this.host = host; this.host = host;
this.headers = headers; this.headers = headers;
this.scMaxConcurrentPosts = scMaxConcurrentPosts; this.scMaxBufferedPosts = scMaxBufferedPosts;
this.scMaxEachPostBytes = scMaxEachPostBytes; this.scMaxEachPostBytes = scMaxEachPostBytes;
this.scMinPostsIntervalMs = scMinPostsIntervalMs;
this.noSSEHeader = noSSEHeader; this.noSSEHeader = noSSEHeader;
this.xPaddingBytes = xPaddingBytes; this.xPaddingBytes = xPaddingBytes;
this.xmux = xmux;
this.mode = mode; this.mode = mode;
this.noGRPCHeader = noGRPCHeader;
} }
addHeader(name, value) { addHeader(name, value) {
@@ -562,18 +517,15 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
} }
static fromJson(json = {}) { static fromJson(json = {}) {
return new SplitHTTPStreamSettings( return new xHTTPStreamSettings(
json.path, json.path,
json.host, json.host,
XrayCommonClass.toHeaders(json.headers), XrayCommonClass.toHeaders(json.headers),
json.scMaxConcurrentPosts, json.scMaxBufferedPosts,
json.scMaxEachPostBytes, json.scMaxEachPostBytes,
json.scMinPostsIntervalMs,
json.noSSEHeader, json.noSSEHeader,
json.xPaddingBytes, json.xPaddingBytes,
json.xmux,
json.mode, json.mode,
json.noGRPCHeader
); );
} }
@@ -582,19 +534,11 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
path: this.path, path: this.path,
host: this.host, host: this.host,
headers: XrayCommonClass.toV2Headers(this.headers, false), headers: XrayCommonClass.toV2Headers(this.headers, false),
scMaxConcurrentPosts: this.scMaxConcurrentPosts, scMaxBufferedPosts: this.scMaxBufferedPosts,
scMaxEachPostBytes: this.scMaxEachPostBytes, scMaxEachPostBytes: this.scMaxEachPostBytes,
scMinPostsIntervalMs: this.scMinPostsIntervalMs,
noSSEHeader: this.noSSEHeader, noSSEHeader: this.noSSEHeader,
xPaddingBytes: this.xPaddingBytes, xPaddingBytes: this.xPaddingBytes,
xmux: {
maxConcurrency: this.xmux.maxConcurrency,
maxConnections: this.xmux.maxConnections,
cMaxReuseTimes: this.xmux.cMaxReuseTimes,
cMaxLifetimeMs: this.xmux.cMaxLifetimeMs
},
mode: this.mode, mode: this.mode,
noGRPCHeader: this.noGRPCHeader
}; };
} }
} }
@@ -745,7 +689,10 @@ TlsStreamSettings.Cert = class extends XrayCommonClass {
}; };
TlsStreamSettings.Settings = class extends XrayCommonClass { TlsStreamSettings.Settings = class extends XrayCommonClass {
constructor(allowInsecure = false, fingerprint = '') { constructor(
allowInsecure = false,
fingerprint = UTLS_FINGERPRINT.UTLS_CHROME,
) {
super(); super();
this.allowInsecure = allowInsecure; this.allowInsecure = allowInsecure;
this.fingerprint = fingerprint; this.fingerprint = fingerprint;
@@ -834,7 +781,7 @@ class RealityStreamSettings extends XrayCommonClass {
RealityStreamSettings.Settings = class extends XrayCommonClass { RealityStreamSettings.Settings = class extends XrayCommonClass {
constructor( constructor(
publicKey = '', publicKey = '',
fingerprint = UTLS_FINGERPRINT.UTLS_RANDOM, fingerprint = UTLS_FINGERPRINT.UTLS_CHROME,
serverName = '', serverName = '',
spiderX = '/' spiderX = '/'
) { ) {
@@ -953,10 +900,9 @@ class StreamSettings extends XrayCommonClass {
tcpSettings = new TcpStreamSettings(), tcpSettings = new TcpStreamSettings(),
kcpSettings = new KcpStreamSettings(), kcpSettings = new KcpStreamSettings(),
wsSettings = new WsStreamSettings(), wsSettings = new WsStreamSettings(),
httpSettings = new HttpStreamSettings(),
grpcSettings = new GrpcStreamSettings(), grpcSettings = new GrpcStreamSettings(),
httpupgradeSettings = new HTTPUpgradeStreamSettings(), httpupgradeSettings = new HTTPUpgradeStreamSettings(),
splithttpSettings = new SplitHTTPStreamSettings(), xhttpSettings = new xHTTPStreamSettings(),
sockopt = undefined, sockopt = undefined,
) { ) {
super(); super();
@@ -968,10 +914,9 @@ class StreamSettings extends XrayCommonClass {
this.tcp = tcpSettings; this.tcp = tcpSettings;
this.kcp = kcpSettings; this.kcp = kcpSettings;
this.ws = wsSettings; this.ws = wsSettings;
this.http = httpSettings;
this.grpc = grpcSettings; this.grpc = grpcSettings;
this.httpupgrade = httpupgradeSettings; this.httpupgrade = httpupgradeSettings;
this.splithttp = splithttpSettings; this.xhttp = xhttpSettings;
this.sockopt = sockopt; this.sockopt = sockopt;
} }
@@ -1018,10 +963,9 @@ class StreamSettings extends XrayCommonClass {
TcpStreamSettings.fromJson(json.tcpSettings), TcpStreamSettings.fromJson(json.tcpSettings),
KcpStreamSettings.fromJson(json.kcpSettings), KcpStreamSettings.fromJson(json.kcpSettings),
WsStreamSettings.fromJson(json.wsSettings), WsStreamSettings.fromJson(json.wsSettings),
HttpStreamSettings.fromJson(json.httpSettings),
GrpcStreamSettings.fromJson(json.grpcSettings), GrpcStreamSettings.fromJson(json.grpcSettings),
HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings), HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
SplitHTTPStreamSettings.fromJson(json.splithttpSettings), xHTTPStreamSettings.fromJson(json.xhttpSettings),
SockoptStreamSettings.fromJson(json.sockopt), SockoptStreamSettings.fromJson(json.sockopt),
); );
} }
@@ -1037,10 +981,9 @@ class StreamSettings extends XrayCommonClass {
tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined, tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined,
kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined, kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
wsSettings: network === 'ws' ? this.ws.toJson() : undefined, wsSettings: network === 'ws' ? this.ws.toJson() : undefined,
httpSettings: network === 'http' ? this.http.toJson() : undefined,
grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined, grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined, httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
splithttpSettings: network === 'splithttp' ? this.splithttp.toJson() : undefined, xhttpSettings: network === 'xhttp' ? this.xhttp.toJson() : undefined,
sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined, sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined,
}; };
} }
@@ -1169,16 +1112,12 @@ class Inbound extends XrayCommonClass {
return this.network === "grpc"; return this.network === "grpc";
} }
get isH2() {
return this.network === "http";
}
get isHttpupgrade() { get isHttpupgrade() {
return this.network === "httpupgrade"; return this.network === "httpupgrade";
} }
get isSplithttp() { get isXHTTP() {
return this.network === "splithttp"; return this.network === "xhttp";
} }
// Shadowsocks // Shadowsocks
@@ -1217,12 +1156,10 @@ class Inbound extends XrayCommonClass {
return this.getHeader(this.stream.tcp.request, 'host'); return this.getHeader(this.stream.tcp.request, 'host');
} else if (this.isWs) { } else if (this.isWs) {
return this.stream.ws.host?.length > 0 ? this.stream.ws.host : this.getHeader(this.stream.ws, 'host'); return this.stream.ws.host?.length > 0 ? this.stream.ws.host : this.getHeader(this.stream.ws, 'host');
} else if (this.isH2) {
return this.stream.http.host[0];
} else if (this.isHttpupgrade) { } else if (this.isHttpupgrade) {
return this.stream.httpupgrade.host?.length > 0 ? this.stream.httpupgrade.host : this.getHeader(this.stream.httpupgrade, 'host'); return this.stream.httpupgrade.host?.length > 0 ? this.stream.httpupgrade.host : this.getHeader(this.stream.httpupgrade, 'host');
} else if (this.isSplithttp) { } else if (this.isXHTTP) {
return this.stream.splithttp.host?.length > 0 ? this.stream.splithttp.host : this.getHeader(this.stream.splithttp, 'host'); return this.stream.xhttp.host?.length > 0 ? this.stream.xhttp.host : this.getHeader(this.stream.xhttp, 'host');
} }
return null; return null;
} }
@@ -1232,12 +1169,10 @@ class Inbound extends XrayCommonClass {
return this.stream.tcp.request.path[0]; return this.stream.tcp.request.path[0];
} else if (this.isWs) { } else if (this.isWs) {
return this.stream.ws.path; return this.stream.ws.path;
} else if (this.isH2) {
return this.stream.http.path;
} else if (this.isHttpupgrade) { } else if (this.isHttpupgrade) {
return this.stream.httpupgrade.path; return this.stream.httpupgrade.path;
} else if (this.isSplithttp) { } else if (this.isXHTTP) {
return this.stream.splithttp.path; return this.stream.xhttp.path;
} }
return null; return null;
} }
@@ -1261,7 +1196,7 @@ class Inbound extends XrayCommonClass {
canEnableTls() { canEnableTls() {
if (![Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol)) return false; if (![Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol)) return false;
return ["tcp", "ws", "http", "grpc", "httpupgrade", "splithttp"].includes(this.network); return ["tcp", "ws", "http", "grpc", "httpupgrade", "xhttp"].includes(this.network);
} }
//this is used for xtls-rprx-vision //this is used for xtls-rprx-vision
@@ -1274,7 +1209,7 @@ class Inbound extends XrayCommonClass {
canEnableReality() { canEnableReality() {
if (![Protocols.VLESS, Protocols.TROJAN].includes(this.protocol)) return false; if (![Protocols.VLESS, Protocols.TROJAN].includes(this.protocol)) return false;
return ["tcp", "http", "grpc", "splithttp"].includes(this.network); return ["tcp", "http", "grpc", "xhttp"].includes(this.network);
} }
canEnableStream() { canEnableStream() {
@@ -1326,10 +1261,6 @@ class Inbound extends XrayCommonClass {
const ws = this.stream.ws; const ws = this.stream.ws;
obj.path = ws.path; obj.path = ws.path;
obj.host = ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host'); obj.host = ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host');
} else if (network === 'http') {
obj.net = 'h2';
obj.path = this.stream.http.path;
obj.host = this.stream.http.host.join(',');
} else if (network === 'grpc') { } else if (network === 'grpc') {
obj.path = this.stream.grpc.serviceName; obj.path = this.stream.grpc.serviceName;
obj.authority = this.stream.grpc.authority; obj.authority = this.stream.grpc.authority;
@@ -1340,14 +1271,14 @@ class Inbound extends XrayCommonClass {
const httpupgrade = this.stream.httpupgrade; const httpupgrade = this.stream.httpupgrade;
obj.path = httpupgrade.path; obj.path = httpupgrade.path;
obj.host = httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host'); obj.host = httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host');
} else if (network === 'splithttp') { } else if (network === 'xhttp') {
const splithttp = this.stream.splithttp; const xhttp = this.stream.xhttp;
obj.path = splithttp.path; obj.path = xhttp.path;
obj.host = splithttp.host?.length > 0 ? splithttp.host : this.getHeader(splithttp, 'host'); obj.host = xhttp.host?.length > 0 ? xhttp.host : this.getHeader(xhttp, 'host');
obj.mode = splithttp.mode; obj.mode = xhttp.mode;
} }
if (security === 'tls') { if (tls === 'tls') {
if (!ObjectUtil.isEmpty(this.stream.tls.sni)) { if (!ObjectUtil.isEmpty(this.stream.tls.sni)) {
obj.sni = this.stream.tls.sni; obj.sni = this.stream.tls.sni;
} }
@@ -1395,11 +1326,6 @@ class Inbound extends XrayCommonClass {
params.set("path", ws.path); params.set("path", ws.path);
params.set("host", ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host')); params.set("host", ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host'));
break; break;
case "http":
const http = this.stream.http;
params.set("path", http.path);
params.set("host", http.host);
break;
case "grpc": case "grpc":
const grpc = this.stream.grpc; const grpc = this.stream.grpc;
params.set("serviceName", grpc.serviceName); params.set("serviceName", grpc.serviceName);
@@ -1413,11 +1339,11 @@ class Inbound extends XrayCommonClass {
params.set("path", httpupgrade.path); params.set("path", httpupgrade.path);
params.set("host", httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host')); params.set("host", httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host'));
break; break;
case "splithttp": case "xhttp":
const splithttp = this.stream.splithttp; const xhttp = this.stream.xhttp;
params.set("path", splithttp.path); params.set("path", xhttp.path);
params.set("host", splithttp.host?.length > 0 ? splithttp.host : this.getHeader(splithttp, 'host')); params.set("host", xhttp.host?.length > 0 ? xhttp.host : this.getHeader(xhttp, 'host'));
params.set("mode", splithttp.mode); params.set("mode", xhttp.mode);
break; break;
} }
@@ -1499,11 +1425,6 @@ class Inbound extends XrayCommonClass {
params.set("path", ws.path); params.set("path", ws.path);
params.set("host", ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host')); params.set("host", ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host'));
break; break;
case "http":
const http = this.stream.http;
params.set("path", http.path);
params.set("host", http.host);
break;
case "grpc": case "grpc":
const grpc = this.stream.grpc; const grpc = this.stream.grpc;
params.set("serviceName", grpc.serviceName); params.set("serviceName", grpc.serviceName);
@@ -1517,11 +1438,11 @@ class Inbound extends XrayCommonClass {
params.set("path", httpupgrade.path); params.set("path", httpupgrade.path);
params.set("host", httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host')); params.set("host", httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host'));
break; break;
case "splithttp": case "xhttp":
const splithttp = this.stream.splithttp; const xhttp = this.stream.xhttp;
params.set("path", splithttp.path); params.set("path", xhttp.path);
params.set("host", splithttp.host?.length > 0 ? splithttp.host : this.getHeader(splithttp, 'host')); params.set("host", xhttp.host?.length > 0 ? xhttp.host : this.getHeader(xhttp, 'host'));
params.set("mode", splithttp.mode); params.set("mode", xhttp.mode);
break; break;
} }
@@ -1582,11 +1503,6 @@ class Inbound extends XrayCommonClass {
params.set("path", ws.path); params.set("path", ws.path);
params.set("host", ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host')); params.set("host", ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host'));
break; break;
case "http":
const http = this.stream.http;
params.set("path", http.path);
params.set("host", http.host);
break;
case "grpc": case "grpc":
const grpc = this.stream.grpc; const grpc = this.stream.grpc;
params.set("serviceName", grpc.serviceName); params.set("serviceName", grpc.serviceName);
@@ -1600,11 +1516,11 @@ class Inbound extends XrayCommonClass {
params.set("path", httpupgrade.path); params.set("path", httpupgrade.path);
params.set("host", httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host')); params.set("host", httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host'));
break; break;
case "splithttp": case "xhttp":
const splithttp = this.stream.splithttp; const xhttp = this.stream.xhttp;
params.set("path", splithttp.path); params.set("path", xhttp.path);
params.set("host", splithttp.host?.length > 0 ? splithttp.host : this.getHeader(splithttp, 'host')); params.set("host", xhttp.host?.length > 0 ? xhttp.host : this.getHeader(xhttp, 'host'));
params.set("mode", splithttp.mode); params.set("mode", xhttp.mode);
break; break;
} }
@@ -1862,6 +1778,7 @@ Inbound.VmessSettings.VMESS = class extends XrayCommonClass {
enable = true, enable = true,
tgId = '', tgId = '',
subId = RandomUtil.randomLowerAndNum(16), subId = RandomUtil.randomLowerAndNum(16),
comment = '',
reset = 0 reset = 0
) { ) {
super(); super();
@@ -1874,6 +1791,7 @@ Inbound.VmessSettings.VMESS = class extends XrayCommonClass {
this.enable = enable; this.enable = enable;
this.tgId = tgId; this.tgId = tgId;
this.subId = subId; this.subId = subId;
this.comment = comment;
this.reset = reset; this.reset = reset;
} }
@@ -1888,6 +1806,7 @@ Inbound.VmessSettings.VMESS = class extends XrayCommonClass {
json.enable, json.enable,
json.tgId, json.tgId,
json.subId, json.subId,
json.comment,
json.reset, json.reset,
); );
} }
@@ -1968,6 +1887,7 @@ Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
enable = true, enable = true,
tgId = '', tgId = '',
subId = RandomUtil.randomLowerAndNum(16), subId = RandomUtil.randomLowerAndNum(16),
comment = '',
reset = 0 reset = 0
) { ) {
super(); super();
@@ -1980,6 +1900,7 @@ Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
this.enable = enable; this.enable = enable;
this.tgId = tgId; this.tgId = tgId;
this.subId = subId; this.subId = subId;
this.comment = comment;
this.reset = reset; this.reset = reset;
} }
@@ -1994,6 +1915,7 @@ Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
json.enable, json.enable,
json.tgId, json.tgId,
json.subId, json.subId,
json.comment,
json.reset, json.reset,
); );
} }
@@ -2104,6 +2026,7 @@ Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
enable = true, enable = true,
tgId = '', tgId = '',
subId = RandomUtil.randomLowerAndNum(16), subId = RandomUtil.randomLowerAndNum(16),
comment = '',
reset = 0 reset = 0
) { ) {
super(); super();
@@ -2115,6 +2038,7 @@ Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
this.enable = enable; this.enable = enable;
this.tgId = tgId; this.tgId = tgId;
this.subId = subId; this.subId = subId;
this.comment = comment;
this.reset = reset; this.reset = reset;
} }
@@ -2128,6 +2052,7 @@ Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
enable: this.enable, enable: this.enable,
tgId: this.tgId, tgId: this.tgId,
subId: this.subId, subId: this.subId,
comment: this.comment,
reset: this.reset, reset: this.reset,
}; };
} }
@@ -2142,6 +2067,7 @@ Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
json.enable, json.enable,
json.tgId, json.tgId,
json.subId, json.subId,
json.comment,
json.reset, json.reset,
); );
} }
@@ -2261,6 +2187,7 @@ Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass {
enable = true, enable = true,
tgId = '', tgId = '',
subId = RandomUtil.randomLowerAndNum(16), subId = RandomUtil.randomLowerAndNum(16),
comment = '',
reset = 0 reset = 0
) { ) {
super(); super();
@@ -2273,6 +2200,7 @@ Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass {
this.enable = enable; this.enable = enable;
this.tgId = tgId; this.tgId = tgId;
this.subId = subId; this.subId = subId;
this.comment = comment;
this.reset = reset; this.reset = reset;
} }
@@ -2287,6 +2215,7 @@ Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass {
enable: this.enable, enable: this.enable,
tgId: this.tgId, tgId: this.tgId,
subId: this.subId, subId: this.subId,
comment: this.comment,
reset: this.reset, reset: this.reset,
}; };
} }
@@ -2302,6 +2231,7 @@ Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass {
json.enable, json.enable,
json.tgId, json.tgId,
json.subId, json.subId,
json.comment,
json.reset, json.reset,
); );
} }

View File

@@ -39,6 +39,7 @@ const UTLS_FINGERPRINT = {
UTLS_QQ: "qq", UTLS_QQ: "qq",
UTLS_RANDOM: "random", UTLS_RANDOM: "random",
UTLS_RANDOMIZED: "randomized", UTLS_RANDOMIZED: "randomized",
UTLS_UNSAFE: "unsafe",
}; };
const ALPN_OPTION = { const ALPN_OPTION = {
@@ -81,6 +82,7 @@ const MODE_OPTION = {
AUTO: "auto", AUTO: "auto",
PACKET_UP: "packet-up", PACKET_UP: "packet-up",
STREAM_UP: "stream-up", STREAM_UP: "stream-up",
STREAM_ONE: "stream-one",
}; };
Object.freeze(Protocols); Object.freeze(Protocols);
@@ -205,16 +207,23 @@ class KcpStreamSettings extends CommonClass {
} }
class WsStreamSettings extends CommonClass { class WsStreamSettings extends CommonClass {
constructor(path = '/', host = '') { constructor(
path = '/',
host = '',
heartbeatPeriod = 0,
) {
super(); super();
this.path = path; this.path = path;
this.host = host; this.host = host;
this.heartbeatPeriod = heartbeatPeriod;
} }
static fromJson(json = {}) { static fromJson(json = {}) {
return new WsStreamSettings( return new WsStreamSettings(
json.path, json.path,
json.host, json.host,
json.heartbeatPeriod,
); );
} }
@@ -222,63 +231,11 @@ class WsStreamSettings extends CommonClass {
return { return {
path: this.path, path: this.path,
host: this.host, host: this.host,
heartbeatPeriod: this.heartbeatPeriod
}; };
} }
} }
class HttpStreamSettings extends CommonClass {
constructor(path = '/', host = '') {
super();
this.path = path;
this.host = host;
}
static fromJson(json = {}) {
return new HttpStreamSettings(
json.path,
json.host ? json.host.join(',') : '',
);
}
toJson() {
return {
path: this.path,
host: ObjectUtil.isEmpty(this.host) ? [''] : this.host.split(','),
}
}
}
class QuicStreamSettings extends CommonClass {
constructor(
security = 'none',
key = '',
type = 'none'
) {
super();
this.security = security;
this.key = key;
this.type = type;
}
static fromJson(json = {}) {
return new QuicStreamSettings(
json.security,
json.key,
json.header ? json.header.type : 'none',
);
}
toJson() {
return {
security: this.security,
key: this.key,
header: {
type: this.type,
}
}
}
}
class GrpcStreamSettings extends CommonClass { class GrpcStreamSettings extends CommonClass {
constructor( constructor(
serviceName = "", serviceName = "",
@@ -326,23 +283,39 @@ class HttpUpgradeStreamSettings extends CommonClass {
} }
} }
class SplitHTTPStreamSettings extends CommonClass { class xHTTPStreamSettings extends CommonClass {
constructor( constructor(
path = '/', path = '/',
host = '', host = '',
mode = '', mode = '',
noGRPCHeader = false,
scMinPostsIntervalMs = "30",
xmux = {
maxConcurrency: "16-32",
maxConnections: 0,
cMaxReuseTimes: "64-128",
cMaxLifetimeMs: 0,
hMaxRequestTimes: "800-900",
hKeepAlivePeriod: 0,
},
) { ) {
super(); super();
this.path = path; this.path = path;
this.host = host; this.host = host;
this.mode = mode; this.mode = mode;
this.noGRPCHeader = noGRPCHeader;
this.scMinPostsIntervalMs = scMinPostsIntervalMs;
this.xmux = xmux;
} }
static fromJson(json = {}) { static fromJson(json = {}) {
return new SplitHTTPStreamSettings( return new xHTTPStreamSettings(
json.path, json.path,
json.host, json.host,
json.mode, json.mode,
json.noGRPCHeader,
json.scMinPostsIntervalMs,
json.xmux
); );
} }
@@ -351,6 +324,16 @@ class SplitHTTPStreamSettings extends CommonClass {
path: this.path, path: this.path,
host: this.host, host: this.host,
mode: this.mode, mode: this.mode,
noGRPCHeader: this.noGRPCHeader,
scMinPostsIntervalMs: this.scMinPostsIntervalMs,
xmux: {
maxConcurrency: this.xmux.maxConcurrency,
maxConnections: this.xmux.maxConnections,
cMaxReuseTimes: this.xmux.cMaxReuseTimes,
cMaxLifetimeMs: this.xmux.cMaxLifetimeMs,
hMaxRequestTimes: this.xmux.hMaxRequestTimes,
hKeepAlivePeriod: this.xmux.hKeepAlivePeriod,
},
}; };
} }
} }
@@ -469,11 +452,9 @@ class StreamSettings extends CommonClass {
tcpSettings = new TcpStreamSettings(), tcpSettings = new TcpStreamSettings(),
kcpSettings = new KcpStreamSettings(), kcpSettings = new KcpStreamSettings(),
wsSettings = new WsStreamSettings(), wsSettings = new WsStreamSettings(),
httpSettings = new HttpStreamSettings(),
quicSettings = new QuicStreamSettings(),
grpcSettings = new GrpcStreamSettings(), grpcSettings = new GrpcStreamSettings(),
httpupgradeSettings = new HttpUpgradeStreamSettings(), httpupgradeSettings = new HttpUpgradeStreamSettings(),
splithttpSettings = new SplitHTTPStreamSettings(), xhttpSettings = new xHTTPStreamSettings(),
sockopt = undefined, sockopt = undefined,
) { ) {
super(); super();
@@ -484,10 +465,9 @@ class StreamSettings extends CommonClass {
this.tcp = tcpSettings; this.tcp = tcpSettings;
this.kcp = kcpSettings; this.kcp = kcpSettings;
this.ws = wsSettings; this.ws = wsSettings;
this.http = httpSettings;
this.grpc = grpcSettings; this.grpc = grpcSettings;
this.httpupgrade = httpupgradeSettings; this.httpupgrade = httpupgradeSettings;
this.splithttp = splithttpSettings; this.xhttp = xhttpSettings;
this.sockopt = sockopt; this.sockopt = sockopt;
} }
@@ -516,11 +496,9 @@ class StreamSettings extends CommonClass {
TcpStreamSettings.fromJson(json.tcpSettings), TcpStreamSettings.fromJson(json.tcpSettings),
KcpStreamSettings.fromJson(json.kcpSettings), KcpStreamSettings.fromJson(json.kcpSettings),
WsStreamSettings.fromJson(json.wsSettings), WsStreamSettings.fromJson(json.wsSettings),
HttpStreamSettings.fromJson(json.httpSettings),
QuicStreamSettings.fromJson(json.quicSettings),
GrpcStreamSettings.fromJson(json.grpcSettings), GrpcStreamSettings.fromJson(json.grpcSettings),
HttpUpgradeStreamSettings.fromJson(json.httpupgradeSettings), HttpUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
SplitHTTPStreamSettings.fromJson(json.splithttpSettings), xHTTPStreamSettings.fromJson(json.xhttpSettings),
SockoptStreamSettings.fromJson(json.sockopt), SockoptStreamSettings.fromJson(json.sockopt),
); );
} }
@@ -535,10 +513,9 @@ class StreamSettings extends CommonClass {
tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined, tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined,
kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined, kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
wsSettings: network === 'ws' ? this.ws.toJson() : undefined, wsSettings: network === 'ws' ? this.ws.toJson() : undefined,
httpSettings: network === 'http' ? this.http.toJson() : undefined,
grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined, grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined, httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
splithttpSettings: network === 'splithttp' ? this.splithttp.toJson() : undefined, xhttpSettings: network === 'xhttp' ? this.xhttp.toJson() : undefined,
sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined, sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined,
}; };
} }
@@ -576,7 +553,7 @@ class Mux extends CommonClass {
class Outbound extends CommonClass { class Outbound extends CommonClass {
constructor( constructor(
tag = '', tag = '',
protocol = Protocols.VMess, protocol = Protocols.VLESS,
settings = null, settings = null,
streamSettings = new StreamSettings(), streamSettings = new StreamSettings(),
sendThrough, sendThrough,
@@ -603,7 +580,7 @@ class Outbound extends CommonClass {
canEnableTls() { canEnableTls() {
if (![Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks].includes(this.protocol)) return false; if (![Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks].includes(this.protocol)) return false;
return ["tcp", "ws", "http", "grpc", "httpupgrade", "splithttp"].includes(this.stream.network); return ["tcp", "ws", "http", "grpc", "httpupgrade", "xhttp"].includes(this.stream.network);
} }
//this is used for xtls-rprx-vision //this is used for xtls-rprx-vision
@@ -616,7 +593,7 @@ class Outbound extends CommonClass {
canEnableReality() { canEnableReality() {
if (![Protocols.VLESS, Protocols.Trojan].includes(this.protocol)) return false; if (![Protocols.VLESS, Protocols.Trojan].includes(this.protocol)) return false;
return ["tcp", "http", "grpc", "splithttp"].includes(this.stream.network); return ["tcp", "http", "grpc", "xhttp"].includes(this.stream.network);
} }
canEnableStream() { canEnableStream() {
@@ -714,17 +691,12 @@ class Outbound extends CommonClass {
stream.seed = json.path; stream.seed = json.path;
} else if (network === 'ws') { } else if (network === 'ws') {
stream.ws = new WsStreamSettings(json.path, json.host); stream.ws = new WsStreamSettings(json.path, json.host);
} else if (network === 'http' || network == 'h2') {
stream.network = 'http'
stream.http = new HttpStreamSettings(
json.path,
json.host);
} else if (network === 'grpc') { } else if (network === 'grpc') {
stream.grpc = new GrpcStreamSettings(json.path, json.authority, json.type == 'multi'); stream.grpc = new GrpcStreamSettings(json.path, json.authority, json.type == 'multi');
} else if (network === 'httpupgrade') { } else if (network === 'httpupgrade') {
stream.httpupgrade = new HttpUpgradeStreamSettings(json.path, json.host); stream.httpupgrade = new HttpUpgradeStreamSettings(json.path, json.host);
} else if (network === 'splithttp') { } else if (network === 'xhttp') {
stream.splithttp = new SplitHTTPStreamSettings(json.path, json.host, json.mode); stream.xhttp = new xHTTPStreamSettings(json.path, json.host, json.mode);
} }
if (json.tls && json.tls == 'tls') { if (json.tls && json.tls == 'tls') {
@@ -749,6 +721,7 @@ class Outbound extends CommonClass {
let headerType = url.searchParams.get('headerType') ?? undefined; let headerType = url.searchParams.get('headerType') ?? undefined;
let host = url.searchParams.get('host') ?? undefined; let host = url.searchParams.get('host') ?? undefined;
let path = url.searchParams.get('path') ?? undefined; let path = url.searchParams.get('path') ?? undefined;
let mode = url.searchParams.get('mode') ?? undefined;
if (type === 'tcp' || type === 'none') { if (type === 'tcp' || type === 'none') {
stream.tcp = new TcpStreamSettings(headerType ?? 'none', host, path); stream.tcp = new TcpStreamSettings(headerType ?? 'none', host, path);
@@ -758,8 +731,6 @@ class Outbound extends CommonClass {
stream.kcp.seed = path; stream.kcp.seed = path;
} else if (type === 'ws') { } else if (type === 'ws') {
stream.ws = new WsStreamSettings(path, host); stream.ws = new WsStreamSettings(path, host);
} else if (type === 'http' || type == 'h2') {
stream.http = new HttpStreamSettings(path, host);
} else if (type === 'grpc') { } else if (type === 'grpc') {
stream.grpc = new GrpcStreamSettings( stream.grpc = new GrpcStreamSettings(
url.searchParams.get('serviceName') ?? '', url.searchParams.get('serviceName') ?? '',
@@ -767,8 +738,8 @@ class Outbound extends CommonClass {
url.searchParams.get('mode') == 'multi'); url.searchParams.get('mode') == 'multi');
} else if (type === 'httpupgrade') { } else if (type === 'httpupgrade') {
stream.httpupgrade = new HttpUpgradeStreamSettings(path, host); stream.httpupgrade = new HttpUpgradeStreamSettings(path, host);
} else if (type === 'splithttp') { } else if (type === 'xhttp') {
stream.splithttp = new SplitHTTPStreamSettings(path, host, mode); stream.xhttp = new xHTTPStreamSettings(path, host, mode);
} }
if (security == 'tls') { if (security == 'tls') {

File diff suppressed because one or more lines are too long

View File

@@ -9,6 +9,7 @@ import (
"x-ui/web/service" "x-ui/web/service"
"x-ui/web/session" "x-ui/web/session"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@@ -49,8 +50,8 @@ func (a *IndexController) index(c *gin.Context) {
func (a *IndexController) login(c *gin.Context) { func (a *IndexController) login(c *gin.Context) {
var form LoginForm var form LoginForm
err := c.ShouldBind(&form)
if err != nil { if err := c.ShouldBind(&form); err != nil {
pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.invalidFormData")) pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.invalidFormData"))
return return
} }
@@ -68,29 +69,31 @@ func (a *IndexController) login(c *gin.Context) {
safeUser := template.HTMLEscapeString(form.Username) safeUser := template.HTMLEscapeString(form.Username)
safePass := template.HTMLEscapeString(form.Password) safePass := template.HTMLEscapeString(form.Password)
safeSecret := template.HTMLEscapeString(form.LoginSecret) safeSecret := template.HTMLEscapeString(form.LoginSecret)
if user == nil { if user == nil {
logger.Warningf("wrong username or password or secret: \"%s\" \"%s\" \"%s\"", safeUser, safePass, safeSecret) logger.Warningf("wrong username: \"%s\", password: \"%s\", secret: \"%s\", IP: \"%s\"", safeUser, safePass, safeSecret, getRemoteIp(c))
a.tgbot.UserLoginNotify(safeUser, safePass, getRemoteIp(c), timeStr, 0) a.tgbot.UserLoginNotify(safeUser, safePass, getRemoteIp(c), timeStr, 0)
pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.wrongUsernameOrPassword")) pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.wrongUsernameOrPassword"))
return return
} else {
logger.Infof("%s logged in successfully, Ip Address: %s\n", safeUser, getRemoteIp(c))
a.tgbot.UserLoginNotify(safeUser, ``, getRemoteIp(c), timeStr, 1)
} }
logger.Infof("%s logged in successfully, Ip Address: %s\n", safeUser, getRemoteIp(c))
a.tgbot.UserLoginNotify(safeUser, ``, getRemoteIp(c), timeStr, 1)
sessionMaxAge, err := a.settingService.GetSessionMaxAge() sessionMaxAge, err := a.settingService.GetSessionMaxAge()
if err != nil { if err != nil {
logger.Warning("Unable to get session's max age from DB") logger.Warning("Unable to get session's max age from DB")
} }
err = session.SetMaxAge(c, sessionMaxAge*60) session.SetMaxAge(c, sessionMaxAge*60)
if err != nil { session.SetLoginUser(c, user)
logger.Warning("Unable to set session's max age") if err := sessions.Default(c).Save(); err != nil {
logger.Warning("Unable to save session: ", err)
return
} }
err = session.SetLoginUser(c, user) logger.Infof("%s logged in successfully", safeUser)
logger.Infof("%s logged in successfully", user.Username) jsonMsg(c, I18nWeb(c, "pages.login.toasts.successLogin"), nil)
jsonMsg(c, I18nWeb(c, "pages.login.toasts.successLogin"), err)
} }
func (a *IndexController) logout(c *gin.Context) { func (a *IndexController) logout(c *gin.Context) {
@@ -99,6 +102,9 @@ func (a *IndexController) logout(c *gin.Context) {
logger.Infof("%s logged out successfully", user.Username) logger.Infof("%s logged out successfully", user.Username)
} }
session.ClearSession(c) session.ClearSession(c)
if err := sessions.Default(c).Save(); err != nil {
logger.Warning("Unable to save session after clearing:", err)
}
c.Redirect(http.StatusTemporaryRedirect, c.GetString("base_path")) c.Redirect(http.StatusTemporaryRedirect, c.GetString("base_path"))
} }

View File

@@ -68,6 +68,9 @@
</template> </template>
<a-input-number style="width: 50%" v-model="client.tgId" min="0"></a-input-number> <a-input-number style="width: 50%" v-model="client.tgId" min="0"></a-input-number>
</a-form-item> </a-form-item>
<a-form-item v-if="client.email" label='Comment'>
<a-input v-model.trim="client.comment"></a-input>
</a-form-item>
<a-form-item v-if="app.ipLimitEnable"> <a-form-item v-if="app.ipLimitEnable">
<template slot="label"> <template slot="label">
<a-tooltip> <a-tooltip>

View File

@@ -270,10 +270,9 @@
<a-select-option value="tcp">TCP (RAW)</a-select-option> <a-select-option value="tcp">TCP (RAW)</a-select-option>
<a-select-option value="kcp">mKCP</a-select-option> <a-select-option value="kcp">mKCP</a-select-option>
<a-select-option value="ws">WebSocket</a-select-option> <a-select-option value="ws">WebSocket</a-select-option>
<a-select-option value="http">HTTP</a-select-option>
<a-select-option value="grpc">gRPC</a-select-option> <a-select-option value="grpc">gRPC</a-select-option>
<a-select-option value="httpupgrade">HTTPUpgrade</a-select-option> <a-select-option value="httpupgrade">HTTPUpgrade</a-select-option>
<a-select-option value="splithttp">SplitHTTP (XHTTP)</a-select-option> <a-select-option value="xhttp">XHTTP</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<template v-if="outbound.stream.network === 'tcp'"> <template v-if="outbound.stream.network === 'tcp'">
@@ -337,15 +336,8 @@
<a-form-item label='{{ i18n "path" }}'> <a-form-item label='{{ i18n "path" }}'>
<a-input v-model.trim="outbound.stream.ws.path"></a-input> <a-input v-model.trim="outbound.stream.ws.path"></a-input>
</a-form-item> </a-form-item>
</template> <a-form-item label='Heartbeat Period'>
<a-input-number v-model.number="outbound.stream.ws.heartbeatPeriod" :min="0"></a-input-number>
<!-- http -->
<template v-if="outbound.stream.network === 'http'">
<a-form-item label='{{ i18n "host" }}'>
<a-input v-model.trim="outbound.stream.http.host"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "path" }}'>
<a-input v-model.trim="outbound.stream.http.path"></a-input>
</a-form-item> </a-form-item>
</template> </template>
@@ -372,19 +364,43 @@
</a-form-item> </a-form-item>
</template> </template>
<!-- splithttp --> <!-- xhttp -->
<template v-if="outbound.stream.network === 'splithttp'"> <template v-if="outbound.stream.network === 'xhttp'">
<a-form-item label='{{ i18n "host" }}'> <a-form-item label='{{ i18n "host" }}'>
<a-input v-model="outbound.stream.splithttp.host"></a-input> <a-input v-model="outbound.stream.xhttp.host"></a-input>
</a-form-item> </a-form-item>
<a-form-item label='{{ i18n "path" }}'> <a-form-item label='{{ i18n "path" }}'>
<a-input v-model.trim="outbound.stream.splithttp.path"></a-input> <a-input v-model.trim="outbound.stream.xhttp.path"></a-input>
</a-form-item> </a-form-item>
<a-form-item label='Mode'> <a-form-item label='Mode'>
<a-select v-model="outbound.stream.splithttp.mode" :dropdown-class-name="themeSwitcher.currentTheme"> <a-select v-model="outbound.stream.xhttp.mode" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in MODE_OPTION" :value="key">[[ key ]]</a-select-option> <a-select-option v-for="key in MODE_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item label="No gRPC Header" v-if="outbound.stream.xhttp.mode === 'stream-up' || outbound.stream.xhttp.mode === 'stream-one'">
<a-switch v-model="outbound.stream.xhttp.noGRPCHeader"></a-switch>
</a-form-item>
<a-form-item label="Min Upload Interval (Ms)" v-if="outbound.stream.xhttp.mode === 'packet-up'">
<a-input v-model.trim="outbound.stream.xhttp.scMinPostsIntervalMs"></a-input>
</a-form-item>
<a-form-item label="Max Concurrency" v-if="!outbound.stream.xhttp.xmux.maxConnections">
<a-input v-model="outbound.stream.xhttp.xmux.maxConcurrency"></a-input>
</a-form-item>
<a-form-item label="Max Connections" v-if="!outbound.stream.xhttp.xmux.maxConcurrency">
<a-input v-model="outbound.stream.xhttp.xmux.maxConnections"></a-input>
</a-form-item>
<a-form-item label="Max Reuse Times">
<a-input v-model="outbound.stream.xhttp.xmux.cMaxReuseTimes"></a-input>
</a-form-item>
<a-form-item label="Max Lifetime (ms)">
<a-input v-model="outbound.stream.xhttp.xmux.cMaxLifetimeMs"></a-input>
</a-form-item>
<a-form-item label="Max Request Times">
<a-input v-model="outbound.stream.xhttp.xmux.hMaxRequestTimes"></a-input>
</a-form-item>
<a-form-item label='Keep Alive Period'>
<a-input v-model.number="outbound.stream.xhttp.xmux.hKeepAlivePeriod"></a-input>
</a-form-item>
</template> </template>
</template> </template>

View File

@@ -1,17 +0,0 @@
{{define "form/streamHTTP"}}
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
<a-form-item label='{{ i18n "path" }}'>
<a-input v-model.trim="inbound.stream.http.path"></a-input>
</a-form-item>
<a-form-item>
<template slot="label">{{ i18n "host" }}
<a-button icon="plus" size="small" @click="inbound.stream.http.addHost()"></a-button>
</template>
<template v-for="(host, index) in inbound.stream.http.host">
<a-input v-model.trim="inbound.stream.http.host[index]">
<a-button icon="minus" size="small" slot="addonAfter" @click="inbound.stream.http.removeHost(index)" v-if="inbound.stream.http.host.length>1"></a-button>
</a-input>
</template>
</a-form-item>
</a-form>
{{end}}

View File

@@ -7,10 +7,9 @@
<a-select-option value="tcp">TCP (RAW)</a-select-option> <a-select-option value="tcp">TCP (RAW)</a-select-option>
<a-select-option value="kcp">mKCP</a-select-option> <a-select-option value="kcp">mKCP</a-select-option>
<a-select-option value="ws">WebSocket</a-select-option> <a-select-option value="ws">WebSocket</a-select-option>
<a-select-option value="http">HTTP</a-select-option>
<a-select-option value="grpc">gRPC</a-select-option> <a-select-option value="grpc">gRPC</a-select-option>
<a-select-option value="httpupgrade">HTTPUpgrade</a-select-option> <a-select-option value="httpupgrade">HTTPUpgrade</a-select-option>
<a-select-option value="splithttp">SplitHTTP (XHTTP)</a-select-option> <a-select-option value="xhttp">XHTTP</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-form> </a-form>
@@ -30,11 +29,6 @@
{{template "form/streamWS"}} {{template "form/streamWS"}}
</template> </template>
<!-- http -->
<template v-if="inbound.stream.network === 'http'">
{{template "form/streamHTTP"}}
</template>
<!-- grpc --> <!-- grpc -->
<template v-if="inbound.stream.network === 'grpc'"> <template v-if="inbound.stream.network === 'grpc'">
{{template "form/streamGRPC"}} {{template "form/streamGRPC"}}
@@ -45,9 +39,9 @@
{{template "form/streamHTTPUpgrade"}} {{template "form/streamHTTPUpgrade"}}
</template> </template>
<!-- splithttp --> <!-- xhttp -->
<template v-if="inbound.stream.network === 'splithttp'"> <template v-if="inbound.stream.network === 'xhttp'">
{{template "form/streamSplitHTTP"}} {{template "form/streamXHTTP"}}
</template> </template>
<!-- sockopt --> <!-- sockopt -->

View File

@@ -1,62 +0,0 @@
{{define "form/streamSplitHTTP"}}
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
<a-form-item label='{{ i18n "host" }}'>
<a-input v-model.trim="inbound.stream.splithttp.host"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "path" }}'>
<a-input v-model.trim="inbound.stream.splithttp.path"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'>
<a-button icon="plus" size="small" @click="inbound.stream.splithttp.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.splithttp.headers">
<a-input style="width: 50%" v-model.trim="header.name"
placeholder='{{ i18n "pages.inbounds.stream.general.name"}}'>
<template slot="addonBefore" style="margin: 0;">[[ index+1 ]]</template>
</a-input>
<a-input style="width: 50%" v-model.trim="header.value"
placeholder='{{ i18n "pages.inbounds.stream.general.value" }}'>
<a-button slot="addonAfter" size="small"
@click="inbound.stream.splithttp.removeHeader(index)">-</a-button>
</a-input>
</a-input-group>
</a-form-item>
<a-form-item label='Mode'>
<a-select v-model="inbound.stream.splithttp.mode" style="width: 50%"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in MODE_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="Max Concurrent Upload">
<a-input v-model.trim="inbound.stream.splithttp.scMaxConcurrentPosts"></a-input>
</a-form-item>
<a-form-item label="Max Upload Size (Byte)">
<a-input v-model.trim="inbound.stream.splithttp.scMaxEachPostBytes"></a-input>
</a-form-item>
<a-form-item label="Min Upload Interval (Ms)">
<a-input v-model.trim="inbound.stream.splithttp.scMinPostsIntervalMs"></a-input>
</a-form-item>
<a-form-item label="Padding Bytes">
<a-input v-model.trim="inbound.stream.splithttp.xPaddingBytes"></a-input>
</a-form-item>
<a-form-item label="No SSE Header">
<a-switch v-model="inbound.stream.splithttp.noSSEHeader"></a-switch>
</a-form-item>
<a-form-item label="Max Concurrency" v-if="!inbound.stream.splithttp.xmux.maxConnections">
<a-input v-model="inbound.stream.splithttp.xmux.maxConcurrency"></a-input>
</a-form-item>
<a-form-item label="Max Connections" v-if="!inbound.stream.splithttp.xmux.maxConcurrency">
<a-input v-model="inbound.stream.splithttp.xmux.maxConnections"></a-input>
</a-form-item>
<a-form-item label="Max Reuse Times">
<a-input v-model="inbound.stream.splithttp.xmux.cMaxReuseTimes"></a-input>
</a-form-item>
<a-form-item label="Max Lifetime (ms)">
<a-input v-model="inbound.stream.splithttp.xmux.cMaxLifetimeMs"></a-input>
</a-form-item>
<a-form-item label="No gRPC Header">
<a-switch v-model="inbound.stream.splithttp.noGRPCHeader"></a-switch>
</a-form-item>
</a-form>
{{end}}

View File

@@ -9,8 +9,11 @@
<a-form-item label='{{ i18n "path" }}'> <a-form-item label='{{ i18n "path" }}'>
<a-input v-model.trim="inbound.stream.ws.path"></a-input> <a-input v-model.trim="inbound.stream.ws.path"></a-input>
</a-form-item> </a-form-item>
<a-form-item label='Heartbeat Period'>
<a-input-number v-model.number="inbound.stream.ws.heartbeatPeriod" :min="0"></a-input-number>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'> <a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'>
<a-button icon="plus" size="small" @click="inbound.stream.ws.addHeader('host', '')"></a-button> <a-button icon="plus" size="small" @click="inbound.stream.ws.addHeader('', '')"></a-button>
</a-form-item> </a-form-item>
<a-form-item :wrapper-col="{span:24}"> <a-form-item :wrapper-col="{span:24}">
<a-input-group compact v-for="(header, index) in inbound.stream.ws.headers"> <a-input-group compact v-for="(header, index) in inbound.stream.ws.headers">

View File

@@ -0,0 +1,43 @@
{{define "form/streamXHTTP"}}
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
<a-form-item label='{{ i18n "host" }}'>
<a-input v-model.trim="inbound.stream.xhttp.host"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "path" }}'>
<a-input v-model.trim="inbound.stream.xhttp.path"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'>
<a-button icon="plus" size="small" @click="inbound.stream.xhttp.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.xhttp.headers">
<a-input style="width: 50%" v-model.trim="header.name"
placeholder='{{ i18n "pages.inbounds.stream.general.name"}}'>
<template slot="addonBefore" style="margin: 0;">[[ index+1 ]]</template>
</a-input>
<a-input style="width: 50%" v-model.trim="header.value"
placeholder='{{ i18n "pages.inbounds.stream.general.value" }}'>
<a-button slot="addonAfter" size="small" @click="inbound.stream.xhttp.removeHeader(index)">-</a-button>
</a-input>
</a-input-group>
</a-form-item>
<a-form-item label='Mode'>
<a-select v-model="inbound.stream.xhttp.mode" style="width: 50%"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in MODE_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="Max Buffered Upload" v-if="inbound.stream.xhttp.mode === 'packet-up'">
<a-input v-model.trim="inbound.stream.xhttp.scMaxBufferedPosts"></a-input>
</a-form-item>
<a-form-item label="Max Upload Size (Byte)" v-if="inbound.stream.xhttp.mode === 'packet-up'">
<a-input v-model.trim="inbound.stream.xhttp.scMaxEachPostBytes"></a-input>
</a-form-item>
<a-form-item label="Padding Bytes">
<a-input v-model.trim="inbound.stream.xhttp.xPaddingBytes"></a-input>
</a-form-item>
<a-form-item label="No SSE Header">
<a-switch v-model="inbound.stream.xhttp.noSSEHeader"></a-switch>
</a-form-item>
</a-form>
{{end}}

View File

@@ -34,7 +34,7 @@
<a-tag color="green">[[ inbound.network ]]</a-tag> <a-tag color="green">[[ inbound.network ]]</a-tag>
</td> </td>
</tr> </tr>
<template v-if="inbound.isTcp || inbound.isWs || inbound.isH2 || inbound.isHttpupgrade || inbound.isSplithttp"> <template v-if="inbound.isTcp || inbound.isWs || inbound.isHttpupgrade || inbound.isXHTTP">
<tr> <tr>
<td>{{ i18n "host" }}</td> <td>{{ i18n "host" }}</td>
<td v-if="inbound.host"> <td v-if="inbound.host">
@@ -58,11 +58,11 @@
</td> </td>
</tr> </tr>
</template> </template>
<template v-if="inbound.isSplithttp"> <template v-if="inbound.isXHTTP">
<tr> <tr>
<td>Mode</td> <td>Mode</td>
<td> <td>
<a-tag>[[ inbound.stream.splithttp.mode ]]</a-tag> <a-tag>[[ inbound.stream.xhttp.mode ]]</a-tag>
</td> </td>
</tr> </tr>
</template> </template>
@@ -185,6 +185,33 @@
<a-tag>↑ [[ sizeFormat(infoModal.clientStats.up) ]] / [[ sizeFormat(infoModal.clientStats.down) ]] ↓</a-tag> <a-tag>↑ [[ sizeFormat(infoModal.clientStats.up) ]] / [[ sizeFormat(infoModal.clientStats.down) ]] ↓</a-tag>
</td> </td>
</tr> </tr>
<tr v-if="infoModal.clientSettings.comment">
<td>Comment</td>
<td>
<a-tooltip :title="[[ infoModal.clientSettings.comment ]]">
<a-tag class="info-large-tag">[[ infoModal.clientSettings.comment ]]</a-tag>
</a-tooltip>
</td>
</tr>
<tr v-if="app.ipLimitEnable">
<td>{{ i18n "pages.inbounds.IPLimit" }}</td>
<td>
<a-tag>[[ infoModal.clientSettings.limitIp ]]</a-tag>
</td>
</tr>
<tr v-if="app.ipLimitEnable">
<td>{{ i18n "pages.inbounds.IPLimitlog" }}</td>
<td>
<a-tag>[[ infoModal.clientIps ]]</a-tag>
<a-icon type="sync" :spin="refreshing" @click="refreshIPs" style="margin: 0 5px;"></a-icon>
<a-tooltip :title="[[ dbInbound.address ]]">
<template slot="title">
<span>{{ i18n "pages.inbounds.IPLimitlogclear" }}</span>
</template>
<a-icon type="delete" @click="clearClientIps"></a-icon>
</a-tooltip>
</td>
</tr>
</table> </table>
<table style="display: inline-table; margin-block: 10px; width: 100%; text-align: center;"> <table style="display: inline-table; margin-block: 10px; width: 100%; text-align: center;">
<tr> <tr>
@@ -417,6 +444,18 @@
</template> </template>
</a-modal> </a-modal>
<script> <script>
function refreshIPs(email) {
return HttpUtil.post(`/panel/inbound/clientIps/${email}`).then((msg) => {
if (msg.success) {
try {
return JSON.parse(msg.obj).join(', ');
} catch (e) {
return msg.obj;
}
}
});
}
const infoModal = { const infoModal = {
visible: false, visible: false,
inbound: new Inbound(), inbound: new Inbound(),
@@ -431,6 +470,7 @@
isExpired: false, isExpired: false,
subLink: '', subLink: '',
subJsonLink: '', subJsonLink: '',
clientIps: '',
show(dbInbound, index) { show(dbInbound, index) {
this.index = index; this.index = index;
this.inbound = dbInbound.toInbound(); this.inbound = dbInbound.toInbound();
@@ -438,6 +478,12 @@
this.clientSettings = this.inbound.clients ? this.inbound.clients[index] : null; this.clientSettings = this.inbound.clients ? this.inbound.clients[index] : null;
this.isExpired = this.inbound.clients ? this.inbound.isExpiry(index) : this.dbInbound.isExpiry; 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.clientStats = this.inbound.clients ? this.dbInbound.clientStats.find(row => row.email === this.clientSettings.email) : [];
if (app.ipLimitEnable && this.clientSettings.limitIp) {
refreshIPs(this.clientStats.email).then((ips) => {
this.clientIps = ips;
})
}
if (this.inbound.protocol == Protocols.WIREGUARD) { if (this.inbound.protocol == Protocols.WIREGUARD) {
this.links = this.inbound.genInboundLinks(dbInbound.remark).split('\r\n') this.links = this.inbound.genInboundLinks(dbInbound.remark).split('\r\n')
} else { } else {
@@ -466,6 +512,7 @@
el: '#inbound-info-modal', el: '#inbound-info-modal',
data: { data: {
infoModal, infoModal,
refreshing: false,
get dbInbound() { get dbInbound() {
return this.infoModal.dbInbound; return this.infoModal.dbInbound;
}, },
@@ -502,6 +549,26 @@
remained = this.infoModal.clientStats.total - this.infoModal.clientStats.up - this.infoModal.clientStats.down; remained = this.infoModal.clientStats.total - this.infoModal.clientStats.up - this.infoModal.clientStats.down;
return remained > 0 ? sizeFormat(remained) : '-'; return remained > 0 ? sizeFormat(remained) : '-';
}, },
refreshIPs() {
this.refreshing = true;
refreshIPs(this.infoModal.clientStats.email)
.then((ips) => {
this.infoModal.clientIps = ips;
})
.finally(() => {
this.refreshing = false;
});
},
clearClientIps() {
HttpUtil.post(`/panel/inbound/clearClientIps/${this.infoModal.clientStats.email}`)
.then((msg) => {
if (!msg.success) {
return;
}
this.infoModal.clientIps = 'No IP Record';
})
.catch(() => {});
},
}, },
}); });
</script> </script>

View File

@@ -151,13 +151,13 @@ func (j *CheckClientIpJob) processLogFile() bool {
} }
sort.Strings(ips) sort.Strings(ips)
inboundClientIps, err := j.getInboundClientIps(email) clientIpsRecord, err := j.getInboundClientIps(email)
if err != nil { if err != nil {
j.addInboundClientIps(email, ips) j.addInboundClientIps(email, ips)
continue continue
} }
shouldCleanLog = j.updateInboundClientIps(inboundClientIps, email, ips) || shouldCleanLog shouldCleanLog = j.updateInboundClientIps(clientIpsRecord, email, ips) || shouldCleanLog
} }
return shouldCleanLog return shouldCleanLog
@@ -309,12 +309,12 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun
func (j *CheckClientIpJob) getInboundByEmail(clientEmail string) (*model.Inbound, error) { func (j *CheckClientIpJob) getInboundByEmail(clientEmail string) (*model.Inbound, error) {
db := database.GetDB() db := database.GetDB()
var inbounds *model.Inbound inbound := &model.Inbound{}
err := db.Model(model.Inbound{}).Where("settings LIKE ?", "%"+clientEmail+"%").Find(&inbounds).Error err := db.Model(&model.Inbound{}).Where("settings LIKE ?", "%"+clientEmail+"%").First(inbound).Error
if err != nil { if err != nil {
return nil, err return nil, err
} }
return inbounds, nil return inbound, nil
} }

View File

@@ -286,7 +286,7 @@ func (s *ServerService) GetXrayVersions() ([]string, error) {
} }
if (major == 1 && minor == 8 && patch == 24) || if (major == 1 && minor == 8 && patch == 24) ||
(major == 24 && ((minor > 11) || (minor == 11 && patch >= 11))) || (major == 24 && ((minor > 11) || (minor == 11 && patch >= 30))) ||
(major > 24) { (major > 24) {
versions = append(versions, release.TagName) versions = append(versions, release.TagName)
} }

View File

@@ -8,6 +8,7 @@ import (
"os" "os"
"time" "time"
"x-ui/logger" "x-ui/logger"
"x-ui/util/common"
) )
type WarpService struct { type WarpService struct {
@@ -150,13 +151,23 @@ func (s *WarpService) SetWarpLicense(license string) (string, error) {
return "", err return "", err
} }
var response map[string]interface{}
err = json.Unmarshal(buffer.Bytes(), &response)
if err != nil {
return "", err
}
if response["success"] == false {
errorArr, _ := response["errors"].([]interface{})
errorObj := errorArr[0].(map[string]interface{})
return "", common.NewError(errorObj["code"], errorObj["message"])
}
warpData["license_key"] = license warpData["license_key"] = license
newWarpData, err := json.MarshalIndent(warpData, "", " ") newWarpData, err := json.MarshalIndent(warpData, "", " ")
if err != nil { if err != nil {
return "", err return "", err
} }
s.SettingService.SetWarp(string(newWarpData)) s.SettingService.SetWarp(string(newWarpData))
println(string(newWarpData))
return string(newWarpData), nil return string(newWarpData), nil
} }

View File

@@ -10,38 +10,41 @@ import (
) )
const ( const (
loginUser = "LOGIN_USER" loginUserKey = "LOGIN_USER"
defaultPath = "/" defaultPath = "/"
) )
func init() { func init() {
gob.Register(model.User{}) gob.Register(model.User{})
} }
func SetLoginUser(c *gin.Context, user *model.User) error { func SetLoginUser(c *gin.Context, user *model.User) {
if user == nil {
return
}
s := sessions.Default(c) s := sessions.Default(c)
s.Set(loginUser, user) s.Set(loginUserKey, *user)
return s.Save()
} }
func SetMaxAge(c *gin.Context, maxAge int) error { func SetMaxAge(c *gin.Context, maxAge int) {
s := sessions.Default(c) s := sessions.Default(c)
s.Options(sessions.Options{ s.Options(sessions.Options{
Path: defaultPath, Path: defaultPath,
MaxAge: maxAge, MaxAge: maxAge,
HttpOnly: true, HttpOnly: true,
}) })
return s.Save()
} }
func GetLoginUser(c *gin.Context) *model.User { func GetLoginUser(c *gin.Context) *model.User {
s := sessions.Default(c) s := sessions.Default(c)
obj := s.Get(loginUser) obj := s.Get(loginUserKey)
if obj == nil { if obj == nil {
return nil return nil
} }
user, ok := obj.(model.User) user, ok := obj.(model.User)
if !ok { if !ok {
s.Delete(loginUserKey)
return nil return nil
} }
return &user return &user
@@ -51,7 +54,7 @@ func IsLogin(c *gin.Context) bool {
return GetLoginUser(c) != nil return GetLoginUser(c) != nil
} }
func ClearSession(c *gin.Context) error { func ClearSession(c *gin.Context) {
s := sessions.Default(c) s := sessions.Default(c)
s.Clear() s.Clear()
s.Options(sessions.Options{ s.Options(sessions.Options{
@@ -59,5 +62,4 @@ func ClearSession(c *gin.Context) error {
MaxAge: -1, MaxAge: -1,
HttpOnly: true, HttpOnly: true,
}) })
return s.Save()
} }

View File

@@ -41,7 +41,7 @@
"offline" = "Офлайн" "offline" = "Офлайн"
"online" = "Онлайн" "online" = "Онлайн"
"domainName" = "Домен" "domainName" = "Домен"
"monitor" = "Порт IP" "monitor" = "Слушать IP"
"certificate" = "Цифровой сертификат" "certificate" = "Цифровой сертификат"
"fail" = "Неудачно" "fail" = "Неудачно"
"success" = "Успешно" "success" = "Успешно"

217
x-ui.sh
View File

@@ -2,6 +2,7 @@
red='\033[0;31m' red='\033[0;31m'
green='\033[0;32m' green='\033[0;32m'
blue='\033[0;34m'
yellow='\033[0;33m' yellow='\033[0;33m'
plain='\033[0m' plain='\033[0m'
@@ -682,10 +683,12 @@ show_xray_status() {
} }
firewall_menu() { firewall_menu() {
echo -e "${green}\t1.${plain} Install Firewall & open ports" echo -e "${green}\t1.${plain} Install Firewall"
echo -e "${green}\t2.${plain} Allowed List" echo -e "${green}\t2.${plain} Port List"
echo -e "${green}\t3.${plain} Delete Ports from List" echo -e "${green}\t3.${plain} Open Ports"
echo -e "${green}\t4.${plain} Disable Firewall" echo -e "${green}\t4.${plain} Delete Ports from List"
echo -e "${green}\t5.${plain} Disable Firewall"
echo -e "${green}\t6.${plain} Firewall Status"
echo -e "${green}\t0.${plain} Back to Main Menu" echo -e "${green}\t0.${plain} Back to Main Menu"
read -p "Choose an option: " choice read -p "Choose an option: " choice
case "$choice" in case "$choice" in
@@ -693,19 +696,27 @@ firewall_menu() {
show_menu show_menu
;; ;;
1) 1)
open_ports install_firewall
firewall_menu firewall_menu
;; ;;
2) 2)
sudo ufw status ufw status numbered
firewall_menu firewall_menu
;; ;;
3) 3)
delete_ports open_ports
firewall_menu firewall_menu
;; ;;
4) 4)
sudo ufw disable delete_ports
firewall_menu
;;
5)
ufw disable
firewall_menu
;;
6)
ufw status verbose
firewall_menu firewall_menu
;; ;;
*) *)
@@ -715,7 +726,7 @@ firewall_menu() {
esac esac
} }
open_ports() { install_firewall() {
if ! command -v ufw &>/dev/null; then if ! command -v ufw &>/dev/null; then
echo "ufw firewall is not installed. Installing now..." echo "ufw firewall is not installed. Installing now..."
apt-get update apt-get update
@@ -733,13 +744,16 @@ open_ports() {
ufw allow ssh ufw allow ssh
ufw allow http ufw allow http
ufw allow https ufw allow https
ufw allow 2053/tcp ufw allow 2053/tcp #webPort
ufw allow 2096/tcp #subport
# Enable the firewall # Enable the firewall
ufw --force enable ufw --force enable
fi fi
}
# Prompt the user to enter a list of ports open_ports() {
# Prompt the user to enter the ports they want to open
read -p "Enter the ports you want to open (e.g. 80,443,2053 or range 400-500): " ports read -p "Enter the ports you want to open (e.g. 80,443,2053 or range 400-500): " ports
# Check if the input is valid # Check if the input is valid
@@ -755,19 +769,28 @@ open_ports() {
# Split the range into start and end ports # Split the range into start and end ports
start_port=$(echo $port | cut -d'-' -f1) start_port=$(echo $port | cut -d'-' -f1)
end_port=$(echo $port | cut -d'-' -f2) end_port=$(echo $port | cut -d'-' -f2)
# Open the port range
ufw allow $start_port:$end_port/tcp ufw allow $start_port:$end_port/tcp
ufw allow $start_port:$end_port/udp ufw allow $start_port:$end_port/udp
else else
# Open the single port
ufw allow "$port" ufw allow "$port"
fi fi
done done
# Confirm that the ports are open # Confirm that the ports are opened
echo "The following ports are now open:" echo "Opened the specified ports:"
ufw status | grep "ALLOW" | grep -Eo "[0-9]+(/[a-z]+)?" for port in "${PORT_LIST[@]}"; do
if [[ $port == *-* ]]; then
echo "Firewall status:" start_port=$(echo $port | cut -d'-' -f1)
ufw status verbose end_port=$(echo $port | cut -d'-' -f2)
# Check if the port range has been successfully opened
(ufw status | grep -q "$start_port:$end_port") && echo "$start_port-$end_port"
else
# Check if the individual port has been successfully opened
(ufw status | grep -q "$port") && echo "$port"
fi
done
} }
delete_ports() { delete_ports() {
@@ -818,7 +841,6 @@ update_geo() {
echo -e "${green}\t0.${plain} Back to Main Menu" echo -e "${green}\t0.${plain} Back to Main Menu"
read -p "Choose an option: " choice read -p "Choose an option: " choice
systemctl stop x-ui
cd /usr/local/x-ui/bin cd /usr/local/x-ui/bin
case "$choice" in case "$choice" in
@@ -826,6 +848,7 @@ update_geo() {
show_menu show_menu
;; ;;
1) 1)
systemctl stop x-ui
rm -f geoip.dat geosite.dat rm -f geoip.dat geosite.dat
wget -N https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat wget -N https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
wget -N https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat wget -N https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat
@@ -833,6 +856,7 @@ update_geo() {
restart restart
;; ;;
2) 2)
systemctl stop x-ui
rm -f geoip_IR.dat geosite_IR.dat rm -f geoip_IR.dat geosite_IR.dat
wget -O geoip_IR.dat -N https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat wget -O geoip_IR.dat -N https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat
wget -O geosite_IR.dat -N https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat wget -O geosite_IR.dat -N https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat
@@ -840,6 +864,7 @@ update_geo() {
restart restart
;; ;;
3) 3)
systemctl stop x-ui
rm -f geoip_VN.dat geosite_VN.dat rm -f geoip_VN.dat geosite_VN.dat
wget -O geoip_VN.dat -N https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geoip.dat wget -O geoip_VN.dat -N https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geoip.dat
wget -O geosite_VN.dat -N https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geosite.dat wget -O geosite_VN.dat -N https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geosite.dat
@@ -852,7 +877,6 @@ update_geo() {
;; ;;
esac esac
systemctl start x-ui
before_show_menu before_show_menu
} }
@@ -1277,8 +1301,8 @@ run_speedtest() {
} }
create_iplimit_jails() { create_iplimit_jails() {
# Use default bantime if not passed => 15 minutes # Use default bantime if not passed => 30 minutes
local bantime="${1:-15}" local bantime="${1:-30}"
# Uncomment 'allowipv6 = auto' in fail2ban.conf # Uncomment 'allowipv6 = auto' in fail2ban.conf
sed -i 's/#allowipv6 = auto/allowipv6 = auto/g' /etc/fail2ban/fail2ban.conf sed -i 's/#allowipv6 = auto/allowipv6 = auto/g' /etc/fail2ban/fail2ban.conf
@@ -1309,7 +1333,7 @@ EOF
cat << EOF > /etc/fail2ban/action.d/3x-ipl.conf cat << EOF > /etc/fail2ban/action.d/3x-ipl.conf
[INCLUDES] [INCLUDES]
before = iptables-common.conf before = iptables-allports.conf
[Definition] [Definition]
actionstart = <iptables> -N f2b-<name> actionstart = <iptables> -N f2b-<name>
@@ -1352,15 +1376,22 @@ iplimit_remove_conflicts() {
done done
} }
ip_validation() {
ipv6_regex="^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$"
ipv4_regex="^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)$"
}
iplimit_main() { iplimit_main() {
echo -e "\n${green}\t1.${plain} Install Fail2ban and configure IP Limit" echo -e "\n${green}\t1.${plain} Install Fail2ban and configure IP Limit"
echo -e "${green}\t2.${plain} Change Ban Duration" echo -e "${green}\t2.${plain} Change Ban Duration"
echo -e "${green}\t3.${plain} Unban Everyone" echo -e "${green}\t3.${plain} Unban Everyone"
echo -e "${green}\t4.${plain} Ban Logs" echo -e "${green}\t4.${plain} Ban Logs"
echo -e "${green}\t5.${plain} Real-Time Logs" echo -e "${green}\t5.${plain} Ban an IP Address"
echo -e "${green}\t6.${plain} Service Status" echo -e "${green}\t6.${plain} Unban an IP Address"
echo -e "${green}\t7.${plain} Service Restart" echo -e "${green}\t7.${plain} Real-Time Logs"
echo -e "${green}\t8.${plain} Uninstall Fail2ban and IP Limit" echo -e "${green}\t8.${plain} Service Status"
echo -e "${green}\t9.${plain} Service Restart"
echo -e "${green}\t10.${plain} Uninstall Fail2ban and IP Limit"
echo -e "${green}\t0.${plain} Back to Main Menu" echo -e "${green}\t0.${plain} Back to Main Menu"
read -p "Choose an option: " choice read -p "Choose an option: " choice
case "$choice" in case "$choice" in
@@ -1402,22 +1433,44 @@ iplimit_main() {
iplimit_main iplimit_main
;; ;;
5) 5)
tail -f /var/log/fail2ban.log read -rp "Enter the IP address you want to ban: " ban_ip
ip_validation
if [[ $ban_ip =~ $ipv4_regex || $ban_ip =~ $ipv6_regex ]]; then
fail2ban-client set 3x-ipl banip "$ban_ip"
echo -e "${green}IP Address ${ban_ip} has been banned successfully.${plain}"
else
echo -e "${red}Invalid IP address format! Please try again.${plain}"
fi
iplimit_main iplimit_main
;; ;;
6) 6)
service fail2ban status read -rp "Enter the IP address you want to unban: " unban_ip
ip_validation
if [[ $unban_ip =~ $ipv4_regex || $unban_ip =~ $ipv6_regex ]]; then
fail2ban-client set 3x-ipl unbanip "$unban_ip"
echo -e "${green}IP Address ${unban_ip} has been unbanned successfully.${plain}"
else
echo -e "${red}Invalid IP address format! Please try again.${plain}"
fi
iplimit_main iplimit_main
;; ;;
7) 7)
systemctl restart fail2ban tail -f /var/log/fail2ban.log
iplimit_main iplimit_main
;; ;;
8) 8)
service fail2ban status
iplimit_main
;;
9)
systemctl restart fail2ban
iplimit_main
;;
10)
remove_iplimit remove_iplimit
iplimit_main iplimit_main
;; ;;
*) *)
echo -e "${red}Invalid option. Please select a valid number.${plain}\n" echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
iplimit_main iplimit_main
;; ;;
@@ -1628,61 +1681,63 @@ SSH_port_forwarding() {
} }
show_usage() { show_usage() {
echo "x-ui control menu usages: " echo -e "┌───────────────────────────────────────────────────────┐
echo "------------------------------------------" ${blue}x-ui control menu usages (subcommands):${plain}
echo -e "SUBCOMMANDS:" │ │
echo -e "x-ui - Admin Management Script" ${blue}x-ui${plain} - Admin Management Script
echo -e "x-ui start - Start" ${blue}x-ui start${plain} - Start │
echo -e "x-ui stop - Stop" ${blue}x-ui stop${plain} - Stop │
echo -e "x-ui restart - Restart" ${blue}x-ui restart${plain} - Restart │
echo -e "x-ui status - Current Status" ${blue}x-ui status${plain} - Current Status
echo -e "x-ui settings - Current Settings" ${blue}x-ui settings${plain} - Current Settings
echo -e "x-ui enable - Enable Autostart on OS Startup" ${blue}x-ui enable${plain} - Enable Autostart on OS Startup
echo -e "x-ui disable - Disable Autostart on OS Startup" ${blue}x-ui disable${plain} - Disable Autostart on OS Startup
echo -e "x-ui log - Check logs" ${blue}x-ui log${plain} - Check logs │
echo -e "x-ui banlog - Check Fail2ban ban logs" ${blue}x-ui banlog${plain} - Check Fail2ban ban logs
echo -e "x-ui update - Update" ${blue}x-ui update${plain} - Update │
echo -e "x-ui custom - custom version" ${blue}x-ui legacy${plain} - legacy version
echo -e "x-ui install - Install" ${blue}x-ui install${plain} - Install │
echo -e "x-ui uninstall - Uninstall" ${blue}x-ui uninstall${plain} - Uninstall │
echo "------------------------------------------" └───────────────────────────────────────────────────────┘"
} }
show_menu() { show_menu() {
echo -e " echo -e "
${green}3X-UI Panel Management Script${plain} ╔────────────────────────────────────────────────╗
${green}0.${plain} Exit Script ${green}3X-UI Panel Management Script${plain}
———————————————— ${green}0.${plain} Exit Script │
${green}1.${plain} Install │────────────────────────────────────────────────│
${green}2.${plain} Update ${green}1.${plain} Install │
${green}3.${plain} Update Menu ${green}2.${plain} Update
${green}4.${plain} Legacy Version ${green}3.${plain} Update Menu │
${green}5.${plain} Uninstall ${green}4.${plain} Legacy Version │
———————————————— ${green}5.${plain} Uninstall │
${green}6.${plain} Reset Username & Password & Secret Token │────────────────────────────────────────────────│
${green}7.${plain} Reset Web Base Path ${green}6.${plain} Reset Username & Password & Secret Token │
${green}8.${plain} Reset Settings ${green}7.${plain} Reset Web Base Path │
${green}9.${plain} Change Port ${green}8.${plain} Reset Settings │
${green}10.${plain} View Current Settings ${green}9.${plain} Change Port │
———————————————— ${green}10.${plain} View Current Settings │
${green}11.${plain} Start │────────────────────────────────────────────────│
${green}12.${plain} Stop ${green}11.${plain} Start │
${green}13.${plain} Restart ${green}12.${plain} Stop │
${green}14.${plain} Check Status ${green}13.${plain} Restart │
${green}15.${plain} Logs Management ${green}14.${plain} Check Status │
———————————————— ${green}15.${plain} Logs Management │
${green}16.${plain} Enable Autostart │────────────────────────────────────────────────│
${green}17.${plain} Disable Autostart ${green}16.${plain} Enable Autostart
———————————————— ${green}17.${plain} Disable Autostart │
${green}18.${plain} SSL Certificate Management │────────────────────────────────────────────────│
${green}19.${plain} Cloudflare SSL Certificate ${green}18.${plain} SSL Certificate Management │
${green}20.${plain} IP Limit Management ${green}19.${plain} Cloudflare SSL Certificate │
${green}21.${plain} Firewall Management ${green}20.${plain} IP Limit Management
${green}22.${plain} SSH Port Forwarding Management ${green}21.${plain} Firewall Management │
———————————————— ${green}22.${plain} SSH Port Forwarding Management │
${green}23.${plain} Enable BBR │────────────────────────────────────────────────│
${green}24.${plain} Update Geo Files ${green}23.${plain} Enable BBR │
${green}25.${plain} Speedtest by Ookla ${green}24.${plain} Update Geo Files │
${green}25.${plain} Speedtest by Ookla │
╚────────────────────────────────────────────────╝
" "
show_status show_status
echo && read -p "Please enter your selection [0-25]: " num echo && read -p "Please enter your selection [0-25]: " num

View File

@@ -16,11 +16,24 @@ type LogWriter struct {
} }
func (lw *LogWriter) Write(m []byte) (n int, err error) { 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}) \[([^\]]+)\] (.+)$`) crashRegex := regexp.MustCompile(`(?i)(panic|exception|stack trace|fatal error)`)
// Convert the data to a string // Convert the data to a string
message := strings.TrimSpace(string(m)) message := strings.TrimSpace(string(m))
// Check if the message contains a crash
if crashRegex.MatchString(message) {
logger.Debug("Core crash detected:\n", message)
lw.lastLine = message
err1 := writeCrachReport(m)
if err1 != nil {
logger.Error("Unable to write crash report:", err1)
}
return len(m), nil
}
regex := regexp.MustCompile(`^(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}) \[([^\]]+)\] (.+)$`)
messages := strings.Split(message, "\n") messages := strings.Split(message, "\n")
lw.lastLine = messages[len(messages)-1]
for _, msg := range messages { for _, msg := range messages {
matches := regex.FindStringSubmatch(msg) matches := regex.FindStringSubmatch(msg)
@@ -42,9 +55,10 @@ func (lw *LogWriter) Write(m []byte) (n int, err error) {
default: default:
logger.Debug("XRAY: " + msg) logger.Debug("XRAY: " + msg)
} }
lw.lastLine = ""
} else if msg != "" { } else if msg != "" {
logger.Debug("XRAY: " + msg) logger.Debug("XRAY: " + msg)
return len(m), nil lw.lastLine = msg
} }
} }

View File

@@ -226,7 +226,6 @@ func (p *process) Start() (err error) {
if err != nil { if err != nil {
logger.Error("Failure in running xray-core:", err) logger.Error("Failure in running xray-core:", err)
p.exitErr = err p.exitErr = err
p.witeCrachReport(err)
} }
}() }()
@@ -243,7 +242,7 @@ func (p *process) Stop() error {
return p.cmd.Process.Signal(syscall.SIGTERM) return p.cmd.Process.Signal(syscall.SIGTERM)
} }
func (p *process) witeCrachReport(err error) error { func writeCrachReport(m []byte) error {
crashReportPath := config.GetBinFolderPath() + "/core_crash_" + time.Now().Format("20060102_150405") + ".log" crashReportPath := config.GetBinFolderPath() + "/core_crash_" + time.Now().Format("20060102_150405") + ".log"
return os.WriteFile(crashReportPath, []byte(err.Error()), os.ModePerm) return os.WriteFile(crashReportPath, m, os.ModePerm)
} }