【Raspberry Pi】PiVPN(WireGuard)をインストール

過去にPiVPNでOpenVPNをインストールしましたが、何やら最近のPiVPNでは「WireGuard」が利用できるようなので、そちらでインストールしてみました。

■参考サイト
Setting up a WireGuard VPN on the Raspberry Pi - Pi My Life Up
https://qiita.com/Aiyama_R/items/7addb0ed3d67640125b0
https://www.wundertech.net/setup-wireguard-on-a-raspberry-pi-vpn-setup-tutorial/

1.PiVPNのインストール

いきなりですが、前回記載と同様の部分は端折ります。
engetu21.hatenablog.com

この画面でWireGuardを選択

勝手にコマンドが実行されます。

ポート設定する。特に気にならなければデフォルトの「51820」で設定。

2.インストール完了後のユーザ作成

ここは前回と変わらず「pivpn add」で作成。


「pivpn -qr ユーザ名」でAndroidなどのクライアントアプリから読み込めるQRコードを生成できます。

QRコードを読み込まない場合は、生成される[ユーザ名.conf]ファイルをコピーして、アプリでインポートする必要があります。

3.内部LANにアクセスするための設定

$ sudo vi /etc/sysctl.conf
net.ipv4.ip_forward=1
コメントアウトされていたら取り外す。

$ sudo vi /etc/wireguard/wg0.conf
※[Interface]の項目は以下を追加する。
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

wg0 はWireGuardがインストールされた時点で仮想インタフェースとして追加される模様。ifconfigで確認可能。

4.ルータでポートフォワード設定

ラズパイ4のIPアドレスに対してUDP:51820ポートの転送設定を行います。

5.VPN接続タイプ

How to Set Up WireGuard on a Raspberry Pi in 2022
の2項にてVPN接続タイプについて説明があります。デフォルトはFull-Tunnel VPNのようですがFree-WiFiなどを利用した際に、自宅のネットワークから接続している形となるため、接続元の隠蔽と接続内容の暗号化によってセキュアな通信になると思われるため(自信はない)、個人的にはデフォルトのままでいいんじゃないかなと思います。

6.感想

OpenVPNより手早く繋がります。それこそボタン押した直後から1秒未満でスッと繋がります。
ただ問題点というか、OpenVPN違い、繋がっているクライアントはVPNサーバ(今回はラズパイ4)のサブネットワークに属している形になるため、内部LANのマシンからは見えない存在になります。
なので、内部LANからVPNクライアントのマシンにアクセスしたいといった用途がある場合は、もう一工夫必要になりそうです。
ヒントは以下参考ページの7項に書いてありますが、ルータの機能にも依存すると思われるため、対応したい人は頑張りましょう。
https://www.wundertech.net/setup-wireguard-on-a-raspberry-pi-vpn-setup-tutorial/

【Linux】コマンドでBluetooth接続

LinuxではBluetoothを利用するにはコマンドラインを使うようです。
といってもUbuntuの場合はGUIでもできる模様。
※今使ってるのはUbuntu派生のドマイナーOSなので、GUIでは無理そうだった。

おもむろにコマンドを叩きます。

$ bluetoothctl

実行できなければ、bluzのパッケージをを入れます。

$ sudo apt install bluez
$ bluetoothctl

実行できれば、プロンプトが変わります。

・デバイスのスキャン

# scan on

・スキャン停止

# scan off

・デバイスとのペアリング

# pair [接続したいデバイスMACアドレス]

・ペアリング状況確認

# paired-devices
Device [接続したデバイスMACアドレス] [デバイス名]

・ペアリングしたデバイスの確認

# info [接続したデバイスMACアドレス]

・接続デバイスを信頼する。(やらなくてもよい?)

trust [接続したデバイスMACアドレス]

・接続!

# connect [接続したデバイスMACアドレス]

connectで「Failed to connect: org.bluez.Error.Failed」と出る場合、
pulseaudioのモジュールが足りてない場合があるのでインストールします。
その場合は、exitで一旦bluetoothctlを抜けます。
そしてaptコマンド実行。

$ sudo apt install pulseaudio-module-bluetooth

その後にpluse audioを再起動します(マシンごとでもいい)。

b.u.i(ビュイ)のメガネ買ってみました。

b.u.i(ビュイ)とは。
ネッツペックコーティングによるレンズで光を減少させ、眼精疲労を低減してくれるのだ!
www.aoyamaopt.co.jp

という触れ込みで、目の疲れが最近ひどかったので買ってみました。
PCを一日中弄ってるので、職業病ですね。レーシックしたのに視力も1.0以下になってきました。悲しみ。
で、まだ一日しか使ってませんが、使ってみた感じは疲れなくなってるかも・・・という感じ。
買ったのは楽天で1万円ぐらいのヤツ、レンズ、フレーム付きでした。

www.nire.com

こちらのブログを参考にしましたが、かけてみた感じで言えば、
・特に光がマイルドになった感じはない。
→夜間もグレアを抑えるといったこともない
・ピンホール効果により視力を上げる効果は感じない。
→遠くにあるものは多少見やすくなったように思えるけど、多分目が疲れなくなったからかな


疲れ目については期待通りだけど、それ以外は期待はずれ。そんな感じですね。
レンズが安いものだからだろうか・・・?
b.u.iはいくつかバージョンがあるようですが、このメガネで使われているバージョンもわからないし、
高いやつだと変わってくるのかも。
まぁいいレンズはレンズだけで結構な値段するので、買うのはちょっとなぁという感じですが。
とはいえ、昔に比べれば今がフレーム付きで安すぎるんですけどね。

【Azure】Ubuntu 18.04 × Bottle × Let's Encrypt で SSL対応

Bottleはお手軽に使えるWebサーバとしてとても重宝します。
で、自宅Webサーバを公開したいわけですが、極力限定的にしたく、インターネットに全公開!はやめたいので、Azure上に組んだVMにBottleを入れ、外部公開はそのVMにやらせ(一枚かませ)ます。また、そのVMは外部とのSSL終端をさせて、リバースプロキシらしきものとして動かします。

なので、必要な技術としては
・Azure VMの実装
・Bottleの導入
・通信のSSL
です。

1.Azure VMの実装

といっても、これは割愛。Microsoftのアカウントを作ってAzureにアクセス。コンソールからVMを作るだけ。
ただし、サーバとして公開する最低限の設定として、グローバルIPの固定IP化(何個かまでは無料だったはず)、ネットワーク設定での送信元IPアドレス/送信先ポート番号の限定化をします。
もっといえば、Application Gatewayを導入したほうがより安全(WAFとして使う)。

2.Bottleの導入

Bottleは1ファイルでできています。AzureVMを立ち上げてwgetで入手可能。

$ wget http://bottlepy.org/bottle.py

サンプルは公式に書いてあるので、その通りにPythonソースファイルを作ればOK。
bottlepy.org

ひとまず動くことを確認する。

$ python helloworld.py
※Webサーバが起動するので、ブラウザでアクセス。

3.Let's Encryptを導入する

letsencrypt.org
Let's Encryptを使えば無料でSSL化が可能です。用途的にはオレオレ証明書でも同じですが、作る手間とかアクセス時のブラウザの警告とか考えるととてもありがたいサービスです。

■参考サイト
loumo.jp

AzureVMにSSHログインして以下のコマンドを実行します。

$ sudo wget https://dl.eff.org/certbot-auto -O /usr/sbin/certbot-auto
$ sudo chmod a+x /usr/sbin/certbot-auto

 
【2021/12/23追記】
上記コマンドは使えなくなってるので、以下の方法でインストールします。
Certbot Instructions | Certbot

$ sudo apt install snapd
$ sudo snap install core; sudo snap refresh core
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

 
今回はAzureVMを利用しますが、事前にドメインは設定しておかないといけません。
設定はVMのメニュー→「構成」からいける(はず)。
f:id:engetu21:20191001190048j:plain
かぶってなければ、前半は好きな文言をいれてドメインを作成できる。また、同画面にてIPアドレスの静的化も可能。

設定後にSSH画面に戻り、ドメインに対しての証明書を発行。
今回はhogehoge.japaneast.cloudapp.azure.comを例として発行してもらいます。

$ sudo certbot-auto certonly -d hogehoge.japaneast.cloudapp.azure.com
【2021/12/23 コマンドが変更されているので追記】
$ sudo certbot certonly -d hogehoge.japaneast.cloudapp.azure.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?

  • - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)

  • - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
※ここでは1を選択。nginx等を事前に導入しておくと、nginxで使用するかどうかの選択肢が現れる

Plugins selected: Authenticator standalone, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for hogehoge.japaneast.cloudapp.azure.com
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/hogehoge.japaneast.cloudapp.azure.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/hogehoge.japaneast.cloudapp.azure.com/privkey.pem
Your cert will expire on 2019-12-24. To obtain a new or tweaked
version of this certificate in the future, simply run certbot-auto
again. To non-interactively renew *all* of your certificates, run
"certbot-auto renew"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

無事作られると祝われます。なお、この際VMのポートは80を開けておかないと通信できずに証明書の発行も失敗する模様なので、一時的でもいいので開けておきましょう。

証明書は赤文字の通り、
/etc/letsencrypt/live/hogehoge.japaneast.cloudapp.azure.com/ の配下に生成されます。
fullchain.pemは中間証明書と証明書が一緒になったものでprivkey.pemは秘密鍵とのこと。

4.BottleでSSL

■参考
blog.motikan2010.com

上記サイトを参考に、以下のように作成しました。

import sys, os, datetime
from bottle import route, run, request, HTTPResponse, ServerAdapter

class SSLWebServer(ServerAdapter):
    def run(self, handler):
        from gevent.pywsgi import WSGIServer
        srv = WSGIServer((self.host, self.port), handler,
        certfile='/etc/letsencrypt/live/hogehoge.japaneast.cloudapp.azure.com/fullchain.pem',
        keyfile='/etc/letsencrypt/live/hogehoge.japaneast.cloudapp.azure.com/privkey.pem')
        srv.serve_forever()

@route('/bottle',  method='GET')
def bottle():
    return '<b>Hello bottle!</b>'

run(host='0.0.0.0', port=8080, server=SSLWebServer)

で、サーバ起動。

$ sudo python ./hellobottle.py

sudoをつけているのは、ブラウザからアクセス時にパーミッションエラーが発生するため。秘密鍵ファイル(下記は実態の方)の権限を直せば不要になります。

$ ls -ltr /etc/letsencrypt/archive/hogehoge.japaneast.cloudapp.azure.com/

  • rw------- 1 root root 1704 Sep 25 22:50 privkey1.pem
  • rw-r--r-- 1 root root 3611 Sep 25 22:50 fullchain1.pem
  • rw-r--r-- 1 root root 1647 Sep 25 22:50 chain1.pem
  • rw-r--r-- 1 root root 1964 Sep 25 22:50 cert1.pem

$ sudo chmod 644 /etc/letsencrypt/archive/hogehoge.japaneast.cloudapp.azure.com/privkey1.pem

  • rw-r--r-- 1 root root 1704 Sep 25 22:50 privkey1.pem
  • rw-r--r-- 1 root root 3611 Sep 25 22:50 fullchain1.pem
  • rw-r--r-- 1 root root 1647 Sep 25 22:50 chain1.pem
  • rw-r--r-- 1 root root 1964 Sep 25 22:50 cert1.pem

f:id:engetu21:20191002080748j:plain
証明書については有効期限が3ヶ月となっているため、手動で更新するかcronで定期的に更新しないといけません。
sudo certbot-auto renew のコマンドで実行できるようなので、設定しておきましょう。

Asterisk+050plusの着信でAGIによるサーバの遠隔操作をしたかった(未完)

・やりたかったこと
1.Asteriskに050plusを収容
2.収容した電話番号に対してスマホなどで発呼する。その際にサフィックスIPアドレスを入れる。
 例えばIPアドレスが「123.456.789.12」だった場合、
 「05012345678*123#456#789#12」といった形で入力する。(#は.(ドット)の代わりとして入力し、後ほどサーバ側で置換)
3.Asteriskは着信した際にAGI(https://www.voip-info.org/asterisk-agi/)でPythonプログラムを起動。
 その際、SIP-INVITEのToヘッダから取得した宛先電話番号をPythonプログラムに渡す。Pythonプログラムでは取得した番号からサフィックス部分を切り取り、加工する。
4.切り取った部分(IPアドレス)をIPTABLES(Linuxファイアウォール)にぶち込んで、そのIPからのVPN接続だけを許容するよう穴を開ける。
 
・実際
1.出来た。というか、まぁ昔やってるんですけど
engetu21.hatenablog.com

2.まぁこれは発呼するだけなので出来た。
3.AGIが動いて宛先電話番号も渡せた。ただし、サフィックスはついてなかった。
 どうやら050plusのサーバ側でサフィックス部分を除外してINVITEのToに電話番号を載せるらしい・・・。
4.3ができてないので、当然できない。
 
 
う〜む・・・。
Toヘッダにサフィックスも載っかる前提だったのでアテが外れた。
他のヘッダにもしかしたら載るかもと思ったけど、RFC3261(http://www.softfront.co.jp/tech/ietfdoc/trans/rfc3261j.txt)見てもなさそう・・・。
まぁそもそもSIPキャプチャしてもなさそうだったからダメなのでしょう。
 
 
もう一つの方法として考えたのは、着信後にIVR(Interactive Voice Response)の要領で発呼側でダイアルIPアドレスを入力させること。
入力終了後にサーバ側のAsteriskでAGIが起動、IPTABLESの設定を書き換える。
 
ただし、この方法は通話料がかかる。元々考えてた案は200OK前(というか180 Ringingの前)で完結するため、お金がかからない。
(ご存知の通り、呼び出し音がなっている間(180 Ringing)ではお金はかからない。発着が通信確定(着側が200OKを返却)してから通話料がかかるようになっている)
 
 
 
1動作で10円だけど、なるべくなら余計なお金は掛けたくないですなぁ。
と思ってたところ、ふと会社から渡されてるスマホは050の電話帯であり、かつNTT Communicationだったのを思い出しました。
そして050plusを提供しているOCNはNTT Communication。
もしや・・・?と調べてみると、やはり無料で通話できますね。
www.ntt.com
 
これを使えば通話料はかからない。
しかしなぁ、会社備品の私的利用はなぁ。う〜む・・・

【LIVA Z】ルータにしてるサーバでのDockerネットワーク設定【Ubuntu18.04】

engetu21.hatenablog.com
で、docker runするときに pオプションでポート番号を指定してましたが、Dockerを入れたLIVA Zはiptablesでルータ(Firewall設定)にしてる代物なので、これでは困ることに気づきました。

というのも、pオプションで設定したポートに関しては、設定すれば勝手にiptabelsにChainを作り、そのポートが叩かれたら「どのネットワークからの通信でも」Dockerに流すようにセッティングを変えてしまうらしい(デフォルトの仕様)。
qiita.com

これがルータサーバで作用すると、インターネットからポートにアクセスされた場合もどうぞどうぞと招いてしまうので、悪い人に悪いことをされちゃうわけですね。


pオプションを使わない場合は、後からポート設定することは可能で、これは自力でiptablesを設定すればいい。
で、ルータサーバの現状は、iptablesの設定はシェルスクリプトを組んで起動時に実行しているので、そこにDocker用のルーティング設定とインターネットからの該当ポートアクセス規制を組み込めばOK。
しかし、もっと簡単にdocker runのオプションで「--net=host」を設定することで、ホストと同様のネットワーク設定で動くようになるとのこと。
 --net=hostを付けなかった場合は、iptablesでFORWARD設定等が必要になりますが、--net=hostの場合はINPUT/OUTPUT設定で制御できるようになり、個人的にはこちらのほうが管理しやすいので、--net=hostでの設定を採用します。

Dockerのネットワークについては、こちらで詳しく記載されていました。
qiita.com

1.--net=hostオプションを付けてコンテナの再構築

元々あったコンテナを削除し、昨日のブログでも書いた、自作イメージからコンテナを再構築します。

$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
df8293948e68 ubuntu:18.04 "/bin/bash" 3 days ago Exited (0) 3 days ago ubuntu18.04-Asterisk
 
$ docker rm df8293948e68
df8293948e68
 
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
 
※コンテナ無し
 
$ docker run -it -d --name ubuntu18.04-Asterisk --net=host asterisk
ff7596c64b24...
 
$ docker exec -it ubuntu18.04-Asterisk /bin/bash
# whereis asterisk
asterisk: /usr/sbin/asterisk /usr/lib/asterisk /etc/asterisk /usr/include/asterisk /usr/include/asterisk.h /usr/share/man/man8/asterisk.8

あっという間に環境復元。これは楽・・・。


ネットワークがホストになっているかは「docker network inspect」コマンドで見られます。

$ docker network inspect host
[
    {
        "Name": "host",
        "Id": "8add9139014f(略)",
        "Created": "2019-06-01T23:45:58.08816873+09:00",
        "Scope": "local",
        "Driver": "host",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": []
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "<span style="color: #ff0000">ff7596c64b(略): {
                "Name": ubuntu18.04-Asterisk",</span>
                "EndpointID": "90b75801ed376a1(略)",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

Dockerで自動で作られるネットワークは以下のコマンドの通り。

$ docker network ls
NETWORK ID NAME DRIVER SCOPE
46758297af06 bridge bridge local
8add9139014f host host local
d11e638cdb4c none null local

※赤文字部分はdocker network inspectで出力されたIDと同じになっている

あとはiptablesでINPUT/OUTPUTを設定するだけ。
とはいえ、時間が厳しいので設定はまた後日。

【LIVA Z】Dockerで作ったコンテナをイメージ化して保存してみる【Ubuntu18.04】

昨日作ったDockerコンテナ(Asterisk)↓をイメージ化してtarにします。
engetu21.hatenablog.com

1.イメージ化の実施

一応、コンテナは止めておいたほうがいい?と思うので、とりあえず止めます。

$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
df8293948e68 ubuntu:18.04 "/bin/bash" 25 hours ago Up 25 hours 0.0.0.0:5060->5060/tcp ubuntu18.04-Asterisk

$ sudo docker stop ubuntu18.04-Asterisk


イメージ化はcommitオプションをつけるとのこと。

$ docker commit ubuntu18.04-Asterisk asterisk

コンテナ(ubuntu18.04-Asterisk)を指定して、イメージ名(asterisk)を指定。
イメージ名はすべて小文字じゃないとエラーになるようです。

$ docker commit ubuntu18.04-Asterisk Asterisk
invalid reference format: repository name must be lowercase

イメージはimagesオプションで確認可能。

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
asterisk latest 82da6fd3119d 12 minutes ago 1.82GB
ubuntu 18.04 7698f282e524 2 weeks ago 69.9MB

サイズでかくない・・・?まぁいいや。

2.イメージの保存(save)

saveオプションでtar化(書庫化)できるらしいです。tarにしたコンテナを別のdocker環境に移すことで、手軽に環境が再構築できるようですね。

$ docker save asterisk > asterisk.tar

ファイルができました。

$ ls -ltrh

  • rw-rw-r-- 1 engetu engetu 1.8G 6月 3 22:38 asterisk.tar

3.loadをしてみる

先程作ったtarイメージをロードしてみます。
その前に一旦イメージ化している「asterisk」を削除

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
asterisk latest 82da6fd3119d 28 minutes ago 1.82GB
ubuntu 18.04 7698f282e524 2 weeks ago 69.9MB
 
$ docker rmi asterisk:latest
Deleted: sha256:82da6fd3119de…
 
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 7698f282e524 2 weeks ago 69.9MB

ロード実行。

$ docker load < asterisk.tar.gz

※進捗状況が表示される。

終わったので確認

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
asterisk latest 82da6fd3119d 34 minutes ago 1.82GB
ubuntu 18.04 7698f282e524 2 weeks ago 69.9MB

問題なく読み込み出来てますね。

4.export/importもあるらしい

どうやらsave/loadとexport/importの2つの手段があるようですが、save/loadはイメージまるごと、export/importはコンテナのみとのこと。
何が違うねん、というところで以下の記事。
qiita.com
save/loadの場合はメタ情報等々も含まれるとのこと。それで1.8GB・・・。(やっぱりでかくない?)
とりあえずsave/loadを使っとけばよさそうですね。

www.itmedia.co.jp
ただし、データベースなどでデータボリュームで指定されたディレクトリは保存しきれないと言ったことがあるようなので、注意が必要な模様です。
(イメージ化するcommitの時点で漏れるらしいので、これはsave/load、export/importのどちらの手段を使っても起こると思われる)