mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-04-19 21:42:24 +00:00
removed - XTLS Security
because its too old and no one use it anymore
This commit is contained in:
parent
3b3bd3dea4
commit
e359b5c75e
20 changed files with 3 additions and 395 deletions
|
@ -452,38 +452,7 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if security == "xtls" {
|
if security != "tls" && security != "reality" {
|
||||||
params["security"] = "xtls"
|
|
||||||
xtlsSetting, _ := stream["xtlsSettings"].(map[string]interface{})
|
|
||||||
alpns, _ := xtlsSetting["alpn"].([]interface{})
|
|
||||||
var alpn []string
|
|
||||||
for _, a := range alpns {
|
|
||||||
alpn = append(alpn, a.(string))
|
|
||||||
}
|
|
||||||
if len(alpn) > 0 {
|
|
||||||
params["alpn"] = strings.Join(alpn, ",")
|
|
||||||
}
|
|
||||||
if sniValue, ok := searchKey(xtlsSetting, "serverName"); ok {
|
|
||||||
params["sni"], _ = sniValue.(string)
|
|
||||||
}
|
|
||||||
xtlsSettings, _ := searchKey(xtlsSetting, "settings")
|
|
||||||
if xtlsSetting != nil {
|
|
||||||
if fpValue, ok := searchKey(xtlsSettings, "fingerprint"); ok {
|
|
||||||
params["fp"], _ = fpValue.(string)
|
|
||||||
}
|
|
||||||
if insecure, ok := searchKey(xtlsSettings, "allowInsecure"); ok {
|
|
||||||
if insecure.(bool) {
|
|
||||||
params["allowInsecure"] = "1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 {
|
|
||||||
params["flow"] = clients[clientIndex].Flow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if security != "tls" && security != "reality" && security != "xtls" {
|
|
||||||
params["security"] = "none"
|
params["security"] = "none"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,39 +645,7 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if security == "xtls" {
|
if security != "tls" && security != "reality" {
|
||||||
params["security"] = "xtls"
|
|
||||||
xtlsSetting, _ := stream["xtlsSettings"].(map[string]interface{})
|
|
||||||
alpns, _ := xtlsSetting["alpn"].([]interface{})
|
|
||||||
var alpn []string
|
|
||||||
for _, a := range alpns {
|
|
||||||
alpn = append(alpn, a.(string))
|
|
||||||
}
|
|
||||||
if len(alpn) > 0 {
|
|
||||||
params["alpn"] = strings.Join(alpn, ",")
|
|
||||||
}
|
|
||||||
if sniValue, ok := searchKey(xtlsSetting, "serverName"); ok {
|
|
||||||
params["sni"], _ = sniValue.(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
xtlsSettings, _ := searchKey(xtlsSetting, "settings")
|
|
||||||
if xtlsSetting != nil {
|
|
||||||
if fpValue, ok := searchKey(xtlsSettings, "fingerprint"); ok {
|
|
||||||
params["fp"], _ = fpValue.(string)
|
|
||||||
}
|
|
||||||
if insecure, ok := searchKey(xtlsSettings, "allowInsecure"); ok {
|
|
||||||
if insecure.(bool) {
|
|
||||||
params["allowInsecure"] = "1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 {
|
|
||||||
params["flow"] = clients[clientIndex].Flow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if security != "tls" && security != "reality" && security != "xtls" {
|
|
||||||
params["security"] = "none"
|
params["security"] = "none"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,6 @@ const SSMethods = {
|
||||||
BLAKE3_CHACHA20_POLY1305: '2022-blake3-chacha20-poly1305',
|
BLAKE3_CHACHA20_POLY1305: '2022-blake3-chacha20-poly1305',
|
||||||
};
|
};
|
||||||
|
|
||||||
const XTLS_FLOW_CONTROL = {
|
|
||||||
ORIGIN: "xtls-rprx-origin",
|
|
||||||
DIRECT: "xtls-rprx-direct",
|
|
||||||
};
|
|
||||||
|
|
||||||
const TLS_FLOW_CONTROL = {
|
const TLS_FLOW_CONTROL = {
|
||||||
VISION: "xtls-rprx-vision",
|
VISION: "xtls-rprx-vision",
|
||||||
VISION_UDP443: "xtls-rprx-vision-udp443",
|
VISION_UDP443: "xtls-rprx-vision-udp443",
|
||||||
|
@ -120,7 +115,6 @@ const USERS_SECURITY = {
|
||||||
|
|
||||||
Object.freeze(Protocols);
|
Object.freeze(Protocols);
|
||||||
Object.freeze(SSMethods);
|
Object.freeze(SSMethods);
|
||||||
Object.freeze(XTLS_FLOW_CONTROL);
|
|
||||||
Object.freeze(TLS_FLOW_CONTROL);
|
Object.freeze(TLS_FLOW_CONTROL);
|
||||||
Object.freeze(TLS_VERSION_OPTION);
|
Object.freeze(TLS_VERSION_OPTION);
|
||||||
Object.freeze(TLS_CIPHER_OPTION);
|
Object.freeze(TLS_CIPHER_OPTION);
|
||||||
|
@ -755,137 +749,6 @@ TlsStreamSettings.Settings = class extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class XtlsStreamSettings extends XrayCommonClass {
|
|
||||||
constructor(
|
|
||||||
serverName = '',
|
|
||||||
certificates = [new XtlsStreamSettings.Cert()],
|
|
||||||
alpn = [ALPN_OPTION.H3, ALPN_OPTION.H2, ALPN_OPTION.HTTP1],
|
|
||||||
settings = new XtlsStreamSettings.Settings()
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
this.sni = serverName;
|
|
||||||
this.certs = certificates;
|
|
||||||
this.alpn = alpn;
|
|
||||||
this.settings = settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
addCert() {
|
|
||||||
this.certs.push(new XtlsStreamSettings.Cert());
|
|
||||||
}
|
|
||||||
|
|
||||||
removeCert(index) {
|
|
||||||
this.certs.splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromJson(json = {}) {
|
|
||||||
let certs;
|
|
||||||
let settings;
|
|
||||||
if (!ObjectUtil.isEmpty(json.certificates)) {
|
|
||||||
certs = json.certificates.map(cert => XtlsStreamSettings.Cert.fromJson(cert));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ObjectUtil.isEmpty(json.settings)) {
|
|
||||||
settings = new XtlsStreamSettings.Settings(json.settings.allowInsecure, json.settings.serverName);
|
|
||||||
}
|
|
||||||
return new XtlsStreamSettings(
|
|
||||||
json.serverName,
|
|
||||||
certs,
|
|
||||||
json.alpn,
|
|
||||||
settings,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
toJson() {
|
|
||||||
return {
|
|
||||||
serverName: this.sni,
|
|
||||||
certificates: XtlsStreamSettings.toJsonArray(this.certs),
|
|
||||||
alpn: this.alpn,
|
|
||||||
settings: this.settings,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XtlsStreamSettings.Cert = class extends XrayCommonClass {
|
|
||||||
constructor(
|
|
||||||
useFile = true,
|
|
||||||
certificateFile = '',
|
|
||||||
keyFile = '',
|
|
||||||
certificate = '',
|
|
||||||
key = '',
|
|
||||||
ocspStapling = 3600,
|
|
||||||
oneTimeLoading = false,
|
|
||||||
usage = USAGE_OPTION.ENCIPHERMENT
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
this.useFile = useFile;
|
|
||||||
this.certFile = certificateFile;
|
|
||||||
this.keyFile = keyFile;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromJson(json = {}) {
|
|
||||||
if ('certificateFile' in json && 'keyFile' in json) {
|
|
||||||
return new XtlsStreamSettings.Cert(
|
|
||||||
true,
|
|
||||||
json.certificateFile,
|
|
||||||
json.keyFile, '', '',
|
|
||||||
json.ocspStapling,
|
|
||||||
json.oneTimeLoading,
|
|
||||||
json.usage,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return new XtlsStreamSettings.Cert(
|
|
||||||
false, '', '',
|
|
||||||
json.certificate.join('\n'),
|
|
||||||
json.key.join('\n'),
|
|
||||||
json.ocspStapling,
|
|
||||||
json.oneTimeLoading,
|
|
||||||
json.usage,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toJson() {
|
|
||||||
if (this.useFile) {
|
|
||||||
return {
|
|
||||||
certificateFile: this.certFile,
|
|
||||||
keyFile: this.keyFile,
|
|
||||||
ocspStapling: this.ocspStapling,
|
|
||||||
oneTimeLoading: this.oneTimeLoading,
|
|
||||||
usage: this.usage,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
certificate: this.cert.split('\n'),
|
|
||||||
key: this.key.split('\n'),
|
|
||||||
ocspStapling: this.ocspStapling,
|
|
||||||
oneTimeLoading: this.oneTimeLoading,
|
|
||||||
usage: this.usage,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
XtlsStreamSettings.Settings = class extends XrayCommonClass {
|
|
||||||
constructor(allowInsecure = false) {
|
|
||||||
super();
|
|
||||||
this.allowInsecure = allowInsecure;
|
|
||||||
}
|
|
||||||
static fromJson(json = {}) {
|
|
||||||
return new XtlsStreamSettings.Settings(
|
|
||||||
json.allowInsecure,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
toJson() {
|
|
||||||
return {
|
|
||||||
allowInsecure: this.allowInsecure,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class RealityStreamSettings extends XrayCommonClass {
|
class RealityStreamSettings extends XrayCommonClass {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -1071,7 +934,6 @@ class StreamSettings extends XrayCommonClass {
|
||||||
security = 'none',
|
security = 'none',
|
||||||
externalProxy = [],
|
externalProxy = [],
|
||||||
tlsSettings = new TlsStreamSettings(),
|
tlsSettings = new TlsStreamSettings(),
|
||||||
xtlsSettings = new XtlsStreamSettings(),
|
|
||||||
realitySettings = new RealityStreamSettings(),
|
realitySettings = new RealityStreamSettings(),
|
||||||
tcpSettings = new TcpStreamSettings(),
|
tcpSettings = new TcpStreamSettings(),
|
||||||
kcpSettings = new KcpStreamSettings(),
|
kcpSettings = new KcpStreamSettings(),
|
||||||
|
@ -1087,7 +949,6 @@ class StreamSettings extends XrayCommonClass {
|
||||||
this.security = security;
|
this.security = security;
|
||||||
this.externalProxy = externalProxy;
|
this.externalProxy = externalProxy;
|
||||||
this.tls = tlsSettings;
|
this.tls = tlsSettings;
|
||||||
this.xtls = xtlsSettings;
|
|
||||||
this.reality = realitySettings;
|
this.reality = realitySettings;
|
||||||
this.tcp = tcpSettings;
|
this.tcp = tcpSettings;
|
||||||
this.kcp = kcpSettings;
|
this.kcp = kcpSettings;
|
||||||
|
@ -1111,18 +972,6 @@ class StreamSettings extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get isXtls() {
|
|
||||||
return this.security === "xtls";
|
|
||||||
}
|
|
||||||
|
|
||||||
set isXtls(isXtls) {
|
|
||||||
if (isXtls) {
|
|
||||||
this.security = 'xtls';
|
|
||||||
} else {
|
|
||||||
this.security = 'none';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//for Reality
|
//for Reality
|
||||||
get isReality() {
|
get isReality() {
|
||||||
return this.security === "reality";
|
return this.security === "reality";
|
||||||
|
@ -1150,7 +999,6 @@ class StreamSettings extends XrayCommonClass {
|
||||||
json.security,
|
json.security,
|
||||||
json.externalProxy,
|
json.externalProxy,
|
||||||
TlsStreamSettings.fromJson(json.tlsSettings),
|
TlsStreamSettings.fromJson(json.tlsSettings),
|
||||||
XtlsStreamSettings.fromJson(json.xtlsSettings),
|
|
||||||
RealityStreamSettings.fromJson(json.realitySettings),
|
RealityStreamSettings.fromJson(json.realitySettings),
|
||||||
TcpStreamSettings.fromJson(json.tcpSettings),
|
TcpStreamSettings.fromJson(json.tcpSettings),
|
||||||
KcpStreamSettings.fromJson(json.kcpSettings),
|
KcpStreamSettings.fromJson(json.kcpSettings),
|
||||||
|
@ -1170,7 +1018,6 @@ class StreamSettings extends XrayCommonClass {
|
||||||
security: this.security,
|
security: this.security,
|
||||||
externalProxy: this.externalProxy,
|
externalProxy: this.externalProxy,
|
||||||
tlsSettings: this.isTls ? this.tls.toJson() : undefined,
|
tlsSettings: this.isTls ? this.tls.toJson() : undefined,
|
||||||
xtlsSettings: this.isXtls ? this.xtls.toJson() : undefined,
|
|
||||||
realitySettings: this.isReality ? this.reality.toJson() : undefined,
|
realitySettings: this.isReality ? this.reality.toJson() : undefined,
|
||||||
tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined,
|
tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined,
|
||||||
kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
|
kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
|
||||||
|
@ -1283,18 +1130,6 @@ class Inbound extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get xtls() {
|
|
||||||
return this.stream.security === 'xtls';
|
|
||||||
}
|
|
||||||
|
|
||||||
set xtls(isXtls) {
|
|
||||||
if (isXtls) {
|
|
||||||
this.stream.security = 'xtls';
|
|
||||||
} else {
|
|
||||||
this.stream.security = 'none';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get network() {
|
get network() {
|
||||||
return this.stream.network;
|
return this.stream.network;
|
||||||
}
|
}
|
||||||
|
@ -1349,7 +1184,6 @@ class Inbound extends XrayCommonClass {
|
||||||
|
|
||||||
get serverName() {
|
get serverName() {
|
||||||
if (this.stream.isTls) return this.stream.tls.sni;
|
if (this.stream.isTls) return this.stream.tls.sni;
|
||||||
if (this.stream.isXtls) return this.stream.xtls.sni;
|
|
||||||
if (this.stream.isReality) return this.stream.reality.serverNames;
|
if (this.stream.isReality) return this.stream.reality.serverNames;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -1428,11 +1262,6 @@ class Inbound extends XrayCommonClass {
|
||||||
return ["tcp", "http", "grpc"].includes(this.network);
|
return ["tcp", "http", "grpc"].includes(this.network);
|
||||||
}
|
}
|
||||||
|
|
||||||
canEnableXtls() {
|
|
||||||
if (![Protocols.VLESS, Protocols.TROJAN].includes(this.protocol)) return false;
|
|
||||||
return this.network === "tcp";
|
|
||||||
}
|
|
||||||
|
|
||||||
canEnableStream() {
|
canEnableStream() {
|
||||||
return [Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol);
|
return [Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol);
|
||||||
}
|
}
|
||||||
|
@ -1592,18 +1421,6 @@ class Inbound extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (security === 'xtls') {
|
|
||||||
params.set("security", "xtls");
|
|
||||||
params.set("alpn", this.stream.xtls.alpn);
|
|
||||||
if (this.stream.xtls.settings.allowInsecure) {
|
|
||||||
params.set("allowInsecure", "1");
|
|
||||||
}
|
|
||||||
if (!ObjectUtil.isEmpty(this.stream.xtls.sni)) {
|
|
||||||
params.set("sni", this.stream.xtls.sni);
|
|
||||||
}
|
|
||||||
params.set("flow", flow);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (security === 'reality') {
|
else if (security === 'reality') {
|
||||||
params.set("security", "reality");
|
params.set("security", "reality");
|
||||||
params.set("pbk", this.stream.reality.settings.publicKey);
|
params.set("pbk", this.stream.reality.settings.publicKey);
|
||||||
|
@ -1801,18 +1618,6 @@ class Inbound extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (security === 'xtls') {
|
|
||||||
params.set("security", "xtls");
|
|
||||||
params.set("alpn", this.stream.xtls.alpn);
|
|
||||||
if (this.stream.xtls.settings.allowInsecure) {
|
|
||||||
params.set("allowInsecure", "1");
|
|
||||||
}
|
|
||||||
if (!ObjectUtil.isEmpty(this.stream.xtls.sni)) {
|
|
||||||
params.set("sni", this.stream.xtls.sni);
|
|
||||||
}
|
|
||||||
params.set("flow", flow);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
else {
|
||||||
params.set("security", "none");
|
params.set("security", "none");
|
||||||
}
|
}
|
||||||
|
@ -2273,7 +2078,6 @@ Inbound.TrojanSettings = class extends Inbound.Settings {
|
||||||
Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
|
Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
|
||||||
constructor(
|
constructor(
|
||||||
password = RandomUtil.randomSeq(10),
|
password = RandomUtil.randomSeq(10),
|
||||||
flow = '',
|
|
||||||
email = RandomUtil.randomLowerAndNum(8),
|
email = RandomUtil.randomLowerAndNum(8),
|
||||||
limitIp = 0,
|
limitIp = 0,
|
||||||
totalGB = 0,
|
totalGB = 0,
|
||||||
|
@ -2285,7 +2089,6 @@ Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.flow = flow;
|
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.limitIp = limitIp;
|
this.limitIp = limitIp;
|
||||||
this.totalGB = totalGB;
|
this.totalGB = totalGB;
|
||||||
|
@ -2299,7 +2102,6 @@ Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
|
||||||
toJson() {
|
toJson() {
|
||||||
return {
|
return {
|
||||||
password: this.password,
|
password: this.password,
|
||||||
flow: this.flow,
|
|
||||||
email: this.email,
|
email: this.email,
|
||||||
limitIp: this.limitIp,
|
limitIp: this.limitIp,
|
||||||
totalGB: this.totalGB,
|
totalGB: this.totalGB,
|
||||||
|
@ -2314,7 +2116,6 @@ Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
|
||||||
static fromJson(json = {}) {
|
static fromJson(json = {}) {
|
||||||
return new Inbound.TrojanSettings.Trojan(
|
return new Inbound.TrojanSettings.Trojan(
|
||||||
json.password,
|
json.password,
|
||||||
json.flow,
|
|
||||||
json.email,
|
json.email,
|
||||||
json.limitIp,
|
json.limitIp,
|
||||||
json.totalGB,
|
json.totalGB,
|
||||||
|
|
|
@ -39,12 +39,6 @@
|
||||||
<a-select-option v-for="key in TLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
<a-select-option v-for="key in TLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label='Flow' v-if="clientsBulkModal.inbound.xtls">
|
|
||||||
<a-select v-model="clientsBulkModal.flow" :dropdown-class-name="themeSwitcher.currentTheme">
|
|
||||||
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
|
|
||||||
<a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item v-if="app.subSettings.enable">
|
<a-form-item v-if="app.subSettings.enable">
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
|
@ -181,9 +175,6 @@
|
||||||
if (clientsBulkModal.inbound.canEnableTlsFlow()) {
|
if (clientsBulkModal.inbound.canEnableTlsFlow()) {
|
||||||
newClient.flow = clientsBulkModal.flow;
|
newClient.flow = clientsBulkModal.flow;
|
||||||
}
|
}
|
||||||
if (clientsBulkModal.inbound.xtls) {
|
|
||||||
newClient.flow = clientsBulkModal.flow;
|
|
||||||
}
|
|
||||||
newClient.reset = clientsBulkModal.reset;
|
newClient.reset = clientsBulkModal.reset;
|
||||||
clients.push(newClient);
|
clients.push(newClient);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,12 +104,6 @@
|
||||||
</a-textarea>
|
</a-textarea>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item v-if="inbound.stream.isXtls" label='Flow'>
|
|
||||||
<a-select v-model="client.flow" :dropdown-class-name="themeSwitcher.currentTheme">
|
|
||||||
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
|
|
||||||
<a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item v-if="inbound.canEnableTlsFlow()" label='Flow'>
|
<a-form-item v-if="inbound.canEnableTlsFlow()" label='Flow'>
|
||||||
<a-select v-model="client.flow" :dropdown-class-name="themeSwitcher.currentTheme">
|
<a-select v-model="client.flow" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
|
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
|
||||||
|
|
|
@ -5,18 +5,7 @@
|
||||||
<a-form-item label='{{ i18n "security" }}'>
|
<a-form-item label='{{ i18n "security" }}'>
|
||||||
<a-radio-group v-model="inbound.stream.security" button-style="solid">
|
<a-radio-group v-model="inbound.stream.security" button-style="solid">
|
||||||
<a-radio-button value="none">{{ i18n "none" }}</a-radio-button>
|
<a-radio-button value="none">{{ i18n "none" }}</a-radio-button>
|
||||||
<a-tooltip>
|
<a-radio-button v-if="inbound.canEnableReality()" value="reality">Reality</a-radio-button>
|
||||||
<template slot="title">
|
|
||||||
<span>{{ i18n "pages.inbounds.xtlsDesc" }}</span>
|
|
||||||
</template>
|
|
||||||
<a-radio-button v-if="inbound.canEnableXtls()" value="xtls">XTLS</a-radio-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
|
||||||
<template slot="title">
|
|
||||||
<span>{{ i18n "pages.inbounds.realityDesc" }}</span>
|
|
||||||
</template>
|
|
||||||
<a-radio-button v-if="inbound.canEnableReality()" value="reality">REALITY</a-radio-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-radio-button value="tls">TLS</a-radio-button>
|
<a-radio-button value="tls">TLS</a-radio-button>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
@ -116,11 +105,6 @@
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- xtls settings -->
|
|
||||||
<template v-else-if="inbound.stream.isXtls">
|
|
||||||
{{template "form/xtlsSettings"}}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- reality settings -->
|
<!-- reality settings -->
|
||||||
<template v-if="inbound.stream.isReality">
|
<template v-if="inbound.stream.isReality">
|
||||||
{{template "form/realitySettings"}}
|
{{template "form/realitySettings"}}
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
{{define "form/xtlsSettings"}}
|
|
||||||
<template>
|
|
||||||
<a-form-item label="SNI" placeholder="Server Name Indication">
|
|
||||||
<a-input v-model.trim="inbound.stream.xtls.sni"></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="ALPN">
|
|
||||||
<a-select mode="multiple" :dropdown-class-name="themeSwitcher.currentTheme" v-model="inbound.stream.xtls.alpn">
|
|
||||||
<a-select-option v-for="alpn in ALPN_OPTION" :value="alpn">[[ alpn ]]</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="Allow Insecure">
|
|
||||||
<a-switch v-model="inbound.stream.xtls.settings.allowInsecure"></a-switch>
|
|
||||||
</a-form-item>
|
|
||||||
<template v-for="cert,index in inbound.stream.xtls.certs">
|
|
||||||
<a-form-item label='{{ i18n "certificate" }}'>
|
|
||||||
<a-radio-group v-model="cert.useFile" button-style="solid">
|
|
||||||
<a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button>
|
|
||||||
<a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button>
|
|
||||||
</a-radio-group>
|
|
||||||
<a-button icon="plus" v-if="index === 0" type="primary" size="small" @click="inbound.stream.xtls.addCert()"
|
|
||||||
style="margin-left: 10px"></a-button>
|
|
||||||
<a-button icon="minus" v-if="inbound.stream.xtls.certs.length>1" type="primary" size="small"
|
|
||||||
@click="inbound.stream.xtls.removeCert(index)" style="margin-left: 10px"></a-button>
|
|
||||||
</a-form-item>
|
|
||||||
<template v-if="cert.useFile">
|
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.publicKey" }}'>
|
|
||||||
<a-input v-model.trim="cert.certFile"></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.privatekey" }}'>
|
|
||||||
<a-input v-model.trim="cert.keyFile"></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label=" ">
|
|
||||||
<a-button type="primary" icon="import" @click="setDefaultCertXtls(index)">
|
|
||||||
{{ i18n "pages.inbounds.setDefaultCert" }}</a-button>
|
|
||||||
</a-form-item>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.publicKey" }}'>
|
|
||||||
<a-input type="textarea" :rows="3" v-model="cert.cert"></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.privatekey" }}'>
|
|
||||||
<a-input type="textarea" :rows="3" v-model="cert.key"></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</template>
|
|
||||||
<a-form-item label='OCSP stapling'>
|
|
||||||
<a-input-number v-model.number="cert.ocspStapling" :min="0"></a-input-number>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="One Time Loading">
|
|
||||||
<a-switch v-model="cert.oneTimeLoading"></a-switch>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label='Usage Option'>
|
|
||||||
<a-select v-model="cert.usage" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
|
|
||||||
<a-select-option v-for="key in USAGE_OPTION" :value="key">[[ key ]]</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
{{end}}
|
|
|
@ -154,15 +154,6 @@
|
||||||
<a-tag color="orange">{{ i18n "none" }}</a-tag>
|
<a-tag color="orange">{{ i18n "none" }}</a-tag>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-if="infoModal.inbound.xtls">
|
|
||||||
<td>Flow</td>
|
|
||||||
<td v-if="infoModal.clientSettings.flow">
|
|
||||||
<a-tag>[[ infoModal.clientSettings.flow ]]</a-tag>
|
|
||||||
</td>
|
|
||||||
<td v-else>
|
|
||||||
<a-tag color="orange">{{ i18n "none" }}</a-tag>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr v-if="infoModal.clientSettings.password">
|
<tr v-if="infoModal.clientSettings.password">
|
||||||
<td>{{ i18n "password" }}</td>
|
<td>{{ i18n "password" }}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -102,11 +102,6 @@
|
||||||
client.flow = "";
|
client.flow = "";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if ((this.inModal.inbound.protocol == Protocols.VLESS || this.inModal.inbound.protocol == Protocols.TROJAN) && !inModal.inbound.xtls) {
|
|
||||||
this.inModal.inbound.settings.vlesses.forEach(client => {
|
|
||||||
client.flow = "";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
SSMethodChange() {
|
SSMethodChange() {
|
||||||
if (this.inModal.inbound.isSSMultiUser) {
|
if (this.inModal.inbound.isSSMultiUser) {
|
||||||
|
@ -132,10 +127,6 @@
|
||||||
inModal.inbound.stream.tls.certs[index].certFile = app.defaultCert;
|
inModal.inbound.stream.tls.certs[index].certFile = app.defaultCert;
|
||||||
inModal.inbound.stream.tls.certs[index].keyFile = app.defaultKey;
|
inModal.inbound.stream.tls.certs[index].keyFile = app.defaultKey;
|
||||||
},
|
},
|
||||||
setDefaultCertXtls(index) {
|
|
||||||
inModal.inbound.stream.xtls.certs[index].certFile = app.defaultCert;
|
|
||||||
inModal.inbound.stream.xtls.certs[index].keyFile = app.defaultKey;
|
|
||||||
},
|
|
||||||
async getNewX25519Cert() {
|
async getNewX25519Cert() {
|
||||||
inModal.loading(true);
|
inModal.loading(true);
|
||||||
const msg = await HttpUtil.post('/server/getNewX25519Cert');
|
const msg = await HttpUtil.post('/server/getNewX25519Cert');
|
||||||
|
|
|
@ -338,7 +338,6 @@
|
||||||
<template v-if="dbInbound.isVMess || dbInbound.isVLess || dbInbound.isTrojan || dbInbound.isSS">
|
<template v-if="dbInbound.isVMess || dbInbound.isVLess || dbInbound.isTrojan || dbInbound.isSS">
|
||||||
<a-tag style="margin:0;" color="green">[[ dbInbound.toInbound().stream.network ]]</a-tag>
|
<a-tag style="margin:0;" color="green">[[ dbInbound.toInbound().stream.network ]]</a-tag>
|
||||||
<a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isTls" color="blue">TLS</a-tag>
|
<a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isTls" color="blue">TLS</a-tag>
|
||||||
<a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isXtls" color="blue">XTLS</a-tag>
|
|
||||||
<a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isReality" color="blue">Reality</a-tag>
|
<a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isReality" color="blue">Reality</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "The IPs history log. (to enable inbound after disabling, clear the log)"
|
"IPLimitlogDesc" = "The IPs history log. (to enable inbound after disabling, clear the log)"
|
||||||
"IPLimitlogclear" = "Clear The Log"
|
"IPLimitlogclear" = "Clear The Log"
|
||||||
"setDefaultCert" = "Set Cert from Panel"
|
"setDefaultCert" = "Set Cert from Panel"
|
||||||
"xtlsDesc" = "Xray must be v1.7.5"
|
|
||||||
"realityDesc" = "Xray must be v1.8.0+"
|
|
||||||
"telegramDesc" = "Please provide Telegram Chat ID. (use '/id' command in the bot) or (@userinfobot)"
|
"telegramDesc" = "Please provide Telegram Chat ID. (use '/id' command in the bot) or (@userinfobot)"
|
||||||
"subscriptionDesc" = "To find your subscription URL, navigate to the 'Details'. Additionally, you can use the same name for several clients."
|
"subscriptionDesc" = "To find your subscription URL, navigate to the 'Details'. Additionally, you can use the same name for several clients."
|
||||||
"info" = "Info"
|
"info" = "Info"
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "Registro de historial de IPs (antes de habilitar la entrada después de que haya sido desactivada por el límite de IP, debes borrar el registro)."
|
"IPLimitlogDesc" = "Registro de historial de IPs (antes de habilitar la entrada después de que haya sido desactivada por el límite de IP, debes borrar el registro)."
|
||||||
"IPLimitlogclear" = "Limpiar el Registro"
|
"IPLimitlogclear" = "Limpiar el Registro"
|
||||||
"setDefaultCert" = "Establecer certificado desde el panel"
|
"setDefaultCert" = "Establecer certificado desde el panel"
|
||||||
"xtlsDesc" = "La versión del núcleo de Xray debe ser 1.7.5"
|
|
||||||
"realityDesc" = "La versión del núcleo de Xray debe ser 1.8.0 o superior."
|
|
||||||
"telegramDesc" = "Por favor, proporciona el ID de Chat de Telegram. (usa el comando '/id' en el bot) o (@userinfobot)"
|
"telegramDesc" = "Por favor, proporciona el ID de Chat de Telegram. (usa el comando '/id' en el bot) o (@userinfobot)"
|
||||||
"subscriptionDesc" = "Puedes encontrar tu enlace de suscripción en Detalles, también puedes usar el mismo nombre para varias configuraciones."
|
"subscriptionDesc" = "Puedes encontrar tu enlace de suscripción en Detalles, también puedes usar el mismo nombre para varias configuraciones."
|
||||||
"info" = "Info"
|
"info" = "Info"
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "گزارش تاریخچه آیپی. برای فعال کردن ورودی پس از غیرفعال شدن، گزارش را پاک کنید"
|
"IPLimitlogDesc" = "گزارش تاریخچه آیپی. برای فعال کردن ورودی پس از غیرفعال شدن، گزارش را پاک کنید"
|
||||||
"IPLimitlogclear" = "پاک کردن گزارشها"
|
"IPLimitlogclear" = "پاک کردن گزارشها"
|
||||||
"setDefaultCert" = "استفاده از گواهی پنل"
|
"setDefaultCert" = "استفاده از گواهی پنل"
|
||||||
"xtlsDesc" = "ایکسری باید 1.7.5 باشد"
|
|
||||||
"realityDesc" = "ایکسری باید +1.8.0 باشد"
|
|
||||||
"telegramDesc" = "لطفا شناسه گفتگوی تلگرام را وارد کنید. (از دستور '/id' در ربات استفاده کنید) یا (@userinfobot)"
|
"telegramDesc" = "لطفا شناسه گفتگوی تلگرام را وارد کنید. (از دستور '/id' در ربات استفاده کنید) یا (@userinfobot)"
|
||||||
"subscriptionDesc" = "شما میتوانید لینک سابسکربپشن خودرا در 'جزئیات' پیدا کنید، همچنین میتوانید از همین نام برای چندین کاربر استفادهکنید"
|
"subscriptionDesc" = "شما میتوانید لینک سابسکربپشن خودرا در 'جزئیات' پیدا کنید، همچنین میتوانید از همین نام برای چندین کاربر استفادهکنید"
|
||||||
"info" = "اطلاعات"
|
"info" = "اطلاعات"
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "Log histori IP. (untuk mengaktifkan masuk setelah menonaktifkan, hapus log)"
|
"IPLimitlogDesc" = "Log histori IP. (untuk mengaktifkan masuk setelah menonaktifkan, hapus log)"
|
||||||
"IPLimitlogclear" = "Hapus Log"
|
"IPLimitlogclear" = "Hapus Log"
|
||||||
"setDefaultCert" = "Atur Sertifikat dari Panel"
|
"setDefaultCert" = "Atur Sertifikat dari Panel"
|
||||||
"xtlsDesc" = "Xray harus versi 1.7.5"
|
|
||||||
"realityDesc" = "Xray harus versi 1.8.0+"
|
|
||||||
"telegramDesc" = "Harap berikan ID Obrolan Telegram. (gunakan perintah '/id' di bot) atau (@userinfobot)"
|
"telegramDesc" = "Harap berikan ID Obrolan Telegram. (gunakan perintah '/id' di bot) atau (@userinfobot)"
|
||||||
"subscriptionDesc" = "Untuk menemukan URL langganan Anda, buka 'Rincian'. Selain itu, Anda dapat menggunakan nama yang sama untuk beberapa klien."
|
"subscriptionDesc" = "Untuk menemukan URL langganan Anda, buka 'Rincian'. Selain itu, Anda dapat menggunakan nama yang sama untuk beberapa klien."
|
||||||
"info" = "Info"
|
"info" = "Info"
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "O histórico de IPs. (para ativar o inbound após a desativação, limpe o log)"
|
"IPLimitlogDesc" = "O histórico de IPs. (para ativar o inbound após a desativação, limpe o log)"
|
||||||
"IPLimitlogclear" = "Limpar o Log"
|
"IPLimitlogclear" = "Limpar o Log"
|
||||||
"setDefaultCert" = "Definir Certificado pelo Painel"
|
"setDefaultCert" = "Definir Certificado pelo Painel"
|
||||||
"xtlsDesc" = "O Xray deve ser v1.7.5"
|
|
||||||
"realityDesc" = "O Xray deve ser v1.8.0+"
|
|
||||||
"telegramDesc" = "Por favor, forneça o ID do Chat do Telegram. (use o comando '/id' no bot) ou (@userinfobot)"
|
"telegramDesc" = "Por favor, forneça o ID do Chat do Telegram. (use o comando '/id' no bot) ou (@userinfobot)"
|
||||||
"subscriptionDesc" = "Para encontrar seu URL de assinatura, navegue até 'Detalhes'. Além disso, você pode usar o mesmo nome para vários clientes."
|
"subscriptionDesc" = "Para encontrar seu URL de assinatura, navegue até 'Detalhes'. Além disso, você pode usar o mesmo nome para vários clientes."
|
||||||
"info" = "Informações"
|
"info" = "Informações"
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "Лог IP-адресов (перед включением лога IP-адресов, вы должны очистить список)"
|
"IPLimitlogDesc" = "Лог IP-адресов (перед включением лога IP-адресов, вы должны очистить список)"
|
||||||
"IPLimitlogclear" = "Очистить лог"
|
"IPLimitlogclear" = "Очистить лог"
|
||||||
"setDefaultCert" = "Установить сертификат с панели"
|
"setDefaultCert" = "Установить сертификат с панели"
|
||||||
"xtlsDesc" = "Версия Xray должна быть не ниже 1.7.5"
|
|
||||||
"realityDesc" = "Версия Xray должна быть не ниже 1.8.0"
|
|
||||||
"telegramDesc" = "Пожалуйста, укажите ID чата Telegram. (используйте команду '/id' в боте) или (@userinfobot)"
|
"telegramDesc" = "Пожалуйста, укажите ID чата Telegram. (используйте команду '/id' в боте) или (@userinfobot)"
|
||||||
"subscriptionDesc" = "Вы можете найти свою ссылку подписки в разделе 'Подробнее', также вы можете использовать одно и то же имя для нескольких конфигураций"
|
"subscriptionDesc" = "Вы можете найти свою ссылку подписки в разделе 'Подробнее', также вы можете использовать одно и то же имя для нескольких конфигураций"
|
||||||
"info" = "Информация"
|
"info" = "Информация"
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "IP geçmiş günlüğü. (devre dışı bırakıldıktan sonra gelini etkinleştirmek için günlüğü temizleyin)"
|
"IPLimitlogDesc" = "IP geçmiş günlüğü. (devre dışı bırakıldıktan sonra gelini etkinleştirmek için günlüğü temizleyin)"
|
||||||
"IPLimitlogclear" = "Günlüğü Temizle"
|
"IPLimitlogclear" = "Günlüğü Temizle"
|
||||||
"setDefaultCert" = "Panelden Sertifikayı Ayarla"
|
"setDefaultCert" = "Panelden Sertifikayı Ayarla"
|
||||||
"xtlsDesc" = "Xray v1.7.5 olmalıdır"
|
|
||||||
"realityDesc" = "Xray v1.8.0+ olmalıdır"
|
|
||||||
"telegramDesc" = "Lütfen Telegram Sohbet Kimliği sağlayın. (botta '/id' komutunu kullanın) veya (@userinfobot)"
|
"telegramDesc" = "Lütfen Telegram Sohbet Kimliği sağlayın. (botta '/id' komutunu kullanın) veya (@userinfobot)"
|
||||||
"subscriptionDesc" = "Abonelik URL'inizi bulmak için 'Detaylar'a gidin. Ayrıca, aynı adı birden fazla müşteri için kullanabilirsiniz."
|
"subscriptionDesc" = "Abonelik URL'inizi bulmak için 'Detaylar'a gidin. Ayrıca, aynı adı birden fazla müşteri için kullanabilirsiniz."
|
||||||
"info" = "Bilgi"
|
"info" = "Bilgi"
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "Журнал історії IP-адрес. (щоб увімкнути вхідну після вимкнення, очистіть журнал)"
|
"IPLimitlogDesc" = "Журнал історії IP-адрес. (щоб увімкнути вхідну після вимкнення, очистіть журнал)"
|
||||||
"IPLimitlogclear" = "Очистити журнал"
|
"IPLimitlogclear" = "Очистити журнал"
|
||||||
"setDefaultCert" = "Установити сертифікат з панелі"
|
"setDefaultCert" = "Установити сертифікат з панелі"
|
||||||
"xtlsDesc" = "Xray має бути v1.7.5"
|
|
||||||
"realityDesc" = "Xray має бути v1.8.0+"
|
|
||||||
"telegramDesc" = "Будь ласка, вкажіть ID чату Telegram. (використовуйте команду '/id' у боті) або (@userinfobot)"
|
"telegramDesc" = "Будь ласка, вкажіть ID чату Telegram. (використовуйте команду '/id' у боті) або (@userinfobot)"
|
||||||
"subscriptionDesc" = "Щоб знайти URL-адресу вашої підписки, перейдіть до «Деталі». Крім того, ви можете використовувати одне ім'я для кількох клієнтів."
|
"subscriptionDesc" = "Щоб знайти URL-адресу вашої підписки, перейдіть до «Деталі». Крім того, ви можете використовувати одне ім'я для кількох клієнтів."
|
||||||
"info" = "Інформація"
|
"info" = "Інформація"
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "Lịch sử đăng nhập IP (trước khi kích hoạt điểm vào sau khi bị vô hiệu hóa bởi giới hạn IP, bạn nên xóa lịch sử)."
|
"IPLimitlogDesc" = "Lịch sử đăng nhập IP (trước khi kích hoạt điểm vào sau khi bị vô hiệu hóa bởi giới hạn IP, bạn nên xóa lịch sử)."
|
||||||
"IPLimitlogclear" = "Xóa Lịch sử"
|
"IPLimitlogclear" = "Xóa Lịch sử"
|
||||||
"setDefaultCert" = "Đặt chứng chỉ từ bảng điều khiển"
|
"setDefaultCert" = "Đặt chứng chỉ từ bảng điều khiển"
|
||||||
"xtlsDesc" = "Xray core cần phiên bản 1.7.5"
|
|
||||||
"realityDesc" = "Xray core cần phiên bản 1.8.0 hoặc cao hơn."
|
|
||||||
"telegramDesc" = "Vui lòng cung cấp ID Trò chuyện Telegram. (sử dụng lệnh '/id' trong bot) hoặc (@userinfobot)"
|
"telegramDesc" = "Vui lòng cung cấp ID Trò chuyện Telegram. (sử dụng lệnh '/id' trong bot) hoặc (@userinfobot)"
|
||||||
"subscriptionDesc" = "Bạn có thể tìm liên kết gói đăng ký của mình trong Chi tiết, cũng như bạn có thể sử dụng cùng tên cho nhiều cấu hình khác nhau"
|
"subscriptionDesc" = "Bạn có thể tìm liên kết gói đăng ký của mình trong Chi tiết, cũng như bạn có thể sử dụng cùng tên cho nhiều cấu hình khác nhau"
|
||||||
"info" = "Thông tin"
|
"info" = "Thông tin"
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "IP 历史日志(要启用被禁用的入站流量,请清除日志)"
|
"IPLimitlogDesc" = "IP 历史日志(要启用被禁用的入站流量,请清除日志)"
|
||||||
"IPLimitlogclear" = "清除日志"
|
"IPLimitlogclear" = "清除日志"
|
||||||
"setDefaultCert" = "从面板设置证书"
|
"setDefaultCert" = "从面板设置证书"
|
||||||
"xtlsDesc" = "Xray 核心需要 1.7.5"
|
|
||||||
"realityDesc" = "Xray 核心需要 1.8.0 及以上版本"
|
|
||||||
"telegramDesc" = "请提供Telegram聊天ID。(在机器人中使用'/id'命令)或(@userinfobot"
|
"telegramDesc" = "请提供Telegram聊天ID。(在机器人中使用'/id'命令)或(@userinfobot"
|
||||||
"subscriptionDesc" = "要找到你的订阅 URL,请导航到“详细信息”。此外,你可以为多个客户端使用相同的名称。"
|
"subscriptionDesc" = "要找到你的订阅 URL,请导航到“详细信息”。此外,你可以为多个客户端使用相同的名称。"
|
||||||
"info" = "信息"
|
"info" = "信息"
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
"IPLimitlogDesc" = "IP 歷史日誌(要啟用被禁用的入站流量,請清除日誌)"
|
"IPLimitlogDesc" = "IP 歷史日誌(要啟用被禁用的入站流量,請清除日誌)"
|
||||||
"IPLimitlogclear" = "清除日誌"
|
"IPLimitlogclear" = "清除日誌"
|
||||||
"setDefaultCert" = "從面板設定證書"
|
"setDefaultCert" = "從面板設定證書"
|
||||||
"xtlsDesc" = "Xray 核心需要 1.7.5"
|
|
||||||
"realityDesc" = "Xray 核心需要 1.8.0 及以上版本"
|
|
||||||
"telegramDesc" = "請提供Telegram聊天ID。(在機器人中使用'/id'命令)或(@userinfobot"
|
"telegramDesc" = "請提供Telegram聊天ID。(在機器人中使用'/id'命令)或(@userinfobot"
|
||||||
"subscriptionDesc" = "要找到你的訂閱 URL,請導航到“詳細資訊”。此外,你可以為多個客戶端使用相同的名稱。"
|
"subscriptionDesc" = "要找到你的訂閱 URL,請導航到“詳細資訊”。此外,你可以為多個客戶端使用相同的名稱。"
|
||||||
"info" = "資訊"
|
"info" = "資訊"
|
||||||
|
|
Loading…
Reference in a new issue