💞

グローバルなIPを持たないPCへSSHでインターネット経由の接続する方法

2023/04/22に公開

はじめに

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ポートへ転送する
  • ここの通信が切れると今回のやり方ではインターネットから研究室の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)が正しく実施されていた場合は、localhost2222ポートへの接続が自動的に研究室PCの22ポートへ転送される。

以上、(1),(2),(3)の手順を踏めば一応、インターネットからの研究室PCへの接続は可能になります。
しかし、このままでは、色々と不便なので、以下のように設定を加えることで、より快適にします。

トンネル掘りのサービス化 : 研究室PC

サービスの設定ファイルを作成

ubuntuの場合は、以下のコマンドを実行して、サービス設定ファイルを作成する。

$ sudo vim /lib/systemd/system/dig-tunnel.service

設定ファイルを編集する

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

サービスの有効化

  1. サービス情報の更新読み込み
$ sudo systemctl daemon-reload
  1. dig-tunnelの有効化
$ sudo systemctl enable dig-tunnel.service
  1. dig-tunnelが正常に起動したか確認
$ sudo systemctl status dig-tunnel.service
  • Active: active (running)と表示されればOK

こうすることで、PCを再起動しても、自動的にトンネルが掘られるようになる。

.ssh/configの設定 : 自宅PC

上記の手順でアクセスができていることを確認できたら、以下のように.ssh/config/ファイルを設定する。
コマンド1つでログインができるようになり大変楽。

.ssh/config
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!)」
教授「踏み台サーバーあるよ」
僕「!?、今なんて?」
教授「踏み台サーバ、あ・る・よ」
僕「ファ〜〜〜!!!」

というわけで、踏み台サーバーが学校側で用意してあり、そこからアクセスできる様してもらったため、必要なくなりましたとさ、めでたしめでたし🥺

参考資料

https://qiita.com/m4saka/items/ad9d944693ddd2ae7bfa
https://memo.yammer.jp/posts/ssh-to-home
https://atmarkit.itmedia.co.jp/ait/articles/1811/02/news035.html

GitHubで編集を提案

Discussion