グローバルなIPを持たないPCへSSHでインターネット経由の接続する方法
はじめに
2023年春、ついに私も研究室へ配属となりました。
ただ、第一志望の研究室に入れたは良いものの、僕は大学への通学に1時間かかるため、できるだけ行きたくないです。
そこで、研究室のPCへ自宅PCからアクセスできる様にして、快適なリモート環境を構築することにしました(とりあえず、環境だけ作って後から許可取れば問題ないやろ的なノリでやりました)。
前提条件
-
グローバルなipを持ったSSHサーバーがあること
- 踏み台用として使います
-
接続先のPCからネットワーク上のコンピュータへSSH接続できること
- ゲートウェイで弾かれないこと
- PCでSSHの利用が禁止されていないこと
-
接続先のPCでSSHサーバーが動作していること
-
踏み台サーバー、接続先サーバ共が公開鍵認証に対応していること
- 今回の説明では公開鍵があることを前提に説明します
やり方
手順
(1) 研究室のPCから踏み台サーバーへリバーストンネルを掘る
研究室のPC上で以下のコマンドを打つ。
$ ssh -R 2222:localhost:22 vps
-
R
オプションはリモートポートフォワードを実現するためのオプション- 今回の図の場合はvpsの
2222
ポートを研究室PCの22
ポートへ転送している- つまり、vpsの
2222
番ポートへ来た通信を研究室PCの22
ポートへ転送する
- つまり、vpsの
- 今回の図の場合はvpsの
-
ここの通信が切れると今回のやり方ではインターネットから研究室のPCへはログインできなくなる
- そのため、永続化のために、
ssh -fNR 2222:localhost:22 vps
のようにするか、後述するようにサービス化する必要がある-
f
オプションでバックグラウンド実行 -
N
オプションでシェルを割り当てない
-
- そのため、永続化のために、
(2) 自宅PCから踏み台サーバーへsshで接続する
自宅PCで以下コマンドを実行して普通にsshでvpsへログインする。
$ ssh vps
- 後述するように、.ssh/configに設定した場合、この過程は必要ないですが、説明上踏み台サーバーへsshでグインしています
(3) 踏み台サーバーから研究室PCへsshで接続する
踏み台サーバーで以下コマンドを実行して研究室PCへ接続する。
$ ssh localhost -p 2222
- 手順(1)が正しく実施されていた場合は、
localhost
の2222
ポートへの接続が自動的に研究室PCの22
ポートへ転送される。
以上、(1),(2),(3)の手順を踏めば一応、インターネットからの研究室PCへの接続は可能になります。
しかし、このままでは、色々と不便なので、以下のように設定を加えることで、より快適にします。
トンネル掘りのサービス化 : 研究室PC
サービスの設定ファイルを作成
ubuntuの場合は、以下のコマンドを実行して、サービス設定ファイルを作成する。
$ sudo vim /lib/systemd/system/dig-tunnel.service
設定ファイルを編集する
[Unit]
Description=DIG SSH TUNNEL
After=network.target
[Service]
ExecStart=/usr/bin/ssh -NT -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -i <SSH用の秘密鍵までのフルパス> -R <リモート側のポート>:localhost:22 <vpsのユーザー>@<vpsのアドレス> -p 2222
RestartSec=3
Restart=always
[Install]
WantedBy=multi-user.target
サービスの有効化
- サービス情報の更新読み込み
$ sudo systemctl daemon-reload
-
dig-tunnel
の有効化
$ sudo systemctl enable dig-tunnel.service
-
dig-tunnel
が正常に起動したか確認
$ sudo systemctl status dig-tunnel.service
-
Active: active (running)
と表示されればOK
こうすることで、PCを再起動しても、自動的にトンネルが掘られるようになる。
.ssh/configの設定 : 自宅PC
上記の手順でアクセスができていることを確認できたら、以下のように.ssh/config/
ファイルを設定する。
コマンド1つでログインができるようになり大変楽。
Host labo-pc
HostName localhost
User <接続先PCのユーザ>
Port <リモートポートフォワードされているポート番号>
IdentityFile <labo-pc用の秘密鍵へのパス>
ProxyJump vps
Host vps
HostName <vpsのipアドレス>
User <vpsのユーザ名>
RequestTTY yes
IdentityFile <vps用の秘密鍵へのパス>
IdentitiesOnly yes
ForwardAgent yes
以上を設定後に以下コマンドを実行して接続に成功することを確認する。
$ ssh labo-pc
- fingetPrintに関するエラーが出た場合は
ssh-keygen -R <接続先>
で登録を削除してから接続する。
セキュリティ対策 : 踏み台サーバ
今回のやり方の場合、秘密鍵にパスフレーズをかけないため、サーバーへの不正アクセスの可能性が高まる。
そこで、権限をかなり絞ったトンネリング専用のユーザーを作成して、セキュリティーを高める。
穴掘り専用のアカウントを作成する
ユーザーを作成する。
sudo useradd -s /bin/false -d /home/tunnel -m tunnel
-
s
オプションでは、シェルの割り当てを設定する。- 今回の場合、シェルが割り当てられないので通常のログインはできない。
-
d
オプションでは、ホームディレクトリのパスを指定する。 -
m
オプションでは、ホームディレクトリをなければ作成する。
パスワードを設定する。
passwd tunnel
接続先PCから、アクセスする場合はこの穴掘りアカウントを使うようにします。
そうすることで、不正アクセスを防ぐことができます。
ポートフォワード可能なポートを制限する
上で作成したtunnelユーザーの設定ファイルを以下のように修正します。
permitopen="localhost:<ポート番号>" <公開鍵>
-
permitopen
オプションを設定することで、ポートフォワード可能なポートを制限できます。- 尚、特に設定しなければ、全てのポートがフォワード可能になります。
-
また、接続先PCに対してのポートフォーワードについては、この設定は影響しません。
まとめ
上記のように、設定をすることでグローバルなIPを持たないPCに対して、外部から接続することが可能になります。
しかし、これは本来許可されていない経路のアクセスのため、利用するためには許可をもらうべきです。
後日談.PCをセットアップした日の会話
僕「先生!、実はこうこうこういう仕組みで〜(上のやつの説明をする)、家のPCから接続したいんですけど、やってもいいですか?(Time is Money!)」
教授「踏み台サーバーあるよ」
僕「!?、今なんて?」
教授「踏み台サーバ、あ・る・よ」
僕「ファ〜〜〜!!!」
というわけで、踏み台サーバーが学校側で用意してあり、そこからアクセスできる様してもらったため、必要なくなりましたとさ、めでたしめでたし🥺
参考資料
Discussion