The need is usually narrow. One site got swept into the proxy by a subscription rule and now demands a captcha at every login; or one tool refuses to load on a direct connection and you want that one thing, and nothing else, on a node. Neither case calls for a new subscription or a rewritten policy group. One line does it.
Rules are read top to bottom and the first hit ends it
When a request arrives, the core walks the rules list in order. The moment an entry matches, the connection is handed to that entry's target and reading stops — nothing below is ever consulted. The list is not a set of conditions, it is an ordered pipeline. Once that lands, the question you ask about a new rule shifts from “is this written correctly” to “what is sitting above it”.
rules:
- DOMAIN-SUFFIX,github.com,PROXY
- DOMAIN-KEYWORD,steamcommunity,PROXY
- DOMAIN,ocsp.apple.com,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- PROCESS-NAME,Telegram.exe,PROXY
- GEOIP,CN,DIRECT,no-resolve
- MATCH,PROXY
SponsoredWhere does the subscription link come from?Our partner provider gives you 1 GB of high-speed Hong Kong data at signup — import it in one click.Get high-speed nodes
The rule types you will actually reach for
DOMAIN— an exact match.DOMAIN,example.comcovers that one name and nothing else;www.example.comis a different name and will not hit.DOMAIN-SUFFIX— the domain plus every subdomain under it. The workhorse: one line sweeps in the api, cdn and img prefixes together.DOMAIN-KEYWORD— hits when the string appears anywhere in the hostname. Convenient, and the easiest way to catch things you never meant to. A keyword likegoogledrags in a pile of unrelated hosts.IP-CIDRandIP-CIDR6— match an address range. These handle private networks and connections that carry no hostname at all.GEOIP— matches by the country an address belongs to, decided by the local GeoIP database.PROCESS-NAME— matches the program that opened the connection, with no reference to the destination.DST-PORT— matches the destination port, useful for pinning SMTP or a game's port somewhere specific.
The last field on each line is the target. It can be the name of a policy group, spelled exactly as it appears in proxy-groups — one stray space or a dropped emoji and the config refuses to load — or the literals DIRECT and REJECT. IP rules take one more optional field, no-resolve. Without it, a request carrying a hostname has to be resolved first so there is an address to compare against, and you pay twice: an extra lookup, plus the very query you were trying to avoid going out anyway.
A rule in the wrong place is a rule that never runs
The usual failure looks like this. You append the rule at the bottom of the list, just above MATCH, because that looks tidy. It never fires. A subscription-generated list normally carries dozens or hundreds of geosite entries and a GEOIP,CN,DIRECT line long before that point, and one of them claimed your domain already. Custom rules belong above anything that could match them first, which in practice means the very top of rules. To find out who is taking the traffic, open the connection in your client's connections view — it shows which rule that connection matched.
Working out which domains a site needs
- Open the connections page in your client and clear the existing list so new entries stand out.
- Load the site in a browser and use it for real: sign in, page through, open an image, let a video play for a couple of seconds.
- Go back to the connections page and read the hostnames that appeared. One page usually pulls from three groups — the main domain, a CDN domain serving static assets, and an API domain for the backend. The last two are often registered under names with no visible relation to the first.
- Adding only the main domain is the classic half-finished job: the page renders, images spin forever, or the login request times out. Cover all three and the rule is done.
Routing by program name
PROCESS-NAME matches the executable that opened the connection, which is what you want for “this app goes through the proxy wherever it connects”. The spelling differs by platform: on Windows include the extension, as in Telegram.exe; on macOS and Linux use the executable's own name with no suffix. The core also has to be able to see process information before it can match anything, and on some platforms that means the client needs sufficient privileges or a matching option switched on. When the process name cannot be read the rule does not error — it just quietly never matches.
After you save
Reload the config so the core picks it up. Most clients put a reload control on the profiles page, and switching away from the profile and back does the same job. Then comes the step that trips people up: connections that already exist do not change route. A TCP connection's path is fixed at handshake time and a later rule change never reaches it. Your browser is still reusing keep-alive connections, so ten refreshes all show the old path. Close the relevant connections from the connections page before you test, and close and reopen the tab if it stays stubborn.