NGINX Plus의 R29 릴리스를 발표할 때, MQTT 메시지 구문 분석을 위한 새로운 기본 지원에 대해 간략히 다루었습니다. 이 게시물에서는 이를 기반으로 NGINX Plus를 구성하여 엔터프라이즈 환경에서 MQTT 배포를 최적화하는 방법에 대해 논의합니다.
MQTT는 Message Queuing Telemetry Transport의 약자입니다. 이는 매우 인기 있는 가벼운 게시-구독 메시징 프로토콜로, 사물 인터넷(IoT) 또는 기계 간(M2M) 장치와 애플리케이션을 인터넷을 통해 연결하는 데 이상적입니다. MQTT는 낮은 대역폭이나 저전력 환경에서 효율적으로 작동하도록 설계되어 많은 수의 원격 클라이언트가 있는 애플리케이션에 이상적인 선택입니다. 가전제품, 자동차, 운송, 제조, 의료 등 다양한 산업에서 사용됩니다.
NGINX Plus R29는 MQTT 3.1.1 및 MQTT 5.0을 지원합니다. 클라이언트와 브로커 사이의 프록시 역할을 하여 핵심 시스템의 작업 부담을 덜어주고, 확장성을 간소화하며, 컴퓨팅 비용을 절감합니다. 특히 NGINX Plus는 MQTT CONNECT 메시지의 일부를 구문 분석하고 다시 작성하여 다음과 같은 기능을 활성화합니다.
MQTT 메시지 처리 지침은 NGINX 구성 파일의 스트림
컨텍스트에서 정의되어야 하며 ngx_stream_mqtt_preread_module
에서 제공됩니다.
및 ngx_stream_mqtt_filter_module
.
사전 읽기
모듈은 NGINX의 내부 프록싱 이전에 MQTT 데이터를 처리하여 파싱된 메시지 데이터를 기반으로 부하 분산 및 업스트림 라우팅 결정을 내릴 수 있습니다.
필터
모듈을 사용하면 수신된 CONNECT 메시지 내의 clientid
, username
및 password
필드를 다시 쓸 수 있습니다. 이러한 필드를 변수와 복합 값으로 설정할 수 있는 기능을 사용하면 구성 옵션이 크게 확장되어 NGINX Plus에서 민감한 장치 정보를 마스킹하거나 TLS 인증서 고유 이름과 같은 데이터를 삽입할 수 있습니다.
이제 MQTT 배포를 최적화하고 특정 요구 사항을 충족하도록 NGINX 구성을 조정하는 데 사용할 수 있는 여러 가지 새로운 지침과 내장 변수가 제공됩니다.
mqtt_preread
– MQTT 구문 분석을 활성화하여 클라이언트 장치에서 보낸 CONNECT 메시지에서 clientid
및 username
필드를 추출합니다. 이러한 값은 내장된 변수를 통해 제공되고 해시 세션을 로드 밸런싱하여 업스트림 서버에 부하를 분산하는 데 도움이 됩니다(아래 예 참조).$mqtt_preread_clientid
– 장치에서 보낸 MQTT 클라이언트 식별자를 나타냅니다.$mqtt_preread_username
– 인증 목적으로 클라이언트가 보낸 사용자 이름을 나타냅니다.mqtt
– MQTT 재작성이 활성화되어 있는지 여부를 정의합니다.mqtt_buffers
– 연결당 할당할 수 있는 MQTT 처리 버퍼의 최대 수와 각 버퍼의 크기를 재정의합니다. 기본적으로 NGINX는 연결당 버퍼 수를 100개로 제한하고 각 버퍼 길이는 1k입니다. 일반적으로 이는 성능에 최적화되어 있지만 특수한 상황에서는 조정이 필요할 수 있습니다. 예를 들어, 더 긴 MQTT 메시지에는 더 큰 버퍼 크기가 필요합니다. 짧은 시간 내에 주어진 연결에 대해 더 많은 양의 MQTT 메시지를 처리하는 시스템의 경우 버퍼 수를 늘리면 이점이 있을 수 있습니다. 대부분의 경우, 버퍼 매개변수를 조정하는 것은 기본 시스템 성능에 거의 영향을 미치지 않습니다. NGINX는 내부 메모리 풀에서 버퍼를 구성하기 때문입니다.mqtt_rewrite_buffer_size
– MQTT 메시지를 구성하는 데 사용되는 버퍼의 크기를 지정합니다. 이 지침은 더 이상 사용되지 않으며 NGINX Plus R30 이후로는 사용되지 않습니다.mqtt_set_connect
– 클라이언트에서 보낸 CONNECT 메시지의 매개변수를 다시 씁니다. 지원되는 매개변수는 다음과 같습니다: clientid
, username
및 password
.NGINX Plus를 사용하여 MQTT 메시지를 처리하는 이점과 관련된 모범 사례를 더 자세히 살펴보겠습니다. 아래 예에서는 1883과 8883 포트를 사용했습니다. 포트 1883은 기본 비보안 MQTT 포트이고, 8883은 기본 SSL/TLS 암호화 포트입니다.
MQTT 장치의 일시적인 특성으로 인해 클라이언트 IP가 예기치 않게 변경될 수 있습니다. 이로 인해 장치 연결을 올바른 업스트림 브로커로 라우팅할 때 문제가 발생할 수 있습니다. 이후 한 업스트림 브로커에서 다른 업스트림 브로커로 장치 연결을 이동하면 브로커 간에 비용이 많이 드는 동기화 작업이 발생하여 지연 시간과 비용이 늘어날 수 있습니다.
MQTT CONNECT 메시지에서 clientid
필드를 구문 분석함으로써 NGINX는 업스트림 서비스 브로커와의 스티키 세션을 설정할 수 있습니다. 이는 백엔드의 브로커 서비스에 대한 연결을 유지하기 위한 해시 키로 클라이언트 ID
를 사용하여 달성됩니다.
이 예에서 우리는 클라이언트 ID를
토큰으로 사용하여 MQTT 장치 데이터를 프록시하여 세 개의 업스트림 브로커에 대한 스티키 세션을 설정합니다. 일관된 매개변수를 사용하면 업스트림 서버에 장애가 발생하더라도 해당 서버의 트래픽이 나머지 서버에 균등하게 분산되어 해당 서버에 이미 설정된 세션에 영향을 미치지 않습니다.
stream { mqtt_preread 켜짐;
업스트림 백엔드 {
zone tcp_mem 64k;
해시 $mqtt_preread_clientid 일관성 있음;
서버 10.0.0.7:1883; # 업스트림 mqtt 브로커 1
서버 10.0.0.8:1883; # 업스트림 mqtt 브로커 2
서버 10.0.0.9:1883; # 업스트림 mqtt 브로커 3
}
서버 {
수신 1883;
proxy_pass 백엔드;
proxy_connect_timeout 1초;
}
}
NGINX Plus는 MQTT CONNECT 메시지의 사용자 이름 필드를 구문 분석할 수도 있습니다. 자세한 내용은 ngx_stream_mqtt_preread_module
사양을 참조하세요.
장치 통신을 암호화하는 것은 데이터 기밀성을 보장하고 중간자 공격으로부터 보호하는 데 중요합니다. 그러나 TLS 핸드셰이킹, 암호화 및 복호화는 MQTT 브로커에 리소스 부담이 될 수 있습니다. 이를 해결하기 위해 NGINX Plus는 브로커(또는 브로커 클러스터)에서 데이터 암호화의 부담을 덜어 보안 규칙을 단순화하고 브로커가 장치 메시지 처리에 집중할 수 있도록 합니다.
이 예에서는 NGINX를 사용하여 장치에서 백엔드 브로커로 TLS로 암호화된 MQTT 트래픽을 프록시하는 방법을 보여줍니다. ssl_session_cache
지시어는 5메가바이트의 캐시를 정의하는데, 이는 약 20,000개의 SSL 세션을 저장하기에 충분합니다. NGINX는 proxy_connect_timeout
지시문에서 정의한 대로 시간이 초과되기 전까지 5초 동안 프록시 브로커에 접속을 시도합니다.
스트림 { 서버 {
수신 8883 ssl;
ssl_certificate /etc/nginx/certs/tls-cert.crt;
ssl_certificate_key /etc/nginx/certs/tls-key.key;
ssl_session_cache 공유:SSL:5m;
proxy_pass 10.0.0.8:1883;
proxy_connect_timeout 5s;
}
}
보안상의 이유로 MQTT 브로커의 데이터베이스에 클라이언트 식별 정보를 저장하지 않도록 선택할 수 있습니다. 예를 들어, 장치는 MQTT CONNECT 메시지의 일부로 일련 번호나 기타 민감한 데이터를 보낼 수 있습니다. 클라이언트로부터 수신한 다른 알려진 정적 값으로 장치 식별자를 대체함으로써 NGINX Plus 프록시 브로커에 도달하려는 모든 장치에 대해 대체 고유 키를 설정할 수 있습니다.
이 예에서 우리는 장치의 클라이언트 SSL 인증서에서 고유 식별자를 추출하고 이를 사용하여 MQTT 클라이언트 ID를 마스크합니다. 클라이언트 인증서 인증(상호 TLS)은 ssl_verify_client
지시문으로 제어됩니다. 이 매개변수를 on으로 설정하면, NGINX는 클라이언트 인증서가 신뢰할 수 있는 인증 기관(CA)에서 서명되었는지 확인합니다. 신뢰할 수 있는 CA 인증서 목록은 ssl_client_certificate
지시어에 의해 정의됩니다.
스트림 { mqtt 켜짐;
서버 {
수신 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 공유:SSL:10m;
ssl_verify_client 켜짐;
proxy_pass 10.0.0.8:1883;
proxy_connect_timeout 1초;
mqtt_set_connect 클라이언트 ID $ssl_client_serial;
}
}
MQTT 클라이언트를 인증하는 일반적인 방법 중 하나는 클라이언트 인증서에 저장된 데이터를 사용자 이름으로 사용하는 것입니다. NGINX Plus는 클라이언트 인증서를 구문 분석하고 MQTT 사용자 이름 필드를 다시 작성하여 백엔드 브로커의 작업 부담을 덜어줍니다. 다음 예에서 우리는 클라이언트 인증서의 주체 고유 이름(Subject DN)을 추출하여 MQTT CONNECT 메시지의 사용자 이름 부분에 복사합니다.
스트림 { mqtt 켜짐;
서버 {
수신 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 공유:SSL:10m;
ssl_verify_client 켜짐;
proxy_pass 10.0.0.8:1883;
proxy_connect_timeout 1초;
mqtt_set_connect 사용자 이름 $ssl_client_s_dn;
}
}
NGINX Plus MQTT CONNECT 메시지 재작성에 대한 전체 사양은 ngx_stream_mqtt_filter_module
사양을 참조하세요.
NGINX Plus에서 MQTT에 대한 향후 개발에는 다른 MQTT 메시지 유형의 구문 분석과 다음과 같은 기능을 활성화하기 위한 CONNECT 메시지의 심층 구문 분석이 포함될 수 있습니다.
NGINX Plus를 처음 사용하시는 경우 무료 30일 체험판 에 가입하여 MQTT를 시작해 보세요. 또한 여러분에게 가장 중요한 기능에 대한 여러분의 피드백을 듣고 싶습니다. 여러분의 의견을 댓글로 알려주세요.
"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."