MQTT 배포 최적화 NGINX Plus 로 구현
이 포스트에서는 NGINX Plus 를 구성하여 엔터프라이즈 환경에서 MQTT 배포를 최적화하는 방법에 대해 논의합니다.
목차
1. MQTT 란 무엇일까요?
2. NGINX Plus MQTT 메시지 처리
2-1. MQTT 지시문 및 변수
2-2. 미리 읽은 모듈 지시문 및 내장 변수
2-3. MQTT 필터 모듈 지시문
3. MQTT 모범 사례
3-1. MQTT 브로커 로드 밸런싱
3-2. SSL/TLS Termination
3-3. 클라이언트 ID 대체
3-4. 인증 자격 증명으로서의 클라이언트 인증서
4. MQTT 배포 최적화, 오늘 시작하세요
1. MQTT 란 무엇일까요?
MQTT는 Message Queuing Telemetry Transport의 약자로, 인터넷을 통해 사물 인터넷(IoT)이나 기계 간 통신(M2M) 장치 및 애플리케이션을 연결하기에 이상적인 인기 있는 경량 게시(Publish)-구독(Subscribe) 메시징 프로토콜입니다. MQTT는 대역폭이 제한된 환경이나 저전력 환경에서 효율적으로 작동하도록 설계되어, 원격 클라이언트가 많은 애플리케이션에 이상적인 선택입니다. 소비자 전자제품, 자동차, 교통, 제조 및 의료 등 다양한 산업에서 사용됩니다.
2. NGINX Plus MQTT 메시지 처리
NGINX Plus R29부터 MQTT 3.1.1 및 5.0을 지원합니다. NGINX Plus는 클라이언트와 브로커 사이에서 프록시 역할을 하며, 핵심 시스템으로부터 작업을 분산시켜 확장성을 간소화하고 계산 비용을 줄입니다. 특히 NGINX Plus는 CONNECT 메시지의 일부를 구문 분석하고 재작성하여 다음과 같은 기능을 제공합니다:
- MQTT 브로커 로드 밸런싱
- 세션 지속성 (클라이언트를 동일한 브로커에 다시 연결)
- SSL/TLS Termination
- 클라이언트 인증서 인증
MQTT 메시지 처리 지시문은 NGINX 구성 파일의 스트림 컨텍스트에 정의되어야 하며, ngx_stream_mqtt_preread_module
및 ngx_stream_mqtt_filter_module
에서 제공됩니다.
사전 판독 모듈은 NGINX의 내부 프록시 처리 이전에 데이터를 처리하여 구문 분석된 메시지 데이터를 기반으로 로드 밸런싱 및 업스트림 라우팅 결정을 내릴 수 있게 합니다.
필터 모듈은 받은 CONNECT 메시지 내의 clientid, username 및 password 필드를 rewrite 할 수 있습니다. 이러한 필드를 변수 및 복잡한 값으로 설정할 수 있는 능력은 구성 옵션을 크게 확장시켜줍니다. 이를 통해 NGINX Plus는 민감한 장치 정보를 가리거나 TLS 인증서의 식별 이름과 같은 데이터를 삽입할 수 있습니다.
2-1. MQTT 지시문 및 변수
MQTT 배포를 최적화하고 특정 요구 사항을 충족하기 위해 NGINX 구성을 조정하는 데 몇 가지 새로운 지시문 및 포함된 변수를 사용할 수 있습니다.
2-2. 미리 읽은 모듈 지시문 및 내장 변수
mqtt_preread
– 구문 분석을 활성화하며, 클라이언트 장치에서 보낸 CONNECT 메시지에서 clientid와 username 필드를 추출합니다. 이 값들은 내장 변수를 통해 사용 가능하며, 세션을 해싱하여 로드 밸런싱된 업스트림 서버로 전달하는 데 도움이 됩니다$mqtt_preread_clientid
– 장치가 보낸 클라이언트 식별자를 나타냅니다.$mqtt_preread_username
– 인증 목적으로 클라이언트가 보낸 사용자 이름을 나타냅니다.
2-3. MQTT 필터 모듈 지시문
mqtt
– MQTT Rewrite가 활성화되었는지 여부를 정의합니다.mqtt_rewrite_buffer_size
– 수정된 메시지를 구성하는 데 사용되는 버퍼의 크기를 지정합니다.mqtt_set_connect
– 클라이언트에서 보내는 CONNECT 메시지의 매개변수를 Rewrite 합니다. 지원되는 매개변수에는 clientid
, username
및 password
가 포함됩니다.
3. MQTT 모범 사례
NGINX Plus로 MQTT 메시지를 처리할 때의 이점과 관련 모범 사례를 자세히 살펴보겠습니다. 아래 예에서는 포트 1883 및 8883을 사용합니다. 포트 1883은 기본 비보안 포트이고 8883은 기본 SSL/TLS 암호화 포트입니다.
3-1. MQTT 브로커 로드 밸런싱
MQTT 장치의 일시적인 특성으로 인해 클라이언트 IP가 예기치 않게 변경될 수 있습니다. 이는 장치 연결을 올바른 업스트림 브로커로 라우팅하는 데 어려움을 초래할 수 있습니다. 장치 연결이 하나의 업스트림 브로커에서 다른 업스트림 브로커로 이동하면 브로커 간의 비용이 많이 소요되고 지연 및 비용이 추가될 수 있습니다.
NGINX는 MQTT CONNECT 메시지의 clientid
필드를 구문 분석하여 업스트림 서비스 브로커에 대한 고정 세션을 설정할 수 있습니다. 클라이언트 ID를 백엔드의 브로커 서비스에 대한 연결을 유지하기 위한 해시 키(hash key)로 사용하여 이 작업을 수행할 수 있습니다.
이 예에서는 clientid
를 사용하여 sticky session을 세 개의 업스트림 브로커에 설정하여 MQTT 장치 데이터를 프록시로 전달합니다. 일관된 매개변수를 사용하여 업스트림 서버 중 하나가 장애를 발생하더라도 해당 서버에 이미 설정된 세션에 영향을 주지 않고 남은 서버들에게 트래픽을 고르게 분산시킵니다.
stream {
mqtt_preread on;
upstream backend {
zone tcp_mem 64k;
hash $mqtt_preread_clientid consistent;
server 10.0.0.7:1883; # upstream mqtt broker 1
server 10.0.0.8:1883; # upstream mqtt broker 2
server 10.0.0.9:1883; # upstream mqtt broker 3
}
server {
listen 1883;
proxy_pass backend;
proxy_connect_timeout 1s;
}
}
NGINX Plus는 CONNECT 메시지의 사용자 이름 필드를 구문 분석할 수도 있습니다.
3-2. SSL/TLS Termination
장치 간 통신을 암호화하는 것은 데이터 기밀성을 보장하고 중간자 공격으로부터 보호하는 데 중요합니다. 그러나 TLS 핸드셰이킹, 암호화 및 복호화는 리소스 부담이 될 수 있습니다. 이를 해결하기 위해 NGINX Plus는 브로커(또는 브로커 클러스터)에서 데이터 암호화를 오프로드하여 보안 규칙을 간소화하고 브로커가 장치 메시지 처리에 집중할 수 있도록 합니다.
이 예에서는 NGINX를 사용하여 장치에서 백엔드 브로커로의 TLS 암호화된 MQTT 트래픽을 프록시하는 방법을 보여줍니다. ssl_session_cache
지시문은 약 20,000개의 SSL 세션을 저장할 수 있는 5MB 캐시를 정의합니다. NGINX는 proxy_connect_timeout
지시문에 정의된대로 5초 동안 프록시 브로커에 연결을 시도한 후 타임아웃됩니다.
stream {
server {
listen 8883 ssl;
ssl_certificate /etc/nginx/certs/tls-cert.crt;
ssl_certificate_key /etc/nginx/certs/tls-key.key;
ssl_session_cache shared:SSL:5m;
proxy_pass 10.0.0.8:1883;
proxy_connect_timeout 5s;
}
}
3-3. 클라이언트 ID 대체
보안상의 이유로 데이터베이스에는 클라이언트 식별 정보를 저장하지 않을 수도 있습니다. 예를 들어, 장치는 MQTT CONNECT 메시지의 일부로 일련 번호나 기타 민감한 데이터를 전송할 수 있습니다. 장치의 식별자를 클라이언트에서 수신한 다른 알려진 정적 값으로 대체함으로써 NGINX Plus 프록시된 브로커에 접근하려는 모든 장치에 대해 대체 고유 키를 설정할 수 있습니다.
이 예제에서는 장치의 클라이언트 SSL 인증서에서 고유 식별자를 추출하고 이를 사용하여 MQTT 클라이언트 ID를 마스킹합니다. 클라이언트 인증서 인증 (상호 TLS)은 ssl_verify_client
지시문으로 제어됩니다. on 매개변수로 설정하면 NGINX는 클라이언트 인증서가 신뢰할 수 있는 인증 기관 (CA)에 의해 서명되었는지 확인합니다. 신뢰할 수 있는 CA 인증서 목록은 ssl_client_certificate
지시문으로 정의됩니다.
stream {
mqtt on;
server {
listen 8883 ssl;
ssl_certificate /etc/nginx/certs/tls-cert.crt;
ssl_certificate_key /etc/nginx/certs/tls-key.key;
ssl_client_certificate /etc/nginx/certs/client-ca.crt;
ssl_session_cache shared:SSL:10m;
ssl_verify_client on;
proxy_pass 10.0.0.8:1883;
proxy_connect_timeout 1s;
mqtt_rewrite_buffer_size 16k;
mqtt_set_connect clientid $ssl_client_serial;
}
}
3-4. 인증 자격 증명으로서의 클라이언트 인증서
MQTT 클라이언트를 인증하는 일반적인 방법 중 하나는 클라이언트 인증서에 저장된 데이터를 사용하여 사용자 이름으로 사용하는 것입니다. NGINX Plus는 클라이언트 인증서를 구문 분석하고 사용자 이름 필드를 다시 작성하여 이 작업을 백엔드 브로커에서 분담할 수 있습니다. 다음 예제에서는 클라이언트 인증서의 주체 식별 이름 (Subject DN)을 추출하고 CONNECT 메시지의 사용자 이름 부분에 복사합니다.
stream {
mqtt on;
server {
listen 8883 ssl;
ssl_certificate /etc/nginx/certs/tls-cert.crt;
ssl_certificate_key /etc/nginx/certs/tls-key.key;
ssl_client_certificate /etc/nginx/certs/client-ca.crt;
ssl_session_cache shared:SSL:10m;
ssl_verify_client on;
proxy_pass 10.0.0.8:1883;
proxy_connect_timeout 1s;
mqtt_rewrite_buffer_size 16k;
mqtt_set_connect username $ssl_client_s_dn;
}
}
NGINX Plus CONNECT 메시지 Rewrite에 대한 완전한 사양은 ngx_stream_mqtt_filter_module Docs를 참조하십시오.
4. MQTT 배포 최적화, 오늘 시작하세요
NGINX Plus의 MQTT에 대한 향후 개발은 다른 MQTT 메시지 유형의 구문 분석뿐만 아니라 CONNECT 메시지의 깊은 구문 분석을 통해 다음과 같은 기능을 가능하게 할 수 있습니다.
- 추가 인증 및 액세스 제어 메커니즘
- 클라이언트의 속도 제한(Rate Limit)을 통한 브로커 보호
- 메시지 원격 분석 및 연결 메트릭
NGINX Plus에 처음이시라면, 무료 30일 체험을 신청하여 MQTT를 시작해보세요. 또한, NGINX STORE에 문의하여 궁금한 기능을 물어볼 수도 있습니다.
아래 뉴스레터를 구독하고 NGINX와 NGINX STORE의 최신 정보들을 빠르게 전달 받아보세요.