- 今年は Advent Calendar に 2 つ参加することができました。
- もうひとつはこちらです。
Prologue
-
IoT 家電が普及してきたことで、家の各種状態を
外出先から見るということの需要が増えてきました。 -
でも、家庭内 LAN の機器に WAN から接続するためには
NAT 越えなどのややこしい話をクリアする必要があり、
一歩間違えば家庭内 LAN を脆弱
にしてしまうリスクもあるため、
安易にオススメできません。 -
そこで…
VPS を使って家庭内 LAN と公開サーバーを切り離そう
-
今は VPS のプロバイダーや契約プランが増え、ワンコインから
契約できるため、気軽に利用できるようになりました。 -
VPS を利用して、家庭内 LAN の機器を WAN に公開することなく、
家庭内の状況を監視するようにします。
仕組み概念図
- 家庭内 LAN 側からのアクションは
upload
だけなので、
家庭内の機器がセキュリティリスクに曝されることはありません。
VPS を準備する
-
まだ VPS を契約していない方々
- 契約してください!
- ググったら各社の特徴比較の記事がいっぱいあります。
-
準備の内容は、ここでは省略します。
- ご契約の会社が公開している手順をご覧ください。
- どの手順でも、終わった段階で作業 PC から VPS に
ssh で接続できるようになっているはずです。
家庭の状況を収集し、upload する仕組みを作る。
- ここでは簡単な事例として、RasPi で定期的に vmstat を実行し、
その直近 10 回を表示することにします。- ここでは、こちらで準備した Pi4 を使います。
秘密鍵と公開鍵を作る
- まず RasPi から password 認証無しに VPS に
ssh で login できるように秘密鍵と公開鍵を準備します。
pi $ ssh-keygen -t ed25519
- デフォルトのままポチポチしたらこうなっていると思います。
pi $ ls ~/.ssh/
id_ed25519 id_ed25519.pub
- VPS をセットアップした作業 PC から rsync で
id_ed25519.pub
を引っ張ってきて、VPS に上げます。
PC $ rsync -av pi@192.168.xxx.yyy:~/.ssh/id_ed25519.pub ./
PC $ rsync -av id_ed25519.pub [VPS USER]@[VPS IP]:~/
PC $ ssh [VPS USER]@[VPS IP]
VPS $ cat ~/id_ed25519.pub >> ~/.ssh/authorized_keys
- ~/.ssh/config を書きます。
- ホスト名は、ここでは仮に
flask-vps
とします。
- ホスト名は、ここでは仮に
Host flask-vps
HostName aaa.bbb.ccc.ddd
Port xxxxx
User username
IdentityFile ~/.ssh/id_ed25519
- RasPi から VPS に login できることを確認します。
pi $ ssh flask-vps
VPS $
make_report.sh
- 次に vmstat の結果と、実行した日時を txt に出力する script を作ります。
#!/bin/bash
date
echo
vmstat -S M 2 5
echo
- ここの内容をもっと工夫することで、様々な情報を収集することができます。
submit.sh
-
更に make_report.sh で
log_report.txt
を作成し、定期的に
最後の方を切り出して VPS に upload する shellscript を作ります。- ファイル名のネーミングが今イチですがご容赦ください。
-
無限 loop で service として動かすため、ファイルを別にしました。
- make_report を function にして 1 ファイルにすることもできます。
-
upload する VPS のディレクトリは、ここでは
~/workspace/home_report/
とします。
#!/bin/bash
LOG='log_report.txt'
PERIODIC_MINUTES='10'
VPS_SVR="flask-vps:~/workspace/home_report/static"
while :
do
./make_report.sh >> $LOG
cat $LOG | tail -n 100 > recent_${LOG}
rsync -av recent_${LOG} $VPS_SVR/
# exit 0
sleep $(($PERIODIC_MINUTES * 60))
done
-
実行した後、VPS 側できちんと upload できていることを確認します。
-
できていたら、RasPi で submit.sh を service 実行します。
$ nohup ./submit.sh &
$ exit
- これで、RasPi が稼働中で、ネットワークに接続されている間は
定期的にrecent_log_report.txt
が VPS に upload されます。- シャットダウンや再起動を行うと停止するので、
その際はまたnohup ./submit.sh &
してください。
- シャットダウンや再起動を行うと停止するので、
upload された家庭の状況を Flask で公開する
- ここまでの仕組みで
~/workspace/home_report/static/
の中に定期的にデータが上がってくるので、あとはこのデータを
Web ページのコンテンツとして表示するだけです。
home_report.py
- あまり書くことないです。
"""
advent calendar 2019 flask.
"""
from __future__ import absolute_import, division, print_function, unicode_literals
import sys
from os import path
from flask import Flask, render_template
app = Flask( __name__)
@app.route( '/')
def entrance() :
return "{}".format( __name__)
@app.route( '/home-report')
def default_report() :
with open( 'static/recent_log_report.txt', 'r') as file :
report = file.readlines()
return render_template( 'report.html', report = report)
def main( argv) :
host_ip = argv[1]
host_port = int( argv[2])
app.run( host = host_ip,
port = host_port )
if __name__ == "__main__" :
if len( sys.argv) < 3 :
print( "USAGE: {:s} [ip] [port]".format( sys.argv[0]))
sys.exit( 1)
main( sys.argv)
templates/report.html
- 最低限です。
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Home Report</title>
<style>
div.report {
background-color : #EEE;
font-family : monospace;
max-width : 800px;
padding : 20px;
margin : 0 auto 0 40px;
}
</style>
</head>
<body>
<h1>Home Report</h1>
<div class="report">
<!-- {{report}} -->
{% for line in report %}
{{line}}<br>
{% endfor %}
</div>
</body>
</html>
VPS 側で Flask を実行する
- ここまでで、VPS の作業ディレクトリの中はこんな感じです。
~/workspace/home_report/
|-- home_report.py
|-- static/
| `-- recent_log_report.txt
`-- templates/
`-- report.html
- service として実行します。
VPS $ export IP=`networkctl status | grep -i address | awk '{print $2}'`
VPS $ export PORT='xxxxx'
VPS $ nohup python3 home_report.py $IP $PORT &
VPS $ exit
完成
-
ブラウザーで VPS の
http://IP:PORT/home-report
にアクセスすると、
static/recent_log_report.txt
の内容が表示されました。- 見た目はショボいですが、
直近の家庭の状況が見られるサイトができました。
- 見た目はショボいですが、
Epilogue
-
今回は RasPi の情報だけでしたが、
RasPi から収集可能な家庭内のテキストデータや画像なら
何でも upload することができるため、汎用性は高いです。 -
VPS の入門ネタとしても、ぜひご活用ください