Files
panel/docs/learn-en/routing-rules.md

6.9 KiB

title, sidebar_position
title sidebar_position
Response Rules 8

:::warning If you are unsure about the changes you are making, please proceed with caution. Incorrect modifications can disrupt the system. :::

Response Rules (SRR) are an ordered (top-to-bottom; if the rule applies, the evaluation stops), JSON set of rules that the backend evaluates for incoming subscription requests.

<img src={require('./images/52.webp').default} width="100%" style={{borderRadius: '8px'}} alt="Templates menu" />

:::tip Response Rules will override the External Squads configuration. :::

Create a Custom Response Rule

Let's create a custom Response Rule that will give Android user with Happ client app a custom Template, and a custom header.

It should look something like this:

  1. The user requests a subscription
  2. Remnawave recognizes that he's using Happ on Android.
  3. Remnawave responds with a custom Happ Android Template and adds a custom header HappTheBestAppOnTheWorld.

Here's how the rule could look:

{
  "name": "Happ Android",
  "description": "Serve custom JSON for Android",
  "enabled": true,
  "operator": "AND",          // Both "user-agent" and "x-device-os" must be matched
  "conditions": [
    {
      "caseSensitive": false,
      "headerName": "user-agent",
      "operator": "CONTAINS",
      "value": "happ"
    },
    {
      "caseSensitive": false,
      "headerName": "x-device-os",
      "operator": "EQUALS",
      "value": "android"
    }
  ],
  "responseType": "XRAY_JSON",
  "responseModifications": {
    "subscriptionTemplate": "Happ Android",   // Serve the custom Template
    "headers": [                              // Serve the custom headers
    {
      "key": "x-provider-id",
      "value": "HappTheBestAppOnTheWorld"
    }
    ]
  }
}  

rules

Each rule is an object with the following fields:

  • name (string) — required; 1..50 chars

    "name": "Block Legacy Clients"
    
  • description (string) — optional; max 250 chars

    "description": "Blocks requests from legacy clients"
    
  • enabled (boolean) — required
    Controls whether the rule is active. When false, the rule is skipped during evaluation.

    "enabled": true
    
  • operator (enum) — required; AND or OR

    "operator": "AND" // Rule matches only if ALL conditions match
    "operator": "OR"  // Rule matches if ANY condition matches
    
  • conditions (array)
    List of conditions to evaluate.

    "conditions": []  // Empty = match everything (use for fallback rules)
    
  • responseType (enum) — required
    Determines what response to send when the rule matches:

    Type Description
    MIHOMO Mihomo YAML config
    CLASH Clash YAML config
    STASH Stash YAML config
    SINGBOX Sing-box JSON config
    XRAY_JSON Xray JSON config
    XRAY_BASE64 Base64-encoded Xray config
    BROWSER HTML page for browsers
    BLOCK HTTP 403 Forbidden
    STATUS_CODE_404 HTTP 404 Not Found
    STATUS_CODE_451 HTTP 451 Unavailable For Legal Reasons
    SOCKET_DROP Drop the socket connection
  • responseModifications (array) - optional
    Additional modifications to apply to the response. Can be used to give a custom Template or headers.

    • subscriptionTemplate (string) - optional
      Define a specific Template to be given if the rule is matched.
    • headers (array) - optional
      Respond with a custom header.
      • key (string) - optional
        Header name.
      • value (string) - optional
        Header value.
    "responseType": "SINGBOX",
    "responseModifications": {
        "subscriptionTemplate": "Singbox Legacy",
        "headers": [
          {
            "key": "x-custom-header",
            "value": "CustomHeaderValue"
          }
        ]
    }
    

rules.conditions

  • headerName (string) — required
    The HTTP header to check. Must comply with RFC 7230.

    "headerName": "user-agent"    // Client app user-agent
    
  • operator (enum) — required
    Comparison operation to perform:

    Operator Description
    EQUALS Exact match
    NOT_EQUALS Inverse exact match
    CONTAINS Substring exists
    NOT_CONTAINS Substring absent
    STARTS_WITH Prefix match
    NOT_STARTS_WITH Prefix absence
    ENDS_WITH Suffix match
    NOT_ENDS_WITH Suffix absence
    REGEX Regular expression
    NOT_REGEX Inverse regex
  • value (string) — required; 1..255 chars
    The value to compare against the header value.

    "value": "^sfa|sfi|sfm|sft|karing|singbox|rabbithole"
    
  • caseSensitive (boolean) — required

    "caseSensitive": true   // The value is compared as is
    "caseSensitive": false  // The value is lowercased before comparison
    

:::tip Serve OS-specific Templates You can easily respond with different Templates to different OSes.

In the example below users with iOS will get a Happ iOS JSON, and users with Android will get a Happ Android JSON.

{
  "name": "Happ Android",
  "description": "Serve custom JSON for Android",
  "enabled": true,
  "operator": "AND",
  "conditions": [
    {
      "caseSensitive": false,
      "headerName": "user-agent",
      "operator": "CONTAINS",
      "value": "happ"
    },
    {
      "caseSensitive": false,
      "headerName": "x-device-os",
      "operator": "CONTAINS",
      "value": "android"
    }
  ],
  "responseType": "XRAY_JSON",
  "responseModifications": {
    "subscriptionTemplate": "Happ Android"
  }
},
{
  "name": "Happ iOS",
  "description": "Serve custom JSON for iOS",
  "enabled": true,
  "operator": "AND",
  "conditions": [
    {
      "caseSensitive": false,
      "headerName": "user-agent",
      "operator": "CONTAINS",
      "value": "happ"
    },
    {
      "caseSensitive": false,
      "headerName": "x-device-os",
      "operator": "CONTAINS",
      "value": "ios"
    }
  ],
  "responseType": "XRAY_JSON",
  "responseModifications": {
    "subscriptionTemplate": "Happ iOS"
  }
}

:::

:::tip Header Resolution Rules

  1. Header names are case-insensitive
    "user-agent" === "User-Agent" === "USER-AGENT"
    
  2. If a header has multiple values, these will be concatenated into a single string, separated by commas.
  3. Missing value of the headers result in skipped rule. :::