mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-03-19 17:15:49 +00:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86586b7e8f | ||
|
|
f9792632d4 | ||
|
|
a9ec24f811 | ||
|
|
2da7dda794 | ||
|
|
39aae6fd16 | ||
|
|
f355ab5758 | ||
|
|
3847bc0a78 | ||
|
|
546d676472 | ||
|
|
6fb6241c3c | ||
|
|
f481ab993e | ||
|
|
3ef4ab423f | ||
|
|
b5a32ef57e | ||
|
|
4033001798 | ||
|
|
2486b5ff43 | ||
|
|
58647c6496 | ||
|
|
0b8a28d56d | ||
|
|
5d007435ab | ||
|
|
9c05aa514b | ||
|
|
7f2c11220f | ||
|
|
52b02fdef9 | ||
|
|
a4b76929f4 | ||
|
|
33082a271f | ||
|
|
28ede36a10 | ||
|
|
5036e9e28a | ||
|
|
4ca481d071 | ||
|
|
8259024fbe | ||
|
|
e275adbccd |
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Version (please complete the following information):**
|
||||||
|
- 3X-UI Version : [e.g. 2.3.5]
|
||||||
|
- Xray Version : [e.g. 1.8.13]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
56
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
56
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,56 +0,0 @@
|
|||||||
name: Issue Report
|
|
||||||
description: "Create a report to help us improve."
|
|
||||||
body:
|
|
||||||
- type: checkboxes
|
|
||||||
id: terms
|
|
||||||
attributes:
|
|
||||||
label: Welcome
|
|
||||||
options:
|
|
||||||
- label: Yes, I'm using the latest major release. Only such installations are supported.
|
|
||||||
required: true
|
|
||||||
- label: Yes, I'm using the supported system. Only such systems are supported.
|
|
||||||
required: true
|
|
||||||
- label: Yes, I have read all WIKI document,nothing can help me in my problem.
|
|
||||||
required: true
|
|
||||||
- label: Yes, I've searched similar issues on GitHub and didn't find any.
|
|
||||||
required: true
|
|
||||||
- label: Yes, I've included all information below (version, config, log, etc).
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: problem
|
|
||||||
attributes:
|
|
||||||
label: Description of the problem,screencshot would be good
|
|
||||||
placeholder: Your problem description
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version of 3x-ui
|
|
||||||
value: |-
|
|
||||||
<details>
|
|
||||||
|
|
||||||
```console
|
|
||||||
# Paste here
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: log
|
|
||||||
attributes:
|
|
||||||
label: x-ui log reports or xray log
|
|
||||||
value: |-
|
|
||||||
<details>
|
|
||||||
|
|
||||||
```console
|
|
||||||
# paste log here
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
|||||||
images: ghcr.io/${{ github.repository }}
|
images: ghcr.io/${{ github.repository }}
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
|||||||
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/v1.8.13/"
|
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v1.8.16/"
|
||||||
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/v1.8.13/Xray-linux-${ARCH}.zip"
|
wget "https://github.com/XTLS/Xray-core/releases/download/v1.8.16/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}"
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
# 3X-UI
|
|
||||||
|
|
||||||
[English](/README.md) | [Chinese](/README.zh.md) | [Español](/README.es_ES.md)
|
[English](/README.md) | [Chinese](/README.zh.md) | [Español](/README.es_ES.md)
|
||||||
|
|
||||||
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p>
|
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p>
|
||||||
@@ -28,10 +26,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.3.4`:
|
Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.3.6`:
|
||||||
|
|
||||||
```
|
```
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.4
|
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.6
|
||||||
```
|
```
|
||||||
|
|
||||||
## Certificado SSL
|
## Certificado SSL
|
||||||
@@ -258,7 +256,7 @@ Nuestra plataforma ofrece compatibilidad con una amplia gama de arquitecturas y
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## [Configuración WARP](https://gitlab.com/fscarmen/warp)
|
## Configuración WARP
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Haz clic para detalles de la configuración WARP</summary>
|
<summary>Haz clic para detalles de la configuración WARP</summary>
|
||||||
|
|||||||
197
README.md
197
README.md
@@ -1,5 +1,3 @@
|
|||||||
# 3X-UI
|
|
||||||
|
|
||||||
[English](/README.md) | [Chinese](/README.zh.md) | [Español](/README.es_ES.md)
|
[English](/README.md) | [Chinese](/README.zh.md) | [Español](/README.es_ES.md)
|
||||||
|
|
||||||
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p>
|
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p>
|
||||||
@@ -28,48 +26,59 @@ 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.3.5`:
|
To install your desired version, add the version to the end of the installation command. e.g., ver `v2.3.7`:
|
||||||
|
|
||||||
```
|
```
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.5
|
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.7
|
||||||
```
|
```
|
||||||
|
|
||||||
## SSL Certificate
|
## SSL Certificate
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Click for SSL Certificate</summary>
|
<summary>Click for SSL Certificate details</summary>
|
||||||
|
|
||||||
### Cloudflare
|
### ACME
|
||||||
|
|
||||||
The Management script has a built-in SSL certificate application for Cloudflare. To use this script to apply for a certificate, you need the following:
|
To manage SSL certificates using ACME:
|
||||||
|
|
||||||
- Cloudflare registered email
|
1. Ensure your domain is correctly resolved to the server.
|
||||||
- Cloudflare Global API Key
|
2. Run the `x-ui` command in the terminal, then choose `SSL Certificate Management`.
|
||||||
- The domain name has been resolved to the current server through cloudflare
|
3. You will be presented with the following options:
|
||||||
|
|
||||||
How to get the Cloudflare Global API Key:
|
- **Get SSL:** Obtain SSL certificates.
|
||||||
|
- **Revoke:** Revoke existing SSL certificates.
|
||||||
1. Run the`x-ui`command on the terminal, then choose `Cloudflare SSL Certificate`.
|
- **Force Renew:** Force renewal of SSL certificates.
|
||||||
|
|
||||||
2. Visit the link https://dash.cloudflare.com/profile/api-tokens
|
|
||||||
|
|
||||||
3. Click on View Global API Key (See the screenshot below)
|
|
||||||

|
|
||||||
|
|
||||||
4. You may have to re-authenticate your account. After that, the API Key will be shown (See the screenshot below)\
|
|
||||||

|
|
||||||
|
|
||||||
When using, just enter `domain name`, `email`, `API KEY`, the diagram is as follows:
|
|
||||||

|
|
||||||
|
|
||||||
### Certbot
|
### Certbot
|
||||||
```
|
|
||||||
|
To install and use Certbot:
|
||||||
|
|
||||||
|
```sh
|
||||||
apt-get install certbot -y
|
apt-get install certbot -y
|
||||||
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com
|
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com
|
||||||
certbot renew --dry-run
|
certbot renew --dry-run
|
||||||
```
|
```
|
||||||
|
|
||||||
***Tip:*** *Certbot is also built into the Management script. You can run the `x-ui` command, then choose `SSL Certificate Management`.*
|
### Cloudflare
|
||||||
|
|
||||||
|
The management script includes a built-in SSL certificate application for Cloudflare. To use this script to apply for a certificate, you need the following:
|
||||||
|
|
||||||
|
- Cloudflare registered email
|
||||||
|
- Cloudflare Global API Key
|
||||||
|
- The domain name must be resolved to the current server through Cloudflare
|
||||||
|
|
||||||
|
**How to get the Cloudflare Global API Key:**
|
||||||
|
|
||||||
|
1. Run the `x-ui` command in the terminal, then choose `Cloudflare SSL Certificate`.
|
||||||
|
2. Visit the link: [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens).
|
||||||
|
3. Click on "View Global API Key" (see the screenshot below):
|
||||||
|

|
||||||
|
4. You may need to re-authenticate your account. After that, the API Key will be shown (see the screenshot below):
|
||||||
|

|
||||||
|
|
||||||
|
When using, just enter your `domain name`, `email`, and `API KEY`. The diagram is as follows:
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -135,26 +144,26 @@ systemctl restart x-ui
|
|||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
1. Install Docker:
|
1. **Install Docker:**
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
bash <(curl -sSL https://get.docker.com)
|
bash <(curl -sSL https://get.docker.com)
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Clone the Project Repository:
|
2. **Clone the Project Repository:**
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/MHSanaei/3x-ui.git
|
git clone https://github.com/MHSanaei/3x-ui.git
|
||||||
cd 3x-ui
|
cd 3x-ui
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Start the Service
|
3. **Start the Service:**
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
OR
|
**OR**
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker run -itd \
|
docker run -itd \
|
||||||
@@ -167,22 +176,22 @@ systemctl restart x-ui
|
|||||||
ghcr.io/mhsanaei/3x-ui:latest
|
ghcr.io/mhsanaei/3x-ui:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
update to latest version
|
4. **Update to the Latest Version:**
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd 3x-ui
|
cd 3x-ui
|
||||||
docker compose down
|
docker compose down
|
||||||
docker compose pull 3x-ui
|
docker compose pull 3x-ui
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
remove 3x-ui from docker
|
5. **Remove 3x-ui from Docker:**
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker stop 3x-ui
|
docker stop 3x-ui
|
||||||
docker rm 3x-ui
|
docker rm 3x-ui
|
||||||
cd --
|
cd --
|
||||||
rm -r 3x-ui
|
rm -r 3x-ui
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
@@ -255,55 +264,68 @@ Our platform offers compatibility with a diverse range of architectures and devi
|
|||||||
- Supports export/import database from the panel
|
- Supports export/import database from the panel
|
||||||
|
|
||||||
|
|
||||||
## Default Settings
|
## Default Panel Settings
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Click for default settings details</summary>
|
<summary>Click for default settings details</summary>
|
||||||
|
|
||||||
### Information
|
### Username & Password & webbasepath:
|
||||||
|
|
||||||
|
These will be generated randomly if you skip modifying them.
|
||||||
|
|
||||||
|
- **Port:** the default port for panel is `2053`
|
||||||
|
|
||||||
|
### Database Management:
|
||||||
|
|
||||||
|
You can conveniently perform database Backups and Restores directly from the panel.
|
||||||
|
|
||||||
- **Port:** 2053
|
|
||||||
- **Username & Password:** It will be generated randomly if you skip modifying.
|
|
||||||
- **Database Path:**
|
- **Database Path:**
|
||||||
- /etc/x-ui/x-ui.db
|
- `/etc/x-ui/x-ui.db`
|
||||||
- **Xray Config Path:**
|
|
||||||
- /usr/local/x-ui/bin/config.json
|
|
||||||
- **Web Panel Path w/o Deploying SSL:**
|
### Web Base Path
|
||||||
- http://ip:2053/panel
|
|
||||||
- http://domain:2053/panel
|
1. **Reset Web Base Path:**
|
||||||
- **Web Panel Path w/ Deploying SSL:**
|
- Open your terminal.
|
||||||
- https://domain:2053/panel
|
- Run the `x-ui` command.
|
||||||
|
- Select the option to `Reset Web Base Path`.
|
||||||
|
|
||||||
|
2. **Generate or Customize Path:**
|
||||||
|
- The path will be randomly generated, or you can enter a custom path.
|
||||||
|
|
||||||
|
3. **View Current Settings:**
|
||||||
|
- To view your current settings, use the `x-ui settings` command in the terminal or `View Current Settings` in `x-ui`
|
||||||
|
|
||||||
|
### Security Recommendation:
|
||||||
|
- For enhanced security, use a long, random word in your URL structure.
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `http://ip:port/*webbasepath*/panel`
|
||||||
|
- `http://domain:port/*webbasepath*/panel`
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## [WARP Configuration](https://gitlab.com/fscarmen/warp)
|
## WARP Configuration
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Click for WARP configuration details</summary>
|
<summary>Click for WARP configuration details</summary>
|
||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
If you want to use routing to WARP before v2.1.0 follow steps as below:
|
**For versions `v2.1.0` and later:**
|
||||||
|
|
||||||
**1.** Install WARP on **SOCKS Proxy Mode**:
|
WARP is built-in, and no additional installation is required. Simply turn on the necessary configuration in the panel.
|
||||||
|
|
||||||
```sh
|
**For versions before `v2.1.0`:**
|
||||||
bash <(curl -sSL https://raw.githubusercontent.com/hamid-gh98/x-ui-scripts/main/install_warp_proxy.sh)
|
|
||||||
```
|
|
||||||
|
|
||||||
**2.** If you already installed warp, you can uninstall using below command:
|
1. Run the `x-ui` command in the terminal, then choose `WARP Management`.
|
||||||
|
2. You will see the following options:
|
||||||
|
|
||||||
```sh
|
- **Account Type (free, plus, team):** Choose the appropriate account type.
|
||||||
warp u
|
- **Enable/Disable WireProxy:** Toggle WireProxy on or off.
|
||||||
```
|
- **Uninstall WARP:** Remove the WARP application.
|
||||||
|
|
||||||
**3.** Turn on the config you need in panel
|
3. Configure the settings as needed in the panel.
|
||||||
|
|
||||||
Config Features:
|
|
||||||
|
|
||||||
- Block Ads
|
|
||||||
- Route Google + Netflix + Spotify + OpenAI (ChatGPT) to WARP
|
|
||||||
- Fix Google 403 error
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -314,29 +336,40 @@ If you want to use routing to WARP before v2.1.0 follow steps as below:
|
|||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
**Note:** IP Limit won't work correctly when using IP Tunnel
|
**Note:** IP Limit won't work correctly when using IP Tunnel.
|
||||||
|
|
||||||
- For versions up to `v1.6.1`:
|
- **For versions up to `v1.6.1`:**
|
||||||
|
- The IP limit is built-in to the panel
|
||||||
|
|
||||||
- IP limit is built-in into the panel.
|
**For versions `v1.7.0` and newer:**
|
||||||
|
|
||||||
- For versions `v1.7.0` and newer:
|
To enable the IP Limit functionality, you need to install `fail2ban` and its required files by following these steps:
|
||||||
|
|
||||||
- To make IP Limit work properly, you need to install fail2ban and its required files by following these steps:
|
1. Run the `x-ui` command in the terminal, then choose `IP Limit Management`.
|
||||||
|
2. You will see the following options:
|
||||||
|
|
||||||
1. Use the `x-ui` command inside the shell.
|
- **Change Ban Duration:** Adjust the duration of bans.
|
||||||
2. Select `IP Limit Management`.
|
- **Unban Everyone:** Lift all current bans.
|
||||||
3. Choose the appropriate options based on your needs.
|
- **Check Logs:** Review the logs.
|
||||||
|
- **Fail2ban Status:** Check the status of `fail2ban`.
|
||||||
|
- **Restart Fail2ban:** Restart the `fail2ban` service.
|
||||||
|
- **Uninstall Fail2ban:** Uninstall Fail2ban with configuration.
|
||||||
|
|
||||||
|
3. Add a path for the access log on the panel by setting `Xray Configs/log/Access log` to `./access.log` then save and restart xray.
|
||||||
|
|
||||||
- make sure you have ./access.log on your Xray Configuration after v2.1.3 we have an option for it
|
- **For versions before `v2.1.3`:**
|
||||||
|
- You need to set the access log path manually in your Xray configuration:
|
||||||
```sh
|
|
||||||
|
```sh
|
||||||
"log": {
|
"log": {
|
||||||
"access": "./access.log",
|
"access": "./access.log",
|
||||||
"dnsLog": false,
|
"dnsLog": false,
|
||||||
"loglevel": "warning"
|
"loglevel": "warning"
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- **For versions `v2.1.3` and newer:**
|
||||||
|
- There is an option for configuring `access.log` directly from the panel.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
# 3X-UI
|
|
||||||
|
|
||||||
[English](/README.md) | [Chinese](/README.zh.md) | [Español](/README.es_ES.md)
|
[English](/README.md) | [Chinese](/README.zh.md) | [Español](/README.es_ES.md)
|
||||||
|
|
||||||
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p>
|
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p>
|
||||||
@@ -28,10 +26,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
|
|||||||
|
|
||||||
## 安装指定版本
|
## 安装指定版本
|
||||||
|
|
||||||
要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.4`:
|
要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.6`:
|
||||||
|
|
||||||
```
|
```
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.4
|
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.6
|
||||||
```
|
```
|
||||||
|
|
||||||
## SSL 认证
|
## SSL 认证
|
||||||
@@ -257,7 +255,7 @@ systemctl restart x-ui
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## [WARP 配置](https://gitlab.com/fscarmen/warp)
|
## WARP 配置
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>点击查看 WARP 配置</summary>
|
<summary>点击查看 WARP 配置</summary>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.3.5
|
2.3.7
|
||||||
42
go.mod
42
go.mod
@@ -1,6 +1,6 @@
|
|||||||
module x-ui
|
module x-ui
|
||||||
|
|
||||||
go 1.22.3
|
go 1.22.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-contrib/gzip v1.0.1
|
github.com/gin-contrib/gzip v1.0.1
|
||||||
@@ -12,59 +12,59 @@ require (
|
|||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2
|
github.com/pelletier/go-toml/v2 v2.2.2
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5
|
github.com/shirou/gopsutil/v4 v4.24.6
|
||||||
github.com/valyala/fasthttp v1.54.0
|
github.com/valyala/fasthttp v1.55.0
|
||||||
github.com/xtls/xray-core v1.8.13
|
github.com/xtls/xray-core v1.8.16
|
||||||
go.uber.org/atomic v1.11.0
|
go.uber.org/atomic v1.11.0
|
||||||
golang.org/x/text v0.16.0
|
golang.org/x/text v0.16.0
|
||||||
google.golang.org/grpc v1.64.0
|
google.golang.org/grpc v1.64.0
|
||||||
gorm.io/driver/sqlite v1.5.5
|
gorm.io/driver/sqlite v1.5.6
|
||||||
gorm.io/gorm v1.25.10
|
gorm.io/gorm v1.25.10
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
github.com/bytedance/sonic v1.11.8 // indirect
|
github.com/bytedance/sonic v1.11.9 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||||
github.com/cloudflare/circl v1.3.8 // indirect
|
github.com/cloudflare/circl v1.3.9 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
||||||
github.com/fasthttp/router v1.5.1 // indirect
|
github.com/fasthttp/router v1.5.1 // indirect
|
||||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.4 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.21.0 // indirect
|
github.com/go-playground/validator/v10 v10.22.0 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
github.com/google/btree v1.1.2 // indirect
|
github.com/google/btree v1.1.2 // indirect
|
||||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect
|
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect
|
||||||
github.com/gorilla/context v1.1.2 // indirect
|
github.com/gorilla/context v1.1.2 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
github.com/gorilla/sessions v1.2.2 // indirect
|
github.com/gorilla/sessions v1.2.2 // indirect
|
||||||
github.com/gorilla/websocket v1.5.1 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
github.com/grbit/go-json v0.11.0 // indirect
|
github.com/grbit/go-json v0.11.0 // indirect
|
||||||
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.7 // indirect
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 // 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-20231016141302-07b5767bb0ed // indirect
|
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.16.0 // indirect
|
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
|
||||||
github.com/pires/go-proxyproto v0.7.0 // indirect
|
github.com/pires/go-proxyproto v0.7.0 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||||
github.com/quic-go/quic-go v0.44.0 // indirect
|
github.com/quic-go/quic-go v0.45.0 // indirect
|
||||||
github.com/refraction-networking/utls v1.6.6 // indirect
|
github.com/refraction-networking/utls v1.6.6 // 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.11.0 // indirect
|
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||||
github.com/sagernet/sing v0.3.8 // indirect
|
github.com/sagernet/sing v0.4.1 // indirect
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6 // indirect
|
github.com/sagernet/sing-shadowsocks v0.2.6 // indirect
|
||||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 // indirect
|
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 // indirect
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect
|
||||||
@@ -84,16 +84,16 @@ require (
|
|||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
||||||
golang.org/x/arch v0.8.0 // indirect
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
golang.org/x/crypto v0.24.0 // indirect
|
golang.org/x/crypto v0.24.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.18.0 // indirect
|
||||||
golang.org/x/net v0.26.0 // indirect
|
golang.org/x/net v0.26.0 // indirect
|
||||||
golang.org/x/sys v0.21.0 // indirect
|
golang.org/x/sys v0.21.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
golang.org/x/tools v0.22.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
|
||||||
google.golang.org/protobuf v1.34.1 // indirect
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 // indirect
|
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 // indirect
|
||||||
lukechampine.com/blake3 v1.3.0 // indirect
|
lukechampine.com/blake3 v1.3.0 // indirect
|
||||||
|
|||||||
90
go.sum
90
go.sum
@@ -18,13 +18,13 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU
|
|||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||||
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.11.8 h1:Zw/j1KfiS+OYTi9lyB3bb0CFxPJVkM17k1wyDG32LRA=
|
github.com/bytedance/sonic v1.11.9 h1:LFHENlIY/SLzDWverzdOvgMztTxcfcF+cqNsz9pK5zg=
|
||||||
github.com/bytedance/sonic v1.11.8/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
github.com/bytedance/sonic v1.11.9/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||||
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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI=
|
github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE=
|
||||||
github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||||
@@ -43,8 +43,8 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI
|
|||||||
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
||||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
|
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
|
||||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
||||||
@@ -69,10 +69,10 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
|||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.21.0 h1:4fZA11ovvtkdgaeev9RGWPgc1uj3H8W+rNYyH/ySBb0=
|
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
|
||||||
github.com/go-playground/validator/v10 v10.21.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
@@ -84,8 +84,6 @@ github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/
|
|||||||
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
|
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
@@ -99,8 +97,8 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
|||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q=
|
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g=
|
||||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
@@ -110,8 +108,8 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX
|
|||||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
||||||
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
||||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/grbit/go-json v0.11.0 h1:bAbyMdYrYl/OjYsSqLH99N2DyQ291mHy726Mx+sYrnc=
|
github.com/grbit/go-json v0.11.0 h1:bAbyMdYrYl/OjYsSqLH99N2DyQ291mHy726Mx+sYrnc=
|
||||||
github.com/grbit/go-json v0.11.0/go.mod h1:IYpHsdybQ386+6g3VE6AXQ3uTGa5mquBme5/ZWmtzek=
|
github.com/grbit/go-json v0.11.0/go.mod h1:IYpHsdybQ386+6g3VE6AXQ3uTGa5mquBme5/ZWmtzek=
|
||||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
@@ -126,11 +124,11 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
|||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
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.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
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.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
@@ -151,8 +149,8 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o
|
|||||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||||
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
||||||
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
|
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@@ -165,10 +163,10 @@ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJE
|
|||||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
|
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
|
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
|
||||||
github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM=
|
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||||
github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||||
@@ -187,8 +185,8 @@ github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
|||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/quic-go/quic-go v0.44.0 h1:So5wOr7jyO4vzL2sd8/pD9Kesciv91zSk8BoFngItQ0=
|
github.com/quic-go/quic-go v0.45.0 h1:OHmkQGM37luZITyTSu6ff03HP/2IrwDX1ZFiNEhSFUE=
|
||||||
github.com/quic-go/quic-go v0.44.0/go.mod h1:z4cx/9Ny9UtGITIPzmPTXh1ULfOyWh4qGQlpnPcWmek=
|
github.com/quic-go/quic-go v0.45.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
|
||||||
github.com/refraction-networking/utls v1.6.6 h1:igFsYBUJPYM8Rno9xUuDoM5GQrVEqY4llzEXOkL43Ig=
|
github.com/refraction-networking/utls v1.6.6 h1:igFsYBUJPYM8Rno9xUuDoM5GQrVEqY4llzEXOkL43Ig=
|
||||||
github.com/refraction-networking/utls v1.6.6/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
|
github.com/refraction-networking/utls v1.6.6/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||||
@@ -198,8 +196,8 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG
|
|||||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||||
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.3.8 h1:gm4JKalPhydMYX2zFOTnnd4TXtM/16WFRqSjMepYQQk=
|
github.com/sagernet/sing v0.4.1 h1:zVlpE+7k7AFoC2pv6ReqLf0PIHjihL/jsBl5k05PQFk=
|
||||||
github.com/sagernet/sing v0.3.8/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
|
github.com/sagernet/sing v0.4.1/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
|
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
|
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
|
||||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 h1:KanIMPX0QdEdB4R3CiimCAbxFrhB3j7h0/OvpYGVQa8=
|
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 h1:KanIMPX0QdEdB4R3CiimCAbxFrhB3j7h0/OvpYGVQa8=
|
||||||
@@ -207,8 +205,8 @@ github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511/go.mod h1:sM7Mt7uEo
|
|||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
github.com/shirou/gopsutil/v4 v4.24.6 h1:9qqCSYF2pgOU+t+NgJtp7Co5+5mHF/HyKBUckySQL64=
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
github.com/shirou/gopsutil/v4 v4.24.6/go.mod h1:aoebb2vxetJ/yIDZISmduFvVNPHqXQ9SEJwRXxkf0RA=
|
||||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||||
@@ -264,8 +262,8 @@ github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF
|
|||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.54.0 h1:cCL+ZZR3z3HPLMVfEYVUMtJqVaui0+gu7Lx63unHwS0=
|
github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
|
||||||
github.com/valyala/fasthttp v1.54.0/go.mod h1:6dt4/8olwq9QARP/TDuPmWyWcl4byhpvTJ4AAtcz+QM=
|
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
|
||||||
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
||||||
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||||
@@ -277,8 +275,8 @@ github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1Y
|
|||||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc h1:0Nj8T1n7F7+v4vRVroaJIvY6R0vNABLfPH+lzPHRJvI=
|
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc h1:0Nj8T1n7F7+v4vRVroaJIvY6R0vNABLfPH+lzPHRJvI=
|
||||||
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
|
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
|
||||||
github.com/xtls/xray-core v1.8.13 h1:x1wG7iC8xjVnlayGA+S4c7EUobx6Gg0ttSm2SFwLrik=
|
github.com/xtls/xray-core v1.8.16 h1:PhbpdREAIvDS7xmxR6Sdpkx0h5ugmf6wIoWECWtJ0kE=
|
||||||
github.com/xtls/xray-core v1.8.13/go.mod h1:h4A21+wcMIFDAqHzSKTXMZQr3lto6WOTUWodamVi/kM=
|
github.com/xtls/xray-core v1.8.16/go.mod h1:tjzDQQJpFORuhf7fBsiswiexLVEeJpAfMsD0NE5xV7M=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||||
@@ -299,13 +297,13 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk
|
|||||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
|
||||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -355,8 +353,8 @@ golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGm
|
|||||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
||||||
@@ -381,8 +379,8 @@ google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3
|
|||||||
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.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
|
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
|
||||||
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
|
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
|
||||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
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=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
@@ -395,8 +393,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E=
|
gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE=
|
||||||
gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE=
|
gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
|
||||||
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
|
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
|
||||||
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||||
|
|||||||
33
install.sh
33
install.sh
@@ -121,6 +121,12 @@ install_base() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gen_random_string() {
|
||||||
|
local length="$1"
|
||||||
|
local random_string=$(LC_ALL=C tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w "$length" | head -n 1)
|
||||||
|
echo "$random_string"
|
||||||
|
}
|
||||||
|
|
||||||
# This function will be called when user installed x-ui out of security
|
# This function will be called when user installed x-ui out of security
|
||||||
config_after_install() {
|
config_after_install() {
|
||||||
echo -e "${yellow}Install/update finished! For security it's recommended to modify panel settings ${plain}"
|
echo -e "${yellow}Install/update finished! For security it's recommended to modify panel settings ${plain}"
|
||||||
@@ -146,7 +152,7 @@ config_after_install() {
|
|||||||
if [[ ! -f "/etc/x-ui/x-ui.db" ]]; then
|
if [[ ! -f "/etc/x-ui/x-ui.db" ]]; then
|
||||||
local usernameTemp=$(head -c 6 /dev/urandom | base64)
|
local usernameTemp=$(head -c 6 /dev/urandom | base64)
|
||||||
local passwordTemp=$(head -c 6 /dev/urandom | base64)
|
local passwordTemp=$(head -c 6 /dev/urandom | base64)
|
||||||
local webBasePathTemp=$(head -c 6 /dev/urandom | base64)
|
local webBasePathTemp=$(gen_random_string 10)
|
||||||
/usr/local/x-ui/x-ui setting -username ${usernameTemp} -password ${passwordTemp} -webBasePath ${webBasePathTemp}
|
/usr/local/x-ui/x-ui setting -username ${usernameTemp} -password ${passwordTemp} -webBasePath ${webBasePathTemp}
|
||||||
echo -e "This is a fresh installation, will generate random login info for security concerns:"
|
echo -e "This is a fresh installation, will generate random login info for security concerns:"
|
||||||
echo -e "###############################################"
|
echo -e "###############################################"
|
||||||
@@ -218,18 +224,21 @@ install_x-ui() {
|
|||||||
echo -e ""
|
echo -e ""
|
||||||
echo -e "x-ui control menu usages: "
|
echo -e "x-ui control menu usages: "
|
||||||
echo -e "----------------------------------------------"
|
echo -e "----------------------------------------------"
|
||||||
echo -e "x-ui - Enter Admin menu"
|
echo -e "SUBCOMMANDS:"
|
||||||
echo -e "x-ui start - Start x-ui"
|
echo -e "x-ui - Admin Management Script"
|
||||||
echo -e "x-ui stop - Stop x-ui"
|
echo -e "x-ui start - Start"
|
||||||
echo -e "x-ui restart - Restart x-ui"
|
echo -e "x-ui stop - Stop"
|
||||||
echo -e "x-ui status - Show x-ui status"
|
echo -e "x-ui restart - Restart"
|
||||||
echo -e "x-ui enable - Enable x-ui on system startup"
|
echo -e "x-ui status - Current Status"
|
||||||
echo -e "x-ui disable - Disable x-ui on system startup"
|
echo -e "x-ui settings - Current Settings"
|
||||||
echo -e "x-ui log - Check x-ui logs"
|
echo -e "x-ui enable - Enable Autostart on OS Startup"
|
||||||
|
echo -e "x-ui disable - Disable Autostart on OS Startup"
|
||||||
|
echo -e "x-ui log - Check logs"
|
||||||
echo -e "x-ui banlog - Check Fail2ban ban logs"
|
echo -e "x-ui banlog - Check Fail2ban ban logs"
|
||||||
echo -e "x-ui update - Update x-ui"
|
echo -e "x-ui update - Update"
|
||||||
echo -e "x-ui install - Install x-ui"
|
echo -e "x-ui custom - custom version"
|
||||||
echo -e "x-ui uninstall - Uninstall x-ui"
|
echo -e "x-ui install - Install"
|
||||||
|
echo -e "x-ui uninstall - Uninstall"
|
||||||
echo -e "----------------------------------------------"
|
echo -e "----------------------------------------------"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,7 +224,6 @@ func (s *SubJsonService) streamData(stream string) map[string]interface{} {
|
|||||||
case "httpupgrade":
|
case "httpupgrade":
|
||||||
streamSettings["httpupgradeSettings"] = s.removeAcceptProxy(streamSettings["httpupgradeSettings"])
|
streamSettings["httpupgradeSettings"] = s.removeAcceptProxy(streamSettings["httpupgradeSettings"])
|
||||||
}
|
}
|
||||||
|
|
||||||
return streamSettings
|
return streamSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -202,12 +202,11 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
|
|||||||
case "ws":
|
case "ws":
|
||||||
ws, _ := stream["wsSettings"].(map[string]interface{})
|
ws, _ := stream["wsSettings"].(map[string]interface{})
|
||||||
obj["path"] = ws["path"].(string)
|
obj["path"] = ws["path"].(string)
|
||||||
obj["host"] = ws["host"].(string)
|
if host, ok := ws["host"].(string); ok && len(host) > 0 {
|
||||||
if headers, ok := ws["headers"].(map[string]interface{}); ok {
|
obj["host"] = host
|
||||||
hostFromHeaders := searchHost(headers)
|
} else {
|
||||||
if hostFromHeaders != "" {
|
headers, _ := ws["headers"].(map[string]interface{})
|
||||||
obj["host"] = hostFromHeaders
|
obj["host"] = searchHost(headers)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case "http":
|
case "http":
|
||||||
obj["net"] = "h2"
|
obj["net"] = "h2"
|
||||||
@@ -230,12 +229,20 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
|
|||||||
case "httpupgrade":
|
case "httpupgrade":
|
||||||
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
|
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
|
||||||
obj["path"] = httpupgrade["path"].(string)
|
obj["path"] = httpupgrade["path"].(string)
|
||||||
obj["host"] = httpupgrade["host"].(string)
|
if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
|
||||||
if headers, ok := httpupgrade["headers"].(map[string]interface{}); ok {
|
obj["host"] = host
|
||||||
hostFromHeaders := searchHost(headers)
|
} else {
|
||||||
if hostFromHeaders != "" {
|
headers, _ := httpupgrade["headers"].(map[string]interface{})
|
||||||
obj["host"] = hostFromHeaders
|
obj["host"] = searchHost(headers)
|
||||||
}
|
}
|
||||||
|
case "splithttp":
|
||||||
|
splithttp, _ := stream["splithttpSettings"].(map[string]interface{})
|
||||||
|
obj["path"] = splithttp["path"].(string)
|
||||||
|
if host, ok := splithttp["host"].(string); ok && len(host) > 0 {
|
||||||
|
obj["host"] = host
|
||||||
|
} else {
|
||||||
|
headers, _ := splithttp["headers"].(map[string]interface{})
|
||||||
|
obj["host"] = searchHost(headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
security, _ := stream["security"].(string)
|
security, _ := stream["security"].(string)
|
||||||
@@ -352,13 +359,11 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
|
|||||||
case "ws":
|
case "ws":
|
||||||
ws, _ := stream["wsSettings"].(map[string]interface{})
|
ws, _ := stream["wsSettings"].(map[string]interface{})
|
||||||
params["path"] = ws["path"].(string)
|
params["path"] = ws["path"].(string)
|
||||||
params["host"] = ws["host"].(string)
|
if host, ok := ws["host"].(string); ok && len(host) > 0 {
|
||||||
headers, _ := ws["headers"].(map[string]interface{})
|
params["host"] = host
|
||||||
if headers != nil {
|
} else {
|
||||||
hostFromHeaders := searchHost(headers)
|
headers, _ := ws["headers"].(map[string]interface{})
|
||||||
if hostFromHeaders != "" {
|
params["host"] = searchHost(headers)
|
||||||
params["host"] = hostFromHeaders
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case "http":
|
case "http":
|
||||||
http, _ := stream["httpSettings"].(map[string]interface{})
|
http, _ := stream["httpSettings"].(map[string]interface{})
|
||||||
@@ -380,13 +385,20 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
|
|||||||
case "httpupgrade":
|
case "httpupgrade":
|
||||||
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
|
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
|
||||||
params["path"] = httpupgrade["path"].(string)
|
params["path"] = httpupgrade["path"].(string)
|
||||||
params["host"] = httpupgrade["host"].(string)
|
if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
|
||||||
headers, _ := httpupgrade["headers"].(map[string]interface{})
|
params["host"] = host
|
||||||
if headers != nil {
|
} else {
|
||||||
hostFromHeaders := searchHost(headers)
|
headers, _ := httpupgrade["headers"].(map[string]interface{})
|
||||||
if hostFromHeaders != "" {
|
params["host"] = searchHost(headers)
|
||||||
params["host"] = hostFromHeaders
|
}
|
||||||
}
|
case "splithttp":
|
||||||
|
splithttp, _ := stream["splithttpSettings"].(map[string]interface{})
|
||||||
|
params["path"] = splithttp["path"].(string)
|
||||||
|
if host, ok := splithttp["host"].(string); ok && len(host) > 0 {
|
||||||
|
params["host"] = host
|
||||||
|
} else {
|
||||||
|
headers, _ := splithttp["headers"].(map[string]interface{})
|
||||||
|
params["host"] = searchHost(headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
security, _ := stream["security"].(string)
|
security, _ := stream["security"].(string)
|
||||||
@@ -581,13 +593,11 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
|
|||||||
case "ws":
|
case "ws":
|
||||||
ws, _ := stream["wsSettings"].(map[string]interface{})
|
ws, _ := stream["wsSettings"].(map[string]interface{})
|
||||||
params["path"] = ws["path"].(string)
|
params["path"] = ws["path"].(string)
|
||||||
params["host"] = ws["host"].(string)
|
if host, ok := ws["host"].(string); ok && len(host) > 0 {
|
||||||
headers, _ := ws["headers"].(map[string]interface{})
|
params["host"] = host
|
||||||
if headers != nil {
|
} else {
|
||||||
hostFromHeaders := searchHost(headers)
|
headers, _ := ws["headers"].(map[string]interface{})
|
||||||
if hostFromHeaders != "" {
|
params["host"] = searchHost(headers)
|
||||||
params["host"] = hostFromHeaders
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case "http":
|
case "http":
|
||||||
http, _ := stream["httpSettings"].(map[string]interface{})
|
http, _ := stream["httpSettings"].(map[string]interface{})
|
||||||
@@ -609,13 +619,20 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
|
|||||||
case "httpupgrade":
|
case "httpupgrade":
|
||||||
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
|
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
|
||||||
params["path"] = httpupgrade["path"].(string)
|
params["path"] = httpupgrade["path"].(string)
|
||||||
params["host"] = httpupgrade["host"].(string)
|
if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
|
||||||
headers, _ := httpupgrade["headers"].(map[string]interface{})
|
params["host"] = host
|
||||||
if headers != nil {
|
} else {
|
||||||
hostFromHeaders := searchHost(headers)
|
headers, _ := httpupgrade["headers"].(map[string]interface{})
|
||||||
if hostFromHeaders != "" {
|
params["host"] = searchHost(headers)
|
||||||
params["host"] = hostFromHeaders
|
}
|
||||||
}
|
case "splithttp":
|
||||||
|
splithttp, _ := stream["splithttpSettings"].(map[string]interface{})
|
||||||
|
params["path"] = splithttp["path"].(string)
|
||||||
|
if host, ok := splithttp["host"].(string); ok && len(host) > 0 {
|
||||||
|
params["host"] = host
|
||||||
|
} else {
|
||||||
|
headers, _ := splithttp["headers"].(map[string]interface{})
|
||||||
|
params["host"] = searchHost(headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
security, _ := stream["security"].(string)
|
security, _ := stream["security"].(string)
|
||||||
@@ -811,13 +828,11 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
|
|||||||
case "ws":
|
case "ws":
|
||||||
ws, _ := stream["wsSettings"].(map[string]interface{})
|
ws, _ := stream["wsSettings"].(map[string]interface{})
|
||||||
params["path"] = ws["path"].(string)
|
params["path"] = ws["path"].(string)
|
||||||
params["host"] = ws["host"].(string)
|
if host, ok := ws["host"].(string); ok && len(host) > 0 {
|
||||||
headers, _ := ws["headers"].(map[string]interface{})
|
params["host"] = host
|
||||||
if headers != nil {
|
} else {
|
||||||
hostFromHeaders := searchHost(headers)
|
headers, _ := ws["headers"].(map[string]interface{})
|
||||||
if hostFromHeaders != "" {
|
params["host"] = searchHost(headers)
|
||||||
params["host"] = hostFromHeaders
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case "http":
|
case "http":
|
||||||
http, _ := stream["httpSettings"].(map[string]interface{})
|
http, _ := stream["httpSettings"].(map[string]interface{})
|
||||||
@@ -839,13 +854,20 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
|
|||||||
case "httpupgrade":
|
case "httpupgrade":
|
||||||
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
|
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
|
||||||
params["path"] = httpupgrade["path"].(string)
|
params["path"] = httpupgrade["path"].(string)
|
||||||
params["host"] = httpupgrade["host"].(string)
|
if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
|
||||||
headers, _ := httpupgrade["headers"].(map[string]interface{})
|
params["host"] = host
|
||||||
if headers != nil {
|
} else {
|
||||||
hostFromHeaders := searchHost(headers)
|
headers, _ := httpupgrade["headers"].(map[string]interface{})
|
||||||
if hostFromHeaders != "" {
|
params["host"] = searchHost(headers)
|
||||||
params["host"] = hostFromHeaders
|
}
|
||||||
}
|
case "splithttp":
|
||||||
|
splithttp, _ := stream["splithttpSettings"].(map[string]interface{})
|
||||||
|
params["path"] = splithttp["path"].(string)
|
||||||
|
if host, ok := splithttp["host"].(string); ok && len(host) > 0 {
|
||||||
|
params["host"] = host
|
||||||
|
} else {
|
||||||
|
headers, _ := splithttp["headers"].(map[string]interface{})
|
||||||
|
params["host"] = searchHost(headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -985,9 +1007,37 @@ func (s *SubService) genRemark(inbound *model.Inbound, email string, extra strin
|
|||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
switch exp := stats.ExpiryTime / 1000; {
|
switch exp := stats.ExpiryTime / 1000; {
|
||||||
case exp > 0:
|
case exp > 0:
|
||||||
remark = append(remark, fmt.Sprintf("%d%s⏳", (exp-now)/86400, "Days"))
|
remainingSeconds := exp - now
|
||||||
|
days := remainingSeconds / 86400
|
||||||
|
hours := (remainingSeconds % 86400) / 3600
|
||||||
|
minutes := (remainingSeconds % 3600) / 60
|
||||||
|
if days > 0 {
|
||||||
|
if hours > 0 {
|
||||||
|
remark = append(remark, fmt.Sprintf("%dD,%dH⏳", days, hours))
|
||||||
|
} else {
|
||||||
|
remark = append(remark, fmt.Sprintf("%dD⏳", days))
|
||||||
|
}
|
||||||
|
} else if hours > 0 {
|
||||||
|
remark = append(remark, fmt.Sprintf("%dH⏳", hours))
|
||||||
|
} else {
|
||||||
|
remark = append(remark, fmt.Sprintf("%dM⏳", minutes))
|
||||||
|
}
|
||||||
case exp < 0:
|
case exp < 0:
|
||||||
remark = append(remark, fmt.Sprintf("%d%s⏳", exp/-86400, "Days"))
|
passedSeconds := now - exp
|
||||||
|
days := passedSeconds / 86400
|
||||||
|
hours := (passedSeconds % 86400) / 3600
|
||||||
|
minutes := (passedSeconds % 3600) / 60
|
||||||
|
if days > 0 {
|
||||||
|
if hours > 0 {
|
||||||
|
remark = append(remark, fmt.Sprintf("%dD,%dH⏳", days, hours))
|
||||||
|
} else {
|
||||||
|
remark = append(remark, fmt.Sprintf("%dD⏳", days))
|
||||||
|
}
|
||||||
|
} else if hours > 0 {
|
||||||
|
remark = append(remark, fmt.Sprintf("%dH⏳", hours))
|
||||||
|
} else {
|
||||||
|
remark = append(remark, fmt.Sprintf("%dM⏳", minutes))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ import (
|
|||||||
_ "unsafe"
|
_ "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:linkname HostProc github.com/shirou/gopsutil/v3/internal/common.HostProc
|
//go:linkname HostProc github.com/shirou/gopsutil/v4/internal/common.HostProc
|
||||||
func HostProc(combineWith ...string) string
|
func HostProc(combineWith ...string) string
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package sys
|
package sys
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/shirou/gopsutil/v3/net"
|
"github.com/shirou/gopsutil/v4/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetTCPCount() (int, error) {
|
func GetTCPCount() (int, error) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ package sys
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/v3/net"
|
"github.com/shirou/gopsutil/v4/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetConnectionCount(proto string) (int, error) {
|
func GetConnectionCount(proto string) (int, error) {
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ class WsStreamSettings extends CommonClass {
|
|||||||
static fromJson(json={}) {
|
static fromJson(json={}) {
|
||||||
return new WsStreamSettings(
|
return new WsStreamSettings(
|
||||||
json.path,
|
json.path,
|
||||||
json.host
|
json.host,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +202,6 @@ class WsStreamSettings extends CommonClass {
|
|||||||
return {
|
return {
|
||||||
path: this.path,
|
path: this.path,
|
||||||
host: this.host,
|
host: this.host,
|
||||||
headers: ObjectUtil.isEmpty(this.host) ? undefined : {Host: this.host},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,7 +287,29 @@ class HttpUpgradeStreamSettings extends CommonClass {
|
|||||||
static fromJson(json={}) {
|
static fromJson(json={}) {
|
||||||
return new HttpUpgradeStreamSettings(
|
return new HttpUpgradeStreamSettings(
|
||||||
json.path,
|
json.path,
|
||||||
json.host
|
json.host,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
return {
|
||||||
|
path: this.path,
|
||||||
|
host: this.host,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SplitHTTPStreamSettings extends CommonClass {
|
||||||
|
constructor(path='/', host='') {
|
||||||
|
super();
|
||||||
|
this.path = path;
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJson(json={}) {
|
||||||
|
return new SplitHTTPStreamSettings(
|
||||||
|
json.path,
|
||||||
|
json.host,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +317,6 @@ class HttpUpgradeStreamSettings extends CommonClass {
|
|||||||
return {
|
return {
|
||||||
path: this.path,
|
path: this.path,
|
||||||
host: this.host,
|
host: this.host,
|
||||||
headers: ObjectUtil.isEmpty(this.host) ? undefined : {Host: this.host},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -404,6 +424,7 @@ class StreamSettings extends CommonClass {
|
|||||||
quicSettings=new QuicStreamSettings(),
|
quicSettings=new QuicStreamSettings(),
|
||||||
grpcSettings=new GrpcStreamSettings(),
|
grpcSettings=new GrpcStreamSettings(),
|
||||||
httpupgradeSettings=new HttpUpgradeStreamSettings(),
|
httpupgradeSettings=new HttpUpgradeStreamSettings(),
|
||||||
|
splithttpSettings=new SplitHTTPStreamSettings(),
|
||||||
sockopt = undefined,
|
sockopt = undefined,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@@ -418,6 +439,7 @@ class StreamSettings extends CommonClass {
|
|||||||
this.quic = quicSettings;
|
this.quic = quicSettings;
|
||||||
this.grpc = grpcSettings;
|
this.grpc = grpcSettings;
|
||||||
this.httpupgrade = httpupgradeSettings;
|
this.httpupgrade = httpupgradeSettings;
|
||||||
|
this.splithttp = splithttpSettings;
|
||||||
this.sockopt = sockopt;
|
this.sockopt = sockopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,6 +472,7 @@ class StreamSettings extends CommonClass {
|
|||||||
QuicStreamSettings.fromJson(json.quicSettings),
|
QuicStreamSettings.fromJson(json.quicSettings),
|
||||||
GrpcStreamSettings.fromJson(json.grpcSettings),
|
GrpcStreamSettings.fromJson(json.grpcSettings),
|
||||||
HttpUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
|
HttpUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
|
||||||
|
SplitHTTPStreamSettings.fromJson(json.splithttpSettings),
|
||||||
SockoptStreamSettings.fromJson(json.sockopt),
|
SockoptStreamSettings.fromJson(json.sockopt),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -468,6 +491,7 @@ class StreamSettings extends CommonClass {
|
|||||||
quicSettings: network === 'quic' ? this.quic.toJson() : undefined,
|
quicSettings: network === 'quic' ? this.quic.toJson() : undefined,
|
||||||
grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
|
grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
|
||||||
httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
|
httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
|
||||||
|
splithttpSettings: network === 'splithttp' ? this.splithttp.toJson() : undefined,
|
||||||
sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined,
|
sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -532,7 +556,7 @@ class Outbound extends CommonClass {
|
|||||||
|
|
||||||
canEnableTls() {
|
canEnableTls() {
|
||||||
if (![Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks].includes(this.protocol)) return false;
|
if (![Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks].includes(this.protocol)) return false;
|
||||||
return ["tcp", "ws", "http", "quic", "grpc", "httpupgrade"].includes(this.stream.network);
|
return ["tcp", "ws", "http", "quic", "grpc", "httpupgrade" , "splithttp"].includes(this.stream.network);
|
||||||
}
|
}
|
||||||
|
|
||||||
//this is used for xtls-rprx-vision
|
//this is used for xtls-rprx-vision
|
||||||
@@ -653,6 +677,8 @@ class Outbound extends CommonClass {
|
|||||||
stream.grpc = new GrpcStreamSettings(json.path, json.authority, json.type == 'multi');
|
stream.grpc = new GrpcStreamSettings(json.path, json.authority, json.type == 'multi');
|
||||||
} else if (network === 'httpupgrade') {
|
} else if (network === 'httpupgrade') {
|
||||||
stream.httpupgrade = new HttpUpgradeStreamSettings(json.path,json.host);
|
stream.httpupgrade = new HttpUpgradeStreamSettings(json.path,json.host);
|
||||||
|
} else if (network === 'splithttp') {
|
||||||
|
stream.splithttp = new SplitHTTPStreamSettings(json.path,json.host);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(json.tls && json.tls == 'tls'){
|
if(json.tls && json.tls == 'tls'){
|
||||||
@@ -700,6 +726,8 @@ class Outbound extends CommonClass {
|
|||||||
url.searchParams.get('mode') == 'multi');
|
url.searchParams.get('mode') == 'multi');
|
||||||
} else if (type === 'httpupgrade') {
|
} else if (type === 'httpupgrade') {
|
||||||
stream.httpupgrade = new HttpUpgradeStreamSettings(path,host);
|
stream.httpupgrade = new HttpUpgradeStreamSettings(path,host);
|
||||||
|
} else if (type === 'splithttp') {
|
||||||
|
stream.splithttp = new SplitHTTPStreamSettings(path,host);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(security == 'tls'){
|
if(security == 'tls'){
|
||||||
@@ -950,13 +978,14 @@ Outbound.TrojanSettings = class extends CommonClass {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
Outbound.ShadowsocksSettings = class extends CommonClass {
|
Outbound.ShadowsocksSettings = class extends CommonClass {
|
||||||
constructor(address, port, password, method, uot) {
|
constructor(address, port, password, method, uot, UoTVersion) {
|
||||||
super();
|
super();
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.uot = uot;
|
this.uot = uot;
|
||||||
|
this.UoTVersion = UoTVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json={}) {
|
||||||
@@ -968,6 +997,7 @@ Outbound.ShadowsocksSettings = class extends CommonClass {
|
|||||||
servers[0].password,
|
servers[0].password,
|
||||||
servers[0].method,
|
servers[0].method,
|
||||||
servers[0].uot,
|
servers[0].uot,
|
||||||
|
servers[0].UoTVersion,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,6 +1009,7 @@ Outbound.ShadowsocksSettings = class extends CommonClass {
|
|||||||
password: this.password,
|
password: this.password,
|
||||||
method: this.method,
|
method: this.method,
|
||||||
uot: this.uot,
|
uot: this.uot,
|
||||||
|
UoTVersion: this.UoTVersion,
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1053,6 +1084,7 @@ Outbound.WireguardSettings = class extends CommonClass {
|
|||||||
super();
|
super();
|
||||||
this.mtu = mtu;
|
this.mtu = mtu;
|
||||||
this.secretKey = secretKey;
|
this.secretKey = secretKey;
|
||||||
|
this.pubKey = secretKey.length>0 ? Wireguard.generateKeypair(secretKey).publicKey : '';
|
||||||
this.address = address instanceof Array ? address.join(',') : address;
|
this.address = address instanceof Array ? address.join(',') : address;
|
||||||
this.workers = workers;
|
this.workers = workers;
|
||||||
this.domainStrategy = domainStrategy;
|
this.domainStrategy = domainStrategy;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class AllSetting {
|
|||||||
this.webKeyFile = "";
|
this.webKeyFile = "";
|
||||||
this.webBasePath = "/";
|
this.webBasePath = "/";
|
||||||
this.sessionMaxAge = "";
|
this.sessionMaxAge = "";
|
||||||
this.pageSize = 0;
|
this.pageSize = 50;
|
||||||
this.expireDiff = "";
|
this.expireDiff = "";
|
||||||
this.trafficDiff = "";
|
this.trafficDiff = "";
|
||||||
this.remarkModel = "-ieo";
|
this.remarkModel = "-ieo";
|
||||||
|
|||||||
@@ -241,15 +241,6 @@ TcpStreamSettings.TcpRequest = class extends XrayCommonClass {
|
|||||||
this.headers.push({ name: name, value: value });
|
this.headers.push({ name: name, value: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
getHeader(name) {
|
|
||||||
for (const header of this.headers) {
|
|
||||||
if (header.name.toLowerCase() === name.toLowerCase()) {
|
|
||||||
return header.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeHeader(index) {
|
removeHeader(index) {
|
||||||
this.headers.splice(index, 1);
|
this.headers.splice(index, 1);
|
||||||
}
|
}
|
||||||
@@ -379,15 +370,6 @@ class WsStreamSettings extends XrayCommonClass {
|
|||||||
this.headers.push({ name: name, value: value });
|
this.headers.push({ name: name, value: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
getHeader(name) {
|
|
||||||
for (const header of this.headers) {
|
|
||||||
if (header.name.toLowerCase() === name.toLowerCase()) {
|
|
||||||
return header.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeHeader(index) {
|
removeHeader(index) {
|
||||||
this.headers.splice(index, 1);
|
this.headers.splice(index, 1);
|
||||||
}
|
}
|
||||||
@@ -517,15 +499,6 @@ class HTTPUpgradeStreamSettings extends XrayCommonClass {
|
|||||||
this.headers.push({ name: name, value: value });
|
this.headers.push({ name: name, value: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
getHeader(name) {
|
|
||||||
for (const header of this.headers) {
|
|
||||||
if (header.name.toLowerCase() === name.toLowerCase()) {
|
|
||||||
return header.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeHeader(index) {
|
removeHeader(index) {
|
||||||
this.headers.splice(index, 1);
|
this.headers.splice(index, 1);
|
||||||
}
|
}
|
||||||
@@ -549,6 +522,45 @@ class HTTPUpgradeStreamSettings extends XrayCommonClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SplitHTTPStreamSettings extends XrayCommonClass {
|
||||||
|
constructor(path='/', host='', headers=[] , maxUploadSize= 1, maxConcurrentUploads= 10) {
|
||||||
|
super();
|
||||||
|
this.path = path;
|
||||||
|
this.host = host;
|
||||||
|
this.headers = headers;
|
||||||
|
this.maxUploadSize = maxUploadSize;
|
||||||
|
this.maxConcurrentUploads = maxConcurrentUploads;
|
||||||
|
}
|
||||||
|
|
||||||
|
addHeader(name, value) {
|
||||||
|
this.headers.push({ name: name, value: value });
|
||||||
|
}
|
||||||
|
|
||||||
|
removeHeader(index) {
|
||||||
|
this.headers.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJson(json={}) {
|
||||||
|
return new SplitHTTPStreamSettings(
|
||||||
|
json.path,
|
||||||
|
json.host,
|
||||||
|
XrayCommonClass.toHeaders(json.headers),
|
||||||
|
json.maxUploadSize,
|
||||||
|
json.maxConcurrentUploads,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
return {
|
||||||
|
path: this.path,
|
||||||
|
host: this.host,
|
||||||
|
headers: XrayCommonClass.toV2Headers(this.headers, false),
|
||||||
|
maxUploadSize: this.maxUploadSize,
|
||||||
|
maxConcurrentUploads: this.maxConcurrentUploads,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class TlsStreamSettings extends XrayCommonClass {
|
class TlsStreamSettings extends XrayCommonClass {
|
||||||
constructor(serverName='',
|
constructor(serverName='',
|
||||||
minVersion = TLS_VERSION_OPTION.TLS12,
|
minVersion = TLS_VERSION_OPTION.TLS12,
|
||||||
@@ -1001,6 +1013,7 @@ class StreamSettings extends XrayCommonClass {
|
|||||||
quicSettings=new QuicStreamSettings(),
|
quicSettings=new QuicStreamSettings(),
|
||||||
grpcSettings=new GrpcStreamSettings(),
|
grpcSettings=new GrpcStreamSettings(),
|
||||||
httpupgradeSettings=new HTTPUpgradeStreamSettings(),
|
httpupgradeSettings=new HTTPUpgradeStreamSettings(),
|
||||||
|
splithttpSettings=new SplitHTTPStreamSettings(),
|
||||||
sockopt = undefined,
|
sockopt = undefined,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@@ -1017,6 +1030,7 @@ class StreamSettings extends XrayCommonClass {
|
|||||||
this.quic = quicSettings;
|
this.quic = quicSettings;
|
||||||
this.grpc = grpcSettings;
|
this.grpc = grpcSettings;
|
||||||
this.httpupgrade = httpupgradeSettings;
|
this.httpupgrade = httpupgradeSettings;
|
||||||
|
this.splithttp = splithttpSettings;
|
||||||
this.sockopt = sockopt;
|
this.sockopt = sockopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1080,6 +1094,7 @@ class StreamSettings extends XrayCommonClass {
|
|||||||
QuicStreamSettings.fromJson(json.quicSettings),
|
QuicStreamSettings.fromJson(json.quicSettings),
|
||||||
GrpcStreamSettings.fromJson(json.grpcSettings),
|
GrpcStreamSettings.fromJson(json.grpcSettings),
|
||||||
HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
|
HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
|
||||||
|
SplitHTTPStreamSettings.fromJson(json.splithttpSettings),
|
||||||
SockoptStreamSettings.fromJson(json.sockopt),
|
SockoptStreamSettings.fromJson(json.sockopt),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1100,6 +1115,7 @@ class StreamSettings extends XrayCommonClass {
|
|||||||
quicSettings: network === 'quic' ? this.quic.toJson() : undefined,
|
quicSettings: network === 'quic' ? this.quic.toJson() : undefined,
|
||||||
grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
|
grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
|
||||||
httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
|
httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
|
||||||
|
splithttpSettings: network === 'splithttp' ? this.splithttp.toJson() : undefined,
|
||||||
sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined,
|
sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1228,6 +1244,10 @@ class Inbound extends XrayCommonClass {
|
|||||||
return this.network === "httpupgrade";
|
return this.network === "httpupgrade";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isSplithttp() {
|
||||||
|
return this.network === "splithttp";
|
||||||
|
}
|
||||||
|
|
||||||
// Shadowsocks
|
// Shadowsocks
|
||||||
get method() {
|
get method() {
|
||||||
switch (this.protocol) {
|
switch (this.protocol) {
|
||||||
@@ -1251,25 +1271,26 @@ class Inbound extends XrayCommonClass {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getHeader(obj, name) {
|
||||||
|
for (const header of obj.headers) {
|
||||||
|
if (header.name.toLowerCase() === name.toLowerCase()) {
|
||||||
|
return header.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
get host() {
|
get host() {
|
||||||
if (this.isTcp) {
|
if (this.isTcp) {
|
||||||
return this.stream.tcp.request.getHeader("Host");
|
return this.getHeader(this.stream.tcp.request, 'host');
|
||||||
} else if (this.isWs) {
|
} else if (this.isWs) {
|
||||||
const hostHeader = this.stream.ws.getHeader("Host");
|
return this.stream.ws.host?.length>0 ? this.stream.ws.host : this.getHeader(this.stream.ws, 'host');
|
||||||
if (hostHeader !== null) {
|
|
||||||
return hostHeader;
|
|
||||||
} else {
|
|
||||||
return this.stream.ws.host;
|
|
||||||
}
|
|
||||||
} else if (this.isH2) {
|
} else if (this.isH2) {
|
||||||
return this.stream.http.host[0];
|
return this.stream.http.host[0];
|
||||||
} else if (this.isHttpupgrade) {
|
} else if (this.isHttpupgrade) {
|
||||||
const hostHeader = this.stream.httpupgrade.getHeader("Host");
|
return this.stream.httpupgrade.host?.length>0 ? this.stream.httpupgrade.host : this.getHeader(this.stream.httpupgrade, 'host');
|
||||||
if (hostHeader !== null) {
|
} else if (this.isSplithttp) {
|
||||||
return hostHeader;
|
return this.stream.splithttp.host?.length>0 ? this.stream.splithttp.host : this.getHeader(this.stream.splithttp, 'host');
|
||||||
} else {
|
|
||||||
return this.stream.httpupgrade.host;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1283,6 +1304,8 @@ class Inbound extends XrayCommonClass {
|
|||||||
return this.stream.http.path;
|
return this.stream.http.path;
|
||||||
} else if (this.isHttpupgrade) {
|
} else if (this.isHttpupgrade) {
|
||||||
return this.stream.httpupgrade.path;
|
return this.stream.httpupgrade.path;
|
||||||
|
} else if (this.isSplithttp) {
|
||||||
|
return this.stream.splithttp.path;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1318,7 +1341,7 @@ class Inbound extends XrayCommonClass {
|
|||||||
|
|
||||||
canEnableTls() {
|
canEnableTls() {
|
||||||
if(![Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol)) return false;
|
if(![Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol)) return false;
|
||||||
return ["tcp", "ws", "http", "quic", "grpc", "httpupgrade"].includes(this.network);
|
return ["tcp", "ws", "http", "quic", "grpc", "httpupgrade" , "splithttp"].includes(this.network);
|
||||||
}
|
}
|
||||||
|
|
||||||
//this is used for xtls-rprx-vision
|
//this is used for xtls-rprx-vision
|
||||||
@@ -1368,30 +1391,24 @@ class Inbound extends XrayCommonClass {
|
|||||||
type: 'none',
|
type: 'none',
|
||||||
tls: security,
|
tls: security,
|
||||||
};
|
};
|
||||||
let network = this.stream.network;
|
const network = this.stream.network;
|
||||||
if (network === 'tcp') {
|
if (network === 'tcp') {
|
||||||
let tcp = this.stream.tcp;
|
const tcp = this.stream.tcp;
|
||||||
obj.type = tcp.type;
|
obj.type = tcp.type;
|
||||||
if (tcp.type === 'http') {
|
if (tcp.type === 'http') {
|
||||||
let request = tcp.request;
|
const request = tcp.request;
|
||||||
obj.path = request.path.join(',');
|
obj.path = request.path.join(',');
|
||||||
let index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
const host = this.getHeader(request,'host');
|
||||||
if (index >= 0) {
|
if (host) obj.host = host;
|
||||||
obj.host = request.headers[index].value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (network === 'kcp') {
|
} else if (network === 'kcp') {
|
||||||
let kcp = this.stream.kcp;
|
const kcp = this.stream.kcp;
|
||||||
obj.type = kcp.type;
|
obj.type = kcp.type;
|
||||||
obj.path = kcp.seed;
|
obj.path = kcp.seed;
|
||||||
} else if (network === 'ws') {
|
} else if (network === 'ws') {
|
||||||
let ws = this.stream.ws;
|
const ws = this.stream.ws;
|
||||||
obj.path = ws.path;
|
obj.path = ws.path;
|
||||||
obj.host = ws.host;
|
obj.host = ws.host?.length>0 ? ws.host : this.getHeader(ws, 'host');
|
||||||
let index = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
|
||||||
if (index >= 0) {
|
|
||||||
obj.host = ws.headers[index].value;
|
|
||||||
}
|
|
||||||
} else if (network === 'http') {
|
} else if (network === 'http') {
|
||||||
obj.net = 'h2';
|
obj.net = 'h2';
|
||||||
obj.path = this.stream.http.path;
|
obj.path = this.stream.http.path;
|
||||||
@@ -1407,13 +1424,13 @@ class Inbound extends XrayCommonClass {
|
|||||||
obj.type = 'multi'
|
obj.type = 'multi'
|
||||||
}
|
}
|
||||||
} else if (network === 'httpupgrade') {
|
} else if (network === 'httpupgrade') {
|
||||||
let httpupgrade = this.stream.httpupgrade;
|
const httpupgrade = this.stream.httpupgrade;
|
||||||
obj.path = httpupgrade.path;
|
obj.path = httpupgrade.path;
|
||||||
obj.host = httpupgrade.host;
|
obj.host = httpupgrade.host?.length>0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host');
|
||||||
let index = httpupgrade.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
} else if (network === 'splithttp') {
|
||||||
if (index >= 0) {
|
const splithttp = this.stream.splithttp;
|
||||||
obj.host = httpupgrade.headers[index].value;
|
obj.path = splithttp.path;
|
||||||
}
|
obj.host = splithttp.host?.length>0 ? splithttp.host : this.getHeader(splithttp, 'host');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (security === 'tls') {
|
if (security === 'tls') {
|
||||||
@@ -1446,9 +1463,9 @@ class Inbound extends XrayCommonClass {
|
|||||||
if (tcp.type === 'http') {
|
if (tcp.type === 'http') {
|
||||||
const request = tcp.request;
|
const request = tcp.request;
|
||||||
params.set("path", request.path.join(','));
|
params.set("path", request.path.join(','));
|
||||||
const tcpIndex = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
||||||
if (tcpIndex >= 0) {
|
if (index >= 0) {
|
||||||
const host = request.headers[tcpIndex].value;
|
const host = request.headers[index].value;
|
||||||
params.set("host", host);
|
params.set("host", host);
|
||||||
}
|
}
|
||||||
params.set("headerType", 'http');
|
params.set("headerType", 'http');
|
||||||
@@ -1462,12 +1479,7 @@ class Inbound extends XrayCommonClass {
|
|||||||
case "ws":
|
case "ws":
|
||||||
const ws = this.stream.ws;
|
const ws = this.stream.ws;
|
||||||
params.set("path", ws.path);
|
params.set("path", ws.path);
|
||||||
params.set("host", ws.host);
|
params.set("host", ws.host?.length>0 ? ws.host : this.getHeader(ws, 'host'));
|
||||||
const wsIndex = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
|
||||||
if (wsIndex >= 0) {
|
|
||||||
const host = ws.headers[wsIndex].value;
|
|
||||||
params.set("host", host);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "http":
|
case "http":
|
||||||
const http = this.stream.http;
|
const http = this.stream.http;
|
||||||
@@ -1489,14 +1501,14 @@ class Inbound extends XrayCommonClass {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "httpupgrade":
|
case "httpupgrade":
|
||||||
const httpupgrade = this.stream.httpupgrade;
|
const httpupgrade = this.stream.httpupgrade;
|
||||||
params.set("path", httpupgrade.path);
|
params.set("path", httpupgrade.path);
|
||||||
params.set("host", httpupgrade.host);
|
params.set("host", httpupgrade.host?.length>0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host'));
|
||||||
const httpupgradeIndex = httpupgrade.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
break;
|
||||||
if (httpupgradeIndex >= 0) {
|
case "splithttp":
|
||||||
const host = httpupgrade.headers[httpupgradeIndex].value;
|
const splithttp = this.stream.splithttp;
|
||||||
params.set("host", host);
|
params.set("path", splithttp.path);
|
||||||
}
|
params.set("host", splithttp.host?.length>0 ? splithttp.host : this.getHeader(splithttp, 'host'));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1572,9 +1584,9 @@ class Inbound extends XrayCommonClass {
|
|||||||
if (tcp.type === 'http') {
|
if (tcp.type === 'http') {
|
||||||
const request = tcp.request;
|
const request = tcp.request;
|
||||||
params.set("path", request.path.join(','));
|
params.set("path", request.path.join(','));
|
||||||
const tcpIndex = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
||||||
if (tcpIndex >= 0) {
|
if (index >= 0) {
|
||||||
const host = request.headers[tcpIndex].value;
|
const host = request.headers[index].value;
|
||||||
params.set("host", host);
|
params.set("host", host);
|
||||||
}
|
}
|
||||||
params.set("headerType", 'http');
|
params.set("headerType", 'http');
|
||||||
@@ -1588,12 +1600,7 @@ class Inbound extends XrayCommonClass {
|
|||||||
case "ws":
|
case "ws":
|
||||||
const ws = this.stream.ws;
|
const ws = this.stream.ws;
|
||||||
params.set("path", ws.path);
|
params.set("path", ws.path);
|
||||||
params.set("host", ws.host);
|
params.set("host", ws.host?.length>0 ? ws.host : this.getHeader(ws, 'host'));
|
||||||
const wsIndex = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
|
||||||
if (wsIndex >= 0) {
|
|
||||||
const host = ws.headers[wsIndex].value;
|
|
||||||
params.set("host", host);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "http":
|
case "http":
|
||||||
const http = this.stream.http;
|
const http = this.stream.http;
|
||||||
@@ -1615,14 +1622,14 @@ class Inbound extends XrayCommonClass {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "httpupgrade":
|
case "httpupgrade":
|
||||||
const httpupgrade = this.stream.httpupgrade;
|
const httpupgrade = this.stream.httpupgrade;
|
||||||
params.set("path", httpupgrade.path);
|
params.set("path", httpupgrade.path);
|
||||||
params.set("host", httpupgrade.host);
|
params.set("host", httpupgrade.host?.length>0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host'));
|
||||||
const httpupgradeIndex = httpupgrade.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
break;
|
||||||
if (httpupgradeIndex >= 0) {
|
case "splithttp":
|
||||||
const host = httpupgrade.headers[httpupgradeIndex].value;
|
const splithttp = this.stream.splithttp;
|
||||||
params.set("host", host);
|
params.set("path", splithttp.path);
|
||||||
}
|
params.set("host", splithttp.host?.length>0 ? splithttp.host : this.getHeader(splithttp, 'host'));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1665,9 +1672,9 @@ class Inbound extends XrayCommonClass {
|
|||||||
if (tcp.type === 'http') {
|
if (tcp.type === 'http') {
|
||||||
const request = tcp.request;
|
const request = tcp.request;
|
||||||
params.set("path", request.path.join(','));
|
params.set("path", request.path.join(','));
|
||||||
const tcpIndex = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
||||||
if (tcpIndex >= 0) {
|
if (index >= 0) {
|
||||||
const host = request.headers[tcpIndex].value;
|
const host = request.headers[index].value;
|
||||||
params.set("host", host);
|
params.set("host", host);
|
||||||
}
|
}
|
||||||
params.set("headerType", 'http');
|
params.set("headerType", 'http');
|
||||||
@@ -1681,12 +1688,7 @@ class Inbound extends XrayCommonClass {
|
|||||||
case "ws":
|
case "ws":
|
||||||
const ws = this.stream.ws;
|
const ws = this.stream.ws;
|
||||||
params.set("path", ws.path);
|
params.set("path", ws.path);
|
||||||
params.set("host", ws.host);
|
params.set("host", ws.host?.length>0 ? ws.host : this.getHeader(ws, 'host'));
|
||||||
const wsIndex = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
|
||||||
if (wsIndex >= 0) {
|
|
||||||
const host = ws.headers[wsIndex].value;
|
|
||||||
params.set("host", host);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "http":
|
case "http":
|
||||||
const http = this.stream.http;
|
const http = this.stream.http;
|
||||||
@@ -1708,14 +1710,14 @@ class Inbound extends XrayCommonClass {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "httpupgrade":
|
case "httpupgrade":
|
||||||
const httpupgrade = this.stream.httpupgrade;
|
const httpupgrade = this.stream.httpupgrade;
|
||||||
params.set("path", httpupgrade.path);
|
params.set("path", httpupgrade.path);
|
||||||
params.set("host", httpupgrade.host);
|
params.set("host", httpupgrade.host?.length>0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host'));
|
||||||
const httpUpgradeIndex = httpupgrade.headers.findIndex(header => header.name.toLowerCase() === 'host');
|
break;
|
||||||
if (httpUpgradeIndex >= 0) {
|
case "splithttp":
|
||||||
const host = httpupgrade.headers[httpUpgradeIndex].value;
|
const splithttp = this.stream.splithttp;
|
||||||
params.set("host", host);
|
params.set("path", splithttp.path);
|
||||||
}
|
params.set("host", splithttp.host?.length>0 ? splithttp.host : this.getHeader(splithttp, 'host'));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<a-input-number v-model="client.limitIp" min="0"></a-input-number>
|
<a-input-number v-model="client.limitIp" min="0"></a-input-number>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item v-if="client.limitIp > 0 && client.email && isEdit">
|
<a-form-item v-if="app.ipLimitEnable && client.limitIp > 0 && client.email && isEdit">
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
|
|||||||
@@ -72,9 +72,23 @@
|
|||||||
</template>
|
</template>
|
||||||
<a-input v-model.trim="outbound.settings.address"></a-input>
|
<a-input v-model.trim="outbound.settings.address"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label='{{ i18n "pages.xray.wireguard.secretKey" }}'>
|
<a-form-item>
|
||||||
|
<template slot="label">
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "reset" }}</span>
|
||||||
|
</template>
|
||||||
|
{{ i18n "pages.xray.wireguard.secretKey" }}
|
||||||
|
<a-icon type="sync"
|
||||||
|
@click="[outbound.settings.pubKey, outbound.settings.secretKey] = Object.values(Wireguard.generateKeypair())">
|
||||||
|
</a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
<a-input v-model.trim="outbound.settings.secretKey"></a-input>
|
<a-input v-model.trim="outbound.settings.secretKey"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label='{{ i18n "pages.xray.wireguard.publicKey" }}'>
|
||||||
|
<a-input disabled v-model="outbound.settings.pubKey"></a-input>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item label='{{ i18n "pages.xray.wireguard.domainStrategy" }}'>
|
<a-form-item label='{{ i18n "pages.xray.wireguard.domainStrategy" }}'>
|
||||||
<a-select v-model="outbound.settings.domainStrategy" :dropdown-class-name="themeSwitcher.currentTheme">
|
<a-select v-model="outbound.settings.domainStrategy" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-select-option v-for="wds in ['', ...WireguardDomainStrategy]" :value="wds">[[ wds ]]</a-select-option>
|
<a-select-option v-for="wds in ['', ...WireguardDomainStrategy]" :value="wds">[[ wds ]]</a-select-option>
|
||||||
@@ -187,6 +201,9 @@
|
|||||||
<a-form-item label='UDP over TCP'>
|
<a-form-item label='UDP over TCP'>
|
||||||
<a-switch v-model="outbound.settings.uot"></a-switch>
|
<a-switch v-model="outbound.settings.uot"></a-switch>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label='UoTVersion'>
|
||||||
|
<a-input-number v-model.number="outbound.settings.UoTVersion" :min="1" :max="2"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -201,6 +218,7 @@
|
|||||||
<a-select-option value="quic">QUIC</a-select-option>
|
<a-select-option value="quic">QUIC</a-select-option>
|
||||||
<a-select-option value="grpc">gRPC</a-select-option>
|
<a-select-option value="grpc">gRPC</a-select-option>
|
||||||
<a-select-option value="httpupgrade">HTTPUpgrade</a-select-option>
|
<a-select-option value="httpupgrade">HTTPUpgrade</a-select-option>
|
||||||
|
<a-select-option value="splithttp">SplitHTTP</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<template v-if="outbound.stream.network === 'tcp'">
|
<template v-if="outbound.stream.network === 'tcp'">
|
||||||
@@ -322,6 +340,16 @@
|
|||||||
<a-input v-model.trim="outbound.stream.httpupgrade.path"></a-input>
|
<a-input v-model.trim="outbound.stream.httpupgrade.path"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- splithttp -->
|
||||||
|
<template v-if="outbound.stream.network === 'splithttp'">
|
||||||
|
<a-form-item label='{{ i18n "host" }}'>
|
||||||
|
<a-input v-model="outbound.stream.splithttp.host"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label='{{ i18n "path" }}'>
|
||||||
|
<a-input v-model.trim="outbound.stream.splithttp.path"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- tls settings -->
|
<!-- tls settings -->
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
<a-select-option value="quic">QUIC</a-select-option>
|
<a-select-option value="quic">QUIC</a-select-option>
|
||||||
<a-select-option value="grpc">gRPC</a-select-option>
|
<a-select-option value="grpc">gRPC</a-select-option>
|
||||||
<a-select-option value="httpupgrade">HTTPUpgrade</a-select-option>
|
<a-select-option value="httpupgrade">HTTPUpgrade</a-select-option>
|
||||||
|
<a-select-option value="splithttp">SplitHTTP</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
@@ -50,6 +51,11 @@
|
|||||||
{{template "form/streamHTTPUpgrade"}}
|
{{template "form/streamHTTPUpgrade"}}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- splithttp -->
|
||||||
|
<template v-if="inbound.stream.network === 'splithttp'">
|
||||||
|
{{template "form/streamSplitHTTP"}}
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- sockopt -->
|
<!-- sockopt -->
|
||||||
<template>
|
<template>
|
||||||
{{template "form/streamSockopt"}}
|
{{template "form/streamSockopt"}}
|
||||||
|
|||||||
29
web/html/xui/form/stream/stream_splithttp.html
Normal file
29
web/html/xui/form/stream/stream_splithttp.html
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{{define "form/streamSplitHTTP"}}
|
||||||
|
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
|
||||||
|
<a-form-item label='{{ i18n "host" }}'>
|
||||||
|
<a-input v-model.trim="inbound.stream.splithttp.host"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label='{{ i18n "path" }}'>
|
||||||
|
<a-input v-model.trim="inbound.stream.splithttp.path"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'>
|
||||||
|
<a-button icon="plus" size="small" @click="inbound.stream.splithttp.addHeader('host', '')"></a-button>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :wrapper-col="{span:24}">
|
||||||
|
<a-input-group compact v-for="(header, index) in inbound.stream.splithttp.headers">
|
||||||
|
<a-input style="width: 50%" v-model.trim="header.name" placeholder='{{ i18n "pages.inbounds.stream.general.name"}}'>
|
||||||
|
<template slot="addonBefore" style="margin: 0;">[[ index+1 ]]</template>
|
||||||
|
</a-input>
|
||||||
|
<a-input style="width: 50%" v-model.trim="header.value" placeholder='{{ i18n "pages.inbounds.stream.general.value" }}'>
|
||||||
|
<a-button slot="addonAfter" size="small" @click="inbound.stream.splithttp.removeHeader(index)">-</a-button>
|
||||||
|
</a-input>
|
||||||
|
</a-input-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Max Upload Size (MB)">
|
||||||
|
<a-input-number v-model="inbound.stream.splithttp.maxUploadSize" :min="0"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Max Concurrent Upload">
|
||||||
|
<a-input-number v-model="inbound.stream.splithttp.maxConcurrentUploads" :min="0"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
{{end}}
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<a-tag color="green">[[ inbound.network ]]</a-tag>
|
<a-tag color="green">[[ inbound.network ]]</a-tag>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<template v-if="inbound.isTcp || inbound.isWs || inbound.isH2 || inbound.isHttpupgrade ">
|
<template v-if="inbound.isTcp || inbound.isWs || inbound.isH2 || inbound.isHttpupgrade || inbound.isSplithttp">
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ i18n "host" }}</td>
|
<td>{{ i18n "host" }}</td>
|
||||||
<td v-if="inbound.host">
|
<td v-if="inbound.host">
|
||||||
|
|||||||
@@ -664,7 +664,7 @@
|
|||||||
tgBotEnable: false,
|
tgBotEnable: false,
|
||||||
showAlert: false,
|
showAlert: false,
|
||||||
ipLimitEnable: false,
|
ipLimitEnable: false,
|
||||||
pageSize: 0,
|
pageSize: 50,
|
||||||
isMobile: window.innerWidth <= 768,
|
isMobile: window.innerWidth <= 768,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -1058,7 +1058,7 @@
|
|||||||
resetTraffic(dbInboundId) {
|
resetTraffic(dbInboundId) {
|
||||||
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
|
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '{{ i18n "pages.inbounds.resetTraffic"}}',
|
title: '{{ i18n "pages.inbounds.resetTraffic"}}' + ' #' + dbInboundId,
|
||||||
content: '{{ i18n "pages.inbounds.resetTrafficContent"}}',
|
content: '{{ i18n "pages.inbounds.resetTrafficContent"}}',
|
||||||
class: themeSwitcher.currentTheme,
|
class: themeSwitcher.currentTheme,
|
||||||
okText: '{{ i18n "reset"}}',
|
okText: '{{ i18n "reset"}}',
|
||||||
@@ -1141,9 +1141,9 @@
|
|||||||
infoModal.show(newDbInbound, index);
|
infoModal.show(newDbInbound, index);
|
||||||
},
|
},
|
||||||
switchEnable(dbInboundId,state) {
|
switchEnable(dbInboundId,state) {
|
||||||
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
|
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
|
||||||
dbInbound.enable = state;
|
dbInbound.enable = state;
|
||||||
this.submit(`/panel/inbound/update/${dbInboundId}`, dbInbound);
|
this.submit(`/panel/inbound/update/${dbInboundId}`, dbInbound);
|
||||||
},
|
},
|
||||||
async switchEnableClient(dbInboundId, client) {
|
async switchEnableClient(dbInboundId, client) {
|
||||||
this.loading()
|
this.loading()
|
||||||
@@ -1168,7 +1168,7 @@
|
|||||||
resetClientTraffic(client, dbInboundId, confirmation = true) {
|
resetClientTraffic(client, dbInboundId, confirmation = true) {
|
||||||
if (confirmation){
|
if (confirmation){
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '{{ i18n "pages.inbounds.resetTraffic"}}',
|
title: '{{ i18n "pages.inbounds.resetTraffic"}}' + ' ' + client.email,
|
||||||
content: '{{ i18n "pages.inbounds.resetTrafficContent"}}',
|
content: '{{ i18n "pages.inbounds.resetTrafficContent"}}',
|
||||||
class: themeSwitcher.currentTheme,
|
class: themeSwitcher.currentTheme,
|
||||||
okText: '{{ i18n "reset"}}',
|
okText: '{{ i18n "reset"}}',
|
||||||
@@ -1285,12 +1285,12 @@
|
|||||||
return this.onlineClients.includes(email);
|
return this.onlineClients.includes(email);
|
||||||
},
|
},
|
||||||
isRemovable(dbInboundId) {
|
isRemovable(dbInboundId) {
|
||||||
return this.getInboundClients(this.dbInbounds.find(row => row.id === dbInboundId)).length > 1
|
return this.getInboundClients(this.dbInbounds.find(row => row.id === dbInboundId)).length > 1;
|
||||||
},
|
},
|
||||||
inboundLinks(dbInboundId) {
|
inboundLinks(dbInboundId) {
|
||||||
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
|
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
|
||||||
newDbInbound = this.checkFallback(dbInbound);
|
newDbInbound = this.checkFallback(dbInbound);
|
||||||
txtModal.show('{{ i18n "pages.inbounds.export"}}', newDbInbound.genInboundLinks(), newDbInbound.remark);
|
txtModal.show('{{ i18n "pages.inbounds.export"}}', newDbInbound.genInboundLinks(this.remarkModel), newDbInbound.remark);
|
||||||
},
|
},
|
||||||
exportSubs(dbInboundId) {
|
exportSubs(dbInboundId) {
|
||||||
const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
|
const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
<div><b>CPU:</b> [[ cpuCoreFormat(status.cpuCores) ]] <a-tooltip>
|
<div><b>CPU:</b> [[ cpuCoreFormat(status.cpuCores) ]] <a-tooltip>
|
||||||
<a-icon type="area-chart"></a-icon>
|
<a-icon type="area-chart"></a-icon>
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<div><b>Logical Processors(vCPUs):</b> [[ (status.logicalPro) ]]</div>
|
<div><b>Logical Processors:</b> [[ (status.logicalPro) ]]</div>
|
||||||
<div><b>Speed:</b> [[ cpuSpeedFormat(status.cpuSpeedMhz) ]]</div>
|
<div><b>Speed:</b> [[ cpuSpeedFormat(status.cpuSpeedMhz) ]]</div>
|
||||||
</template>
|
</template>
|
||||||
</a-tooltip></div>
|
</a-tooltip></div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"x-ui/web/service"
|
"x-ui/web/service"
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/v3/cpu"
|
"github.com/shirou/gopsutil/v4/cpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CheckCpuJob struct {
|
type CheckCpuJob struct {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package job
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"x-ui/logger"
|
"x-ui/logger"
|
||||||
"x-ui/xray"
|
"x-ui/xray"
|
||||||
@@ -14,28 +15,53 @@ func NewClearLogsJob() *ClearLogsJob {
|
|||||||
return new(ClearLogsJob)
|
return new(ClearLogsJob)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensureFileExists creates the necessary directories and file if they don't exist
|
||||||
|
func ensureFileExists(path string) error {
|
||||||
|
dir := filepath.Dir(path)
|
||||||
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
file.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Here Run is an interface method of the Job interface
|
// Here Run is an interface method of the Job interface
|
||||||
func (j *ClearLogsJob) Run() {
|
func (j *ClearLogsJob) Run() {
|
||||||
logFiles := []string{xray.GetIPLimitLogPath(), xray.GetIPLimitBannedLogPath(), xray.GetAccessPersistentLogPath()}
|
logFiles := []string{xray.GetIPLimitLogPath(), xray.GetIPLimitBannedLogPath(), xray.GetAccessPersistentLogPath()}
|
||||||
logFilesPrev := []string{xray.GetIPLimitBannedPrevLogPath(), xray.GetAccessPersistentPrevLogPath()}
|
logFilesPrev := []string{xray.GetIPLimitBannedPrevLogPath(), xray.GetAccessPersistentPrevLogPath()}
|
||||||
|
|
||||||
// clear log files and copy to previous logs
|
// Ensure all log files and their paths exist
|
||||||
|
for _, path := range append(logFiles, logFilesPrev...) {
|
||||||
|
if err := ensureFileExists(path); err != nil {
|
||||||
|
logger.Warning("Failed to ensure log file exists:", path, "-", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear log files and copy to previous logs
|
||||||
for i := 0; i < len(logFiles); i++ {
|
for i := 0; i < len(logFiles); i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
// copy to previous logs
|
// Copy to previous logs
|
||||||
logFilePrev, err := os.OpenFile(logFilesPrev[i-1], os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
logFilePrev, err := os.OpenFile(logFilesPrev[i-1], os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("clear logs job err:", err)
|
logger.Warning("Failed to open previous log file for writing:", logFilesPrev[i-1], "-", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
logFile, err := os.OpenFile(logFiles[i], os.O_CREATE|os.O_RDONLY, 0644)
|
logFile, err := os.OpenFile(logFiles[i], os.O_RDONLY, 0644)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
_, err = io.Copy(logFilePrev, logFile)
|
logger.Warning("Failed to open current log file for reading:", logFiles[i], "-", err)
|
||||||
if err != nil {
|
logFilePrev.Close()
|
||||||
logger.Warning("clear logs job err:", err)
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
logger.Warning("clear logs job err:", err)
|
_, err = io.Copy(logFilePrev, logFile)
|
||||||
|
if err != nil {
|
||||||
|
logger.Warning("Failed to copy log file:", logFiles[i], "to", logFilesPrev[i-1], "-", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logFile.Close()
|
logFile.Close()
|
||||||
@@ -44,7 +70,7 @@ func (j *ClearLogsJob) Run() {
|
|||||||
|
|
||||||
err := os.Truncate(logFiles[i], 0)
|
err := os.Truncate(logFiles[i], 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("clear logs job err:", err)
|
logger.Warning("Failed to truncate log file:", logFiles[i], "-", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -696,8 +696,12 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
|
|||||||
needRestart := false
|
needRestart := false
|
||||||
if len(oldEmail) > 0 {
|
if len(oldEmail) > 0 {
|
||||||
s.xrayApi.Init(p.GetAPIPort())
|
s.xrayApi.Init(p.GetAPIPort())
|
||||||
if s.xrayApi.RemoveUser(oldInbound.Tag, oldEmail) == nil {
|
err1 := s.xrayApi.RemoveUser(oldInbound.Tag, oldEmail)
|
||||||
|
if err1 == nil {
|
||||||
logger.Debug("Old client deleted by api:", clients[0].Email)
|
logger.Debug("Old client deleted by api:", clients[0].Email)
|
||||||
|
} else {
|
||||||
|
logger.Debug("Error in deleting client by api:", err1)
|
||||||
|
needRestart = true
|
||||||
}
|
}
|
||||||
if clients[0].Enable {
|
if clients[0].Enable {
|
||||||
cipher := ""
|
cipher := ""
|
||||||
@@ -1685,7 +1689,11 @@ func (s *InboundService) DelDepletedClients(id int) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = tx.Where(whereText+" and enable = ?", id, false).Delete(xray.ClientTraffic{}).Error
|
err = tx.Where(whereText+" and enable = ?", id, false).Delete(xray.ClientTraffic{}).Error
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) GetClientTrafficTgBot(tgId int64) ([]*xray.ClientTraffic, error) {
|
func (s *InboundService) GetClientTrafficTgBot(tgId int64) ([]*xray.ClientTraffic, error) {
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ import (
|
|||||||
"x-ui/util/sys"
|
"x-ui/util/sys"
|
||||||
"x-ui/xray"
|
"x-ui/xray"
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/v3/cpu"
|
"github.com/shirou/gopsutil/v4/cpu"
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
"github.com/shirou/gopsutil/v4/disk"
|
||||||
"github.com/shirou/gopsutil/v3/host"
|
"github.com/shirou/gopsutil/v4/host"
|
||||||
"github.com/shirou/gopsutil/v3/load"
|
"github.com/shirou/gopsutil/v4/load"
|
||||||
"github.com/shirou/gopsutil/v3/mem"
|
"github.com/shirou/gopsutil/v4/mem"
|
||||||
"github.com/shirou/gopsutil/v3/net"
|
"github.com/shirou/gopsutil/v4/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProcessState string
|
type ProcessState string
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ var defaultValueMap = map[string]string{
|
|||||||
"secret": random.Seq(32),
|
"secret": random.Seq(32),
|
||||||
"webBasePath": "/",
|
"webBasePath": "/",
|
||||||
"sessionMaxAge": "0",
|
"sessionMaxAge": "0",
|
||||||
"pageSize": "0",
|
"pageSize": "50",
|
||||||
"expireDiff": "0",
|
"expireDiff": "0",
|
||||||
"trafficDiff": "0",
|
"trafficDiff": "0",
|
||||||
"remarkModel": "-ieo",
|
"remarkModel": "-ieo",
|
||||||
|
|||||||
181
x-ui.sh
181
x-ui.sh
@@ -157,6 +157,30 @@ update() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_menu() {
|
||||||
|
echo -e "${yellow}Updating Menu${plain}"
|
||||||
|
confirm "This function will update the menu to the latest changes." "y"
|
||||||
|
if [[ $? != 0 ]]; then
|
||||||
|
LOGE "Cancelled"
|
||||||
|
if [[ $# == 0 ]]; then
|
||||||
|
before_show_menu
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
wget --no-check-certificate -O /usr/bin/x-ui https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.sh
|
||||||
|
chmod +x /usr/local/x-ui/x-ui.sh
|
||||||
|
chmod +x /usr/bin/x-ui
|
||||||
|
|
||||||
|
if [[ $? == 0 ]]; then
|
||||||
|
echo -e "${green}Update successful. The panel has automatically restarted.${plain}"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo -e "${red}Failed to update the menu.${plain}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
custom_version() {
|
custom_version() {
|
||||||
echo "Enter the panel version (like 2.0.0):"
|
echo "Enter the panel version (like 2.0.0):"
|
||||||
read panel_version
|
read panel_version
|
||||||
@@ -228,6 +252,32 @@ reset_user() {
|
|||||||
confirm_restart
|
confirm_restart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gen_random_string() {
|
||||||
|
local length="$1"
|
||||||
|
local random_string=$(LC_ALL=C tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w "$length" | head -n 1)
|
||||||
|
echo "$random_string"
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_webbasepath() {
|
||||||
|
echo -e "${yellow}Resetting Web Base Path${plain}"
|
||||||
|
|
||||||
|
# Prompt user to set a new web base path
|
||||||
|
read -rp "Please set the new web base path [default is a random path]: " config_webBasePath
|
||||||
|
|
||||||
|
# If user input is empty, generate a random path
|
||||||
|
if [[ -z $config_webBasePath ]]; then
|
||||||
|
config_webBasePath=$(gen_random_string 10)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Apply the new web base path setting
|
||||||
|
/usr/local/x-ui/x-ui setting -webBasePath "${config_webBasePath}" >/dev/null 2>&1
|
||||||
|
systemctl restart x-ui
|
||||||
|
|
||||||
|
# Display confirmation message
|
||||||
|
echo -e "Web base path has been reset to: ${green}${config_webBasePath}${plain}"
|
||||||
|
echo -e "${green}Please use the new web base path to access the panel.${plain}"
|
||||||
|
}
|
||||||
|
|
||||||
reset_config() {
|
reset_config() {
|
||||||
confirm "Are you sure you want to reset all panel settings, Account data will not be lost, Username and password will not change" "n"
|
confirm "Are you sure you want to reset all panel settings, Account data will not be lost, Username and password will not change" "n"
|
||||||
if [[ $? != 0 ]]; then
|
if [[ $? != 0 ]]; then
|
||||||
@@ -818,7 +868,7 @@ ssl_cert_issue() {
|
|||||||
# NOTE:This should be handled by user
|
# NOTE:This should be handled by user
|
||||||
# open the port and kill the occupied progress
|
# open the port and kill the occupied progress
|
||||||
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
|
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
|
||||||
~/.acme.sh/acme.sh --issue -d ${domain} --standalone --httpport ${WebPort}
|
~/.acme.sh/acme.sh --issue -d ${domain} --listen-v6 --standalone --httpport ${WebPort}
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
LOGE "issue certs failed,please check logs"
|
LOGE "issue certs failed,please check logs"
|
||||||
rm -rf ~/.acme.sh/${domain}
|
rm -rf ~/.acme.sh/${domain}
|
||||||
@@ -1070,7 +1120,7 @@ iplimit_main() {
|
|||||||
echo -e "${green}\t4.${plain} Check Logs"
|
echo -e "${green}\t4.${plain} Check Logs"
|
||||||
echo -e "${green}\t5.${plain} Fail2ban Status"
|
echo -e "${green}\t5.${plain} Fail2ban Status"
|
||||||
echo -e "${green}\t6.${plain} Restart Fail2ban"
|
echo -e "${green}\t6.${plain} Restart Fail2ban"
|
||||||
echo -e "${green}\t7.${plain} Uninstall IP Limit"
|
echo -e "${green}\t7.${plain} Uninstall Fail2ban"
|
||||||
echo -e "${green}\t0.${plain} Back to Main Menu"
|
echo -e "${green}\t0.${plain} Back to Main Menu"
|
||||||
read -p "Choose an option: " choice
|
read -p "Choose an option: " choice
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
@@ -1253,57 +1303,62 @@ remove_iplimit() {
|
|||||||
show_usage() {
|
show_usage() {
|
||||||
echo "x-ui control menu usages: "
|
echo "x-ui control menu usages: "
|
||||||
echo "------------------------------------------"
|
echo "------------------------------------------"
|
||||||
echo -e "x-ui - Enter control menu"
|
echo -e "SUBCOMMANDS:"
|
||||||
echo -e "x-ui start - Start x-ui "
|
echo -e "x-ui - Admin Management Script"
|
||||||
echo -e "x-ui stop - Stop x-ui "
|
echo -e "x-ui start - Start"
|
||||||
echo -e "x-ui restart - Restart x-ui "
|
echo -e "x-ui stop - Stop"
|
||||||
echo -e "x-ui status - Show x-ui status"
|
echo -e "x-ui restart - Restart"
|
||||||
echo -e "x-ui enable - Enable x-ui on system startup"
|
echo -e "x-ui status - Current Status"
|
||||||
echo -e "x-ui disable - Disable x-ui on system startup"
|
echo -e "x-ui settings - Current Settings"
|
||||||
echo -e "x-ui log - Check x-ui logs"
|
echo -e "x-ui enable - Enable Autostart on OS Startup"
|
||||||
|
echo -e "x-ui disable - Disable Autostart on OS Startup"
|
||||||
|
echo -e "x-ui log - Check logs"
|
||||||
echo -e "x-ui banlog - Check Fail2ban ban logs"
|
echo -e "x-ui banlog - Check Fail2ban ban logs"
|
||||||
echo -e "x-ui update - Update x-ui "
|
echo -e "x-ui update - Update"
|
||||||
echo -e "x-ui install - Install x-ui "
|
echo -e "x-ui custom - custom version"
|
||||||
echo -e "x-ui uninstall - Uninstall x-ui "
|
echo -e "x-ui install - Install"
|
||||||
|
echo -e "x-ui uninstall - Uninstall"
|
||||||
echo "------------------------------------------"
|
echo "------------------------------------------"
|
||||||
}
|
}
|
||||||
|
|
||||||
show_menu() {
|
show_menu() {
|
||||||
echo -e "
|
echo -e "
|
||||||
${green}3X-ui Panel Management Script${plain}
|
${green}3X-UI Panel Management Script${plain}
|
||||||
${green}0.${plain} Exit Script
|
${green}0.${plain} Exit Script
|
||||||
————————————————
|
————————————————
|
||||||
${green}1.${plain} Install
|
${green}1.${plain} Install
|
||||||
${green}2.${plain} Update
|
${green}2.${plain} Update
|
||||||
${green}3.${plain} Custom Version
|
${green}3.${plain} Update Menu
|
||||||
${green}4.${plain} Uninstall
|
${green}4.${plain} Custom Version
|
||||||
|
${green}5.${plain} Uninstall
|
||||||
————————————————
|
————————————————
|
||||||
${green}5.${plain} Reset Username & Password & Secret Token
|
${green}6.${plain} Reset Username & Password & Secret Token
|
||||||
${green}6.${plain} Reset Settings
|
${green}7.${plain} Reset Web Base Path
|
||||||
${green}7.${plain} Change Port
|
${green}8.${plain} Reset Settings
|
||||||
${green}8.${plain} View Current Settings
|
${green}9.${plain} Change Port
|
||||||
|
${green}10.${plain} View Current Settings
|
||||||
————————————————
|
————————————————
|
||||||
${green}9.${plain} Start
|
${green}11.${plain} Start
|
||||||
${green}10.${plain} Stop
|
${green}12.${plain} Stop
|
||||||
${green}11.${plain} Restart
|
${green}13.${plain} Restart
|
||||||
${green}12.${plain} Check Status
|
${green}14.${plain} Check Status
|
||||||
${green}13.${plain} Check Logs
|
${green}15.${plain} Check Logs
|
||||||
————————————————
|
————————————————
|
||||||
${green}14.${plain} Enable Autostart
|
${green}16.${plain} Enable Autostart
|
||||||
${green}15.${plain} Disable Autostart
|
${green}17.${plain} Disable Autostart
|
||||||
————————————————
|
————————————————
|
||||||
${green}16.${plain} SSL Certificate Management
|
${green}18.${plain} SSL Certificate Management
|
||||||
${green}17.${plain} Cloudflare SSL Certificate
|
${green}19.${plain} Cloudflare SSL Certificate
|
||||||
${green}18.${plain} IP Limit Management
|
${green}20.${plain} IP Limit Management
|
||||||
${green}19.${plain} WARP Management
|
${green}21.${plain} WARP Management
|
||||||
${green}20.${plain} Firewall Management
|
${green}22.${plain} Firewall Management
|
||||||
————————————————
|
————————————————
|
||||||
${green}21.${plain} Enable BBR
|
${green}23.${plain} Enable BBR
|
||||||
${green}22.${plain} Update Geo Files
|
${green}24.${plain} Update Geo Files
|
||||||
${green}23.${plain} Speedtest by Ookla
|
${green}25.${plain} Speedtest by Ookla
|
||||||
"
|
"
|
||||||
show_status
|
show_status
|
||||||
echo && read -p "Please enter your selection [0-23]: " num
|
echo && read -p "Please enter your selection [0-25]: " num
|
||||||
|
|
||||||
case "${num}" in
|
case "${num}" in
|
||||||
0)
|
0)
|
||||||
@@ -1316,70 +1371,76 @@ show_menu() {
|
|||||||
check_install && update
|
check_install && update
|
||||||
;;
|
;;
|
||||||
3)
|
3)
|
||||||
check_install && custom_version
|
check_install && update_menu
|
||||||
;;
|
;;
|
||||||
4)
|
4)
|
||||||
check_install && uninstall
|
check_install && custom_version
|
||||||
;;
|
;;
|
||||||
5)
|
5)
|
||||||
check_install && reset_user
|
check_install && uninstall
|
||||||
;;
|
;;
|
||||||
6)
|
6)
|
||||||
check_install && reset_config
|
check_install && reset_user
|
||||||
;;
|
;;
|
||||||
7)
|
7)
|
||||||
check_install && set_port
|
check_install && reset_webbasepath
|
||||||
;;
|
;;
|
||||||
8)
|
8)
|
||||||
check_install && check_config
|
check_install && reset_config
|
||||||
;;
|
;;
|
||||||
9)
|
9)
|
||||||
check_install && start
|
check_install && set_port
|
||||||
;;
|
;;
|
||||||
10)
|
10)
|
||||||
check_install && stop
|
check_install && check_config
|
||||||
;;
|
;;
|
||||||
11)
|
11)
|
||||||
check_install && restart
|
check_install && start
|
||||||
;;
|
;;
|
||||||
12)
|
12)
|
||||||
check_install && status
|
check_install && stop
|
||||||
;;
|
;;
|
||||||
13)
|
13)
|
||||||
check_install && show_log
|
check_install && restart
|
||||||
;;
|
;;
|
||||||
14)
|
14)
|
||||||
check_install && enable
|
check_install && status
|
||||||
;;
|
;;
|
||||||
15)
|
15)
|
||||||
check_install && disable
|
check_install && show_log
|
||||||
;;
|
;;
|
||||||
16)
|
16)
|
||||||
ssl_cert_issue_main
|
check_install && enable
|
||||||
;;
|
;;
|
||||||
17)
|
17)
|
||||||
ssl_cert_issue_CF
|
check_install && disable
|
||||||
;;
|
;;
|
||||||
18)
|
18)
|
||||||
iplimit_main
|
ssl_cert_issue_main
|
||||||
;;
|
;;
|
||||||
19)
|
19)
|
||||||
warp_cloudflare
|
ssl_cert_issue_CF
|
||||||
;;
|
;;
|
||||||
20)
|
20)
|
||||||
firewall_menu
|
iplimit_main
|
||||||
;;
|
;;
|
||||||
21)
|
21)
|
||||||
bbr_menu
|
warp_cloudflare
|
||||||
;;
|
;;
|
||||||
22)
|
22)
|
||||||
update_geo
|
firewall_menu
|
||||||
;;
|
;;
|
||||||
23)
|
23)
|
||||||
|
bbr_menu
|
||||||
|
;;
|
||||||
|
24)
|
||||||
|
update_geo
|
||||||
|
;;
|
||||||
|
25)
|
||||||
run_speedtest
|
run_speedtest
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
LOGE "Please enter the correct number [0-23]"
|
LOGE "Please enter the correct number [0-25]"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -1398,6 +1459,9 @@ if [[ $# > 0 ]]; then
|
|||||||
"status")
|
"status")
|
||||||
check_install 0 && status 0
|
check_install 0 && status 0
|
||||||
;;
|
;;
|
||||||
|
"settings")
|
||||||
|
check_install 0 && check_config 0
|
||||||
|
;;
|
||||||
"enable")
|
"enable")
|
||||||
check_install 0 && enable 0
|
check_install 0 && enable 0
|
||||||
;;
|
;;
|
||||||
@@ -1413,6 +1477,9 @@ if [[ $# > 0 ]]; then
|
|||||||
"update")
|
"update")
|
||||||
check_install 0 && update 0
|
check_install 0 && update 0
|
||||||
;;
|
;;
|
||||||
|
"custom")
|
||||||
|
check_install 0 && custom_version 0
|
||||||
|
;;
|
||||||
"install")
|
"install")
|
||||||
check_uninstall 0 && install 0
|
check_uninstall 0 && install 0
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -35,10 +35,11 @@ func (x *XrayAPI) Init(apiPort int) (err error) {
|
|||||||
if apiPort == 0 {
|
if apiPort == 0 {
|
||||||
return common.NewError("xray api port wrong:", apiPort)
|
return common.NewError("xray api port wrong:", apiPort)
|
||||||
}
|
}
|
||||||
x.grpcClient, err = grpc.Dial(fmt.Sprintf("127.0.0.1:%v", apiPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
conn, err := grpc.NewClient(fmt.Sprintf("127.0.0.1:%v", apiPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
x.grpcClient = conn
|
||||||
x.isConnected = true
|
x.isConnected = true
|
||||||
|
|
||||||
hsClient := command.NewHandlerServiceClient(x.grpcClient)
|
hsClient := command.NewHandlerServiceClient(x.grpcClient)
|
||||||
|
|||||||
Reference in New Issue
Block a user