Merge branch 'MHSanaei:main' into main

This commit is contained in:
Zahar Izmailov 2025-02-01 10:11:32 +03:00 committed by GitHub
commit 055242b493
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 237 additions and 145 deletions

View file

@ -7,7 +7,7 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -31,6 +31,8 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
with:
install: true
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v3

View file

@ -72,7 +72,7 @@ jobs:
export GOARCH=s390x export GOARCH=s390x
export CC=s390x-linux-gnu-gcc export CC=s390x-linux-gnu-gcc
fi fi
go build -o xui-release -v main.go go build -ldflags "-w -s" -o xui-release -v main.go
mkdir x-ui mkdir x-ui
cp xui-release x-ui/ cp xui-release x-ui/
@ -85,41 +85,41 @@ jobs:
# Download dependencies # Download dependencies
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v25.1.1/" Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v25.1.1/"
if [ "${{ matrix.platform }}" == "amd64" ]; then if [ "${{ matrix.platform }}" == "amd64" ]; then
wget ${Xray_URL}Xray-linux-64.zip wget -q ${Xray_URL}Xray-linux-64.zip
unzip Xray-linux-64.zip unzip Xray-linux-64.zip
rm -f Xray-linux-64.zip rm -f Xray-linux-64.zip
elif [ "${{ matrix.platform }}" == "arm64" ]; then elif [ "${{ matrix.platform }}" == "arm64" ]; then
wget ${Xray_URL}Xray-linux-arm64-v8a.zip wget -q ${Xray_URL}Xray-linux-arm64-v8a.zip
unzip Xray-linux-arm64-v8a.zip unzip Xray-linux-arm64-v8a.zip
rm -f Xray-linux-arm64-v8a.zip rm -f Xray-linux-arm64-v8a.zip
elif [ "${{ matrix.platform }}" == "armv7" ]; then elif [ "${{ matrix.platform }}" == "armv7" ]; then
wget ${Xray_URL}Xray-linux-arm32-v7a.zip wget -q ${Xray_URL}Xray-linux-arm32-v7a.zip
unzip Xray-linux-arm32-v7a.zip unzip Xray-linux-arm32-v7a.zip
rm -f Xray-linux-arm32-v7a.zip rm -f Xray-linux-arm32-v7a.zip
elif [ "${{ matrix.platform }}" == "armv6" ]; then elif [ "${{ matrix.platform }}" == "armv6" ]; then
wget ${Xray_URL}Xray-linux-arm32-v6.zip wget -q ${Xray_URL}Xray-linux-arm32-v6.zip
unzip Xray-linux-arm32-v6.zip unzip Xray-linux-arm32-v6.zip
rm -f Xray-linux-arm32-v6.zip rm -f Xray-linux-arm32-v6.zip
elif [ "${{ matrix.platform }}" == "386" ]; then elif [ "${{ matrix.platform }}" == "386" ]; then
wget ${Xray_URL}Xray-linux-32.zip wget -q ${Xray_URL}Xray-linux-32.zip
unzip Xray-linux-32.zip unzip Xray-linux-32.zip
rm -f Xray-linux-32.zip rm -f Xray-linux-32.zip
elif [ "${{ matrix.platform }}" == "armv5" ]; then elif [ "${{ matrix.platform }}" == "armv5" ]; then
wget ${Xray_URL}Xray-linux-arm32-v5.zip wget -q ${Xray_URL}Xray-linux-arm32-v5.zip
unzip Xray-linux-arm32-v5.zip unzip Xray-linux-arm32-v5.zip
rm -f Xray-linux-arm32-v5.zip rm -f Xray-linux-arm32-v5.zip
elif [ "${{ matrix.platform }}" == "s390x" ]; then elif [ "${{ matrix.platform }}" == "s390x" ]; then
wget ${Xray_URL}Xray-linux-s390x.zip wget -q ${Xray_URL}Xray-linux-s390x.zip
unzip Xray-linux-s390x.zip unzip Xray-linux-s390x.zip
rm -f Xray-linux-s390x.zip rm -f Xray-linux-s390x.zip
fi fi
rm -f geoip.dat geosite.dat rm -f geoip.dat geosite.dat
wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat wget -q https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat wget -q https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat
wget -O geoip_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat wget -q -O geoip_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat
wget -O geosite_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat wget -q -O geosite_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat
wget -O geoip_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat wget -q -O geoip_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat
wget -O geosite_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat wget -q -O geosite_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat
mv xray xray-linux-${{ matrix.platform }} mv xray xray-linux-${{ matrix.platform }}
cd ../.. cd ../..

View file

@ -27,14 +27,14 @@ 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/v25.1.1/Xray-linux-${ARCH}.zip" wget -q "https://github.com/XTLS/Xray-core/releases/download/v25.1.1/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}"
wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat wget -q https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat wget -q https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat
wget -O geoip_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat wget -q -O geoip_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat
wget -O geosite_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat wget -q -O geosite_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat
wget -O geoip_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat wget -q -O geoip_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat
wget -O geosite_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat wget -q -O geosite_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat
cd ../../ cd ../../

View file

@ -15,7 +15,7 @@ COPY . .
ENV CGO_ENABLED=1 ENV CGO_ENABLED=1
ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE" ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE"
RUN go build -o build/x-ui main.go RUN go build -ldflags "-w -s" -o build/x-ui main.go
RUN ./DockerInit.sh "$TARGETARCH" RUN ./DockerInit.sh "$TARGETARCH"
# ======================================================== # ========================================================

View file

@ -1 +1 @@
2.4.11 2.5.0

16
go.mod
View file

@ -8,23 +8,23 @@ require (
github.com/gin-gonic/gin v1.10.0 github.com/gin-gonic/gin v1.10.0
github.com/goccy/go-json v0.10.4 github.com/goccy/go-json v0.10.4
github.com/mymmrac/telego v0.32.0 github.com/mymmrac/telego v0.32.0
github.com/nicksnyder/go-i18n/v2 v2.4.1 github.com/nicksnyder/go-i18n/v2 v2.5.0
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.12 github.com/shirou/gopsutil/v4 v4.24.12
github.com/valyala/fasthttp v1.58.0 github.com/valyala/fasthttp v1.58.0
github.com/xtls/xray-core v1.8.25-0.20250119133207-ca9a90221348 github.com/xtls/xray-core v1.8.25-0.20250126155934-7b59379d73c3
go.uber.org/atomic v1.11.0 go.uber.org/atomic v1.11.0
golang.org/x/text v0.21.0 golang.org/x/text v0.21.0
google.golang.org/grpc v1.69.4 google.golang.org/grpc v1.70.0
gorm.io/driver/sqlite v1.5.7 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.7 // indirect github.com/bytedance/sonic v1.12.8 // indirect
github.com/bytedance/sonic/loader v0.2.3 // indirect github.com/bytedance/sonic/loader v0.2.3 // indirect
github.com/cloudflare/circl v1.5.0 // indirect github.com/cloudflare/circl v1.5.0 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect github.com/cloudwego/base64x v0.1.5 // indirect
@ -39,7 +39,7 @@ require (
github.com/go-playground/validator/v10 v10.24.0 // indirect github.com/go-playground/validator/v10 v10.24.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-20250121033306-997b0b79cac0 // indirect github.com/google/pprof v0.0.0-20250125003558-7fdb3d7e6fa0 // 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
@ -61,6 +61,7 @@ require (
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.49.0 // 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
@ -77,7 +78,6 @@ require (
github.com/valyala/fastjson v1.6.4 // indirect github.com/valyala/fastjson v1.6.4 // indirect
github.com/vishvananda/netlink v1.3.0 // indirect github.com/vishvananda/netlink v1.3.0 // indirect
github.com/vishvananda/netns v0.0.5 // indirect github.com/vishvananda/netns v0.0.5 // indirect
github.com/xtls/quic-go v0.48.2 // indirect
github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463 // indirect github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.uber.org/mock v0.5.0 // indirect go.uber.org/mock v0.5.0 // indirect
@ -93,8 +93,8 @@ require (
golang.org/x/tools v0.29.0 // indirect golang.org/x/tools v0.29.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-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 // indirect
google.golang.org/protobuf v1.36.3 // indirect google.golang.org/protobuf v1.36.4 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 // indirect gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 // indirect
lukechampine.com/blake3 v1.3.0 // indirect lukechampine.com/blake3 v1.3.0 // indirect

52
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.7 h1:CQU8pxOy9HToxhndH0Kx/S1qU/CuS9GnKYrGioDcU1Q= github.com/bytedance/sonic v1.12.8 h1:4xYRVRlXIgvSZ4e8iVTlMF5szgpXd4AfvuWgA8I8lgs=
github.com/bytedance/sonic v1.12.7/go.mod h1:tnbal4mxOMju17EGfknm2XyYcpyCnIROYOEYuemj13I= github.com/bytedance/sonic v1.12.8/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8=
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.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0= github.com/bytedance/sonic/loader v0.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0=
github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
@ -67,8 +67,8 @@ 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-20250121033306-997b0b79cac0 h1:EinjE47mmVVsxcjIwVKQWNY+3P+5R2BhkbULjhEDThc= github.com/google/pprof v0.0.0-20250125003558-7fdb3d7e6fa0 h1:my2ucqBZmv+cWHIhZNSIYKzgN8EBGyHdC7zD5sASRAg=
github.com/google/pprof v0.0.0-20250121033306-997b0b79cac0/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/pprof v0.0.0-20250125003558-7fdb3d7e6fa0/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 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/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=
@ -114,8 +114,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mymmrac/telego v0.32.0 h1:4X8C1l3k+opkk86r95+eQE8DxiS2LYlR61L/G7yreDY= github.com/mymmrac/telego v0.32.0 h1:4X8C1l3k+opkk86r95+eQE8DxiS2LYlR61L/G7yreDY=
github.com/mymmrac/telego v0.32.0/go.mod h1:qS6NaRhJgcuEEBEMVCV79S2xCAuHq9O+ixwfLuRW31M= github.com/mymmrac/telego v0.32.0/go.mod h1:qS6NaRhJgcuEEBEMVCV79S2xCAuHq9O+ixwfLuRW31M=
github.com/nicksnyder/go-i18n/v2 v2.4.1 h1:zwzjtX4uYyiaU02K5Ia3zSkpJZrByARkRB4V3YPrr0g= github.com/nicksnyder/go-i18n/v2 v2.5.0 h1:3wH1gpaekcgGuwzWdSu7JwJhH9Tk87k1ezt0i1p2/Is=
github.com/nicksnyder/go-i18n/v2 v2.4.1/go.mod h1:++Pl70FR6Cki7hdzZRnEEqdc2dJt+SAGotyFg/SvZMk= github.com/nicksnyder/go-i18n/v2 v2.5.0/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ=
github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
@ -134,6 +134,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.49.0 h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp94=
github.com/quic-go/quic-go v0.49.0/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
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=
@ -186,26 +188,24 @@ github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
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/quic-go v0.48.2 h1:59Gs+E9qtc9s0uniXYDA649gNEZlMWcNpFLyp9jfkuE=
github.com/xtls/quic-go v0.48.2/go.mod h1:rcyY5J0JT+1d5pa5Y+FbCsXM7Zu79jE87ZSFOBfiH7Q=
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.20250119133207-ca9a90221348 h1:x54/hGG4meg32o8wR0EkIKyVJy7Fv+ey+bmSZuXWkJE= github.com/xtls/xray-core v1.8.25-0.20250126155934-7b59379d73c3 h1:JzofxKb13MvNZeSLPS9B07Few0fu11dPEa40EQNV/hE=
github.com/xtls/xray-core v1.8.25-0.20250119133207-ca9a90221348/go.mod h1:51y3AycMua6m1VFYnc3vJmgXeiL0qTsRGsDpjEaoXXc= github.com/xtls/xray-core v1.8.25-0.20250126155934-7b59379d73c3/go.mod h1:KmpYBu4IFdODX7qgG7DP7v9sHJBcHpdKE+qxUZ2N304=
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.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
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=
@ -242,12 +242,12 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu
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-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 h1:91mG8dNTpkC0uChJUQ9zCiRqx3GEEFOWaRZ0mI6Oj2I=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.4/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=

View file

@ -493,7 +493,7 @@ class xHTTPStreamSettings extends XrayCommonClass {
headers = [], headers = [],
scMaxBufferedPosts = 30, scMaxBufferedPosts = 30,
scMaxEachPostBytes = "1000000", scMaxEachPostBytes = "1000000",
scStreamUpServerSecs = "0", scStreamUpServerSecs = "20-80",
noSSEHeader = false, noSSEHeader = false,
xPaddingBytes = "100-1000", xPaddingBytes = "100-1000",
mode = MODE_OPTION.AUTO, mode = MODE_OPTION.AUTO,
@ -554,6 +554,7 @@ class TlsStreamSettings extends XrayCommonClass {
maxVersion = TLS_VERSION_OPTION.TLS13, maxVersion = TLS_VERSION_OPTION.TLS13,
cipherSuites = '', cipherSuites = '',
rejectUnknownSni = false, rejectUnknownSni = false,
serverNameToVerify = 'dns.google',
disableSystemRoot = false, disableSystemRoot = false,
enableSessionResumption = false, enableSessionResumption = false,
certificates = [new TlsStreamSettings.Cert()], certificates = [new TlsStreamSettings.Cert()],
@ -566,6 +567,7 @@ class TlsStreamSettings extends XrayCommonClass {
this.maxVersion = maxVersion; this.maxVersion = maxVersion;
this.cipherSuites = cipherSuites; this.cipherSuites = cipherSuites;
this.rejectUnknownSni = rejectUnknownSni; this.rejectUnknownSni = rejectUnknownSni;
this.serverNameToVerify = serverNameToVerify;
this.disableSystemRoot = disableSystemRoot; this.disableSystemRoot = disableSystemRoot;
this.enableSessionResumption = enableSessionResumption; this.enableSessionResumption = enableSessionResumption;
this.certs = certificates; this.certs = certificates;
@ -597,6 +599,7 @@ class TlsStreamSettings extends XrayCommonClass {
json.maxVersion, json.maxVersion,
json.cipherSuites, json.cipherSuites,
json.rejectUnknownSni, json.rejectUnknownSni,
json.serverNameToVerify,
json.disableSystemRoot, json.disableSystemRoot,
json.enableSessionResumption, json.enableSessionResumption,
certs, certs,
@ -612,6 +615,7 @@ class TlsStreamSettings extends XrayCommonClass {
maxVersion: this.maxVersion, maxVersion: this.maxVersion,
cipherSuites: this.cipherSuites, cipherSuites: this.cipherSuites,
rejectUnknownSni: this.rejectUnknownSni, rejectUnknownSni: this.rejectUnknownSni,
serverNameToVerify: this.serverNameToVerify,
disableSystemRoot: this.disableSystemRoot, disableSystemRoot: this.disableSystemRoot,
enableSessionResumption: this.enableSessionResumption, enableSessionResumption: this.enableSessionResumption,
certificates: TlsStreamSettings.toJsonArray(this.certs), certificates: TlsStreamSettings.toJsonArray(this.certs),

View file

@ -81,7 +81,7 @@ class HttpUtil {
}, },
body: JSON.stringify(data), body: JSON.stringify(data),
}; };
const resp = await fetch(url, requestOptions); const resp = await fetch(basePath + url.replace(/^\/+|\/+$/g, ''), requestOptions);
const response = await resp.json(); const response = await resp.json();
msg = this._respToMsg({data : response}); msg = this._respToMsg({data : response});

View file

@ -36,12 +36,13 @@
ok() { ok() {
if (app.subSettings.enable && clientModal.group.isGroup && clientModal.group.canGroup) { if (app.subSettings.enable && clientModal.group.isGroup && clientModal.group.canGroup) {
const currentClient = clientModal.group.currentClient; const currentClient = clientModal.group.currentClient;
const { limitIp, totalGB, expiryTime, reset, enable, subId, tgId, flow } = currentClient; const { limitIp, comment, totalGB, expiryTime, reset, enable, subId, tgId, flow } = currentClient;
const uniqueEmails = clientModalApp.makeGroupEmailsUnique(clientModal.dbInbounds, currentClient.email, clientModal.group.clients); const uniqueEmails = clientModalApp.makeGroupEmailsUnique(clientModal.dbInbounds, currentClient.email, clientModal.group.clients);
clientModal.group.clients.forEach((client, index) => { clientModal.group.clients.forEach((client, index) => {
client.email = uniqueEmails[index]; client.email = uniqueEmails[index];
client.limitIp = limitIp; client.limitIp = limitIp;
client.comment = comment;
client.totalGB = totalGB; client.totalGB = totalGB;
client.expiryTime = expiryTime; client.expiryTime = expiryTime;
client.reset = reset; client.reset = reset;
@ -119,9 +120,11 @@
this.group.isGroup = true; this.group.isGroup = true;
dbInbounds.forEach((dbInboundItem) => { dbInbounds.forEach((dbInboundItem) => {
this.showProcess(dbInboundItem); this.showProcess(dbInboundItem);
this.addClient(this.inbound.protocol, this.clients); if (this.dbInbound.isMultiUser()) {
this.group.inbounds.push(dbInboundItem.id) this.addClient(this.inbound.protocol, this.clients);
this.group.clients.push(this.clients[this.index]) this.group.inbounds.push(dbInboundItem.id)
this.group.clients.push(this.clients[this.index])
}
}) })
this.group.currentClient = this.clients[this.index] this.group.currentClient = this.clients[this.index]
} }
@ -139,9 +142,11 @@
showProcess(dbInbound, index = null) { showProcess(dbInbound, index = null) {
this.dbInbound = new DBInbound(dbInbound); this.dbInbound = new DBInbound(dbInbound);
this.inbound = dbInbound.toInbound(); this.inbound = dbInbound.toInbound();
this.clients = this.inbound.clients; if (this.dbInbound.isMultiUser()) {
this.index = index === null ? this.clients.length : index; this.clients = this.inbound.clients;
this.delayedStart = false; this.index = index === null ? this.clients.length : index;
this.delayedStart = false;
}
}, },
singleEditClientProcess(index) { singleEditClientProcess(index) {
if (this.clients[index].expiryTime < 0) { if (this.clients[index].expiryTime < 0) {
@ -259,6 +264,23 @@
return generatedEmails; return generatedEmails;
}, },
async getDBClientIps(email) {
const msg = await HttpUtil.post(`/panel/inbound/clientIps/${email}`);
if (!msg.success) {
document.getElementById("clientIPs").value = msg.obj;
return;
}
let ips = msg.obj;
if (typeof ips === 'string' && ips.startsWith('[') && ips.endsWith(']')) {
try {
ips = JSON.parse(ips);
ips = Array.isArray(ips) ? ips.join("\n") : ips;
} catch (e) {
console.error('Error parsing JSON:', e);
}
}
document.getElementById("clientIPs").value = ips;
},
async clearDBClientIps(email) { async clearDBClientIps(email) {
try { try {
const msg = await HttpUtil.post(`/panel/inbound/clearClientIps/${email}`); const msg = await HttpUtil.post(`/panel/inbound/clearClientIps/${email}`);

View file

@ -33,7 +33,7 @@
<a-form-item label="Max Upload Size (Byte)" v-if="inbound.stream.xhttp.mode === 'packet-up'"> <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-input v-model.trim="inbound.stream.xhttp.scMaxEachPostBytes"></a-input>
</a-form-item> </a-form-item>
<a-form-item label="Stream-Up Server"> <a-form-item label="Stream-Up Server" v-if="inbound.stream.xhttp.mode === 'stream-up'">
<a-input v-model.trim="inbound.stream.xhttp.scStreamUpServerSecs"></a-input> <a-input v-model.trim="inbound.stream.xhttp.scStreamUpServerSecs"></a-input>
</a-form-item> </a-form-item>
<a-form-item label="Padding Bytes"> <a-form-item label="Padding Bytes">

View file

@ -57,6 +57,9 @@
<a-form-item label="Session Resumption"> <a-form-item label="Session Resumption">
<a-switch v-model="inbound.stream.tls.enableSessionResumption"></a-switch> <a-switch v-model="inbound.stream.tls.enableSessionResumption"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label="Server Name To Verify">
<a-input v-model.trim="inbound.stream.tls.serverNameToVerify"></a-input>
</a-form-item>
<template v-for="cert,index in inbound.stream.tls.certs"> <template v-for="cert,index in inbound.stream.tls.certs">
<a-form-item label='{{ i18n "certificate" }}'> <a-form-item label='{{ i18n "certificate" }}'>
<a-radio-group v-model="cert.useFile" button-style="solid"> <a-radio-group v-model="cert.useFile" button-style="solid">

View file

@ -1195,35 +1195,48 @@
} }
}, },
getSubGroupClients(dbInbounds, currentClient) { getSubGroupClients(dbInbounds, currentClient) {
const response = { const response = {
inbounds: [], inbounds: [],
clients: [], clients: [],
editIds: [] editIds: [],
};
if (!Array.isArray(dbInbounds) || dbInbounds.length === 0) {
return response;
}
if (!currentClient || !currentClient.subId) {
return response;
}
dbInbounds.forEach((dbInboundItem) => {
try {
const dbInbound = new DBInbound(dbInboundItem);
if (!dbInbound) {
return;
} }
if (dbInbounds && dbInbounds.length > 0 && currentClient) {
dbInbounds.forEach((dbInboundItem) => { const inbound = dbInbound.toInbound();
const dbInbound = new DBInbound(dbInboundItem); if (!inbound || !Array.isArray(inbound.clients)) {
if (dbInbound) { return;
const inbound = dbInbound.toInbound();
if (inbound) {
const clients = inbound.clients;
if (clients.length > 0) {
clients.forEach((client) => {
if (client['subId'] === currentClient['subId']) {
client['inboundId'] = dbInboundItem.id
client['clientId'] = this.getClientId(dbInbound.protocol, client)
response.inbounds.push(dbInboundItem.id)
response.clients.push(client)
response.editIds.push(client['clientId'])
}
})
}
}
}
})
} }
return response;
}, inbound.clients.forEach((client) => {
if (client.subId === currentClient.subId) {
client.inboundId = dbInboundItem.id;
client.clientId = this.getClientId(dbInbound.protocol, client);
response.inbounds.push(dbInboundItem.id);
response.clients.push(client);
response.editIds.push(client.clientId);
}
});
} catch (error) {
console.error("Error processing dbInboundItem:", dbInboundItem, error);
}
});
return response;
},
getClientId(protocol, client) { getClientId(protocol, client) {
switch (protocol) { switch (protocol) {
case Protocols.TROJAN: return client.password; case Protocols.TROJAN: return client.password;
@ -1455,7 +1468,7 @@
if (clients != null){ if (clients != null){
clients.forEach(c => { clients.forEach(c => {
if (c.subId && c.subId.length>0){ if (c.subId && c.subId.length>0){
subLinks.push(this.subSettings.subURI + c.subId + "?name=" + c.subId) subLinks.push(this.subSettings.subURI + c.subId)
} }
}) })
} }
@ -1482,7 +1495,7 @@
if (clients != null){ if (clients != null){
clients.forEach(c => { clients.forEach(c => {
if (c.subId && c.subId.length>0){ if (c.subId && c.subId.length>0){
subLinks.push(this.subSettings.subURI + c.subId + "?name=" + c.subId) subLinks.push(this.subSettings.subURI + c.subId)
} }
}) })
} }

View file

@ -382,14 +382,40 @@
</a-col> </a-col>
</a-row> </a-row>
<a-collapse v-if="enableDirect" style="margin-top: 14px;"> <a-collapse v-if="enableDirect" style="margin-top: 14px;">
<a-collapse-panel header='{{ i18n "pages.xray.directips"}}'> <a-collapse-panel header='{{ i18n "pages.settings.direct"}}'>
<a-list-item style="padding: 10px 20px"> <a-list-item>
<a-checkbox-group v-model="directIPs" :options="IPsOptions"></a-checkbox-group> <a-row style="padding: 0 20px">
<a-col :lg="24" :xl="12">
<a-list-item-meta
title='{{ i18n "pages.xray.directips" }}'/>
</a-col>
<a-col :lg="24" :xl="12">
<a-select mode="tags" style="width: 100%"
v-model="directIPs"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option :value="p.value" :label="p.label"
v-for="p in directIPsOptions"> [[ p.label ]]
</a-select-option>
</a-select>
</a-col>
</a-row>
</a-list-item> </a-list-item>
</a-collapse-panel> <a-list-item>
<a-collapse-panel header='{{ i18n "pages.xray.directdomains"}}'> <a-row style="padding: 0 20px">
<a-list-item style="padding: 10px 20px"> <a-col :lg="24" :xl="12">
<a-checkbox-group v-model="directDomains" :options="DomainsOptions"></a-checkbox-group> <a-list-item-meta
title='{{ i18n "pages.xray.directdomains" }}'/>
</a-col>
<a-col :lg="24" :xl="12">
<a-select mode="tags" style="width: 100%"
v-model="directDomains"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option :value="p.value" :label="p.label"
v-for="p in diretDomainsOptions"> [[ p.label ]]
</a-select-option>
</a-select>
</a-col>
</a-row>
</a-list-item> </a-list-item>
</a-collapse-panel> </a-collapse-panel>
</a-collapse> </a-collapse>
@ -477,25 +503,26 @@
] ]
}, },
], ],
IPsOptions: [ directIPsOptions: [
{ label: 'Private IP', value: 'private' }, { label: 'Private IP', value: 'geoip:private' },
{ label: '🇮🇷 Iran', value: 'ir' }, { label: '🇮🇷 Iran', value: 'geoip:ir' },
{ label: '🇨🇳 China', value: 'cn' }, { label: '🇨🇳 China', value: 'geoip:cn' },
{ label: '🇷🇺 Russia', value: 'ru' }, { label: '🇷🇺 Russia', value: 'geoip:ru' },
{ label: '🇻🇳 Vietnam', value: 'vn' }, { label: '🇻🇳 Vietnam', value: 'geoip:vn' },
{ label: '🇪🇸 Spain', value: 'es' }, { label: '🇪🇸 Spain', value: 'geoip:es' },
{ label: '🇮🇩 Indonesia', value: 'id' }, { label: '🇮🇩 Indonesia', value: 'geoip:id' },
{ label: '🇺🇦 Ukraine', value: 'ua' }, { label: '🇺🇦 Ukraine', value: 'geoip:ua' },
{ label: '🇹🇷 Türkiye', value: 'tr' }, { label: '🇹🇷 Türkiye', value: 'geoip:tr' },
{ label: '🇧🇷 Brazil', value: 'br' }, { label: '🇧🇷 Brazil', value: 'geoip:br' },
], ],
DomainsOptions: [ diretDomainsOptions: [
{ label: '🇮🇷 Iran', value: 'ir' }, { label: 'Private DNS', value: 'geosite:private' },
{ label: '🇨🇳 China', value: 'cn' }, { label: '🇮🇷 Iran', value: 'geosite:category-ir' },
{ label: '🇷🇺 Russia', value: 'ru' }, { label: '🇨🇳 China', value: 'geosite:cn' },
{ label: 'Apple', value: 'apple' }, { label: '🇷🇺 Russia', value: 'geosite:category-ru' },
{ label: 'Meta', value: 'meta' }, { label: 'Apple', value: 'geosite:apple' },
{ label: 'Google', value: 'google' }, { label: 'Meta', value: 'geosite:meta' },
{ label: 'Google', value: 'geosite:google' },
], ],
get remarkModel() { get remarkModel() {
rm = this.allSetting.remarkModel; rm = this.allSetting.remarkModel;
@ -753,7 +780,7 @@
const rules = JSON.parse(this.allSetting.subJsonRules); const rules = JSON.parse(this.allSetting.subJsonRules);
if (!Array.isArray(rules)) return []; if (!Array.isArray(rules)) return [];
const ipRule = rules.find(r => r.ip); const ipRule = rules.find(r => r.ip);
return ipRule?.ip.map(d => d.replace("geoip:", "")) ?? []; return ipRule?.ip ?? [];
}, },
set: function (v) { set: function (v) {
let rules = JSON.parse(this.allSetting.subJsonRules); let rules = JSON.parse(this.allSetting.subJsonRules);
@ -767,7 +794,7 @@
rules[ruleIndex].ip = []; rules[ruleIndex].ip = [];
v.forEach(d => { v.forEach(d => {
rules[ruleIndex].ip.push("geoip:" + d); rules[ruleIndex].ip.push(d);
}); });
} }
this.allSetting.subJsonRules = JSON.stringify(rules); this.allSetting.subJsonRules = JSON.stringify(rules);
@ -779,34 +806,18 @@
const rules = JSON.parse(this.allSetting.subJsonRules); const rules = JSON.parse(this.allSetting.subJsonRules);
if (!Array.isArray(rules)) return []; if (!Array.isArray(rules)) return [];
const domainRule = rules.find(r => r.domain); const domainRule = rules.find(r => r.domain);
return domainRule?.domain.map(d => { return domainRule?.domain ?? [];
if (d.startsWith("geosite:category-")) {
return d.replace("geosite:category-", "");
}
return d.replace("geosite:", "");
})
?? [];
}, },
set: function (v) { set: function (v) {
let rules = JSON.parse(this.allSetting.subJsonRules); let rules = JSON.parse(this.allSetting.subJsonRules);
if (!Array.isArray(rules)) return; if (!Array.isArray(rules)) return;
if (v.length == 0) { if (v.length == 0) {
rules = rules.filter(r => !r.domain); rules = rules.filter(r => !r.domain);
} else { } else {
let ruleIndex = rules.findIndex(r => r.domain); let ruleIndex = rules.findIndex(r => r.domain);
if (ruleIndex == -1) ruleIndex = rules.push(this.defaultRules[0]) - 1; if (ruleIndex == -1) ruleIndex = rules.push(this.defaultRules[0]) - 1;
rules[ruleIndex].domain = []; rules[ruleIndex].domain = v;
v.forEach(d => {
let category = '';
if (["cn", "apple", "meta", "google"].includes(d)) {
category = "";
} else if (["ru", "ir"].includes(d)) {
category = "category-";
}
rules[ruleIndex].domain.push("geosite:" + category + d);
});
} }
this.allSetting.subJsonRules = JSON.stringify(rules); this.allSetting.subJsonRules = JSON.stringify(rules);
} }

View file

@ -143,6 +143,7 @@
</a-select> </a-select>
</a-col> </a-col>
</a-row> </a-row>
<setting-list-item type="switch" title='{{ i18n "pages.xray.outboundTraffic"}}' desc='{{ i18n "pages.xray.outboundTrafficDesc"}}' v-model="outboundTraffic"></setting-list-item>
</a-list-item> </a-list-item>
</a-collapse-panel> </a-collapse-panel>
<a-collapse-panel header='{{ i18n "pages.xray.logConfigs" }}'> <a-collapse-panel header='{{ i18n "pages.xray.logConfigs" }}'>
@ -1823,6 +1824,18 @@
this.templateSettings = newTemplateSettings; this.templateSettings = newTemplateSettings;
} }
}, },
outboundTraffic: {
get: function () {
if (!this.templateSettings || !this.templateSettings.policy.system || !this.templateSettings.policy.system.statsOutboundDownlink) return false;
return this.templateSettings.policy.system.statsOutboundDownlink;
},
set: function (newValue) {
newTemplateSettings = this.templateSettings;
newTemplateSettings.policy.system.statsOutboundDownlink = newValue;
newTemplateSettings.policy.system.statsOutboundUplink = newValue;
this.templateSettings = newTemplateSettings;
}
},
maskAddressLog: { maskAddressLog: {
get: function () { get: function () {
if (!this.templateSettings || !this.templateSettings.log || !this.templateSettings.log.maskAddress) return ""; if (!this.templateSettings || !this.templateSettings.log || !this.templateSettings.log.maskAddress) return "";

View file

@ -51,8 +51,8 @@
"system": { "system": {
"statsInboundDownlink": true, "statsInboundDownlink": true,
"statsInboundUplink": true, "statsInboundUplink": true,
"statsOutboundDownlink": true, "statsOutboundDownlink": false,
"statsOutboundUplink": true "statsOutboundUplink": false
} }
}, },
"routing": { "routing": {

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "The file path for the error log. The special value 'none' disabled error logs" "errorLogDesc" = "The file path for the error log. The special value 'none' disabled error logs"
"dnsLog" = "DNS Log" "dnsLog" = "DNS Log"
"dnsLogDesc" = "Whether to enable DNS query logs" "dnsLogDesc" = "Whether to enable DNS query logs"
"outboundTraffic" = "Outbounds Traffic"
"outboundTrafficDesc" = "Whether to enable outbound traffic"
"maskAddress" = "Mask Address" "maskAddress" = "Mask Address"
"maskAddressDesc" = "IP address mask, when enabled, will automatically replace the IP address that appears in the log." "maskAddressDesc" = "IP address mask, when enabled, will automatically replace the IP address that appears in the log."

View file

@ -371,6 +371,8 @@
"errorLogDesc" = "La ruta del archivo para el registro de errores. El valor especial 'none' desactiva los registros de errores." "errorLogDesc" = "La ruta del archivo para el registro de errores. El valor especial 'none' desactiva los registros de errores."
"dnsLog" = "Registro DNS" "dnsLog" = "Registro DNS"
"dnsLogDesc" = "Si habilitar los registros de consulta DNS" "dnsLogDesc" = "Si habilitar los registros de consulta DNS"
"outboundTraffic" = "Tráfico saliente"
"outboundTrafficDesc" = "Si se debe habilitar el tráfico saliente"
"maskAddress" = "Enmascarar Dirección" "maskAddress" = "Enmascarar Dirección"
"maskAddressDesc" = "Máscara de dirección IP, cuando se habilita, reemplazará automáticamente la dirección IP que aparece en el registro." "maskAddressDesc" = "Máscara de dirección IP, cuando se habilita, reemplazará automáticamente la dirección IP que aparece en el registro."

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "مسیر فایل برای ورود به سیستم خطا. مقدار ویژه «هیچ» گزارش های خطا را غیرفعال میکند" "errorLogDesc" = "مسیر فایل برای ورود به سیستم خطا. مقدار ویژه «هیچ» گزارش های خطا را غیرفعال میکند"
"dnsLog" = "گزارش DNS" "dnsLog" = "گزارش DNS"
"dnsLogDesc" = "آیا ثبت‌های درخواست DNS را فعال کنید" "dnsLogDesc" = "آیا ثبت‌های درخواست DNS را فعال کنید"
"outboundTraffic" = "ترافیک خروجی"
"outboundTrafficDesc" = "فعال کردن ترافیک خروجی"
"maskAddress" = "پنهان کردن آدرس" "maskAddress" = "پنهان کردن آدرس"
"maskAddressDesc" = "پوشش آدرس IP، هنگامی که فعال می‌شود، به طور خودکار آدرس IP که در لاگ ظاهر می‌شود را جایگزین می‌کند." "maskAddressDesc" = "پوشش آدرس IP، هنگامی که فعال می‌شود، به طور خودکار آدرس IP که در لاگ ظاهر می‌شود را جایگزین می‌کند."

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "Jalur file untuk log kesalahan. Nilai khusus 'tidak ada' menonaktifkan log kesalahan" "errorLogDesc" = "Jalur file untuk log kesalahan. Nilai khusus 'tidak ada' menonaktifkan log kesalahan"
"dnsLog" = "Log DNS" "dnsLog" = "Log DNS"
"dnsLogDesc" = "Apakah akan mengaktifkan log kueri DNS" "dnsLogDesc" = "Apakah akan mengaktifkan log kueri DNS"
"outboundTraffic" = "Lalu Lintas Keluar"
"outboundTrafficDesc" = "Apakah mengaktifkan lalu lintas keluar"
"maskAddress" = "Alamat Masker" "maskAddress" = "Alamat Masker"
"maskAddressDesc" = "Masker alamat IP, ketika diaktifkan, akan secara otomatis mengganti alamat IP yang muncul di log." "maskAddressDesc" = "Masker alamat IP, ketika diaktifkan, akan secara otomatis mengganti alamat IP yang muncul di log."

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "エラーログのファイルパス。特殊値 'none' はエラーログを無効にします" "errorLogDesc" = "エラーログのファイルパス。特殊値 'none' はエラーログを無効にします"
"dnsLog" = "DNS ログ" "dnsLog" = "DNS ログ"
"dnsLogDesc" = "DNSクエリのログを有効にするかどうか" "dnsLogDesc" = "DNSクエリのログを有効にするかどうか"
"outboundTraffic" = "アウトバウンドトラフィック"
"outboundTrafficDesc" = "アウトバウンドトラフィックを有効にするかどうか"
"maskAddress" = "アドレスをマスク" "maskAddress" = "アドレスをマスク"
"maskAddressDesc" = "IPアドレスをマスクし、有効にするとログに表示されるIPアドレスを自動的に置き換えます" "maskAddressDesc" = "IPアドレスをマスクし、有効にするとログに表示されるIPアドレスを自動的に置き換えます"

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "O caminho do arquivo para o log de erros. O valor especial 'none' desativa os logs de erro." "errorLogDesc" = "O caminho do arquivo para o log de erros. O valor especial 'none' desativa os logs de erro."
"dnsLog" = "Log DNS" "dnsLog" = "Log DNS"
"dnsLogDesc" = "Se ativar logs de consulta DNS" "dnsLogDesc" = "Se ativar logs de consulta DNS"
"outboundTraffic" = "Tráfego de saída"
"outboundTrafficDesc" = "Se deve habilitar o tráfego de saída"
"maskAddress" = "Mascarar Endereço" "maskAddress" = "Mascarar Endereço"
"maskAddressDesc" = "Máscara de endereço IP, quando ativado, substitui automaticamente o endereço IP que aparece no log." "maskAddressDesc" = "Máscara de endereço IP, quando ativado, substitui automaticamente o endereço IP que aparece no log."

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "Путь к файлу журнала ошибок. Специальное значение «none» отключает журналы ошибок." "errorLogDesc" = "Путь к файлу журнала ошибок. Специальное значение «none» отключает журналы ошибок."
"dnsLog" = "DNS Журнал" "dnsLog" = "DNS Журнал"
"dnsLogDesc" = "Включить логи запросов DNS" "dnsLogDesc" = "Включить логи запросов DNS"
"outboundTraffic" = "Исходящий трафик"
"outboundTrafficDesc" = "Включить исходящий трафик"
"maskAddress" = "Маскировать Адрес" "maskAddress" = "Маскировать Адрес"
"maskAddressDesc" = "Маска IP-адреса, при активации автоматически заменяет IP-адрес, который появляется в логе." "maskAddressDesc" = "Маска IP-адреса, при активации автоматически заменяет IP-адрес, который появляется в логе."

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "Hata günlüğü için dosya yolu. 'none' özel değeri hata günlüklerini devre dışı bırakır" "errorLogDesc" = "Hata günlüğü için dosya yolu. 'none' özel değeri hata günlüklerini devre dışı bırakır"
"dnsLog" = "DNS Günlüğü" "dnsLog" = "DNS Günlüğü"
"dnsLogDesc" = "DNS sorgu günlüklerini etkinleştirin" "dnsLogDesc" = "DNS sorgu günlüklerini etkinleştirin"
"outboundTraffic" = "Outbounds Traffic"
"outboundTrafficDesc" = ıkış trafiğini etkinleştirip etkinleştirmeyeceğiniz"
"maskAddress" = "Adres Maskesi" "maskAddress" = "Adres Maskesi"
"maskAddressDesc" = "IP adresi maskesi, etkinleştirildiğinde, günlükte görünen IP adresini otomatik olarak değiştirecektir." "maskAddressDesc" = "IP adresi maskesi, etkinleştirildiğinde, günlükte görünen IP adresini otomatik olarak değiştirecektir."

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "Шлях до файлу журналу помилок. Спеціальне значення 'none' вимикає журнали помилок" "errorLogDesc" = "Шлях до файлу журналу помилок. Спеціальне значення 'none' вимикає журнали помилок"
"dnsLog" = "Журнал DNS" "dnsLog" = "Журнал DNS"
"dnsLogDesc" = "Чи включити журнали запитів DNS" "dnsLogDesc" = "Чи включити журнали запитів DNS"
"outboundTraffic" = "Вихідний трафік"
"outboundTrafficDesc" = "Чи потрібно увімкнути вихідний трафік"
"maskAddress" = "Маскувати Адресу" "maskAddress" = "Маскувати Адресу"
"maskAddressDesc" = "Маска IP-адреси, при активації автоматично замінює IP-адресу, яка з'являється у журналі." "maskAddressDesc" = "Маска IP-адреси, при активації автоматично замінює IP-адресу, яка з'являється у журналі."

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "Đường dẫn tệp cho nhật ký lỗi. Nhật ký lỗi bị vô hiệu hóa có giá trị đặc biệt 'không'" "errorLogDesc" = "Đường dẫn tệp cho nhật ký lỗi. Nhật ký lỗi bị vô hiệu hóa có giá trị đặc biệt 'không'"
"dnsLog" = "Nhật ký DNS" "dnsLog" = "Nhật ký DNS"
"dnsLogDesc" = "Có bật nhật ký truy vấn DNS không" "dnsLogDesc" = "Có bật nhật ký truy vấn DNS không"
"outboundTraffic" = "Outbounds Traffic"
"outboundTrafficDesc" = "Có nên bật lưu lượng ra không"
"maskAddress" = "Ẩn Địa Chỉ" "maskAddress" = "Ẩn Địa Chỉ"
"maskAddressDesc" = "Mặt nạ địa chỉ IP, khi được bật, sẽ tự động thay thế địa chỉ IP xuất hiện trong nhật ký." "maskAddressDesc" = "Mặt nạ địa chỉ IP, khi được bật, sẽ tự động thay thế địa chỉ IP xuất hiện trong nhật ký."

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "错误日志的文件路径。特殊值 'none' 禁用错误日志" "errorLogDesc" = "错误日志的文件路径。特殊值 'none' 禁用错误日志"
"dnsLog" = "DNS 日志" "dnsLog" = "DNS 日志"
"dnsLogDesc" = "是否启用 DNS 查询日志" "dnsLogDesc" = "是否启用 DNS 查询日志"
"outboundTraffic" = "出站流量"
"outboundTrafficDesc" = "是否启用出站流量"
"maskAddress" = "隐藏地址" "maskAddress" = "隐藏地址"
"maskAddressDesc" = "IP 地址掩码,启用时会自动替换日志中出现的 IP 地址。" "maskAddressDesc" = "IP 地址掩码,启用时会自动替换日志中出现的 IP 地址。"

View file

@ -373,6 +373,8 @@
"errorLogDesc" = "錯誤日誌的檔案路徑。特殊值 'none' 禁用錯誤日誌" "errorLogDesc" = "錯誤日誌的檔案路徑。特殊值 'none' 禁用錯誤日誌"
"dnsLog" = "DNS 日誌" "dnsLog" = "DNS 日誌"
"dnsLogDesc" = "是否啟用 DNS 查詢日誌" "dnsLogDesc" = "是否啟用 DNS 查詢日誌"
"outboundTraffic" = "出站流量"
"outboundTrafficDesc" = "是否啟用出站流量"
"maskAddress" = "隱藏地址" "maskAddress" = "隱藏地址"
"maskAddressDesc" = "IP 地址掩碼,啟用時會自動替換日誌中出現的 IP 地址。" "maskAddressDesc" = "IP 地址掩碼,啟用時會自動替換日誌中出現的 IP 地址。"