'ActiveMQ.Advisory.Connection' 토픽을 활용한 보안 관제는?
엔터프라이즈 메시징 시스템은 기업의 핵심 데이터가 흐르는 혈관과 같습니다. 따라서 어떤 클라이언트가 브로커에 접근하고 있는지 실시간으로 감시하는 것은 시스템 보호의 최우선 과제입니다. ActiveMQ는 관리자용 콘솔이나 JMX 폴링에 의존하지 않고, 클라이언트의 연결 상태 변화를 실시간 이벤트 메시지로 발행하는 ActiveMQ.Advisory.Connection 토픽을 제공합니다.
이 기능을 활용하면 브로커 자체의 부하를 최소화하면서도, 인가되지 않은 IP 접근이나 비정상적인 연결 시도를 즉각적으로 탐지하고 차단하는 강력한 실시간 보안 관제 파이프라인을 구축할 수 있습니다.

1. 'ActiveMQ.Advisory.Connection' 토픽의 동작 원리
ActiveMQ는 내장된 Advisory 기능을 통해 브로커에서 발생하는 주요 이벤트를 특수한 시스템 토픽으로 브로드캐스팅합니다. 그중 ActiveMQ.Advisory.Connection 토픽은 클라이언트가 브로커와 TCP/IP 연결을 맺거나 끊을 때마다 트리거됩니다.
- 연결 생성 (Connect): 클라이언트가 성공적으로 브로커에 접속하여
Connection객체를 생성하는 순간, 브로커는 해당 클라이언트의 세부 정보를 담은 메시지를 이 토픽으로 발행합니다. - 연결 종료 (Disconnect): 클라이언트가 정상적으로 종료(
close())되거나, 네트워크 파티션/타임아웃으로 인해 브로커가 연결을 강제로 끊을 때 종료 이벤트 메시지를 발행합니다.
2. 페이로드(Payload) 분석: 관제에 필요한 데이터 추출
이 토픽으로 들어오는 메시지는 단순한 텍스트(TextMessage)가 아닙니다. ActiveMQ 내부 데이터 구조체를 담고 있는 ActiveMQMessage 형태이며, 내부의 DataStructure 객체를 파싱해야 관제에 필요한 핵심 정보를 얻을 수 있습니다.
메시지를 수신한 후 getDataStructure() 메서드를 호출하면 이벤트 종류에 따라 두 가지 객체 중 하나가 반환됩니다.
A. 연결 시: ConnectionInfo 객체
getClientId(): 클라이언트가 연결 시 명시한 고유 ID. (예:payment-processor-node-1)getClientIp(): 브로커에 접속한 클라이언트의 실제 IP 주소 및 포트 번호. (예:tcp://192.168.1.50:52314)getUserName(): 인증(Authentication)을 통과한 사용자 계정명.
B. 종료 시: RemoveInfo 객체
getObjectId(): 종료된 연결의 고유 식별자(ConnectionId). 이를 통해 앞서 연결된ConnectionInfo로그와 매칭하여 클라이언트의 체류 시간(Uptime)을 추적할 수 있습니다.
3. 실시간 보안 관제 파이프라인 구축 아키텍처
이러한 연결 정보들을 단순히 로그 파일로 남기는 것을 넘어, SIEM(보안 정보 및 이벤트 관리) 시스템이나 사내 알림 시스템과 연동하는 파이프라인을 구축해야 합니다.
- 전용 관제 워커(Worker) 구성: 비즈니스 로직을 처리하는 서버와 별개로, 오직
ActiveMQ.Advisory.Connection토픽만 구독(Subscribe)하는 경량화된 스프링 부트 애플리케이션을 띄웁니다. - 화이트리스트(Whitelist) 대조: 워커는 수신된
ConnectionInfo의ClientIp와ClientId를 추출하여, 사전에 정의된 보안 화이트리스트(DB 또는 Redis)와 실시간으로 대조합니다. - 이상 탐지 알림(Alert):
- 인가되지 않은 외부 IP 대역에서 접근을 시도한 경우.
- 새벽 시간대에 비정상적으로 잦은 연결/종료(커넥션 풀 오류 또는 Brute Force 공격 의심)가 발생하는 경우.
- 이러한 조건에 부합하면 즉시 메신저 API(슬랙 등)를 호출하여 인프라 보안 담당자에게 경고를 발송합니다.
4. Java (Spring) 기반 관제 컨슈머 구현 예시
실제 관제 워커에서 메시지를 수신하여 파싱하는 핵심 코드 구조는 다음과 같습니다.
import org.apache.activemq.command.ActiveMQMessage;
import org.apache.activemq.command.ConnectionInfo;
import org.apache.activemq.command.RemoveInfo;
import javax.jms.Message;
import javax.jms.MessageListener;
public class ConnectionMonitorListener implements MessageListener {
@Override
public void onMessage(Message message) {
try {
if (message instanceof ActiveMQMessage) {
ActiveMQMessage amqMessage = (ActiveMQMessage) message;
Object dataStructure = amqMessage.getDataStructure();
if (dataStructure instanceof ConnectionInfo) {
ConnectionInfo info = (ConnectionInfo) dataStructure;
String clientIp = info.getClientIp();
String clientId = info.getClientId();
String userName = info.getUserName();
// IP 및 ID 기반 화이트리스트 검증 로직 수행
System.out.println("[ALERT] 신규 접속 감지 - IP: " + clientIp + ", ID: " + clientId);
} else if (dataStructure instanceof RemoveInfo) {
RemoveInfo info = (RemoveInfo) dataStructure;
System.out.println("[INFO] 연결 종료 감지 - Connection ID: " + info.getObjectId());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
5. 도입 시 필수 고려사항 및 제약
관제 시스템을 프로덕션에 적용하기 전 반드시 다음 사항을 점검해야 합니다.
- Advisory 토픽 자체의 접근 제어: 보안을 위해 만든 시스템이 역으로 취약점이 될 수 있습니다. 일반 애플리케이션 계정이
ActiveMQ.Advisory.>경로를 구독하지 못하도록, 브로커의authorizationPlugin설정을 통해 오직 관리자 권한을 가진 계정만 이 토픽에 접근할 수 있도록 엄격히 차단해야 합니다. - 커넥션 폭주 시 부하: L4 로드밸런서의 헬스체크(Health Check) 세션이나, 커넥션 풀을 제대로 설정하지 않아 초당 수백 번씩 접속을 맺고 끊는 불량 클라이언트가 있다면, Advisory 토픽에도 막대한 양의 메시지가 쏟아집니다. 관제 워커가 이 부하를 견딜 수 있도록 비동기 처리(Async Processing) 구조를 갖추어야 브로커에 영향을 주지 않습니다.
'1. 개발 > 1.8. ActiveMQ' 카테고리의 다른 글
| 'JMSReplyTo' 헤더를 이용한 동적 응답 큐 생성법은? (0) | 2026.03.18 |
|---|---|
| 메시지 헤더의 'JMSCorrelationID'를 이용한 RPC 패턴 구현법은? (0) | 2026.03.18 |
| Advisory Topic을 통해 알 수 있는 브로커의 내부 상태 정보들은? (0) | 2026.03.17 |
| 브로커 간 메시지 전달 시 'Hop Count' 제한 방법은? (0) | 2026.03.17 |
| 만료된 메시지(Expired)를 추적하기 위한 감사(Audit) 로그 설정은? (0) | 2026.03.17 |