본문 바로가기
Stove Dev Camp

Spring-boot "Handshake failed due to invalid Upgrade header: null" Error (Spring boot Websocket 연결 에러)

by AndoneKwon 2021. 2. 1.

Handshake failed due to invalid Upgrade header: null?

회사에서 제공해준 EC2 클라우드 환경에서 Websocket을 연결하려고 할 때에 발생했던 오류였다.

현재 구축되어 있는 환경의 대략적인 그림은 다음과 같다.

 

그림1. Server 구조

프로젝트는 앞선 글들을 보면 알 수 있듯이 WebRTC를 주 기술 스택으로 하는 프로젝트여서 반드시 HTTPS를 통한 SSL 인증이 필수였고 그래서 회사에 인증서와 도메인을 함께 요청하였다. 그리고 EC2 서버 내에서 Nginx를 통해서 MSA로 나누어져 있는 각 서버들에게 리버시 프록시를 해주었다.(특히, Websocket의 경우 Header 업그레이드가 필요기 때문이며 SSL 인증이 필요한 포트는 반드시 ELB에서 설정해줘야 했기 때문이었다.)

 

nginx의 config file의 내용은 다음과 같았다.

server {
        listen input.port;
        
        server_name domain.com;

        location / {
                proxy_pass https://127.0.0.1:8888;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_http_version 1.1;
                proxy_pass https://127.0.0.1:포트;
        }
}

 일반적으로 HTTPS(SSL)로 하기 위해서는 도메인에 인증서를 등록하고 그 인증서를 서버내부에 저장하고 nginx로 들어오는 요청에 대해서 SSL로 요청하도록 443번 포트로 Redirect를 하도록 설정해 놓지만 ELB에서 인증서를 등록해놓고 뒷 서버로 넘겨주기 때문에 그래줄 필요가 없다. 특정 포트로 요청이 들어오면 그대로 뒷 서버로 전달만 해주면 된다.

 

하지만 주의 할점은 웹소켓은 기본적으로 HTTP 프로토콜을 이용하여 그 연결을 끊지 않고 유지시켜주는 방식으로 동작하기 때문에 반드시 header에 websocket으로 upgrade한다는 것을 명시해야한다.

이에대한 설정은

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;

위 세줄이다.

 

하지만 예상치 못한 에러가 발생하였다.

저렇게 다 등록을 해주었는데 서버에서 다음과 같은 에러가 발생하였다.

Handshake failed due to invalid Upgrade header: null?

휴..이 에러때문에 인프라 설정을 하는데에 굉장히 골머리를 썩었다.

 

인프라 팀에게 요청을 하여 해결을 하였는데 결말은 다소 허무했다.(진작에 인프라팀에 문의를 했어야 했는데....)

 

문제가 발생한 부분은 바로 ELB쪽에서 생긴 문제였다.

Classic ELB의 경우 기본적으로 Websocket을 지원하지 않는데 기본적으로 요청을 내가 잘못해서

 

HTTP -> HTTPS로 설정되어 있었다. 이방식으로는 헤더가 전달되지 않아 서버입장에서는 Websocket upgrad header가 비어있다고 이야기 하는 것이었다. 다음과 같이 설정하니 해결되었다.

 

SSL -> TCP 로 설정을 한 후에 위와 같이 nginx를 설정해주니 잘 해결 되었다.