Docker でコンテナをコミットする
以下、コミットの流れを備忘録として残します。
コミット
docker commit <コンテナID> <コミット名>:<tag>
上記でコミットしたコンテナは、イメージとして利用できるみたいです。
docker run -it <コミット名>:<tag>
コンテナへのアタッチ
ついでに、コンテナへのアタッチ方法です。
アタッチとは、コンテナをイメージとして起動するのではなく、コンテナをそのまま起動する?感じだと思っています。
# 開始 docker start <コンテナID> # アタッチ docker attach <コンテナID>
なぜか docker attach
は実行後、 Enter を2回押さないといけません。
mosquitto で CommonName が異なっていても無理やり TLS 接続できるようにする
追記(修正)
mosquitto Ver1.4.15 にて修正されているようです。
ですので、最新の mosquitto を使用すると、 CommonName が異なっていても、 --insecure
オプションをつければ、無理やり TLS 接続できます。
mosquitto クライアントアプリの TLS 接続における CommonName に関する仕様
mosquitto のクライアントアプリである「mosquitto_sub」および「mosquitto_pub」の仕様で、TLS接続する際、サーバーの証明書1に含まれるコモンネーム(CommonName)とサーバー(ブローカー)の接続先名称が異なる場合は接続に失敗する。
例えば、サーバーの証明書に含まれる CommonName が i_love_coffee
だった場合、クライアント側の接続は以下のようになる。
# 接続失敗 $ mosquitto_sub -t abc -h 192.168.0.1 -p 8883 -d --cafile <CAの証明書> Error: A TLS error occurred. # 接続成功 $ mosquitto_sub -t abc -h i_love_coffee -p 8883 -d --cafile <CAの証明書> Client mosqsub/1900-i_love_coffee sending CONNECT Client mosqsub/1900-i_love_coffee received CONNACK Client mosqsub/1900-i_love_coffee sending SUBSCRIBE (Mid: 1, Topic: abc, QoS: 0) Client mosqsub/1900-i_love_coffee received SUBACK Subscribed (mid: 1): 0
接続しようとするサーバーと CommonName が異なれば TLS 接続失敗するというのは、セキュリティ上至極まっとうである。
しかし、オレオレ認証したりデバッグする環境では、 CommonName なんて気にしたくないし、実行環境がころころ変わる場合もあり、かなり不便。
--insecure
オプション・・・
一応、 --insecure
オプションをつけると、ホスト名等を気にせずサーバー認証できると、 マニュアルに書いてあるが、実際にそのオプション付けても、 CommonName が異なるとはじかれる。
(これバグなの?仕様?)
mosquitto の改造
ということで、今回、ソースコードを変更して無理やり CommonName が異なっていても TLS 接続できるようにしてみた。
変更仕様としては以下である。
--insecure
オプションを付加した場合のみ、サーバーの証明書に含まれる CommonName と接続先サーバー(ブローカー)名が異なっていても、 TLS 接続可能とする- 対象は
mosquitto.dll
- mosquitto_sub と mosquitto_sub は
mosquitto.dll
をロードして動作するため、この DLL を変更してデプロイすれば、変更される
- mosquitto_sub と mosquitto_sub は
で、ソースの変更内容は以下である。
とりあえずこれで、目的を達成することができた。
SSL/TLS の仕組みについて備忘録
備忘録と言いつつ、ほとんど参考サイトの掲載になるが、↓のサイトの「デジタル証明書の仕組み」の絵が非常に参考になります。
これで、認証局とか CSR(証明書要求)とかの登場人物がどういう関係かがわかります。最強です。感謝。
なお、自分なりに少し情報を整理してみます。
以前やった OpenSSL による SSL/TLS 環境の作成で出てきた拡張子とそれが何なのか?
ca.key
:認証局の秘密鍵と公開鍵の対情報。オレオレ認証のときは自分で作るが、普通は認証局の中で厳密に保管されているはず。ca.crt
:認証局のルート証明書。中身は認証局の公開鍵と認証局の情報をデジタル署名されたものが含まれている。これもオレオレ認証では自分で作るが、普通は認証局が公開している。server.key
:サーバーの秘密鍵と公開鍵の対情報。server.csr
:サーバーの証明書署名要求。中身はサーバーの公開鍵とコモンネーム等の各種証明書。各種証明書を認証局にデジタル署名してもらうと*.crt
になる。server.crt
:認証局によるサーバー証明書。中身はサーバー公開鍵と認証局によりディジタル署名されたサーバーの各種証明書。これは認証局の公開鍵で復号できる。
なお、↓も非常に参考になります。
mosquitto を Visual Studio でコンパイルする
githubに公開されている mosquitto のソースファイルを、Visual Studio でコンパイルします。
前提
- 今回は Visual Studio 2010 を使用する(たぶん2017とかでも大丈夫)
- Visual Studio の C++ コンパイラがインストールされていることが前提
- CMake を使用して Visual Studio のソリューションファイルを生成する
CMake を使用してソリューションファイルを生成
ここでは、CMake のインストール方法については言及しません。
mosquitto のソースファイルの用意
mosquitto のリポジトリを github からクローンします。
CMake のビルド環境を用意
必要ファイルのダウンロード
Readmeに書いてある通り、以下をそれぞれ用意する必要があります。
OpenSSL
- Link: http://slproweb.com/products/Win32OpenSSL.html
- Install "Win32 OpenSSL
" - Required DLLs: libeay32.dll ssleay32.dll
pthreads
- Link: ftp://sourceware.org/pub/pthreads-win32
- Install "pthreads-w32-
-release.zip - Required DLLs: pthreadVC2.dll
環境変数の設定
ここで、ビルドを通すために、以下の通り環境変数を設定する必要があります。
- OpenSSL
OPENSSL_ROOT_DIR
という環境変数名で、OpenSSLの の展開フォルダを設定(例:c:\temp\OpenSSL-Win32\
)
CMake のビルドを実行
CMake を起動し、以下を指定し、 Configure ボタンを押す。
Where is the source code:
に、 mosquitto のCMakeList.txt
の存在するパスWhere to build the binaries:
に、ソリューションを出力するフォルダパス
コンパイラに何を使うか聞かれるので、今回は Visual Studio 2010 を選択しました。
Finish ボタンを押すと、自動でコンパイルが走ります。
が、たぶん、 c-ares library not found
とか言って怒られるので、画面上の WITH_SRV
のチェックボックスを外し、再度 Generate すします。
正常に終了したら、CMake のコンソール上に Generating done
と表示されます。
すると、指定したフォルダに、 Visual Studio のソリューションファイルが出力されています。
参考
Visual Studio で mosquitto をビルドする
生成されたソリューションファイル(mosquitto.sln
)を起動します。
そのままビルドしてもエラーになるので、以下のようにライブラリの設定をします。
OpenSSL の環境変数
system の Path
環境変数に、OpenSSLの の展開フォルダ\bin を設定します。(例: c:\temp\OpenSSL-Win32\bin\
)
pthreads の設定
pthreads を展開したフォルダから、以下のものをコピーしていきます。
ヘッダファイル
- pthread.h
- sched.h
- semaphore.h
上記ファイルを、C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include
へコピー
lib ファイル
- pthreadVC2.lib
- pthreadVCE2.lib
- pthreadVSE2.lib
上記ファイルを、 C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib
へコピー
dll ファイル
- pthreadGC2.dll
- pthreadGCE2.dll
- pthreadVC2.dll
- pthreadVCE2.dll *pthreadVSE2.dll
上記ファイルを、 C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin
へコピー
参考
全ては時の中に… : 【VC++】スレッド(pThread)を利用する環境を整える
ビルド実行
上記でたぶん、ビルドできるはずです。
とりあえず mosquitto_sub をコンパイルしてみましたが、警告が出まくりますが、なんとか mosquitto_sub.exe が出力されました・・・
EMQ を使用して mqtt の通信をする
EMQ とは
EMQ とは、 Erlang で実装された mqtt ブローカーです。
mqtt ブローカーとしては mosquitto が有名ですが、以下の特徴があります。
- mosquitto と比較しても、 EMQ もなかなか性能が良い(らしい)
- mosquitto ではできない、ブローカーのクラスタを実現できる
- Web ブラウザの GUI が提供されているので、クライアントの管理がしやすい
Document
英語ですが、こちらに公式ドキュメントが公開されています。
インストール
環境は、 Windows 10 64bit とします。
EMQ からダウンロードして、C直下にでも解凍します。解凍するだけで、OS へのインストール作業は不要です。
ブローカーの設定
とりあえずここでは、クラスタ設定は省略します。単一ブローカーのみの接続を想定します。
C:\emqttd\etc\emq.conf
(C直下に解凍した場合)がブローカーの設定ファイルです。
IPアドレスの設定
以下を変更します。ここでは、ブローカーのIPアドレスを 192.168.0.1
を想定します。
設定キー名 | 変更前 | 変更後 |
---|---|---|
node.name | node.name = emq@127.0.0.1 | node.name = emq@192.168.0.1 |
listener.tcp.external | listener.tcp.external = 127.0.0.1:1883 | listener.tcp.external = 192.168.100.106:1883 |
listener.tcp.internal | listener.tcp.internal = 127.0.0.1:11883 | listener.tcp.internal = 192.168.100.106 |
listener.tcp.external
(たぶうんグローバルIPアドレス) は設定不要かもしれません
SSLの設定
↓に雑ですが記載しています。
ブローカーの起動
C:\emqttd
フォルダに移動し、コマンドプロンプトで以下を実行します。
bin\emqttd console
最初の起動では、ファイアウォールの許可みたいなのが出るかもしれませんが、[OK] すればよいです。
ちょっと待つと、Erlang のウィンドウが表示されます。
ウィンドウ内で (emq@192.168.0.1)1> Load emq_mod_presence module successfully.
と表示されれば、起動成功です。
Web ブラウザで確認
上記の起動方法でブローカーが正常に起動しているならば、http://localhost:18083/へアクセスするとダッシュボードが表示されます。
終了方法
Eranlg のウィンドウを閉じれば、同時にブローカーも停止します。
クラスタについて
今回は省略しましたが、クラスタに関しては、以下が参考になります。
EMQ で TLS 接続する
今回はEMQ(emqttd)を使用して、mqtt の TLS 接続をする方法。
EMQのインストール方法とかは割愛。
サーバーの公開鍵/暗号鍵の生成、それらのオレオレ認証
↓が参考になった。
基本的には前記事の mosquitto の場合と同じ。
EMQ側の設定を変更
これも↑のサイトのまんまになるが、一つ気を付けないといけないのが、公開鍵の生成時に「CommonName」にブローカーの FQDN を設定する必要があること。
ここは mosquitto の場合と同じで、 CommonName とブローカーのホスト名が異なると、 TLS 接続できない。
mosquitto で OpenSSL を 用いて TLS 接続する
mosquitto をで TLS 接続する方法です。
OpenSSL を使用するのが簡単だと思うけど、ちょっと間が空くとすぐやり方を忘れてしまうので備忘録として残しておきます。
2018/03/11 追記/修正
いろいろ TLS について勉強してみると、言葉の使い方や理解が正しくない箇所が複数あったので修正しました。
そして、まだ勉強不足なので間違っている箇所がある可能性は十分あります・・・。
前提
- OS : Windows 10 64bit
- mqtt ブローカーもクライアントも mosquitto を使用する
- 秘密鍵/公開鍵やサーバー証明書の生成は、OpenSSL を使用して行う
- TLS するためのサーバー証明書は、自己認証局(オレオレ認証局)で実現する
- あらかじめ pfx 形式1のものが存在しており、それを使用して自己認証局の開局する
(pfx ファイルのパスワードは把握しているものとする)
今回は 5. が特殊な条件ですが、現案件がこういう条件下なのでこれを前提で記述します。
pfx ファイルを秘密鍵/公開鍵情報とルート証明書に分離する
pfx ファイル(ca.pfx
)を OpenSSL を使用して秘密鍵/公開鍵情報(ca.key
)と自己認証局のルート証明書(ca.crt
)に分離します。
# 秘密鍵/公開鍵の取り出し $ openssl pkcs12 -in ca.pfx -nocerts -nodes -out ca.key Enter Import Password: # ca.pfx ファイルのパスワードを入力 MAC verified OK # ca.key が出力される # 自己認証局のルート証明書の取り出し $ openssl pkcs12 -in ca.pfx -clcerts -nokeys -out ca.crt Enter Import Password: # ca.pfx ファイルのパスワードを入力 MAC verified OK # ca.crt が出力される
mosquitto で TSL 接続を行う場合は、出来上がった crt ファイルをOSに「信頼できるルート証明書」として登録する必要はないので、事実上これで自己認証局の開局は済んだことになります。(mosquitto を起動する際に、ブローカーでもクライアントでも、起動引数にパスを付加することでこのルート証明書を使用します)
参考
サーバー(ブローカー)の秘密鍵/公開鍵を生成
ブローカーの TSL 接続用の秘密鍵/公開鍵として server.key
を生成します。
# 秘密鍵/公開鍵生成 $ openssl genrsa -out server.key 2048
サーバー(ブローカー)のサーバー証明書署名要求の作成
「証明書署名要求」とは、公開鍵にコモンネーム(Common Name
)等のサーバーの情報を付加したものです。
ブローカーの証明書署名要求として server.csr
を生成します。
# 証明書署名要求の生成 $ openssl req -out server.csr -key server.key -new
いろいろ入力を促されますが、とりあえずはオレオレ認証なので Common Name (e.g. server FQDN or YOUR name) []:
以外は全て未入力(そのまま Enter )でよいです。
Common Name
には、ブローカーの FQDN (ホスト名またはIPアドレス)を入力する必要があります。
もし正しく FQDN を入力しなかったら、Error: A TLS error occurred.
と言われてブローカーと接続できません。
Common Name
(コモンネーム)について追記
そもそも、SSL/TLS 接続を行う際に、クライアント側がサーバーを認証する(なりすましでないと特定する)手法が、サーバーへの接続文字列とコモンネームを比較することらしいです。
つまり、コモンネームが一致しないならば、相手が本物と特定できない(クライアントは相手がなりすましだと思わざるをえない)ので、それくらいコモンネームは重要です。
詳細は↓のサイトが非常に参考になります。
このサイトは SSL 接続の知識が体系的にまとめられていて、非常に勉強になります。
サーバー証明書の署名と発行
上記で生成したサーバー証明書署名要求を、自己認証局の秘密鍵(ca.key
)でデジタル署名して、サーバー証明書を発行します。
# サーバー証明書の署名と発行 $ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 36500
ここでは、有効期限を100年としています。(普通はこんなことしませんが、オレオレ認証なので・・・)
とりあえずここまでで、 OpenSSL を使用した TSL 接続用の鍵生成や署名は終了です。
参考
mosquitto.conf の設定
TSL 接続で使用する各証明書ファイルのパスを mosquitto.conf
に追加します。
ファイルのどこに書いても良いそうです。
// C:\Program Files (x86)\mosquitto\mosquitto.conf listener 8883 cafile ./certs/ca.crt certfile ./certs/server.crt keyfile ./certs/server.key
ここでは、上記で生成した鍵等を、 C:\Program Files (x86)\mosquitto\certs
に入れているものとしています。
動作確認
# ブローカーの起動 $ mosquitto -v -c mosquitto.conf 1520414168: mosquitto version 1.4.12 (build date 29/05/2017 11:24:45.10) starting 1520414168: Config loaded from mosquitto.conf. 1520414168: Opening ipv6 listen socket on port 8883. 1520414168: Opening ipv4 listen socket on port 8883.
# mosquitto_sub の起動 $ mosquitto_sub -d -t test -h <BrokerのFQDN> -p 8883 --cafile ./certs/ca.crt
# mosquitto_pub の起動 $ mosquitto_pub -d -t test -m aaaaaa -h <BrokerのFQDN> -p 8883 --cafile ./certs/ca.crt