mirror of
https://github.com/alireza0/x-ui.git
synced 2026-03-13 21:13:09 +00:00
so-far updates
This commit is contained in:
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
github: alireza0 # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
patreon: # Replace with a single Patreon username
|
patreon: # Replace with a single Patreon username
|
||||||
open_collective: # Replace with a single Open Collective username
|
open_collective: # Replace with a single Open Collective username
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
@@ -10,5 +10,5 @@ liberapay: # Replace with a single Liberapay username
|
|||||||
issuehunt: # Replace with a single IssueHunt username
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||||
polar: # Replace with a single Polar username
|
polar: # Replace with a single Polar username
|
||||||
buy_me_a_coffee: alireza7
|
buy_me_a_coffee: # removed
|
||||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||||
|
|||||||
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@@ -7,7 +7,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|||||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
- armv5
|
- armv5
|
||||||
- 386
|
- 386
|
||||||
- s390x
|
- s390x
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -84,7 +84,7 @@ jobs:
|
|||||||
cd x-ui/bin
|
cd x-ui/bin
|
||||||
|
|
||||||
# Download dependencies
|
# Download dependencies
|
||||||
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v25.1.1/"
|
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v25.7.26/"
|
||||||
if [ "${{ matrix.platform }}" == "amd64" ]; then
|
if [ "${{ matrix.platform }}" == "amd64" ]; then
|
||||||
wget -q ${Xray_URL}Xray-linux-64.zip
|
wget -q ${Xray_URL}Xray-linux-64.zip
|
||||||
unzip Xray-linux-64.zip
|
unzip Xray-linux-64.zip
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ case $1 in
|
|||||||
esac
|
esac
|
||||||
mkdir -p build/bin
|
mkdir -p build/bin
|
||||||
cd build/bin
|
cd build/bin
|
||||||
wget -q "https://github.com/XTLS/Xray-core/releases/download/v25.1.1/Xray-linux-${ARCH}.zip"
|
wget -q "https://github.com/XTLS/Xray-core/releases/download/v25.7.26/Xray-linux-${ARCH}.zip"
|
||||||
unzip "Xray-linux-${ARCH}.zip"
|
unzip "Xray-linux-${ARCH}.zip"
|
||||||
rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat LICENSE README.md
|
rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat LICENSE README.md
|
||||||
mv xray "xray-linux-${FNAME}"
|
mv xray "xray-linux-${FNAME}"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.23-alpine AS builder
|
FROM golang:1.24-alpine AS builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
RUN apk --no-cache --update add build-base gcc wget unzip
|
RUN apk --no-cache --update add build-base gcc wget unzip
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ docker build -t x-ui .
|
|||||||
|
|
||||||
## Recommended OS
|
## Recommended OS
|
||||||
|
|
||||||
- Ubuntu 20.04+
|
- Ubuntu 22.04+
|
||||||
- Debian 11+
|
- Debian 11+
|
||||||
- CentOS 8+
|
- CentOS 8+
|
||||||
- OpenEuler 22.03+
|
- OpenEuler 22.03+
|
||||||
|
|||||||
24
install.sh
24
install.sh
@@ -60,8 +60,8 @@ elif [[ "${release}" == "centos" ]]; then
|
|||||||
echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1
|
echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "ubuntu" ]]; then
|
elif [[ "${release}" == "ubuntu" ]]; then
|
||||||
if [[ ${os_version} -lt 2004 ]]; then
|
if [[ ${os_version} -lt 2204 ]]; then
|
||||||
echo -e "${red} Please use Ubuntu 20 or higher version!${plain}\n" && exit 1
|
echo -e "${red} Please use Ubuntu 22 or higher version!${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "fedora" ]]; then
|
elif [[ "${release}" == "fedora" ]]; then
|
||||||
if [[ ${os_version} -lt 36 ]]; then
|
if [[ ${os_version} -lt 36 ]]; then
|
||||||
@@ -72,16 +72,16 @@ elif [[ "${release}" == "amzn" ]]; then
|
|||||||
echo -e "${red} Please use Amazon Linux 2023!${plain}\n" && exit 1
|
echo -e "${red} Please use Amazon Linux 2023!${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "debian" ]]; then
|
elif [[ "${release}" == "debian" ]]; then
|
||||||
if [[ ${os_version} -lt 11 ]]; then
|
if [[ ${os_version} -lt 12 ]]; then
|
||||||
echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1
|
echo -e "${red} Please use Debian 12 or higher ${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "almalinux" ]]; then
|
elif [[ "${release}" == "almalinux" ]]; then
|
||||||
if [[ ${os_version} -lt 80 ]]; then
|
if [[ ${os_version} -lt 95 ]]; then
|
||||||
echo -e "${red} Please use AlmaLinux 8.0 or higher ${plain}\n" && exit 1
|
echo -e "${red} Please use AlmaLinux 9.5 or higher ${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "rocky" ]]; then
|
elif [[ "${release}" == "rocky" ]]; then
|
||||||
if [[ ${os_version} -lt 8 ]]; then
|
if [[ ${os_version} -lt 95 ]]; then
|
||||||
echo -e "${red} Please use Rocky Linux 8 or higher ${plain}\n" && exit 1
|
echo -e "${red} Please use Rocky Linux 9.5 or higher ${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "ol" ]]; then
|
elif [[ "${release}" == "ol" ]]; then
|
||||||
if [[ ${os_version} -lt 8 ]]; then
|
if [[ ${os_version} -lt 8 ]]; then
|
||||||
@@ -90,8 +90,8 @@ elif [[ "${release}" == "ol" ]]; then
|
|||||||
else
|
else
|
||||||
echo -e "${red}Your operating system is not supported by this script.${plain}\n"
|
echo -e "${red}Your operating system is not supported by this script.${plain}\n"
|
||||||
echo "Please ensure you are using one of the following supported operating systems:"
|
echo "Please ensure you are using one of the following supported operating systems:"
|
||||||
echo "- Ubuntu 20.04+"
|
echo "- Ubuntu 22.04+"
|
||||||
echo "- Debian 11+"
|
echo "- Debian 12+"
|
||||||
echo "- CentOS 8+"
|
echo "- CentOS 8+"
|
||||||
echo "- OpenEuler 22.03+"
|
echo "- OpenEuler 22.03+"
|
||||||
echo "- Fedora 36+"
|
echo "- Fedora 36+"
|
||||||
@@ -99,8 +99,8 @@ else
|
|||||||
echo "- Parch Linux"
|
echo "- Parch Linux"
|
||||||
echo "- Manjaro"
|
echo "- Manjaro"
|
||||||
echo "- Armbian"
|
echo "- Armbian"
|
||||||
echo "- AlmaLinux 8.0+"
|
echo "- AlmaLinux 9.5+"
|
||||||
echo "- Rocky Linux 8+"
|
echo "- Rocky Linux 9.5+"
|
||||||
echo "- Oracle Linux 8+"
|
echo "- Oracle Linux 8+"
|
||||||
echo "- OpenSUSE Tumbleweed"
|
echo "- OpenSUSE Tumbleweed"
|
||||||
echo "- Amazon Linux 2023"
|
echo "- Amazon Linux 2023"
|
||||||
|
|||||||
@@ -263,6 +263,7 @@ func (s *SubJsonService) realityData(rData map[string]interface{}) map[string]in
|
|||||||
rltyData["show"] = false
|
rltyData["show"] = false
|
||||||
rltyData["publicKey"] = rltyClientSettings["publicKey"]
|
rltyData["publicKey"] = rltyClientSettings["publicKey"]
|
||||||
rltyData["fingerprint"] = rltyClientSettings["fingerprint"]
|
rltyData["fingerprint"] = rltyClientSettings["fingerprint"]
|
||||||
|
rltyData["mldsa65Verify"] = rltyClientSettings["mldsa65Verify"]
|
||||||
|
|
||||||
// Set random data
|
// Set random data
|
||||||
rltyData["spiderX"] = "/" + random.Seq(15)
|
rltyData["spiderX"] = "/" + random.Seq(15)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,7 @@ const UTLS_FINGERPRINT = {
|
|||||||
UTLS_QQ: "qq",
|
UTLS_QQ: "qq",
|
||||||
UTLS_RANDOM: "random",
|
UTLS_RANDOM: "random",
|
||||||
UTLS_RANDOMIZED: "randomized",
|
UTLS_RANDOMIZED: "randomized",
|
||||||
|
UTLS_RONDOMIZEDNOALPN: "randomizednoalpn",
|
||||||
UTLS_UNSAFE: "unsafe",
|
UTLS_UNSAFE: "unsafe",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -70,19 +71,41 @@ const WireguardDomainStrategy = [
|
|||||||
"ForceIPv6v4"
|
"ForceIPv6v4"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const USERS_SECURITY = {
|
||||||
|
AES_128_GCM: "aes-128-gcm",
|
||||||
|
CHACHA20_POLY1305: "chacha20-poly1305",
|
||||||
|
AUTO: "auto",
|
||||||
|
NONE: "none",
|
||||||
|
ZERO: "zero",
|
||||||
|
};
|
||||||
|
|
||||||
const MODE_OPTION = {
|
const MODE_OPTION = {
|
||||||
AUTO: "auto",
|
AUTO: "auto",
|
||||||
PACKET_UP: "packet-up",
|
PACKET_UP: "packet-up",
|
||||||
STREAM_UP: "stream-up",
|
STREAM_UP: "stream-up",
|
||||||
|
STREAM_ONE: "stream-one",
|
||||||
|
};
|
||||||
|
|
||||||
|
const Address_Port_Strategy = {
|
||||||
|
NONE: "none",
|
||||||
|
SrvPortOnly: "srvportonly",
|
||||||
|
SrvAddressOnly: "srvaddressonly",
|
||||||
|
SrvPortAndAddress: "srvportandaddress",
|
||||||
|
TxtPortOnly: "txtportonly",
|
||||||
|
TxtAddressOnly: "txtaddressonly",
|
||||||
|
TxtPortAndAddress: "txtportandaddress"
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.freeze(Protocols);
|
Object.freeze(Protocols);
|
||||||
Object.freeze(SSMethods);
|
Object.freeze(SSMethods);
|
||||||
Object.freeze(TLS_FLOW_CONTROL);
|
Object.freeze(TLS_FLOW_CONTROL);
|
||||||
|
Object.freeze(UTLS_FINGERPRINT);
|
||||||
Object.freeze(ALPN_OPTION);
|
Object.freeze(ALPN_OPTION);
|
||||||
Object.freeze(OutboundDomainStrategies);
|
Object.freeze(OutboundDomainStrategies);
|
||||||
Object.freeze(WireguardDomainStrategy);
|
Object.freeze(WireguardDomainStrategy);
|
||||||
|
Object.freeze(USERS_SECURITY);
|
||||||
Object.freeze(MODE_OPTION);
|
Object.freeze(MODE_OPTION);
|
||||||
|
Object.freeze(Address_Port_Strategy);
|
||||||
|
|
||||||
class CommonClass {
|
class CommonClass {
|
||||||
|
|
||||||
@@ -98,30 +121,30 @@ class CommonClass {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(format=true) {
|
toString(format = true) {
|
||||||
return format ? JSON.stringify(this.toJson(), null, 2) : JSON.stringify(this.toJson());
|
return format ? JSON.stringify(this.toJson(), null, 2) : JSON.stringify(this.toJson());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TcpStreamSettings extends CommonClass {
|
class TcpStreamSettings extends CommonClass {
|
||||||
constructor(type='none', host, path) {
|
constructor(type = 'none', host, path) {
|
||||||
super();
|
super();
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
let header = json.header;
|
let header = json.header;
|
||||||
if (!header) return new TcpStreamSettings();
|
if (!header) return new TcpStreamSettings();
|
||||||
if(header.type == 'http' && header.request){
|
if (header.type == 'http' && header.request) {
|
||||||
return new TcpStreamSettings(
|
return new TcpStreamSettings(
|
||||||
header.type,
|
header.type,
|
||||||
header.request.headers.Host.join(','),
|
header.request.headers.Host.join(','),
|
||||||
header.request.path.join(','),
|
header.request.path.join(','),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return new TcpStreamSettings(header.type,'','');
|
return new TcpStreamSettings(header.type, '', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
toJson() {
|
toJson() {
|
||||||
@@ -140,15 +163,17 @@ class TcpStreamSettings extends CommonClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class KcpStreamSettings extends CommonClass {
|
class KcpStreamSettings extends CommonClass {
|
||||||
constructor(mtu=1350, tti=20,
|
constructor(
|
||||||
uplinkCapacity=5,
|
mtu = 1350,
|
||||||
downlinkCapacity=20,
|
tti = 50,
|
||||||
congestion=false,
|
uplinkCapacity = 5,
|
||||||
readBufferSize=2,
|
downlinkCapacity = 20,
|
||||||
writeBufferSize=2,
|
congestion = false,
|
||||||
type='none',
|
readBufferSize = 2,
|
||||||
seed='',
|
writeBufferSize = 2,
|
||||||
) {
|
type = 'none',
|
||||||
|
seed = '',
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.mtu = mtu;
|
this.mtu = mtu;
|
||||||
this.tti = tti;
|
this.tti = tti;
|
||||||
@@ -161,7 +186,7 @@ class KcpStreamSettings extends CommonClass {
|
|||||||
this.seed = seed;
|
this.seed = seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
return new KcpStreamSettings(
|
return new KcpStreamSettings(
|
||||||
json.mtu,
|
json.mtu,
|
||||||
json.tti,
|
json.tti,
|
||||||
@@ -193,16 +218,23 @@ class KcpStreamSettings extends CommonClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class WsStreamSettings extends CommonClass {
|
class WsStreamSettings extends CommonClass {
|
||||||
constructor(path='/', host='') {
|
constructor(
|
||||||
|
path = '/',
|
||||||
|
host = '',
|
||||||
|
heartbeatPeriod = 0,
|
||||||
|
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
|
this.heartbeatPeriod = heartbeatPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
return new WsStreamSettings(
|
return new WsStreamSettings(
|
||||||
json.path,
|
json.path,
|
||||||
json.host,
|
json.host,
|
||||||
|
json.heartbeatPeriod,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,19 +242,24 @@ class WsStreamSettings extends CommonClass {
|
|||||||
return {
|
return {
|
||||||
path: this.path,
|
path: this.path,
|
||||||
host: this.host,
|
host: this.host,
|
||||||
|
heartbeatPeriod: this.heartbeatPeriod
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GrpcStreamSettings extends CommonClass {
|
class GrpcStreamSettings extends CommonClass {
|
||||||
constructor(serviceName="", authority="", multiMode=false) {
|
constructor(
|
||||||
|
serviceName = "",
|
||||||
|
authority = "",
|
||||||
|
multiMode = false
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.serviceName = serviceName;
|
this.serviceName = serviceName;
|
||||||
this.authority = authority;
|
this.authority = authority;
|
||||||
this.multiMode = multiMode;
|
this.multiMode = multiMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
return new GrpcStreamSettings(json.serviceName, json.authority, json.multiMode);
|
return new GrpcStreamSettings(json.serviceName, json.authority, json.multiMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,19 +267,19 @@ class GrpcStreamSettings extends CommonClass {
|
|||||||
return {
|
return {
|
||||||
serviceName: this.serviceName,
|
serviceName: this.serviceName,
|
||||||
authority: this.authority,
|
authority: this.authority,
|
||||||
multiMode: this.multiMode,
|
multiMode: this.multiMode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HttpUpgradeStreamSettings extends CommonClass {
|
class HttpUpgradeStreamSettings extends CommonClass {
|
||||||
constructor(path='/', host='') {
|
constructor(path = '/', host = '') {
|
||||||
super();
|
super();
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
return new HttpUpgradeStreamSettings(
|
return new HttpUpgradeStreamSettings(
|
||||||
json.path,
|
json.path,
|
||||||
json.host,
|
json.host,
|
||||||
@@ -313,10 +350,12 @@ class xHTTPStreamSettings extends CommonClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TlsStreamSettings extends CommonClass {
|
class TlsStreamSettings extends CommonClass {
|
||||||
constructor(serverName='',
|
constructor(
|
||||||
alpn=[],
|
serverName = '',
|
||||||
fingerprint = '',
|
alpn = [],
|
||||||
allowInsecure = false) {
|
fingerprint = '',
|
||||||
|
allowInsecure = false
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.serverName = serverName;
|
this.serverName = serverName;
|
||||||
this.alpn = alpn;
|
this.alpn = alpn;
|
||||||
@@ -324,7 +363,7 @@ class TlsStreamSettings extends CommonClass {
|
|||||||
this.allowInsecure = allowInsecure;
|
this.allowInsecure = allowInsecure;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
return new TlsStreamSettings(
|
return new TlsStreamSettings(
|
||||||
json.serverName,
|
json.serverName,
|
||||||
json.alpn,
|
json.alpn,
|
||||||
@@ -344,7 +383,13 @@ class TlsStreamSettings extends CommonClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class RealityStreamSettings extends CommonClass {
|
class RealityStreamSettings extends CommonClass {
|
||||||
constructor(publicKey = '', fingerprint = '', serverName = '', shortId = '', spiderX = '/') {
|
constructor(
|
||||||
|
publicKey = '',
|
||||||
|
fingerprint = '',
|
||||||
|
serverName = '',
|
||||||
|
shortId = '',
|
||||||
|
spiderX = '/'
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.publicKey = publicKey;
|
this.publicKey = publicKey;
|
||||||
this.fingerprint = fingerprint;
|
this.fingerprint = fingerprint;
|
||||||
@@ -371,14 +416,22 @@ class RealityStreamSettings extends CommonClass {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SockoptStreamSettings extends CommonClass {
|
class SockoptStreamSettings extends CommonClass {
|
||||||
constructor(dialerProxy = "", tcpFastOpen = false, tcpKeepAliveInterval = 0, penetrate = false) {
|
constructor(
|
||||||
|
dialerProxy = "",
|
||||||
|
tcpFastOpen = false,
|
||||||
|
tcpKeepAliveInterval = 0,
|
||||||
|
tcpMptcp = false,
|
||||||
|
penetrate = false,
|
||||||
|
addressPortStrategy = Address_Port_Strategy.NONE,
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.dialerProxy = dialerProxy;
|
this.dialerProxy = dialerProxy;
|
||||||
this.tcpFastOpen = tcpFastOpen;
|
this.tcpFastOpen = tcpFastOpen;
|
||||||
this.tcpKeepAliveInterval = tcpKeepAliveInterval;
|
this.tcpKeepAliveInterval = tcpKeepAliveInterval;
|
||||||
|
this.tcpMptcp = tcpMptcp;
|
||||||
this.penetrate = penetrate;
|
this.penetrate = penetrate;
|
||||||
|
this.addressPortStrategy = addressPortStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json = {}) {
|
static fromJson(json = {}) {
|
||||||
@@ -387,7 +440,9 @@ class SockoptStreamSettings extends CommonClass {
|
|||||||
json.dialerProxy,
|
json.dialerProxy,
|
||||||
json.tcpFastOpen,
|
json.tcpFastOpen,
|
||||||
json.tcpKeepAliveInterval,
|
json.tcpKeepAliveInterval,
|
||||||
|
json.tcpMptcp,
|
||||||
json.penetrate,
|
json.penetrate,
|
||||||
|
json.addressPortStrategy
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,24 +451,27 @@ class SockoptStreamSettings extends CommonClass {
|
|||||||
dialerProxy: this.dialerProxy,
|
dialerProxy: this.dialerProxy,
|
||||||
tcpFastOpen: this.tcpFastOpen,
|
tcpFastOpen: this.tcpFastOpen,
|
||||||
tcpKeepAliveInterval: this.tcpKeepAliveInterval,
|
tcpKeepAliveInterval: this.tcpKeepAliveInterval,
|
||||||
|
tcpMptcp: this.tcpMptcp,
|
||||||
penetrate: this.penetrate,
|
penetrate: this.penetrate,
|
||||||
|
addressPortStrategy: this.addressPortStrategy
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StreamSettings extends CommonClass {
|
class StreamSettings extends CommonClass {
|
||||||
constructor(network='tcp',
|
constructor(
|
||||||
security='none',
|
network = 'tcp',
|
||||||
tlsSettings=new TlsStreamSettings(),
|
security = 'none',
|
||||||
realitySettings = new RealityStreamSettings(),
|
tlsSettings = new TlsStreamSettings(),
|
||||||
tcpSettings=new TcpStreamSettings(),
|
realitySettings = new RealityStreamSettings(),
|
||||||
kcpSettings=new KcpStreamSettings(),
|
tcpSettings = new TcpStreamSettings(),
|
||||||
wsSettings=new WsStreamSettings(),
|
kcpSettings = new KcpStreamSettings(),
|
||||||
grpcSettings=new GrpcStreamSettings(),
|
wsSettings = new WsStreamSettings(),
|
||||||
httpupgradeSettings=new HttpUpgradeStreamSettings(),
|
grpcSettings = new GrpcStreamSettings(),
|
||||||
xhttpSettings=new xHTTPStreamSettings(),
|
httpupgradeSettings = new HttpUpgradeStreamSettings(),
|
||||||
sockopt = undefined,
|
xhttpSettings = new xHTTPStreamSettings(),
|
||||||
) {
|
sockopt = undefined,
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.network = network;
|
this.network = network;
|
||||||
this.security = security;
|
this.security = security;
|
||||||
@@ -427,7 +485,7 @@ class StreamSettings extends CommonClass {
|
|||||||
this.xhttp = xhttpSettings;
|
this.xhttp = xhttpSettings;
|
||||||
this.sockopt = sockopt;
|
this.sockopt = sockopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isTls() {
|
get isTls() {
|
||||||
return this.security === 'tls';
|
return this.security === 'tls';
|
||||||
}
|
}
|
||||||
@@ -444,7 +502,7 @@ class StreamSettings extends CommonClass {
|
|||||||
this.sockopt = value ? new SockoptStreamSettings() : undefined;
|
this.sockopt = value ? new SockoptStreamSettings() : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
return new StreamSettings(
|
return new StreamSettings(
|
||||||
json.network,
|
json.network,
|
||||||
json.security,
|
json.security,
|
||||||
@@ -509,9 +567,9 @@ class Mux extends CommonClass {
|
|||||||
|
|
||||||
class Outbound extends CommonClass {
|
class Outbound extends CommonClass {
|
||||||
constructor(
|
constructor(
|
||||||
tag='',
|
tag = '',
|
||||||
protocol=Protocols.VMess,
|
protocol = Protocols.VLESS,
|
||||||
settings=null,
|
settings = null,
|
||||||
streamSettings = new StreamSettings(),
|
streamSettings = new StreamSettings(),
|
||||||
sendThrough,
|
sendThrough,
|
||||||
mux = new Mux(),
|
mux = new Mux(),
|
||||||
@@ -558,11 +616,27 @@ class Outbound extends CommonClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canEnableMux() {
|
canEnableMux() {
|
||||||
if (this.settings.flow && this.settings.flow != ''){
|
// Disable Mux if flow is set
|
||||||
|
if (this.settings.flow && this.settings.flow !== '') {
|
||||||
this.mux.enabled = false;
|
this.mux.enabled = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return [Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks, Protocols.HTTP, Protocols.Socks].includes(this.protocol);
|
|
||||||
|
// Disable Mux if network is xhttp
|
||||||
|
if (this.stream.network === 'xhttp') {
|
||||||
|
this.mux.enabled = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow Mux only for these protocols
|
||||||
|
return [
|
||||||
|
Protocols.VMess,
|
||||||
|
Protocols.VLESS,
|
||||||
|
Protocols.Trojan,
|
||||||
|
Protocols.Shadowsocks,
|
||||||
|
Protocols.HTTP,
|
||||||
|
Protocols.Socks
|
||||||
|
].includes(this.protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
hasVnext() {
|
hasVnext() {
|
||||||
@@ -589,7 +663,7 @@ class Outbound extends CommonClass {
|
|||||||
return [Protocols.Socks, Protocols.HTTP].includes(this.protocol);
|
return [Protocols.Socks, Protocols.HTTP].includes(this.protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
return new Outbound(
|
return new Outbound(
|
||||||
json.tag,
|
json.tag,
|
||||||
json.protocol,
|
json.protocol,
|
||||||
@@ -620,8 +694,8 @@ class Outbound extends CommonClass {
|
|||||||
|
|
||||||
static fromLink(link) {
|
static fromLink(link) {
|
||||||
data = link.split('://');
|
data = link.split('://');
|
||||||
if(data.length !=2) return null;
|
if (data.length != 2) return null;
|
||||||
switch(data[0].toLowerCase()){
|
switch (data[0].toLowerCase()) {
|
||||||
case Protocols.VMess:
|
case Protocols.VMess:
|
||||||
return this.fromVmessLink(JSON.parse(Base64.decode(data[1])));
|
return this.fromVmessLink(JSON.parse(Base64.decode(data[1])));
|
||||||
case Protocols.VLESS:
|
case Protocols.VLESS:
|
||||||
@@ -633,7 +707,7 @@ class Outbound extends CommonClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromVmessLink(json={}){
|
static fromVmessLink(json = {}) {
|
||||||
let stream = new StreamSettings(json.net, json.tls);
|
let stream = new StreamSettings(json.net, json.tls);
|
||||||
|
|
||||||
let network = json.net;
|
let network = json.net;
|
||||||
@@ -647,16 +721,16 @@ class Outbound extends CommonClass {
|
|||||||
stream.type = json.type;
|
stream.type = json.type;
|
||||||
stream.seed = json.path;
|
stream.seed = json.path;
|
||||||
} else if (network === 'ws') {
|
} else if (network === 'ws') {
|
||||||
stream.ws = new WsStreamSettings(json.path,json.host);
|
stream.ws = new WsStreamSettings(json.path, json.host);
|
||||||
} else if (network === 'grpc') {
|
} else if (network === 'grpc') {
|
||||||
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 === 'xhttp') {
|
} else if (network === 'xhttp') {
|
||||||
stream.xhttp = new xHTTPStreamSettings(json.path,json.host,json.mode);
|
stream.xhttp = new xHTTPStreamSettings(json.path, json.host, json.mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(json.tls && json.tls == 'tls'){
|
if (json.tls && json.tls == 'tls') {
|
||||||
stream.tls = new TlsStreamSettings(
|
stream.tls = new TlsStreamSettings(
|
||||||
json.sni,
|
json.sni,
|
||||||
json.alpn ? json.alpn.split(',') : [],
|
json.alpn ? json.alpn.split(',') : [],
|
||||||
@@ -666,10 +740,10 @@ class Outbound extends CommonClass {
|
|||||||
|
|
||||||
const port = json.port * 1;
|
const port = json.port * 1;
|
||||||
|
|
||||||
return new Outbound(json.ps, Protocols.VMess, new Outbound.VmessSettings(json.add, port, json.id), stream);
|
return new Outbound(json.ps, Protocols.VMess, new Outbound.VmessSettings(json.add, port, json.id, json.scy), stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromParamLink(link){
|
static fromParamLink(link) {
|
||||||
const url = new URL(link);
|
const url = new URL(link);
|
||||||
let type = url.searchParams.get('type') ?? 'tcp';
|
let type = url.searchParams.get('type') ?? 'tcp';
|
||||||
let security = url.searchParams.get('security') ?? 'none';
|
let security = url.searchParams.get('security') ?? 'none';
|
||||||
@@ -687,32 +761,32 @@ class Outbound extends CommonClass {
|
|||||||
stream.kcp.type = headerType ?? 'none';
|
stream.kcp.type = headerType ?? 'none';
|
||||||
stream.kcp.seed = path;
|
stream.kcp.seed = path;
|
||||||
} else if (type === 'ws') {
|
} else if (type === 'ws') {
|
||||||
stream.ws = new WsStreamSettings(path,host);
|
stream.ws = new WsStreamSettings(path, host);
|
||||||
} else if (type === 'grpc') {
|
} else if (type === 'grpc') {
|
||||||
stream.grpc = new GrpcStreamSettings(
|
stream.grpc = new GrpcStreamSettings(
|
||||||
url.searchParams.get('serviceName') ?? '',
|
url.searchParams.get('serviceName') ?? '',
|
||||||
url.searchParams.get('authority') ?? '',
|
url.searchParams.get('authority') ?? '',
|
||||||
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 === 'xhttp') {
|
} else if (type === 'xhttp') {
|
||||||
stream.xhttp = new xHTTPStreamSettings(path,host,mode);
|
stream.xhttp = new xHTTPStreamSettings(path, host, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(security == 'tls'){
|
if (security == 'tls') {
|
||||||
let fp=url.searchParams.get('fp') ?? 'none';
|
let fp = url.searchParams.get('fp') ?? 'none';
|
||||||
let alpn=url.searchParams.get('alpn');
|
let alpn = url.searchParams.get('alpn');
|
||||||
let allowInsecure=url.searchParams.get('allowInsecure');
|
let allowInsecure = url.searchParams.get('allowInsecure');
|
||||||
let sni=url.searchParams.get('sni') ?? '';
|
let sni = url.searchParams.get('sni') ?? '';
|
||||||
stream.tls = new TlsStreamSettings(sni, alpn ? alpn.split(',') : [], fp, allowInsecure == 1);
|
stream.tls = new TlsStreamSettings(sni, alpn ? alpn.split(',') : [], fp, allowInsecure == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(security == 'reality'){
|
if (security == 'reality') {
|
||||||
let pbk=url.searchParams.get('pbk');
|
let pbk = url.searchParams.get('pbk');
|
||||||
let fp=url.searchParams.get('fp');
|
let fp = url.searchParams.get('fp');
|
||||||
let sni=url.searchParams.get('sni') ?? '';
|
let sni = url.searchParams.get('sni') ?? '';
|
||||||
let sid=url.searchParams.get('sid') ?? '';
|
let sid = url.searchParams.get('sid') ?? '';
|
||||||
let spx=url.searchParams.get('spx') ?? '';
|
let spx = url.searchParams.get('spx') ?? '';
|
||||||
stream.reality = new RealityStreamSettings(pbk, fp, sni, sid, spx);
|
stream.reality = new RealityStreamSettings(pbk, fp, sni, sid, spx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -720,14 +794,14 @@ class Outbound extends CommonClass {
|
|||||||
const match = link.match(regex);
|
const match = link.match(regex);
|
||||||
|
|
||||||
if (!match) return null;
|
if (!match) return null;
|
||||||
let [, protocol, userData, address, port, ] = match;
|
let [, protocol, userData, address, port,] = match;
|
||||||
port *= 1;
|
port *= 1;
|
||||||
if(protocol == 'ss') {
|
if (protocol == 'ss') {
|
||||||
protocol = 'shadowsocks';
|
protocol = 'shadowsocks';
|
||||||
userData = atob(userData).split(':');
|
userData = atob(userData).split(':');
|
||||||
}
|
}
|
||||||
var settings;
|
var settings;
|
||||||
switch(protocol){
|
switch (protocol) {
|
||||||
case Protocols.VLESS:
|
case Protocols.VLESS:
|
||||||
settings = new Outbound.VLESSSettings(address, port, userData, url.searchParams.get('flow') ?? '');
|
settings = new Outbound.VLESSSettings(address, port, userData, url.searchParams.get('flow') ?? '');
|
||||||
break;
|
break;
|
||||||
@@ -735,7 +809,7 @@ class Outbound extends CommonClass {
|
|||||||
settings = new Outbound.TrojanSettings(address, port, userData);
|
settings = new Outbound.TrojanSettings(address, port, userData);
|
||||||
break;
|
break;
|
||||||
case Protocols.Shadowsocks:
|
case Protocols.Shadowsocks:
|
||||||
let method = userData.splice(0,1)[0];
|
let method = userData.splice(0, 1)[0];
|
||||||
settings = new Outbound.ShadowsocksSettings(address, port, userData.join(":"), method, true);
|
settings = new Outbound.ShadowsocksSettings(address, port, userData.join(":"), method, true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -832,14 +906,18 @@ Outbound.FreedomSettings = class extends CommonClass {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Outbound.FreedomSettings.Fragment = class extends CommonClass {
|
Outbound.FreedomSettings.Fragment = class extends CommonClass {
|
||||||
constructor(packets='1-3',length='',interval=''){
|
constructor(
|
||||||
|
packets = '1-3',
|
||||||
|
length = '',
|
||||||
|
interval = ''
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.packets = packets;
|
this.packets = packets;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
this.interval = interval;
|
this.interval = interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
return new Outbound.FreedomSettings.Fragment(
|
return new Outbound.FreedomSettings.Fragment(
|
||||||
json.packets,
|
json.packets,
|
||||||
json.length,
|
json.length,
|
||||||
@@ -883,7 +961,7 @@ Outbound.BlackholeSettings = class extends CommonClass {
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
return new Outbound.BlackholeSettings(
|
return new Outbound.BlackholeSettings(
|
||||||
json.response ? json.response.type : undefined,
|
json.response ? json.response.type : undefined,
|
||||||
);
|
);
|
||||||
@@ -891,14 +969,14 @@ Outbound.BlackholeSettings = class extends CommonClass {
|
|||||||
|
|
||||||
toJson() {
|
toJson() {
|
||||||
return {
|
return {
|
||||||
response: ObjectUtil.isEmpty(this.type) ? undefined : {type: this.type},
|
response: ObjectUtil.isEmpty(this.type) ? undefined : { type: this.type },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Outbound.DNSSettings = class extends CommonClass {
|
Outbound.DNSSettings = class extends CommonClass {
|
||||||
constructor(
|
constructor(
|
||||||
network = 'udp',
|
network = 'udp',
|
||||||
address = '1.1.1.1',
|
address = '',
|
||||||
port = 53,
|
port = 53,
|
||||||
nonIPQuery = 'drop',
|
nonIPQuery = 'drop',
|
||||||
blockTypes = []
|
blockTypes = []
|
||||||
@@ -922,19 +1000,21 @@ Outbound.DNSSettings = class extends CommonClass {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
Outbound.VmessSettings = class extends CommonClass {
|
Outbound.VmessSettings = class extends CommonClass {
|
||||||
constructor(address, port, id) {
|
constructor(address, port, id, security) {
|
||||||
super();
|
super();
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.security = security;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
if(ObjectUtil.isArrEmpty(json.vnext)) return new Outbound.VmessSettings();
|
if (ObjectUtil.isArrEmpty(json.vnext)) return new Outbound.VmessSettings();
|
||||||
return new Outbound.VmessSettings(
|
return new Outbound.VmessSettings(
|
||||||
json.vnext[0].address,
|
json.vnext[0].address,
|
||||||
json.vnext[0].port,
|
json.vnext[0].port,
|
||||||
json.vnext[0].users[0].id,
|
json.vnext[0].users[0].id,
|
||||||
|
json.vnext[0].users[0].security,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -943,13 +1023,13 @@ Outbound.VmessSettings = class extends CommonClass {
|
|||||||
vnext: [{
|
vnext: [{
|
||||||
address: this.address,
|
address: this.address,
|
||||||
port: this.port,
|
port: this.port,
|
||||||
users: [{id: this.id}],
|
users: [{ id: this.id, security: this.security }],
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Outbound.VLESSSettings = class extends CommonClass {
|
Outbound.VLESSSettings = class extends CommonClass {
|
||||||
constructor(address, port, id, flow, encryption='none') {
|
constructor(address, port, id, flow, encryption = 'none') {
|
||||||
super();
|
super();
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
@@ -958,8 +1038,8 @@ Outbound.VLESSSettings = class extends CommonClass {
|
|||||||
this.encryption = encryption
|
this.encryption = encryption
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
if(ObjectUtil.isArrEmpty(json.vnext)) return new Outbound.VLESSSettings();
|
if (ObjectUtil.isArrEmpty(json.vnext)) return new Outbound.VLESSSettings();
|
||||||
return new Outbound.VLESSSettings(
|
return new Outbound.VLESSSettings(
|
||||||
json.vnext[0].address,
|
json.vnext[0].address,
|
||||||
json.vnext[0].port,
|
json.vnext[0].port,
|
||||||
@@ -974,7 +1054,7 @@ Outbound.VLESSSettings = class extends CommonClass {
|
|||||||
vnext: [{
|
vnext: [{
|
||||||
address: this.address,
|
address: this.address,
|
||||||
port: this.port,
|
port: this.port,
|
||||||
users: [{id: this.id, flow: this.flow, encryption: 'none',}],
|
users: [{ id: this.id, flow: this.flow, encryption: 'none', }],
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -987,8 +1067,8 @@ Outbound.TrojanSettings = class extends CommonClass {
|
|||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
if(ObjectUtil.isArrEmpty(json.servers)) return new Outbound.TrojanSettings();
|
if (ObjectUtil.isArrEmpty(json.servers)) return new Outbound.TrojanSettings();
|
||||||
return new Outbound.TrojanSettings(
|
return new Outbound.TrojanSettings(
|
||||||
json.servers[0].address,
|
json.servers[0].address,
|
||||||
json.servers[0].port,
|
json.servers[0].port,
|
||||||
@@ -1007,24 +1087,26 @@ 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 = {}) {
|
||||||
let servers = json.servers;
|
let servers = json.servers;
|
||||||
if(ObjectUtil.isArrEmpty(servers)) servers=[{}];
|
if (ObjectUtil.isArrEmpty(servers)) servers = [{}];
|
||||||
return new Outbound.ShadowsocksSettings(
|
return new Outbound.ShadowsocksSettings(
|
||||||
servers[0].address,
|
servers[0].address,
|
||||||
servers[0].port,
|
servers[0].port,
|
||||||
servers[0].password,
|
servers[0].password,
|
||||||
servers[0].method,
|
servers[0].method,
|
||||||
servers[0].uot,
|
servers[0].uot,
|
||||||
|
servers[0].UoTVersion,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1036,10 +1118,12 @@ 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,
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Outbound.SocksSettings = class extends CommonClass {
|
Outbound.SocksSettings = class extends CommonClass {
|
||||||
constructor(address, port, user, pass) {
|
constructor(address, port, user, pass) {
|
||||||
super();
|
super();
|
||||||
@@ -1049,9 +1133,9 @@ Outbound.SocksSettings = class extends CommonClass {
|
|||||||
this.pass = pass;
|
this.pass = pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
let servers = json.servers;
|
let servers = json.servers;
|
||||||
if(ObjectUtil.isArrEmpty(servers)) servers=[{users: [{}]}];
|
if (ObjectUtil.isArrEmpty(servers)) servers = [{ users: [{}] }];
|
||||||
return new Outbound.SocksSettings(
|
return new Outbound.SocksSettings(
|
||||||
servers[0].address,
|
servers[0].address,
|
||||||
servers[0].port,
|
servers[0].port,
|
||||||
@@ -1065,7 +1149,7 @@ Outbound.SocksSettings = class extends CommonClass {
|
|||||||
servers: [{
|
servers: [{
|
||||||
address: this.address,
|
address: this.address,
|
||||||
port: this.port,
|
port: this.port,
|
||||||
users: ObjectUtil.isEmpty(this.user) ? [] : [{user: this.user, pass: this.pass}],
|
users: ObjectUtil.isEmpty(this.user) ? [] : [{ user: this.user, pass: this.pass }],
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1079,9 +1163,9 @@ Outbound.HttpSettings = class extends CommonClass {
|
|||||||
this.pass = pass;
|
this.pass = pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json = {}) {
|
||||||
let servers = json.servers;
|
let servers = json.servers;
|
||||||
if(ObjectUtil.isArrEmpty(servers)) servers=[{users: [{}]}];
|
if (ObjectUtil.isArrEmpty(servers)) servers = [{ users: [{}] }];
|
||||||
return new Outbound.HttpSettings(
|
return new Outbound.HttpSettings(
|
||||||
servers[0].address,
|
servers[0].address,
|
||||||
servers[0].port,
|
servers[0].port,
|
||||||
@@ -1095,16 +1179,23 @@ Outbound.HttpSettings = class extends CommonClass {
|
|||||||
servers: [{
|
servers: [{
|
||||||
address: this.address,
|
address: this.address,
|
||||||
port: this.port,
|
port: this.port,
|
||||||
users: ObjectUtil.isEmpty(this.user) ? [] : [{user: this.user, pass: this.pass}],
|
users: ObjectUtil.isEmpty(this.user) ? [] : [{ user: this.user, pass: this.pass }],
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Outbound.WireguardSettings = class extends CommonClass {
|
Outbound.WireguardSettings = class extends CommonClass {
|
||||||
constructor(
|
constructor(
|
||||||
mtu=1420, secretKey='',
|
mtu = 1420,
|
||||||
address='', workers=2, domainStrategy='', reserved='',
|
secretKey = '',
|
||||||
peers=[new Outbound.WireguardSettings.Peer()], kernelMode=false) {
|
address = [''],
|
||||||
|
workers = 2,
|
||||||
|
domainStrategy = '',
|
||||||
|
reserved = '',
|
||||||
|
peers = [new Outbound.WireguardSettings.Peer()],
|
||||||
|
kernelMode = false,
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.mtu = mtu;
|
this.mtu = mtu;
|
||||||
this.secretKey = secretKey;
|
this.secretKey = secretKey;
|
||||||
@@ -1125,7 +1216,7 @@ Outbound.WireguardSettings = class extends CommonClass {
|
|||||||
this.peers.splice(index, 1);
|
this.peers.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}){
|
static fromJson(json = {}) {
|
||||||
return new Outbound.WireguardSettings(
|
return new Outbound.WireguardSettings(
|
||||||
json.mtu,
|
json.mtu,
|
||||||
json.secretKey,
|
json.secretKey,
|
||||||
@@ -1140,10 +1231,10 @@ Outbound.WireguardSettings = class extends CommonClass {
|
|||||||
|
|
||||||
toJson() {
|
toJson() {
|
||||||
return {
|
return {
|
||||||
mtu: this.mtu?? undefined,
|
mtu: this.mtu ?? undefined,
|
||||||
secretKey: this.secretKey,
|
secretKey: this.secretKey,
|
||||||
address: this.address ? this.address.split(",") : [],
|
address: this.address ? this.address.split(",") : [],
|
||||||
workers: this.workers?? undefined,
|
workers: this.workers ?? undefined,
|
||||||
domainStrategy: WireguardDomainStrategy.includes(this.domainStrategy) ? this.domainStrategy : undefined,
|
domainStrategy: WireguardDomainStrategy.includes(this.domainStrategy) ? this.domainStrategy : undefined,
|
||||||
reserved: this.reserved ? this.reserved.split(",").map(Number) : undefined,
|
reserved: this.reserved ? this.reserved.split(",").map(Number) : undefined,
|
||||||
peers: Outbound.WireguardSettings.Peer.toJsonArray(this.peers),
|
peers: Outbound.WireguardSettings.Peer.toJsonArray(this.peers),
|
||||||
@@ -1151,8 +1242,15 @@ Outbound.WireguardSettings = class extends CommonClass {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Outbound.WireguardSettings.Peer = class extends CommonClass {
|
Outbound.WireguardSettings.Peer = class extends CommonClass {
|
||||||
constructor(publicKey='', psk='', allowedIPs=['0.0.0.0/0','::/0'], endpoint='', keepAlive=0) {
|
constructor(
|
||||||
|
publicKey = '',
|
||||||
|
psk = '',
|
||||||
|
allowedIPs = ['0.0.0.0/0', '::/0'],
|
||||||
|
endpoint = '',
|
||||||
|
keepAlive = 0
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.publicKey = publicKey;
|
this.publicKey = publicKey;
|
||||||
this.psk = psk;
|
this.psk = psk;
|
||||||
@@ -1161,7 +1259,7 @@ Outbound.WireguardSettings.Peer = class extends CommonClass {
|
|||||||
this.keepAlive = keepAlive;
|
this.keepAlive = keepAlive;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}){
|
static fromJson(json = {}) {
|
||||||
return new Outbound.WireguardSettings.Peer(
|
return new Outbound.WireguardSettings.Peer(
|
||||||
json.publicKey,
|
json.publicKey,
|
||||||
json.preSharedKey,
|
json.preSharedKey,
|
||||||
@@ -1174,10 +1272,10 @@ Outbound.WireguardSettings.Peer = class extends CommonClass {
|
|||||||
toJson() {
|
toJson() {
|
||||||
return {
|
return {
|
||||||
publicKey: this.publicKey,
|
publicKey: this.publicKey,
|
||||||
preSharedKey: this.psk.length>0 ? this.psk : undefined,
|
preSharedKey: this.psk.length > 0 ? this.psk : undefined,
|
||||||
allowedIPs: this.allowedIPs ? this.allowedIPs : undefined,
|
allowedIPs: this.allowedIPs ? this.allowedIPs : undefined,
|
||||||
endpoint: this.endpoint,
|
endpoint: this.endpoint,
|
||||||
keepAlive: this.keepAlive?? undefined,
|
keepAlive: this.keepAlive ?? undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -49,6 +49,7 @@ func (a *ServerController) initRouter(g *gin.RouterGroup) {
|
|||||||
g.GET("/getDb", a.getDb)
|
g.GET("/getDb", a.getDb)
|
||||||
g.POST("/importDB", a.importDB)
|
g.POST("/importDB", a.importDB)
|
||||||
g.POST("/getNewX25519Cert", a.getNewX25519Cert)
|
g.POST("/getNewX25519Cert", a.getNewX25519Cert)
|
||||||
|
g.POST("/getNewmldsa65", a.getNewmldsa65)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ServerController) refreshStatus() {
|
func (a *ServerController) refreshStatus() {
|
||||||
@@ -186,3 +187,12 @@ func (a *ServerController) getNewX25519Cert(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
jsonObj(c, cert, nil)
|
jsonObj(c, cert, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *ServerController) getNewmldsa65(c *gin.Context) {
|
||||||
|
cert, err := a.serverService.GetNewmldsa65()
|
||||||
|
if err != nil {
|
||||||
|
jsonMsg(c, "get mldsa65 certificate", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
jsonObj(c, cert, nil)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="renderer" content="webkit">
|
<meta name="renderer" content="webkit">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta name="robots" content="noindex,nofollow">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="stylesheet" href="{{ .base_path }}assets/ant-design-vue@1.7.8/antd.min.css">
|
<link rel="stylesheet" href="{{ .base_path }}assets/ant-design-vue@1.7.8/antd.min.css">
|
||||||
<link rel="stylesheet" href="{{ .base_path }}assets/element-ui@2.15.0/theme-chalk/display.css">
|
<link rel="stylesheet" href="{{ .base_path }}assets/element-ui@2.15.0/theme-chalk/display.css">
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
</a-divider>
|
</a-divider>
|
||||||
<a-form-item label='Type'>
|
<a-form-item label='Type'>
|
||||||
<a-select v-model="noise.type" :dropdown-class-name="themeSwitcher.currentTheme">
|
<a-select v-model="noise.type" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-select-option v-for="s in ['rand','base64','str']" :value="s">[[ s ]]</a-select-option>
|
<a-select-option v-for="s in ['rand','base64','str','hex']" :value="s">[[ s ]]</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label='Packet'>
|
<a-form-item label='Packet'>
|
||||||
@@ -460,12 +460,20 @@
|
|||||||
<a-select-option v-for="tag in ['', ...outModal.tags]" :value="tag">[[ tag ]]</a-select-option>
|
<a-select-option v-for="tag in ['', ...outModal.tags]" :value="tag">[[ tag ]]</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="TCP Fast Open">
|
<a-form-item label='Address Port Strategy'>
|
||||||
<a-switch v-model="outbound.stream.sockopt.tcpFastOpen"></a-switch>
|
<a-select v-model="outbound.stream.sockopt.addressPortStrategy" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option v-for="key in Address_Port_Strategy" :value="key">[[ key ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Keep Alive Interval">
|
<a-form-item label="Keep Alive Interval">
|
||||||
<a-input-number v-model.number="outbound.stream.sockopt.tcpKeepAliveInterval" :min="0"></a-input-number>
|
<a-input-number v-model.number="outbound.stream.sockopt.tcpKeepAliveInterval" :min="0"></a-input-number>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label="TCP Fast Open">
|
||||||
|
<a-switch v-model="outbound.stream.sockopt.tcpFastOpen"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Multipath TCP">
|
||||||
|
<a-switch v-model.trim="outbound.stream.sockopt.tcpMptcp"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item label="Penetrate">
|
<a-form-item label="Penetrate">
|
||||||
<a-switch v-model="outbound.stream.sockopt.penetrate"></a-switch>
|
<a-switch v-model="outbound.stream.sockopt.penetrate"></a-switch>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|||||||
@@ -42,5 +42,14 @@
|
|||||||
<a-form-item label=" ">
|
<a-form-item label=" ">
|
||||||
<a-button type="primary" icon="import" @click="getNewX25519Cert">Get New Cert</a-button>
|
<a-button type="primary" icon="import" @click="getNewX25519Cert">Get New Cert</a-button>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label="mldsa65 Seed">
|
||||||
|
<a-input v-model="inbound.stream.reality.mldsa65Seed"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="mldsa65 Verify">
|
||||||
|
<a-textarea v-model="inbound.stream.reality.settings.mldsa65Verify"></a-textarea>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label=" ">
|
||||||
|
<a-button type="primary" icon="import" @click="getNewmldsa65">Get New Seed</a-button>
|
||||||
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -33,6 +33,9 @@
|
|||||||
<a-form-item label="Max Upload Size (Byte)" v-if="inbound.stream.xhttp.mode === 'packet-up'">
|
<a-form-item label="Max Upload Size (Byte)" v-if="inbound.stream.xhttp.mode === 'packet-up'">
|
||||||
<a-input v-model.trim="inbound.stream.xhttp.scMaxEachPostBytes"></a-input>
|
<a-input v-model.trim="inbound.stream.xhttp.scMaxEachPostBytes"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label="Stream-Up Server" v-if="inbound.stream.xhttp.mode === 'stream-up'">
|
||||||
|
<a-input v-model.trim="inbound.stream.xhttp.scStreamUpServerSecs"></a-input>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item label="Padding Bytes">
|
<a-form-item label="Padding Bytes">
|
||||||
<a-input v-model.trim="inbound.stream.xhttp.xPaddingBytes"></a-input>
|
<a-input v-model.trim="inbound.stream.xhttp.xPaddingBytes"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|||||||
@@ -132,6 +132,16 @@
|
|||||||
inModal.inbound.stream.reality.privateKey = msg.obj.privateKey;
|
inModal.inbound.stream.reality.privateKey = msg.obj.privateKey;
|
||||||
inModal.inbound.stream.reality.settings.publicKey = msg.obj.publicKey;
|
inModal.inbound.stream.reality.settings.publicKey = msg.obj.publicKey;
|
||||||
},
|
},
|
||||||
|
async getNewmldsa65() {
|
||||||
|
inModal.loading(true);
|
||||||
|
const msg = await HttpUtil.post('/server/getNewmldsa65');
|
||||||
|
inModal.loading(false);
|
||||||
|
if (!msg.success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inModal.inbound.stream.reality.mldsa65Seed = msg.obj.seed;
|
||||||
|
inModal.inbound.stream.reality.settings.mldsa65Verify = msg.obj.verify;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -328,7 +328,7 @@
|
|||||||
:dropdown-class-name="themeSwitcher.currentTheme"
|
:dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
@change="(value) => updateNoiseType(index, value)">
|
@change="(value) => updateNoiseType(index, value)">
|
||||||
<a-select-option :value="p" :label="p"
|
<a-select-option :value="p" :label="p"
|
||||||
v-for="p in ['rand', 'base64', 'str']" :key="p">
|
v-for="p in ['rand', 'base64', 'str', 'hex']" :key="p">
|
||||||
[[ p ]] </a-select-option>
|
[[ p ]] </a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|||||||
@@ -174,10 +174,10 @@ new Vue({
|
|||||||
},
|
},
|
||||||
async register(){
|
async register(){
|
||||||
warpModal.loading(true);
|
warpModal.loading(true);
|
||||||
keys = Wireguard.generateKeypair();
|
const keys = Wireguard.generateKeypair();
|
||||||
const msg = await HttpUtil.post('/xui/xray/warp/reg',keys);
|
const msg = await HttpUtil.post('/xui/xray/warp/reg',keys);
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
resp = JSON.parse(msg.obj);
|
const resp = JSON.parse(msg.obj);
|
||||||
warpModal.warpData = resp.data;
|
warpModal.warpData = resp.data;
|
||||||
warpModal.warpConfig = resp.config;
|
warpModal.warpConfig = resp.config;
|
||||||
this.collectConfig();
|
this.collectConfig();
|
||||||
|
|||||||
@@ -1258,8 +1258,7 @@
|
|||||||
}
|
}
|
||||||
newTemplateSettings.routing.balancers.push(tmpBalancer);
|
newTemplateSettings.routing.balancers.push(tmpBalancer);
|
||||||
this.templateSettings = newTemplateSettings;
|
this.templateSettings = newTemplateSettings;
|
||||||
if (balancer.strategy == 'leastPing' || balancer.strategy == 'leastLoad')
|
this.updateObservatorySelectors();
|
||||||
this.updateObservatorySelectors();
|
|
||||||
balancerModal.close();
|
balancerModal.close();
|
||||||
this.changeObsCode();
|
this.changeObsCode();
|
||||||
},
|
},
|
||||||
@@ -1307,8 +1306,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.templateSettings = newTemplateSettings;
|
this.templateSettings = newTemplateSettings;
|
||||||
if (balancer.strategy == 'leastPing' || balancer.strategy == 'leastLoad')
|
this.updateObservatorySelectors();
|
||||||
this.updateObservatorySelectors();
|
|
||||||
balancerModal.close();
|
balancerModal.close();
|
||||||
this.changeObsCode();
|
this.changeObsCode();
|
||||||
},
|
},
|
||||||
@@ -1318,7 +1316,11 @@
|
|||||||
updateObservatorySelectors(){
|
updateObservatorySelectors(){
|
||||||
newTemplateSettings = this.templateSettings;
|
newTemplateSettings = this.templateSettings;
|
||||||
const leastPings = this.balancersData.filter((b) => b.strategy == 'leastPing');
|
const leastPings = this.balancersData.filter((b) => b.strategy == 'leastPing');
|
||||||
const leastLoads = this.balancersData.filter((b) => b.strategy == 'leastLoad');
|
const leastLoads = this.balancersData.filter((b) =>
|
||||||
|
b.strategy === 'leastLoad' ||
|
||||||
|
b.strategy === 'roundRobin' ||
|
||||||
|
b.strategy === 'random'
|
||||||
|
);
|
||||||
if (leastPings.length>0){
|
if (leastPings.length>0){
|
||||||
if (!newTemplateSettings.observatory)
|
if (!newTemplateSettings.observatory)
|
||||||
newTemplateSettings.observatory = this.defaultObservatory;
|
newTemplateSettings.observatory = this.defaultObservatory;
|
||||||
|
|||||||
@@ -79,5 +79,6 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"stats": {}
|
"stats": {},
|
||||||
|
"metrics": {}
|
||||||
}
|
}
|
||||||
@@ -564,3 +564,29 @@ func (s *ServerService) GetNewX25519Cert() (interface{}, error) {
|
|||||||
|
|
||||||
return keyPair, nil
|
return keyPair, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ServerService) GetNewmldsa65() (any, error) {
|
||||||
|
// Run the command
|
||||||
|
cmd := exec.Command(xray.GetBinaryPath(), "mldsa65")
|
||||||
|
var out bytes.Buffer
|
||||||
|
cmd.Stdout = &out
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(out.String(), "\n")
|
||||||
|
|
||||||
|
SeedLine := strings.Split(lines[0], ":")
|
||||||
|
VerifyLine := strings.Split(lines[1], ":")
|
||||||
|
|
||||||
|
seed := strings.TrimSpace(SeedLine[1])
|
||||||
|
verify := strings.TrimSpace(VerifyLine[1])
|
||||||
|
|
||||||
|
keyPair := map[string]any{
|
||||||
|
"seed": seed,
|
||||||
|
"verify": verify,
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyPair, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,8 +56,7 @@ func (s *WarpService) GetWarpConfig() (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
buffer := bytes.NewBuffer(make([]byte, 8192))
|
buffer := &bytes.Buffer{}
|
||||||
buffer.Reset()
|
|
||||||
_, err = buffer.ReadFrom(resp.Body)
|
_, err = buffer.ReadFrom(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -87,8 +86,7 @@ func (s *WarpService) RegWarp(secretKey string, publicKey string) (string, error
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
buffer := bytes.NewBuffer(make([]byte, 8192))
|
buffer := &bytes.Buffer{}
|
||||||
buffer.Reset()
|
|
||||||
_, err = buffer.ReadFrom(resp.Body)
|
_, err = buffer.ReadFrom(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -144,8 +142,7 @@ func (s *WarpService) SetWarpLicense(license string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
buffer := bytes.NewBuffer(make([]byte, 8192))
|
buffer := &bytes.Buffer{}
|
||||||
buffer.Reset()
|
|
||||||
_, err = buffer.ReadFrom(resp.Body)
|
_, err = buffer.ReadFrom(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
24
x-ui.sh
24
x-ui.sh
@@ -56,8 +56,8 @@ elif [[ "${release}" == "centos" ]]; then
|
|||||||
echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1
|
echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "ubuntu" ]]; then
|
elif [[ "${release}" == "ubuntu" ]]; then
|
||||||
if [[ ${os_version} -lt 2004 ]]; then
|
if [[ ${os_version} -lt 2204 ]]; then
|
||||||
echo -e "${red} Please use Ubuntu 20 or higher version!${plain}\n" && exit 1
|
echo -e "${red} Please use Ubuntu 22 or higher version!${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "fedora" ]]; then
|
elif [[ "${release}" == "fedora" ]]; then
|
||||||
if [[ ${os_version} -lt 36 ]]; then
|
if [[ ${os_version} -lt 36 ]]; then
|
||||||
@@ -68,16 +68,16 @@ elif [[ "${release}" == "amzn" ]]; then
|
|||||||
echo -e "${red} Please use Amazon Linux 2023!${plain}\n" && exit 1
|
echo -e "${red} Please use Amazon Linux 2023!${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "debian" ]]; then
|
elif [[ "${release}" == "debian" ]]; then
|
||||||
if [[ ${os_version} -lt 11 ]]; then
|
if [[ ${os_version} -lt 12 ]]; then
|
||||||
echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1
|
echo -e "${red} Please use Debian 12 or higher ${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "almalinux" ]]; then
|
elif [[ "${release}" == "almalinux" ]]; then
|
||||||
if [[ ${os_version} -lt 80 ]]; then
|
if [[ ${os_version} -lt 95 ]]; then
|
||||||
echo -e "${red} Please use AlmaLinux 8.0 or higher ${plain}\n" && exit 1
|
echo -e "${red} Please use AlmaLinux 9.5 or higher ${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "rocky" ]]; then
|
elif [[ "${release}" == "rocky" ]]; then
|
||||||
if [[ ${os_version} -lt 8 ]]; then
|
if [[ ${os_version} -lt 95 ]]; then
|
||||||
echo -e "${red} Please use Rocky Linux 8 or higher ${plain}\n" && exit 1
|
echo -e "${red} Please use Rocky Linux 9.5 or higher ${plain}\n" && exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${release}" == "ol" ]]; then
|
elif [[ "${release}" == "ol" ]]; then
|
||||||
if [[ ${os_version} -lt 8 ]]; then
|
if [[ ${os_version} -lt 8 ]]; then
|
||||||
@@ -86,8 +86,8 @@ elif [[ "${release}" == "ol" ]]; then
|
|||||||
else
|
else
|
||||||
echo -e "${red}Your operating system is not supported by this script.${plain}\n"
|
echo -e "${red}Your operating system is not supported by this script.${plain}\n"
|
||||||
echo "Please ensure you are using one of the following supported operating systems:"
|
echo "Please ensure you are using one of the following supported operating systems:"
|
||||||
echo "- Ubuntu 20.04+"
|
echo "- Ubuntu 22.04+"
|
||||||
echo "- Debian 11+"
|
echo "- Debian 12+"
|
||||||
echo "- CentOS 8+"
|
echo "- CentOS 8+"
|
||||||
echo "- OpenEuler 22.03+"
|
echo "- OpenEuler 22.03+"
|
||||||
echo "- Fedora 36+"
|
echo "- Fedora 36+"
|
||||||
@@ -95,8 +95,8 @@ else
|
|||||||
echo "- Parch Linux"
|
echo "- Parch Linux"
|
||||||
echo "- Manjaro"
|
echo "- Manjaro"
|
||||||
echo "- Armbian"
|
echo "- Armbian"
|
||||||
echo "- AlmaLinux 8.0+"
|
echo "- AlmaLinux 9.5+"
|
||||||
echo "- Rocky Linux 8+"
|
echo "- Rocky Linux 9.5+"
|
||||||
echo "- Oracle Linux 8+"
|
echo "- Oracle Linux 8+"
|
||||||
echo "- OpenSUSE Tumbleweed"
|
echo "- OpenSUSE Tumbleweed"
|
||||||
echo "- Amazon Linux 2023"
|
echo "- Amazon Linux 2023"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ type Config struct {
|
|||||||
FakeDNS json_util.RawMessage `json:"fakedns"`
|
FakeDNS json_util.RawMessage `json:"fakedns"`
|
||||||
Observatory json_util.RawMessage `json:"observatory"`
|
Observatory json_util.RawMessage `json:"observatory"`
|
||||||
BurstObservatory json_util.RawMessage `json:"burstObservatory"`
|
BurstObservatory json_util.RawMessage `json:"burstObservatory"`
|
||||||
|
Metrics json_util.RawMessage `json:"metrics"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Equals(other *Config) bool {
|
func (c *Config) Equals(other *Config) bool {
|
||||||
@@ -61,5 +62,8 @@ func (c *Config) Equals(other *Config) bool {
|
|||||||
if !bytes.Equal(c.FakeDNS, other.FakeDNS) {
|
if !bytes.Equal(c.FakeDNS, other.FakeDNS) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if !bytes.Equal(c.Metrics, other.Metrics) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func (lw *LogWriter) Write(m []byte) (n int, err error) {
|
|||||||
if crashRegex.MatchString(message) {
|
if crashRegex.MatchString(message) {
|
||||||
logger.Debug("Core crash detected:\n", message)
|
logger.Debug("Core crash detected:\n", message)
|
||||||
lw.lastLine = message
|
lw.lastLine = message
|
||||||
err1 := writeCrachReport(m)
|
err1 := writeCrashReport(m)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
logger.Error("Unable to write crash report:", err1)
|
logger.Error("Unable to write crash report:", err1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ func (p *process) Stop() error {
|
|||||||
return p.cmd.Process.Signal(syscall.SIGTERM)
|
return p.cmd.Process.Signal(syscall.SIGTERM)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeCrachReport(m []byte) error {
|
func writeCrashReport(m []byte) error {
|
||||||
crashReportPath := config.GetBinFolderPath() + "/core_crash_" + time.Now().Format("20060102_150405") + ".log"
|
crashReportPath := config.GetBinFolderPath() + "/core_crash_" + time.Now().Format("20060102_150405") + ".log"
|
||||||
return os.WriteFile(crashReportPath, m, os.ModePerm)
|
return os.WriteFile(crashReportPath, m, os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user