LoginSignup
1

posted at

updated at

ローカルに立てたWebサーバーを、VPSのSSHサーバーを経由して外部公開する(リバースSSHポートフォワーディング)

記事の内容

ローカルで立ち上げたWebサーバーをインターネットに公開します。
ローカル環境は、今回は私の自宅PCです。
普通の光回線契約で、固定IPアドレスではありません。

本記事では既に、VPSにSSHサーバーを立ててあります。
ローカルからVPSにSSH接続し、リバースSSHポートフォワーディングの機能を利用して、外部からのWebアクセスをローカルWebサーバーで受けます。

図にすると以下のような感じです(等幅フォントで見てね)。

┏━━━━━━━┓   ┏━━━━━━━━━━━━━━┓   ┏━━━━━━━━━┓
┃ 外部利用者 ┃   ┃      VPS       ┃   ┃  ローカル   ┃
┃       ┃   ┃              ┃   ┃         ┃
┃       ┃   ┃             ┏┻━┓ ┃         ┃
┃       ┃   ┃             ┃  ┃ポートフォワード   ┃
┃       ┃   ┃        ┌────┨  ┠─╂────┐    ┃
┃       ┃   ┃        │    ┃SSH ┃ ┃    │    ┃
┃       ┃   ┃        ↓    ┃  ┃ ┃    ↓    ┃
┃┌────┐ ┃ ┏━┻━┓  ┌──────┐ ┃  ┃ ┃ ┌──────┐┃
┃│    │ ┃ ┃   ┃  │      │ ┃  ┃ ┃ │      │┃
┃│ブラウザ│←╂─┨HTTP/S┃←→│SSHサーバー │←┨  ┠─╂─┤Webサーバー │┃
┃│    ├─╂→┃   ┃  │      ├─┨  ┠─╂→│      │┃
┃│    │ ┃ ┃   ┃  │      │ ┃  ┃ ┃ │      │┃
┃└────┘ ┃ ┗━┳━┛  └──────┘ ┗┳━┛ ┃ └──────┘┃
┃       ┃   ┃              ┃   ┃         ┃
┃       ┃   ┃              ┃   ┃         ┃
┗━━━━━━━┛   ┗━━━━━━━━━━━━━━┛   ┗━━━━━━━━━┛

参考ページ(感謝します)

ngrokやserveoなしでローカルで開発しているサイトに外部からアクセスする方法
caddyで簡単にhttpsサイト

環境

VPS環境

ドメイン名:example.com (本当は違う)
OS:CentOS 8.2
ユーザー名:usrname
sshポート:2222
Ed25519鍵認証

以下のように、ファイアウォールの設定でhttpとhttpsを開けてあります。


# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens3
  sources: 
  services: dhcpv6-client http https
  ports: 2222/tcp
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

ローカル環境

OS:Ubuntu 20.04
Python 3.8.5

外部から http でアクセスする

VPS側:SSHの設定

VPS側で、VPSからローカル環境へポートフォワードできるように、SSHのコンフィグを設定します。


# editor /etc/ssh/sshd_config

変更点は以下の通り。


- GatewayPorts no
+ GatewayPorts yes
(2023/02/20追記)
GatewayPortsをyesにするのは古いやり方で良くないそうです。
まだ試せていませんが、GatewayPorts clientspecified を検討するのが良いようです。

保存したら、sshdサービスを再起動します。


systemctl restart sshd.service

ローカル側:動作確認用Webサーバーを立てる

以下のように、動作確認用のディレクトリ(名前は何でも良いです)を作成し、Webで公開するファイルも適当に用意し(本記事ではa.txt)、Webサーバーを立てます。
本記事では、ローカルhttpのポートは3001にしました。


mkdir ~/test
cd ~/test
echo "Hello world!" > a.txt
python3 -m http.server 3001

ローカル環境でブラウザで「 http://localhost:3001 」にWebアクセスしたら、以下のように表示されました。

001.png

ローカルからVPSへssh接続:コマンドライン編

ローカル側の端末から以下を実行して、VPSにSSH接続します。
SSH接続がタイムアウトして自動切断されないよう、あらかじめKeep Aliveを有効にしておくと良いでしょう(その手順は省略します)。

本記事では、外部公開するhttpのポートは13001にしました。


ssh -o ExitOnForwardFailure=yes -p 2222 -R 13001:localhost:3001 usrname@example.com

http動作確認:コマンドライン編

ブラウザで「 http://example.com:13001 」にWebアクセスしたら、以下のように表示され、外部からローカルWebサーバーにアクセスできました。

002.png

ローカルからVPSへssh接続:Python編

先程は端末からssh接続しましたが、同じことをPythonプログラムから行うこともできます。
端末からssh接続してあったら、それをログアウトしてからお試しください。

ローカル側で、pip 等で paramiko ライブラリをインストールします。


pip3 install paramiko

適当なディレクトリで以下を実行し、paramikoライブラリのコードを取得します。


git clone https://github.com/paramiko/paramiko

取得したコードのうち、「paramiko/demos/rforward.py」を使用します。
以下のように複製してから編集します。


cp paramiko/demos/rforward.py .
editor rforward.py
rforward.py

前略

- SSH_PORT = 22
+ SSH_PORT = 2222

中略

    try:
        client.connect(
            server[0],
            server[1],
            username=options.user,
            key_filename=options.keyfile,
            look_for_keys=options.look_for_keys,
            password=password,
        )
+         client.get_transport().set_keepalive(60)
    except Exception as e:

後略

本記事ではVPSのSSHポートは2222ですので、ソースコードもそのように書き換えました。
また、ssh接続がタイムアウトで切れないように、keepaliveの処理を加えました。

書き換えた rforward.py を動かして、ローカル側からVPSにssh接続します。


python3 rforward.py example.com -p 13001 -r localhost:3001 --user usrname --key /home/usrname/.ssh/id_ed25519 --password

http動作確認:Python編

ブラウザで「 http://example.com:13001 」にWebアクセスしたら、以下のように表示され、外部からローカルWebサーバーにアクセスできました。

003.png

外部から https でアクセスする

先程までは外部からの http をリバースポートフォワードしました。
引き続き、https でも行うことにします。
今までの手順に加えて、以下を実行します。

VPS側で Caddy を導入する

Caddyについては、caddyで簡単にhttpsサイト を参考にしました(感謝)。
本記事では、Caddyのバイナリをダウンロードして使用します。

以下のページを見て、ダウンロードするバージョンを決め、ターボールのURLを調べます。
https://github.com/caddyserver/caddy/releases/

以下を実行して、ターボールをダウンロードし、適当なディレクトリて展開します。


cd ~/Downloads
wget https://github.com/caddyserver/caddy/releases/download/v2.2.1/caddy_2.2.1_linux_amd64.tar.gz
cd
mkdir caddy
cd caddy
tar xf ~/Downloads/caddy_2.2.1_linux_amd64.tar.gz

Caddyfileという名前のファイルを新規作成します。


editor Caddyfile

内容は以下の通り。


example.com

reverse_proxy 127.0.0.1:13001

Caddyを起動します。


sudo ./caddy run --config Caddyfile

https動作確認

ブラウザで「 https://example.com 」にWebアクセスし、a.txtのリンクをクリックしたら、以下のように表示され、外部からhttpsでローカルWebサーバーにアクセスできました。

004.png

本記事の手順では、最終的に外部からhttp(ポート13001)とhttps(ポート443)の両方にアクセスできることにご注意ください。
httpへのアクセスを塞ぐ何らかの対策が必要か..(方法は調べていません)

以上となります。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1