Compare commits

...

12 Commits

Author SHA1 Message Date
mhsanaei
43713fbdf8 v2.4.2 2024-09-24 15:15:29 +02:00
mhsanaei
dc29e858c9 Xray Core v24.9.19 2024-09-24 15:15:19 +02:00
mhsanaei
c30c6f08f3 Direct Sub Json - geoIP, geoSite 2024-09-24 15:11:16 +02:00
mhsanaei
7c892ac051 Iplimit - warning improved 2024-09-24 13:24:10 +02:00
mhsanaei
75dd7b93f5 update dependencies 2024-09-24 12:19:08 +02:00
mhsanaei
d5de8e1bf3 removeNoise - hide when only one noise 2024-09-24 12:18:42 +02:00
mhsanaei
16b4795956 removed - timeout 2024-09-24 12:00:37 +02:00
Pavel Kogen
e5835c299c OS Support - Amazon Linux (#2564) 2024-09-24 11:53:12 +02:00
mhsanaei
4fdef3cfde add or remove noise 2024-09-24 11:38:10 +02:00
dependabot[bot]
cf6a8bd463 Bump google.golang.org/grpc from 1.66.2 to 1.67.0 (#2563)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.66.2 to 1.67.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.66.2...v1.67.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-20 11:45:21 +02:00
mhsanaei
59a84e844c HTTP - Allow Transparent 2024-09-17 11:37:24 +02:00
mhsanaei
6b0c9a5fad update noise to noises
+ type
2024-09-17 09:51:57 +02:00
35 changed files with 311 additions and 166 deletions

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.9.16/" Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v24.9.19/"
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.9.16/Xray-linux-${ARCH}.zip" wget "https://github.com/XTLS/Xray-core/releases/download/v24.9.19/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

@@ -32,10 +32,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## Instalar una Versión Personalizada ## Instalar una Versión Personalizada
Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.4.1`: Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.4.2`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.1 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.2
``` ```
## Certificado SSL ## Certificado SSL
@@ -225,6 +225,7 @@ location /sub {
- AlmaLinux 9+ - AlmaLinux 9+
- Rockylinux 9+ - Rockylinux 9+
- OpenSUSE Tubleweed - OpenSUSE Tubleweed
- Amazon Linux 2023
## Arquitecturas y Dispositivos Compatibles ## Arquitecturas y Dispositivos Compatibles

View File

@@ -32,10 +32,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## Install Custom Version ## Install Custom Version
To install your desired version, add the version to the end of the installation command. e.g., ver `v2.4.1`: To install your desired version, add the version to the end of the installation command. e.g., ver `v2.4.2`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.1 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.2
``` ```
## SSL Certificate ## SSL Certificate
@@ -254,6 +254,7 @@ location /sub {
- Rocky Linux 9+ - Rocky Linux 9+
- Oracle Linux 8+ - Oracle Linux 8+
- OpenSUSE Tubleweed - OpenSUSE Tubleweed
- Amazon Linux 2023
## Supported Architectures and Devices ## Supported Architectures and Devices

View File

@@ -32,10 +32,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## Установка определённой версии ## Установка определённой версии
Чтобы установить нужную вам версию, добавьте номер версии в конец команды установки. Например, `v2.4.1`: Чтобы установить нужную вам версию, добавьте номер версии в конец команды установки. Например, `v2.4.2`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.1 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.2
``` ```
## SSL Сертификат ## SSL Сертификат
@@ -253,6 +253,7 @@ location /sub {
- Rocky Linux 9+ - Rocky Linux 9+
- Oracle Linux 8+ - Oracle Linux 8+
- OpenSUSE Tubleweed - OpenSUSE Tubleweed
- Amazon Linux 2023
## Поддерживаемые архитектуры и устройства ## Поддерживаемые архитектуры и устройства

View File

@@ -32,10 +32,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## 安装指定版本 ## 安装指定版本
要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.4.1`: 要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.4.2`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.1 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.2
``` ```
### SSL证书 ### SSL证书
@@ -248,6 +248,7 @@ location /sub {
- AlmaLinux 9+ - AlmaLinux 9+
- Rockylinux 9+ - Rockylinux 9+
- OpenSUSE Tubleweed - OpenSUSE Tubleweed
- Amazon Linux 2023
## 支持的架构和设备 ## 支持的架构和设备
<details> <details>

View File

@@ -1 +1 @@
2.4.1 2.4.2

8
go.mod
View File

@@ -17,14 +17,14 @@ require (
github.com/xtls/xray-core v1.8.24 github.com/xtls/xray-core v1.8.24
go.uber.org/atomic v1.11.0 go.uber.org/atomic v1.11.0
golang.org/x/text v0.18.0 golang.org/x/text v0.18.0
google.golang.org/grpc v1.66.2 google.golang.org/grpc v1.67.0
gorm.io/driver/sqlite v1.5.6 gorm.io/driver/sqlite v1.5.6
gorm.io/gorm v1.25.12 gorm.io/gorm v1.25.12
) )
require ( require (
github.com/andybalholm/brotli v1.1.0 // indirect github.com/andybalholm/brotli v1.1.0 // indirect
github.com/bytedance/sonic v1.12.2 // indirect github.com/bytedance/sonic v1.12.3 // indirect
github.com/bytedance/sonic/loader v0.2.0 // indirect github.com/bytedance/sonic/loader v0.2.0 // indirect
github.com/cloudflare/circl v1.4.0 // indirect github.com/cloudflare/circl v1.4.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/base64x v0.1.4 // indirect
@@ -49,7 +49,7 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/compress v1.17.10 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
@@ -64,7 +64,7 @@ require (
github.com/quic-go/quic-go v0.47.0 // indirect github.com/quic-go/quic-go v0.47.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.12.0 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/sagernet/sing v0.4.3 // indirect github.com/sagernet/sing v0.4.3 // indirect
github.com/sagernet/sing-shadowsocks v0.2.7 // indirect github.com/sagernet/sing-shadowsocks v0.2.7 // indirect
github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 // indirect github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 // indirect

10
go.sum
View File

@@ -20,6 +20,8 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/bytedance/sonic v1.12.2 h1:oaMFuRTpMHYLpCntGca65YWt5ny+wAceDERTkT2L9lg= github.com/bytedance/sonic v1.12.2 h1:oaMFuRTpMHYLpCntGca65YWt5ny+wAceDERTkT2L9lg=
github.com/bytedance/sonic v1.12.2/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic v1.12.2/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU=
github.com/bytedance/sonic v1.12.3/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.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
@@ -127,6 +129,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0=
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
@@ -198,6 +202,8 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sagernet/sing v0.4.3 h1:Ty/NAiNnVd6844k7ujlL5lkzydhcTH5Psc432jXA4Y8= github.com/sagernet/sing v0.4.3 h1:Ty/NAiNnVd6844k7ujlL5lkzydhcTH5Psc432jXA4Y8=
github.com/sagernet/sing v0.4.3/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls= github.com/sagernet/sing v0.4.3/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
@@ -374,8 +380,8 @@ google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
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=

View File

@@ -39,12 +39,12 @@ arch() {
echo "arch: $(arch)" echo "arch: $(arch)"
os_version="" os_version=""
os_version=$(grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1) os_version=$(grep "^VERSION_ID" /etc/os-release | cut -d '=' -f2 | tr -d '"')
if [[ "${release}" == "arch" ]]; then if [[ "${release}" == "arch" ]]; then
echo "Your OS is Arch Linux" echo "Your OS is Arch Linux"
elif [[ "${release}" == "parch" ]]; then elif [[ "${release}" == "parch" ]]; then
echo "Your OS is Parch linux" echo "Your OS is Parch Linux"
elif [[ "${release}" == "manjaro" ]]; then elif [[ "${release}" == "manjaro" ]]; then
echo "Your OS is Manjaro" echo "Your OS is Manjaro"
elif [[ "${release}" == "armbian" ]]; then elif [[ "${release}" == "armbian" ]]; then
@@ -63,6 +63,10 @@ elif [[ "${release}" == "fedora" ]]; then
if [[ ${os_version} -lt 36 ]]; then if [[ ${os_version} -lt 36 ]]; then
echo -e "${red} Please use Fedora 36 or higher version!${plain}\n" && exit 1 echo -e "${red} Please use Fedora 36 or higher version!${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "amzn" ]]; then
if [[ ${os_version} != "2023" ]]; then
echo -e "${red} Please use Amazon Linux 2023!${plain}\n" && exit 1
fi
elif [[ "${release}" == "debian" ]]; then elif [[ "${release}" == "debian" ]]; then
if [[ ${os_version} -lt 11 ]]; then if [[ ${os_version} -lt 11 ]]; then
echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1 echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1
@@ -94,8 +98,8 @@ else
echo "- Rocky Linux 9+" echo "- Rocky Linux 9+"
echo "- Oracle Linux 8+" echo "- Oracle Linux 8+"
echo "- OpenSUSE Tumbleweed" echo "- OpenSUSE Tumbleweed"
echo "- Amazon Linux 2023"
exit 1 exit 1
fi fi
install_base() { install_base() {

View File

@@ -92,9 +92,9 @@ func (s *Server) initRouter() (*gin.Engine, error) {
SubJsonFragment = "" SubJsonFragment = ""
} }
SubJsonNoise, err := s.settingService.GetSubJsonNoise() SubJsonNoises, err := s.settingService.GetSubJsonNoises()
if err != nil { if err != nil {
SubJsonNoise = "" SubJsonNoises = ""
} }
SubJsonMux, err := s.settingService.GetSubJsonMux() SubJsonMux, err := s.settingService.GetSubJsonMux()
@@ -111,7 +111,7 @@ func (s *Server) initRouter() (*gin.Engine, error) {
s.sub = NewSUBController( s.sub = NewSUBController(
g, LinksPath, JsonPath, Encrypt, ShowInfo, RemarkModel, SubUpdates, g, LinksPath, JsonPath, Encrypt, ShowInfo, RemarkModel, SubUpdates,
SubJsonFragment, SubJsonNoise, SubJsonMux, SubJsonRules) SubJsonFragment, SubJsonNoises, SubJsonMux, SubJsonRules)
return engine, nil return engine, nil
} }

View File

@@ -21,14 +21,14 @@ type SubJsonService struct {
configJson map[string]interface{} configJson map[string]interface{}
defaultOutbounds []json_util.RawMessage defaultOutbounds []json_util.RawMessage
fragment string fragment string
noise string noises string
mux string mux string
inboundService service.InboundService inboundService service.InboundService
SubService *SubService SubService *SubService
} }
func NewSubJsonService(fragment string, noise string, mux string, rules string, subService *SubService) *SubJsonService { func NewSubJsonService(fragment string, noises string, mux string, rules string, subService *SubService) *SubJsonService {
var configJson map[string]interface{} var configJson map[string]interface{}
var defaultOutbounds []json_util.RawMessage var defaultOutbounds []json_util.RawMessage
json.Unmarshal([]byte(defaultJson), &configJson) json.Unmarshal([]byte(defaultJson), &configJson)
@@ -53,15 +53,15 @@ func NewSubJsonService(fragment string, noise string, mux string, rules string,
defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(fragment)) defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(fragment))
} }
if noise != "" { if noises != "" {
defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(noise)) defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(noises))
} }
return &SubJsonService{ return &SubJsonService{
configJson: configJson, configJson: configJson,
defaultOutbounds: defaultOutbounds, defaultOutbounds: defaultOutbounds,
fragment: fragment, fragment: fragment,
noise: noise, noises: noises,
mux: mux, mux: mux,
SubService: subService, SubService: subService,
} }

View File

@@ -851,39 +851,44 @@ Outbound.Settings = class extends CommonClass {
Outbound.FreedomSettings = class extends CommonClass { Outbound.FreedomSettings = class extends CommonClass {
constructor( constructor(
domainStrategy = '', domainStrategy = '',
timeout = 10,
redirect = '', redirect = '',
fragment = {}, fragment = {},
noise = {} noises = []
) { ) {
super(); super();
this.domainStrategy = domainStrategy; this.domainStrategy = domainStrategy;
this.timeout = timeout;
this.redirect = redirect; this.redirect = redirect;
this.fragment = fragment; this.fragment = fragment;
this.noise = noise; this.noises = noises;
}
addNoise() {
this.noises.push(new Outbound.FreedomSettings.Noise());
}
delNoise(index) {
this.noises.splice(index, 1);
} }
static fromJson(json = {}) { static fromJson(json = {}) {
return new Outbound.FreedomSettings( return new Outbound.FreedomSettings(
json.domainStrategy, json.domainStrategy,
json.timeout,
json.redirect, json.redirect,
json.fragment ? Outbound.FreedomSettings.Fragment.fromJson(json.fragment) : undefined, json.fragment ? Outbound.FreedomSettings.Fragment.fromJson(json.fragment) : undefined,
json.noise ? Outbound.FreedomSettings.Noise.fromJson(json.noise) : undefined, json.noises ? json.noises.map(noise => Outbound.FreedomSettings.Noise.fromJson(noise)) : [new Outbound.FreedomSettings.Noise()],
); );
} }
toJson() { toJson() {
return { return {
domainStrategy: ObjectUtil.isEmpty(this.domainStrategy) ? undefined : this.domainStrategy, domainStrategy: ObjectUtil.isEmpty(this.domainStrategy) ? undefined : this.domainStrategy,
timeout: this.timeout,
redirect: this.redirect, redirect: this.redirect,
fragment: Object.keys(this.fragment).length === 0 ? undefined : this.fragment, fragment: Object.keys(this.fragment).length === 0 ? undefined : this.fragment,
noise: Object.keys(this.noise).length === 0 ? undefined : this.noise, noises: Outbound.FreedomSettings.Noise.toJsonArray(this.noises),
}; };
} }
}; };
Outbound.FreedomSettings.Fragment = class extends CommonClass { Outbound.FreedomSettings.Fragment = class extends CommonClass {
constructor(packets = '1-3', length = '', interval = '') { constructor(packets = '1-3', length = '', interval = '') {
super(); super();
@@ -900,19 +905,38 @@ Outbound.FreedomSettings.Fragment = class extends CommonClass {
); );
} }
}; };
Outbound.FreedomSettings.Noise = class extends CommonClass { Outbound.FreedomSettings.Noise = class extends CommonClass {
constructor(packet = 'rand:100-200', delay = '10-20') { constructor(
type = 'rand',
packet = '10-20',
delay = '10-16'
) {
super(); super();
this.type = type;
this.packet = packet; this.packet = packet;
this.delay = delay; this.delay = delay;
} }
static fromJson(json = {}) { static fromJson(json = {}) {
return new Outbound.FreedomSettings.Noise( return new Outbound.FreedomSettings.Noise(
json.type,
json.packet, json.packet,
json.delay, json.delay,
); );
} }
toJson() {
return {
type: this.type,
packet: this.packet,
delay: this.delay,
};
}
static toJsonArray(noises) {
return noises.map(noise => noise.toJson());
}
}; };
Outbound.BlackholeSettings = class extends CommonClass { Outbound.BlackholeSettings = class extends CommonClass {

View File

@@ -38,7 +38,7 @@ class AllSetting {
this.subURI = ""; this.subURI = "";
this.subJsonURI = ""; this.subJsonURI = "";
this.subJsonFragment = ""; this.subJsonFragment = "";
this.subJsonNoise = ""; this.subJsonNoises = "";
this.subJsonMux = ""; this.subJsonMux = "";
this.subJsonRules = ""; this.subJsonRules = "";

View File

@@ -530,8 +530,8 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
noSSEHeader = false, noSSEHeader = false,
xPaddingBytes = "100-1000", xPaddingBytes = "100-1000",
xmux = { xmux = {
maxConnections: 0,
maxConcurrency: 0, maxConcurrency: 0,
maxConnections: 0,
cMaxReuseTimes: 0, cMaxReuseTimes: 0,
cMaxLifetimeMs: 0 cMaxLifetimeMs: 0
} }
@@ -581,8 +581,8 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
noSSEHeader: this.noSSEHeader, noSSEHeader: this.noSSEHeader,
xPaddingBytes: this.xPaddingBytes, xPaddingBytes: this.xPaddingBytes,
xmux: { xmux: {
maxConnections: this.xmux.maxConnections,
maxConcurrency: this.xmux.maxConcurrency, maxConcurrency: this.xmux.maxConcurrency,
maxConnections: this.xmux.maxConnections,
cMaxReuseTimes: this.xmux.cMaxReuseTimes, cMaxReuseTimes: this.xmux.cMaxReuseTimes,
cMaxLifetimeMs: this.xmux.cMaxLifetimeMs cMaxLifetimeMs: this.xmux.cMaxLifetimeMs
} }
@@ -2513,15 +2513,13 @@ Inbound.DokodemoSettings = class extends Inbound.Settings {
address, address,
port, port,
network = 'tcp,udp', network = 'tcp,udp',
followRedirect = false, followRedirect = false
timeout = 30
) { ) {
super(protocol); super(protocol);
this.address = address; this.address = address;
this.port = port; this.port = port;
this.network = network; this.network = network;
this.followRedirect = followRedirect; this.followRedirect = followRedirect;
this.timeout = timeout;
} }
static fromJson(json = {}) { static fromJson(json = {}) {
@@ -2531,7 +2529,6 @@ Inbound.DokodemoSettings = class extends Inbound.Settings {
json.port, json.port,
json.network, json.network,
json.followRedirect, json.followRedirect,
json.timeout,
); );
} }
@@ -2541,7 +2538,6 @@ Inbound.DokodemoSettings = class extends Inbound.Settings {
port: this.port, port: this.port,
network: this.network, network: this.network,
followRedirect: this.followRedirect, followRedirect: this.followRedirect,
timeout: this.timeout,
}; };
} }
}; };
@@ -2601,9 +2597,14 @@ Inbound.SocksSettings.SocksAccount = class extends XrayCommonClass {
}; };
Inbound.HttpSettings = class extends Inbound.Settings { Inbound.HttpSettings = class extends Inbound.Settings {
constructor(protocol, accounts = [new Inbound.HttpSettings.HttpAccount()]) { constructor(
protocol,
accounts = [new Inbound.HttpSettings.HttpAccount()],
allowTransparent = false,
) {
super(protocol); super(protocol);
this.accounts = accounts; this.accounts = accounts;
this.allowTransparent = allowTransparent;
} }
addAccount(account) { addAccount(account) {
@@ -2618,12 +2619,14 @@ Inbound.HttpSettings = class extends Inbound.Settings {
return new Inbound.HttpSettings( return new Inbound.HttpSettings(
Protocols.HTTP, Protocols.HTTP,
json.accounts.map(account => Inbound.HttpSettings.HttpAccount.fromJson(account)), json.accounts.map(account => Inbound.HttpSettings.HttpAccount.fromJson(account)),
json.allowTransparent,
); );
} }
toJson() { toJson() {
return { return {
accounts: Inbound.HttpSettings.toJsonArray(this.accounts), accounts: Inbound.HttpSettings.toJsonArray(this.accounts),
allowTransparent: this.allowTransparent,
}; };
} }
}; };

View File

@@ -52,7 +52,7 @@ type AllSetting struct {
SubJsonPath string `json:"subJsonPath" form:"subJsonPath"` SubJsonPath string `json:"subJsonPath" form:"subJsonPath"`
SubJsonURI string `json:"subJsonURI" form:"subJsonURI"` SubJsonURI string `json:"subJsonURI" form:"subJsonURI"`
SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"` SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"`
SubJsonNoise string `json:"subJsonNoise" form:"subJsonNoise"` SubJsonNoises string `json:"subJsonNoises" form:"subJsonNoises"`
SubJsonMux string `json:"subJsonMux" form:"subJsonMux"` SubJsonMux string `json:"subJsonMux" form:"subJsonMux"`
SubJsonRules string `json:"subJsonRules" form:"subJsonRules"` SubJsonRules string `json:"subJsonRules" form:"subJsonRules"`
Datepicker string `json:"datepicker" form:"datepicker"` Datepicker string `json:"datepicker" form:"datepicker"`

View File

@@ -22,9 +22,6 @@
<a-select-option v-for="s in OutboundDomainStrategies" :value="s">[[ s ]]</a-select-option> <a-select-option v-for="s in OutboundDomainStrategies" :value="s">[[ s ]]</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item label='Timeout'>
<a-input-number v-model.number="outbound.settings.timeout" min="0" ></a-input-number>
</a-form-item>
<a-form-item label='Redirect'> <a-form-item label='Redirect'>
<a-input v-model="outbound.settings.redirect"></a-input> <a-input v-model="outbound.settings.redirect"></a-input>
</a-form-item> </a-form-item>
@@ -46,16 +43,39 @@
<a-input v-model.trim="outbound.settings.fragment.interval"></a-input> <a-input v-model.trim="outbound.settings.fragment.interval"></a-input>
</a-form-item> </a-form-item>
</template> </template>
<a-form-item label='Noise'>
<a-switch :checked="Object.keys(outbound.settings.noise).length >0" @change="checked => outbound.settings.noise = checked ? new Outbound.FreedomSettings.Noise() : {}"></a-switch> <!-- Switch for Noises -->
<a-form-item label='Noises'>
<a-switch :checked="outbound.settings.noises.length > 0"
@change="checked => outbound.settings.noises = checked ? [new Outbound.FreedomSettings.Noise()] : []">
</a-switch>
</a-form-item> </a-form-item>
<template v-if="Object.keys(outbound.settings.noise).length >0">
<a-form-item label='Packet'> <!-- Add Noise Button -->
<a-input v-model.trim="outbound.settings.noise.packet"></a-input> <template v-if="outbound.settings.noises.length > 0">
</a-form-item> <a-form-item label="Noises">
<a-form-item label='Delay'> <a-button icon="plus" type="primary" size="small" @click="outbound.settings.addNoise()"></a-button>
<a-input v-model.trim="outbound.settings.noise.delay"></a-input>
</a-form-item> </a-form-item>
<!-- Noise Configurations -->
<a-form v-for="(noise, index) in outbound.settings.noises" :key="index" :colon="false" :label-col="{ md: {span:8} }"
:wrapper-col="{ md: {span:14} }">
<a-divider style="margin:0;"> Noise [[ index + 1 ]]
<a-icon v-if="outbound.settings.noises.length > 1" type="delete" @click="() => outbound.settings.delNoise(index)"
style="color: rgb(255, 77, 79); cursor: pointer;"></a-icon>
</a-divider>
<a-form-item label='Type'>
<a-select v-model="noise.type" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="s in ['rand','base64','str']" :value="s">[[ s ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='Packet'>
<a-input v-model.trim="noise.packet"></a-input>
</a-form-item>
<a-form-item label='Delay'>
<a-input v-model.trim="noise.delay"></a-input>
</a-form-item>
</a-form>
</template> </template>
</template> </template>

View File

@@ -16,8 +16,5 @@
<a-form-item label='Follow Redirect'> <a-form-item label='Follow Redirect'>
<a-switch v-model="inbound.settings.followRedirect"></a-switch> <a-switch v-model="inbound.settings.followRedirect"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label='Timeout'>
<a-input-number v-model.number="inbound.settings.timeout" :min="0"></a-input-number>
</a-form-item>
</a-form> </a-form>
{{end}} {{end}}

View File

@@ -19,5 +19,8 @@
</template> </template>
</a-input> </a-input>
</a-input-group> </a-input-group>
<a-form-item label="Allow Transparent">
<a-switch v-model="inbound.settings.allowTransparent" />
</a-form-item>
</a-form> </a-form>
{{end}} {{end}}

View File

@@ -34,17 +34,17 @@
<a-form-item label="No SSE Header"> <a-form-item label="No SSE Header">
<a-switch v-model="inbound.stream.splithttp.noSSEHeader"></a-switch> <a-switch v-model="inbound.stream.splithttp.noSSEHeader"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label="Max Connections">
<a-input-number v-model.trim="inbound.stream.splithttp.xmux.maxConnections"></a-input-number>
</a-form-item>
<a-form-item label="Max Concurrency"> <a-form-item label="Max Concurrency">
<a-input-number v-model.trim="inbound.stream.splithttp.xmux.maxConcurrency"></a-input-number> <a-input-number v-model="inbound.stream.splithttp.xmux.maxConcurrency"></a-input-number>
</a-form-item>
<a-form-item label="Max Connections">
<a-input-number v-model="inbound.stream.splithttp.xmux.maxConnections"></a-input-number>
</a-form-item> </a-form-item>
<a-form-item label="Max Reuse Times"> <a-form-item label="Max Reuse Times">
<a-input-number v-model.trim="inbound.stream.splithttp.xmux.cMaxReuseTimes"></a-input-number> <a-input-number v-model="inbound.stream.splithttp.xmux.cMaxReuseTimes"></a-input-number>
</a-form-item> </a-form-item>
<a-form-item label="Max Lifetime (ms)"> <a-form-item label="Max Lifetime (ms)">
<a-input-number v-model.trim="inbound.stream.splithttp.xmux.cMaxLifetimeMs"></a-input-number> <a-input-number v-model="inbound.stream.splithttp.xmux.cMaxLifetimeMs"></a-input-number>
</a-form-item> </a-form-item>
</a-form> </a-form>
{{end}} {{end}}

View File

@@ -305,20 +305,38 @@
<a-list-item style="padding: 20px"> <a-list-item style="padding: 20px">
<a-row> <a-row>
<a-col :lg="24" :xl="12"> <a-col :lg="24" :xl="12">
<a-list-item-meta title='Noise'> <a-list-item-meta title='Noises'>
<template slot="description">{{ i18n "pages.settings.noiseDesc"}}</template> <template slot="description">{{ i18n "pages.settings.noisesDesc"}}</template>
</a-list-item-meta> </a-list-item-meta>
</a-col> </a-col>
<a-col :lg="24" :xl="12"> <a-col :lg="24" :xl="12">
<a-switch v-model="noise"></a-switch> <a-switch v-model="noises"></a-switch>
</a-col> </a-col>
</a-row> </a-row>
<a-collapse v-if="noise" style="margin-top: 14px;"> <a-collapse v-if="noises" style="margin-top: 14px;">
<a-collapse-panel header='{{ i18n "pages.settings.noiseSett"}}' v-if="noise"> <a-collapse-panel v-for="(noise, index) in noisesArray" :key="index" :header="`Noise ${index + 1}`">
<setting-list-item style="padding: 10px 20px" type="text" title='Packet (ms)' v-model="noisePacket" placeholder="rand:5-10"></setting-list-item> <a-list-item style="padding: 10px 20px">
<setting-list-item style="padding: 10px 20px" type="text" title='Delay (ms)' v-model="noiseDelay" placeholder="10-20"></setting-list-item> <a-row>
<a-col :lg="24" :xl="12">
<a-list-item-meta title='Type'></a-list-item-meta>
</a-col>
<a-col :lg="24" :xl="12">
<a-select :value="noise.type" style="width: 100%" :dropdown-class-name="themeSwitcher.currentTheme"
@change="(value) => updateNoiseType(index, value)">
<a-select-option :value="p" :label="p" v-for="p in ['rand', 'base64', 'str']" :key="p">
[[ p ]] </a-select-option>
</a-select>
</a-col>
</a-row>
</a-list-item>
<setting-list-item style="padding: 10px 20px" type="text" title='Packet' :value="noise.packet"
@input="(value) => updateNoisePacket(index, value)" placeholder="5-10"></setting-list-item>
<setting-list-item style="padding: 10px 20px" type="text" title='Delay (ms)' :value="noise.delay"
@input="(value) => updateNoiseDelay(index, value)" placeholder="10-20"></setting-list-item>
<a-button v-if="noisesArray.length > 1" type="danger" @click="removeNoise(index)">Remove</a-button>
</a-collapse-panel> </a-collapse-panel>
</a-collapse> </a-collapse>
<a-button v-if="noises" type="primary" @click="addNoise" style="margin-top: 10px">Add Noise</a-button>
</a-list-item> </a-list-item>
<a-list-item style="padding: 20px"> <a-list-item style="padding: 20px">
<a-row> <a-row>
@@ -362,9 +380,14 @@
</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.settings.directSett"}}'> <a-collapse-panel header='Geo IP'>
<a-list-item style="padding: 10px 20px"> <a-list-item style="padding: 10px 20px">
<a-checkbox-group v-model="directCountries" name="Countries" :options="countryOptions"></a-checkbox-group> <a-checkbox-group v-model="geoIP" name="Geo IP" :options="geoIPOptions"></a-checkbox-group>
</a-list-item>
</a-collapse-panel>
<a-collapse-panel header='Geo Site'>
<a-list-item style="padding: 10px 20px">
<a-checkbox-group v-model="geoSite" name="Geo Site" :options="geoSiteOptions"></a-checkbox-group>
</a-list-item> </a-list-item>
</a-collapse-panel> </a-collapse-panel>
</a-collapse> </a-collapse>
@@ -419,15 +442,14 @@
} }
} }
}, },
defaultNoise: { defaultNoises: {
tag: "noise", tag: "noises",
protocol: "freedom", protocol: "freedom",
settings: { settings: {
domainStrategy: "AsIs", domainStrategy: "AsIs",
noise: { noises: [
packet: "rand:5-10", { type: "rand", packet: "10-20", delay: "10-16" },
delay: "10-20", ],
}
}, },
}, },
defaultMux: { defaultMux: {
@@ -441,8 +463,7 @@
type: "field", type: "field",
outboundTag: "direct", outboundTag: "direct",
domain: [ domain: [
"geosite:category-ir", "geosite:category-ir"
"geosite:cn"
], ],
"enabled": true "enabled": true
}, },
@@ -451,17 +472,30 @@
outboundTag: "direct", outboundTag: "direct",
ip: [ ip: [
"geoip:private", "geoip:private",
"geoip:ir", "geoip:ir"
"geoip:cn"
], ],
enabled: true enabled: true
}, },
], ],
countryOptions: [ geoIPOptions: [
{ label: 'Private IP/Domain', value: 'private' }, { label: 'Private IP/Domain', value: 'private' },
{ label: '🇮🇷 Iran', value: 'ir' }, { label: '🇮🇷 Iran', value: 'ir' },
{ label: '🇨🇳 China', value: 'cn' }, { label: '🇨🇳 China', value: 'cn' },
{ label: '🇷🇺 Russia', value: 'ru' }, { label: '🇷🇺 Russia', value: 'ru' },
{ label: '🇻🇳 Vietnam', value: 'vn' },
{ label: '🇪🇸 Spain', value: 'es' },
{ label: '🇮🇩 Indonesia', value: 'id' },
{ label: '🇺🇦 Ukraine', value: 'ua' },
{ label: '🇹🇷 Türkiye', value: 'tr' },
{ label: '🇧🇷 Brazil', value: 'br' },
],
geoSiteOptions: [
{ label: '🇮🇷 Iran', value: 'ir' },
{ label: '🇨🇳 China', value: 'cn' },
{ label: '🇷🇺 Russia', value: 'ru' },
{ label: 'Apple', value: 'apple' },
{ label: 'Meta', value: 'meta' },
{ label: 'Google', value: 'google' },
], ],
get remarkModel() { get remarkModel() {
rm = this.allSetting.remarkModel; rm = this.allSetting.remarkModel;
@@ -591,6 +625,30 @@
this.user.loginSecret = ""; this.user.loginSecret = "";
} }
}, },
addNoise() {
const newNoise = { type: "rand", packet: "10-20", delay: "10-16" };
this.noisesArray = [...this.noisesArray, newNoise];
},
removeNoise(index) {
const newNoises = [...this.noisesArray];
newNoises.splice(index, 1);
this.noisesArray = newNoises;
},
updateNoiseType(index, value) {
const updatedNoises = [...this.noisesArray];
updatedNoises[index] = { ...updatedNoises[index], type: value };
this.noisesArray = updatedNoises;
},
updateNoisePacket(index, value) {
const updatedNoises = [...this.noisesArray];
updatedNoises[index] = { ...updatedNoises[index], packet: value };
this.noisesArray = updatedNoises;
},
updateNoiseDelay(index, value) {
const updatedNoises = [...this.noisesArray];
updatedNoises[index] = { ...updatedNoises[index], delay: value };
this.noisesArray = updatedNoises;
},
}, },
computed: { computed: {
fragment: { fragment: {
@@ -629,29 +687,27 @@
} }
} }
}, },
noise: { noises: {
get: function () { return this.allSetting?.subJsonNoise != ""; }, get() {
set: function (v) { return this.allSetting?.subJsonNoises != "";
this.allSetting.subJsonNoise = v ? JSON.stringify(this.defaultNoise) : ""; },
} set(v) {
}, if (v) {
noisePacket: { this.allSetting.subJsonNoises = JSON.stringify(this.defaultNoises);
get: function () { return this.noise ? JSON.parse(this.allSetting.subJsonNoise).settings.noise.packet : ""; }, } else {
set: function (v) { this.allSetting.subJsonNoises = "";
if (v != "") {
newNoise = JSON.parse(this.allSetting.subJsonNoise);
newNoise.settings.noise.packet = v;
this.allSetting.subJsonNoise = JSON.stringify(newNoise);
} }
} }
}, },
noiseDelay: { noisesArray: {
get: function () { return this.noise ? JSON.parse(this.allSetting.subJsonNoise).settings.noise.delay : ""; }, get() {
set: function (v) { return this.noises ? JSON.parse(this.allSetting.subJsonNoises).settings.noises : [];
if (v != "") { },
newNoise = JSON.parse(this.allSetting.subJsonNoise); set(value) {
newNoise.settings.noise.delay = v; if (this.noises) {
this.allSetting.subJsonNoise = JSON.stringify(newNoise); const newNoises = JSON.parse(this.allSetting.subJsonNoises);
newNoises.settings.noises = value;
this.allSetting.subJsonNoises = JSON.stringify(newNoises);
} }
} }
}, },
@@ -691,26 +747,49 @@
this.allSetting.subJsonRules = v ? JSON.stringify(this.defaultRules) : ""; this.allSetting.subJsonRules = v ? JSON.stringify(this.defaultRules) : "";
} }
}, },
directCountries: { geoIP: {
get: function () { get: function () {
if (!this.enableDirect) return []; if (!this.enableDirect) return [];
rules = JSON.parse(this.allSetting.subJsonRules); const rules = JSON.parse(this.allSetting.subJsonRules);
return Array.isArray(rules) ? rules[1].ip.map(d => d.replace("geoip:", "")) : []; return Array.isArray(rules) ? rules[1].ip.map(d => d.replace("geoip:", "")) : [];
}, },
set: function (v) { set: function (v) {
rules = JSON.parse(this.allSetting.subJsonRules); const rules = JSON.parse(this.allSetting.subJsonRules);
if (!Array.isArray(rules)) return; if (!Array.isArray(rules)) return;
rules[0].domain = [];
rules[1].ip = []; rules[1].ip = [];
v.forEach(d => {
rules[1].ip.push("geoip:" + d);
});
this.allSetting.subJsonRules = JSON.stringify(rules);
}
},
geoSite: {
get: function () {
if (!this.enableDirect) return [];
const rules = JSON.parse(this.allSetting.subJsonRules);
return Array.isArray(rules) ?
rules[0].domain.map(d => {
if (d.startsWith("geosite:category-")) {
return d.replace("geosite:category-", "");
}
return d.replace("geosite:", "");
})
: [];
},
set: function (v) {
const rules = JSON.parse(this.allSetting.subJsonRules);
if (!Array.isArray(rules)) return;
rules[0].domain = [];
v.forEach(d => { v.forEach(d => {
let category = ''; let category = '';
if (["cn", "private"].includes(d)) { if (["cn", "apple", "meta", "google"].includes(d)) {
category = ""; category = "";
} else if (["ru", "ir"].includes(d)) { } else if (["ru", "ir"].includes(d)) {
category = "category-"; category = "category-";
} }
rules[0].domain.push("geosite:" + category + d); rules[0].domain.push("geosite:" + category + d);
rules[1].ip.push("geoip:" + d);
}); });
this.allSetting.subJsonRules = JSON.stringify(rules); this.allSetting.subJsonRules = JSON.stringify(rules);
} }

View File

@@ -37,17 +37,11 @@ func (j *CheckClientIpJob) Run() {
shouldClearAccessLog := false shouldClearAccessLog := false
iplimitActive := j.hasLimitIp() iplimitActive := j.hasLimitIp()
f2bInstalled := j.checkFail2BanInstalled() f2bInstalled := j.checkFail2BanInstalled(iplimitActive)
isAccessLogAvailable := j.checkAccessLogAvailable(iplimitActive) isAccessLogAvailable := j.checkAccessLogAvailable(iplimitActive)
if iplimitActive { if iplimitActive && f2bInstalled && isAccessLogAvailable {
if f2bInstalled && isAccessLogAvailable { shouldClearAccessLog = j.processLogFile()
shouldClearAccessLog = j.processLogFile()
} else {
if !f2bInstalled {
logger.Warning("[iplimit] fail2ban is not installed. IP limiting may not work properly.")
}
}
} }
if shouldClearAccessLog || (isAccessLogAvailable && time.Now().Unix()-j.lastClear > 3600) { if shouldClearAccessLog || (isAccessLogAvailable && time.Now().Unix()-j.lastClear > 3600) {
@@ -168,11 +162,17 @@ func (j *CheckClientIpJob) processLogFile() bool {
return shouldCleanLog return shouldCleanLog
} }
func (j *CheckClientIpJob) checkFail2BanInstalled() bool { func (j *CheckClientIpJob) checkFail2BanInstalled(iplimitActive bool) bool {
cmd := "fail2ban-client" cmd := "fail2ban-client"
args := []string{"-h"} args := []string{"-h"}
err := exec.Command(cmd, args...).Run() err := exec.Command(cmd, args...).Run()
return err == nil
if iplimitActive && err != nil {
logger.Warning("[LimitIP] Fail2Ban is not installed, Please install Fail2Ban from the x-ui bash menu.")
return false
}
return true
} }
func (j *CheckClientIpJob) checkAccessLogAvailable(iplimitActive bool) bool { func (j *CheckClientIpJob) checkAccessLogAvailable(iplimitActive bool) bool {
@@ -183,7 +183,7 @@ func (j *CheckClientIpJob) checkAccessLogAvailable(iplimitActive bool) bool {
if accessLogPath == "none" || accessLogPath == "" { if accessLogPath == "none" || accessLogPath == "" {
if iplimitActive { if iplimitActive {
logger.Warning("Access log path is not set, and IP limit is active. Please configure the access log path.") logger.Warning("[LimitIP] Access log path is not set, Please configure the access log path in Xray configs.")
} }
return false return false
} }

View File

@@ -2,8 +2,9 @@
"log": { "log": {
"access": "none", "access": "none",
"dnsLog": false, "dnsLog": false,
"error": "./error.log", "error": "",
"loglevel": "warning" "loglevel": "warning",
"maskAddress": ""
}, },
"api": { "api": {
"tag": "api", "tag": "api",

View File

@@ -62,7 +62,7 @@ var defaultValueMap = map[string]string{
"subJsonPath": "/json/", "subJsonPath": "/json/",
"subJsonURI": "", "subJsonURI": "",
"subJsonFragment": "", "subJsonFragment": "",
"subJsonNoise": "", "subJsonNoises": "",
"subJsonMux": "", "subJsonMux": "",
"subJsonRules": "", "subJsonRules": "",
"datepicker": "gregorian", "datepicker": "gregorian",
@@ -459,8 +459,8 @@ func (s *SettingService) GetSubJsonFragment() (string, error) {
return s.getString("subJsonFragment") return s.getString("subJsonFragment")
} }
func (s *SettingService) GetSubJsonNoise() (string, error) { func (s *SettingService) GetSubJsonNoises() (string, error) {
return s.getString("subJsonNoise") return s.getString("subJsonNoises")
} }
func (s *SettingService) GetSubJsonMux() (string, error) { func (s *SettingService) GetSubJsonMux() (string, error) {

View File

@@ -309,14 +309,14 @@
"fragment" = "Fragmentation" "fragment" = "Fragmentation"
"fragmentDesc" = "Enable fragmentation for TLS hello packet." "fragmentDesc" = "Enable fragmentation for TLS hello packet."
"fragmentSett" = "Fragmentation Settings" "fragmentSett" = "Fragmentation Settings"
"noiseDesc" = "Enable Noise." "noisesDesc" = "Enable Noises."
"noiseSett" = "Noise Settings" "noisesSett" = "Noises Settings"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Transmit multiple independent data streams within an established data stream." "muxDesc" = "Transmit multiple independent data streams within an established data stream."
"muxSett" = "Mux Settings" "muxSett" = "Mux Settings"
"direct" = "Direct Connection" "direct" = "Direct Connection"
"directDesc" = "Directly establishes connections with domains or IP ranges of a specific country." "directDesc" = "Directly establishes connections with domains or IP ranges of a specific country."
"directSett" = "Direct Connection Options"
[pages.xray] [pages.xray]
"title" = "Xray Configs" "title" = "Xray Configs"

View File

@@ -309,14 +309,14 @@
"fragment" = "Fragmentación" "fragment" = "Fragmentación"
"fragmentDesc" = "Habilitar la fragmentación para el paquete de saludo de TLS" "fragmentDesc" = "Habilitar la fragmentación para el paquete de saludo de TLS"
"fragmentSett" = "Configuración de Fragmentación" "fragmentSett" = "Configuración de Fragmentación"
"noiseDesc" = "Activar Noise." "noisesDesc" = "Activar Noises."
"noiseSett" = "Configuración de Noise" "noisesSett" = "Configuración de Noises"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Transmite múltiples flujos de datos independientes dentro de un flujo de datos establecido." "muxDesc" = "Transmite múltiples flujos de datos independientes dentro de un flujo de datos establecido."
"muxSett" = "Configuración Mux" "muxSett" = "Configuración Mux"
"direct" = "Conexión Directa" "direct" = "Conexión Directa"
"directDesc" = "Establece conexiones directas con dominios o rangos de IP de un país específico." "directDesc" = "Establece conexiones directas con dominios o rangos de IP de un país específico."
"directSett" = "Opciones de Conexión Directa"
[pages.xray] [pages.xray]
"title" = "Xray Configuración" "title" = "Xray Configuración"

View File

@@ -309,14 +309,14 @@
"fragment" = "فرگمنت" "fragment" = "فرگمنت"
"fragmentDesc" = "فعال کردن فرگمنت برای بسته‌ی نخست تی‌ال‌اس" "fragmentDesc" = "فعال کردن فرگمنت برای بسته‌ی نخست تی‌ال‌اس"
"fragmentSett" = "تنظیمات فرگمنت" "fragmentSett" = "تنظیمات فرگمنت"
"noiseDesc" = "فعال کردن Noise." "noisesDesc" = "فعال کردن Noises."
"noiseSett" = "تنظیمات Noise" "noisesSett" = "تنظیمات Noises"
"mux" = "ماکس" "mux" = "ماکس"
"muxDesc" = "چندین جریان داده مستقل را در یک جریان داده ثابت منتقل می کند" "muxDesc" = "چندین جریان داده مستقل را در یک جریان داده ثابت منتقل می کند"
"muxSett" = "تنظیمات ماکس" "muxSett" = "تنظیمات ماکس"
"direct" = "اتصال مستقیم" "direct" = "اتصال مستقیم"
"directDesc" = "به طور مستقیم با دامنه ها یا محدوده آی‌پی یک کشور خاص ارتباط برقرار می کند" "directDesc" = "به طور مستقیم با دامنه ها یا محدوده آی‌پی یک کشور خاص ارتباط برقرار می کند"
"directSett" = "گزینه های اتصال مستقیم"
[pages.xray] [pages.xray]
"title" = "پیکربندی ایکس‌ری" "title" = "پیکربندی ایکس‌ری"

View File

@@ -309,14 +309,14 @@
"fragment" = "Fragmentasi" "fragment" = "Fragmentasi"
"fragmentDesc" = "Aktifkan fragmentasi untuk paket hello TLS" "fragmentDesc" = "Aktifkan fragmentasi untuk paket hello TLS"
"fragmentSett" = "Pengaturan Fragmentasi" "fragmentSett" = "Pengaturan Fragmentasi"
"noiseDesc" = "Aktifkan Noise." "noisesDesc" = "Aktifkan Noises."
"noiseSett" = "Pengaturan Noise" "noisesSett" = "Pengaturan Noises"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Mengirimkan beberapa aliran data independen dalam aliran data yang sudah ada." "muxDesc" = "Mengirimkan beberapa aliran data independen dalam aliran data yang sudah ada."
"muxSett" = "Pengaturan Mux" "muxSett" = "Pengaturan Mux"
"direct" = "Koneksi langsung" "direct" = "Koneksi langsung"
"directDesc" = "Secara langsung membuat koneksi dengan domain atau rentang IP negara tertentu." "directDesc" = "Secara langsung membuat koneksi dengan domain atau rentang IP negara tertentu."
"directSett" = "Opsi Koneksi Langsung"
[pages.xray] [pages.xray]
"title" = "Konfigurasi Xray" "title" = "Konfigurasi Xray"

View File

@@ -309,14 +309,14 @@
"fragment" = "Fragmentação" "fragment" = "Fragmentação"
"fragmentDesc" = "Ativa a fragmentação para o pacote TLS hello." "fragmentDesc" = "Ativa a fragmentação para o pacote TLS hello."
"fragmentSett" = "Configurações de Fragmentação" "fragmentSett" = "Configurações de Fragmentação"
"noiseDesc" = "Ativar Noise." "noisesDesc" = "Ativar Noises."
"noiseSett" = "Configurações de Noise" "noisesSett" = "Configurações de Noises"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Transmitir múltiplos fluxos de dados independentes dentro de um fluxo de dados estabelecido." "muxDesc" = "Transmitir múltiplos fluxos de dados independentes dentro de um fluxo de dados estabelecido."
"muxSett" = "Configurações de Mux" "muxSett" = "Configurações de Mux"
"direct" = "Conexão Direta" "direct" = "Conexão Direta"
"directDesc" = "Estabelece conexões diretamente com domínios ou intervalos de IP de um país específico." "directDesc" = "Estabelece conexões diretamente com domínios ou intervalos de IP de um país específico."
"directSett" = "Opções de Conexão Direta"
[pages.xray] [pages.xray]
"title" = "Configurações Xray" "title" = "Configurações Xray"

View File

@@ -309,14 +309,14 @@
"fragment" = "Фрагментация" "fragment" = "Фрагментация"
"fragmentDesc" = "Включить фрагментацию для пакета приветствия TLS" "fragmentDesc" = "Включить фрагментацию для пакета приветствия TLS"
"fragmentSett" = "Настройки фрагментации" "fragmentSett" = "Настройки фрагментации"
"noiseDesc" = "Включить Noise." "noisesDesc" = "Включить Noises."
"noiseSett" = "Настройки Noise" "noisesSett" = "Настройки Noises"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Передача нескольких независимых потоков данных в рамках установленного потока данных." "muxDesc" = "Передача нескольких независимых потоков данных в рамках установленного потока данных."
"muxSett" = "Mux Настройки" "muxSett" = "Mux Настройки"
"direct" = "Прямая связь" "direct" = "Прямая связь"
"directDesc" = "Напрямую устанавливает соединения с доменами или диапазонами IP конкретной страны." "directDesc" = "Напрямую устанавливает соединения с доменами или диапазонами IP конкретной страны."
"directSett" = "Варианты прямого подключения"
[pages.xray] [pages.xray]
"title" = "Настройки Xray" "title" = "Настройки Xray"

View File

@@ -309,14 +309,14 @@
"fragment" = "Parçalama" "fragment" = "Parçalama"
"fragmentDesc" = "TLS merhaba paketinin parçalanmasını etkinleştir." "fragmentDesc" = "TLS merhaba paketinin parçalanmasını etkinleştir."
"fragmentSett" = "Parçalama Ayarları" "fragmentSett" = "Parçalama Ayarları"
"noiseDesc" = "Noise'i Etkinleştir." "noisesDesc" = "Noises'i Etkinleştir."
"noiseSett" = "Noise Ayarları" "noisesSett" = "Noises Ayarları"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Kurulmuş bir veri akışında birden çok bağımsız veri akışını iletir." "muxDesc" = "Kurulmuş bir veri akışında birden çok bağımsız veri akışını iletir."
"muxSett" = "Mux Ayarları" "muxSett" = "Mux Ayarları"
"direct" = "Doğrudan Bağlantı" "direct" = "Doğrudan Bağlantı"
"directDesc" = "Belirli bir ülkenin alan adları veya IP aralıkları ile doğrudan bağlantı kurar." "directDesc" = "Belirli bir ülkenin alan adları veya IP aralıkları ile doğrudan bağlantı kurar."
"directSett" = "Doğrudan Bağlantı Seçenekleri"
[pages.xray] [pages.xray]
"title" = "Xray Yapılandırmaları" "title" = "Xray Yapılandırmaları"

View File

@@ -309,14 +309,14 @@
"fragment" = "Фрагментація" "fragment" = "Фрагментація"
"fragmentDesc" = "Увімкнути фрагментацію для пакету привітання TLS" "fragmentDesc" = "Увімкнути фрагментацію для пакету привітання TLS"
"fragmentSett" = "Параметри фрагментації" "fragmentSett" = "Параметри фрагментації"
"noiseDesc" = "Увімкнути Noise." "noisesDesc" = "Увімкнути Noises."
"noiseSett" = "Налаштування Noise" "noisesSett" = "Налаштування Noises"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Передавати кілька незалежних потоків даних у межах встановленого потоку даних." "muxDesc" = "Передавати кілька незалежних потоків даних у межах встановленого потоку даних."
"muxSett" = "Налаштування Mux" "muxSett" = "Налаштування Mux"
"direct" = "Пряме підключення" "direct" = "Пряме підключення"
"directDesc" = "Безпосередньо встановлює з’єднання з доменами або діапазонами IP певної країни." "directDesc" = "Безпосередньо встановлює з’єднання з доменами або діапазонами IP певної країни."
"directSett" = "Параметри прямого підключення"
[pages.xray] [pages.xray]
"title" = "Xray конфігурації" "title" = "Xray конфігурації"

View File

@@ -309,14 +309,14 @@
"fragment" = "Sự phân mảnh" "fragment" = "Sự phân mảnh"
"fragmentDesc" = "Kích hoạt phân mảnh cho gói TLS hello" "fragmentDesc" = "Kích hoạt phân mảnh cho gói TLS hello"
"fragmentSett" = "Cài đặt phân mảnh" "fragmentSett" = "Cài đặt phân mảnh"
"noiseDesc" = "Bật Noise." "noisesDesc" = "Bật Noises."
"noiseSett" = "Cài đặt Noise" "noisesSett" = "Cài đặt Noises"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Truyền nhiều luồng dữ liệu độc lập trong luồng dữ liệu đã thiết lập." "muxDesc" = "Truyền nhiều luồng dữ liệu độc lập trong luồng dữ liệu đã thiết lập."
"muxSett" = "Mux Cài đặt" "muxSett" = "Mux Cài đặt"
"direct" = "Kết nối trực tiếp" "direct" = "Kết nối trực tiếp"
"directDesc" = "Trực tiếp thiết lập kết nối với tên miền hoặc dải IP của một quốc gia cụ thể." "directDesc" = "Trực tiếp thiết lập kết nối với tên miền hoặc dải IP của một quốc gia cụ thể."
"directSett" = "Tùy chọn kết nối trực tiếp"
[pages.xray] [pages.xray]
"title" = "Cài đặt Xray" "title" = "Cài đặt Xray"

View File

@@ -309,14 +309,14 @@
"fragment" = "分片" "fragment" = "分片"
"fragmentDesc" = "启用 TLS hello 数据包分片" "fragmentDesc" = "启用 TLS hello 数据包分片"
"fragmentSett" = "设置" "fragmentSett" = "设置"
"noiseDesc" = "启用 Noise." "noisesDesc" = "启用 Noises."
"noiseSett" = "Noise 设置" "noisesSett" = "Noises 设置"
"mux" = "多路复用器" "mux" = "多路复用器"
"muxDesc" = "在已建立的数据流内传输多个独立的数据流" "muxDesc" = "在已建立的数据流内传输多个独立的数据流"
"muxSett" = "复用器设置" "muxSett" = "复用器设置"
"direct" = "直接连接" "direct" = "直接连接"
"directDesc" = "直接与特定国家的域或IP范围建立连接" "directDesc" = "直接与特定国家的域或IP范围建立连接"
"directSett" = "直接连接选项"
[pages.xray] [pages.xray]
"title" = "Xray 配置" "title" = "Xray 配置"

10
x-ui.sh
View File

@@ -36,12 +36,12 @@ fi
echo "The OS release is: $release" echo "The OS release is: $release"
os_version="" os_version=""
os_version=$(grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1) os_version=$(grep "^VERSION_ID" /etc/os-release | cut -d '=' -f2 | tr -d '"')
if [[ "${release}" == "arch" ]]; then if [[ "${release}" == "arch" ]]; then
echo "Your OS is Arch Linux" echo "Your OS is Arch Linux"
elif [[ "${release}" == "parch" ]]; then elif [[ "${release}" == "parch" ]]; then
echo "Your OS is Parch linux" echo "Your OS is Parch Linux"
elif [[ "${release}" == "manjaro" ]]; then elif [[ "${release}" == "manjaro" ]]; then
echo "Your OS is Manjaro" echo "Your OS is Manjaro"
elif [[ "${release}" == "armbian" ]]; then elif [[ "${release}" == "armbian" ]]; then
@@ -60,6 +60,10 @@ elif [[ "${release}" == "fedora" ]]; then
if [[ ${os_version} -lt 36 ]]; then if [[ ${os_version} -lt 36 ]]; then
echo -e "${red} Please use Fedora 36 or higher version!${plain}\n" && exit 1 echo -e "${red} Please use Fedora 36 or higher version!${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "amzn" ]]; then
if [[ ${os_version} != "2023" ]]; then
echo -e "${red} Please use Amazon Linux 2023!${plain}\n" && exit 1
fi
elif [[ "${release}" == "debian" ]]; then elif [[ "${release}" == "debian" ]]; then
if [[ ${os_version} -lt 11 ]]; then if [[ ${os_version} -lt 11 ]]; then
echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1 echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1
@@ -91,8 +95,8 @@ else
echo "- Rocky Linux 9+" echo "- Rocky Linux 9+"
echo "- Oracle Linux 8+" echo "- Oracle Linux 8+"
echo "- OpenSUSE Tumbleweed" echo "- OpenSUSE Tumbleweed"
echo "- Amazon Linux 2023"
exit 1 exit 1
fi fi
# Declare Variables # Declare Variables