記事の内容
ローカルで立ち上げた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
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アクセスしたら、以下のように表示されました。
ローカルから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サーバーにアクセスできました。
ローカルから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
(前略)
- 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サーバーにアクセスできました。
外部から 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サーバーにアクセスできました。
本記事の手順では、最終的に外部からhttp(ポート13001)とhttps(ポート443)の両方にアクセスできることにご注意ください。
httpへのアクセスを塞ぐ何らかの対策が必要か..(方法は調べていません)
以上となります。