8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2020-12-13

記事の内容

ローカルで立ち上げた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へのアクセスを塞ぐ何らかの対策が必要か..(方法は調べていません)

以上となります。

8
6
4

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
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?