Compare commits

...

5 Commits

Author SHA1 Message Date
Ho3ein
5db35c32de v1.2.0 2023-04-10 20:00:04 +03:30
MHSanaei
abb79bd978 Reality 2023-04-10 19:58:52 +03:30
Ho3ein
38c318737b v1.1.6 2023-04-10 14:36:24 +03:30
Ho3ein
c1ed6d8454 Merge pull request #187 from MHSanaei/dev
http header bug fixed
2023-04-10 14:35:52 +03:30
MHSanaei
26a0481d82 http header bug fixed 2023-04-10 14:33:50 +03:30
14 changed files with 271 additions and 38 deletions

View File

@@ -1 +1 @@
1.1.5 1.2.0

View File

@@ -92,7 +92,7 @@ func InitDB(dbPath string) error {
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }

View File

@@ -80,7 +80,7 @@ type Client struct {
LimitIP int `json:"limitIp"` LimitIP int `json:"limitIp"`
TotalGB int64 `json:"totalGB" form:"totalGB"` TotalGB int64 `json:"totalGB" form:"totalGB"`
ExpiryTime int64 `json:"expiryTime" form:"expiryTime"` ExpiryTime int64 `json:"expiryTime" form:"expiryTime"`
Enable bool `json:"enable" from:"enable"` Enable bool `json:"enable" form:"enable"`
TgID string `json:"tgId" from:"tgId"` TgID string `json:"tgId" form:"tgId"`
SubID string `json:"subId" from:"subId"` SubID string `json:"subId" form:"subId"`
} }

2
go.mod
View File

@@ -8,6 +8,7 @@ require (
github.com/gin-gonic/gin v1.9.0 github.com/gin-gonic/gin v1.9.0
github.com/go-cmd/cmd v1.4.1 github.com/go-cmd/cmd v1.4.1
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
github.com/goccy/go-json v0.10.0
github.com/nicksnyder/go-i18n/v2 v2.2.1 github.com/nicksnyder/go-i18n/v2 v2.2.1
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pelletier/go-toml/v2 v2.0.7 github.com/pelletier/go-toml/v2 v2.0.7
@@ -30,7 +31,6 @@ require (
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.11.2 // indirect github.com/go-playground/validator/v10 v10.11.2 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect github.com/gorilla/securecookie v1.1.1 // indirect

View File

@@ -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",
@@ -106,7 +109,6 @@ 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);
Object.freeze(UTLS_FINGERPRINT);
Object.freeze(ALPN_OPTION); Object.freeze(ALPN_OPTION);
class XrayCommonClass { class XrayCommonClass {
@@ -177,7 +179,6 @@ class TcpStreamSettings extends XrayCommonClass {
this.type = type; this.type = type;
this.request = request; this.request = request;
this.response = response; this.response = response;
this.acceptProxyProtocol = acceptProxyProtocol;
} }
static fromJson(json={}) { static fromJson(json={}) {
@@ -185,9 +186,8 @@ class TcpStreamSettings extends XrayCommonClass {
if (!header) { if (!header) {
header = {}; header = {};
} }
return new TcpStreamSettings( return new TcpStreamSettings(json.acceptProxyProtocol,
header.type, header.type,
json.acceptProxyProtocol,
TcpStreamSettings.TcpRequest.fromJson(header.request), TcpStreamSettings.TcpRequest.fromJson(header.request),
TcpStreamSettings.TcpResponse.fromJson(header.response), TcpStreamSettings.TcpResponse.fromJson(header.response),
); );
@@ -201,7 +201,6 @@ class TcpStreamSettings extends XrayCommonClass {
request: this.type === 'http' ? this.request.toJson() : undefined, request: this.type === 'http' ? this.request.toJson() : undefined,
response: this.type === 'http' ? this.response.toJson() : undefined, response: this.type === 'http' ? this.response.toJson() : undefined,
}, },
acceptProxyProtocol: this.acceptProxyProtocol,
}; };
} }
} }
@@ -600,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(),
@@ -615,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;
@@ -647,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),
@@ -675,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,
@@ -747,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';
@@ -759,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;
} }
@@ -961,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;
@@ -994,6 +1096,7 @@ class Inbound extends XrayCommonClass {
case Protocols.VMESS: case Protocols.VMESS:
case Protocols.VLESS: case Protocols.VLESS:
case Protocols.TROJAN: case Protocols.TROJAN:
case Protocols.SHADOWSOCKS:
return true; return true;
default: default:
return false; return false;
@@ -1172,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) {

View File

@@ -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 = '';

View File

@@ -32,7 +32,7 @@
<a-input type="number" v-model.number="client.limitIp" min="0" style="width: 70px;" ></a-input> <a-input type="number" v-model.number="client.limitIp" min="0" style="width: 70px;" ></a-input>
</a-form-item> </a-form-item>
<a-form-item v-if="inbound.XTLS" label="Flow"> <a-form-item v-if="inbound.XTLS" label="Flow">
<a-select v-model="client.flow" style="width: 150px"> <a-select v-model="client.flow" style="width: 150px" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
<a-select-option value="">{{ i18n "none" }}</a-select-option> <a-select-option value="">{{ i18n "none" }}</a-select-option>
<a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option> <a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
</a-select> </a-select>

View File

@@ -20,25 +20,25 @@
<a-input v-model.trim="client.id" style="width: 300px;" ></a-input> <a-input v-model.trim="client.id" style="width: 300px;" ></a-input>
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">
<span>{{ i18n "pages.inbounds.IPLimit" }}</span> <span>{{ i18n "pages.inbounds.IPLimit" }}</span>
<a-tooltip> <a-tooltip>
<template slot="title"> <template slot="title">
<span>{{ i18n "pages.inbounds.IPLimitDesc" }}</span> <span>{{ i18n "pages.inbounds.IPLimitDesc" }}</span>
</template> </template>
<a-icon type="question-circle" theme="filled"></a-icon> <a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip> </a-tooltip>
</span> </span>
<a-input type="number" v-model.number="client.limitIp" min="0" style="width: 70px;" ></a-input> <a-input type="number" v-model.number="client.limitIp" min="0" style="width: 70px;" ></a-input>
</a-form-item> </a-form-item>
<a-form-item v-if="inbound.XTLS" label="Flow"> <a-form-item v-if="inbound.XTLS" label="Flow">
<a-select v-model="inbound.settings.vlesses[index].flow" style="width: 150px"> <a-select v-model="inbound.settings.vlesses[index].flow" style="width: 150px" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option> <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-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item v-else-if="inbound.canEnableTlsFlow()" label="Flow" layout="inline"> <a-form-item v-else-if="inbound.canEnableTlsFlow()" label="Flow" layout="inline">
<a-select v-model="inbound.settings.vlesses[index].flow" style="width: 150px"> <a-select v-model="inbound.settings.vlesses[index].flow" style="width: 150px" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option> <a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
<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>
@@ -66,8 +66,8 @@
</a-tooltip> </a-tooltip>
</span> </span>
<a-date-picker :show-time="{ format: 'HH:mm' }" format="YYYY-MM-DD HH:mm" <a-date-picker :show-time="{ format: 'HH:mm' }" format="YYYY-MM-DD HH:mm"
:dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"
v-model="client._expiryTime" style="width: 170px;"></a-date-picker> v-model="client._expiryTime" style="width: 170px;"></a-date-picker>
</a-form-item> </a-form-item>
</a-collapse-panel> </a-collapse-panel>
</a-collapse> </a-collapse>

View File

@@ -4,7 +4,7 @@
<a-form-item label="AcceptProxyProtocol"> <a-form-item label="AcceptProxyProtocol">
<a-switch v-model="inbound.stream.tcp.acceptProxyProtocol"></a-switch> <a-switch v-model="inbound.stream.tcp.acceptProxyProtocol"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label="HTTP Camouflage"> <a-form-item label="HTTP {{ i18n "camouflage" }}">
<a-switch <a-switch
:checked="inbound.stream.tcp.type === 'http'" :checked="inbound.stream.tcp.type === 'http'"
@change="checked => inbound.stream.tcp.type = checked ? 'http' : 'none'"> @change="checked => inbound.stream.tcp.type = checked ? 'http' : 'none'">

View File

@@ -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}}

View File

@@ -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" }}',
@@ -262,7 +263,7 @@
{ title: '{{ i18n "pages.inbounds.operate" }}', width: 70, scopedSlots: { customRender: 'actions' } }, { title: '{{ i18n "pages.inbounds.operate" }}', width: 70, scopedSlots: { customRender: 'actions' } },
{ title: '{{ i18n "pages.inbounds.enable" }}', width: 30, scopedSlots: { customRender: 'enable' } }, { title: '{{ i18n "pages.inbounds.enable" }}', width: 30, scopedSlots: { customRender: 'enable' } },
{ title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } }, { title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } },
{ title: '{{ i18n "pages.inbounds.traffic" }}↑|↓', width: 70, scopedSlots: { customRender: 'traffic' } }, { title: '{{ i18n "pages.inbounds.traffic" }}↑|↓', width: 120, scopedSlots: { customRender: 'traffic' } },
{ title: '{{ i18n "pages.inbounds.expireDate" }}', width: 70, scopedSlots: { customRender: 'expiryTime' } }, { title: '{{ i18n "pages.inbounds.expireDate" }}', width: 70, scopedSlots: { customRender: 'expiryTime' } },
{ title: 'UID', width: 120, dataIndex: "id" }, { title: 'UID', width: 120, dataIndex: "id" },
]; ];
@@ -271,9 +272,9 @@
{ title: '{{ i18n "pages.inbounds.operate" }}', width: 70, scopedSlots: { customRender: 'actions' } }, { title: '{{ i18n "pages.inbounds.operate" }}', width: 70, scopedSlots: { customRender: 'actions' } },
{ title: '{{ i18n "pages.inbounds.enable" }}', width: 30, scopedSlots: { customRender: 'enable' } }, { title: '{{ i18n "pages.inbounds.enable" }}', width: 30, scopedSlots: { customRender: 'enable' } },
{ title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } }, { title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } },
{ title: '{{ i18n "pages.inbounds.traffic" }}↑|↓', width: 70, scopedSlots: { customRender: 'traffic' } }, { title: '{{ i18n "pages.inbounds.traffic" }}↑|↓', width: 120, scopedSlots: { customRender: 'traffic' } },
{ title: '{{ i18n "pages.inbounds.expireDate" }}', width: 70, scopedSlots: { customRender: 'expiryTime' } }, { title: '{{ i18n "pages.inbounds.expireDate" }}', width: 70, scopedSlots: { customRender: 'expiryTime' } },
{ title: 'Password', width: 100, dataIndex: "password" }, { title: 'Password', width: 120, dataIndex: "password" },
]; ];
const app = new Vue({ const app = new Vue({

View File

@@ -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"

View File

@@ -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" = "کاربر جدید"

View File

@@ -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" = "添加客户端"