서버 인증서 보기

openssl s_client -connect [mqtt server ip/domain]:8883

 

결과

CONNECTED(00000138)
Can't use SSL_get_servername
depth=1 C = KR, ST = seoul, O = korea_company, OU = lab, CN = dbserver, emailAddress = xxxx@korea.com
verify error:num=19:self signed certificate in certificate chain
verify return:1
depth=1 C = KR, ST = seoul, O = korea_company, OU = lab, CN = dbserver, emailAddress = xxxx@korea.com
verify return:1
depth=0 C = KR, ST = seoul, O = korea_company, OU = lab, CN = 192.168.99.225, emailAddress = xxxx@korea.com
verify return:1
---
Certificate chain
 0 s:C = KR, ST = seoul, O = korea_company, OU = lab, CN = 192.168.99.225, emailAddress = xxxx@korea.com
   i:C = KR, ST = seoul, O = korea_company, OU = lab, CN = dbserver, emailAddress = xxxx@korea.com
 1 s:C = KR, ST = seoul, O = korea_company, OU = lab, CN = dbserver, emailAddress = xxxx@korea.com
   i:C = KR, ST = seoul, O = korea_company, OU = lab, CN = dbserver, emailAddress = xxxx@korea.com
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDfTCCAmUCFAGMGehiEEUnQsHsJMEkWyausJtGMA0GCSqGSIb3DQEBCwUAMHgx
CzAJBgNVBAYTAktSMQ4wDAYDVQQIDAVzZW91bDENMAsGA1UECgwEa2l0czEMMAoG
A1UECwwDbGFiMREwDwYDVQQDDAhkYnNlcnZlcjEpMCcGCSqGSIb3DQEJARYaamFl
Y2hlb2wucGFya0Brb3JlYWl0cy5jb20wHhcNMjIwODI2MDEwNjUyWhcNMjIwOTI1
MDEwNjUyWjB+MQswCQYDVQQGEwJLUjEOMAwGA1UECAwFc2VvdWwxDTALBgNVBAoM
BGtpdHMxDDAKBgNVBAsMA2xhYjEXMBUGA1UEAwwOMTkyLjE2OC45OS4yMjUxKTAn
BgkqhkiG9w0BCQEWGmphZWNoZW9sLnBhcmtAa29yZWFpdHMuY29tMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiHgm9YBlp4/LoHtIPp0JG4LbQN8LjdOs
yBctKSsDWdPxa2JBKXBLYj0YTUtzcWUiDmkjOMjf8Wk0fiAYEZ/N+TR5W4afz+Qf
AV195YepblU0put2dX5o/2h/j/d9mvEAc46SkA9ehiX2U7EVwcHw1kbbqAfLFct9
d6ga6hU43H2gN1ME0O0c4YKPwYwckZih8JCxtMcP9CQzShBYulNtM8w9Dtgo7IA2
8TqukOGZGa6HNlLbHNb7d0XWRBunjw5dreg9w6QUKERLQml9oIEyE3H8mzBHHu39
DUNsPHvocKdK2otkGZRoZz/clriuZ0I2F+T8KtZiwrDjFjs5INHx3QIDAQABMA0G
CSqGSIb3DQEBCwUAA4IBAQBfs8kd4LHRGQMj+Ji1JixFrP+rVBgY4jypLv/YuP+L
Sgn8NWbglMVcVhmxlfvg5ULEIcZleV5D+iE08leajaAggLOrVY7qIVUtOVE3r/Qp
dVNyRdk3l8MygACXQLVy+hXehiNFSBkRi5qj2zaQJMHV5FDUkOBt2fvwSRwVpyob
bn3X2Tm+AbsSmNL49wc2EyKqCrCT45dZrzYCjd13WyiSkP4OrAGakeIipHLdNUhP
72KrsemVw35vBfnUOWjAzQtpcc5RlNFfTnY+/p0i2mNm50cab7rtEkZAD6CAmegb
wDfsdzKgBglfSzYIUfQXExDw/N2L788byyBPuy3nFQo8
-----END CERTIFICATE-----
subject=C = KR, ST = seoul, O = korea_company, OU = lab, CN = 192.168.99.225, emailAddress = xxxx@korea.com

issuer=C = KR, ST = seoul, O = korea_company, OU = lab, CN = dbserver, emailAddress = xxxx@korea.com

---
No client certificate CA names sent
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 2506 bytes and written 403 bytes
Verification error: self signed certificate in certificate chain
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 19 (self signed certificate in certificate chain)
---
read:errno=10054

 

생성된 인증서 확인

openssl verify -CAfile ca.crt server.crt

 

결과

server.crt: OK

 

인증서 내용 보기

openssl x509 -in ca.crt -text -noout

 

결과

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            06:56:e5:11:b1:16:46:8d:d8:fb:70:bd:41:d2:84:9e:3f:43:b5:31
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = KR, ST = seoul, O = korea_company, OU = lab, CN = dbserver, emailAddress = xxxx@korea.com
        Validity
            Not Before: Aug 26 01:06:12 2022 GMT
            Not After : Aug 26 01:06:12 2027 GMT
        Subject: C = KR, ST = seoul, O = korea_company, OU = lab, CN = dbserver, emailAddress = xxxx@korea.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:bb:87:40:77:8f:fa:07:70:11:27:35:b4:f6:13:
                    77:2e:33:9c:c6:9b:99:11:65:30:6a:dd:1a:be:0a:
                    93:0e:f7:d3:40:2a:7a:96:64:dc:75:33:cc:26:e5:
                    1c:6c:e7:23:b4:98:12:51:7d:b1:18:41:20:74:cb:
                    e9:f4:8a:0e:d3:72:05:91:69:07:f3:86:84:07:93:
                    cd:aa:dd:fa:12:72:d2:2e:ec:cd:77:5a:ec:1c:f2:
                    80:94:a6:b5:d5:4b:3e:ba:ee:71:74:b1:9f:7f:93:
                    31:9d:09:7f:40:64:79:b6:56:53:ea:fc:4a:fc:f4:
                    f5:09:26:c7:1b:97:0c:68:c9:71:34:d4:7f:f2:5c:
                    df:56:61:91:f3:57:b9:64:d7:82:e1:2c:bf:d2:1c:
                    60:03:37:26:d1:34:15:03:59:32:5a:4e:d6:39:bd:
                    ba:8b:2a:f2:bb:fa:e3:02:99:df:ea:7c:fe:aa:5e:
                    74:97:45:84:03:b6:45:7a:81:af:63:ea:bf:77:4b:
                    35:79:3a:3a:cf:19:2e:71:e0:10:a9:74:7f:eb:95:
                    d0:14:54:e3:00:05:04:1a:df:ce:84:b9:4d:17:8b:
                    ed:75:5d:b3:31:ea:ef:76:7f:2e:1c:f9:7d:f0:c7:
                    8e:53:7a:da:31:cb:8a:f2:b1:a7:f5:4b:ff:57:81:
                    41:8d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                04:6E:20:10:D2:C9:DB:CE:AE:70:D3:EF:98:BD:BC:9F:AF:0A:EB:91
            X509v3 Authority Key Identifier:
                keyid:04:6E:20:10:D2:C9:DB:CE:AE:70:D3:EF:98:BD:BC:9F:AF:0A:EB:91

            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         3f:33:88:41:c7:45:73:f9:1f:09:2a:bf:a9:9e:f8:da:79:75:
         b6:03:f1:e1:a9:75:d9:0b:02:63:35:5e:09:af:df:31:52:94:
         8b:90:c5:d6:ac:e0:64:ee:d1:46:47:09:6b:76:6a:0e:04:60:
         f0:37:24:79:f7:1a:83:f0:08:c7:60:b9:d0:f5:3d:60:71:77:
         64:a3:b4:21:19:6d:9d:69:ea:a5:7b:6d:f0:b9:9a:96:39:24:
         b4:e3:7a:ec:25:0e:5e:a3:23:5e:fe:9d:b3:8a:28:2b:96:28:
         76:3b:e1:de:e9:3a:df:b6:72:42:dd:8b:d4:2c:5f:e1:2c:e4:
         6d:b1:32:2a:51:6b:33:ce:e6:f7:4a:cf:96:f0:96:9a:a4:32:
         b1:fc:94:aa:82:a6:f3:f2:8f:ae:74:93:93:86:a9:1c:7d:d2:
         2e:2e:fb:f1:08:68:a8:57:49:72:b1:ed:b8:c1:da:c3:f2:92:
         39:ba:95:e6:38:f7:2f:fc:e4:47:3b:4e:0c:2d:6a:76:87:d1:
         67:15:fd:60:69:72:0b:d4:c9:9c:e9:56:8f:d7:2f:b9:d8:c7:
         24:4f:db:d6:05:3a:a7:85:5f:cf:0a:c9:96:c7:75:51:1e:1a:
         76:55:60:26:1e:c3:a4:7f:d9:36:df:f6:3c:05:4e:da:c6:d0:
         7f:f2:57:3a

'네트워크 > MQTT' 카테고리의 다른 글

[MQTT] 4. MQTT Arduino  (0) 2025.02.07
[MQTT] 3. MQTT Node.js  (0) 2025.01.31
[MQTT] 2. mosquitto-auth-plug 셋업  (0) 2025.01.24
[MQTT] 1. Mosquitto 셋업  (0) 2025.01.17

main.cpp

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <ESPmDNS.h>

const char* ssid = "[ssid]";
const char* password = "[ssid password]";

const char* ServerIp = "[mqtt server ip]";
const char* clientId = "[client id]";
const char* mqttUsername = "[mqtt username]";
const char* mqttPassword = "[mqtt password]";

#define TOPIC    "[topic]"

const char* ca_cert = "[ca.crt 파일 텍스트]";

const char* server_key = "[server.key 파일 텍스트]";

const char* server_crt = "[server.crt 파일 텍스트]";

/* create an instance of WiFiClientSecure */
WiFiClientSecure espClient;
PubSubClient client(espClient);

long lastMsg = 0;
char msg[20];
int counter = 0;

void receivedCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message received: ");
  Serial.println(topic);

  Serial.print("payload: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void mqttconnect() {
  /* Loop until reconnected */
  while (!client.connected()) {
    Serial.print("MQTT connecting ...");
    /* connect now */
    if (client.connect(clientId, mqttUsername, mqttPassword)) {
      Serial.println("connected");
      /* subscribe topic */
      client.subscribe(TOPIC);
    } else {
      Serial.print("failed, status code =");
      Serial.print(client.state());
      Serial.println("try again in 5 seconds");
      /* Wait 5 seconds before retrying */
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  /*setup MDNS for ESP32 */
  if (!MDNS.begin("esp32")) {
      Serial.println("Error setting up MDNS responder!");
      while(1) {
          delay(1000);
      }
  }
  /* get the IP address of server by MDNS name */
  Serial.println("mDNS responder started");
  Serial.print("IP address of server: ");
  Serial.println(ServerIp);
  /* set SSL/TLS certificate */
  espClient.setCACert(ca_cert);
  espClient.setPrivateKey(server_key);
  espClient.setCertificate(server_crt);
  /* configure the MQTT server with IPaddress and port */
  client.setServer(ServerIp, 8883);
  /* this receivedCallback function will be invoked
  when client received subscribed topic */
  client.setCallback(receivedCallback);

}
void loop() {
  /* if client was disconnected then try to reconnect again */
  if (!client.connected()) {
    mqttconnect();
  }
  /* this function will listen for incomming
  subscribed topic-process-invoke receivedCallback */
  client.loop();
  /* we increase counter every 3 secs
  we count until 3 secs reached to avoid blocking program if using delay()*/
  long now = millis();
  if (now - lastMsg > 3000) {
    lastMsg = now;
    if (counter < 100) {
      counter++;
      snprintf (msg, 20, "%d", counter);
      /* publish the message */
      client.publish(TOPIC, msg);
    }else {
      counter = 0;
    }
  }
}

 

platformio.ini

lib_deps =
  PubSubClient

 

main.cpp 예제

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <ESPmDNS.h>

const char* ssid = "[ssid]";
const char* password = "[ssid password]";

const char* ServerIp = "192.168.99.225";
const char* clientId = "ESP32Client";
const char* mqttUsername = "korea_company";
const char* mqttPassword = "korea_company";

#define TOPIC    "test/topic"

const char* ca_cert = \
"-----BEGIN CERTIFICATE-----\n" \
"MIID0TCCArmgAwIBAgIUBlblEbEWRo3Y+3C9QdKEnj9DtTEwDQYJKoZIhvcNAQEL\n" \
"BQAweDELMAkGA1UEBhMCS1IxDjAMBgNVBAgMBXNlb3VsMQ0wCwYDVQQKDARraXRz\n" \
"MQwwCgYDVQQLDANsYWIxETAPBgNVBAMMCGRic2VydmVyMSkwJwYJKoZIhvcNAQkB\n" \
"FhpqYWVjaGVvbC5wYXJrQGtvcmVhaXRzLmNvbTAeFw0yMjA4MjYwMTA2MTJaFw0y\n" \
"NzA4MjYwMTA2MTJaMHgxCzAJBgNVBAYTAktSMQ4wDAYDVQQIDAVzZW91bDENMAsG\n" \
"A1UECgwEa2l0czEMMAoGA1UECwwDbGFiMREwDwYDVQQDDAhkYnNlcnZlcjEpMCcG\n" \
"CSqGSIb3DQEJARYaamFlY2hlb2wucGFya0Brb3JlYWl0cy5jb20wggEiMA0GCSqG\n" \
"SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7h0B3j/oHcBEnNbT2E3cuM5zGm5kRZTBq\n" \
"3Rq+CpMO99NAKnqWZNx1M8wm5Rxs5yO0mBJRfbEYQSB0y+n0ig7TcgWRaQfzhoQH\n" \
"k82q3foSctIu7M13Wuwc8oCUprXVSz667nF0sZ9/kzGdCX9AZHm2VlPq/Er89PUJ\n" \
"JscblwxoyXE01H/yXN9WYZHzV7lk14LhLL/SHGADNybRNBUDWTJaTtY5vbqLKvK7\n" \
"+uMCmd/qfP6qXnSXRYQDtkV6ga9j6r93SzV5OjrPGS5x4BCpdH/rldAUVOMABQQa\n" \
"386EuU0Xi+11XbMx6u92fy4c+X3wx45Tetoxy4rysaf1S/9XgUGNAgMBAAGjUzBR\n" \
"MB0GA1UdDgQWBBQEbiAQ0snbzq5w0++YvbyfrwrrkTAfBgNVHSMEGDAWgBQEbiAQ\n" \
"0snbzq5w0++YvbyfrwrrkTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA\n" \
"A4IBAQA/M4hBx0Vz+R8JKr+pnvjaeXW2A/HhqXXZCwJjNV4Jr98xUpSLkMXWrOBk\n" \
"7tFGRwlrdmoOBGDwNyR59xqD8AjHYLnQ9T1gcXdko7QhGW2daeqle23wuZqWOSS0\n" \
"43rsJQ5eoyNe/p2ziigrlih2O+He6TrftnJC3YvULF/hLORtsTIqUWszzub3Ss+W\n" \
"8JaapDKx/JSqgqbz8o+udJOThqkcfdIuLvvxCGioV0lyse24wdrD8pI5upXmOPcv\n" \
"/ORHO04MLWp2h9FnFf1gaXIL1Mmc6VaP1y+52MckT9vWBTqnhV/PCsmWx3VRHhp2\n" \
"VWAmHsOkf9k23/Y8BU7axtB/8lc6\n" \
"-----END CERTIFICATE-----\n";

const char* server_key = \
"-----BEGIN PRIVATE KEY-----\n" \
"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCIeCb1gGWnj8ug\n" \
"e0g+nQkbgttA3wuN06zIFy0pKwNZ0/FrYkEpcEtiPRhNS3NxZSIOaSM4yN/xaTR+\n" \
"IBgRn835NHlbhp/P5B8BXX3lh6luVTSm63Z1fmj/aH+P932a8QBzjpKQD16GJfZT\n" \
"sRXBwfDWRtuoB8sVy313qBrqFTjcfaA3UwTQ7Rzhgo/BjByRmKHwkLG0xw/0JDNK\n" \
"EFi6U20zzD0O2CjsgDbxOq6Q4ZkZroc2Utsc1vt3RdZEG6ePDl2t6D3DpBQoREtC\n" \
"aX2ggTITcfybMEce7f0NQ2w8e+hwp0rai2QZlGhnP9yWuK5nQjYX5Pwq1mLCsOMW\n" \
"Ozkg0fHdAgMBAAECggEABx4vOARZqP72ybjMaJmjuTfezDgl/+B/xVLyI9DOxK9p\n" \
"iuaNzAXDpMzXeOabz5kNCO/iaqqNhaetWXu+jaLGaT5bqxKvQLZfCKDx+VgVVgAj\n" \
"NiaXX+L3QoUWjDGGL1/tHFneGp32meweeDiHEDtXnrGE8PNxHAKoWWae+sEfHV7r\n" \
"jGhY+GAvDA4QCG9EUJyq0RSKyXiy6qo5axzGTHrS6Mp17QaWgAkPHUtSsOLL2yAV\n" \
"0YjDzZbKcx5dpWbwvHxaEqMOFmIo2SCcwUw0/OWYZchQ9S6Ee5awaEWUSp9FVT3a\n" \
"UV6oTpY6kGkwmGWBxaGTZP0HvCbvPOkEYcD4uYmdEQKBgQC/3rZ9nfJqqBKUe2uV\n" \
"VwXxtAyv/X0vQRpvht8Etk0HNm3wKJ7oywtdF7+zelxgld+9tNkQCxUJhjz21ecM\n" \
"mh+ZlGQ4+6DJqK88MRt8Cpgahai8FBWhA6l0g7wbu3ZY0blUsLSwsuvfJqSyd1OF\n" \
"bD2h49ooCDu2rjuxQJ8lvJTOsQKBgQC2FRqeP8sDsGoAl2syGrBjdBPUB9+iBl0h\n" \
"0gtYhxO4AbjKkb6JryqouzW+gNl0zxQpAMR0QvkxoBcQUKKmHwi/y1GZdyrCsoyf\n" \
"ooX8Qq4vn0HnbMzS2LteZQUI7fKZEzRReksbe5aIMYPamXYvd5Mr7g+uDr69sPHL\n" \
"FLLTag4Y7QKBgQCnvL5xhzm8wH6tzFA7WL7blXpaCRP90b6YraIe7njcy1rFT93M\n" \
"ymV+1xpCf8But9fIc2goPGgB0ZdOe6XoQH1LuIz9vA3O/mdkCdJrWJ+s4BiphC18\n" \
"fEUSlXBIFlTaRU7umST+LQ1EIvZtByC/Ted7tkSsJrZ9eEi7JzF6viihoQKBgA7z\n" \
"OqVFraCW6o0z4YxSnqr7y+j74IPIK/tr6JyTMq5IDeksAE4DwOfrvyTuJWyu2APp\n" \
"2TeGjDlj4KDpTgF/yNMemYuVOkCUMnGlAYVN4ElutRWQXFzviKredoReLS4eYoxS\n" \
"Ezqlch2qmx3mvcp18fKIcGclNMoUbjXzdB9htNidAoGAYf/X4CZrab05O5fHzXD2\n" \
"JXcgWe2aIt3jR0pf/LyOHFjhiyHpw4vfcEwNcsu7MmHq6ifUr0Q/sM1zDUa3uFjb\n" \
"WoSDGIkcfDJ9sZ1CL+lhaCcCaevlIuoLn9vVPfrMss5LGGk/Q3/oco7zfgeWtIOg\n" \
"VLAL3aop4nLey84XBPNxhj4=\n" \
"-----END PRIVATE KEY-----\n";

const char* server_crt = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIDfTCCAmUCFAGMGehiEEUnQsHsJMEkWyausJtGMA0GCSqGSIb3DQEBCwUAMHgx\n" \
"CzAJBgNVBAYTAktSMQ4wDAYDVQQIDAVzZW91bDENMAsGA1UECgwEa2l0czEMMAoG\n" \
"A1UECwwDbGFiMREwDwYDVQQDDAhkYnNlcnZlcjEpMCcGCSqGSIb3DQEJARYaamFl\n" \
"Y2hlb2wucGFya0Brb3JlYWl0cy5jb20wHhcNMjIwODI2MDEwNjUyWhcNMjIwOTI1\n" \
"MDEwNjUyWjB+MQswCQYDVQQGEwJLUjEOMAwGA1UECAwFc2VvdWwxDTALBgNVBAoM\n" \
"BGtpdHMxDDAKBgNVBAsMA2xhYjEXMBUGA1UEAwwOMTkyLjE2OC45OS4yMjUxKTAn\n" \
"BgkqhkiG9w0BCQEWGmphZWNoZW9sLnBhcmtAa29yZWFpdHMuY29tMIIBIjANBgkq\n" \
"hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiHgm9YBlp4/LoHtIPp0JG4LbQN8LjdOs\n" \
"yBctKSsDWdPxa2JBKXBLYj0YTUtzcWUiDmkjOMjf8Wk0fiAYEZ/N+TR5W4afz+Qf\n" \
"AV195YepblU0put2dX5o/2h/j/d9mvEAc46SkA9ehiX2U7EVwcHw1kbbqAfLFct9\n" \
"d6ga6hU43H2gN1ME0O0c4YKPwYwckZih8JCxtMcP9CQzShBYulNtM8w9Dtgo7IA2\n" \
"8TqukOGZGa6HNlLbHNb7d0XWRBunjw5dreg9w6QUKERLQml9oIEyE3H8mzBHHu39\n" \
"DUNsPHvocKdK2otkGZRoZz/clriuZ0I2F+T8KtZiwrDjFjs5INHx3QIDAQABMA0G\n" \
"CSqGSIb3DQEBCwUAA4IBAQBfs8kd4LHRGQMj+Ji1JixFrP+rVBgY4jypLv/YuP+L\n" \
"Sgn8NWbglMVcVhmxlfvg5ULEIcZleV5D+iE08leajaAggLOrVY7qIVUtOVE3r/Qp\n" \
"dVNyRdk3l8MygACXQLVy+hXehiNFSBkRi5qj2zaQJMHV5FDUkOBt2fvwSRwVpyob\n" \
"bn3X2Tm+AbsSmNL49wc2EyKqCrCT45dZrzYCjd13WyiSkP4OrAGakeIipHLdNUhP\n" \
"72KrsemVw35vBfnUOWjAzQtpcc5RlNFfTnY+/p0i2mNm50cab7rtEkZAD6CAmegb\n" \
"wDfsdzKgBglfSzYIUfQXExDw/N2L788byyBPuy3nFQo8\n" \
"-----END CERTIFICATE-----\n";

/* create an instance of WiFiClientSecure */
WiFiClientSecure espClient;
PubSubClient client(espClient);

long lastMsg = 0;
char msg[20];
int counter = 0;

void receivedCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message received: ");
  Serial.println(topic);

  Serial.print("payload: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void mqttconnect() {
  /* Loop until reconnected */
  while (!client.connected()) {
    Serial.print("MQTT connecting ...");
    /* connect now */
    if (client.connect(clientId, mqttUsername, mqttPassword)) {
      Serial.println("connected");
      /* subscribe topic */
      client.subscribe(TOPIC);
    } else {
      Serial.print("failed, status code =");
      Serial.print(client.state());
      Serial.println("try again in 5 seconds");
      /* Wait 5 seconds before retrying */
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  /*setup MDNS for ESP32 */
  if (!MDNS.begin("esp32")) {
      Serial.println("Error setting up MDNS responder!");
      while(1) {
          delay(1000);
      }
  }
  /* get the IP address of server by MDNS name */
  Serial.println("mDNS responder started");
  Serial.print("IP address of server: ");
  Serial.println(ServerIp);
  /* set SSL/TLS certificate */
  espClient.setCACert(ca_cert);
  espClient.setPrivateKey(server_key);
  espClient.setCertificate(server_crt);
  /* configure the MQTT server with IPaddress and port */
  client.setServer(ServerIp, 8883);
  /* this receivedCallback function will be invoked
  when client received subscribed topic */
  client.setCallback(receivedCallback);

}
void loop() {
  /* if client was disconnected then try to reconnect again */
  if (!client.connected()) {
    mqttconnect();
  }
  /* this function will listen for incomming
  subscribed topic-process-invoke receivedCallback */
  client.loop();
  /* we increase counter every 3 secs
  we count until 3 secs reached to avoid blocking program if using delay()*/
  long now = millis();
  if (now - lastMsg > 3000) {
    lastMsg = now;
    if (counter < 100) {
      counter++;
      snprintf (msg, 20, "%d", counter);
      /* publish the message */
      client.publish(TOPIC, msg);
    }else {
      counter = 0;
    }
  }
}

 

참고 : http://www.iotsharing.com/2017/08/how-to-use-esp32-mqtts-with-mqtts-mosquitto-broker-tls-ssl.html

 

Demo 30: How to use Arduino ESP32 MQTTS with MQTTS Mosquitto broker (TLS/SSL)

This is a place where I can share my knowledge of: IoT, machine learning self learning and other interetsing topics.

www.iotsharing.com

 

'네트워크 > MQTT' 카테고리의 다른 글

[MQTT] 5. Certification 확인 (문제 발생시만 확인)  (0) 2025.02.14
[MQTT] 3. MQTT Node.js  (0) 2025.01.31
[MQTT] 2. mosquitto-auth-plug 셋업  (0) 2025.01.24
[MQTT] 1. Mosquitto 셋업  (0) 2025.01.17

프로젝트 환경

1. 프로젝트 폴더 생성 후 이동
ex) cd mqtt-test

 

2. mqtt 모듈 세팅

yarn
yarn add mqtt

 

3. 인증 파일을 프로젝트 폴더로 복사

ca.crt
server.crt
server.key

 

4. subscriber 생성 후 실행

mqtt-receiver.js

const mqtt = require('mqtt')
const fs = require('fs')
const path = require('path')

const KEY = fs.readFileSync(path.join(__dirname, '/server.key'))
const CERT = fs.readFileSync(path.join(__dirname, '/server.crt'))
const TRUSTED_CA_LIST = fs.readFileSync(path.join(__dirname, '/ca.crt'))

const PORT = 8883
const HOST = '[ip/domain]'

const options = {
  port: PORT,
  host: HOST,
  key: KEY,
  cert: CERT,
  rejectUnauthorized: false,
  ca: TRUSTED_CA_LIST,
  protocol: 'mqtts',
  username: '[username]',
  password: '[pw]'
};
const client = mqtt.connect(options);

client.on('connect', function () {
  client.subscribe('[topic]', function (err) {
    if (!err) {
      console.log('Receiver Connect!');
    }
  })
});

client.on('message', function (topic, message) {
  console.log(message.toString())
})

 

예) ip/domain : 192.168.1.101, username : korea_company, pw : korea_company , topic : test/topic

node mqtt-receiver.js

 

5. publisher 생성 후 실행

mqtt-sender.js

const mqtt = require('mqtt')
const fs = require('fs')
const path = require('path')

const KEY = fs.readFileSync(path.join(__dirname, '/server.key'))
const CERT = fs.readFileSync(path.join(__dirname, '/server.crt'))
const TRUSTED_CA_LIST = fs.readFileSync(path.join(__dirname, '/ca.crt'))

const PORT = 8883
const HOST = '[ip/domain]'

const options = {
  port: PORT,
  host: HOST,
  key: KEY,
  cert: CERT,
  rejectUnauthorized: false,
  ca: TRUSTED_CA_LIST,
  protocol: 'mqtts',
  username: '[username]',
  password: '[pw]'
};
const client = mqtt.connect(options);

client.on('connect', function () {
  client.subscribe('test/topic', function (err) {
    if (!err) {
      console.log('Sender Connect!');
      client.publish('test/topic', 'Hello nodejs');
    }
    client.end();
  })
})

예) ip/domain : 192.168.1.101, username : korea_company , pw : korea_company , topic : test/topic

node mqtt-sender.js

'네트워크 > MQTT' 카테고리의 다른 글

[MQTT] 5. Certification 확인 (문제 발생시만 확인)  (0) 2025.02.14
[MQTT] 4. MQTT Arduino  (0) 2025.02.07
[MQTT] 2. mosquitto-auth-plug 셋업  (0) 2025.01.24
[MQTT] 1. Mosquitto 셋업  (0) 2025.01.17

Step 1. mosquitto-auth-plug 빌드

1. 빌드 관련 패키지 설치

sudo apt install git build-essential libssl-dev libmysqlclient-dev libmosquitto-dev
sudo apt install libmariadb-dev
sudo apt install mosquitto-dev

2. 패키지 다운로드

git clone https://github.com/jpmens/mosquitto-auth-plug.git
git clone https://github.com/eclipse/mosquitto.git
cd mosquitto-auth-plug
cp config.mk.in config.mk

3. 설정파일 수정

vi config.mk
MOSQUITTO_SRC = [mosquitto 소스 경로] 예) /root/project/mosquitto
OPENSSLDIR = /usr/lib/openssh

경로 추가

vi Makefile
ifneq ($(BACKEND_MYSQL),no)
    BACKENDS += -DBE_MYSQL
    BACKENDSTR += MySQL
    BE_CFLAGS += `mariadb_config --cflags`
    BE_LDADD += `mariadb_config --libs`
    OBJS += be-mysql.o

mysql_config 를 mariadb_config 로 수정

 

4. 소스파일 컴파일 에러시 아래 수정

vi auth-plug.c
502
line int mosquitto_auth_unpwd_check(void *userdata, struct mosquitto *client, const char *username, const char *password)

601 line int mosquitto_auth_acl_check(void *userdata, int access, struct mosquitto *client, const struct mosquitto_acl_msg *msg)

752
line int mosquitto_auth_psk_key_get(void *userdata, struct mosquitto *client, const char *hint, const char *identity, char *key, int max_key_len)

첫번째 const 제거

 

vi log.c
#include <mosquitto.h>
#include <mosquitto_broker.h>
#include <mosquitto_plugin.h>

mosquitto_broker.h 추가

 

5. 빌드 & 생성 파일 복사

make
sudo cp auth-plug.so np /etc/mosquitto/

 

Step 2. mysql 세팅

1. mysql 설치

sudo apt-get install mysql-server
sudo mysql -u root -p

default password: root

 

2. db & db 유저 생성

create database mosquitto;
CREATE USER 'mosquitto'@'%' IDENTIFIED BY 'mosquitto';
GRANT ALL ON *.* TO 'mosquitto'@'%';
FLUSH PRIVILEGES;

 

3. 테이블 생성

use mosquitto
DROP TABLE IF EXISTS users;
CREATE TABLE users (
        id INTEGER AUTO_INCREMENT,
        username VARCHAR(25) NOT NULL,
        pw VARCHAR(128) NOT NULL,
        super INT(1) NOT NULL DEFAULT 0,
        PRIMARY KEY (id)
  );
CREATE UNIQUE INDEX users_username ON users (username);
DROP TABLE IF EXISTS acls;
CREATE TABLE acls (
        id INTEGER AUTO_INCREMENT,
        username VARCHAR(25) NOT NULL,
        topic VARCHAR(256) NOT NULL,
        rw INTEGER(1) NOT NULL DEFAULT 1,       -- 1: read-only, 2: read-write
        PRIMARY KEY (id)
        );
CREATE UNIQUE INDEX acls_user_topic ON acls (username, topic(228));

 

4. 비밀번호 생성

/etc/mosquitto/np -p [pw]
예) pw : korea_company
generated pw : PBKDF2$sha256901qbLGPB2fIZ5RbSWk$AzHmP01PoHTFdYhgd91oRvqeqFd/oc/S

 

5. mosquitto 유저 & topic 설정

INSERT INTO users (username, pw) VALUES ('[user name]', '[generated pw]');
INSERT INTO acls (username, topic, rw) VALUES ('[user name]', '[topic]', 5);
예) username : korea_company, pw : korea_company, topic : test/topic
insert into users (username, pw) values ('korea_company', 'PBKDF2$sha256901qbLGPB2fIZ5RbSWk$AzHmP01PoHTFdYhgd91oRvqeqFd/oc/S');
insert into acls (username, topic, rw) values ('korea_company', 'test/topic', 5);

rw : (2 for write, 5 for read+subscribe, 7 for read/write)

 

6. db 테이블 조회

url : 192.168.1.101
port : 3306
id : mosquitto
pw : mosquitto

 

users 테이블

 

acls 테이블

 

Step 3. mosquitto에 적용

1. 설정에 auth-plug.so 추가와 옵션 기재

sudo vi /etc/mosquitto/mosquitto.conf
auth_plugin /etc/mosquitto/auth-plug.so
auth_opt_backends mysql
auth_opt_host localhost
auth_opt_port 3306
auth_opt_dbname mosquitto
auth_opt_user mosquitto
auth_opt_pass mosquitto
auth_opt_userquery SELECT pw FROM users WHERE username = '%s'
auth_opt_superquery SELECT COUNT(*) FROM users WHERE username = '%s' AND super = 1
auth_opt_aclquery SELECT topic FROM acls WHERE (username = '%s') AND (rw >= %d)
auth_opt_acl_cacheseconds 60 auth_opt_auth_cacheseconds 60

anonymous 허락은 제거
allow_anonymous true

 

2. 서비스 재시작

sudo service mosquitto restart

 

3. 테스트

3.1 구독

mosquitto_sub -h [ip/domain] -p 8883 --cafile /etc/mosquitto/ca_certificates/ca.crt --cert /etc/mosquitto/certs/server.crt --key /etc/mosquitto/certs/server.key -t [topic] -u [username] -P [pw]

 

3.2 발행

mosquitto_pub -h [ip/domain] -p 8883 --cafile /etc/mosquitto/ca_certificates/ca.crt --cert /etc/mosquitto/certs/server.crt --key /etc/mosquitto/certs/server.key -t [topic] -u [username] -P [pw] -m 'hello auth_plug'
예) username : korea_company, pw : korea_company, topic : test/topic

'네트워크 > MQTT' 카테고리의 다른 글

[MQTT] 5. Certification 확인 (문제 발생시만 확인)  (0) 2025.02.14
[MQTT] 4. MQTT Arduino  (0) 2025.02.07
[MQTT] 3. MQTT Node.js  (0) 2025.01.31
[MQTT] 1. Mosquitto 셋업  (0) 2025.01.17

Step 1. mosquitto 설치

1. 설치

sudo apt update
sudo apt install mosquitto mosquitto-clients

2. 설치 확인

mosquitto -v

3. 테스트

3.1 구독

mosquitto_sub -h localhost -t test/topic

3.2 발행

mosquitto_pub -h localhost -t test/topic -m 'hello mqtt'

 

Step 2. TLS 세팅

1. 인증키 생성과 mosquitto 폴더에 복사

openssl genrsa -des3 -out ca.key 2048
openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
Country Name : KR
State or Province Name : seoul
Locality Name :
Organization Name : korea_company
Organizational Unit Name : lab
Common Name : hostname 입력
Email Address : email 입력
openssl genrsa -out server.key 2048
openssl req -new -out server.csr -key server.key
Country Name : KR
State or Province Name : seoul
Locality Name :
Organization Name : korea_company
Organizational Unit Name : lab
Common Name : ip/domain 입력
Email Address : email 입력

 

예) ip/domain : 192.168.1.100

 

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
chmod +r server.key
sudo cp ca.crt /etc/mosquitto/ca_certificates/
sudo cp server.crt server.key /etc/mosquitto/certs/

 

2. mosquitto 설정

sudo vi /etc/mosquitto/mosquitto.conf
listener 8883
allow_anonymous true
require_certificate true
cafile /etc/mosquitto/ca_certificates/ca.crt
keyfile /etc/mosquitto/certs/server.key
certfile /etc/mosquitto/certs/server.crt
tls_version tlsv1.2

 

서비스 재시작

sudo service mosquitto restart

 

3. 테스트

3.1 구독

mosquitto_sub -h [ip/domain] -p 8883 --cafile /etc/mosquitto/ca_certificates/ca.crt --cert /etc/mosquitto/certs/server.crt --key /etc/mosquitto/certs/server.key -t [topic]

 

3.2 발행

mosquitto_pub -h [ip/domain] -p 8883 --cafile /etc/mosquitto/ca_certificates/ca.crt --cert /etc/mosquitto/certs/server.crt --key /etc/mosquitto/certs/server.key -t [topic] -m 'hello tls'
예) ip/domain : 192.168.1.100, topic : test/topic

'네트워크 > MQTT' 카테고리의 다른 글

[MQTT] 5. Certification 확인 (문제 발생시만 확인)  (0) 2025.02.14
[MQTT] 4. MQTT Arduino  (0) 2025.02.07
[MQTT] 3. MQTT Node.js  (0) 2025.01.31
[MQTT] 2. mosquitto-auth-plug 셋업  (0) 2025.01.24

+ Recent posts