ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Handshake failed due to invalid Upgrade header: null 알아보자
    Protocol/HTTP 2023. 12. 12. 14:57

     

    들어기가전에

    iOS 클라이언트와 Simple(or Streaming) Text Orientated Messaging Protocol(STOMP)  통신을 하는데 SPRING 서버에서 Handshake failed due to invalid Upgrade header: null 오류가 발생했고 해결과정을 작성해보려고 한다.

     

     

    해결 포인트는 공식 레퍼런스에 있다

    이전 포스팅에서(https://doit94.tistory.com/80) 확인한 것처럼 웹서버(ex. nginx)를 거쳐서 뒷단에 SPRING 이 동작할 때는 웹 서버단에서 프록시 설정을 할 확률이 높다는 안내가 떠올랐다!

     

    다시 한번 오류 내용을 짚어보자면,

    $ ERROR "Handshake failed due to invalid Upgrade header: null"

     

    HTTP 요청으로 HTTP Upgrade 헤더를 만들고 Connection 헤더의 값을 Upgrade를 사용하게 만들지 못하는 상황이다!

    위 내용이 원인이지만 근본 원인은 따로 있다.

     

    왜? HTTP Upgrade 헤더를 만들지 못할까? 여기서 `포워드 프록시`, `리버스 프록시` 개념을 알아야 한다.

     

     

    포워드 프록시와 리버스 프록시

    먼저, 프록시 개념을 가볍게 알아보자. 프록시를 사용하는 다양한 사례가 존재하지만 부하 분산 장치를 사용하게 되었을 때 프록시를 주로 사용한다. 클라이언트에서 요청이 오면 부하 분산 장치가 listener 로 확인하고 도메인 네임, IP 주소 등을 통해 해당하는 웹 서버로 요청을 분배하는 것이다.

     

    여기서 재밌는 정보는 프록시라는 구조는 원래 클라이언트 측에 두는 방법에서 시작되었다. 이 유형이 프록시의 원형으로 `포워드 프록시`라고 한다.

    포워드 프록시가 처음 등장했을 때 캐시를 이용하는 것이 목적이었고 방화벽을 실현한다는 중요한 목적이 한 가지 더 있었다.
    이 목적을 달성하기 위해 가장 현실적인 방법은 패킷 왕래를 전부 정지시키는 것이다. 그러나 패킷을 전부 정지시키면 인터넷에 대한 액세스도 정지된다. 이렇게 하여 필요한 것을 통과시키는 방법을 생각하기 위해 `프록시` 라는 구조를 고안한 것이다.

     

     

    포워드 프록시는 메시지를 전송하는 동작도 서버측에 두는 캐시 서버가 웹 서버를 판단하는 부분이 약간 다르다. 포워드 프록시를 사용할 때 URI 부분에 http://~~~ 라는 URL이 그대로 쓰여있어 웹 서버를 사전에 설정해둘 필요없고 모든 웹 서버에 전송할 수 있다.

     

    포워드 프록시를 사용할 경우 브라우저에 대한 설정이 꼭 필요한데 설정이 번거롭고 잘못 설정한 경우에는 브라우저가 제대로 작동하지 않는다. 이에 따라 브라우저에 프록시를 설정하지 않아도 사용할 수 있도록 개량되었다. 리퀘스트 메시지의 URI에 쓰여있는 디렉토리 명과 전송 대상의 웹 서버를 대응시켜서 URI 부분에 http://~~~ 라고 쓰여있지 않은 보통의 리퀘스트 메시지를 전송할 수 있도록 했다. 이것이 서버 측 캐시 서버가 채택한 방식으로 `리버스 프록시`라고 부른다.

     

    여기까지의 정보를 종합해서 내 상황과 연결해보면,

    1. iOS 클라이언트에서 요청이 왔다
    2. 해당 요청은 nginx 프록시 구조로 통한다
    3. nginx는 클라우드 서버측에 설치되어 있기 때문에 서버측 판단이 필요한 리버스 프록시이다
    4. 리버스 프록시로 동작하는 nginx 설정을 변경 해야한다

     

     

     

    프록시 서버(nginx, 그림에서는 캐시), 프록시 뒷 단(spring, 그림에서는 웹), 클라이언트(iOS)

     

    해결방안

     

    # nginx 80 포트로 요청이 들어오면 아래 프록시 경로로 보내준다.
    location / {
    	proxy_pass http://아이피주소;
    	proxy_set_header Host $host;
    	proxy_set_header X-Real-IP $remote_addr;
    	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    	proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    # 게이트웨이 역할을 하는 nginx 설정에서 아래 프록시 헤더 설정을 추가한다.
    location / {
    	proxy_pass http://아이피주소;
    	proxy_set_header Host $host;
    	proxy_set_header X-Real-IP $remote_addr;
    	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    	proxy_set_header X-Forwarded-Proto $scheme;
    	proxy_set_header Upgrade $http_upgrade;
    	proxy_set_header Connection "upgrade";
    	proxy_http_version 1.1;
    }

     

    리버스 프록시 역할을 하는 nginx 설정을 추가하면 해결된다.

    'Protocol > HTTP' 카테고리의 다른 글

    HTTP 메서드 속성을 알아보자  (0) 2023.12.23
Designed by Tistory.