振り分けの前提:ルールモードとプロキシグループ

中国国内は直結、海外はプロキシという振り分けは、ドメインの分類、宛先IPのアドレス範囲、ルールの順序によって決まります。日本語のページが海外のAPIを使うこともあれば、海外サービスが中国国内のCDNを利用することもあります。そのため、「国内と確認できるドメインは直結し、それ以外は明示した方針で処理する」ことを目標にし、ドメインの末尾だけでサーバーの所在地を判断しないようにしましょう。

以下はMihomoカーネルを使うクライアント向けです。設定を始める前に、動作モードをRuleに切り替え、利用可能なノードをインポートし、設定にPROXYという名前のプロキシグループがあることを確認してください。DIRECTはカーネル標準の直結ポリシーなので、作成する必要はありません。PROXYはこの記事で使うグループ名であり、標準で用意されている出口ではありません。

  • 実際のグループ名が「ノード選択」の場合は、ルールの接続先として指定しているPROXYをすべて「ノード選択」に置き換えてください。グループ名は完全一致させる必要があります。
  • まず現在の設定をバックアップし、クライアントのオーバーライド機能またはマージ機能を使ってローカルルールを保存してください。サブスクリプションから生成されたファイルを直接編集すると、次回の更新で上書きされることがあります。
  • アプリの通信が実際にカーネルを通っているか確認してください。システムプロキシを有効にしても、すべてのアプリがプロキシを使うとは限りません。TUNを使うとより多くの通信を取り込めますが、ルールの先頭から判定する順序は変わりません。

GEOSITEを使う方法:ドメイン、IP、最後にフォールバック

GeoSiteとGeoIPのデータが利用できる場合は、次のルールを基本形として使えます。ローカルネットワークのアドレスは先頭に置き、ローカルサービスがプロキシを経由しないようにします。また、ドメインルールをIPの所属判定より先に置くことで、海外サービスが中国国内のIPに解決された場合に、先に直結判定されるのを防ぎます。

mode: rule

rules:
  - DOMAIN-SUFFIX,localhost,DIRECT
  - DOMAIN-SUFFIX,local,DIRECT
  - IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR6,::1/128,DIRECT,no-resolve
  - IP-CIDR6,fc00::/7,DIRECT,no-resolve
  - IP-CIDR6,fe80::/10,DIRECT,no-resolve
  - GEOSITE,cn,DIRECT
  - GEOSITE,geolocation-!cn,PROXY
  - GEOIP,CN,DIRECT,no-resolve
  - MATCH,PROXY

各ルール層の役割

ルール層判定基準処理内容
ローカルネットワークの例外ローカルドメイン、ループバック、プライベートアドレス範囲DIRECT
GEOSITE,cnデータファイル内のcnドメイン一覧DIRECT
GEOSITE,geolocation-!cnデータファイル内の該当ドメイン一覧PROXY
GEOIP,CN既知の宛先IPの所属DIRECT
MATCHここまでのルールに一致しない接続PROXY

GEOSITEはドメインの分類に使うもので、接続先サーバーの物理的な所在地を判定する機能ではありません。geolocation-!cnはデータセット内の分類名であり、cnの判定結果をリアルタイムで反転する記法ではありません。データソースによって収録範囲は異なり、この分類が存在しない場合もあります。分類が見つからないというエラーが出たら、まずクライアントが使用しているGeoSiteのデータソースを確認してください。

GEOIP,CN,DIRECT,no-resolveのno-resolveは、このルールのためにドメイン名の解決を新たに行わないという指定です。接続に利用可能な実IPがすでにあれば、それを使って判定できます。ドメイン名しかなく、先行するドメインルールにも一致しない場合、このルールはスキップされ、続いてMATCHで処理されることがあります。これは余分な名前解決を抑えるための選択であり、中国国内のIPがすべて必ず直結されるという意味ではありません。

Geoデータの更新に関する注意点

GeoSiteとGeoIPはローカルのデータファイルです。初回読み込みには、利用可能なファイルか、アクセスできるダウンロード元が必要です。サブスクリプションを更新しても、これらのデータが更新されるとは限りません。クライアントのGeoデータ管理画面、カーネルの読み込みログ、実際のデータソースをそれぞれ確認してください。Geoデータのエラーが出たときに、ノードのサブスクリプションだけを何度も更新しても解決しません。

rule-providersを使う方法:リモートルールセットを個別に更新

ルールの配布元や更新間隔を個別に管理したい場合は、rule-providersを使えます。プロバイダーがルールセットをダウンロードして解析し、RULE-SETがルール一覧の指定位置でそのセットを参照します。プロバイダーを定義しただけでは振り分けは行われず、ルールセットが自動的にルール一覧の先頭へ追加されることもありません。

以下では、Loyalsoldier/clash-rulesの公開リリースファイルを構文例として使います。2つのファイルはYAML形式のドメイン一覧なので、behavior: domainとformat: yamlを指定します。導入前に配布元の内容と、現在のネットワークからアクセスできることを確認してください。これらのURLはノードのサブスクリプションURLではありません。

rule-providers:
  overseas-domains:
    type: http
    behavior: domain
    format: yaml
    url: "https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/proxy.txt"
    path: ./ruleset/overseas-domains.yaml
    interval: 86400

  domestic-domains:
    type: http
    behavior: domain
    format: yaml
    url: "https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/direct.txt"
    path: ./ruleset/domestic-domains.yaml
    interval: 86400

rules:
  - DOMAIN-SUFFIX,localhost,DIRECT
  - DOMAIN-SUFFIX,local,DIRECT
  - IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR6,::1/128,DIRECT,no-resolve
  - IP-CIDR6,fc00::/7,DIRECT,no-resolve
  - IP-CIDR6,fe80::/10,DIRECT,no-resolve
  - RULE-SET,overseas-domains,PROXY
  - RULE-SET,domestic-domains,DIRECT
  - MATCH,PROXY

この一覧を前のセクションのrulesと置き換えてください。2つの完全なルール一覧をつなげてはいけません。前の例にあるMATCHは、それ以外のすべての接続に一致するため、その後ろにあるルールは判定されません。ここではGeoIPに依存せず、ローカルネットワークのルールに一致しないIP接続と一覧にないドメインを、すべてプロキシに回します。

  • interval: 86400の単位は秒で、24時間ごとに更新を確認します。キャッシュファイルの有効期間を保証する設定ではありません。
  • pathはカーネルの作業ディレクトリを基準としたローカルファイルのパスです。2つのプロバイダーには別々のパスを指定し、ファイルが互いに上書きされないようにします。
  • overseas-domainsとdomestic-domainsは任意に付けた名前です。RULE-SETに指定する名前と完全に一致させてください。
  • この例では、プロキシ用のセットを直結用のセットより前に置いています。2つのセットに重複がある場合は、先に一致したプロキシルールが適用されます。異なる管理者が作成したセットに重複がないとは限りません。

ルール形式:domain、ipcidr、classical

リモートのURLにアクセスできても、内容の形式が正しいとは限りません。サブスクリプションサービスが返すノード設定、ログイン案内を含むHTML、ドメイン名だけのテキストを、同じ解析方式で扱うことはできません。behaviorは各項目の意味を、formatはファイルの形式を指定します。どちらも配布元の内容に合わせる必要があります。

behaviorYAMLのpayload項目例対象となる内容
domain'+ .example.com'は誤りです。'+\.example.com'も正しい形式ではなく、'+ .'も使えません。正しい項目は下のコードを参照してください。ドメイン一致ルールの一覧
ipcidr'192.168.0.0/16'IPアドレス範囲の一覧
classical'DOMAIN-SUFFIX,example.com'ルールタイプ付きの項目

ドメイン一覧は、次のように簡潔に記述できます。+.example.comはルートドメインとそのサブドメインに一致します。途中に空白やバックスラッシュは不要です。

payload:
  - '+.example.com'
  - 'api.example.net'

classicalを使う場合、同じ内容は次の形式で記述します。ルールセットの項目に出口は指定せず、外側のRULE-SET,セット名,ポリシーで指定してください。

payload:
  - DOMAIN-SUFFIX,example.com
  - DOMAIN,api.example.net

ファイルの拡張子は解析形式の判定基準ではありません。前述のdirect.txtは拡張子が.txtですが、内容はpayloadを含むYAMLなので、format: yamlを指定します。1行に1項目が書かれたプレーンテキストの配布元を使う場合は、その形式に合わせてformat: textを指定してください。

例外ルールとDNS:国内向けAPIがプロキシに回るのを防ぐ

個別の例外はルールセットより前に置く

ログイン時のリスク判定、社内ネットワークへのアクセス、ローカル機器の検出などの理由で特定のサービスを直結する必要がある場合は、接続ログで実際の宛先ドメインを確認してから、個別ルールを追加してください。1つのAPIに問題があるからといって、海外ドメイン全体を直結に切り替えないようにしましょう。以下は構文例です。example.comは説明用に予約されたドメインなので、実際には接続ログに記録された宛先に置き換えてください。

rules:
  - DOMAIN,api.example.com,DIRECT
  - DOMAIN-SUFFIX,example.com,PROXY
  - RULE-SET,overseas-domains,PROXY
  - RULE-SET,domestic-domains,DIRECT
  - MATCH,PROXY

この順序では、api.example.comが先に直結ルールに一致し、その他のexample.comのサブドメインはプロキシに回ります。これは具体的なルールを広いルールより先に置くという考え方です。DOMAINがDOMAIN-SUFFIXより常に優先されるわけではありません。2つのルールの順序を入れ替えれば、結果も変わります。

振り分けルールとDNSの振り分けは別

GEOSITE,cn,DIRECTは接続の出口を決めるもので、ドメイン名をどのDNSサーバーで問い合わせるかは指定しません。DNSの上流サーバーは、dns内のnameserverやnameserver-policyなどの設定を確認してください。respect-rulesを有効にしてDNS通信にもルーティングルールを適用する場合は、ノードのドメイン名解決に必要なproxy-server-nameserverも、使用中のカーネルのドキュメントに従って設定し、名前解決の依存ループを避けてください。

Fake-IPは合成アドレスを返し、カーネルがドメイン名と接続の対応関係を管理します。合成IPを見て、実際のIPアドレスの所属を判断することはできません。一方、redir-hostは実際の名前解決結果により強く依存します。どちらのモードでも、まず接続ログでドメイン名、適用されたルール、最終的な出口を確認し、問題が名前解決と振り分けのどちらで起きているかを切り分けましょう。

検証とトラブル対処:接続ログを順に確認

設定を保存したら、まず設定の検証と再読み込みが成功したことを確認してから、新しい接続でテストしてください。既存の長時間接続は変更前の出口を使い続けることがあります。ルールを変更した後は、同じページを何度も更新するより、対象の接続を閉じるかテスト用アプリを再起動して確認する方が確実です。

  1. 動作モードを確認する。現在のモードがRuleであることを確認してください。Globalで全体の出口を確認しても、このルール一覧が正しく動作するかは検証できません。
  2. 通信の入口を確認する。クライアントに表示されたローカル混合ポートが実際に7890の場合は、下のコマンドでプロキシを明示してテストできます。ポートが異なる場合は、画面に表示されている値を使ってください。
  3. ルールの判定結果を確認する。クライアントの接続一覧で、宛先ドメイン、ルールタイプ、ルールの内容、プロキシグループ、実際に使われたノードを記録してください。PROXYに一致しても、必ずリモートノードを使うとは限りません。グループ内でDIRECTが選択されている場合もあります。
  4. プロバイダーの状態を確認する。最終更新時刻と項目数を確認してください。ログにダウンロードのタイムアウトが出ている場合は、まずリモートURLとダウンロード経路を確認します。解析エラーの場合は、ファイルがYAML、プレーンテキスト、HTMLのどれを返しているか確認してください。
  5. 最終的にマージされた設定を確認する。ローカルのオーバーライドがサブスクリプションのルールで上書きされていないこと、カスタムルールがフォールバックルールより前にあること、すべてのルールの接続先グループが存在することを確認してください。
curl --proxy http://127.0.0.1:7890 --head https://www.baidu.com
curl --proxy http://127.0.0.1:7890 --head https://www.wikipedia.org

上記のコマンドは、追跡しやすいHTTPプロキシ接続を作るためのものです。どの配布元でも、この2つのドメインが特定のセットに一致するとは限りません。また、HTTPステータスコードだけでは振り分けの成否を判断できません。サーバーがリダイレクトやアクセス拒否を返すこともあるため、カーネルの接続ログで出口を確認してください。

よくある症状と確認手順

  • 中国国内のサイトがプロキシを経由する:まずMATCHに一致しているか確認します。一致している場合は、ドメインが直結用のセットに含まれているか確認してください。一致していない場合は、先行するプロキシルールやセットの重複を確認します。
  • 海外サイトが直結になる:先行するドメイン例外ルールやGEOIP,CNに一致していないか確認し、その後、プロキシグループで直結の出口が選択されていないか確認してください。
  • ブラウザーは使えるが、ほかのアプリで問題が起きる:対象アプリがシステムプロキシに従うか、TUNによる通信の取り込みが必要かを確認してください。まずルールセットにドメインがないことを原因と決めつけないようにしましょう。
  • ルールを更新しても変化がない:更新したのがノードのサブスクリプションではなくルールプロバイダーか確認してから、新しい接続で再テストしてください。クライアントが別の設定ファイルを読み込んでいないかも確認します。

メンテナンス時は、対象を絞った明確なローカル例外リストを用意し、主要な分類元としてGeoSiteまたはリモートルールセットを選びます。ルールは種類ごとに変更し、変更前後の判定結果を記録してください。こうすることで、データの収録内容、ルールの順序、DNS名前解決、通信の取り込みのどこに原因があるかを切り分けられます。セットを追加し続けて問題を覆い隠すのは避けましょう。