• yundream
  • 2022-07-23 16:01:41
  • 2018-01-23 16:32:51
  • 62640

Contents

WebSocket

WebSocketHTTP와는 달리 전이중 통신 채널을 제공하는 프로토콜이다. HTTP와는 전혀 다른 프로토콜이지만 HTTP로 부터 유도되기 때문에, HTTP와 쎄트로 취급하는 경우가 많기는 하다. WebSocket을 이용하면 서버&클라이언트가 (마치 소켓 프로그램처럼) 자유롭게 메시지를 주고 받을 수 있다.

NginX를 이용해서 WS를 프락시하는 방법을 살펴보려 한다.

테스트용 WS 애플리케이션 준비

테스트를 위해서 echo를 서비스하는 golang 으로 개발된 웹 애플리케이션을 준비했다. echo golang websocket application에 있는 server.go 프로그램을 그대로 사용했다. 코드를 실행했다. 이 코드는 8080 포트에 바인드 한다.
# go run echo.go

Nginx 설정을 변경한다. 우분투리눅스에서 Nginx 설정은 /etc/nginx/site-enabled/default 를 수정하면 된다.
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    ......
    ......
    location /ws/ {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }
}
nginx를 재시작하고 localhost제 접근하면 프락시 되는 걸 볼 수 있다. 그런데 Websocket으로 업그레이드 하면서 아래와 같은 에러가 발생했다.
$ go run echo.go 
recv: Hello world!
read: websocket: close 1001 (going away)
upgrade:websocket: 'Origin' header value not allowed
Nginx에서 웹소켓을 리버스프락시 할 때의 헤더 정보를 보자.
GET /echo HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate, br
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: no-cache
Connection: Upgrade
Cookie: _ga=GA1.1.1798860791.1500182387
Origin: http://localhost
Pragma: no-cache
Sec-Websocket-Extensions: permessage-deflate; client_max_window_bits
Sec-Websocket-Key: 03SvnEbGeWQjug0BmxXzaw==
Sec-Websocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
Origin 헤더가 보일 것이다. Origin 헤더는 요청이 이루어진 위치를 나타낸다. 여기에는 경로정보가 포함되지 않으며 오직 서버이름만 표시된다. 이 헤더는 CSRF(Cross-Site Request Forgery)취약점을 완화하기 위해서 사용한다. go언어의 gorilla 툴킷이 Orgin이 포함된 경우 CSRF 취약점에 노출될 수 있다고 판단해서 연결을 거부한 거다. "proxy_set_header"로 Orign 헤더를 빈 문자열로 설정하면 된다.
    location /ws/ {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Origin "";
    }