# Mosquitto server TLS加密連線 參考自https://www.itread01.com/content/1545349354.html 在Mosquitto中配置基於certificate的TLS/SSL ![](https://i.imgur.com/pUKdfXA.jpg) ## 證書(CA) 首先要用openssl製作一個證書(CA),參考官方文件即可。 先把官方的過程列下來,後面我的過程也有 ### 程序 1.建立ca.key、ca.crt 2.建立server.key、server.crt 3.建立client.key、client.crt 其中, server.crt中的CN, 必須與連線URL的FQDN相同, 例如連線URL為mqtts://iot.kh.edu.tw:8883, 則 server.crt 中的 CN 必須為 iot.kh.edu.tw。mosquitto1.6.10中不檢查憑證與連線URL是否相符, 但後面的版本就會檢查, 如果不相符就會出現`Error: A TLS error occurred.` 另外, ca.crt、server.crt、client.crt中的CN都必需不同。 ### 建立 ca.key、ca.crt ``` openssl req -new -x509 -days <duration> -extensions v3_ca -keyout ca.key -out ca.crt #<duration>指的是日數 ``` ## server(伺服端) ### 建立一個 server端的 Key ``` openssl genrsa -des3 -out server.key 2048 若不想加密碼, 則去掉 -des3 即可 openssl genrsa -out server.key 2048 ``` ### 用 server.key 去建立 server.csr ``` openssl req -out server.csr -key server.key -new ### 注意,當要求輸入CN(common name)的時候,請輸入你伺服器的域名或者IP 也可以將參數加入, 直接使用 openssl req -out server.csr -key server.key -new -subj "/C=TW/ST=TAIWAN/L=KAOHSIUNG/O=KH/OU=EDU/CN=alubasMQTT/emailAddress=alubas@gmail.com" ``` ### 傳送CSR給CA, 或者用自己的CA key進行簽章(Send the CSR to the CA, or sign it with your CA key) ``` openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days <duration> ``` ## client(客戶端) ### 建立一個 client端的 key ``` openssl genrsa -des3 -out client.key 2048 若不想加密碼, 則去掉 -des3 即可 openssl genrsa -out client.key 2048 ``` ### 用 client.key 去建立 client.csr ``` openssl req -out client.csr -key client.key -new 系統會要求回答一些參數: Country Name (2 letter code) [XX]:TW State or Province Name (full name) []:Taiwan Locality Name (eg, city) [Default City]:Kaohsiung Organization Name (eg, company) [Default Company Ltd]:KH Organizational Unit Name (eg, section) []:EDU Common Name (eg, your name or your server's hostname) []:163.32.x.x Email Address []:aluabs@gmail.com 也可以將參數加入, 直接使用 openssl req -out server.csr -key server.key -new -subj "/C=TW/ST=TAIWAN/L=KAOHSIUNG/O=KH/OU=EDU/CN=alubasMQTT/emailAddress=alubas@gmail.com" ``` ### 傳送CSR給CA或者用自己的CA key簽名(Send the CSR to the CA, or sign it with your CA key) ``` openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days <duration> ``` # 實作過程 首先建立ca.key和ca.crt,注意這裡有個坑,倒2行的Common Name,等等服務端和客戶端設定過程中也有這個,ca的Common Name 的值不能和客戶端和服務端的Common Name值一樣,否則無效 -days 我就設定365了,畢竟是測試用。 ## 1.建立ca.key、ca.crt ``` [root@mqttSrv]# /etc/mosquitto# mkdir ca [root@mqttSrv]# /etc/mosquitto# cd ca [root@mqttSrv]# /etc/mosquitto/ca# openssl req -new -x509 -days 365 -extensions v3_ca -keyout ca.key -out ca.crt Generating a 2048 bit RSA private key ............+++ ...............................................................+++ writing new private key to 'ca.key' Enter PEM pass phrase:<---輸入自訂密碼 Verifying - Enter PEM pass phrase: ----- 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]:TW State or Province Name (full name) [Some-State]:TAIWAN Locality Name (eg, city) []:KAOHSIUNG Organization Name (eg, company) [Internet Widgits Pty Ltd]:KH Organizational Unit Name (eg, section) []:EDU # 就是這個,和後面的不能一樣 Common Name (e.g. server FQDN or YOUR name) []:mqttSrv Email Address []:. ``` 這步走完生成了兩個檔案 ``` [root@mqttSrv]# /etc/mosquitto/ca# ll total 16 drwxr-xr-x 2 root root 4096 Nov 11 17:27 ./ drwxr-xr-x 3 root root 4096 Nov 11 17:26 ../ -rw-r--r-- 1 root root 1285 Nov 11 17:27 ca.crt -rw-r--r-- 1 root root 1834 Nov 11 17:27 ca.key ``` ## 2. server 端 ### 2.1 建立 server.key ``` [root@mqttSrv]# /etc/mosquitto/ca# openssl genrsa -des3 -out server.key 2048 Generating RSA private key, 2048 bit long modulus .........+++ ...................+++ e is 65537 (0x10001) #### 注意~這裡設定的-des3就會設定使用server.key要提供密碼,啟動mosquitto服務要用到 Enter pass phrase for server.key: <---輸入自訂密碼 Verifying - Enter pass phrase for server.key: ``` ### 2.2產生 server.csr ``` [root@mqttSrv]# /etc/mosquitto/ca# openssl req -out server.csr -key server.key -new Enter pass phrase for 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]:TW State or Province Name (full name) [Some-State]:TAIWAN Locality Name (eg, city) []:KAOHSIUNG Organization Name (eg, company) [Internet Widgits Pty Ltd]:KH Organizational Unit Name (eg, section) []:EDU # 這裡設定成主機的ip了,沒試過別的行不行 Common Name (e.g. server FQDN or YOUR name) []:192.168.193.128 Email Address []:. Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:lxy128server An optional company name []:. ``` #### 最好不要設定密碼(即去掉-des3), 因為加上密碼後, 每次啟用mosquitto都要輸入密碼, 安全性雖較高,但不實際。 ### 2.3 產生 server.crt(傳送CSR給CA或者用自己的CA key簽名) ``` [root@mqttSrv]# /etc/mosquitto/ca# openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 Signature ok subject=/C=TW/ST=TAIWAN/L=KAOHSIUNG/O=KH/OU=EDU/CN=192.168.193.128 Getting CA Private Key Enter pass phrase for ca.key: ``` 這步走完ca目錄下有這些檔案 ``` [root@mqttSrv]# /etc/mosquitto/ca# ll total 32 drwxr-xr-x 2 root root 4096 Nov 9 23:13 ./ drwxr-xr-x 4 root root 4096 Nov 9 23:06 ../ -rw-r--r-- 1 root root 1285 Nov 9 23:09 ca.crt -rw-r--r-- 1 root root 1834 Nov 9 23:09 ca.key -rw-r--r-- 1 root root 17 Nov 9 23:13 ca.srl -rw-r--r-- 1 root root 1172 Nov 9 23:13 server.crt -rw-r--r-- 1 root root 1029 Nov 9 23:12 server.csr -rw-r--r-- 1 root root 1743 Nov 9 23:11 server.key ``` ## 3.Client端 ### 3.1 建立 client.key ``` [root@mqttSrv]# /etc/mosquitto/ca# openssl genrsa -des3 -out client.key 2048 Generating RSA private key, 2048 bit long modulus ......+++ ......+++ e is 65537 (0x10001) # 注意,這裡設定的是客戶端sub/pub的時候需要的密碼 Enter pass phrase for client.key: Verifying - Enter pass phrase for client.key: ``` #### 最好不要設密碼(即去掉-des3),因為每次使用這個client.key都要輸入密碼,安全性高卻不實際。 ### 3.2 產生 client.csr ``` [root@mqttSrv]# /etc/mosquitto/ca# openssl req -out client.csr -key client.key -new Enter pass phrase for client.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]:TW State or Province Name (full name) [Some-State]:TAIWAN Locality Name (eg, city) []:KAOHSIUNG Organization Name (eg, company) [Internet Widgits Pty Ltd]:KH Organizational Unit Name (eg, section) []:EDU Common Name (e.g. server FQDN or YOUR name) []:192.168.193.128 Email Address []:. Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:. An optional company name []:. ``` ### 3.3 產生 client.crt ``` [root@mqttSrv]# /etc/mosquitto/ca# openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 Signature ok subject=/C=cn/ST=fj/L=fz/O=wecon/OU=r3/CN=192.168.193.128 Getting CA Private Key Enter pass phrase for ca.key: ``` #### 注意, 產生client.crt的過程中, 需要有ca.crt、ca.key, 因此, 如果製作過程不在mqttSrv上, 要記得把這兩個檔複製過去。 打完這一套,就有下面這些個檔案 [root@mqttSrv]# /etc/mosquitto/ca# ll total 44 drwxr-xr-x 2 root root 4096 Nov 9 23:15 ./ drwxr-xr-x 4 root root 4096 Nov 9 23:06 ../ -rw-r--r-- 1 root root 1285 Nov 9 23:09 ca.crt -rw-r--r-- 1 root root 1834 Nov 9 23:09 ca.key -rw-r--r-- 1 root root 17 Nov 9 23:15 ca.srl -rw-r--r-- 1 root root 1172 Nov 9 23:15 client.crt -rw-r--r-- 1 root root 1029 Nov 9 23:14 client.csr -rw-r--r-- 1 root root 1743 Nov 9 23:13 client.key -rw-r--r-- 1 root root 1172 Nov 9 23:13 server.crt -rw-r--r-- 1 root root 1029 Nov 9 23:12 server.csr -rw-r--r-- 1 root root 1743 Nov 9 23:11 server.key ## 4.mosquitto.conf 設定 到mosquitto.conf中進行設定,我這裡直接加在最後面 ``` port 8883 cafile /etc/mosquitto/ca/ca.crt keyfile /etc/mosquitto/ca/server.key certfile /etc/mosquitto/ca/server.crt require_certificate true use_identity_as_username false # 如果要以帳號密碼登入, 則需再加上 pwfile.conf 密碼檔案 # password_file /etc/mosquitto/pwfile.conf ``` 設定完重啟mosquitto ``` [root@mqttSrv]# systemctl restart mosquitto ``` 應該會出現失敗, 因為前面的server.key, 有加上密碼(-des3), 在系統啟動時會要求輸入密碼, 當使用systemctl 這類啟動service的作法, 無法輸入密碼, 故而造成錯誤。因此, **必需重新產生不加密碼的 server.key**。 看到日誌沒有報錯,就成功了。 [root@mqttSrv]# systemctl start mosquitto 1541842331: mosquitto version 1.5.3 starting 1541842331: Config loaded from /etc/mosquitto/mosquitto.conf. 1541842331: Opening ipv4 listen socket on port 8883. 1541842331: Opening ipv6 listen socket on port 8883. ## 5.client端以TLS連線到mosquitto ### 訂閱 mosquitto_sub ``` [root@mqttSrv]# mosquitto_sub -h 192.168.193.128 -p 8883 \ -t "ssl/topic/#" \ --cafile /etc/mosquitto/ca/ca.crt \ --cert /etc/mosquitto/ca/client.crt \ --key /etc/mosquitto/ca/client.key \ -u alubas -P haha1234 ``` -h 主機 -p 埠 -t 話題,訂閱 ssl/topic/下的所有主題 --cafile 指定ca.crt --cert 客戶端的client.crt --key 客戶端的client.key 如果mosquitto.conf 還設定使用password_file登入,則必需再帶上使用者名稱密碼,如果 這項 use_identity_as_username設為 true,那就不用了 -u alubas 帳號 -P haha1234 密碼 #### 系統日誌 ``` 1541842539: New connection from 192.168.193.128 on port 8883. 1541842543: New client connected from 192.168.193.128 as mosqsub|19778-ubuntu (c1, k60, u'alubas'). ``` ### 發佈 mosquitto_pub ``` [root@mqttSrv]# mosquitto_pub -h 192.168.193.128 -p 8883 \ -t "ssl/topic/128" \ --cafile /etc/mosquitto/ca/ca.crt \ --cert /etc/mosquitto/ca/client.crt \ --key /etc/mosquitto/ca/client.key \ -m "Hello world, I am a TLS client, and publishing msg to mqttSrv at port 8883" \ -u alubas -P haha1234 ``` 參數基本上和訂閱一樣,如果client.key有加密碼, 執行時也必需同步輸入。 #### 監聽端收到訊息了 ``` [root@mqttSrv]# mosquitto_sub -h 192.168.193.128 -p 8883 -t "ssl/topic/#" \ --cafile /etc/mosquitto/ca/ca.crt \ --cert /etc/mosquitto/ca/client.crt \ --key /etc/mosquitto/ca/client.key \ -u alubas -P haha1234 Hello world, I am a TLS client, and publishing msg to mqttSrv at port 8883 ``` ## 6.好用的工具- [generate-CA](https://github.com/owntracks/tools/blob/master/TLS/generate-CA.sh) 一套自動化產生 server 端和 client 端所需全部檔案的工具, 基本上就是把前面所有的程序打包起來, 但我建議先一步一步敲指令, 等熟練後再使用 generate-CA, 以免不知其所以然~ 使用前要先修改環境變數, 例如: IPLIST="192.168.193.128" HOSTLIST="mqttSrv.alubas.com" 執行 generate-CA.sh 可產生server 端所需檔案 執行 generate-CA.sh client pc1 可產生 client 端所需的檔案(pc1.key, pc1.crt, pc1.csr) 打完收工~ alubas@20211220