BLOG

Python(클라이언트 장치)으로 포트 443에 TLS 클라이언트 인증을 사용하여 MQTT를 구현하는 방법
작성일: 2018년 5월 14일

ALPN(응용 프로그램 계층 프로토콜 협상)은 TLS 서버에 연결되는 클라이언트가 ProtocolNameList라고 하는 추가 매개 변수를 통과시킬 수 있도록 하는 TLS로의 확장입니다. ProtocolNameList는 클라이언트가 통신에 사용할 응용 프로그램 프로토콜의 우선 순위 목록입니다. 이제 AWS IoT Core를 사용하면 ALPN TLS 확장을 사용하여 MQTT 위에 있는 장치를 포트 443의 TLS 클라이언트 인증으로 연결할 수 있습니다. 이 방법이 유용한 이유에 대한 자세한 내용은 이 블로그 게시물을 참조하십시오.

 

이 블로그 포스트에서는 포트 443의 MQTT를 통해 기기를 AWS IoT Core에 연결할 수 있는 두 가지 방법을 알려 드리겠습니다.

 

 

방법 1: Paho-MQTT 클라이언트 및 OpenSSL 사용하기

 

OpenSSL 및 mbedTLS를 포함하여 가장 일반적인 TLS 구현은 ALPN TLS확장을 지원합니다. 이 예에서는 Paho-mqtt 클라이언트와 OpenSSL 라이브러리를 사용해 디바이스를 AWS IoT 엔드포인트에 연결합니다.

 

선행 조건

장치를 연결하기 전에 Python 및 OpenSSL의 소프트웨어 버전이 ALPN 확장을 지원하는지 확인합니다.

 

 

환경을 확인하려면 다음과 같이 하십시오.

 

  1. OpenSSL 버전을 확인합니다.

openssl version

OpenSSL 1.0.2k-fips  26 Jan 2017

 

  1. Python 버전을 확인합니다.

python –version

Python 2.7.13

 

  1. Python이 참조하는 OpenSSL 버전을 확인합니다.

python

>>> import ssl

>>> print ssl.OPENSSL_VERSIONOpenSSL 1.0.2k-fips  26 Jan 2017

*If the reference is to older version of OpenSSL, you have to update it.

 

이 샘플 스크립트는 MQTT 라이브러리에 메시지를 게시하기 위해 Paho를 사용합니다. Paho-MQTT 클라이언트의 최신의 안정적인 버전은 Python Package Index(PyPi)에서 사용할 수 있습니다. pip을 사용하여 설치합니다.

 

pip install paho-mqtt

 

연결된 각 장치마다 메시지 브로커 또는 장치 섀도우 서비스에 액세스 하려면 자격 증명이 있어야 합니다. 샘플 스크립트는 X.509 인증서를 인증 메커니즘으로 사용하여 AWS IoT 엔드포인트에 연결합니다. AWS IoT 콘솔 또는 CLI를 사용하여 AWS IoT 인증서를 만들 수 있습니다. 자세한 내용은 AWS IoT Developer Guide의 AWS IoT Device Certificate 생성 및 등록, AWS CLI Command Reference의 키와 인증 정보 생성을 참조하십시오.

 

다음의 매우 간단한 예는 AWS IoT 엔드포인트에 연결하여 이에 대한 메세지를 게시하는 것입니다. 다음 스크립트를 파일에 복사하고 파일을 alpn_mqtt.py으로 저장합니다.

 

from __future__ import print_function

import sys

import ssl

import time

import datetime

import logging, traceback

import paho.mqtt.client as mqtt

 

IoT_protocol_name = “x-amzn-mqtt-ca”

aws_iot_endpoint = “AWS_IoT_ENDPOINT_HERE” # <random>.iot.<region>.amazonaws.com

url = “https://{}”.format(aws_iot_endpoint)

 

ca = “YOUR/ROOT/CA/PATH”

cert = “YOUR/DEVICE/CERT/PATH”

private = “YOUR/DEVICE/KEY/PATH”

 

logger = logging.getLogger()

logger.setLevel(logging.DEBUG)

handler = logging.StreamHandler(sys.stdout)

log_format = logging.Formatter(‘%(asctime)s – %(name)s – %(levelname)s – %(message)s’)

handler.setFormatter(log_format)

logger.addHandler(handler)

 

def ssl_alpn():

try:

#debug print opnessl version

logger.info(“open ssl version:{}”.format(ssl.OPENSSL_VERSION))

ssl_context = ssl.create_default_context()

ssl_context.set_alpn_protocols([IoT_protocol_name])

ssl_context.load_verify_locations(cafile=ca)

ssl_context.load_cert_chain(certfile=cert, keyfile=private)

 

return  ssl_context

except Exception as e:

print(“exception ssl_alpn()”)

raise e

 

if __name__ == ‘__main__’:

topic = “test/date”

try:

mqttc = mqtt.Client()

ssl_context= ssl_alpn()

mqttc.tls_set_context(context=ssl_context)

logger.info(“start connect”)

mqttc.connect(aws_iot_endpoint, port=443)

logger.info(“connect success”)

mqttc.loop_start()

 

while True:

now = datetime.datetime.now().strftime(‘%Y-%m-%dT%H:%M:%S’)

logger.info(“try to publish:{}”.format(now))

mqttc.publish(topic, now)

time.sleep(1)

 

except Exception as e:

logger.error(“exception main()”)

logger.error(“e obj:{}”.format(vars(e)))

logger.error(“message:{}”.format(e.message))

traceback.print_exc(file=sys.stdout)

 

 

Python 스크립트 실행하기

다음 명령을 실행하여 생성한 Python 스크립트를 실행합니다.

 

<span style="color: #808080;"><em>python alpn_mqtt.py

2018-03-15 11:03:25,174 - root - INFO - start connect 
2018-03-15 11:03:25,254 - root - INFO - connect success 
2018-03-15 11:03:25,255 - root - INFO - published:&lt;timestamp&gt; 
2018-03-15 11:03:26,256 - root - INFO - published:&lt;timestamp&gt;</em></span>

 

콘솔에 “연결 성공” 및 “게시됨: <타임 스탬프>”메시지가 표시되면 AWS IoT Core에 대한 연결이 성공적으로 설정되고 이 메시지가 게시된 것입니다.

 

스크립트를 실행하는 동안 오류가 발생하면 AWS IoT 엔드포인트 또는 제공한 인증서 정보를 확인해야합니다.

 

 

AWS IoT가 클라이언트 메시지를 받았는지 테스트하기

 

AWS IoT가 클라이언트 메시지를 받았는지 확인하려면 AWS IoT 콘솔에 로그인합니다. 왼쪽 탐색 창에서 테스트를 선택한 다음 등록을 선택합니다. 테스트/날짜 항목을 등록하십시오.

 

등록하면 여기에 나와 있는 것처럼 콘솔에 있는 클라이언트 장치에 게시된 메시지가 1초당 표시됩니다.

 

 

클라이언트 장치가 Linux에서 실행 중인 경우 tcpdump를 사용하여 테스트할 수 있습니다.

 

tcpdump port 443

 

방법 2: Python으로 AWS IoT Device SDK 사용하기

 

Python용 AWS IoT Device SDK를 사용하면 개발자가 자신의 디바이스를 사용하여 AWS IoT에 액세스 할 수 있도록 Python 스크립트를 쓸 수 있습니다. 현재, 포트 8883의 TLS를 초과하는 MQTT또는 포트 443의 WebSocket 프로토콜을 초과하도록 선택할 수 있습니다. 포트 443의 MQTT는 기본적으로 지원되지 않습니다. 이 기능을 사용하려면 Device SDK를 수정해야 합니다. Device SDK와 함께 기본으로 제공되는 OpenSSL 라이브러리가 ALPN 확장을 지원하기 때문에, 포트 443에 대한 MQTT 통신을 사용하려면 SSL 라이브러리 구성 방법을 수정해야 한다. 이 예에서는 포트 443의 MQTT에서 AWS IoT 엔드포인트에 연결하기 위해 Device SDK을 변경하는 방법을 보여 줍니다.

 

Python용 AWS IoT Device SDK는 수정된 Paho-MQTT Python client library위에 구축되어 있습니다. AWSIoTPythonSDK/core/protocol/paho/ 폴더에서 client.py 파일을 수정합니다.

 

예:   /usr/local/lib/python2.7/site-packages/AWSIoTPythonSDK/core/protocol/paho/client.py

 

변경해야 하는 내용은 다음과 같습니다.

 

— a/AWSIoTPythonSDK/core/protocol/paho/client.py

+++ b/AWSIoTPythonSDK/core/protocol/paho/client.py

@@ -787,15 +787,26 @@ class Client(object):

self._ssl = SecuredWebSocketCore(rawSSL, self._host, self._port, self._AWSAccessKeyIDCustomConfig, self._AWSSecretAccessKeyCustomConfig, self._AWSSessionTokenCustomConfig)  # Overeride the _ssl socket

# self._ssl.enableDebug()

else:

–           self._ssl = ssl.wrap_socket(

–               sock,

–               certfile=self._tls_certfile,

–               keyfile=self._tls_keyfile,

–               ca_certs=self._tls_ca_certs,

–               cert_reqs=self._tls_cert_reqs,

–               ssl_version=self._tls_version,

–               ciphers=self._tls_ciphers)

+           if self._port == 8883:

+               self._ssl = ssl.wrap_socket(

+                   sock,

+                   certfile=self._tls_certfile,

+                   keyfile=self._tls_keyfile,

+                   ca_certs=self._tls_ca_certs,

+                   cert_reqs=self._tls_cert_reqs,

+                   ssl_version=self._tls_version,

+                   ciphers=self._tls_ciphers)

+           else:

+               context = ssl.SSLContext(self._tls_version)

+               context.load_cert_chain(self._tls_certfile, self._tls_keyfile)

+               context.verify_mode = self._tls_cert_reqs

+               context.load_verify_locations(self._tls_ca_certs)

+               context.set_alpn_protocols([“x-amzn-mqtt-ca”])

+

+               self._ssl = context.wrap_socket(sock, server_hostname=self._host, do_handshake_on_connect=False)

+

+               self._ssl.do_handshake()

+

if self._tls_insecure is False:

if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 5):  # No IP host match before 3.5.x

self._tls_match_hostname()

 

변경한 후 AWS IoT 엔드포인트에 연결하여 메시지를 게시하는 간단한 Python 스크립트를 만듭니다. 자세한 내용은 Python용 AWS IoT Device SDK를 참조하십시오.

 

# Import SDK packages

from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient

 

# For certificate based connection

myMQTTClient = AWSIoTMQTTClient(“myClientID”)

 

# Configure the MQTT Client

myMQTTClient.configureEndpoint(<YOUR_AWS_IOT_ENDPOIT>, 443)

myMQTTClient.configureCredentials(“YOUR/ROOT/CA/PATH”, YOUR/DEVICE/KEY/PATH “, ” YOUR/DEVICE/CERT/PATH “)

myMQTTClient.configureOfflinePublishQueueing(-1)  # Infinite offline Publish queueing

myMQTTClient.configureDrainingFrequency(2)  # Draining: 2 Hz

myMQTTClient.configureConnectDisconnectTimeout(10)  # 10 sec

myMQTTClient.configureMQTTOperationTimeout(5)  # 5 sec

 

# Connect to AWS IoT endpoint and publish a message

myMQTTClient.connect()

print (“Connected to AWS IoT”)

myMQTTClient.publish(“alpn/devicesdk”, “Hello over MQTT on port 443”, 0)

myMQTTClient.disconnect()

 

Python 스크립트 실행

 

다음 명령을 실행하여 생성한 Python 스크립트를 실행합니다.

 

python aws-iot-with-alpn.py

Connected to AWS IoT

 

콘솔에 “연결됨” 메시지가 표시되면, AWS IoT Core에 대한 연결이 성공적으로 설정되었으며 이 메시지가 게시되었다는 것을 의미합니다. 스크립트를 실행하는 동안 오류가 표시되면 장치 인증서를 확인하여 연결된 정책이 AWS IoT Core액세스를 허용하는지 확인합니다.

 

요약

이 포스트에서는 포트 443의 MQTT를 통해 IoT 디바이스를 AWS IoT Core에 연결할 수 있는 두 가지 방법을 보여 드렸습니다. 과거에 회사 방화벽에서 포트 8883을 열어야 하는 제약이 있었다면 이제 HTTPS 트래픽(443)에 대한 표준 포트를 사용하여 MQTT를 AWS IoT Core 엔드포인트로 보낼 수 있습니다.

 

AWS IoT Core에 대한 자세한 내용은 AWS IoT Core Developer 가이드를 참조하십시오.

 

원문 URL: https://aws.amazon.com/ko/blogs/iot/how-to-implement-mqtt-with-tls-client-authentication-on-port-443-from-client-devices-python/

** 메가존 TechBlog는 AWS BLOG 영문 게재글중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아서, 정기적으로 게재하고 있습니다. 추가로 번역및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.