WebArenaでMQTTサーバを立てたときに、電子証明書はWebサーバのものを使うように設定しましたが、これだとLet’s Encryptでサーバ証明書やフィンガープリントが更新されたときに困ってしまいます。
ですので、mosquitto用に専用の証明書を用意します。Webブラウザは関係ないので、今回はオレオレ証明書で行くことにします。といっても、ほぼこちらの記事のままです。ですので、参考にされる方はこちらの記事を見てください。あと、公式ドキュメントも参考になります。以下は自分の作業記録として必要な部分だけです。
証明書の生成
まず、CA証明書に必要な秘密鍵を生成します。-des3を付けるとパスフレーズ必須なので、なにか考えておきます。
ubuntu@i-xxxxxxxxxxxxxx:~$ sudo su -
root@i-xxxxxxxxxxxxxx:~# cd /etc/mosquitto/certs/
root@i-xxxxxxxxxxxxxx:/etc/mosquitto# ls -la certs
total 12
drwxr-xr-x 2 root root 4096 Oct 2 13:47 .
drwxr-xr-x 5 root root 4096 Oct 2 13:47 ..
-rw-r--r-- 1 root root 130 Jun 18 2019 README
root@i-xxxxxxxxxxxxxx:/etc/mosquitto# chown mosquitto.mosquitto certs
root@i-xxxxxxxxxxxxxx:/etc/mosquitto# chmod 700 certs
root@i-xxxxxxxxxxxxxx:/etc/mosquitto# ls -la certs
total 12
drwx------ 2 mosquitto mosquitto 4096 Oct 2 13:47 .
drwxr-xr-x 5 root root 4096 Oct 2 13:47 ..
-rw-r--r-- 1 root root 130 Jun 18 2019 README
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# sudo -u mosquitto openssl genrsa -des3 -out ca.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
...........................................+++++
....................................+++++
e is 65537 (0x010001)
Enter pass phrase for ca.key:
Verifying - Enter pass phrase for ca.key:
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# ls -la
total 16
drwx------ 2 mosquitto mosquitto 4096 Nov 8 05:50 .
drwxr-xr-x 5 root root 4096 Oct 2 13:47 ..
-rw-r--r-- 1 root root 130 Jun 18 2019 README
-rw------- 1 mosquitto mosquitto 1743 Nov 8 05:50 ca.key
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs#
※安全に鍵を保管できるなら、
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# openssl rsa -in ca.key -out ca_nopass.key
Enter pass phrase for ca.key:
writing RSA key
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs#
などとして秘密鍵からパスフレーズを削除することもできます。(-out の代わりに -text とすると、秘密鍵の内容をテキスト表示できます)
次に、秘密鍵を使って、CA証明書を生成します。設定は適当にしました。有効期間は7305日(20年)にしました。暗号強度的には20年も持つものではないと思いますが、しょせん趣味ですので、実質永遠とします。
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# sudo -u mosquitto openssl req -new -x509 -days 7305 -key ca.key -out ca.crt
Enter pass phrase for ca.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Tokyo
Organization Name (eg, company) [Internet Widgits Pty Ltd]:example.com
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:example.com
Email Address []:
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# ls -la
total 20
drwx------ 2 mosquitto mosquitto 4096 Nov 8 06:08 .
drwxr-xr-x 5 root root 4096 Oct 2 13:47 ..
-rw-r--r-- 1 root root 130 Jun 18 2019 README
-rw-rw-r-- 1 mosquitto mosquitto 1257 Nov 8 06:08 ca.crt
-rw------- 1 mosquitto mosquitto 1751 Nov 8 06:07 ca.key
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs#
サーバ証明書を生成します。
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# sudo -u mosquitto openssl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
.................................................+++++
..........................................................................+++++
e is 65537 (0x010001)
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# ls -la
total 24
drwx------ 2 mosquitto mosquitto 4096 Nov 8 06:09 .
drwxr-xr-x 5 root root 4096 Oct 2 13:47 ..
-rw-r--r-- 1 root root 130 Jun 18 2019 README
-rw-rw-r-- 1 mosquitto mosquitto 1257 Nov 8 06:08 ca.crt
-rw------- 1 mosquitto mosquitto 1751 Nov 8 06:07 ca.key
-rw------- 1 mosquitto mosquitto 1679 Nov 8 06:09 server.key
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs#
サーバ証明書を生成したCA証明書で認証してもらうのに必要なCSRファイルを作成します。
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# sudo -u mosquitto openssl req -new -out server.csr -key server.key
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Tokyo
Organization Name (eg, company) [Internet Widgits Pty Ltd]:example.com
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:example.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# ls -la
total 28
drwx------ 2 mosquitto mosquitto 4096 Nov 8 06:11 .
drwxr-xr-x 5 root root 4096 Oct 2 13:47 ..
-rw-r--r-- 1 root root 130 Jun 18 2019 README
-rw-rw-r-- 1 mosquitto mosquitto 1257 Nov 8 06:08 ca.crt
-rw------- 1 mosquitto mosquitto 1751 Nov 8 06:07 ca.key
-rw-rw-r-- 1 mosquitto mosquitto 964 Nov 8 06:11 server.csr
-rw------- 1 mosquitto mosquitto 1679 Nov 8 06:09 server.key
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs#
サーバ証明書をCAに認証してもらいます。
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# sudo -u mosquitto openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3605
Signature ok
subject=C = JP, ST = Tokyo, L = Tokyo, O = example.com, CN = example.com
Getting CA Private Key
Enter pass phrase for ca.key:
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# ls -la
total 36
drwx------ 2 mosquitto mosquitto 4096 Nov 8 06:11 .
drwxr-xr-x 5 root root 4096 Oct 2 13:47 ..
-rw-r--r-- 1 root root 130 Jun 18 2019 README
-rw-rw-r-- 1 mosquitto mosquitto 1257 Nov 8 06:08 ca.crt
-rw------- 1 mosquitto mosquitto 1751 Nov 8 06:07 ca.key
-rw-rw-r-- 1 mosquitto mosquitto 41 Nov 8 06:11 ca.srl
-rw-rw-r-- 1 mosquitto mosquitto 1135 Nov 8 06:11 server.crt
-rw-rw-r-- 1 mosquitto mosquitto 964 Nov 8 06:11 server.csr
-rw------- 1 mosquitto mosquitto 1679 Nov 8 06:09 server.key
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs#
ついでに、フィンガープリントも確認しておきます。
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# openssl x509 -sha1 -fingerprint -noout -in server.crt
SHA1 Fingerprint=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs#
mosquittoの設定変更
上記で生成した各ファイルを /etc/mosquitto/certs に配置します。(実際には /etc/mosquitto/certs で作業しました)
設定ファイルである、/etc/mosquitto/conf.d/default.conf を以下のように修正します。
allow_anonymous false
password_file /etc/mosquitto/passwd
listener 1883 localhost
listener 8883
certfile /etc/mosquitto/certs/server.crt
cafile /etc/mosquitto/certs/ca.crt
keyfile /etc/mosquitto/certs/server.key
listener 8083
protocol websockets
certfile /etc/mosquitto/certs/server.crt
cafile /etc/mosquitto/certs/ca.crt
keyfile /etc/mosquitto/certs/server.key
mosquittoを再起動します。
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/conf.d# service mosquitto restart
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/conf.d# service mosquitto status
● mosquitto.service - Mosquitto MQTT v3.1/v3.1.1 Broker
Loaded: loaded (/lib/systemd/system/mosquitto.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2020-11-08 06:32:06 JST; 4s ago
Docs: man:mosquitto.conf(5)
man:mosquitto(8)
Main PID: 155046 (mosquitto)
Tasks: 3 (limit: 1075)
Memory: 1.4M
CGroup: /system.slice/mosquitto.service
└─155046 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
Nov 08 06:32:06 i-xxxxxxxxxxxxxx systemd[1]: Starting Mosquitto MQTT v3.1/v3.1.1 Broker...
Nov 08 06:32:06 i-xxxxxxxxxxxxxx mosquitto[155046]: 1604784726: Loading config file /etc/mosquitto/conf.>
Nov 08 06:32:06 i-xxxxxxxxxxxxxx mosquitto[155046]: [3169503.676688]~DLT~155046~INFO ~FIFO /tmp/dlt >
Nov 08 06:32:06 i-xxxxxxxxxxxxxx systemd[1]: Started Mosquitto MQTT v3.1/v3.1.1 Broker.
Arduino側の証明書の更新
Arduino(esp32)側のWiFiClientSecure側に /etc/mosquitto/certs/ca.crt の内容を証明書として取り込んでファームウェアを更新します。
Arduino(esp8266)の場合には、証明書の検証ではなく、フィンガープリントの検証でサーバを確認しているので、
root@i-xxxxxxxxxxxxxx:/etc/mosquitto/certs# openssl x509 -sha1 -fingerprint -noout -in server.crt
SHA1 Fingerprint=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
として取得したフィンガープリントをファームウェアのソースコードに取り込んでファームウェアを更新します。
Linux上でのクライアント接続
以下のように、オプションに –cafile server.crt を追加してサーバ証明書を指定して接続します。
$ mosquitto_sub -t '/#' -h example.com -p 8883 -u ユーザ名 -P パスワード --cafile server.crt
–cafile オプションは ~/.config/mosquitto_sub にする際は以下のようにフルパスが必要(~は使えない)なようです。(考えてみれば、~はシェルの機能なのであたり前ですね・・)
-h example.com
-p 8883
-u MQTTユーザ名
-P MQTTパスワード
--cafile /home/ユーザー名/.config/mosquitto/server.crt
これで、コマンドラインから、
$ mosquitto_sub -t '/#'
といった感じでsubscribeできます。