so-far updates

This commit is contained in:
Alireza Ahmadi
2025-07-30 16:09:15 +02:00
parent ee03836eeb
commit e954ccd957
26 changed files with 806 additions and 403 deletions

4
.github/FUNDING.yml vendored
View File

@@ -1,6 +1,6 @@
# 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
open_collective: # Replace with a single Open Collective 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
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
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']

View File

@@ -7,7 +7,7 @@ on:
jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

View File

@@ -18,7 +18,7 @@ jobs:
- armv5
- 386
- s390x
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -84,7 +84,7 @@ jobs:
cd x-ui/bin
# 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
wget -q ${Xray_URL}Xray-linux-64.zip
unzip Xray-linux-64.zip

View File

@@ -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/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"
rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat LICENSE README.md
mv xray "xray-linux-${FNAME}"

View File

@@ -1,4 +1,4 @@
FROM golang:1.23-alpine AS builder
FROM golang:1.24-alpine AS builder
WORKDIR /app
ARG TARGETARCH
RUN apk --no-cache --update add build-base gcc wget unzip

View File

@@ -188,7 +188,7 @@ docker build -t x-ui .
## Recommended OS
- Ubuntu 20.04+
- Ubuntu 22.04+
- Debian 11+
- CentOS 8+
- OpenEuler 22.03+

View File

@@ -60,8 +60,8 @@ elif [[ "${release}" == "centos" ]]; then
echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1
fi
elif [[ "${release}" == "ubuntu" ]]; then
if [[ ${os_version} -lt 2004 ]]; then
echo -e "${red} Please use Ubuntu 20 or higher version!${plain}\n" && exit 1
if [[ ${os_version} -lt 2204 ]]; then
echo -e "${red} Please use Ubuntu 22 or higher version!${plain}\n" && exit 1
fi
elif [[ "${release}" == "fedora" ]]; 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
fi
elif [[ "${release}" == "debian" ]]; then
if [[ ${os_version} -lt 11 ]]; then
echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1
if [[ ${os_version} -lt 12 ]]; then
echo -e "${red} Please use Debian 12 or higher ${plain}\n" && exit 1
fi
elif [[ "${release}" == "almalinux" ]]; then
if [[ ${os_version} -lt 80 ]]; then
echo -e "${red} Please use AlmaLinux 8.0 or higher ${plain}\n" && exit 1
if [[ ${os_version} -lt 95 ]]; then
echo -e "${red} Please use AlmaLinux 9.5 or higher ${plain}\n" && exit 1
fi
elif [[ "${release}" == "rocky" ]]; then
if [[ ${os_version} -lt 8 ]]; then
echo -e "${red} Please use Rocky Linux 8 or higher ${plain}\n" && exit 1
if [[ ${os_version} -lt 95 ]]; then
echo -e "${red} Please use Rocky Linux 9.5 or higher ${plain}\n" && exit 1
fi
elif [[ "${release}" == "ol" ]]; then
if [[ ${os_version} -lt 8 ]]; then
@@ -90,8 +90,8 @@ elif [[ "${release}" == "ol" ]]; then
else
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 "- Ubuntu 20.04+"
echo "- Debian 11+"
echo "- Ubuntu 22.04+"
echo "- Debian 12+"
echo "- CentOS 8+"
echo "- OpenEuler 22.03+"
echo "- Fedora 36+"
@@ -99,8 +99,8 @@ else
echo "- Parch Linux"
echo "- Manjaro"
echo "- Armbian"
echo "- AlmaLinux 8.0+"
echo "- Rocky Linux 8+"
echo "- AlmaLinux 9.5+"
echo "- Rocky Linux 9.5+"
echo "- Oracle Linux 8+"
echo "- OpenSUSE Tumbleweed"
echo "- Amazon Linux 2023"

View File

@@ -263,6 +263,7 @@ func (s *SubJsonService) realityData(rData map[string]interface{}) map[string]in
rltyData["show"] = false
rltyData["publicKey"] = rltyClientSettings["publicKey"]
rltyData["fingerprint"] = rltyClientSettings["fingerprint"]
rltyData["mldsa65Verify"] = rltyClientSettings["mldsa65Verify"]
// Set random data
rltyData["spiderX"] = "/" + random.Seq(15)

View File

@@ -34,10 +34,6 @@ const TLS_VERSION_OPTION = {
};
const TLS_CIPHER_OPTION = {
RSA_AES_128_CBC: "TLS_RSA_WITH_AES_128_CBC_SHA",
RSA_AES_256_CBC: "TLS_RSA_WITH_AES_256_CBC_SHA",
RSA_AES_128_GCM: "TLS_RSA_WITH_AES_128_GCM_SHA256",
RSA_AES_256_GCM: "TLS_RSA_WITH_AES_256_GCM_SHA384",
AES_128_GCM: "TLS_AES_128_GCM_SHA256",
AES_256_GCM: "TLS_AES_256_GCM_SHA384",
CHACHA20_POLY1305: "TLS_CHACHA20_POLY1305_SHA256",
@@ -64,6 +60,7 @@ const UTLS_FINGERPRINT = {
UTLS_QQ: "qq",
UTLS_RANDOM: "random",
UTLS_RANDOMIZED: "randomized",
UTLS_RONDOMIZEDNOALPN: "randomizednoalpn",
UTLS_UNSAFE: "unsafe",
};
@@ -80,10 +77,45 @@ const SNIFFING_OPTION = {
FAKEDNS: "fakedns"
};
const USAGE_OPTION = {
ENCIPHERMENT: "encipherment",
VERIFY: "verify",
ISSUE: "issue",
};
const DOMAIN_STRATEGY_OPTION = {
AS_IS: "AsIs",
USE_IP: "UseIP",
USE_IPV6V4: "UseIPv6v4",
USE_IPV6: "UseIPv6",
USE_IPV4V6: "UseIPv4v6",
USE_IPV4: "UseIPv4",
FORCE_IP: "ForceIP",
FORCE_IPV6V4: "ForceIPv6v4",
FORCE_IPV6: "ForceIPv6",
FORCE_IPV4V6: "ForceIPv4v6",
FORCE_IPV4: "ForceIPv4",
};
const TCP_CONGESTION_OPTION = {
BBR: "bbr",
CUBIC: "cubic",
RENO: "reno",
};
const USERS_SECURITY = {
AES_128_GCM: "aes-128-gcm",
CHACHA20_POLY1305: "chacha20-poly1305",
AUTO: "auto",
NONE: "none",
ZERO: "zero",
};
const MODE_OPTION = {
AUTO: "auto",
PACKET_UP: "packet-up",
STREAM_UP: "stream-up",
STREAM_ONE: "stream-one",
};
Object.freeze(Protocols);
@@ -94,9 +126,12 @@ Object.freeze(TLS_CIPHER_OPTION);
Object.freeze(UTLS_FINGERPRINT);
Object.freeze(ALPN_OPTION);
Object.freeze(SNIFFING_OPTION);
Object.freeze(USAGE_OPTION);
Object.freeze(DOMAIN_STRATEGY_OPTION);
Object.freeze(TCP_CONGESTION_OPTION);
Object.freeze(USERS_SECURITY);
Object.freeze(MODE_OPTION);
class XrayCommonClass {
static toJsonArray(arr) {
@@ -155,7 +190,8 @@ class XrayCommonClass {
}
class TcpStreamSettings extends XrayCommonClass {
constructor(acceptProxyProtocol=false,
constructor(
acceptProxyProtocol = false,
type = 'none',
request = new TcpStreamSettings.TcpRequest(),
response = new TcpStreamSettings.TcpResponse(),
@@ -192,7 +228,8 @@ class TcpStreamSettings extends XrayCommonClass {
}
TcpStreamSettings.TcpRequest = class extends XrayCommonClass {
constructor(version='1.1',
constructor(
version = '1.1',
method = 'GET',
path = ['/'],
headers = [],
@@ -240,7 +277,8 @@ TcpStreamSettings.TcpRequest = class extends XrayCommonClass {
};
TcpStreamSettings.TcpResponse = class extends XrayCommonClass {
constructor(version='1.1',
constructor(
version = '1.1',
status = '200',
reason = 'OK',
headers = [],
@@ -280,7 +318,9 @@ TcpStreamSettings.TcpResponse = class extends XrayCommonClass {
};
class KcpStreamSettings extends XrayCommonClass {
constructor(mtu=1350, tti=20,
constructor(
mtu = 1350,
tti = 50,
uplinkCapacity = 5,
downlinkCapacity = 20,
congestion = false,
@@ -333,12 +373,19 @@ class KcpStreamSettings extends XrayCommonClass {
}
class WsStreamSettings extends XrayCommonClass {
constructor(acceptProxyProtocol=false, path='/', host='', headers=[]) {
constructor(
acceptProxyProtocol = false,
path = '/',
host = '',
headers = [],
heartbeatPeriod = 0,
) {
super();
this.acceptProxyProtocol = acceptProxyProtocol;
this.path = path;
this.host = host;
this.headers = headers;
this.heartbeatPeriod = heartbeatPeriod;
}
addHeader(name, value) {
@@ -355,6 +402,7 @@ class WsStreamSettings extends XrayCommonClass {
json.path,
json.host,
XrayCommonClass.toHeaders(json.headers),
json.heartbeatPeriod,
);
}
@@ -364,12 +412,17 @@ class WsStreamSettings extends XrayCommonClass {
path: this.path,
host: this.host,
headers: XrayCommonClass.toV2Headers(this.headers, false),
heartbeatPeriod: this.heartbeatPeriod,
};
}
}
class GrpcStreamSettings extends XrayCommonClass {
constructor(serviceName='', authority='', multiMode=false) {
constructor(
serviceName = "",
authority = "",
multiMode = false,
) {
super();
this.serviceName = serviceName;
this.authority = authority;
@@ -377,7 +430,11 @@ class GrpcStreamSettings extends XrayCommonClass {
}
static fromJson(json = {}) {
return new GrpcStreamSettings(json.serviceName, json.authority, json.multiMode);
return new GrpcStreamSettings(
json.serviceName,
json.authority,
json.multiMode
);
}
toJson() {
@@ -390,7 +447,12 @@ class GrpcStreamSettings extends XrayCommonClass {
}
class HttpUpgradeStreamSettings extends XrayCommonClass {
constructor(acceptProxyProtocol=false, path='/', host='', headers=[]) {
constructor(
acceptProxyProtocol = false,
path = '/',
host = '',
headers = []
) {
super();
this.acceptProxyProtocol = acceptProxyProtocol;
this.path = path;
@@ -424,6 +486,7 @@ class HttpUpgradeStreamSettings extends XrayCommonClass {
};
}
}
class xHTTPStreamSettings extends XrayCommonClass {
constructor(
path = '/',
@@ -431,6 +494,7 @@ class xHTTPStreamSettings extends XrayCommonClass {
headers = [],
scMaxBufferedPosts = 30,
scMaxEachPostBytes = "1000000",
scStreamUpServerSecs = "20-80",
noSSEHeader = false,
xPaddingBytes = "100-1000",
mode = MODE_OPTION.AUTO,
@@ -441,6 +505,7 @@ class xHTTPStreamSettings extends XrayCommonClass {
this.headers = headers;
this.scMaxBufferedPosts = scMaxBufferedPosts;
this.scMaxEachPostBytes = scMaxEachPostBytes;
this.scStreamUpServerSecs = scStreamUpServerSecs;
this.noSSEHeader = noSSEHeader;
this.xPaddingBytes = xPaddingBytes;
this.mode = mode;
@@ -461,6 +526,7 @@ class xHTTPStreamSettings extends XrayCommonClass {
XrayCommonClass.toHeaders(json.headers),
json.scMaxBufferedPosts,
json.scMaxEachPostBytes,
json.scStreamUpServerSecs,
json.noSSEHeader,
json.xPaddingBytes,
json.mode,
@@ -474,6 +540,7 @@ class xHTTPStreamSettings extends XrayCommonClass {
headers: XrayCommonClass.toV2Headers(this.headers, false),
scMaxBufferedPosts: this.scMaxBufferedPosts,
scMaxEachPostBytes: this.scMaxEachPostBytes,
scStreamUpServerSecs: this.scStreamUpServerSecs,
noSSEHeader: this.noSSEHeader,
xPaddingBytes: this.xPaddingBytes,
mode: this.mode,
@@ -482,20 +549,28 @@ class xHTTPStreamSettings extends XrayCommonClass {
}
class TlsStreamSettings extends XrayCommonClass {
constructor(serverName='',
constructor(
serverName = '',
minVersion = TLS_VERSION_OPTION.TLS12,
maxVersion = TLS_VERSION_OPTION.TLS13,
cipherSuites = '',
rejectUnknownSni = false,
verifyPeerCertInNames = ['dns.google', 'cloudflare-dns.com'],
disableSystemRoot = false,
enableSessionResumption = false,
certificates = [new TlsStreamSettings.Cert()],
alpn=[ALPN_OPTION.H2,ALPN_OPTION.HTTP1],
settings=new TlsStreamSettings.Settings()) {
alpn = [ALPN_OPTION.H3, ALPN_OPTION.H2, ALPN_OPTION.HTTP1],
settings = new TlsStreamSettings.Settings()
) {
super();
this.sni = serverName;
this.minVersion = minVersion;
this.maxVersion = maxVersion;
this.cipherSuites = cipherSuites;
this.rejectUnknownSni = rejectUnknownSni;
this.verifyPeerCertInNames = Array.isArray(verifyPeerCertInNames) ? verifyPeerCertInNames.join(",") : verifyPeerCertInNames;
this.disableSystemRoot = disableSystemRoot;
this.enableSessionResumption = enableSessionResumption;
this.certs = certificates;
this.alpn = alpn;
this.settings = settings;
@@ -525,6 +600,9 @@ class TlsStreamSettings extends XrayCommonClass {
json.maxVersion,
json.cipherSuites,
json.rejectUnknownSni,
json.verifyPeerCertInNames,
json.disableSystemRoot,
json.enableSessionResumption,
certs,
json.alpn,
settings,
@@ -538,6 +616,9 @@ class TlsStreamSettings extends XrayCommonClass {
maxVersion: this.maxVersion,
cipherSuites: this.cipherSuites,
rejectUnknownSni: this.rejectUnknownSni,
verifyPeerCertInNames: this.verifyPeerCertInNames.split(","),
disableSystemRoot: this.disableSystemRoot,
enableSessionResumption: this.enableSessionResumption,
certificates: TlsStreamSettings.toJsonArray(this.certs),
alpn: this.alpn,
settings: this.settings,
@@ -546,14 +627,27 @@ class TlsStreamSettings extends XrayCommonClass {
}
TlsStreamSettings.Cert = class extends XrayCommonClass {
constructor(useFile=true, certificateFile='', keyFile='', certificate='', key='', ocspStapling=3600) {
constructor(
useFile = true,
certificateFile = '',
keyFile = '',
certificate = '',
key = '',
ocspStapling = 0,
oneTimeLoading = false,
usage = USAGE_OPTION.ENCIPHERMENT,
buildChain = false,
) {
super();
this.useFile = useFile;
this.certFile = certificateFile;
this.keyFile = keyFile;
this.cert = certificate instanceof Array ? certificate.join('\n') : certificate;
this.key = key instanceof Array ? key.join('\n') : key;
this.cert = Array.isArray(certificate) ? certificate.join('\n') : certificate;
this.key = Array.isArray(key) ? key.join('\n') : key;
this.ocspStapling = ocspStapling;
this.oneTimeLoading = oneTimeLoading;
this.usage = usage;
this.buildChain = buildChain
}
static fromJson(json = {}) {
@@ -563,6 +657,9 @@ TlsStreamSettings.Cert = class extends XrayCommonClass {
json.certificateFile,
json.keyFile, '', '',
json.ocspStapling,
json.oneTimeLoading,
json.usage,
json.buildChain,
);
} else {
return new TlsStreamSettings.Cert(
@@ -570,6 +667,9 @@ TlsStreamSettings.Cert = class extends XrayCommonClass {
json.certificate.join('\n'),
json.key.join('\n'),
json.ocspStapling,
json.oneTimeLoading,
json.usage,
json.buildChain,
);
}
}
@@ -580,12 +680,18 @@ TlsStreamSettings.Cert = class extends XrayCommonClass {
certificateFile: this.certFile,
keyFile: this.keyFile,
ocspStapling: this.ocspStapling,
oneTimeLoading: this.oneTimeLoading,
usage: this.usage,
buildChain: this.buildChain,
};
} else {
return {
certificate: this.cert.split('\n'),
key: this.key.split('\n'),
ocspStapling: this.ocspStapling,
oneTimeLoading: this.oneTimeLoading,
usage: this.usage,
buildChain: this.buildChain,
};
}
}
@@ -614,13 +720,21 @@ TlsStreamSettings.Settings = class extends XrayCommonClass {
}
};
class RealityStreamSettings extends XrayCommonClass {
constructor(show = false, xver = 0,
constructor(
show = false,
xver = 0,
dest = 'microsoft.com:443',
serverNames = 'microsoft.com,www.microsoft.com',
privateKey = '', minClient = '', maxClient = '',
maxTimediff = 0, shortIds = RandomUtil.randomShortId(),
settings= new RealityStreamSettings.Settings()) {
privateKey = '',
minClient = '',
maxClient = '',
maxTimediff = 0,
shortIds = RandomUtil.randomShortId(),
mldsa65Seed = '',
settings = new RealityStreamSettings.Settings()
) {
super();
this.show = show;
this.xver = xver;
@@ -631,13 +745,20 @@ class RealityStreamSettings extends XrayCommonClass {
this.maxClient = maxClient;
this.maxTimediff = maxTimediff;
this.shortIds = shortIds instanceof Array ? shortIds.join(",") : shortIds;
this.mldsa65Seed = mldsa65Seed;
this.settings = settings;
}
static fromJson(json = {}) {
let settings;
if (!ObjectUtil.isEmpty(json.settings)) {
settings = new RealityStreamSettings.Settings(json.settings.publicKey , json.settings.fingerprint, json.settings.serverName, json.settings.spiderX);
settings = new RealityStreamSettings.Settings(
json.settings.publicKey,
json.settings.fingerprint,
json.settings.serverName,
json.settings.spiderX,
json.settings.mldsa65Verify,
);
}
return new RealityStreamSettings(
json.show,
@@ -649,10 +770,11 @@ class RealityStreamSettings extends XrayCommonClass {
json.maxClient,
json.maxTimediff,
json.shortIds,
json.settings,
json.mldsa65Seed,
settings,
);
}
toJson() {
return {
show: this.show,
@@ -664,6 +786,7 @@ class RealityStreamSettings extends XrayCommonClass {
maxClient: this.maxClient,
maxTimediff: this.maxTimediff,
shortIds: this.shortIds.split(","),
mldsa65Seed: this.mldsa65Seed,
settings: this.settings,
};
}
@@ -674,13 +797,15 @@ RealityStreamSettings.Settings = class extends XrayCommonClass {
publicKey = '',
fingerprint = UTLS_FINGERPRINT.UTLS_CHROME,
serverName = '',
spiderX = '/'
spiderX = '/',
mldsa65Verify = ''
) {
super();
this.publicKey = publicKey;
this.fingerprint = fingerprint;
this.serverName = serverName;
this.spiderX = spiderX;
this.mldsa65Verify = mldsa65Verify;
}
static fromJson(json = {}) {
return new RealityStreamSettings.Settings(
@@ -688,6 +813,7 @@ RealityStreamSettings.Settings = class extends XrayCommonClass {
json.fingerprint,
json.serverName,
json.spiderX,
json.mldsa65Verify
);
}
toJson() {
@@ -696,17 +822,47 @@ RealityStreamSettings.Settings = class extends XrayCommonClass {
fingerprint: this.fingerprint,
serverName: this.serverName,
spiderX: this.spiderX,
mldsa65Verify: this.mldsa65Verify
};
}
};
class SockoptStreamSettings extends XrayCommonClass {
constructor(acceptProxyProtocol = false, tcpFastOpen = false, mark = 0, tproxy="off") {
constructor(
acceptProxyProtocol = false,
tcpFastOpen = false,
mark = 0,
tproxy = "off",
tcpMptcp = false,
penetrate = false,
domainStrategy = DOMAIN_STRATEGY_OPTION.USE_IP,
tcpMaxSeg = 1440,
dialerProxy = "",
tcpKeepAliveInterval = 0,
tcpKeepAliveIdle = 300,
tcpUserTimeout = 10000,
tcpcongestion = TCP_CONGESTION_OPTION.BBR,
V6Only = false,
tcpWindowClamp = 600,
interfaceName = "",
) {
super();
this.acceptProxyProtocol = acceptProxyProtocol;
this.tcpFastOpen = tcpFastOpen;
this.mark = mark;
this.tproxy = tproxy;
this.tcpMptcp = tcpMptcp;
this.penetrate = penetrate;
this.domainStrategy = domainStrategy;
this.tcpMaxSeg = tcpMaxSeg;
this.dialerProxy = dialerProxy;
this.tcpKeepAliveInterval = tcpKeepAliveInterval;
this.tcpKeepAliveIdle = tcpKeepAliveIdle;
this.tcpUserTimeout = tcpUserTimeout;
this.tcpcongestion = tcpcongestion;
this.V6Only = V6Only;
this.tcpWindowClamp = tcpWindowClamp;
this.interfaceName = interfaceName;
}
static fromJson(json = {}) {
@@ -716,6 +872,18 @@ class SockoptStreamSettings extends XrayCommonClass {
json.tcpFastOpen,
json.mark,
json.tproxy,
json.tcpMptcp,
json.penetrate,
json.domainStrategy,
json.tcpMaxSeg,
json.dialerProxy,
json.tcpKeepAliveInterval,
json.tcpKeepAliveIdle,
json.tcpUserTimeout,
json.tcpcongestion,
json.V6Only,
json.tcpWindowClamp,
json.interface,
);
}
@@ -725,6 +893,18 @@ class SockoptStreamSettings extends XrayCommonClass {
tcpFastOpen: this.tcpFastOpen,
mark: this.mark,
tproxy: this.tproxy,
tcpMptcp: this.tcpMptcp,
penetrate: this.penetrate,
domainStrategy: this.domainStrategy,
tcpMaxSeg: this.tcpMaxSeg,
dialerProxy: this.dialerProxy,
tcpKeepAliveInterval: this.tcpKeepAliveInterval,
tcpKeepAliveIdle: this.tcpKeepAliveIdle,
tcpUserTimeout: this.tcpUserTimeout,
tcpcongestion: this.tcpcongestion,
V6Only: this.V6Only,
tcpWindowClamp: this.tcpWindowClamp,
interface: this.interfaceName,
};
}
}
@@ -759,7 +939,7 @@ class StreamSettings extends XrayCommonClass {
}
get isTls() {
return this.security === 'tls';
return this.security === "tls";
}
set isTls(isTls) {
@@ -770,6 +950,7 @@ class StreamSettings extends XrayCommonClass {
}
}
//for Reality
get isReality() {
return this.security === "reality";
}
@@ -856,7 +1037,8 @@ class Sniffing extends XrayCommonClass {
}
class Inbound extends XrayCommonClass {
constructor(port=RandomUtil.randomIntRange(10000, 60000),
constructor(
port = RandomUtil.randomIntRange(10000, 60000),
listen = '',
protocol = Protocols.VLESS,
settings = null,
@@ -897,7 +1079,7 @@ class Inbound extends XrayCommonClass {
this._protocol = protocol;
this.settings = Inbound.Settings.getSettings(protocol);
if (protocol === Protocols.TROJAN) {
this.stream.isTls = true;
this.tls = false;
}
}
@@ -939,7 +1121,7 @@ class Inbound extends XrayCommonClass {
case Protocols.SHADOWSOCKS:
return this.settings.method;
default:
return '';
return "";
}
}
get isSSMultiUser() {
@@ -990,7 +1172,6 @@ class Inbound extends XrayCommonClass {
return null;
}
get kcpType() {
return this.stream.kcp.type;
}
@@ -1015,7 +1196,7 @@ class Inbound extends XrayCommonClass {
//this is used for xtls-rprx-vision
canEnableTlsFlow() {
if ((this.stream.security != 'none') && (this.network === "tcp")) {
if (((this.stream.security === 'tls') || (this.stream.security === 'reality')) && (this.network === "tcp")) {
return this.protocol === Protocols.VLESS;
}
return false;
@@ -1040,20 +1221,20 @@ class Inbound extends XrayCommonClass {
this.sniffing = new Sniffing();
}
genVmessLink(address='', port=this.port, forceTls, remark='', clientId) {
genVmessLink(address = '', port = this.port, forceTls, remark = '', clientId, security) {
if (this.protocol !== Protocols.VMESS) {
return '';
}
const security = forceTls == 'same' ? this.stream.security : forceTls;
const tls = forceTls == 'same' ? this.stream.security : forceTls;
let obj = {
v: '2',
ps: remark,
add: address,
port: port,
id: clientId,
scy: security,
net: this.stream.network,
type: 'none',
tls: security,
tls: tls,
};
const network = this.stream.network;
if (network === 'tcp') {
@@ -1073,10 +1254,6 @@ class Inbound extends XrayCommonClass {
const ws = this.stream.ws;
obj.path = ws.path;
obj.host = ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host');
} else if (network === 'http') {
obj.net = 'h2';
obj.path = this.stream.http.path;
obj.host = this.stream.http.host.join(',');
} else if (network === 'grpc') {
obj.path = this.stream.grpc.serviceName;
obj.authority = this.stream.grpc.authority;
@@ -1091,10 +1268,10 @@ class Inbound extends XrayCommonClass {
const xhttp = this.stream.xhttp;
obj.path = xhttp.path;
obj.host = xhttp.host?.length > 0 ? xhttp.host : this.getHeader(xhttp, 'host');
obj.mode = xhttp.mode;
obj.type = xhttp.mode;
}
if (security === 'tls') {
if (tls === 'tls') {
if (!ObjectUtil.isEmpty(this.stream.tls.sni)) {
obj.sni = this.stream.tls.sni;
}
@@ -1109,7 +1286,7 @@ class Inbound extends XrayCommonClass {
}
}
return 'vmess://' + base64(JSON.stringify(obj, null, 2));
return 'vmess://' + Base64.encode(JSON.stringify(obj, null, 2));
}
genVLESSLink(address = '', port = this.port, forceTls, remark = '', clientId, flow) {
@@ -1368,6 +1545,7 @@ class Inbound extends XrayCommonClass {
params.set("spx", this.stream.reality.settings.spiderX);
}
}
else {
params.set("security", "none");
}
@@ -1406,7 +1584,7 @@ class Inbound extends XrayCommonClass {
genLink(address = '', port = this.port, forceTls = 'same', remark = '', client) {
switch (this.protocol) {
case Protocols.VMESS:
return this.genVmessLink(address, port, forceTls, remark, client.id);
return this.genVmessLink(address, port, forceTls, remark, client.id, client.security);
case Protocols.VLESS:
return this.genVLESSLink(address, port, forceTls, remark, client.id, client.flow);
case Protocols.SHADOWSOCKS:
@@ -1579,10 +1757,22 @@ Inbound.VmessSettings = class extends Inbound.Settings {
};
}
};
Inbound.VmessSettings.Vmess = class extends XrayCommonClass {
constructor(id=RandomUtil.randomUUID(), email=RandomUtil.randomLowerAndNum(9), totalGB=0, expiryTime=0, enable=true, tgId='', subId=RandomUtil.randomLowerAndNum(16), reset=0) {
constructor(
id = RandomUtil.randomUUID(),
security = USERS_SECURITY.AUTO,
email = RandomUtil.randomLowerAndNum(8),
totalGB = 0,
expiryTime = 0,
enable = true,
tgId = '',
subId = RandomUtil.randomLowerAndNum(16),
reset = 0
) {
super();
this.id = id;
this.security = security;
this.email = email;
this.totalGB = totalGB;
this.expiryTime = expiryTime;
@@ -1595,6 +1785,7 @@ Inbound.VmessSettings.Vmess = class extends XrayCommonClass {
static fromJson(json = {}) {
return new Inbound.VmessSettings.Vmess(
json.id,
json.security,
json.email,
json.totalGB,
json.expiryTime,
@@ -1632,10 +1823,12 @@ Inbound.VmessSettings.Vmess = class extends XrayCommonClass {
};
Inbound.VLESSSettings = class extends Inbound.Settings {
constructor(protocol,
constructor(
protocol,
vlesses = [new Inbound.VLESSSettings.VLESS()],
decryption = 'none',
fallbacks=[],) {
fallbacks = []
) {
super(protocol);
this.vlesses = vlesses;
this.decryption = decryption;
@@ -1655,22 +1848,31 @@ Inbound.VLESSSettings = class extends Inbound.Settings {
return new Inbound.VLESSSettings(
Protocols.VLESS,
json.clients.map(client => Inbound.VLESSSettings.VLESS.fromJson(client)),
'none',
Inbound.VLESSSettings.Fallback.fromJson(json.fallbacks),
);
json.decryption || 'none',
Inbound.VLESSSettings.Fallback.fromJson(json.fallbacks),);
}
toJson() {
return {
clients: Inbound.VLESSSettings.toJsonArray(this.vlesses),
decryption: 'none',
decryption: this.decryption,
fallbacks: Inbound.VLESSSettings.toJsonArray(this.fallbacks),
};
}
};
Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
constructor(id=RandomUtil.randomUUID(), flow='', email=RandomUtil.randomLowerAndNum(9), totalGB=0, expiryTime=0, enable=true, tgId='', subId=RandomUtil.randomLowerAndNum(16), reset=0) {
constructor(
id = RandomUtil.randomUUID(),
flow = '',
email = RandomUtil.randomLowerAndNum(8),
totalGB = 0,
expiryTime = 0,
enable = true,
tgId = '',
subId = RandomUtil.randomLowerAndNum(16),
reset = 0
) {
super();
this.id = id;
this.flow = flow;
@@ -1788,12 +1990,22 @@ Inbound.TrojanSettings = class extends Inbound.Settings {
toJson() {
return {
clients: Inbound.TrojanSettings.toJsonArray(this.trojans),
fallbacks: Inbound.TrojanSettings.toJsonArray(this.fallbacks),
fallbacks: Inbound.TrojanSettings.toJsonArray(this.fallbacks)
};
}
};
Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
constructor(password=RandomUtil.randomSeq(10), email=RandomUtil.randomLowerAndNum(9), totalGB=0, expiryTime=0, enable=true, tgId='', subId=RandomUtil.randomLowerAndNum(16), reset=0) {
constructor(
password = RandomUtil.randomSeq(10),
email = RandomUtil.randomLowerAndNum(8),
totalGB = 0,
expiryTime = 0,
enable = true,
tgId = '',
subId = RandomUtil.randomLowerAndNum(16),
reset = 0
) {
super();
this.password = password;
this.email = email;
@@ -1936,7 +2148,17 @@ Inbound.ShadowsocksSettings = class extends Inbound.Settings {
};
Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass {
constructor(method='', password=RandomUtil.randomShadowsocksPassword(), email=RandomUtil.randomLowerAndNum(9), totalGB=0, expiryTime=0, enable=true, tgId='', subId=RandomUtil.randomLowerAndNum(16), reset=0) {
constructor(
method = '',
password = RandomUtil.randomShadowsocksPassword(),
email = RandomUtil.randomLowerAndNum(8),
totalGB = 0,
expiryTime = 0,
enable = true,
tgId = '',
subId = RandomUtil.randomLowerAndNum(16),
reset = 0
) {
super();
this.method = method;
this.password = password;
@@ -2005,7 +2227,13 @@ Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass {
};
Inbound.DokodemoSettings = class extends Inbound.Settings {
constructor(protocol, address, port, network='tcp,udp', followRedirect=false) {
constructor(
protocol,
address,
port,
network = 'tcp,udp',
followRedirect = false
) {
super(protocol);
this.address = address;
this.port = port;
@@ -2019,7 +2247,7 @@ Inbound.DokodemoSettings = class extends Inbound.Settings {
json.address,
json.port,
json.network,
json.followRedirect
json.followRedirect,
);
}
@@ -2028,7 +2256,7 @@ Inbound.DokodemoSettings = class extends Inbound.Settings {
address: this.address,
port: this.port,
network: this.network,
followRedirect: this.followRedirect
followRedirect: this.followRedirect,
};
}
};
@@ -2135,7 +2363,13 @@ Inbound.HttpSettings.HttpAccount = class extends XrayCommonClass {
};
Inbound.WireguardSettings = class extends XrayCommonClass {
constructor(protocol, mtu=1420, secretKey=Wireguard.generateKeypair().privateKey, peers=[new Inbound.WireguardSettings.Peer()], kernelMode=false) {
constructor(
protocol,
mtu = 1420,
secretKey = Wireguard.generateKeypair().privateKey,
peers = [new Inbound.WireguardSettings.Peer()],
kernelMode = false
) {
super(protocol);
this.mtu = mtu;
this.secretKey = secretKey;

View File

@@ -39,6 +39,7 @@ const UTLS_FINGERPRINT = {
UTLS_QQ: "qq",
UTLS_RANDOM: "random",
UTLS_RANDOMIZED: "randomized",
UTLS_RONDOMIZEDNOALPN: "randomizednoalpn",
UTLS_UNSAFE: "unsafe",
};
@@ -70,19 +71,41 @@ const WireguardDomainStrategy = [
"ForceIPv6v4"
];
const USERS_SECURITY = {
AES_128_GCM: "aes-128-gcm",
CHACHA20_POLY1305: "chacha20-poly1305",
AUTO: "auto",
NONE: "none",
ZERO: "zero",
};
const MODE_OPTION = {
AUTO: "auto",
PACKET_UP: "packet-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(SSMethods);
Object.freeze(TLS_FLOW_CONTROL);
Object.freeze(UTLS_FINGERPRINT);
Object.freeze(ALPN_OPTION);
Object.freeze(OutboundDomainStrategies);
Object.freeze(WireguardDomainStrategy);
Object.freeze(USERS_SECURITY);
Object.freeze(MODE_OPTION);
Object.freeze(Address_Port_Strategy);
class CommonClass {
@@ -140,7 +163,9 @@ class TcpStreamSettings extends CommonClass {
}
class KcpStreamSettings extends CommonClass {
constructor(mtu=1350, tti=20,
constructor(
mtu = 1350,
tti = 50,
uplinkCapacity = 5,
downlinkCapacity = 20,
congestion = false,
@@ -193,16 +218,23 @@ class KcpStreamSettings extends CommonClass {
}
class WsStreamSettings extends CommonClass {
constructor(path='/', host='') {
constructor(
path = '/',
host = '',
heartbeatPeriod = 0,
) {
super();
this.path = path;
this.host = host;
this.heartbeatPeriod = heartbeatPeriod;
}
static fromJson(json = {}) {
return new WsStreamSettings(
json.path,
json.host,
json.heartbeatPeriod,
);
}
@@ -210,12 +242,17 @@ class WsStreamSettings extends CommonClass {
return {
path: this.path,
host: this.host,
heartbeatPeriod: this.heartbeatPeriod
};
}
}
class GrpcStreamSettings extends CommonClass {
constructor(serviceName="", authority="", multiMode=false) {
constructor(
serviceName = "",
authority = "",
multiMode = false
) {
super();
this.serviceName = serviceName;
this.authority = authority;
@@ -230,7 +267,7 @@ class GrpcStreamSettings extends CommonClass {
return {
serviceName: this.serviceName,
authority: this.authority,
multiMode: this.multiMode,
multiMode: this.multiMode
}
}
}
@@ -313,10 +350,12 @@ class xHTTPStreamSettings extends CommonClass {
}
class TlsStreamSettings extends CommonClass {
constructor(serverName='',
constructor(
serverName = '',
alpn = [],
fingerprint = '',
allowInsecure = false) {
allowInsecure = false
) {
super();
this.serverName = serverName;
this.alpn = alpn;
@@ -344,7 +383,13 @@ class TlsStreamSettings extends CommonClass {
}
class RealityStreamSettings extends CommonClass {
constructor(publicKey = '', fingerprint = '', serverName = '', shortId = '', spiderX = '/') {
constructor(
publicKey = '',
fingerprint = '',
serverName = '',
shortId = '',
spiderX = '/'
) {
super();
this.publicKey = publicKey;
this.fingerprint = fingerprint;
@@ -371,14 +416,22 @@ class RealityStreamSettings 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();
this.dialerProxy = dialerProxy;
this.tcpFastOpen = tcpFastOpen;
this.tcpKeepAliveInterval = tcpKeepAliveInterval;
this.tcpMptcp = tcpMptcp;
this.penetrate = penetrate;
this.addressPortStrategy = addressPortStrategy;
}
static fromJson(json = {}) {
@@ -387,7 +440,9 @@ class SockoptStreamSettings extends CommonClass {
json.dialerProxy,
json.tcpFastOpen,
json.tcpKeepAliveInterval,
json.tcpMptcp,
json.penetrate,
json.addressPortStrategy
);
}
@@ -396,13 +451,16 @@ class SockoptStreamSettings extends CommonClass {
dialerProxy: this.dialerProxy,
tcpFastOpen: this.tcpFastOpen,
tcpKeepAliveInterval: this.tcpKeepAliveInterval,
tcpMptcp: this.tcpMptcp,
penetrate: this.penetrate,
addressPortStrategy: this.addressPortStrategy
};
}
}
class StreamSettings extends CommonClass {
constructor(network='tcp',
constructor(
network = 'tcp',
security = 'none',
tlsSettings = new TlsStreamSettings(),
realitySettings = new RealityStreamSettings(),
@@ -510,7 +568,7 @@ class Mux extends CommonClass {
class Outbound extends CommonClass {
constructor(
tag = '',
protocol=Protocols.VMess,
protocol = Protocols.VLESS,
settings = null,
streamSettings = new StreamSettings(),
sendThrough,
@@ -558,11 +616,27 @@ class Outbound extends CommonClass {
}
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;
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() {
@@ -666,7 +740,7 @@ class Outbound extends CommonClass {
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) {
@@ -832,7 +906,11 @@ Outbound.FreedomSettings = class extends CommonClass {
};
Outbound.FreedomSettings.Fragment = class extends CommonClass {
constructor(packets='1-3',length='',interval=''){
constructor(
packets = '1-3',
length = '',
interval = ''
) {
super();
this.packets = packets;
this.length = length;
@@ -898,7 +976,7 @@ Outbound.BlackholeSettings = class extends CommonClass {
Outbound.DNSSettings = class extends CommonClass {
constructor(
network = 'udp',
address = '1.1.1.1',
address = '',
port = 53,
nonIPQuery = 'drop',
blockTypes = []
@@ -922,11 +1000,12 @@ Outbound.DNSSettings = class extends CommonClass {
}
};
Outbound.VmessSettings = class extends CommonClass {
constructor(address, port, id) {
constructor(address, port, id, security) {
super();
this.address = address;
this.port = port;
this.id = id;
this.security = security;
}
static fromJson(json = {}) {
@@ -935,6 +1014,7 @@ Outbound.VmessSettings = class extends CommonClass {
json.vnext[0].address,
json.vnext[0].port,
json.vnext[0].users[0].id,
json.vnext[0].users[0].security,
);
}
@@ -943,7 +1023,7 @@ Outbound.VmessSettings = class extends CommonClass {
vnext: [{
address: this.address,
port: this.port,
users: [{id: this.id}],
users: [{ id: this.id, security: this.security }],
}],
};
}
@@ -1007,13 +1087,14 @@ Outbound.TrojanSettings = class extends CommonClass {
}
};
Outbound.ShadowsocksSettings = class extends CommonClass {
constructor(address, port, password, method, uot) {
constructor(address, port, password, method, uot, UoTVersion) {
super();
this.address = address;
this.port = port;
this.password = password;
this.method = method;
this.uot = uot;
this.UoTVersion = UoTVersion;
}
static fromJson(json = {}) {
@@ -1025,6 +1106,7 @@ Outbound.ShadowsocksSettings = class extends CommonClass {
servers[0].password,
servers[0].method,
servers[0].uot,
servers[0].UoTVersion,
);
}
@@ -1036,10 +1118,12 @@ Outbound.ShadowsocksSettings = class extends CommonClass {
password: this.password,
method: this.method,
uot: this.uot,
UoTVersion: this.UoTVersion,
}],
};
}
};
Outbound.SocksSettings = class extends CommonClass {
constructor(address, port, user, pass) {
super();
@@ -1100,11 +1184,18 @@ Outbound.HttpSettings = class extends CommonClass {
};
}
};
Outbound.WireguardSettings = class extends CommonClass {
constructor(
mtu=1420, secretKey='',
address='', workers=2, domainStrategy='', reserved='',
peers=[new Outbound.WireguardSettings.Peer()], kernelMode=false) {
mtu = 1420,
secretKey = '',
address = [''],
workers = 2,
domainStrategy = '',
reserved = '',
peers = [new Outbound.WireguardSettings.Peer()],
kernelMode = false,
) {
super();
this.mtu = mtu;
this.secretKey = secretKey;
@@ -1151,8 +1242,15 @@ Outbound.WireguardSettings = 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();
this.publicKey = publicKey;
this.psk = psk;

View File

@@ -49,6 +49,7 @@ func (a *ServerController) initRouter(g *gin.RouterGroup) {
g.GET("/getDb", a.getDb)
g.POST("/importDB", a.importDB)
g.POST("/getNewX25519Cert", a.getNewX25519Cert)
g.POST("/getNewmldsa65", a.getNewmldsa65)
}
func (a *ServerController) refreshStatus() {
@@ -186,3 +187,12 @@ func (a *ServerController) getNewX25519Cert(c *gin.Context) {
}
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)
}

View File

@@ -2,7 +2,7 @@
<head>
<meta charset="UTF-8">
<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">
<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">

View File

@@ -66,7 +66,7 @@
</a-divider>
<a-form-item label='Type'>
<a-select v-model="noise.type" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="s in ['rand','base64','str']" :value="s">[[ s ]]</a-select-option>
<a-select-option v-for="s in ['rand','base64','str','hex']" :value="s">[[ s ]]</a-select-option>
</a-select>
</a-form-item>
<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>
</a-form-item>
<a-form-item label="TCP Fast Open">
<a-switch v-model="outbound.stream.sockopt.tcpFastOpen"></a-switch>
<a-form-item label='Address Port Strategy'>
<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 label="Keep Alive Interval">
<a-input-number v-model.number="outbound.stream.sockopt.tcpKeepAliveInterval" :min="0"></a-input-number>
</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-switch v-model="outbound.stream.sockopt.penetrate"></a-switch>
</a-form-item>

View File

@@ -42,5 +42,14 @@
<a-form-item label=" ">
<a-button type="primary" icon="import" @click="getNewX25519Cert">Get New Cert</a-button>
</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>
{{end}}

View File

@@ -33,6 +33,9 @@
<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-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-input v-model.trim="inbound.stream.xhttp.xPaddingBytes"></a-input>
</a-form-item>

View File

@@ -132,6 +132,16 @@
inModal.inbound.stream.reality.privateKey = msg.obj.privateKey;
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;
},
},
});

View File

@@ -328,7 +328,7 @@
:dropdown-class-name="themeSwitcher.currentTheme"
@change="(value) => updateNoiseType(index, value)">
<a-select-option :value="p" :label="p"
v-for="p in ['rand', 'base64', 'str']" :key="p">
v-for="p in ['rand', 'base64', 'str', 'hex']" :key="p">
[[ p ]] </a-select-option>
</a-select>
</a-col>

View File

@@ -174,10 +174,10 @@ new Vue({
},
async register(){
warpModal.loading(true);
keys = Wireguard.generateKeypair();
const keys = Wireguard.generateKeypair();
const msg = await HttpUtil.post('/xui/xray/warp/reg',keys);
if (msg.success) {
resp = JSON.parse(msg.obj);
const resp = JSON.parse(msg.obj);
warpModal.warpData = resp.data;
warpModal.warpConfig = resp.config;
this.collectConfig();

View File

@@ -1258,7 +1258,6 @@
}
newTemplateSettings.routing.balancers.push(tmpBalancer);
this.templateSettings = newTemplateSettings;
if (balancer.strategy == 'leastPing' || balancer.strategy == 'leastLoad')
this.updateObservatorySelectors();
balancerModal.close();
this.changeObsCode();
@@ -1307,7 +1306,6 @@
});
}
this.templateSettings = newTemplateSettings;
if (balancer.strategy == 'leastPing' || balancer.strategy == 'leastLoad')
this.updateObservatorySelectors();
balancerModal.close();
this.changeObsCode();
@@ -1318,7 +1316,11 @@
updateObservatorySelectors(){
newTemplateSettings = this.templateSettings;
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 (!newTemplateSettings.observatory)
newTemplateSettings.observatory = this.defaultObservatory;

View File

@@ -79,5 +79,6 @@
}
]
},
"stats": {}
"stats": {},
"metrics": {}
}

View File

@@ -564,3 +564,29 @@ func (s *ServerService) GetNewX25519Cert() (interface{}, error) {
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
}

View File

@@ -56,8 +56,7 @@ func (s *WarpService) GetWarpConfig() (string, error) {
return "", err
}
defer resp.Body.Close()
buffer := bytes.NewBuffer(make([]byte, 8192))
buffer.Reset()
buffer := &bytes.Buffer{}
_, err = buffer.ReadFrom(resp.Body)
if err != nil {
return "", err
@@ -87,8 +86,7 @@ func (s *WarpService) RegWarp(secretKey string, publicKey string) (string, error
return "", err
}
defer resp.Body.Close()
buffer := bytes.NewBuffer(make([]byte, 8192))
buffer.Reset()
buffer := &bytes.Buffer{}
_, err = buffer.ReadFrom(resp.Body)
if err != nil {
return "", err
@@ -144,8 +142,7 @@ func (s *WarpService) SetWarpLicense(license string) (string, error) {
return "", err
}
defer resp.Body.Close()
buffer := bytes.NewBuffer(make([]byte, 8192))
buffer.Reset()
buffer := &bytes.Buffer{}
_, err = buffer.ReadFrom(resp.Body)
if err != nil {
return "", err

24
x-ui.sh
View File

@@ -56,8 +56,8 @@ elif [[ "${release}" == "centos" ]]; then
echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1
fi
elif [[ "${release}" == "ubuntu" ]]; then
if [[ ${os_version} -lt 2004 ]]; then
echo -e "${red} Please use Ubuntu 20 or higher version!${plain}\n" && exit 1
if [[ ${os_version} -lt 2204 ]]; then
echo -e "${red} Please use Ubuntu 22 or higher version!${plain}\n" && exit 1
fi
elif [[ "${release}" == "fedora" ]]; 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
fi
elif [[ "${release}" == "debian" ]]; then
if [[ ${os_version} -lt 11 ]]; then
echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1
if [[ ${os_version} -lt 12 ]]; then
echo -e "${red} Please use Debian 12 or higher ${plain}\n" && exit 1
fi
elif [[ "${release}" == "almalinux" ]]; then
if [[ ${os_version} -lt 80 ]]; then
echo -e "${red} Please use AlmaLinux 8.0 or higher ${plain}\n" && exit 1
if [[ ${os_version} -lt 95 ]]; then
echo -e "${red} Please use AlmaLinux 9.5 or higher ${plain}\n" && exit 1
fi
elif [[ "${release}" == "rocky" ]]; then
if [[ ${os_version} -lt 8 ]]; then
echo -e "${red} Please use Rocky Linux 8 or higher ${plain}\n" && exit 1
if [[ ${os_version} -lt 95 ]]; then
echo -e "${red} Please use Rocky Linux 9.5 or higher ${plain}\n" && exit 1
fi
elif [[ "${release}" == "ol" ]]; then
if [[ ${os_version} -lt 8 ]]; then
@@ -86,8 +86,8 @@ elif [[ "${release}" == "ol" ]]; then
else
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 "- Ubuntu 20.04+"
echo "- Debian 11+"
echo "- Ubuntu 22.04+"
echo "- Debian 12+"
echo "- CentOS 8+"
echo "- OpenEuler 22.03+"
echo "- Fedora 36+"
@@ -95,8 +95,8 @@ else
echo "- Parch Linux"
echo "- Manjaro"
echo "- Armbian"
echo "- AlmaLinux 8.0+"
echo "- Rocky Linux 8+"
echo "- AlmaLinux 9.5+"
echo "- Rocky Linux 9.5+"
echo "- Oracle Linux 8+"
echo "- OpenSUSE Tumbleweed"
echo "- Amazon Linux 2023"

View File

@@ -20,6 +20,7 @@ type Config struct {
FakeDNS json_util.RawMessage `json:"fakedns"`
Observatory json_util.RawMessage `json:"observatory"`
BurstObservatory json_util.RawMessage `json:"burstObservatory"`
Metrics json_util.RawMessage `json:"metrics"`
}
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) {
return false
}
if !bytes.Equal(c.Metrics, other.Metrics) {
return false
}
return true
}

View File

@@ -25,7 +25,7 @@ func (lw *LogWriter) Write(m []byte) (n int, err error) {
if crashRegex.MatchString(message) {
logger.Debug("Core crash detected:\n", message)
lw.lastLine = message
err1 := writeCrachReport(m)
err1 := writeCrashReport(m)
if err1 != nil {
logger.Error("Unable to write crash report:", err1)
}

View File

@@ -192,7 +192,7 @@ func (p *process) Stop() error {
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"
return os.WriteFile(crashReportPath, m, os.ModePerm)
}