diff --git a/web/assets/js/model/inbound.js b/web/assets/js/model/inbound.js
index bb30dbcc..263091d9 100644
--- a/web/assets/js/model/inbound.js
+++ b/web/assets/js/model/inbound.js
@@ -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;
}
diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js
index 9b740297..f312ed96 100644
--- a/web/assets/js/model/outbound.js
+++ b/web/assets/js/model/outbound.js
@@ -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 !== '') {
diff --git a/web/html/form/outbound.html b/web/html/form/outbound.html
index 96891b04..53f8fae4 100644
--- a/web/html/form/outbound.html
+++ b/web/html/form/outbound.html
@@ -354,6 +354,41 @@
+
+
+
+ Reverse Sniffing
+
+
+ {{ i18n "pages.inbounds.noRecommendKeepDefault" }}
+
+
+
+
+
+
+
+
+
+ [[ value ]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+