mirror of
https://github.com/alireza0/x-ui.git
synced 2026-03-17 14:29:46 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d93468332 | ||
|
|
5e28644ec7 | ||
|
|
9b08f181a6 | ||
|
|
1a0c39693e | ||
|
|
18662b9c71 | ||
|
|
c39ad9cac1 | ||
|
|
b8f2195a3a | ||
|
|
57d437dff8 |
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -86,7 +86,7 @@ jobs:
|
||||
cd x-ui/bin
|
||||
|
||||
# Download dependencies
|
||||
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v26.1.31/"
|
||||
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v26.2.6/"
|
||||
if [ "${{ matrix.platform }}" == "amd64" ]; then
|
||||
wget -q ${Xray_URL}Xray-linux-64.zip
|
||||
unzip Xray-linux-64.zip
|
||||
@@ -182,7 +182,7 @@ jobs:
|
||||
cd x-ui\bin
|
||||
|
||||
# Download Xray for Windows
|
||||
$Xray_URL = "https://github.com/XTLS/Xray-core/releases/download/v26.1.31/"
|
||||
$Xray_URL = "https://github.com/XTLS/Xray-core/releases/download/v26.2.6/"
|
||||
Invoke-WebRequest -Uri "${Xray_URL}Xray-windows-64.zip" -OutFile "Xray-windows-64.zip"
|
||||
Expand-Archive -Path "Xray-windows-64.zip" -DestinationPath .
|
||||
Remove-Item "Xray-windows-64.zip"
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -14,4 +14,5 @@ dist/
|
||||
release/
|
||||
/release.sh
|
||||
/x-ui
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
/dev/
|
||||
|
||||
94
CONTRIBUTING.md
Normal file
94
CONTRIBUTING.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Contribution guide
|
||||
|
||||
This document describes **development-only** setup options for contributing to the x-ui project.
|
||||
Production deployments are **out of scope** for this guide.
|
||||
|
||||
For safety, Docker-based development is **strongly recommended**.
|
||||
Local installation should be performed **only inside a VM or disposable environment**.
|
||||
|
||||
---
|
||||
|
||||
## Recommended: Docker development setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker
|
||||
- Docker Compose (v2+)
|
||||
- Git
|
||||
|
||||
### Steps
|
||||
|
||||
```bash
|
||||
git clone https://github.com/alireza0/x-ui.git
|
||||
# or:
|
||||
# git clone https://github.com/<your_fork_name>/x-ui.git
|
||||
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
|
||||
```
|
||||
|
||||
### Explore panel
|
||||
|
||||
- Panel should be available at localhost:54321 like: [http://127.0.0.1:54321](http://127.0.0.1:54321) for example
|
||||
- Default credentials: `admin` / `admin`
|
||||
|
||||
To stop and remove containers or `ctrl` + `C`:
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
### Environment
|
||||
|
||||
When using the Docker development setup, the [docker-compose.dev.yml](/docker-compose.dev.yml) file mounts the local database directory into the container:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./dev/db:/etc/x-ui
|
||||
```
|
||||
|
||||
This means:
|
||||
|
||||
- [./dev/db](/dev/db/) on the host is used to persist panel state during development
|
||||
- `/etc/x-ui` inside the container is the active database/config directory
|
||||
- Data will survive container restarts but is isolated from the host system
|
||||
- You can safely delete `./dev/db` to reset the development database
|
||||
|
||||
---
|
||||
|
||||
## Local development setup (unsafe on host OS)
|
||||
|
||||
This method runs scripts with root privileges and alters the host system.
|
||||
Use **only inside a VM, container, or disposable test environment**.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Ubuntu/Debian or Fedora (actually anything with systemd, just use proper package manager)
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```bash
|
||||
# Ubuntu / Debian
|
||||
sudo apt update
|
||||
sudo apt upgrade -y
|
||||
sudo apt install -y golang unzip git wget
|
||||
|
||||
# Fedora
|
||||
sudo dnf update -y
|
||||
sudo dnf install -y golang unzip git wget
|
||||
```
|
||||
|
||||
### Setup panel
|
||||
|
||||
```bash
|
||||
git clone https://github.com/alireza0/x-ui.git
|
||||
# or:
|
||||
# git clone https://github.com/<your_fork_name>/x-ui.git
|
||||
|
||||
cd x-ui/
|
||||
sudo bash x-ui.sh # Select -> 10. Start
|
||||
```
|
||||
|
||||
### Explore panel
|
||||
|
||||
- Panel should be available at localhost:54321 like: [http://127.0.0.1:54321](http://127.0.0.1:54321) for example
|
||||
- Default credentials: `admin` / `admin`
|
||||
@@ -23,7 +23,7 @@ case $1 in
|
||||
esac
|
||||
mkdir -p build/bin
|
||||
cd build/bin
|
||||
wget -q "https://github.com/XTLS/Xray-core/releases/download/v26.1.31/Xray-linux-${ARCH}.zip"
|
||||
wget -q "https://github.com/XTLS/Xray-core/releases/download/v26.2.6/Xray-linux-${ARCH}.zip"
|
||||
unzip "Xray-linux-${ARCH}.zip"
|
||||
rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat LICENSE README.md
|
||||
mv xray "xray-linux-${FNAME}"
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.10.0
|
||||
1.10.1
|
||||
15
docker-compose.dev.yml
Normal file
15
docker-compose.dev.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
services:
|
||||
xui:
|
||||
build:
|
||||
context: .
|
||||
target: builder
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- .:/app
|
||||
- ./dev/db:/etc/x-ui
|
||||
environment:
|
||||
XUI_BIN_FOLDER: /app/dev/bin
|
||||
XUI_DB_FOLDER: /etc/x-ui
|
||||
XUI_LOG_LEVEL: debug
|
||||
XUI_DEBUG: "true"
|
||||
command: ["go","run","./main.go"]
|
||||
10
go.mod
10
go.mod
@@ -12,13 +12,13 @@ require (
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||
github.com/pelletier/go-toml/v2 v2.2.4
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/shirou/gopsutil/v4 v4.25.12
|
||||
github.com/xtls/xray-core v1.260131.0
|
||||
github.com/shirou/gopsutil/v4 v4.26.1
|
||||
github.com/xtls/xray-core v1.260202.0
|
||||
go.uber.org/atomic v1.11.0
|
||||
golang.org/x/text v0.33.0
|
||||
google.golang.org/grpc v1.78.0
|
||||
gorm.io/driver/sqlite v1.6.0
|
||||
gorm.io/gorm v1.31.0
|
||||
gorm.io/gorm v1.31.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -30,13 +30,13 @@ require (
|
||||
github.com/cloudflare/circl v1.6.3 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/ebitengine/purego v0.9.1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
|
||||
github.com/gin-contrib/sse v1.1.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/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/gorilla/context v1.1.2 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
|
||||
10
go.sum
10
go.sum
@@ -21,6 +21,8 @@ github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s
|
||||
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
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/gin-contrib/gzip v1.2.5 h1:fIZs0S+l17pIu1P5XRJOo/YNqfIuPCrZZ3TWB7pjckI=
|
||||
@@ -52,6 +54,8 @@ github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=
|
||||
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
@@ -134,6 +138,8 @@ github.com/sagernet/sing-shadowsocks v0.2.9 h1:Paep5zCszRKsEn8587O0MnhFWKJwDW1Y4
|
||||
github.com/sagernet/sing-shadowsocks v0.2.9/go.mod h1:TE/Z6401Pi8tgr0nBZcM/xawAI6u3F6TTbz4nH/qw+8=
|
||||
github.com/shirou/gopsutil/v4 v4.25.12 h1:e7PvW/0RmJ8p8vPGJH4jvNkOyLmbkXgXW4m6ZPic6CY=
|
||||
github.com/shirou/gopsutil/v4 v4.25.12/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU=
|
||||
github.com/shirou/gopsutil/v4 v4.26.1 h1:TOkEyriIXk2HX9d4isZJtbjXbEjf5qyKPAzbzY0JWSo=
|
||||
github.com/shirou/gopsutil/v4 v4.26.1/go.mod h1:medLI9/UNAb0dOI9Q3/7yWSqKkj00u+1tgY8nvv41pc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
@@ -161,6 +167,8 @@ github.com/xtls/reality v0.0.0-20251116175510-cd53f7d50237 h1:UXjrmniKlY+ZbIqpN9
|
||||
github.com/xtls/reality v0.0.0-20251116175510-cd53f7d50237/go.mod h1:vbHCV/3VWUvy1oKvTxxWJRPEWSeR1sYgQHIh6u/JiZQ=
|
||||
github.com/xtls/xray-core v1.260131.0 h1:gPBykLhUvRZ8sfubNerkwWqV3c15UtmSYQG2cgKqrV4=
|
||||
github.com/xtls/xray-core v1.260131.0/go.mod h1:cxzYFZrxu1B1NtPjHsqv4UzgDvRA71mV4rXYH4KtO7Q=
|
||||
github.com/xtls/xray-core v1.260202.0 h1:dYduYxGlkn/krSQJbmksbTtCdRe8OFb3YwpuXXEJG5c=
|
||||
github.com/xtls/xray-core v1.260202.0/go.mod h1:cxzYFZrxu1B1NtPjHsqv4UzgDvRA71mV4rXYH4KtO7Q=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
@@ -235,6 +243,8 @@ gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
|
||||
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
|
||||
gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY=
|
||||
gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
||||
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
|
||||
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
||||
gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0 h1:Lk6hARj5UPY47dBep70OD/TIMwikJ5fGUGX0Rm3Xigk=
|
||||
gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0/go.mod h1:QkHjoMIBaYtpVufgwv3keYAbln78mBoCuShZrPrer1Q=
|
||||
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
|
||||
|
||||
@@ -596,7 +596,6 @@ class TlsStreamSettings extends XrayCommonClass {
|
||||
maxVersion = TLS_VERSION_OPTION.TLS13,
|
||||
cipherSuites = '',
|
||||
rejectUnknownSni = false,
|
||||
pinnedPeerCertSha256 = [],
|
||||
disableSystemRoot = false,
|
||||
enableSessionResumption = false,
|
||||
certificates = [new TlsStreamSettings.Cert()],
|
||||
@@ -611,7 +610,6 @@ class TlsStreamSettings extends XrayCommonClass {
|
||||
this.maxVersion = maxVersion;
|
||||
this.cipherSuites = cipherSuites;
|
||||
this.rejectUnknownSni = rejectUnknownSni;
|
||||
this.pinnedPeerCertSha256 = pinnedPeerCertSha256;
|
||||
this.disableSystemRoot = disableSystemRoot;
|
||||
this.enableSessionResumption = enableSessionResumption;
|
||||
this.certs = certificates;
|
||||
@@ -645,7 +643,6 @@ class TlsStreamSettings extends XrayCommonClass {
|
||||
json.maxVersion,
|
||||
json.cipherSuites,
|
||||
json.rejectUnknownSni,
|
||||
json.pinnedPeerCertSha256 || [],
|
||||
json.disableSystemRoot,
|
||||
json.enableSessionResumption,
|
||||
certs,
|
||||
@@ -663,7 +660,6 @@ class TlsStreamSettings extends XrayCommonClass {
|
||||
maxVersion: this.maxVersion,
|
||||
cipherSuites: this.cipherSuites,
|
||||
rejectUnknownSni: this.rejectUnknownSni,
|
||||
pinnedPeerCertSha256: this.pinnedPeerCertSha256.length > 0 ? this.pinnedPeerCertSha256 : undefined,
|
||||
disableSystemRoot: this.disableSystemRoot,
|
||||
enableSessionResumption: this.enableSessionResumption,
|
||||
certificates: TlsStreamSettings.toJsonArray(this.certs),
|
||||
@@ -984,6 +980,8 @@ class UdpMask extends XrayCommonClass {
|
||||
case 'header-dns':
|
||||
case 'xdns':
|
||||
return { domain: settings.domain || '' };
|
||||
case 'xicmp':
|
||||
return { ip: settings.ip || '', id: settings.id ?? 0 };
|
||||
case 'mkcp-original':
|
||||
case 'header-dtls':
|
||||
case 'header-srtp':
|
||||
@@ -1309,14 +1307,6 @@ class Inbound extends XrayCommonClass {
|
||||
return null;
|
||||
}
|
||||
|
||||
get kcpType() {
|
||||
return this.stream.kcp.type;
|
||||
}
|
||||
|
||||
get kcpSeed() {
|
||||
return this.stream.kcp.seed;
|
||||
}
|
||||
|
||||
get serviceName() {
|
||||
return this.stream.grpc.serviceName;
|
||||
}
|
||||
@@ -1392,8 +1382,6 @@ class Inbound extends XrayCommonClass {
|
||||
}
|
||||
} else if (network === 'kcp') {
|
||||
const kcp = this.stream.kcp;
|
||||
obj.type = kcp.type;
|
||||
obj.path = kcp.seed;
|
||||
} else if (network === 'ws') {
|
||||
const ws = this.stream.ws;
|
||||
obj.path = ws.path;
|
||||
@@ -1456,8 +1444,6 @@ class Inbound extends XrayCommonClass {
|
||||
break;
|
||||
case "kcp":
|
||||
const kcp = this.stream.kcp;
|
||||
params.set("headerType", kcp.type);
|
||||
params.set("seed", kcp.seed);
|
||||
break;
|
||||
case "ws":
|
||||
const ws = this.stream.ws;
|
||||
@@ -1561,8 +1547,6 @@ class Inbound extends XrayCommonClass {
|
||||
break;
|
||||
case "kcp":
|
||||
const kcp = this.stream.kcp;
|
||||
params.set("headerType", kcp.type);
|
||||
params.set("seed", kcp.seed);
|
||||
break;
|
||||
case "ws":
|
||||
const ws = this.stream.ws;
|
||||
@@ -1642,8 +1626,6 @@ class Inbound extends XrayCommonClass {
|
||||
break;
|
||||
case "kcp":
|
||||
const kcp = this.stream.kcp;
|
||||
params.set("headerType", kcp.type);
|
||||
params.set("seed", kcp.seed);
|
||||
break;
|
||||
case "ws":
|
||||
const ws = this.stream.ws;
|
||||
|
||||
@@ -345,7 +345,8 @@ class TlsStreamSettings extends CommonClass {
|
||||
fingerprint = '',
|
||||
allowInsecure = false,
|
||||
echConfigList = '',
|
||||
verifyPeerCertByName = []
|
||||
verifyPeerCertByName = 'cloudflare-dns.com',
|
||||
pinnedPeerCertSha256 = '',
|
||||
) {
|
||||
super();
|
||||
this.serverName = serverName;
|
||||
@@ -353,7 +354,8 @@ class TlsStreamSettings extends CommonClass {
|
||||
this.fingerprint = fingerprint;
|
||||
this.allowInsecure = allowInsecure;
|
||||
this.echConfigList = echConfigList;
|
||||
this.verifyPeerCertByName = Array.isArray(verifyPeerCertByName) ? verifyPeerCertByName.join(",") : verifyPeerCertByName;
|
||||
this.verifyPeerCertByName = verifyPeerCertByName;
|
||||
this.pinnedPeerCertSha256 = pinnedPeerCertSha256;
|
||||
}
|
||||
|
||||
static fromJson(json = {}) {
|
||||
@@ -363,7 +365,8 @@ class TlsStreamSettings extends CommonClass {
|
||||
json.fingerprint,
|
||||
json.allowInsecure,
|
||||
json.echConfigList,
|
||||
json.verifyPeerCertByName
|
||||
json.verifyPeerCertByName,
|
||||
json.pinnedPeerCertSha256,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -374,7 +377,8 @@ class TlsStreamSettings extends CommonClass {
|
||||
fingerprint: this.fingerprint,
|
||||
allowInsecure: this.allowInsecure,
|
||||
echConfigList: this.echConfigList,
|
||||
verifyPeerCertByName: this.verifyPeerCertByName.length > 0 ? this.verifyPeerCertByName.split(",") : undefined,
|
||||
verifyPeerCertByName: this.verifyPeerCertByName,
|
||||
pinnedPeerCertSha256: this.pinnedPeerCertSha256
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -577,6 +581,8 @@ class UdpMask extends CommonClass {
|
||||
case 'header-dns':
|
||||
case 'xdns':
|
||||
return { domain: settings.domain || '' };
|
||||
case 'xicmp':
|
||||
return { ip: settings.ip || '', id: settings.id ?? 0 };
|
||||
case 'mkcp-original':
|
||||
case 'header-dtls':
|
||||
case 'header-srtp':
|
||||
|
||||
@@ -586,8 +586,13 @@
|
||||
<a-form-item label="Allow Insecure">
|
||||
<a-switch v-model="outbound.stream.tls.allowInsecure"></a-switch>
|
||||
</a-form-item>
|
||||
<a-form-item label="VerifyPeerCertByNames">
|
||||
<a-input v-model.trim="outbound.stream.tls.verifyPeerCertByNames"></a-input>
|
||||
<a-form-item label="Verify Peer Cert By Name">
|
||||
<a-input v-model.trim="outbound.stream.tls.verifyPeerCertByName"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="Pinned Peer Cert">
|
||||
<a-input v-model.trim="outbound.stream.tls.pinnedPeerCertSha256"
|
||||
placeholder="Enter SHA256 fingerprints (base64)">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
v-if="['tcp', 'ws', 'httpupgrade', 'xhttp'].includes(inbound.stream.network)"
|
||||
value="xdns">
|
||||
xDNS (Experimental)</a-select-option>
|
||||
<a-select-option v-if="inbound.stream.network === 'kcp'"
|
||||
value="xicmp">
|
||||
xICMP (Experimental)</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label='Password'
|
||||
|
||||
@@ -58,12 +58,6 @@
|
||||
<a-form-item label="Session Resumption">
|
||||
<a-switch v-model="inbound.stream.tls.enableSessionResumption"></a-switch>
|
||||
</a-form-item>
|
||||
<a-form-item label="Pinned Peer Cert">
|
||||
<a-select mode="tags" v-model="inbound.stream.tls.pinnedPeerCertSha256"
|
||||
:dropdown-class-name="themeSwitcher.currentTheme"
|
||||
placeholder="Enter SHA256 fingerprints (base64)">
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-divider :style="{ margin: '0' }"></a-divider>
|
||||
<template v-for="cert,index in inbound.stream.tls.certs">
|
||||
<a-form-item label='{{ i18n "certificate" }}'>
|
||||
|
||||
@@ -51,12 +51,7 @@
|
||||
<a-tag>[[ inbound.stream.xhttp.mode ]]</a-tag>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
<template v-if="inbound.isKcp">
|
||||
<tr><td>kcp {{ i18n "encryption" }}</td><td><a-tag>[[ inbound.kcpType ]]</a-tag></td></tr>
|
||||
<tr><td>kcp {{ i18n "password" }}</td><td><a-tag>[[ inbound.kcpSeed ]]</a-tag></td></tr>
|
||||
</template>
|
||||
|
||||
</template>
|
||||
<template v-if="inbound.isGrpc">
|
||||
<tr><td>grpc serviceName</td><td>
|
||||
<a-tooltip :title="[[ inbound.serviceName ]]">
|
||||
@@ -443,4 +438,4 @@
|
||||
});
|
||||
|
||||
</script>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -220,13 +220,13 @@
|
||||
newRule = {};
|
||||
rule.type = "field";
|
||||
rule.domainMatcher = value.domainMatcher;
|
||||
rule.domain = value.domain.length>0 ? value.domain.split(',') : [];
|
||||
rule.ip = value.ip.length>0 ? value.ip.split(',') : [];
|
||||
rule.domain = value.domain.length>0 ? value.domain.split(',').map(s => s.trim()) : [];
|
||||
rule.ip = value.ip.length>0 ? value.ip.split(',').map(s => s.trim()) : [];
|
||||
rule.port = value.port;
|
||||
rule.sourcePort = value.sourcePort;
|
||||
rule.network = value.network;
|
||||
rule.source = value.source.length>0 ? value.source.split(',') : [];
|
||||
rule.user = value.user.length>0 ? value.user.split(',') : [];
|
||||
rule.source = value.source.length>0 ? value.source.split(',').map(s => s.trim()) : [];
|
||||
rule.user = value.user.length>0 ? value.user.split(',').map(s => s.trim()) : [];
|
||||
rule.inboundTag = value.inboundTag;
|
||||
rule.protocol = value.protocol;
|
||||
rule.attrs = Object.fromEntries(value.attrs);
|
||||
|
||||
@@ -48,10 +48,10 @@ func InitLocalizer(i18nFS embed.FS, settingService SettingService) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func createTemplateData(params []string, seperator ...string) map[string]interface{} {
|
||||
func createTemplateData(params []string, separator ...string) map[string]interface{} {
|
||||
var sep string = "=="
|
||||
if len(seperator) > 0 {
|
||||
sep = seperator[0]
|
||||
if len(separator) > 0 {
|
||||
sep = separator[0]
|
||||
}
|
||||
|
||||
templateData := make(map[string]interface{})
|
||||
|
||||
@@ -359,7 +359,12 @@ func (s *SettingService) GetTimeLocation() (*time.Location, error) {
|
||||
if err != nil {
|
||||
defaultLocation := defaultValueMap["timeLocation"]
|
||||
logger.Errorf("location <%v> not exist, using default location: %v", l, defaultLocation)
|
||||
return time.LoadLocation(defaultLocation)
|
||||
location, err = time.LoadLocation(defaultLocation)
|
||||
if err != nil {
|
||||
logger.Errorf("failed to load default location, using UTC: %v", err)
|
||||
return time.UTC, nil
|
||||
}
|
||||
return location, nil
|
||||
}
|
||||
return location, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user