mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-03-19 09:05:49 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43713fbdf8 | ||
|
|
dc29e858c9 | ||
|
|
c30c6f08f3 | ||
|
|
7c892ac051 | ||
|
|
75dd7b93f5 | ||
|
|
d5de8e1bf3 | ||
|
|
16b4795956 | ||
|
|
e5835c299c | ||
|
|
4fdef3cfde | ||
|
|
cf6a8bd463 | ||
|
|
59a84e844c | ||
|
|
6b0c9a5fad |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -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
|
||||||
|
|||||||
@@ -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}"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
## Поддерживаемые архитектуры и устройства
|
## Поддерживаемые архитектуры и устройства
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.4.1
|
2.4.2
|
||||||
8
go.mod
8
go.mod
@@ -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
10
go.sum
@@ -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=
|
||||||
|
|||||||
10
install.sh
10
install.sh
@@ -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() {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 = "";
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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}}
|
||||||
|
|||||||
@@ -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}}
|
||||||
|
|||||||
@@ -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}}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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" = "پیکربندی ایکسری"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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ı"
|
||||||
|
|||||||
@@ -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 конфігурації"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
10
x-ui.sh
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user