If you've ever opened a config file generated by a provider's subscription, you've probably seen a rules list that runs hundreds of lines long. Most of those rules weren't written by the provider itself — they're references to publicly maintained community rule sets (well-known ones include ACL4SSR and the blackmatrix7 series). The rule set itself is hosted remotely, and the config file simply "declares which rule sets it references."

What problem do Rule Providers solve?

Without Rule Providers, fine-grained control over routing for a specific app or site meant writing DOMAIN-SUFFIX / DOMAIN-KEYWORD entries one by one, and the rule list needed constant upkeep as domains changed and new services appeared. Rule Providers shift that maintenance burden onto the community that maintains the rule set — you just reference it, and the content updates automatically from the remote file.

Three key fields

FieldWhat it doesCommon values
type Where the rule set comes from http (remote subscription, auto-updating), file (local file)
behavior The kind of data the rule set contains, which determines how it's parsed domain (plain domain list), ipcidr (IP range list), classical (full rule syntax lines)
interval When type is http, how often (in seconds) it checks for updates Commonly 43200 (12 hours) to 86400 (24 hours)

A complete example

rule-providers.yaml
rule-providers:
  reject:
    type: http
    behavior: domain
    url: https://example.com/reject.txt
    path: ./ruleset/reject.yaml
    interval: 86400
  direct:
    type: http
    behavior: classical
    url: https://example.com/direct.txt
    path: ./ruleset/direct.yaml
    interval: 86400

rules:
  # Reference a rule set with RULE-SET,rule-set-name,policy
  - RULE-SET,reject,REJECT
  - RULE-SET,direct,DIRECT
  - GEOIP,CN,DIRECT
  - MATCH,PROXY

path specifies the local cache location. Once the core fetches a rule set for the first time, it saves a copy locally and then checks for updates periodically according to interval. Even if you're briefly offline, it keeps working from the local cache instead of breaking every rule that depends on it.

Common pitfalls

Should you maintain your own rule set?

For most users, referencing publicly maintained community rule sets is more than enough — there's no need to reinvent the wheel. It's only worth creating a local rule set with type: file when you have a very specific, personal need — say, a list of internal company domains, or a handful of niche sites only you use — and pairing it alongside the public rule sets, each handling its own slice of the traffic.

What Rule Providers solve is a "maintenance cost" problem, not a "capability" problem — anything a regular rule can do, a rule set can also do. It just outsources the upkeep.

How rule sets combine and layer together

In practice, a single config often references several rule sets at once, each covering a different category. A common layering approach: blocking rules first (ads, tracking), then app categories that need to go through the proxy (for example, region-restricted streaming and social apps), then large local/direct-routing lists, and finally a MATCH catch-all at the end. Each layer has a single responsibility, which also makes it much easier to pinpoint which rule set is causing an issue.

If referenced rule sets overlap (say, two rule sets both include the same domain but point to different policies), whichever one is matched first — i.e., listed earlier — always wins. So the order in which you reference rule sets is itself a kind of priority declaration; sometimes reordering solves a problem faster than editing the rule set's contents.

How to verify a rule set is working

Once a rule set is configured, you don't have to guess whether it's active. In the dashboard covered in an earlier article, the "Connections" view shows exactly which rule each connection actually matched — if it shows the name of a rule set instead of "no match," the rule set is working correctly. This is the fastest, most direct way to troubleshoot rule issues, far more efficient than repeatedly tweaking the config and testing again.