MQTTのプロトコルを理解するために、MacのDockerでMQTTのブローカー(mosquitto)を動かしてtcpdumpしてWiresharkで見てみる。

# はじめに
MQTTを使うならもうちょいプロトコルを理解しておいたほうがよいかなと思ったので、パケットを観察してみた。

# しなかったこと
## AWS IoT（あきらめた）
最初、AWS IoTにpublishしたりsubscribeしたりするところを観察してたけど、tlsで暗号化されてて、復号の仕方がいまいちわかんなかった。なので、まずは、ローカルでmosquittoってのを動かして試すことにした。

## コンテナ
Mac上のコンテナで作業したけれど、mosquittoのオフィシャルイメージは使わなかった。既存のコンテナを使ったので。
[eclipse-mosquitto - Docker Hub](https://hub.docker.com/_/eclipse-mosquitto)

コンテナを分けるのも考えたけど、めんどくさくなってやめた。
全部localhostでやると、だれがpub/subしたかわからないので、真面目にやるにはこういう環境が必要そう。
[DockerとMosquitto™でMQTTに触れる - Qiita](https://qiita.com/narutaro/items/e48def9dca38036f01f9)

# したこと
## 環境
適当にDockerのコンテナ作って作業した。
debian系。

mosquittoはこんな感じでいれた。
`mosquitto-clients`をいれないと、`mosquitto-sub`とか使えなかった。

```bash
apt-get install mosquitto
apt-get install mosquitto-clients
```

## tcpdump
ここらを参考にしようとしたけど、`docker0`が見当たらなかった。
[Dockerコンテナの上で流れるパケットをキャプチャ方法 - Qiita](https://qiita.com/koduki/items/6ae20f6052ec5239164e)

macOSだとないっぽい。他のOSでどう見えるか確認してないけども。

[Docker Desktop for Mac のネットワーク機能 | Docker ドキュメント](https://matsuand.github.io/docs.docker.jp.onthefly/docker-for-mac/networking/)
> macOS 上に docker0 ブリッジがない🔗
Docker Desktop for Mac におけるネットワーク機能の実装方法により、ホスト上から docker0 インターフェースを見ることはできません。 このインターフェースは仮想マシン内にあります。

よくわからないので、コンテナ内で、ダンプした。ローカルでしか動かしてないので、`lo`を見てる。

```bash
tcpdump -i lo -s 0 -w ./hoge4.cap
```

ちなみに、これで`lo`とか`eth0`とかの情報みれた。`ifconfig`は入ってなかった。

```bash
ip a
```

## mosquitto
これで、ブローカーを動かしてそう。

```bash
mosquitto -d
```

subscriber側。

```bash
mosquitto_sub -h localhost -t topic/001
```

publisher側。

```bash
mosquitto_pub -h localhost -t topic/001 -m "hello!"
```

publishすると、subscriber側で、メッセージが表示される。

## Wireshark
capファイルは、コンテナからMacに移動して読み込んでる。vscodeだと、右クリックからのDownloadで持ってこれるから楽。コマンド覚えなくても直感的にわかっていい感じ。楽。

上記方法でdumpしたcapファイルをOpenすると、こんな感じで見える。

![Screen Shot 2020-12-28 at 23.04.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/47c4a4a0-9fcf-5d0a-d05f-a440b7c73f8b.png)

protocolがMQTTのだけ表示している。
TCPのヘッダ情報とMQTTのパケット情報をいい感じに見れる。
MQTTの情報もいい感じに解析してくれて表示してくれるので、フォーマット知らなくてもそれっぽい情報を理解できる。
encryptされてないので、portは1883。
QoSが`At most once delivery`なこともわかる。
それっぽい流れがみれる。ただ、全部ローカルで動いてるので、だれ（pub or sub or ブローカー）がどれかわかりにくい・・・。

こんな感じ。

- Conn→Conn ack→Sub→Sub ack
- Conn→Conn ack→Pub→Pub→Disconn

# 最後に
パケットの中身みれると、プロトコルの理解が進む。教科書的な情報だけやと、イメージしにくいので。もうちょい、いろいろ試してみるか。

# 参考
## 仕様
ここがやたら詳しい。ありがたや。

[MQTT Version 3.1.1 をふりかえる - OPTiM TECH BLOG](https://tech-blog.optim.co.jp/entry/2019/08/20/163000)

> しかしそれ故か、中途半端な実装のものが多く、細かい挙動までをカバーしたライブラリ自体は少ないのもまた事実です。

これが、衝撃的。まじか。

こっちの方の記載も参考になった。簡潔で丁寧。
[MQTTを調べている - Qiita](https://qiita.com/narutaro/items/1837e392ef3255c9d6b2)

## wiki

[MQTT - Wikipedia](https://en.wikipedia.org/wiki/MQTT)
> The default unencrypted MQTT port is 1883. The encrypted port is 8883.[19]

確かに、1883やった。


## パケットのキャプチャ
先人。
[MQTTのパケットを覗いてみた(1) | MQTT and ...](https://mm011106.github.io/2014/12/20/mqtt-packets/)

## その他
これ、気になる。そのうち試してみたいけど、時間とれるかなぁ。
[MQTTの通信を可視化する - shiftr.io - Qiita](https://qiita.com/narutaro/items/5a9102f4a2e29e4525db)

## mosquitto
参考にした。
ドローン楽しそう。
[MQTTブローカーのセットアップ - Qiita](https://qiita.com/hsgucci/items/be9665bafe6e449377c9)

## TLS
ここらを参考にdecryptしようとしたけど、よくわからず断念。
HTTPSやから、今回やろうとしてるところとも、雰囲気違いそう、
もうちょい、基礎的な知識が必要そう。勉強したことあった気もするけど、わからんかった。
出直してこよう。
[Wireshark Tutorial: Decrypting HTTPS Traffic (Includes SSL and TLS)](https://unit42.paloaltonetworks.com/wireshark-tutorial-decrypting-https-traffic/)
[HTTPSのパケットをwiresharkで見てみる - Qiita](https://qiita.com/toshihirock/items/acbf9800f7e784118e46)
[【解析】https(SSL/TLS)をwiresharkで復号化する方法(SSLKEYLOGFILE),ブラウザで見る方法 | SEの道標](https://milestone-of-se.nesuke.com/nw-basic/tls/decrypt-tls-at-executing-packetcapture/)

Macで`SSLKEYLOGFILE`にログをためるのは、こんな感じらしい。
[Wireshark で HTTP/2 over TLS の通信をダンプする方法 · GitHub](https://gist.github.com/summerwind/a482dd1f8e9887d26199)