Backend/Backend 관련 학습 내용

기존 채팅 시스템에서의 WebSocket(웹소켓) 프로토콜의 STOMP 보안 문제점과 인증 레이어 설계

pjhcsol 2024. 11. 29. 19:19

웹소켓은 기본적으로 보안이 없는 프로토콜입니다. 웹소켓은 클라이언트와 서버 간의 지속적인 연결을 제공하지만, HTTP와 달리 본래 인증이나 권한 부여 기능을 내장하고 있지 않습니다. 그로 인해, 웹소켓 연결은 기본적으로 열린 연결로, 특별한 보안 메커니즘이 없으면 누구든지 해당 채널에 접근하고 메시지를 보낼 수 있습니다.

 

웹소켓에서 보안 문제가 발생할 수 있는 이유:

  • 인증 부재: 웹소켓은 클라이언트가 연결을 시작할 때 서버로부터 인증을 받지 않기 때문에, 누구든지 연결할 수 있고 메시지를 주고받을 수 있습니다.
  • 민감한 데이터 노출: 인증 없이 메시지를 전송하게 되면 중요한 정보가 쉽게 노출될 수 있습니다. 예를 들어, 민감한 사용자 데이터나 대화 내용이 외부 공격자에게 노출될 위험이 있습니다.

 

 

Service - WebSocket 프로토콜을 사용한 STOMP 인증 레이어 설계

 

웹소켓 통신에서 보안 강화를 위해 JWT 인증을 추가한 설계를 진행하였습니다. 기존 웹소켓 통신은 인증 없이 메시지를 주고받을 수 있어, 중요한 데이터를 보호할 수 있는 보안이 부족했습니다. 이를 해결하기 위해, 클라이언트가 서버와 연결할 때마다 JWT를 통해 사용자를 인증하고, 연결된 사용자만 메시지를 주고받을 수 있도록 설계했습니다.

 

주요 설계 과정은 클라이언트가 메시지 헤더에 Authorization 추가하여 WebSocket 연결 요청 시 JWT를 포함시켜 서버로 보냅니다.

 

메시지 전송 시에도 Authorization 헤더에 JWT 토큰을 포함시켜 해당 유저에 대한 검증 및 메시지 전송 요청을 인증하게 됩니다.

 

서버는 이 토큰을 검증한 후 유효한 사용자라면 서버는 JwtProvider를 통해 JWT의 유효성을 검증하고, 이를 기반으로 Authentication 객체를 생성하여 WebSocket 세션에 설정합니다.

 

인증된 사용자만 구독/발행 가능: 인증이 완료된 후, STOMP는 메시지를 주고받는 사용자들이 권한을 가지고 있는지 체크하고, 인증된 사용자만 특정 채팅방에 메시지를 보내거나 구독할 수 있도록 처리합니다.

 

이 방식은 특히 채팅 거래 플랫폼 등 중요한 채팅 거래 기록을 다룰 때 사용자 인증을 안전하게 처리하고, WebSocket을 통한 중요한 데이터를 보호할 수 있었습니다. 이 방식은 웹소켓 통신의 보안성을 대폭 향상시키며, 인증된 사용자만 접근할 수 있도록 하여 보안 문제를 해결합니다.

 

그럼 인증된 사용자 접근 외에 메시지 자체 탈취에 대한 부분은?

메시지를 자체를 암/복호화 & 인/디코딩 을 통해 추후 HSM으로의 확장을 통해 메시지의 암호화가 가능하다. 현재는 금액적인 면에서 하드웨어 보안장비를 대체하는 인코딩 디코딩 형식으로 진행된다.

 

 

Access Token을 발급받고, 이를 SHA 해시 함수를 이용해 다시 한 번 유효성 검사를 하는 방식으로 세션ID 하이재킹을 방지할 수 있게 대응했다.

Access Token을 세션에 저장하고 SHA256 해시 함수로 암호화 해서 클라이언트에 넘겨주면 현재 접근한 URL에 포함되어 있는 Access Token을 SHA256 해시 함수로 암호화한 값과 비교를 하여 CSRF 여부 를 판단하게 된다.

 

 

 

 

 

WebSocket 프로토콜을 사용하는 STOMP 메시징 시스템에서 인증을 추가하는 것은 매우 합리적인 설계라고 생각한다.

STOMP 인증 레이어 설계 개요:

  1. WebSocket 연결클라이언트가 서버에 WebSocket 연결을 요청합니다. WebSocket 양방향 통신 지원하며, 클라이언트와 서버가 연결된 상태에서 지속적인 데이터 교환이 가능합니다.
  2. STOMP 메시징 프로토콜: STOMP는 WebSocket 통해 메시지 전송구독발행 등을 처리하는 메시징 프로토콜입니다. STOMP는 메시지의 주제(topic)와 목적지(destination)를 기반으로 메시지를 라우팅하고, 구독/발행 기능을 제공합니다.
  3. 인증WebSocket 연결 시작할 , 클라이언트는 메시지에 Authorization 포함시켜 JWT(Json Web Token) 같은 인증 정보를 서버에 전달합니다서버는 토큰을 사용하여 클라이언트를 인증하고, Authentication 객체를 설정하여 사용자 정보를 확인합니다.STOMP WebSocket 위에서 동작하므로, 클라이언트가 보내는 메시지에 대해 권한이 있는지 확인하거나, 인증된 사용자만 특정 채팅방을 구독할 있도록 하는 등의 인증 권한 관리 있습니다.

WebSocket + STOMP 인증 과정:

  1. 클라이언트가 WebSocket 연결을 요청: 클라이언트는 WebSocket 연결 시 Authorization 헤더를 포함시켜 서버에 요청합니다. 이 헤더에는 JWT와 같은 인증 정보가 담깁니다.
  2. 서버에서 JWT를 검증: 서버는 JwtProvider를 통해 JWT의 유효성을 검증하고, 이를 기반으로 Authentication 객체를 생성합니다.
  3. STOMP 메시징 처리: 클라이언트가 WebSocket 연결 후 STOMP 메시징 프로토콜을 사용하여 메시지를 발행하거나 구독합니다. 서버는 STOMP 메시지의 헤더와 내용을 기반으로 인증된 사용자에게만 메시지를 처리할 수 있도록 합니다.
  4. 인증된 사용자만 구독/발행 가능: 인증이 완료된 후, STOMP는 메시지를 주고받는 사용자들이 권한을 가지고 있는지 체크하고, 인증된 사용자만 특정 채팅방에 메시지를 보내거나 구독할 수 있도록 처리합니다.

결론:

"WebSocket 프로토콜을 사용한 STOMP 인증 레이어 설계"는 WebSocket을 통해 실시간 메시징을 처리하면서 STOMP 메시징 프로토콜을 사용해 메시지 발행 및 구독을 관리하는 방식으로, 이 과정에서 인증 및 권한 검증을 추가하는 설계입니다. WebSocket과 STOMP를 결합하여 보안인증을 강화하는 방식으로 적합한 설계입니다.

 

 

STOMP를 Spring에서 사용하는 장점

  • 하위 프로토콜 혹은 컨벤션을 따로 정의할 필요가 없다.
  • 연결 주소마다 새로 핸들러를 구현하고 설정해줄 필요가 없다.
  • 외부 Messaging Queue를 사용할 수 있다. (RabbitMQ, 카프카, …)
  • Spring Security 사용할 있다.
  • 하지만 프로젝트가 커지고 협업하는 사람들이 많아진다면 어떤 문제점들이 있을까 ->
  • STOMP를 사용하면 형식을 따로 고민할 필요도, 파싱하기 위한 코드를 구현할 필요도 없다.