콘텐츠로 이동
무료 평가 시작

TLS와 인증

MQTT 패킷 자체에는 암호화가 없습니다. 보안은 전송 계층의 TLS와 브로커의 인증, 권한 설정으로 만듭니다. MQTT 5.0 §5(보안)은 이 구성을 권고 사항으로 설명합니다.

위협 대책
네트워크에서 메시지 엿보기와 변조 TLS 암호화
가짜 브로커에 연결 서버 인증서 검증(신뢰할 CA와 호스트 이름 확인)
허가되지 않은 클라이언트의 연결 클라이언트 인증서, 사용자 이름과 비밀번호, 확장 인증
연결된 클라이언트의 범위 밖 토픽 사용 브로커의 토픽 권한(ACL)

MQTT over TLS는 TCP 연결 위에서 먼저 TLS 핸드셰이크를 마친 뒤 MQTT 패킷을 주고받습니다. 표준 포트는 8883입니다(§4.2).

클라이언트는 서버 인증서를 다음 순서로 검증합니다.

  1. 인증서 체인이 클라이언트가 신뢰하는 CA(인증 기관)로 이어지는지 확인합니다.
  2. 인증서의 subjectAltName에 연결한 호스트 이름이나 IP 주소가 있는지 확인합니다.
  3. 유효 기간과 용도(extendedKeyUsage의 serverAuth)를 확인합니다.

하나라도 실패하면 핸드셰이크가 끝나지 않고 MQTT CONNECT도 보내지 않습니다. 이때 클라이언트는 TLS 오류를 보고하고, 브로커 로그에는 TLS 경보(alert)가 남습니다. 실제 메시지는 TLS 문제에 정리했습니다.

브로커가 클라이언트에게도 인증서를 요구하는 방식입니다. 클라이언트 인증서는 브로커가 신뢰하는 CA가 발급하고 extendedKeyUsage에 clientAuth가 있어야 합니다. Mosquitto는 require_certificate true로 인증서를 요구하고, use_identity_as_username true로 인증서의 CN을 사용자 이름으로 씁니다. 그러면 인증서마다 토픽 권한을 다르게 줄 수 있습니다.

CONNECT 패킷에 User Name과 Password를 넣는 방식입니다(§3.1.3.5, §3.1.3.6). 값이 평문으로 전송되므로 반드시 TLS 연결에서만 씁니다.

MQTT 5.0은 AUTH 패킷과 Authentication Method, Authentication Data 속성으로 질문과 응답을 여러 번 주고받는 인증을 지원합니다(§4.12). SCRAM 같은 방식을 쓸 수 있지만, 지원 여부와 방법 이름은 브로커마다 다릅니다.

인증된 클라이언트가 어떤 토픽에 발행하고 구독할 수 있는지는 브로커가 정합니다. MQTT 표준은 권한 규칙의 형식을 정하지 않습니다.

Mosquitto의 acl_file은 다음 형식을 씁니다.

# 익명 클라이언트 규칙(user 줄보다 앞)
topic read opcua/uadp/data/#
# 사용자별 규칙
user pdcomm-edge
topic write opcua/#

거부된 발행에 대해 MQTT 5.0 브로커는 PUBACK 이유 코드 0x87(Not authorized)을 돌려줍니다. 구독은 수락하더라도 읽기 권한이 없는 메시지는 전달하지 않을 수 있습니다.

PDComm 시뮬레이터의 MQTT 연결은 TCP 평문이며 사용자 이름, 비밀번호, 인증서 입력이 없습니다. 보안이 필요한 환경에서는 다음처럼 구성합니다.

  1. 시뮬레이터와 같은 호스트나 보호된 네트워크에 로컬 브로커를 두고 평문 리스너를 루프백 주소에만 엽니다.
  2. 로컬 브로커가 TLS 브리지로 원격 브로커에 연결합니다. 원격 쪽 인증은 브리지의 클라이언트 인증서가 맡습니다.

이 구성은 TLS 브로커에 연결 튜토리얼에서 직접 만들어 봅니다.