
ネットワーク認識型SSHルーター - アクティブなVPNやネットワークに基づいて、異なるIP/ポート/キー/踏み台ホストへ接続をルーティングします
| CI | コード | OpenSpec | セキュリティ |
|---|---|---|---|
|
|
|
|
|
ネットワーク対応SSHルーター。アクティブなネットワークやVPNを検出し、~/.ssh/config に触れることなく、各SSH接続に対して適切なホスト、ポート、IDファイル、ジャンプホストを自動選択します。
論理ホストごとに default プロファイルと、オプションのネットワーク別上書きを一度定義します。接続のたびに sshroute は現在のネットワーク(VPN、オフィスLAN、WireGuardピアなど)を検出し、適切なSSHパラメータを解決した上で、実際の /usr/bin/ssh に処理を引き継ぎます。
ssh myserver
→ sshroute 検出: corp-vpn がアクティブ
→ 解決: 10.100.0.50:2222 via bastion.corp.internal
→ exec /usr/bin/ssh -p 2222 -i ~/.ssh/corp_key -J bastion.corp.internal 10.100.0.50
あなたのラボにはおそらく少なくとも2つの現実があります。自宅でLAN内にいるか、外出中でWireGuardや別のVPN経由で接続しているかです。問題は ~/.ssh/config がどちらにいるかを認識できないことです。その結果、別々のエイリアス(server-lan、server-vpn)を使ったり、半分の時間しか機能しないジャンプホストを使ったり、あるいはIPを暗記したりすることになります。
sshroute は接続のたびに現在のネットワークを検出することでこれを解決します。WireGuardインターフェースが起動していてピアルートが存在する場合は、トンネルIPに直接接続します。LAN上にいる場合はローカルアドレスを使用します。どちらも到達不能な場合は、パブリックホスト名にフォールバックします。1つのエイリアス、3つの現実、手動切り替えは不要です。
また、透過的にSSHをインターセプトします。一度シャドウモードを設定すれば、git push、rsync、scp はすべて自動的に sshroute 経由で処理されます。ラッパーもシェル関数も考える必要もありません。
エンタープライズネットワークはさらにひどいものです。パブリックインターネット、サイト間VPN、個人VPNのスプリットトンネル、その内側に異なる環境(dev、staging、prod)ごとに異なるジャンプホストがあり、それぞれに異なるキーがあります。これを ~/.ssh/config で管理するには、巨大な設定ファイル(インフラ変更があると壊れる)か、チームメンバーがそれぞれ異なる方法でメンテナンスするスクリプトを書くかのどちらかです。
sshroute ではルーティングロジックを宣言的に定義し、バージョン管理されたYAMLファイルに保存し、チーム全体で共有できます。同じ設定が全員に機能します。各マシンでアクティブなインターフェースやルートに基づいて、適切なネットワークが自動検出されます。ユーザーは考えなくても、キーやポート、ユーザー、ジャンプホストが解決されます。
| 機能 | ~/.ssh/config | WireGuardのみ | Teleport / Boundary | sshroute |
|---|---|---|---|---|
| 現在のネットワークを検出 | ❌ | ❌ | ❌ | ✅ |
| 最適なパスを自動選択 | ❌ | ❌ | ❌ | ✅ |
| 接続失敗時にフォールバック | ❌ | ❌ | ✅ | ✅ |
| 切断時の自動再接続+再ルーティング | ❌ | ⚠️ トンネルローミング | ⚠️ 固定プロキシ経由 | ✅ |
| 1つのコマンドでどの場所からでも1ホスト | ❌ | ⚠️ VPNが起動している必要あり | ✅ | ✅ |
| 10ホスト×4パスでの設定サイズ | 📄 約600行 | 📄 約600行+VPN設定 | 📄 サーバー側設定 | 📄 約60行 |
| モバイルデバイスのローミング | ⚠️ 手動エイリアス | ⚠️ VPN必須 | ✅ | ✅ |
| ジャンプホストの自動連鎖 | ⚠️ 手動 -J | ➖ 該当なし | ✅ | ✅ |
| scp / rsync / git / Ansible で動作 | ✅ | ✅ | ⚠️ 部分的 | ✅ |
| ターゲットへのサーバー側インストール不要 | ✅ | ❌ | ❌ | ✅ |
| 認証サーバーやデーモン不要 | ✅ | ❌ | ❌ | ✅ |
| クライアントエージェント不要 | ✅ | ❌ | ❌ | ✅ |
| オープンソース、完全セルフホスト | ✅ | ✅ | ⚠️ オープンコア | ✅ |
Teleport と Boundary は異なるカテゴリです。ルーティングに加えてアクセス制御、監査ログ、証明書ベースの認証を追加します。それが必要な場合はそれらを使ってください。sshroute は、中央認証サーバーを運用する運用オーバーヘッドなしにルーティングのインテリジェンスが必要な場合に使用します。
GitHub Releases から最新のリリースをダウンロードします。Linux、macOS、Android向けにAMD64およびARM64のバイナリが用意されています。
go install github.com/thereisnotime/sshroute@latest
GitHub Releases から android_arm64 のtarballをダウンロードし、展開してバイナリを ~/.local/bin に配置します:
mkdir -p ~/.local/bin
curl -Lo "$TMPDIR/sshroute.tar.gz" \
https://github.com/thereisnotime/sshroute/releases/latest/download/sshroute_android_arm64.tar.gz
tar -xzf "$TMPDIR/sshroute.tar.gz" -C ~/.local/bin sshroute
chmod +x ~/.local/bin/sshroute
まだの場合、~/.bashrc または ~/.profile で ~/.local/bin を PATH に追加します:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
または、TermuxのGoを使ってソースからコンパイルします。公式のGoツールチェーンはandroid/arm64バイナリを公開していないため、GOTOOLCHAIN=local を設定してTermuxが提供するものを使います:
GOTOOLCHAIN=local go install github.com/thereisnotime/sshroute@latest
インストール後、Termuxには /usr/bin/ssh がないため、SSHバイナリのパスを設定します:
# ~/.config/sshroute/config.yaml
ssh_binary: /data/data/com.termux/files/usr/bin/ssh
または環境変数を使用:export SSHROUTE_SSH=$(which ssh)
docker run --rm -v ~/.config/sshroute:/root/.config/sshroute \
ghcr.io/thereisnotime/sshroute network
podman run --rm -v ~/.config/sshroute:/root/.config/sshroute \
ghcr.io/thereisnotime/sshroute network
SELinux対応システム(Fedora、RHELなど)では、ボリュームフラグに :Z を追加します:
podman run --rm -v ~/.config/sshroute:/root/.config/sshroute:Z \
ghcr.io/thereisnotime/sshroute network
sshroute を $PATH の早い段階で ssh としてインストールします。ターミナル、git、rsync、scp からのすべてのSSH呼び出しが自動的にインターセプトされます。設定にないホストは変更されずに /usr/bin/ssh に渡されます。
mkdir -p ~/.local/bin
ln -s $(which sshroute) ~/.local/bin/ssh
# ~/.bashrc または ~/.zshrc に追加(まだない場合):
export PATH="$HOME/.local/bin:$PATH"
# デフォルトプロファイルでホストを追加
sshroute add myserver --host myserver.example.com --user alice --key ~/.ssh/id_ed25519
# VPN固有の上書きを追加
sshroute add myserver --network vpn --host 10.8.0.50 --port 2222 --jump bastion.vpn
# 接続 — ネットワークは自動検出
sshroute connect myserver
# 実行せずに解決されたコマンドをプレビュー
sshroute connect myserver --dry-run
# 現在アクティブなネットワークを表示
sshroute network
これらのフラグはすべてのコマンドに適用されます: