mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-08 14:36:13 +00:00
outbound: reverse Sniffing
This commit is contained in:
@@ -2617,12 +2617,14 @@ Inbound.VLESSSettings.VLESS = class extends Inbound.ClientBase {
|
|||||||
id = RandomUtil.randomUUID(),
|
id = RandomUtil.randomUUID(),
|
||||||
flow = '',
|
flow = '',
|
||||||
reverseTag = '',
|
reverseTag = '',
|
||||||
|
reverseSniffing = new Sniffing(),
|
||||||
email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at,
|
email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at,
|
||||||
) {
|
) {
|
||||||
super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at);
|
super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.flow = flow;
|
this.flow = flow;
|
||||||
this.reverseTag = reverseTag;
|
this.reverseTag = reverseTag;
|
||||||
|
this.reverseSniffing = reverseSniffing;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json = {}) {
|
static fromJson(json = {}) {
|
||||||
@@ -2630,6 +2632,7 @@ Inbound.VLESSSettings.VLESS = class extends Inbound.ClientBase {
|
|||||||
json.id,
|
json.id,
|
||||||
json.flow,
|
json.flow,
|
||||||
json.reverse?.tag ?? '',
|
json.reverse?.tag ?? '',
|
||||||
|
Sniffing.fromJson(json.reverse?.sniffing || {}),
|
||||||
...Inbound.ClientBase.commonArgsFromJson(json),
|
...Inbound.ClientBase.commonArgsFromJson(json),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2641,7 +2644,9 @@ Inbound.VLESSSettings.VLESS = class extends Inbound.ClientBase {
|
|||||||
...this._clientBaseToJson(),
|
...this._clientBaseToJson(),
|
||||||
};
|
};
|
||||||
if (this.reverseTag) {
|
if (this.reverseTag) {
|
||||||
json.reverse = { tag: this.reverseTag };
|
json.reverse = {
|
||||||
|
tag: this.reverseTag,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,13 @@ const ALPN_OPTION = {
|
|||||||
HTTP1: "http/1.1",
|
HTTP1: "http/1.1",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SNIFFING_OPTION = {
|
||||||
|
HTTP: "http",
|
||||||
|
TLS: "tls",
|
||||||
|
QUIC: "quic",
|
||||||
|
FAKEDNS: "fakedns"
|
||||||
|
};
|
||||||
|
|
||||||
const OutboundDomainStrategies = [
|
const OutboundDomainStrategies = [
|
||||||
"AsIs",
|
"AsIs",
|
||||||
"UseIP",
|
"UseIP",
|
||||||
@@ -170,6 +177,7 @@ Object.freeze(SSMethods);
|
|||||||
Object.freeze(TLS_FLOW_CONTROL);
|
Object.freeze(TLS_FLOW_CONTROL);
|
||||||
Object.freeze(UTLS_FINGERPRINT);
|
Object.freeze(UTLS_FINGERPRINT);
|
||||||
Object.freeze(ALPN_OPTION);
|
Object.freeze(ALPN_OPTION);
|
||||||
|
Object.freeze(SNIFFING_OPTION);
|
||||||
Object.freeze(OutboundDomainStrategies);
|
Object.freeze(OutboundDomainStrategies);
|
||||||
Object.freeze(WireguardDomainStrategy);
|
Object.freeze(WireguardDomainStrategy);
|
||||||
Object.freeze(USERS_SECURITY);
|
Object.freeze(USERS_SECURITY);
|
||||||
@@ -196,6 +204,50 @@ class CommonClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ReverseSniffing extends CommonClass {
|
||||||
|
constructor(
|
||||||
|
enabled = false,
|
||||||
|
destOverride = ['http', 'tls', 'quic', 'fakedns'],
|
||||||
|
metadataOnly = false,
|
||||||
|
routeOnly = false,
|
||||||
|
ipsExcluded = [],
|
||||||
|
domainsExcluded = [],
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
this.enabled = enabled;
|
||||||
|
this.destOverride = Array.isArray(destOverride) && destOverride.length > 0 ? destOverride : ['http', 'tls', 'quic', 'fakedns'];
|
||||||
|
this.metadataOnly = metadataOnly;
|
||||||
|
this.routeOnly = routeOnly;
|
||||||
|
this.ipsExcluded = Array.isArray(ipsExcluded) ? ipsExcluded : [];
|
||||||
|
this.domainsExcluded = Array.isArray(domainsExcluded) ? domainsExcluded : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJson(json = {}) {
|
||||||
|
if (!json || Object.keys(json).length === 0) {
|
||||||
|
return new ReverseSniffing();
|
||||||
|
}
|
||||||
|
return new ReverseSniffing(
|
||||||
|
!!json.enabled,
|
||||||
|
json.destOverride,
|
||||||
|
json.metadataOnly,
|
||||||
|
json.routeOnly,
|
||||||
|
json.ipsExcluded || [],
|
||||||
|
json.domainsExcluded || [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
return {
|
||||||
|
enabled: this.enabled,
|
||||||
|
destOverride: this.destOverride,
|
||||||
|
metadataOnly: this.metadataOnly,
|
||||||
|
routeOnly: this.routeOnly,
|
||||||
|
ipsExcluded: this.ipsExcluded.length > 0 ? this.ipsExcluded : undefined,
|
||||||
|
domainsExcluded: this.domainsExcluded.length > 0 ? this.domainsExcluded : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class TcpStreamSettings extends CommonClass {
|
class TcpStreamSettings extends CommonClass {
|
||||||
constructor(type = 'none', host, path) {
|
constructor(type = 'none', host, path) {
|
||||||
super();
|
super();
|
||||||
@@ -1747,7 +1799,7 @@ Outbound.VmessSettings = class extends CommonClass {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
Outbound.VLESSSettings = class extends CommonClass {
|
Outbound.VLESSSettings = class extends CommonClass {
|
||||||
constructor(address, port, id, flow, encryption, reverseTag = '', testpre = 0, testseed = [900, 500, 900, 256]) {
|
constructor(address, port, id, flow, encryption, reverseTag = '', reverseSniffing = new ReverseSniffing(), testpre = 0, testseed = [900, 500, 900, 256]) {
|
||||||
super();
|
super();
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
@@ -1755,6 +1807,7 @@ Outbound.VLESSSettings = class extends CommonClass {
|
|||||||
this.flow = flow;
|
this.flow = flow;
|
||||||
this.encryption = encryption;
|
this.encryption = encryption;
|
||||||
this.reverseTag = reverseTag;
|
this.reverseTag = reverseTag;
|
||||||
|
this.reverseSniffing = reverseSniffing;
|
||||||
this.testpre = testpre;
|
this.testpre = testpre;
|
||||||
this.testseed = testseed;
|
this.testseed = testseed;
|
||||||
}
|
}
|
||||||
@@ -1768,6 +1821,7 @@ Outbound.VLESSSettings = class extends CommonClass {
|
|||||||
json.flow,
|
json.flow,
|
||||||
json.encryption,
|
json.encryption,
|
||||||
json.reverse?.tag || '',
|
json.reverse?.tag || '',
|
||||||
|
ReverseSniffing.fromJson(json.reverse?.sniffing || {}),
|
||||||
json.testpre || 0,
|
json.testpre || 0,
|
||||||
json.testseed && json.testseed.length >= 4 ? json.testseed : [900, 500, 900, 256]
|
json.testseed && json.testseed.length >= 4 ? json.testseed : [900, 500, 900, 256]
|
||||||
);
|
);
|
||||||
@@ -1782,7 +1836,12 @@ Outbound.VLESSSettings = class extends CommonClass {
|
|||||||
encryption: this.encryption,
|
encryption: this.encryption,
|
||||||
};
|
};
|
||||||
if (!ObjectUtil.isEmpty(this.reverseTag)) {
|
if (!ObjectUtil.isEmpty(this.reverseTag)) {
|
||||||
result.reverse = { tag: this.reverseTag };
|
const reverseSniffing = this.reverseSniffing ? this.reverseSniffing.toJson() : {};
|
||||||
|
const defaultReverseSniffing = new ReverseSniffing().toJson();
|
||||||
|
result.reverse = {
|
||||||
|
tag: this.reverseTag,
|
||||||
|
sniffing: JSON.stringify(reverseSniffing) === JSON.stringify(defaultReverseSniffing) ? {} : reverseSniffing,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// Only include Vision settings when flow is set
|
// Only include Vision settings when flow is set
|
||||||
if (this.flow && this.flow !== '') {
|
if (this.flow && this.flow !== '') {
|
||||||
|
|||||||
@@ -354,6 +354,41 @@
|
|||||||
</template>
|
</template>
|
||||||
<a-input v-model.trim="outbound.settings.reverseTag" :placeholder='`{{ i18n "pages.xray.outbound.reverseTagPlaceholder" }}`'></a-input>
|
<a-input v-model.trim="outbound.settings.reverseTag" :placeholder='`{{ i18n "pages.xray.outbound.reverseTagPlaceholder" }}`'></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<template v-if="outbound.settings.reverseTag">
|
||||||
|
<a-form-item>
|
||||||
|
<span slot="label">
|
||||||
|
Reverse Sniffing
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.noRecommendKeepDefault" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon type="question-circle"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</span>
|
||||||
|
<a-switch v-model="outbound.settings.reverseSniffing.enabled"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
<template v-if="outbound.settings.reverseSniffing.enabled">
|
||||||
|
<a-form-item :wrapper-col="{span:24}">
|
||||||
|
<a-checkbox-group v-model="outbound.settings.reverseSniffing.destOverride">
|
||||||
|
<a-checkbox v-for="key,value in SNIFFING_OPTION" :value="key">[[ value ]]</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Metadata Only">
|
||||||
|
<a-switch v-model="outbound.settings.reverseSniffing.metadataOnly"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Route Only">
|
||||||
|
<a-switch v-model="outbound.settings.reverseSniffing.routeOnly"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="IPs Excluded">
|
||||||
|
<a-select mode="tags" v-model="outbound.settings.reverseSniffing.ipsExcluded" :style="{ width: '100%' }"
|
||||||
|
:token-separators="[',']" placeholder="IP/CIDR/geoip:*/ext:*"></a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="Domains Excluded">
|
||||||
|
<a-select mode="tags" v-model="outbound.settings.reverseSniffing.domainsExcluded" :style="{ width: '100%' }"
|
||||||
|
:token-separators="[',']" placeholder="domain:*/ext:*"></a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="outbound.canEnableTlsFlow()">
|
<template v-if="outbound.canEnableTlsFlow()">
|
||||||
<a-form-item label="Flow">
|
<a-form-item label="Flow">
|
||||||
|
|||||||
Reference in New Issue
Block a user