morning avatar

Express + Nginx Proxy + SSL + WebSocket

morning

Published: 19 Dec 2019 › Updated: 19 Dec 2019

Express + Nginx Proxy + SSL + WebSocket

상황

당신은 Ubuntu 서버에서 Node.js + Express 로 웹서버를 구현해서 http 로 웹페이지를 서비스하고 있습니다.
그런데... https 로 하고 싶은데 nginx 명령어 일일히 공부할 시간은 없고 대충 구글링 해서 복붙 스타일로 해결하고 싶습니다!
그런 분들을 위한 포스팅.

Nginx 프록시를 이용해서 http 를 https 로 업그레이드 해 봅니다.

로컬에서 개발할 때 보통
http://localhost:3000
이렇게 3000번 포트를 사용하죠. 튜토리얼 샘플코드가 보통 그렇게 되어있으니...

서버에 올려서도 그렇게 똑같이 3000 번 포트에서 돌리면 됩니다. nginx 를 이용해서 443 포트 SSL 로 감쪽같이 바꿔줄 수 있으니까요.
https://YOUR_DOMAIN.com
이렇게 바꿔봅니다.
SSL Certificates 는 구매를 하거나 Let’s Encrypt 를 사용하거나 해서 준비해둡니다.

우분투 서버에서 nginx 의 conf 파일을 열어 편집합니다.
보통 아래 경로에 있죠
sudo nano /etc/nginx/sites-enabled/default

server {
    listen 80 default_server;
    server_name YOUR_DOMAIN.com;
    return 301 https://YOUR_DOMAIN.com$request_uri;
}

server {
    listen 443 ssl;
    server_name YOUR_DOMAIN.com;
    ssl_certificate /YOUR_PATH_TO/ssl.crt; # .pem 파일도 ok
    ssl_certificate_key /YOUR_PATH_TO/ssl.key; # .pem 파일도 ok
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    charset utf-8;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

해설...
80번 포트를 listen 하다가 요청이 있을 때마다 https 로 넘겨줍니다.
http 를 강제로 https 로 전환시켜주는 거죠.

443번 포트를 listen 하다가
주어진 ssl_certificate 를 사용해서
http://localhost:3000 로 연결시켜줍니다.

아래 명령어로 nginx 가 conf 파일을 읽어들여 적용시키도록 합니다.
sudo systemctl reload nginx
아무 메세지가 없으면 잘 된거고
에러메세지가 나왔다면 conf 파일에 오타 등 뭔가 오류가 있는겁니다.

웹소켓으로 리얼타임 커뮤니케이션

여기까지 온 이상 ws:// 으로 하면 secure 하지 않다면서 웹브라우저가 불평을 합니다.
https 사이트에는 wss:// 으로 해야만 하죠.

const express = require('express');
const WebSocket = require('ws');
const app = express();
app.set('port', 3000);
const server = app.listen(app.get('port'), () => console.log('Listening on http://localhost:' + app.get('port')));
const wss = new WebSocket.Server({
    server: server
});
wss.on('connection', (ws, req) => {
});

Express 웹서버가 3000 번 포트에서 돌아가고
WebSocket.Server 를 초기화 할 때 server 파라미터에 넘겨주면 웹소켓 포트 또한 3000번 포트에서 돌아갑니다.
로컬에서는 ws://localhost:3000 으로 접속하면 되죠.
서버에 올렸을 때 웹소켓 엔드포인트를 wss://YOUR_DOMAIN/websocket
으로 바꿔주는 부분을 알아봅니다.

서버에서 새로운 nginx conf 파일을 하나 만들어줍니다.
sudo nano /etc/nginx/sites-enabled/websocket
다 하고나서 sudo systemctl reload nginx 하면 sites-enabled/ 에 있는 모든 파일을 다 읽어서 nginx 정책에 적용해주므로 파일 이름은 편한대로 하면 됩니다. 저는 websocket 이라고 이름붙였습니다.

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream appwebsocket {
    server 127.0.0.1:3000;
}

server {
    listen   443;
    server_name YOUR_DOMAIN.com;

    ssl  on;
    ssl_certificate /PATH_TO/ssl.crt;
    ssl_certificate_key /PATH_TO/ssl.key;

    ssl_session_timeout  5m;

    ssl_protocols  SSLv3 TLSv1;
    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
    ssl_prefer_server_ciphers   on;

    location /websocket/ {
        proxy_pass http://appwebsocket;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

저장하고 nginx 에 적용시키고
sudo systemctl reload nginx

자바스크립트에서 아래와 같은 endpoint 로 웹소켓 접속을 하면 됩니다.

var ws = new WebSocket('wss://YOUR_DOMAIN.com/websocket');
ws.onopen = () => {
 console.log('websocket opened!');
};

그렇게 해서 챗방을 만들어봤습니다.
https://coin-on.com/

Leave Express + Nginx Proxy + SSL + WebSocket to:

Written by

약속된 끝이 있기에 더욱 소중한 우리 삶과 순간들

Read more #sct posts


Best Posts From morning

We have not curated any of morning's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From morning