mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-03-01 01:20:49 +03:00
Reality
This commit is contained in:
parent
38c318737b
commit
abb79bd978
@ -91,6 +91,9 @@ const UTLS_FINGERPRINT = {
|
|||||||
UTLS_RANDOMIZED: "randomized",
|
UTLS_RANDOMIZED: "randomized",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const bytesToHex = e => Array.from(e).map(e => e.toString(16).padStart(2, 0)).join('');
|
||||||
|
const hexToBytes = e => new Uint8Array(e.match(/[0-9a-f]{2}/gi).map(e => parseInt(e, 16)));
|
||||||
|
|
||||||
const ALPN_OPTION = {
|
const ALPN_OPTION = {
|
||||||
H3: "h3",
|
H3: "h3",
|
||||||
H2: "h2",
|
H2: "h2",
|
||||||
@ -596,10 +599,62 @@ TlsStreamSettings.Settings = class extends XrayCommonClass {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RealityStreamSettings extends XrayCommonClass {
|
||||||
|
constructor(show = false,xver = 0, fingerprint = UTLS_FINGERPRINT.UTLS_FIREFOX, dest = 'github.io:443', serverNames = 'github.io,www.github.io,', privateKey = RandomUtil.randomX25519PrivateKey(), publicKey = '', minClient = '',
|
||||||
|
maxClient = '', maxTimediff = 0, shortIds = RandomUtil.randowShortId()) {
|
||||||
|
super();
|
||||||
|
this.show = show;
|
||||||
|
this.xver = xver;
|
||||||
|
this.fingerprint = fingerprint;
|
||||||
|
this.dest = dest;
|
||||||
|
this.serverNames = serverNames instanceof Array ? serverNames.join(",") : serverNames;
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
this.publicKey = RandomUtil.randomX25519PublicKey(this.privateKey);
|
||||||
|
this.minClient = minClient;
|
||||||
|
this.maxClient = maxClient;
|
||||||
|
this.maxTimediff = maxTimediff;
|
||||||
|
this.shortIds = shortIds instanceof Array ? shortIds.join(",") : shortIds;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJson(json = {}) {
|
||||||
|
return new RealityStreamSettings(
|
||||||
|
json.show,
|
||||||
|
json.xver,
|
||||||
|
json.fingerprint,
|
||||||
|
json.dest,
|
||||||
|
json.serverNames,
|
||||||
|
json.privateKey,
|
||||||
|
json.publicKey,
|
||||||
|
json.minClient,
|
||||||
|
json.maxClient,
|
||||||
|
json.maxTimediff,
|
||||||
|
json.shortIds
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
toJson() {
|
||||||
|
return {
|
||||||
|
show: this.show,
|
||||||
|
xver: this.xver,
|
||||||
|
fingerprint: this.fingerprint,
|
||||||
|
dest: this.dest,
|
||||||
|
serverNames: this.serverNames.split(/,|,|\s+/),
|
||||||
|
privateKey: this.privateKey,
|
||||||
|
publicKey: this.publicKey,
|
||||||
|
minClient: this.minClient,
|
||||||
|
maxClient: this.maxClient,
|
||||||
|
maxTimediff: this.maxTimediff,
|
||||||
|
shortIds: this.shortIds.split(/,|,|\s+/)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class StreamSettings extends XrayCommonClass {
|
class StreamSettings extends XrayCommonClass {
|
||||||
constructor(network='tcp',
|
constructor(network='tcp',
|
||||||
security='none',
|
security='none',
|
||||||
tlsSettings=new TlsStreamSettings(),
|
tlsSettings=new TlsStreamSettings(),
|
||||||
|
realitySettings = new RealityStreamSettings(),
|
||||||
tcpSettings=new TcpStreamSettings(),
|
tcpSettings=new TcpStreamSettings(),
|
||||||
kcpSettings=new KcpStreamSettings(),
|
kcpSettings=new KcpStreamSettings(),
|
||||||
wsSettings=new WsStreamSettings(),
|
wsSettings=new WsStreamSettings(),
|
||||||
@ -611,6 +666,7 @@ class StreamSettings extends XrayCommonClass {
|
|||||||
this.network = network;
|
this.network = network;
|
||||||
this.security = security;
|
this.security = security;
|
||||||
this.tls = tlsSettings;
|
this.tls = tlsSettings;
|
||||||
|
this.reality = realitySettings;
|
||||||
this.tcp = tcpSettings;
|
this.tcp = tcpSettings;
|
||||||
this.kcp = kcpSettings;
|
this.kcp = kcpSettings;
|
||||||
this.ws = wsSettings;
|
this.ws = wsSettings;
|
||||||
@ -643,17 +699,34 @@ class StreamSettings extends XrayCommonClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
//for Reality
|
||||||
let tls;
|
get isReality() {
|
||||||
if (json.security === "xtls") {
|
return this.security === "reality";
|
||||||
tls = TlsStreamSettings.fromJson(json.XTLSSettings);
|
}
|
||||||
|
|
||||||
|
set isReality(isReality) {
|
||||||
|
if (isReality) {
|
||||||
|
this.security = "reality";
|
||||||
} else {
|
} else {
|
||||||
|
this.security = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJson(json = {}) {
|
||||||
|
let tls, reality;
|
||||||
|
if (json.security === "xtls") {
|
||||||
|
tls = TlsStreamSettings.fromJson(json.xtlsSettings);
|
||||||
|
} else if (json.security === "tls") {
|
||||||
tls = TlsStreamSettings.fromJson(json.tlsSettings);
|
tls = TlsStreamSettings.fromJson(json.tlsSettings);
|
||||||
}
|
}
|
||||||
|
if (json.security === "reality") {
|
||||||
|
reality = RealityStreamSettings.fromJson(json.realitySettings)
|
||||||
|
}
|
||||||
return new StreamSettings(
|
return new StreamSettings(
|
||||||
json.network,
|
json.network,
|
||||||
json.security,
|
json.security,
|
||||||
tls,
|
tls,
|
||||||
|
reality,
|
||||||
TcpStreamSettings.fromJson(json.tcpSettings),
|
TcpStreamSettings.fromJson(json.tcpSettings),
|
||||||
KcpStreamSettings.fromJson(json.kcpSettings),
|
KcpStreamSettings.fromJson(json.kcpSettings),
|
||||||
WsStreamSettings.fromJson(json.wsSettings),
|
WsStreamSettings.fromJson(json.wsSettings),
|
||||||
@ -671,6 +744,7 @@ class StreamSettings extends XrayCommonClass {
|
|||||||
tlsSettings: this.isTls ? this.tls.toJson() : undefined,
|
tlsSettings: this.isTls ? this.tls.toJson() : undefined,
|
||||||
XTLSSettings: this.isXTLS ? this.tls.toJson() : undefined,
|
XTLSSettings: this.isXTLS ? this.tls.toJson() : undefined,
|
||||||
tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined,
|
tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined,
|
||||||
|
realitySettings: this.isReality ? this.reality.toJson() : undefined,
|
||||||
kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
|
kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
|
||||||
wsSettings: network === 'ws' ? this.ws.toJson() : undefined,
|
wsSettings: network === 'ws' ? this.ws.toJson() : undefined,
|
||||||
httpSettings: network === 'http' ? this.http.toJson() : undefined,
|
httpSettings: network === 'http' ? this.http.toJson() : undefined,
|
||||||
@ -743,6 +817,8 @@ class Inbound extends XrayCommonClass {
|
|||||||
|
|
||||||
set tls(isTls) {
|
set tls(isTls) {
|
||||||
if (isTls) {
|
if (isTls) {
|
||||||
|
this.xtls = false;
|
||||||
|
this.reality = false;
|
||||||
this.stream.security = 'tls';
|
this.stream.security = 'tls';
|
||||||
} else {
|
} else {
|
||||||
this.stream.security = 'none';
|
this.stream.security = 'none';
|
||||||
@ -755,12 +831,32 @@ class Inbound extends XrayCommonClass {
|
|||||||
|
|
||||||
set XTLS(isXTLS) {
|
set XTLS(isXTLS) {
|
||||||
if (isXTLS) {
|
if (isXTLS) {
|
||||||
|
this.xtls = false;
|
||||||
|
this.reality = false;
|
||||||
this.stream.security = 'xtls';
|
this.stream.security = 'xtls';
|
||||||
} else {
|
} else {
|
||||||
this.stream.security = 'none';
|
this.stream.security = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//for Reality
|
||||||
|
get reality() {
|
||||||
|
if (this.stream.security === "reality") {
|
||||||
|
return this.network === "tcp" || this.network === "grpc" || this.network === "http";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
set reality(isReality) {
|
||||||
|
if (isReality) {
|
||||||
|
this.tls = false;
|
||||||
|
this.xtls = false;
|
||||||
|
this.stream.security = "reality";
|
||||||
|
} else {
|
||||||
|
this.stream.security = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get network() {
|
get network() {
|
||||||
return this.stream.network;
|
return this.stream.network;
|
||||||
}
|
}
|
||||||
@ -957,9 +1053,19 @@ class Inbound extends XrayCommonClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canEnableReality() {
|
||||||
|
switch (this.protocol) {
|
||||||
|
case Protocols.VLESS:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.network === "tcp" || this.network === "grpc" || this.network === "http";
|
||||||
|
}
|
||||||
|
|
||||||
//this is used for xtls-rprx-vision
|
//this is used for xtls-rprx-vision
|
||||||
canEnableTlsFlow() {
|
canEnableTlsFlow() {
|
||||||
if ((this.stream.security === 'tls') && (this.network === "tcp")) {
|
if (((this.stream.security === 'tls') || (this.stream.security === 'reality')) && (this.network === "tcp")) {
|
||||||
switch (this.protocol) {
|
switch (this.protocol) {
|
||||||
case Protocols.VLESS:
|
case Protocols.VLESS:
|
||||||
return true;
|
return true;
|
||||||
@ -1169,6 +1275,26 @@ class Inbound extends XrayCommonClass {
|
|||||||
params.set("flow", this.settings.vlesses[clientIndex].flow);
|
params.set("flow", this.settings.vlesses[clientIndex].flow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.reality) {
|
||||||
|
params.set("security", "reality");
|
||||||
|
if (!ObjectUtil.isArrEmpty(this.stream.reality.serverNames)) {
|
||||||
|
params.set("sni", this.stream.reality.serverNames.split(/,|,|\s+/)[0]);
|
||||||
|
}
|
||||||
|
if (this.stream.reality.publicKey != "") {
|
||||||
|
//params.set("pbk", Ed25519.getPublicKey(this.stream.reality.privateKey));
|
||||||
|
params.set("pbk", this.stream.reality.publicKey);
|
||||||
|
}
|
||||||
|
if (this.stream.network === 'tcp') {
|
||||||
|
params.set("flow", this.settings.vlesses[clientIndex].flow);
|
||||||
|
}
|
||||||
|
if (this.stream.reality.shortIds != "") {
|
||||||
|
params.set("sid", this.stream.reality.shortIds);
|
||||||
|
}
|
||||||
|
if (this.stream.reality.fingerprint != "") {
|
||||||
|
params.set("fp", this.stream.reality.fingerprint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const link = `vless://${uuid}@${address}:${port}`;
|
const link = `vless://${uuid}@${address}:${port}`;
|
||||||
const url = new URL(link);
|
const url = new URL(link);
|
||||||
for (const [key, value] of params) {
|
for (const [key, value] of params) {
|
||||||
|
@ -89,6 +89,31 @@ const seq = [
|
|||||||
'U', 'V', 'W', 'X', 'Y', 'Z'
|
'U', 'V', 'W', 'X', 'Y', 'Z'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const shortIdSeq = [
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
];
|
||||||
|
|
||||||
|
const x25519Map = new Map(
|
||||||
|
[
|
||||||
|
['EH2FWe-Ij_FFAa2u9__-aiErLvVIneP601GOCdlyPWw', "goY3OtfaA4UYbiz7Hn0NysI5QJrK0VT_Chg6RLgUPQU"],
|
||||||
|
['cKI_6DoMSP1IepeWWXrG3G9nkehl94KYBhagU50g2U0', "VigpKFbSLnHLzBWobZaS1IBmw--giJ51w92y723ajnU"],
|
||||||
|
['qM2SNyK3NyHB6deWpEP3ITyCGKQFRTna_mlKP0w1QH0', "HYyIGuyNFslmcnNT7mrDdmuXwn4cm7smE_FZbYguKHQ"],
|
||||||
|
['qCWg5GMEDFd3n1nxDswlIpOHoPUXMLuMOIiLUVzubkI', "rJFC3dUjJxMnVZiUGzmf_LFsJUwFWY-CU5RQgFOHCWM"],
|
||||||
|
['4NOBxDrEsOhNI3Y3EnVIy_TN-uyBoAjQw6QM0YsOi0s', "CbcY9qc4YuMDJDyyL0OITlU824TBg1O84ClPy27e2RM"],
|
||||||
|
['eBvFb0M4HpSOwWjtXV8zliiEs_hg56zX4a2LpuuqpEI', "CjulQ2qVIky7ImIfysgQhNX7s_drGLheCGSkVHcLZhc"],
|
||||||
|
['yEpOzQV04NNcycWVeWtRNTzv5TS-ynTuKRacZCH-6U8', "O9RSr5gSdok2K_tobQnf_scyKVqnCx6C4Jrl7_rCZEQ"],
|
||||||
|
['CNt6TAUVCwqM6xIBHyni0K3Zqbn2htKQLvLb6XDgh0s', "d9cGLVBrDFS02L2OvkqyqwFZ1Ux3AHs28ehl4Rwiyl0"],
|
||||||
|
['EInKw-6Wr0rAHXlxxDuZU5mByIzcD3Z-_iWPzXlUL1k', "LlYD2nNVAvyjNvjZGZh4R8PkMIwkc6EycPTvR2LE0nQ"],
|
||||||
|
['GKIKo7rcXVyle-EUHtGIDtYnDsI6osQmOUl3DTJRAGc', "VcqHivYGGoBkcxOI6cSSjQmneltstkb2OhvO53dyhEM"],
|
||||||
|
['-FVDzv68IC17fJVlNDlhrrgX44WeBfbhwjWpCQVXGHE', "PGG2EYOvsFt2lAQTD7lqHeRxz2KxvllEDKcUrtizPBU"],
|
||||||
|
['0H3OJEYEu6XW7woqy7cKh2vzg6YHkbF_xSDTHKyrsn4', "mzevpYbS8kXengBY5p7tt56QE4tS3lwlwRemmkcQeyc"],
|
||||||
|
['8F8XywN6ci44ES6em2Z0fYYxyptB9uaXY9Hc1WSSPE4', "qCZUdWQZ2H33vWXnOkG8NpxBeq3qn5QWXlfCOWBNkkc"],
|
||||||
|
['IN0dqfkC10dj-ifRHrg2PmmOrzYs697ajGMwcLbu-1g', "2UW_EO3r7uczPGUUlpJBnMDpDmWUHE2yDzCmXS4sckE"],
|
||||||
|
['uIcmks5rAhvBe4dRaJOdeSqgxLGGMZhsGk4J4PEKL2s', "F9WJV_74IZp0Ide4hWjiJXk9FRtBUBkUr3mzU-q1lzk"],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
class RandomUtil {
|
class RandomUtil {
|
||||||
|
|
||||||
static randomIntRange(min, max) {
|
static randomIntRange(min, max) {
|
||||||
@ -107,6 +132,14 @@ class RandomUtil {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static randomShortIdSeq(count) {
|
||||||
|
let str = '';
|
||||||
|
for (let i = 0; i < count; ++i) {
|
||||||
|
str += shortIdSeq[this.randomInt(16)];
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
static randomLowerAndNum(count) {
|
static randomLowerAndNum(count) {
|
||||||
let str = '';
|
let str = '';
|
||||||
for (let i = 0; i < count; ++i) {
|
for (let i = 0; i < count; ++i) {
|
||||||
@ -137,6 +170,26 @@ class RandomUtil {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static randowShortId() {
|
||||||
|
let str = '';
|
||||||
|
str += this.randomShortIdSeq(8)
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static randomX25519PrivateKey() {
|
||||||
|
let num = x25519Map.size;
|
||||||
|
let index = this.randomInt(num);
|
||||||
|
let cntr = 0;
|
||||||
|
for (let key of x25519Map.keys()) {
|
||||||
|
if (cntr++ === index) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static randomX25519PublicKey(key) {
|
||||||
|
return x25519Map.get(key)
|
||||||
|
}
|
||||||
static randomText() {
|
static randomText() {
|
||||||
var chars = 'abcdefghijklmnopqrstuvwxyz1234567890';
|
var chars = 'abcdefghijklmnopqrstuvwxyz1234567890';
|
||||||
var string = '';
|
var string = '';
|
||||||
|
@ -1,11 +1,32 @@
|
|||||||
{{define "form/tlsSettings"}}
|
{{define "form/tlsSettings"}}
|
||||||
<!-- tls enable -->
|
<!-- tls enable -->
|
||||||
<a-form layout="inline" v-if="inbound.canSetTls()">
|
<a-form layout="inline" v-if="inbound.canSetTls()">
|
||||||
<a-form-item label="TLS">
|
<a-form-item v-if="inbound.canEnableTls()" label="TLS">
|
||||||
<a-switch v-model="inbound.tls">
|
<a-switch v-model="inbound.tls">
|
||||||
</a-switch>
|
</a-switch>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item v-if="inbound.canEnableXTLS()" label="XTLS">
|
<a-form-item v-if="inbound.canEnableReality()">
|
||||||
|
<span slot="label">
|
||||||
|
Reality
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.Realitydec" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</span>
|
||||||
|
<a-switch v-model="inbound.reality"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-if="inbound.canEnableXTLS()">
|
||||||
|
<span slot="label">
|
||||||
|
XTLS
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.XTLSdec" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</span>
|
||||||
<a-switch v-model="inbound.XTLS"></a-switch>
|
<a-switch v-model="inbound.XTLS"></a-switch>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
@ -72,4 +93,33 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
<a-form v-else-if="inbound.reality" layout="inline">
|
||||||
|
<a-form-item label="show">
|
||||||
|
<a-switch v-model="inbound.stream.reality.show">
|
||||||
|
</a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="xver">
|
||||||
|
<a-input type="number" v-model.number="inbound.stream.reality.xver" :min="0" style="width: 60px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="uTLS" >
|
||||||
|
<a-select v-model="inbound.stream.reality.fingerprint" style="width: 135px">
|
||||||
|
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="dest">
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.dest" style="width: 360px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="serverNames">
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.serverNames" style="width: 360px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="privateKey">
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.privateKey" style="width: 360px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="publicKey">
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.publicKey" style="width: 360px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="shortIds">
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.shortIds"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
@ -134,6 +134,7 @@
|
|||||||
<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="cyan">TLS</a-tag>
|
<a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isTls" color="cyan">TLS</a-tag>
|
||||||
<a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isXTLS" color="cyan">XTLS</a-tag>
|
<a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isXTLS" color="cyan">XTLS</a-tag>
|
||||||
|
<a-tag style="margin:0;" v-if="dbInbound.toInbound().stream.isReality" color="cyan">Reality</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template slot="clients" slot-scope="text, dbInbound">
|
<template slot="clients" slot-scope="text, dbInbound">
|
||||||
@ -239,7 +240,7 @@
|
|||||||
}, {
|
}, {
|
||||||
title: '{{ i18n "pages.inbounds.protocol" }}',
|
title: '{{ i18n "pages.inbounds.protocol" }}',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 70,
|
width: 80,
|
||||||
scopedSlots: { customRender: 'protocol' },
|
scopedSlots: { customRender: 'protocol' },
|
||||||
}, {
|
}, {
|
||||||
title: '{{ i18n "clients" }}',
|
title: '{{ i18n "clients" }}',
|
||||||
|
@ -152,6 +152,8 @@
|
|||||||
"IPLimitlogDesc" = "IPs history Log (before enabling inbound after it has been disabled by IP limit, you should clear the log)"
|
"IPLimitlogDesc" = "IPs history Log (before enabling inbound after it has been disabled by IP limit, you should clear the log)"
|
||||||
"IPLimitlogclear" = "Clear The Log"
|
"IPLimitlogclear" = "Clear The Log"
|
||||||
"setDefaultCert" = "Set cert from panel"
|
"setDefaultCert" = "Set cert from panel"
|
||||||
|
"XTLSdec" = "Xray core needs to be 1.7.5 and below"
|
||||||
|
"Realitydec" = "Xray core needs to be 1.8.0 and above"
|
||||||
|
|
||||||
[pages.client]
|
[pages.client]
|
||||||
"add" = "Add client"
|
"add" = "Add client"
|
||||||
|
@ -150,6 +150,8 @@
|
|||||||
"IPLimitlogDesc" = "گزارش سابقه ای پی (قبل از فعال کردن ورودی پس از غیرفعال شدن توسط محدودیت ای پی، باید گزارش را پاک کنید)"
|
"IPLimitlogDesc" = "گزارش سابقه ای پی (قبل از فعال کردن ورودی پس از غیرفعال شدن توسط محدودیت ای پی، باید گزارش را پاک کنید)"
|
||||||
"IPLimitlogclear" = "پاک کردن گزارش ها"
|
"IPLimitlogclear" = "پاک کردن گزارش ها"
|
||||||
"setDefaultCert" = "استفاده از گواهی پنل"
|
"setDefaultCert" = "استفاده از گواهی پنل"
|
||||||
|
"XTLSdec" = "هسته Xray باید 1.7.5 و کمتر باشد"
|
||||||
|
"Realitydec" = "هسته Xray باید 1.8.0 و بالاتر باشد"
|
||||||
|
|
||||||
[pages.client]
|
[pages.client]
|
||||||
"add" = "کاربر جدید"
|
"add" = "کاربر جدید"
|
||||||
|
@ -150,6 +150,8 @@
|
|||||||
"IPLimitlogDesc" = "IP 历史日志 (通过IP限制禁用inbound之前,需要清空日志)"
|
"IPLimitlogDesc" = "IP 历史日志 (通过IP限制禁用inbound之前,需要清空日志)"
|
||||||
"IPLimitlogclear" = "清除日志"
|
"IPLimitlogclear" = "清除日志"
|
||||||
"setDefaultCert" = "从面板设置证书"
|
"setDefaultCert" = "从面板设置证书"
|
||||||
|
"XTLSdec" = "Xray核心需要1.7.5及以下版本"
|
||||||
|
"Realitydec" = "Xray核心需要1.8.0及以上版本"
|
||||||
|
|
||||||
[pages.client]
|
[pages.client]
|
||||||
"add" = "添加客户端"
|
"add" = "添加客户端"
|
||||||
|
Loading…
Reference in New Issue
Block a user