Rule
Chute can forward requests to another proxy server or connect to the host directly, depending on customized rules.
Priority
Rules are matched from the first one to the last one, in the order they appear in the config file. In other words, rules at the top of the list have higher priority than latter ones. Rules added by modules are placed ahead of the configuration's own rules, in module load order, and the rules Chute inserts at runtime for Tailscale come before both.
Composition
Each rule consists of 3 parts: rule type, a traffic matcher (except for FINAL rule), and a policy: TYPE, VALUE, POLICY. Example: DOMAIN-SUFFIX,apple.com,DIRECT IP-CIDR,192.168.0.0/16,ProxyA
The policy must be the name of a proxy server, a policy group, or a built-in policy such as DIRECT, REJECT (or one of its variants) or PROXY. Rules should end with a FINAL rule to define the default behavior. If the configuration contains no FINAL rule, Chute behaves as if FINAL,DIRECT were appended.
Example:
[Rule]
DOMAIN-SUFFIX,company.com,ProxyA
DOMAIN-KEYWORD,google,DIRECT
GEOIP,US,DIRECT
IP-CIDR,192.168.0.0/16,DIRECT
FINAL,ProxyB
Rule Types
Domain-based Rules
| Type | Syntax | Matches |
|---|---|---|
| DOMAIN | DOMAIN,www.apple.com,Proxy |
Exact domain match |
| DOMAIN-SUFFIX | DOMAIN-SUFFIX,apple.com,Proxy |
Domain suffix match |
| DOMAIN-KEYWORD | DOMAIN-KEYWORD,google,Proxy |
Domain contains keyword |
| DOMAIN-WILDCARD | DOMAIN-WILDCARD,*.apple.com,Proxy |
Wildcard domain match |
| DOMAIN-REGEX | DOMAIN-REGEX,^mail\..+\.com$,Proxy |
Domain regex match |
| DOMAIN-SET | DOMAIN-SET,https://example.com/domains.txt,DIRECT |
Domain set downloaded from a URL |
IP-based Rules
| Type | Syntax | Matches |
|---|---|---|
| IP-CIDR | IP-CIDR,192.168.0.0/16,DIRECT |
IP address in CIDR range |
| IP-CIDR6 | IP-CIDR6,2001:db8::/32,DIRECT |
IPv6 address in CIDR range |
| GEOIP | GEOIP,US,DIRECT |
Country code from GeoIP database |
| IP-ASN | IP-ASN,13335,DIRECT |
IP address belongs to ASN |
HTTP-level Rules
| Type | Syntax | Matches |
|---|---|---|
| USER-AGENT | USER-AGENT,Instagram*,DIRECT |
User-Agent header |
| URL-REGEX | URL-REGEX,^http://google\.com.*,DIRECT |
Full URL of a plain HTTP request matches regex |
| PROTOCOL | PROTOCOL,TLS,Proxy |
Detected protocol (HTTP/TLS/QUIC/etc.) |
Process Rules (macOS and Android)
| Type | Syntax | Matches |
|---|---|---|
| PROCESS-NAME | PROCESS-NAME,Telegram,Proxy |
Process name (wildcard matching) |
| PROCESS-PATH | PROCESS-PATH,/Applications/Safari.app,Proxy |
Full process path (wildcard matching) |
| PROCESS-NAME-REGEX | PROCESS-NAME-REGEX,^Safari$,DIRECT |
Process name (regex matching) |
Port & Source Rules
| Type | Syntax | Matches |
|---|---|---|
| DEST-PORT | DEST-PORT,80,DIRECT |
Destination port |
| SRC-IP | SRC-IP,192.168.20.100,DIRECT |
Source IP address (single IP or CIDR) |
| SRC-PORT | SRC-PORT,52345,DIRECT |
Source port |
| IN-PORT | IN-PORT,6152,DIRECT |
Incoming proxy port on Chute |
Advanced Matching Rules
| Type | Syntax | Matches |
|---|---|---|
| SUBNET | SUBNET,TYPE:WIFI,Proxy |
Network subnet attributes (TYPE, BSSID, SSID, ROUTER) |
| HOSTNAME-TYPE | HOSTNAME-TYPE,AAAA,Proxy |
DNS record type (A/AAAA/etc.) |
| IN-TYPE | IN-TYPE,SOCKS5,Proxy |
Inbound connection type (HTTP/SOCKS5/TUN) |
| IN-USER | IN-USER,user1,Proxy |
Inbound authentication username |
| IN-NAME | IN-NAME,my-proxy,Proxy |
Inbound proxy server name |
Notice: SUBNET and HOSTNAME-TYPE match live traffic — SUBNET against the network the device is currently on (Apple TV has no network identity, so SUBNET never matches there). IN-TYPE and IN-USER match live traffic too: IN-TYPE names the inbound a connection arrived on (
HTTP,SOCKS5orTUN), and IN-USER the user name that inbound verified againsthttp-auth— with no credentials configured nothing is verified, so IN-USER matches nothing. IN-NAME is accepted so that a Surge profile loads, but Chute runs a single unnamed HTTP listener and a single unnamed SOCKS5 listener, so there is no inbound name to match and the rule never fires; use IN-TYPE or IN-PORT instead.
Logical Combination Rules
| Type | Syntax | Matches |
|---|---|---|
| AND | AND,((DOMAIN,example.com),(DEST-PORT,443)),Proxy |
All sub-rules match |
| OR | OR,((DOMAIN,example.com),(DOMAIN,test.com)),Proxy |
Any sub-rule matches |
| NOT | NOT,((DOMAIN,example.com)),Proxy |
Sub-rule does NOT match |
Special Rules
| Type | Syntax | Matches |
|---|---|---|
| RULE-SET | RULE-SET,SYSTEM,DIRECT |
Bundle of rules from a URL, a rule provider, or built-in sets |
| SCRIPT | SCRIPT,MyRuleScript,PROXY |
JavaScript-based custom rule matching |
| FINAL | FINAL,ProxyB |
Default when no other rule matches (must be last) |
Options
no-resolve
For a request whose hostname is a domain, Chute evaluates the rule list in two passes. On the first pass, IP-based rules (GEOIP, IP-CIDR, IP-ASN) are skipped. If no other rule matches, Chute resolves the domain with DNS and evaluates the rules again with the resolved IP address. Add the no-resolve option to keep an IP-based rule skipped on the second pass as well, so it only ever matches requests that already carry an IP address.
GEOIP,US,DIRECT,no-resolve
IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
On a RULE-SET line, no-resolve covers every IP-based rule in the set, as if each of them carried it: RULE-SET,https://example.com/cn-ip.list,DIRECT,no-resolve. The built-in SYSTEM and LAN sets are unpacked into separate rules and do not take it.
Notice: Because of the two-pass evaluation, for a request with a domain hostname a later non-IP rule can match before an earlier IP-based rule. If DNS resolution fails, IP-based rules simply never match and the FINAL rule applies; rule evaluation is not aborted.
force-remote-dns
Force DNS resolution through remote proxy server instead of local DNS.
DOMAIN-SUFFIX,google.com,Proxy,force-remote-dns
Notice: This option is currently parsed for compatibility only and has no effect in the current releases.
extended-matching
Extend domain-based rule matching to also inspect the HTTP Host header in addition to the connection hostname. The header comes from the first request of a client connection to the HTTP proxy listener — for HTTPS, the CONNECT request's own Host header — so the option helps when a client addresses a request to an IP address, or to another name than the one its Host header carries. Connections through TUN or SOCKS5 carry no Host header, and the option changes nothing for them.
DOMAIN-SUFFIX,example.com,Proxy,extended-matching
requires-resolve
For SCRIPT rules, this option is accepted by the parser but does not delay script evaluation. $request.dnsResult is only available in the script when the session has already been resolved (for example, requests made directly to an IP address, or the second matching pass after DNS resolution).
SCRIPT,MyRuleScript,PROXY,requires-resolve
pre-matching
Only valid on rules whose policy is REJECT or one of its variants (REJECT-DROP, REJECT-TINYGIF, …). Pre-matching rules are evaluated in a separate pass before the rule result cache and the normal rule table, so a matching REJECT applies on the first pass, before any DNS resolution the rule table would trigger. A RULE-SET or DOMAIN-SET line accepts pre-matching and keeps it, but the set is not matched in that early pass: it still takes part at its own position in the rule list.
DOMAIN-SUFFIX,tracker.example.com,REJECT,pre-matching
dns-failed
Only valid on the FINAL rule. When a request's verdict needs a local DNS lookup and that lookup fails, the request is handed to the FINAL policy instead of failing — see Final Rule.
FINAL,Proxy,dns-failed
notification-text
Post a system notification when the rule matches. The title is the text; the body names the destination and the policy (host:port → policy; on Android host:port · policy · process). notification-interval sets how many seconds must pass before the same rule notifies again (default 300). Any rule can carry these options, FINAL included. A RULE-SET or DOMAIN-SET line accepts them and keeps them, but a match inside the set never posts a notification.
DOMAIN-SUFFIX,bank.example,DIRECT,notification-text="Bank site opened",notification-interval=60
FINAL,Proxy,notification-text=Fell%20to%20FINAL
Quote a text that contains spaces, or write each space as %20; write a comma as %2C. Chute posts the notification itself and follows the app's switch for these — Allow Notification on iPhone, Show report event notifications on Mac, the system's notification permission for Chute on Android — so nothing is shown when that is off, and Apple TV never shows one. Each match is also recorded as a rule notification event — see Notification Reporting.
Aliases
DOMAIN-MATCHis accepted as an alias ofDOMAIN-KEYWORD.NETWORKis accepted as an alias ofPROTOCOL.DST-PORTis accepted as an alias ofDEST-PORT.
Domain Set
Chute supports loading domain sets from an external URL with the DOMAIN-SET rule type. The first field after the type must be an http(s) URL. The optional update-interval parameter is how old, in seconds, the downloaded copy may get before it is fetched again; there is no timer — see External Rule Set.
DOMAIN-SET,https://example.com/domains.txt,DIRECT
DOMAIN-SET,https://example.com/domains.txt,DIRECT,update-interval=86400
The domain set file contains bare domains, one per line: example.com matches the exact domain; .example.com or +.example.com matches the domain and all of its subdomains. Lines starting with # or // are comments.