Rules
Rule Types

Rule Type

By writing rules, you can specify the outbound method of different connections, such as forwarding through a certain proxy, or interception. You can match based on the connection's IP, domain name, process name, or a combination of multiple conditions.

For each connection, rules are always matched from top to bottom.

Rules can be classified into two types, among which IP type may trigger DNS resolution:

  • Based on domain name
  • Based on IP
  • Other composite types
💡

Want to write rules for URLs? Please read the HTTP Rewrite section.

💡

You can add the no-track parameter at the end of the rule to hide the connection that matches this rule, such as SCRIPT,quic,REJECT,no-track. This is very effective in avoiding a large number of REJECT records flooding the page.

DOMAIN

Fully match the domain name, for example, DOMAIN,google.com matches google.com but does not match www.google.com.

DOMAIN-SUFFIX

Match the domain name suffix, for example, DOMAIN-SUFFIX,google.com matches google.com and www.google.com.

DOMAIN-KEYWORD

Keyword matches the domain name, for example, DOMAIN-KEYWORD,google matches google.com and google.jp.

GEOIP

Match the country code through MaxMind GeoIP, such as GEOIP,CN, you can add no-resolve to avoid triggering DNS resolution.

💡

Stash allows users to replace the database in MaxMind GeoIP format, users can choose the MaxMind GeoIP database that is more suitable for their own scenarios according to their needs.

IP-ASN

Through the IP autonomous system number, such as IP-ASN,714, you can add no-resolve to avoid triggering DNS resolution.

IP-CIDR / IP-CIDR6

IP CIDR range, you can add no-resolve to avoid triggering DNS resolution.

DST-PORT

Destination port.

RULE-SET

Please use rule set when referencing a large number of rules.

GEOSITE

domain-list-community (opens in a new tab) is a domain name list maintained by the v2fly community.

For example, GEOSITE,twitter matches the domain names related to Twitter (opens in a new tab) company:

ads-twitter.com
cms-twdigitalassets.com
periscope.tv
pscp.tv
t.co
tellapart.com
tweetdeck.com
twimg.com
twitpic.com
twitter.biz
twitter.com
twitter.jp
twittercommunity.com
twitterflightschool.com
twitterinc.com
twitteroauth.com
twitterstat.us
twtrdns.net
twttr.com
twttr.net
twvid.com
vine.co
x.com
⚠️

The domain-list-community data does not come with Stash distribution, Stash will load the domain name data on demand from github.com when it is used for the first time. Please ensure the connectivity of the current configuration to github.com when using it for the first time.

PROCESS-NAME

Process name, for example, PROCESS-NAME,Telegram, only effective for local processes.

⚠️

Due to the restrictions of Network Extension, Stash iOS/tvOS (including the iOS version running on Apple silicon devices) does not support PROCESS-NAME rules, and the process-related rules in the configuration will be ignored.

PROCESS-PATH

Process path, for example, PROCESS-PATH,/Applications/Telegram.app/Contents/MacOS/Telegram, only effective for local processes.

⚠️

Due to the restrictions of Network Extension, Stash iOS/tvOS (including the iOS version running on Apple silicon devices) does not support PROCESS-PATH rules, and the process-related rules in the configuration will be ignored.

SCRIPT

Match the request through Python expression, the expression must return a Boolean value, and the expression with execution errors will be skipped.

The expression can read the following variables:

{
  "network": "string", // one of tcp / udp
  "host": "string", // may be empty
  "dst_ip": "string", // may be empty
  "dst_port": "number",
  "src_ip": "string", // only works with gateway mode
  "src_port": "number" // only works with gateway mode
}

The expression can call the following functions:

def resolve_ip(host: str) -> str:
    pass
 
def in_cidr(ip: str, cidr: str) -> bool:
    pass
 
def geoip(ip: str) -> str:
    pass
 
def ipasn(ip: str) -> int:
    pass
 
def match_provider(name: str) -> bool:
    pass
 
def match_geosite(name: str) -> bool:
    pass

For example, if you need to intercept QUIC protocol requests, you can write it like this:

rules:
  - SCRIPT,quic,REJECT
  - SCRIPT,udp-cn,ProxyToCN
 
script:
  shortcuts: # can be referenced in rule
    quic: network == 'udp' and dst_port == 443 # match QUIC protocol
    udp-cn: network == 'udp' and geoip(dst_ip if dst_ip != '' else resolve_ip(host)) == 'CN' # match UDP going to CN
    instagram-quic: network == 'udp' and dst_port == 443 and match_geosite('instagram') # match Instagram's QUIC