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(),
|
||||
flow = '',
|
||||
reverseTag = '',
|
||||
reverseSniffing = new Sniffing(),
|
||||
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.flow = flow;
|
||||
this.reverseTag = reverseTag;
|
||||
this.reverseSniffing = reverseSniffing;
|
||||
}
|
||||
|
||||
static fromJson(json = {}) {
|
||||
@@ -2630,6 +2632,7 @@ Inbound.VLESSSettings.VLESS = class extends Inbound.ClientBase {
|
||||
json.id,
|
||||
json.flow,
|
||||
json.reverse?.tag ?? '',
|
||||
Sniffing.fromJson(json.reverse?.sniffing || {}),
|
||||
...Inbound.ClientBase.commonArgsFromJson(json),
|
||||
);
|
||||
}
|
||||
@@ -2641,7 +2644,9 @@ Inbound.VLESSSettings.VLESS = class extends Inbound.ClientBase {
|
||||
...this._clientBaseToJson(),
|
||||
};
|
||||
if (this.reverseTag) {
|
||||
json.reverse = { tag: this.reverseTag };
|
||||
json.reverse = {
|
||||
tag: this.reverseTag,
|
||||
};
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,13 @@ const ALPN_OPTION = {
|
||||
HTTP1: "http/1.1",
|
||||
};
|
||||
|
||||
const SNIFFING_OPTION = {
|
||||
HTTP: "http",
|
||||
TLS: "tls",
|
||||
QUIC: "quic",
|
||||
FAKEDNS: "fakedns"
|
||||
};
|
||||
|
||||
const OutboundDomainStrategies = [
|
||||
"AsIs",
|
||||
"UseIP",
|
||||
@@ -170,6 +177,7 @@ Object.freeze(SSMethods);
|
||||
Object.freeze(TLS_FLOW_CONTROL);
|
||||
Object.freeze(UTLS_FINGERPRINT);
|
||||
Object.freeze(ALPN_OPTION);
|
||||
Object.freeze(SNIFFING_OPTION);
|
||||
Object.freeze(OutboundDomainStrategies);
|
||||
Object.freeze(WireguardDomainStrategy);
|
||||
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 {
|
||||
constructor(type = 'none', host, path) {
|
||||
super();
|
||||
@@ -1747,7 +1799,7 @@ Outbound.VmessSettings = 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();
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
@@ -1755,6 +1807,7 @@ Outbound.VLESSSettings = class extends CommonClass {
|
||||
this.flow = flow;
|
||||
this.encryption = encryption;
|
||||
this.reverseTag = reverseTag;
|
||||
this.reverseSniffing = reverseSniffing;
|
||||
this.testpre = testpre;
|
||||
this.testseed = testseed;
|
||||
}
|
||||
@@ -1768,6 +1821,7 @@ Outbound.VLESSSettings = class extends CommonClass {
|
||||
json.flow,
|
||||
json.encryption,
|
||||
json.reverse?.tag || '',
|
||||
ReverseSniffing.fromJson(json.reverse?.sniffing || {}),
|
||||
json.testpre || 0,
|
||||
json.testseed && json.testseed.length >= 4 ? json.testseed : [900, 500, 900, 256]
|
||||
);
|
||||
@@ -1782,7 +1836,12 @@ Outbound.VLESSSettings = class extends CommonClass {
|
||||
encryption: this.encryption,
|
||||
};
|
||||
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
|
||||
if (this.flow && this.flow !== '') {
|
||||
|
||||
@@ -354,6 +354,41 @@
|
||||
</template>
|
||||
<a-input v-model.trim="outbound.settings.reverseTag" :placeholder='`{{ i18n "pages.xray.outbound.reverseTagPlaceholder" }}`'></a-input>
|
||||
</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 v-if="outbound.canEnableTlsFlow()">
|
||||
<a-form-item label="Flow">
|
||||
|
||||
Reference in New Issue
Block a user