はじめに(この記事で分かること)#
SSHポート22をグローバルIPに公開すると、世界中のスキャナーが1日に何千回もの認証試行を送ってくる。鍵認証のみにしていても、ポートが開いていること自体がサーバーの存在を示すシグナルになる。
Shodan/Censysの記事で説明したとおり、SSHのホスト鍵フィンガープリントはIPアドレスが変わっても残る識別子だ。SSHポートを公開しない設計にすることで、この識別子自体が外に漏れることを防ぐ。
この記事では、踏み台サーバー(bastion)とWireGuardを組み合わせて、バックエンドサーバーのSSHを完全にグローバルネットワークから隠す構成を実装する。検証環境はUbuntu 26.04 LTSである。
前提: 脅威モデルの整理#
SSHを公開しない設計が有効な相手は、脅威モデル入門で整理した5種類の相手のうち、主に2者だ。
CensysやShodanのような走査エンジンは、SSHポートが開いているサーバーを走査し、ホスト鍵のフィンガープリントを収集する。ポートが閉じていれば、この走査は何も得られない。
標的型攻撃者は、公開されたSSHポートを攻撃の起点として使う。鍵認証のみであっても、認証情報の流出やOpenSSH自体の脆弱性を悪用される可能性は残る。
アーキテクチャ#
管理者 → 踏み台サーバー(bastion、公開 IP あり)
↓ ProxyJump または WireGuard
バックエンドサーバー(公開 IP なし、または UFW で bastion のみ許可)
踏み台サーバーだけがグローバルIPでSSHを受ける。バックエンドサーバーのSSHは、踏み台のIPからのアクセスのみを許可するか、WireGuardトンネル内のみで受け付ける。
さらに踏み台をTorのonionサービスとして公開すれば、踏み台のIPアドレスも隠せる。
ステップ1: 踏み台サーバーの設定#
踏み台サーバーには、SSHのhardened設定を適用する。
# /etc/ssh/sshd_config のベースライン
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
MaxAuthTries 3
LoginGraceTime 30
AllowUsers deploy
ForwardAgent no
ForwardAgentを踏み台で有効にしない。踏み台が侵害された場合、エージェント転送によりバックエンドの鍵にアクセスされる。
ステップ2: バックエンドサーバーのUFW設定#
バックエンドサーバーでは、SSHを踏み台のIPからのみ許可する。
ufw default deny incoming
ufw default allow outgoing
ufw allow from BASTION_PUBLIC_IP to any port 22 proto tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
BASTION_PUBLIC_IPは踏み台サーバーの公開IPアドレスに置き換える。
ステップ3: ProxyJumpでの接続#
管理者のマシンから、SSHのProxyJump機能で踏み台を経由してバックエンドに接続する。
# ~/.ssh/config
Host bastion
HostName bastion.example.com
User deploy
Host backend
HostName backend.internal.ip
User deploy
ProxyJump bastion
ssh backend
この接続は、踏み台を経由してバックエンドのSSHに到達する。踏み台が存在しないIPからバックエンドへの接続は、UFWにより拒否される。
ステップ4: WireGuardトンネル内のみでSSHを受け付ける#
さらに厳格にするには、SSHをWireGuardトンネル内のみで受け付ける。
# WireGuard のインストール
apt install wireguard
踏み台サーバーにWireGuardのサーバー側設定を行う。
# /etc/wireguard/wg0.conf(踏み台サーバー)
[Interface]
Address = 10.50.0.1/24
PrivateKey = <bastion-private-key>
ListenPort = 51820
[Peer]
# backend
PublicKey = <backend-public-key>
AllowedIPs = 10.50.0.2/32
バックエンドサーバーにWireGuardのクライアント側設定を行う。
# /etc/wireguard/wg0.conf(バックエンドサーバー)
[Interface]
Address = 10.50.0.2/24
PrivateKey = <backend-private-key>
[Peer]
PublicKey = <bastion-public-key>
Endpoint = <bastion-public-ip>:51820
AllowedIPs = 10.50.0.1/32
PersistentKeepalive = 25
systemctl enable --now wg-quick@wg0
wg show
ステップ5: SSHをトンネルIPでのみリッスンする#
バックエンドサーバーのsshdを、WireGuardのトンネルIPでのみリッスンさせる。
# /etc/ssh/sshd_config
ListenAddress 10.50.0.2
systemctl restart sshd
ss -tulpn | grep sshd
# 10.50.0.2:22 のみが表示されることを確認
この状態では、バックエンドサーバーのSSHはWireGuardトンネル内からのみアクセス可能であり、グローバルIPのどのポートにもSSHは存在しない。
ステップ6: 発信方向の接続制限#
バックエンドサーバーは、SSHを受けないだけでなく、自分から外に向けて接続を開くときにもIPアドレスを露出する。
Shodan/Censysの記事で説明したとおり、パッケージミラー、NTP、Webhook、エラーレポーター、Git remoteなど、バックエンドが自分から接続を開く宛先は、バックエンドのIPを送信元として記録する。
ServPrivacyのガイドは、この問題を「egressリーク」として明確に定義し、二つの対策を示している。
対策A(厳格): バックエンドの全発信トラフィックをWireGuardトンネル経由にし、踏み台サーバーでNATを行う。wg-quickは0.0.0.0/0ルートでfwmarkルールを自動インストールする。
対策B(実用的): ユーザー供給URLを取得する機能(リンクプレビュー、OGPフェッチ等)の前に必ずプロキシを挟む。
どちらの対策を採ったかを明示的に決め、実際に自分のホストへリクエストしてログの送信元IPで検証することまでを手順に含める。
ステップ7: 踏み台をonionサービスとして公開する#
さらに踏み台のIPも隠すには、SSHをTorのonionサービスとして公開する。
SSD Nodesの手法では、sshdをonion serviceで公開し、グローバルポートは完全に閉じる。onionアドレス自体が公開鍵であり、ポートゼロでスキャン不能になる。
# /etc/tor/torrc
HiddenServiceDir /var/lib/tor/ssh-service/
HiddenServicePort 22 127.0.0.1:22
接続にはSSHのProxyCommandでTorを使う。
# ~/.ssh/config
Host bastion-onion
HostName xxxxxxxxxxxx.onion
User deploy
ProxyCommand nc -X 5 -x 127.0.0.1:9050 %h %p
この構成では、踏み台サーバーのIPアドレスは攻撃者から見えず、ポートスキャンの対象にもならない。
限界と残るリスク#
踏み台サーバーのIPアドレスは、踏み台自身が外部のサービスに接続する際には露出する。NTP、DNS、パッケージミラー、ソフトウェアの更新リポジトリへの接続元IPは、踏み台のIPである。
踏み台が侵害されれば、バックエンドへのアクセス経路が攻撃者の手に渡る。踏み台にMFAを設定し、踏み台自体の監査ログを外部に転送することで、このリスクを軽減する。
Shodan/Censysの記事で説明した自己監査の手順を、踏み台とバックエンドの両方に対して定期的に実行する。
まとめ#
SSHをグローバルIPに公開しない設計は、3段階で構築できる。
第一段階は、UFWで踏み台のIPからのみSSHを許可する構成だ。第二段階は、SSHをWireGuardトンネル内でのみリッスンさせる構成だ。第三段階は、踏み台自身をonionサービスとして公開する構成だ。
どの段階でも、バックエンドサーバーの発信方向の接続(NTP、Webhook、SMTPなど)がIPアドレスを露出する点は変わらない。egressの制御は、踏み台とWireGuardの構成とは別の課題として扱う。
この記事で説明した構成は、IPアドレスを出さずにonionサイトを運営する方法と組み合わせることで、サーバー全体の匿名化をさらに進めることができる。
出典#
- HostMyCode — SSH Jump Host Setup Guide Tutorial 2026(ProxyJumpの設定、UFWのベースライン、踏み台のhardened sshd_config)
- ServPrivacy — Hide your origin IP: an offshore reverse proxy that holds(WireGuardトンネル内でのSSHリッスン、egressリークの定義、wg-quickのfwmarkルール、発信方向の検証手順)
- SSD Nodes — SSH over a Tor onion service, no open ports(onionサービスでのSSH公開、Tor経由のProxyCommand設定)
- NIILAA — Secure Remote Administration Without Exposing SSH(WireGuard + bastionの三役構成、鍵管理)
- Qubes OS Forum — Firewalls & secure network configuration(ISPルータのログ漏れからOPNsenseへの移行事例)
- Privacy Guidesフォーラム — Clarification of Tor+VPN recommendations(VPN over Torが非推奨とされる理由と例外。フォーラム参加者の回答で、Privacy Guides本体の文書ではない)