포트 포워딩 없이 ESP8266 제어: MQTT 외부 경로
인터넷에서 접근할 수 있는 브로커가 있으면 기기가 스스로 연 연결을 통해 가정용 기기를 제어할 수 있다. TLS 메모리, 토픽, 재전송에 무엇이 달라지는가.
기기는 포트 포워딩도 공인 주소도 없는 가정용 라우터 뒤에 있지만 몇 초 안에 설정을 받아야 한다. 트릭은 방화벽의 구멍이 아니다. 기기가 도달할 수 있는 브로커로 바깥을 향해 연결을 열고, 브로커가 같은 확립된 경로로 메시지를 되돌려 보내는 것이다. 이 설계에서 사람들이 좋아하는 모든 성질과 그 안의 모든 함정은 이 역전에서 나온다.
NAT를 실제로 통과하는 것
기기가 브로커로 TCP 연결을 열면 가정의 라우터가 매핑을 만들고 흐름이 사는 동안 유지한다. 그 흐름의 응답은 매핑이 이미 있으므로 기기로 돌아온다. 브로커는 집 쪽으로 아무것도 시작하지 않으므로 라우터가 거부할 비요청 인바운드 패킷이 없다. 이것이 네트워킹 논거의 전부이며, 통제하지 않는 네트워크에서 이 접근이 통하는 이유다.
기기는 연결을 살려 두거나 다시 세워야 하고, 아키텍처가 정해지면 이것이 신뢰성 문제가 된다.
브로커는 토픽을 라우팅할 뿐 HTTP를 프록시하지 않는다
MQTT는 발행과 구독의 교환을 정의한다. 기기는 읽도록 허용된 토픽 필터를 구독하고, 권한 있는 컨트롤러가 일치하는 토픽에 발행한다. 브로커는 발행을 구독과 맞추고 사본을 전달한다. 브라우저 요청이 무엇인지 알지 못하며 HTTP GET을 기기의 웹 서버로 전달하지 않는다. 기존 펌웨어가 HTTP만 말한다면 브로커 설계에는 애플리케이션 변경이나 의도적인 변환 구성 요소가 필요하다.
토픽 이름도 권한이 아니다. 대부분의 브로커는 클라이언트별 접근 제어 목록을 지원하며, 기기는 하나의 전역 네임스페이스를 공유하는 대신 자체 발행 및 구독 트리로 제한해야 한다.
기기 자원이 TLS의 형태를 결정한다
ESP8266은 RAM이 제한되어 있고 TLS 핸드셰이크는 그것이 하는 가장 비싼 작업이다. Arduino 코어가 BearSSL을 함께 넣은 이유가 바로 이 제약이며, CA를 검증할지 지문을 고정할지의 선택은 메모리 사용량과 다른 이름에 유효한 인증서를 가진 공격자가 할 수 있는 일을 모두 바꾼다. 힙이 허락한다면 브로커의 CA를 검증하는 쪽이 더 강한 선택이다. 페이로드 크기도 중요하다. MQTT 클라이언트는 버퍼를 유지하고, 그보다 큰 메시지는 버퍼를 의도적으로 늘리지 않는 한 조용히 잘린다.
킵얼라이브와 소켓 타임아웃은 같은 예산의 일부다. 죽은 연결을 알아채지 못하는 클라이언트는 오류를 보고하지 않은 채 명령 수신을 멈춘다.
물어뜯는 메시지 의미론
보존 메시지는 브로커가 저장하고 나중에 일치하는 구독자에게 전달한다. 현재 상태에는 훌륭하고 일회성 명령에는 위험하다. 다시 연결한 기기는 어제의 명령을 새것처럼 받을 수 있다. QoS 1은 최소 한 번 전달을 보장하므로 중복은 정상이고 애플리케이션은 반복에 안전해야 하며, 이상적으로는 거부할 수 있는 식별자나 타임스탬프를 갖는다. 유언은 기기가 끊길 때 상태 신호를 주지만, 연결이 매달리지 않고 실제로 실패할 때만 그렇다.
클린 세션 동작은 당신이 없는 동안 브로커가 구독을 유지하는지 결정하며, 여기서 틀리는 것이 일부 기기가 재연결마다 첫 메시지를 놓치는 이유다.
TLS는 브로커까지의 구간을 보호한다. 브로커 운영자에 대항한 페이로드의 종단 간 암호화는 아니다. 운영자는 당신이 그것을 통해 발행하는 모든 것을 읽을 수 있다.
수명 주기를 제한하고 무해한 데이터로 시험한다
재연결은 촘촘한 재시도 루프가 아니라 백오프로 계획하고, 세션이 지속적이지 않으면 명시적으로 다시 구독하며, 연결 결과를 기록해 조용한 오프라인 기기가 증거를 남기게 한다. 명령 채널의 첫 생산 시험은 진짜 명령이어서는 안 되므로 아무것도 하지 않는 샘플 페이로드로 재연결 경로를 시험한다. 그런 다음 오래된 보존 메시지가 재연결 때 무엇을 하는지 확인하고, 그 동작이 토픽마다 허용되는지 결정한다.
이렇게 하면 설계는 인바운드 네트워크 요구를 하나 없애고 기기 소프트웨어, 브로커 정책, 메시지 의미론을 숨은 가정이 아니라 보이는 작업으로 남긴다.