遠隔地のPCはNAT内、中継サーバーはグローバルIP持ちで名前解決可能という前提です。
OS: Ubuntu 24.04 sshのversion: 9.6 ドメイン名: server.example.com 管理用ユーザー: hiro トンネル専用ユーザー: ssh-tunnel
OS: Ubuntu 24.04 sshのversion: 9.6 autosshのversion: 1.4 ユーザー: user
下記のような感じで接続する。あくまでイメージなのでその他コマンドオプションを指定していない。このまま使わない方が良い。
[遠隔地PC]
| # 逆向きトンネルを作っておく
| ssh -R 12345:localhost:22 ssh-tunnel@server.example.com
|
|
| # 中継サーバーの12345番ポートで遠隔地PCのsshにログインできる
| ssh -p 12345 user@localhost
[中継サーバ]
|
|
| # 中継サーバーは12345番をポート開放しないので
| # sshで中継サーバーにログインして内部から接続する
| ssh hiro@server.example.com
[クライアントPC]
中継サーバーでの設定
はじめに中継サーバー上で最低限の設定を行う。専用ユーザーを作成して、超長ぇセキュアなパスワードを設定する。
# useradd -s /usr/sbin/nologin ssh-tunnel # passwd ssh-tunnel
sshの機能を制限するためsshサーバーの設定に下記を追記する。
Match User ssh-tunnel
X11Forwarding no
AllowTcpForwarding remote
PermitTTY no
PermitOpen localhost:22
ForceCommand echo 'Not permitted.'
ClientAliveInterval 60
ClientAliveCountMax 1
sshサービスをリロードする。
# systemctl reload ssh
遠隔地PCでの設定
遠隔地PCで中継サーバーに逆向きトンネルを常時接続させるためsshpassをインストールする。
# apt install sshpass
パスワードをスクリプトに記述するので、rootしか触れないようにパーミッション700で接続用スクリプトを作成する。rootのcronで毎分実行するので、sshpassのプロセスが存在しない場合のみ接続する。
#!/bin/bash
PASSWORD="password"
killall -0 sshpass > /dev/null 2>&1
if [ $? = 1 ]; then
sshpass -p "${PASSWORD}" ssh -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -o "ConnectTimeout 15" -o "ExitOnForwardFailure yes" -N -R 12345:localhost:22 ssh-tunnel@server.example.com
fi
cronにジョブを登録する。
* * * * * /root/bin/connect-reverse-ssh-tunnel.sh
sshのオプション
| -o “ServerAliveInterval 30” | 30秒ごとにサーバーの応答を確認する。 |
|---|---|
| -o “ServerAliveCountMax 3” | サーバーの応答確認を最大3回まで再試行する。 |
| -o “ConnectTimeout 15” | 15秒以内に接続できなければエラー終了する。 |
| -o “ExitOnForwardFailure yes” | ポートフォワーディングが確立できなかった場合にエラー終了する。 |
| -N | リモートシェルを実行しない。 |
| -R 12345:localhost:22 | リモートホストの12345番ポートに来た接続を、localhostの22番ポートへ転送する。 |