Преглед на файлове

outbound: reverse Sniffing

MHSanaei преди 19 часа
родител
ревизия
a8dff126c7
променени са 3 файла, в които са добавени 102 реда и са изтрити 3 реда
  1. 6 1
      web/assets/js/model/inbound.js
  2. 61 2
      web/assets/js/model/outbound.js
  3. 35 0
      web/html/form/outbound.html

+ 6 - 1
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;
     }

+ 61 - 2
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 !== '') {

+ 35 - 0
web/html/form/outbound.html

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