mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-04-20 05:52:24 +00:00
commit
17f64462d2
7 changed files with 128 additions and 40 deletions
|
@ -156,6 +156,16 @@
|
||||||
padding:16px;
|
padding:16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-menu-dark,
|
||||||
|
.ant-menu-dark .ant-menu-sub,
|
||||||
|
.ant-layout-header,
|
||||||
|
.ant-layout-sider-dark,
|
||||||
|
.ant-layout-sider-zero-width-trigger,
|
||||||
|
.ant-dropdown-menu-dark,.ant-dropdown-menu-dark .ant-dropdown-menu,
|
||||||
|
.ant-menu-dark.ant-menu-horizontal>.ant-menu-item,.ant-menu-dark.ant-menu-horizontal>.ant-menu-submenu {
|
||||||
|
background:#161b22
|
||||||
|
}
|
||||||
|
|
||||||
.ant-card-dark {
|
.ant-card-dark {
|
||||||
color: hsla(0,0%,100%,.65);
|
color: hsla(0,0%,100%,.65);
|
||||||
background-color: #1a212a;
|
background-color: #1a212a;
|
||||||
|
@ -178,9 +188,10 @@
|
||||||
|
|
||||||
.ant-card-dark .ant-collapse-content,
|
.ant-card-dark .ant-collapse-content,
|
||||||
.ant-card-dark .ant-calendar,
|
.ant-card-dark .ant-calendar,
|
||||||
.ant-card-dark .ant-table-placeholder {
|
.ant-card-dark .ant-table-placeholder,
|
||||||
|
.ant-card-dark .ant-input-group-addon {
|
||||||
color: hsla(0,0%,100%,.65);
|
color: hsla(0,0%,100%,.65);
|
||||||
background-color: #1a212a;
|
background-color: #262f3d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-card-dark .ant-list-item-meta-title,
|
.ant-card-dark .ant-list-item-meta-title,
|
||||||
|
@ -198,7 +209,8 @@
|
||||||
.ant-card-dark .ant-calendar-year-select,
|
.ant-card-dark .ant-calendar-year-select,
|
||||||
.ant-card-dark .ant-calendar-date,
|
.ant-card-dark .ant-calendar-date,
|
||||||
.ant-card-dark .ant-collapse>.ant-collapse-item>.ant-collapse-header,
|
.ant-card-dark .ant-collapse>.ant-collapse-item>.ant-collapse-header,
|
||||||
.ant-card-dark .ant-empty-normal {
|
.ant-card-dark .ant-empty-normal,
|
||||||
|
.ant-card-dark .ant-checkbox+span {
|
||||||
color: hsla(0,0%,100%,.65);
|
color: hsla(0,0%,100%,.65);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +222,7 @@
|
||||||
|
|
||||||
.ant-card-dark tbody .ant-table-expanded-row {
|
.ant-card-dark tbody .ant-table-expanded-row {
|
||||||
color: hsla(0,0%,100%,.65);
|
color: hsla(0,0%,100%,.65);
|
||||||
background-color: #023366;
|
background-color: #1a212a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-card-dark .ant-input,
|
.ant-card-dark .ant-input,
|
||||||
|
@ -219,7 +231,7 @@
|
||||||
.ant-card-dark .ant-select-dropdown-menu-item-selected,
|
.ant-card-dark .ant-select-dropdown-menu-item-selected,
|
||||||
.ant-card-dark .ant-select-selection {
|
.ant-card-dark .ant-select-selection {
|
||||||
color: hsla(0,0%,100%,.65);
|
color: hsla(0,0%,100%,.65);
|
||||||
background-color: #023366;
|
background-color: #2e3b52;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-card-dark .ant-collapse-item {
|
.ant-card-dark .ant-collapse-item {
|
||||||
|
@ -232,7 +244,7 @@
|
||||||
.ant-card-dark .ant-modal-header,
|
.ant-card-dark .ant-modal-header,
|
||||||
.ant-card-dark .ant-calendar-selected-day .ant-calendar-date {
|
.ant-card-dark .ant-calendar-selected-day .ant-calendar-date {
|
||||||
color: hsla(0,0%,100%,.65);
|
color: hsla(0,0%,100%,.65);
|
||||||
background-color: #242c3a;
|
background-color: #222a37;
|
||||||
}
|
}
|
||||||
|
|
||||||
.client-table-header {
|
.client-table-header {
|
||||||
|
@ -244,7 +256,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-card-dark .client-table-header {
|
.ant-card-dark .client-table-header {
|
||||||
background-color: #023366;
|
background-color: #1a212a;
|
||||||
color: hsla(0,0%,100%,.65);
|
color: hsla(0,0%,100%,.65);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,3 +279,61 @@
|
||||||
background-color: #1a212a;
|
background-color: #1a212a;
|
||||||
border: 1px solid hsla(0,0%,100%,.30);
|
border: 1px solid hsla(0,0%,100%,.30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-card-dark .ant-tag-blue {
|
||||||
|
color: #3c9ae8;
|
||||||
|
background: #111d2c;
|
||||||
|
border-color: #15395b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-dark .ant-tag-green {
|
||||||
|
color: #6abe39;
|
||||||
|
background: #162312;
|
||||||
|
border-color: #274916;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-dark .ant-tag-cyan {
|
||||||
|
color: #33bcb7;
|
||||||
|
background: #112123;
|
||||||
|
border-color: #144848;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-dark .ant-tag-red {
|
||||||
|
color: #e84749;
|
||||||
|
background: #2a1215;
|
||||||
|
border-color: #58181c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-dark .ant-tag-orange {
|
||||||
|
color: #e89a3c;
|
||||||
|
background: #2b1d11;
|
||||||
|
border-color: #593815;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-dark .ant-table-row-expand-icon,
|
||||||
|
.ant-card-dark .ant-checkbox-inner {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-dark .ant-switch-checked {
|
||||||
|
background-color: #0c61b0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-dark .ant-btn,
|
||||||
|
.ant-card-dark .ant-radio-button-wrapper {
|
||||||
|
color: hsla(0,0%,100%,.65);
|
||||||
|
background: none;
|
||||||
|
border: 1px solid hsla(0,0%,100%,.65);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-dark .ant-radio-button-wrapper:hover {
|
||||||
|
color: #177ddc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-dark .ant-btn-primary {
|
||||||
|
color: hsla(0,0%,100%,.65);
|
||||||
|
background-color: #073763;
|
||||||
|
border-color: #1890ff;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0,0,0,.12);
|
||||||
|
box-shadow: 0 2px 0 rgba(0,0,0,.045);
|
||||||
|
}
|
|
@ -95,7 +95,6 @@ const UTLS_FINGERPRINT = {
|
||||||
const ALPN_OPTION = {
|
const ALPN_OPTION = {
|
||||||
H2: "h2",
|
H2: "h2",
|
||||||
HTTP1: "http/1.1",
|
HTTP1: "http/1.1",
|
||||||
BOTH: "h2,http/1.1",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.freeze(Protocols);
|
Object.freeze(Protocols);
|
||||||
|
@ -476,7 +475,7 @@ class GrpcStreamSettings extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TlsStreamSettings extends XrayCommonClass {
|
class TlsStreamSettings extends XrayCommonClass {
|
||||||
constructor(serverName = '', minVersion = TLS_VERSION_OPTION.TLS12, maxVersion = TLS_VERSION_OPTION.TLS13,
|
constructor(serverName = '', minVersion = TLS_VERSION_OPTION.TLS10, maxVersion = TLS_VERSION_OPTION.TLS12,
|
||||||
cipherSuites = '',
|
cipherSuites = '',
|
||||||
certificates = [new TlsStreamSettings.Cert()], alpn=[''] ,settings=[new TlsStreamSettings.Settings()]) {
|
certificates = [new TlsStreamSettings.Cert()], alpn=[''] ,settings=[new TlsStreamSettings.Settings()]) {
|
||||||
super();
|
super();
|
||||||
|
@ -575,9 +574,9 @@ TlsStreamSettings.Cert = class extends XrayCommonClass {
|
||||||
};
|
};
|
||||||
|
|
||||||
TlsStreamSettings.Settings = class extends XrayCommonClass {
|
TlsStreamSettings.Settings = class extends XrayCommonClass {
|
||||||
constructor(insecure = false, fingerprint = '', serverName = '') {
|
constructor(allowInsecure = false, fingerprint = '', serverName = '') {
|
||||||
super();
|
super();
|
||||||
this.inSecure = insecure;
|
this.allowInsecure = allowInsecure;
|
||||||
this.fingerprint = fingerprint;
|
this.fingerprint = fingerprint;
|
||||||
this.serverName = serverName;
|
this.serverName = serverName;
|
||||||
}
|
}
|
||||||
|
@ -590,7 +589,7 @@ TlsStreamSettings.Settings = class extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
toJson() {
|
toJson() {
|
||||||
return {
|
return {
|
||||||
allowInsecure: this.inSecure,
|
allowInsecure: this.allowInsecure,
|
||||||
fingerprint: this.fingerprint,
|
fingerprint: this.fingerprint,
|
||||||
serverName: this.serverName,
|
serverName: this.serverName,
|
||||||
};
|
};
|
||||||
|
@ -1084,7 +1083,8 @@ class Inbound extends XrayCommonClass {
|
||||||
tls: this.stream.security,
|
tls: this.stream.security,
|
||||||
sni: this.stream.tls.settings[0]['serverName'],
|
sni: this.stream.tls.settings[0]['serverName'],
|
||||||
fp: this.stream.tls.settings[0]['fingerprint'],
|
fp: this.stream.tls.settings[0]['fingerprint'],
|
||||||
alpn: this.stream.tls.alpn[0],
|
alpn: this.stream.tls.alpn.join(','),
|
||||||
|
allowInsecure: this.stream.tls.settings[0].allowInsecure,
|
||||||
};
|
};
|
||||||
return 'vmess://' + base64(JSON.stringify(obj, null, 2));
|
return 'vmess://' + base64(JSON.stringify(obj, null, 2));
|
||||||
}
|
}
|
||||||
|
@ -1096,7 +1096,6 @@ class Inbound extends XrayCommonClass {
|
||||||
const type = this.stream.network;
|
const type = this.stream.network;
|
||||||
const params = new Map();
|
const params = new Map();
|
||||||
params.set("type", this.stream.network);
|
params.set("type", this.stream.network);
|
||||||
params.set("security", this.stream.security);
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "tcp":
|
case "tcp":
|
||||||
const tcp = this.stream.tcp;
|
const tcp = this.stream.tcp;
|
||||||
|
@ -1143,8 +1142,12 @@ class Inbound extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.tls) {
|
if (this.tls) {
|
||||||
|
params.set("security", "tls");
|
||||||
params.set("fp" , this.stream.tls.settings[0]['fingerprint']);
|
params.set("fp" , this.stream.tls.settings[0]['fingerprint']);
|
||||||
params.set("alpn", this.stream.tls.alpn[0]);
|
params.set("alpn", this.stream.tls.alpn);
|
||||||
|
if(this.stream.tls.settings[0].allowInsecure){
|
||||||
|
params.set("allowInsecure", "1");
|
||||||
|
}
|
||||||
if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
|
if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
|
||||||
address = this.stream.tls.server;
|
address = this.stream.tls.server;
|
||||||
}
|
}
|
||||||
|
@ -1156,12 +1159,17 @@ class Inbound extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.XTLS) {
|
if (this.XTLS) {
|
||||||
if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
|
params.set("security", "tls");
|
||||||
|
params.set("alpn", this.stream.tls.alpn);
|
||||||
|
if(this.stream.tls.settings[0].allowInsecure){
|
||||||
|
params.set("allowInsecure", "1");
|
||||||
|
}
|
||||||
|
if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
|
||||||
address = this.stream.tls.server;
|
address = this.stream.tls.server;
|
||||||
}
|
|
||||||
params.set("flow", this.settings.vlesses[clientIndex].flow);
|
|
||||||
}
|
}
|
||||||
|
params.set("flow", this.settings.vlesses[clientIndex].flow);
|
||||||
|
}
|
||||||
|
|
||||||
const link = `vless://${uuid}@${address}:${port}`;
|
const link = `vless://${uuid}@${address}:${port}`;
|
||||||
const url = new URL(link);
|
const url = new URL(link);
|
||||||
|
@ -1192,7 +1200,6 @@ class Inbound extends XrayCommonClass {
|
||||||
const type = this.stream.network;
|
const type = this.stream.network;
|
||||||
const params = new Map();
|
const params = new Map();
|
||||||
params.set("type", this.stream.network);
|
params.set("type", this.stream.network);
|
||||||
params.set("security", this.stream.security);
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "tcp":
|
case "tcp":
|
||||||
const tcp = this.stream.tcp;
|
const tcp = this.stream.tcp;
|
||||||
|
@ -1239,8 +1246,12 @@ class Inbound extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.tls) {
|
if (this.tls) {
|
||||||
|
params.set("security", "tls");
|
||||||
params.set("fp" , this.stream.tls.settings[0]['fingerprint']);
|
params.set("fp" , this.stream.tls.settings[0]['fingerprint']);
|
||||||
params.set("alpn", this.stream.tls.alpn[0]);
|
params.set("alpn", this.stream.tls.alpn);
|
||||||
|
if(this.stream.tls.settings[0].allowInsecure){
|
||||||
|
params.set("allowInsecure", "1");
|
||||||
|
}
|
||||||
if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
|
if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
|
||||||
address = this.stream.tls.server;
|
address = this.stream.tls.server;
|
||||||
}
|
}
|
||||||
|
@ -1249,12 +1260,17 @@ class Inbound extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.XTLS) {
|
if (this.XTLS) {
|
||||||
if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
|
params.set("security", "tls");
|
||||||
address = this.stream.tls.server;
|
params.set("alpn", this.stream.tls.alpn);
|
||||||
}
|
if(this.stream.tls.settings[0].allowInsecure){
|
||||||
|
params.set("allowInsecure", "1");
|
||||||
|
}
|
||||||
|
if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
|
||||||
|
address = this.stream.tls.server;
|
||||||
|
}
|
||||||
params.set("flow", this.settings.trojans[clientIndex].flow);
|
params.set("flow", this.settings.trojans[clientIndex].flow);
|
||||||
}
|
}
|
||||||
|
|
||||||
const link = `trojan://${settings.trojans[clientIndex].password}@${address}:${this.port}#${encodeURIComponent(remark)}`;
|
const link = `trojan://${settings.trojans[clientIndex].password}@${address}:${this.port}#${encodeURIComponent(remark)}`;
|
||||||
const url = new URL(link);
|
const url = new URL(link);
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
</table>
|
</table>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
</a-collapse>
|
</a-collapse>
|
||||||
<template v-if="inbound.isTcp && inbound.tls">
|
<template v-if="inbound.isTcp && (inbound.tls || inbound.xtls)">
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label="Fallbacks">
|
<a-form-item label="Fallbacks">
|
||||||
<a-row>
|
<a-row>
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
</table>
|
</table>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
</a-collapse>
|
</a-collapse>
|
||||||
<template v-if="inbound.isTcp && inbound.tls">
|
<template v-if="inbound.isTcp && (inbound.tls || inbound.xtls)">
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label="Fallbacks">
|
<a-form-item label="Fallbacks">
|
||||||
<a-row>
|
<a-row>
|
||||||
|
|
|
@ -40,11 +40,13 @@
|
||||||
<a-form-item label='{{ i18n "domainName" }}'>
|
<a-form-item label='{{ i18n "domainName" }}'>
|
||||||
<a-input v-model.trim="inbound.stream.tls.server"></a-input>
|
<a-input v-model.trim="inbound.stream.tls.server"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Alpn" v-if="inbound.tls">
|
<a-form-item label="Alpn">
|
||||||
<a-select v-model="inbound.stream.tls.alpn[0]" style="width:200px">
|
<a-checkbox-group v-model="inbound.stream.tls.alpn" style="width:200px">
|
||||||
<a-select-option value=''>auto</a-select-option>
|
<a-checkbox v-for="key in ALPN_OPTION" :value="key">[[ key ]]</a-checkbox>
|
||||||
<a-select-option v-for="key in ALPN_OPTION" :value="key">[[ key ]]</a-select-option>
|
</a-checkbox-group>
|
||||||
</a-select>
|
</a-form-item>
|
||||||
|
<a-form-item label="Allow insecure">
|
||||||
|
<a-switch v-model="inbound.stream.tls.settings[0].allowInsecure"></a-switch>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label='{{ i18n "certificate" }}'>
|
<a-form-item label='{{ i18n "certificate" }}'>
|
||||||
<a-radio-group v-model="inbound.stream.tls.certs[0].useFile" button-style="solid">
|
<a-radio-group v-model="inbound.stream.tls.certs[0].useFile" button-style="solid">
|
||||||
|
|
|
@ -11,10 +11,6 @@
|
||||||
.ant-col-sm-24 {
|
.ant-col-sm-24 {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-table-row-expand-icon {
|
|
||||||
color: rgba(0,0,0,.65);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<body>
|
<body>
|
||||||
<a-layout id="app" v-cloak>
|
<a-layout id="app" v-cloak>
|
||||||
|
|
|
@ -128,10 +128,14 @@ func (t *Tgbot) answerCommand(message *tgbotapi.Message, chatId int64, isAdmin b
|
||||||
case "status":
|
case "status":
|
||||||
msg = "bot is ok ✅"
|
msg = "bot is ok ✅"
|
||||||
case "usage":
|
case "usage":
|
||||||
if isAdmin {
|
if len(message.CommandArguments()) > 1 {
|
||||||
t.searchClient(chatId, message.CommandArguments())
|
if isAdmin {
|
||||||
|
t.searchClient(chatId, message.CommandArguments())
|
||||||
|
} else {
|
||||||
|
t.searchForClient(chatId, message.CommandArguments())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
t.searchForClient(chatId, message.CommandArguments())
|
msg = "❗Please provide a text for search!"
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
msg = "❗ Unknown command"
|
msg = "❗ Unknown command"
|
||||||
|
|
Loading…
Reference in a new issue