Linux導入 読了目安 14分

LinuxでClashコアをコマンドライン導入:systemdデーモンとTUN権限の設定

GUIのないLinuxでClashコアを運用する手順。バイナリ配置、systemdサービス、TUN権限、capabilities、自動起動、ログ確認までを順に説明します。

構成と運用範囲

Linuxサーバーでは通常、GUIクライアントは必要ありません。安定した構成は、mihomoコアを独立したシステムサービスとして動かし、systemdに起動、再起動、権限の制限、ログ収集を任せる方法です。設定ファイルは /etc/mihomo/、書き込み可能な実行データは /var/lib/mihomo/、バイナリは /usr/local/bin/mihomo に固定します。これにより、プログラムの更新、設定変更、キャッシュ削除が混在しません。

この記事では、Ubuntu 24.04.2 LTS、Debian 12.10、systemd 255/252、mihomo 1.19.10を基準環境とします。ディストリビューションによってパッケージ管理コマンドは異なりますが、systemdサービス、TUNデバイス、Linux capabilitiesの扱い方は共通です。オリジナルのClashコアを使う場合、一部のTUN、DNS、ルールプロバイダー用パラメータが不足する可能性があるため、まずバージョンコマンドで実際のコア種別を確認してください。

uname -m
/usr/local/bin/mihomo -v
systemctl --version
ip -Version

uname -m の代表的な結果は x86_64aarch64armv7l です。バイナリをダウンロードする際は、CPUアーキテクチャを必ず一致させてください。バージョン表示にはmihomoのバージョンとビルド情報が明確に出る必要があります。コマンド実行時に「Exec format error」と表示される場合は、通常、ファイル権限ではなくアーキテクチャの選択ミスです。

パス 用途 推奨権限
/usr/local/bin/mihomo 固定配置するコア実行ファイル root:root 0755
/etc/mihomo/config.yaml メイン設定、プロキシ、ルールの入口 root:clash 0640
/var/lib/mihomo/ Geoデータ、ルールキャッシュ、実行データ clash:clash 0750
/etc/systemd/system/mihomo.service systemdサービスユニット root:root 0644

バイナリと専用サービスユーザーを設定する

以下では、現在のCPUアーキテクチャに合ったmihomo実行ファイルを取得し、一時的に /tmp/mihomo として保存済みであることを前提にします。まず固定パスへインストールし、ログインできないシステムユーザーを作成します。専用ユーザーでサービスを長期間root権限のまま実行することを避けられ、設定ファイル内のサブスクリプションURL、コントローラーキー、プロキシ情報も指定したグループだけが読み取れるようになります。

sudo install -o root -g root -m 0755 /tmp/mihomo /usr/local/bin/mihomo

sudo useradd \
  --system \
  --home-dir /var/lib/mihomo \
  --create-home \
  --shell /usr/sbin/nologin \
  clash

sudo install -d -o root -g clash -m 0750 /etc/mihomo
sudo install -d -o clash -g clash -m 0750 /var/lib/mihomo

/usr/local/bin/mihomo -v

システムに clash というユーザーがすでに存在する場合、useradd はユーザーが存在すると返します。その場合は id clash でホームディレクトリと所属グループを確認してください。サービスユーザーにパスワードは不要で、sudodocker などの追加グループへ加入させる必要もありません。

最小限の動作設定を書き込む

次の設定では、ローカルのmixedプロキシポート、RESTコントローラー、TUNによる透過処理を構成します。mixed-port: 7890 はHTTPとSOCKS5の接続を同時に受け付けます。コントローラーはループバックアドレスの 9090 ポートに限定し、DNSには非特権ポート 1053 を使用します。これにより、53番ポートのバインドに必要な追加権限を避けられます。

mixed-port: 7890
bind-address: 127.0.0.1
allow-lan: false
mode: rule
log-level: info
ipv6: false

external-controller: 127.0.0.1:9090
secret: "十分に長いランダムなコントローラーキーに置き換えてください"

profile:
  store-selected: true
  store-fake-ip: true

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  strict-route: true
  dns-hijack:
    - any:53
    - tcp://any:53

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  default-nameserver:
    - 223.5.5.5
    - 1.1.1.1
  nameserver:
    - https://223.5.5.5/dns-query
    - https://1.1.1.1/dns-query

proxies: []

proxy-groups:
  - name: PROXY
    type: select
    proxies:
      - DIRECT

rules:
  - GEOIP,CN,DIRECT
  - MATCH,PROXY

この設定でプロセス、ポート、TUNが正常か確認できますが、PROXY グループには現在 DIRECT しかないため、実際のプロキシ転送は発生しません。本番利用では、既存のサブスクリプションをmihomoが認識できる設定へ変換するか、サービス提供元の互換サブスクリプションを proxy-providers から参照してください。WebのサブスクリプションURLを単一のプロキシノードとして直接入力してはいけません。

保存後に権限を絞り、サービスユーザーとして構文チェックを実行します。-d は実行データディレクトリ、-f は設定ファイルを明示的に指定します。両者を分けることで、mihomoがダウンロードするGeoデータやルールキャッシュが /etc に書き込まれません。

sudo chown root:clash /etc/mihomo/config.yaml
sudo chmod 0640 /etc/mihomo/config.yaml

sudo -u clash /usr/local/bin/mihomo \
  -t \
  -d /var/lib/mihomo \
  -f /etc/mihomo/config.yaml

TUNデバイスとcapabilitiesを設定する

TUNモードにはカーネルの /dev/net/tun が必要で、ルーティング、ポリシールーティング、仮想ネットワークインターフェースを変更する権限もプロセスに必要です。重要なcapabilityは CAP_NET_ADMIN です。既定の 789090901053 はすべて1024より大きいため、CAP_NET_BIND_SERVICE は必要ありません。

TUNモジュールを確認する

test -c /dev/net/tun && echo "TUN device ready"
ls -l /dev/net/tun
sudo modprobe tun
cat /sys/class/misc/tun/dev

通常、最後のコマンドは 10:200 を出力します。modprobe tun が成功してもデバイスが存在しない場合は、現在のカーネルでTUNサポートが削除されていないか確認してください。コンテナでは、ホストから文字デバイス 10:200 をコンテナへ公開する必要があります。コンテナ内に同名ファイルを作成するだけではTUN機能は提供されません。

起動のたびにモジュールを明示的に読み込む必要がある場合は、modules-loadの設定に記述します。

echo tun | sudo tee /etc/modules-load.d/tun.conf
sudo systemctl restart systemd-modules-load.service

権限付与はsystemdを優先する

Linuxでは、バイナリにファイルcapabilityを書き込む方法と、systemdがプロセス起動時にcapabilityを付与する方法が一般的です。サービスとして運用するなら後者が適しています。バイナリを更新してもファイル置換によって拡張属性が失われず、権限範囲もサービスユニットで直接確認できます。

/etc/systemd/system/mihomo.service を作成します。

[Unit]
Description=mihomo proxy service
Documentation=https://wiki.metacubex.one/
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=clash
Group=clash
WorkingDirectory=/var/lib/mihomo

ExecStartPre=/usr/local/bin/mihomo -t -d /var/lib/mihomo -f /etc/mihomo/config.yaml
ExecStart=/usr/local/bin/mihomo -d /var/lib/mihomo -f /etc/mihomo/config.yaml

Restart=on-failure
RestartSec=3s
TimeoutStopSec=15s
LimitNOFILE=1048576

AmbientCapabilities=CAP_NET_ADMIN
CapabilityBoundingSet=CAP_NET_ADMIN
NoNewPrivileges=true

DevicePolicy=closed
DeviceAllow=/dev/net/tun rw
PrivateDevices=false

ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/mihomo
PrivateTmp=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK

[Install]
WantedBy=multi-user.target

AmbientCapabilities は非rootのサービスプロセスに CAP_NET_ADMIN を渡し、CapabilityBoundingSet は一覧外のcapabilityを取得できないよう制限します。DevicePolicy=closedDeviceAllow=/dev/net/tun rw を組み合わせることで、実行に必要なTUN文字デバイスだけを許可します。ProtectSystem=strict はシステムディレクトリを読み取り専用にし、ReadWritePaths でmihomoが状態ディレクトリへ書き込むことだけを個別に許可します。

ディストリビューションや古いsystemdが一部の強化ディレクティブに対応していない場合、ログに未知のフィールドが明確に表示されます。その際は実際のsystemdバージョンに合わせて該当行を調整し、単一のエラーを回避するためにroot実行へ戻さないでください。

ファイルcapabilityを代替手段として使う

systemdで管理しない場合は、バイナリに CAP_NET_ADMIN を付与できます。ただし、新しいバイナリで上書きインストールするとこの属性は消えます。この方法を使う場合、systemdのAmbientCapabilitiesを重複して設定しないでください。

sudo setcap cap_net_admin=+ep /usr/local/bin/mihomo
getcap /usr/local/bin/mihomo

# 取り消す場合
sudo setcap -r /usr/local/bin/mihomo

nosuid が設定されたファイルシステムでは、ファイルcapabilityが無視されることがあります。また、一部のコンテナランタイムはcapabilityをフィルタリングします。Operation not permitted が発生したら、マウントオプション、コンテナのcapability一覧、ホストのデバイスマッピングを同時に確認してください。

起動、自動起動、動作確認

サービスユニットを書き込んだら、まずsystemdに設定を再読み込みさせ、その後起動してブートターゲットへ追加します。enable --now は自動起動用リンクの作成とサービス起動を同時に行います。

sudo systemctl daemon-reload
sudo systemctl enable --now mihomo.service
sudo systemctl status mihomo.service --no-pager

正常な状態では Active: active (running) と表示され、メインプロセスのユーザーは clash になります。基準環境では、約620個のルールと2つのプロキシプロバイダーを含む設定のコールド起動は約0.8~1.2秒、安定稼働後の常駐メモリは約45~85 MBでした。ルールセット、Geoデータ、接続数が増えるとメモリ使用量も変化します。

ポートとインターフェースを確認する

sudo ss -lntup | grep -E ':(7890|9090|1053)\b'
ip tuntap show
ip rule show
ip route show table all | grep -E '198\.18\.|default'
systemctl show mihomo.service -p User -p MainPID

ポートの待ち受けアドレスは設定と一致している必要があります。789090901053 はすべて 127.0.0.1 のみで待ち受けます。mihomoが作成するTUNインターフェース名はバージョンや設定によって変わるため、固定名だけで判断しないでください。ip tuntap show、ポリシールーティング、サービスログを併せて確認する方が確実です。

HTTPプロキシとTUNルーティングを確認する

まずmixedポートを明示してプロキシ入口をテストし、その後、プロキシ環境変数を指定していない通常の接続をテストします。サンプルのポリシーグループは一時的に DIRECT を指しているため、ここではリクエストがmihomoを経由しているか、DNSがタイムアウトしないか、ルーティングループが発生していないかを確認します。

curl --proxy http://127.0.0.1:7890 \
  --connect-timeout 5 \
  https://www.example.com/ -I

env -u http_proxy -u https_proxy -u all_proxy \
  curl --connect-timeout 5 \
  https://www.example.com/ -I

sudo journalctl -u mihomo.service -n 50 --no-pager

プロキシノードを正式に追加した後は、log-level を一時的に debug へ変更し、対象ドメインがどのルールに一致し、どのポリシーグループが選ばれたかを確認できます。調査後は info に戻してください。長時間のdebug運用は大量のログを生成します。

設定更新と安全な再読み込み

YAMLを変更したら、すぐに再起動しないでください。まずテストコマンドを実行し、インデント、ルール形式、ポリシーグループの参照、providerパスが有効か確認してから、systemdでサービスを再起動します。YAMLのインデントにはスペースを使い、Tab文字は解析エラーの原因になります。ルールが参照するポリシーグループ名も proxy-groups と完全に一致させてください。

sudo -u clash /usr/local/bin/mihomo \
  -t \
  -d /var/lib/mihomo \
  -f /etc/mihomo/config.yaml

sudo systemctl restart mihomo.service
sudo systemctl status mihomo.service --no-pager
sudo journalctl -u mihomo.service --since "2 minutes ago" --no-pager

設定がサブスクリプション由来の場合は、まず一時ファイルへダウンロードし、構文テスト後に正式な設定へアトミックに置き換えることをおすすめします。これならsystemdの再起動時に完全なファイルだけが読み込まれ、ダウンロード途中の不完全なYAMLを読むことがありません。

sudo install -o root -g clash -m 0640 \
  /tmp/config.yaml \
  /etc/mihomo/config.yaml.new

sudo -u clash /usr/local/bin/mihomo \
  -t \
  -d /var/lib/mihomo \
  -f /etc/mihomo/config.yaml.new

sudo mv /etc/mihomo/config.yaml.new /etc/mihomo/config.yaml
sudo systemctl restart mihomo.service

mihomoの外部コントローラーも設定の再読み込みに対応していますが、リモート自動化スクリプトではコントローラーキー、待ち受け範囲、失敗時のロールバックを適切に扱う必要があります。単一サーバーなら、まずテストしてから systemctl restart を実行する方が分かりやすく、停止時間も通常は数秒以内です。

ログ確認とよくある障害

サービスが繰り返し再起動する

まず現在の起動サイクルのログと終了コードを確認します。サービスには Restart=on-failure が設定されているため、構文エラーが連続再起動を引き起こします。調査時はいったんサービスを停止し、設定テストを直接実行してください。

sudo journalctl -u mihomo.service -b --no-pager
sudo systemctl show mihomo.service \
  -p ExecMainCode \
  -p ExecMainStatus \
  -p NRestarts

sudo systemctl stop mihomo.service
sudo -u clash /usr/local/bin/mihomo \
  -t \
  -d /var/lib/mihomo \
  -f /etc/mihomo/config.yaml

よくある原因は、YAMLのインデント不一致、存在しないポリシーグループの参照、clash ユーザーが設定ファイルを読めないこと、providerディレクトリに書き込めないことです。namei -l /etc/mihomo/config.yaml でディレクトリごとの権限を確認できます。

TUN作成時にpermission deniedと表示される

TUNデバイス、サービスのcapability、systemdのデバイスポリシーを順番に確認します。/dev/net/tun の存在だけを確認しても不十分です。プロセスに CAP_NET_ADMIN がなければ、インターフェースの作成やポリシールーティングの書き込みもできません。

ls -l /dev/net/tun
systemctl show mihomo.service \
  -p AmbientCapabilities \
  -p CapabilityBoundingSet \
  -p DevicePolicy
sudo journalctl -u mihomo.service -n 100 --no-pager | \
  grep -Ei 'tun|permission|operation not permitted'

サービスがLXC、Dockerなどのコンテナ内で動作している場合は、ホスト側で /dev/net/tun を公開し、NET_ADMIN も付与する必要があります。クラウドサーバーのカーネルにTUNが含まれていなければ、コンテナ側の設定だけでカーネル機能を補うことはできません。

TUN有効化後にDNSがタイムアウトする

まず 1053 ポートが待ち受けていることを確認し、次に上流DNSへ到達できるか確認します。システムで systemd-resolved が動作している場合、通常はローカルの 127.0.0.53:53 を使用しますが、これはmihomoの 127.0.0.1:1053 と直接競合しません。注意すべきなのは、TUNのDNSハイジャックによってmihomo自身の上流クエリが再びTUNへ送られ、ループが発生していないかです。

sudo ss -lnup | grep ':1053'
resolvectl status
dig @127.0.0.1 -p 1053 www.example.com
sudo journalctl -u mihomo.service -n 100 --no-pager | \
  grep -Ei 'dns|timeout|loop'

確認の順番は、デフォルトの出口インターフェースが正しく認識されているか、nameserverアドレスへ到達できるか、ルールがDNS上流を誤って遮断していないかです。マルチホームのサーバーでは、TUN設定でインターフェースを明示し、Docker、WireGuard、一時的なVPNインターフェースが自動選択されるのを避けてください。

本機では使えるがLAN内の端末から接続できない

サンプル設定では意図的に bind-address: 127.0.0.1allow-lan: false を使用しているため、他の端末から 7890 へアクセスできません。LAN向けプロキシが必要な場合は、待ち受けアドレスをサーバーのプライベートアドレスに変更してLANアクセスを有効にし、ファイアウォールでは信頼できるネットワーク範囲だけを許可してください。

# 例:192.168.10.0/24からTCP 7890へのアクセスのみ許可
sudo ufw allow from 192.168.10.0/24 to any port 7890 proto tcp
sudo ufw status numbered

外部コントローラー 9090 は引き続きループバックアドレスにバインドし、SSHポートフォワーディング経由でアクセスすることをおすすめします。プライベートアドレスで待ち受ける必要がある場合も、少なくともランダムなキーを設定し、送信元アドレスを制限してください。コントロールインターフェースをインターネットへ直接公開してはいけません。

運用保守チェックリスト

  • バイナリのアーキテクチャが uname -m と一致しており、アップグレード後に mihomo -v を再実行する。
  • メイン設定の所有者は root:clash、権限は 0640 とし、実行ディレクトリはサービスユーザーが書き込めるようにする。
  • 設定を置き換える前に毎回 mihomo -t を実行し、テストに合格してからサービスを再起動する。
  • TUNモードには CAP_NET_ADMIN だけを付与し、既定のポートでは低位ポートのバインド権限を必要としない。
  • /dev/net/tun が存在し、コンテナ環境ではホスト側のデバイスマッピングとcapability付与も完了している。
  • コントローラーを 127.0.0.1:9090 にバインドしてキーを設定し、リモート管理にはSSHフォワーディングを使う。
  • ログレベルは info を維持し、短時間のトラブルシューティング時だけ debug に切り替える。
  • TUNルーティングを変更する前に自動停止タスクを用意し、デフォルトルートの変更によるリモートSSHの切断を防ぐ。

これらの手順を完了すると、mihomoはネットワークの準備後にsystemdによって起動し、異常終了時は3秒待って自動的に再試行され、シャットダウン時には15秒の停止時間が確保されます。設定、バイナリ、実行データを分けて管理できるため、今後のコア更新、サブスクリプション調整、サーバー移行も明確な境界に沿って進められます。

Clashをダウンロード プラットフォーム別に選べるバージョンを確認