diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js
index 47832686..93379bf0 100644
--- a/web/assets/js/model/xray.js
+++ b/web/assets/js/model/xray.js
@@ -24,6 +24,9 @@ const SSMethods = {
CHACHA20_POLY1305: 'chacha20-poly1305',
AES_256_GCM: 'aes-256-gcm',
AES_128_GCM: 'aes-128-gcm',
+ BLAKE3_AES_128_GCM: '2022-blake3-aes-128-gcm',
+ BLAKE3_AES_256_GCM: '2022-blake3-aes-256-gcm',
+ BLAKE3_CHACHA20_POLY1305: '2022-blake3-chacha20-poly1305',
};
const RULE_IP = {
@@ -40,17 +43,64 @@ const RULE_DOMAIN = {
SPEEDTEST: 'geosite:speedtest',
};
-const FLOW_CONTROL = {
+const XTLS_FLOW_CONTROL = {
ORIGIN: "xtls-rprx-origin",
DIRECT: "xtls-rprx-direct",
};
+const TLS_FLOW_CONTROL = {
+ VISION: "xtls-rprx-vision",
+};
+
+const TLS_VERSION_OPTION = {
+ TLS10: "1.0",
+ TLS11: "1.1",
+ TLS12: "1.2",
+ TLS13: "1.3",
+}
+
+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",
+ ECDHE_ECDSA_AES_128_CBC: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ ECDHE_ECDSA_AES_256_CBC: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ ECDHE_RSA_AES_128_CBC: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ ECDHE_RSA_AES_256_CBC: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ ECDHE_ECDSA_AES_128_GCM: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ ECDHE_ECDSA_AES_256_GCM: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ ECDHE_RSA_AES_128_GCM: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ ECDHE_RSA_AES_256_GCM: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ ECDHE_ECDSA_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+ ECDHE_RSA_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+};
+
+const UTLS_FINGERPRINT = {
+ UTLS_CHROME: "chrome",
+ UTLS_FIREFOX: "firefox",
+ UTLS_SAFARI: "safari",
+ UTLS_IOS: "ios",
+ UTLS_android: "android",
+ UTLS_EDGE: "edge",
+ UTLS_360: "360",
+ UTLS_QQ: "qq",
+ UTLS_RANDOM: "random",
+ UTLS_RANDOMIZED: "randomized",
+};
+
Object.freeze(Protocols);
Object.freeze(VmessMethods);
Object.freeze(SSMethods);
Object.freeze(RULE_IP);
Object.freeze(RULE_DOMAIN);
-Object.freeze(FLOW_CONTROL);
+Object.freeze(XTLS_FLOW_CONTROL);
+Object.freeze(TLS_FLOW_CONTROL);
+Object.freeze(TLS_VERSION_OPTION);
+Object.freeze(TLS_CIPHER_OPTION);
class XrayCommonClass {
@@ -417,9 +467,16 @@ class GrpcStreamSettings extends XrayCommonClass {
class TlsStreamSettings extends XrayCommonClass {
constructor(serverName='',
- certificates=[new TlsStreamSettings.Cert()], alpn=[]) {
+ minVersion = TLS_VERSION_OPTION.TLS12,
+ maxVersion = TLS_VERSION_OPTION.TLS13,
+ cipherSuites = '',
+ certificates=[new TlsStreamSettings.Cert()],
+ alpn=["h2", "http/1.1"]) {
super();
this.server = serverName;
+ this.minVersion = minVersion;
+ this.maxVersion = maxVersion;
+ this.cipherSuites = cipherSuites;
this.certs = certificates;
this.alpn = alpn;
}
@@ -440,6 +497,9 @@ class TlsStreamSettings extends XrayCommonClass {
return new TlsStreamSettings(
json.serverName,
+ json.minVersion,
+ json.maxVersion,
+ json.cipherSuites,
certs,
json.alpn
);
@@ -448,6 +508,9 @@ class TlsStreamSettings extends XrayCommonClass {
toJson() {
return {
serverName: this.server,
+ minVersion: this.minVersion,
+ maxVersion: this.maxVersion,
+ cipherSuites: this.cipherSuites,
certificates: TlsStreamSettings.toJsonArray(this.certs),
alpn: this.alpn
};
@@ -710,7 +773,7 @@ class Inbound extends XrayCommonClass {
case Protocols.VLESS:
return this.settings.vlesses[0].flow;
case Protocols.TROJAN:
- return this.settings.clients[0].flow;
+ return this.settings.trojans[0].flow;
default:
return "";
}
@@ -741,7 +804,7 @@ class Inbound extends XrayCommonClass {
get password() {
switch (this.protocol) {
case Protocols.TROJAN:
- return this.settings.clients[0].password;
+ return this.settings.trojans[0].password;
case Protocols.SHADOWSOCKS:
return this.settings.password;
case Protocols.SOCKS:
@@ -857,6 +920,19 @@ class Inbound extends XrayCommonClass {
}
}
+ //this is used for xtls-rprx-vison
+ canEnableTlsFlow() {
+ if ((this.stream.security === 'tls') && (this.network === "tcp")) {
+ switch (this.protocol) {
+ case Protocols.VLESS:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+ }
+
canSetTls() {
return this.canEnableTls();
}
@@ -876,6 +952,7 @@ class Inbound extends XrayCommonClass {
switch (this.protocol) {
case Protocols.VMESS:
case Protocols.VLESS:
+ case Protocols.TROJAN:
case Protocols.SHADOWSOCKS:
return true;
default:
@@ -1032,6 +1109,7 @@ class Inbound extends XrayCommonClass {
address = this.stream.tls.server;
params.set("sni", address);
}
+ params.set("flow", this.settings.vlesses[clientIndex].flow);
}
if (this.xtls) {
@@ -1053,13 +1131,87 @@ class Inbound extends XrayCommonClass {
if (!ObjectUtil.isEmpty(server)) {
address = server;
}
- return 'ss://' + safeBase64(settings.method + ':' + settings.password + '@' + address + ':' + this.port)
- + '#' + encodeURIComponent(remark);
+ if (settings.method == SSMethods.BLAKE3_AES_128_GCM || settings.method == SSMethods.BLAKE3_AES_256_GCM || settings.method == SSMethods.BLAKE3_CHACHA20_POLY1305) {
+ return `ss://${settings.method}:${settings.password}@${address}:${this.port}#${encodeURIComponent(remark)}`;
+ } else {
+ return 'ss://' + safeBase64(settings.method + ':' + settings.password + '@' + address + ':' + this.port)
+ + '#' + encodeURIComponent(remark);
+ }
}
- genTrojanLink(address='', remark='', clientIndex=0) {
+ genTrojanLink(address = '', remark = '', clientIndex = 0) {
let settings = this.settings;
- return `trojan://${settings.trojans[clientIndex].password}@${address}:${this.port}#${encodeURIComponent(remark)}`;
+ const port = this.port;
+ const type = this.stream.network;
+ const params = new Map();
+ params.set("type", this.stream.network);
+ if (this.xtls) {
+ params.set("security", "xtls");
+ } else {
+ params.set("security", this.stream.security);
+ }
+ switch (type) {
+ case "tcp":
+ const tcp = this.stream.tcp;
+ if (tcp.type === 'http') {
+ const request = tcp.request;
+ params.set("path", request.path.join(','));
+ const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
+ if (index >= 0) {
+ const host = request.headers[index].value;
+ params.set("host", host);
+ }
+ params.set("headerType", 'http');
+ }
+ break;
+ case "kcp":
+ const kcp = this.stream.kcp;
+ params.set("headerType", kcp.type);
+ params.set("seed", kcp.seed);
+ break;
+ case "ws":
+ const ws = this.stream.ws;
+ params.set("path", ws.path);
+ const index = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
+ if (index >= 0) {
+ const host = ws.headers[index].value;
+ params.set("host", host);
+ }
+ break;
+ case "http":
+ const http = this.stream.http;
+ params.set("path", http.path);
+ params.set("host", http.host);
+ break;
+ case "quic":
+ const quic = this.stream.quic;
+ params.set("quicSecurity", quic.security);
+ params.set("key", quic.key);
+ params.set("headerType", quic.type);
+ break;
+ case "grpc":
+ const grpc = this.stream.grpc;
+ params.set("serviceName", grpc.serviceName);
+ break;
+ }
+
+ if (this.stream.security === 'tls') {
+ if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
+ address = this.stream.tls.server;
+ params.set("sni", address);
+ }
+ params.set("flow", this.settings.trojans[clientIndex].flow);
+ }
+ if (this.xtls) {
+ params.set("flow", this.settings.trojans[clientIndex].flow);
+ }
+ const link = `trojan://${settings.trojans[clientIndex].password}@${address}:${this.port}#${encodeURIComponent(remark)}`;
+ const url = new URL(link);
+ for (const [key, value] of params) {
+ url.searchParams.set(key, value)
+ }
+ url.hash = encodeURIComponent(remark);
+ return url.toString();
}
genLink(address='', remark='', clientIndex=0) {
@@ -1279,12 +1431,13 @@ Inbound.VLESSSettings = class extends Inbound.Settings {
};
Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
- constructor(id=RandomUtil.randomUUID(), flow=FLOW_CONTROL.DIRECT, email=RandomUtil.randomText(), totalGB=0, expiryTime='') {
+ constructor(id=RandomUtil.randomUUID(), flow='', email=RandomUtil.randomText(), totalGB=0, fingerprint = UTLS_FINGERPRINT.UTLS_CHROME, expiryTime='') {
super();
this.id = id;
this.flow = flow;
this.email = email;
this.totalGB = totalGB;
+ this.fingerprint = fingerprint;
this.expiryTime = expiryTime;
}
@@ -1295,6 +1448,7 @@ Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
json.flow,
json.email,
json.totalGB,
+ json.fingerprint,
json.expiryTime,
);
@@ -1393,7 +1547,7 @@ Inbound.TrojanSettings = class extends Inbound.Settings {
}
};
Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
- constructor(password=RandomUtil.randomSeq(10), flow=FLOW_CONTROL.DIRECT, email=RandomUtil.randomText(), totalGB=0, expiryTime='') {
+ constructor(password=RandomUtil.randomSeq(10), flow='', email=RandomUtil.randomText(), totalGB=0, expiryTime='') {
super();
this.password = password;
this.flow = flow;
@@ -1488,8 +1642,8 @@ Inbound.TrojanSettings.Fallback = class extends XrayCommonClass {
Inbound.ShadowsocksSettings = class extends Inbound.Settings {
constructor(protocol,
- method=SSMethods.AES_256_GCM,
- password=RandomUtil.randomSeq(10),
+ method=SSMethods.BLAKE3_AES_256_GCM,
+ password=RandomUtil.randomSeq(44),
network='tcp,udp'
) {
super(protocol);
diff --git a/web/html/xui/form/protocol/trojan.html b/web/html/xui/form/protocol/trojan.html
index 5076d395..52bd646b 100644
--- a/web/html/xui/form/protocol/trojan.html
+++ b/web/html/xui/form/protocol/trojan.html
@@ -29,7 +29,7 @@
{{ i18n "none" }}
- [[ key ]]
+ [[ key ]]
@@ -68,7 +68,7 @@
[[ sizeFormat(getUpStats(trojan.email)) ]] / [[ sizeFormat(getDownStats(trojan.email)) ]]
used : [[ sizeFormat(getUpStats(trojan.email) + getDownStats(trojan.email)) ]]
-
+
-
-
- {{ i18n "none" }}
- [[ key ]]
+
+
+ none
+ [[ key ]]
+
+
+ none
+ [[ key ]]
+
+
+
+
+ [[ key ]]
+
+
{{ i18n "pages.inbounds.totalFlow" }}(GB)
@@ -70,7 +81,7 @@
[[ sizeFormat(getUpStats(vless.email)) ]] / [[ sizeFormat(getDownStats(vless.email)) ]]
used : [[ sizeFormat(getUpStats(vless.email) + getDownStats(vless.email)) ]]
-
+
-
+
-
+
+
+
+ [[ key ]]
+
+
+
+
+ [[ key ]]
+
+
+
+
+ auto
+ [[ key ]]
+
+
@@ -20,8 +35,7 @@
-
+
{{ i18n "pages.inbounds.certificatePath" }}
{{ i18n "pages.inbounds.certificateContent" }}
@@ -36,18 +50,11 @@
-
+
-
+
-
-
-
-
-
{{end}}
\ No newline at end of file