티스토리 뷰

728x90

오늘은 Nginx와 daphne을 이용한 django channels(web socket)에 보안 연결을 적용하는 방법을 소개합니다.

위 목적을 이루기 위해서는 크게 2가지 방법이 있습니다.

첫 번째 방법은 Nginx에 직접 ssl 보안 설정을 하는 것이고,
두 번쨰 방법은 daphne의 -e 옵션을 사용해 소켓 연결에 ssl 보안을 설정하는 방법입니다.

두 가지 방식의 차이점

첫 번째 방식은 web server 단계에서, 두 번째 방식은 django Application 단계에서 보안 인증서를 적용합니다. 

만약 Nginx와 daphne을 이용해 web socket을 배포하신다면 첫 번째 방식을 추천드립니다.
첫 번째 방식을 사용하시면 모든 https(https://...), wss(wss://...) 연결을 하나의 보안 인증서로 관리할 수 있지만, 두번째 방식은 오직 daphne으로 돌아가는 application에만 보안 인증서가 적용되어 여러개의 보안 인증서가 필요하게 될 수 있습니다. 

1. Nginx 설정에 보안 인증서 적용하기

보안 인증서 적용

보안 인증서를 만들어줍시다. 저는 Certbot을 이용해 보안 인증서를 만들었어요.
필요한 정보 (ex: 도메인 등)를 입력합니다.
아마 바로 인증서가 위치한 경로를 알려줄텐데 잘 복사해 둡시다!
필요한 패키지를 깔고 생성된 인증서를 /usr/bin/cerbot (Certbot의 실행 파일이 위치하는 경로)에 연결합니다.

apt install snapd
snap install core
snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
certbot certonly --nginx

Nginx 설정하기

ssl_certificate 부분에 아까 받아온 fullchain.pem 경로를 입력해주세요.
ssl_certificate_key 부분에 함께 받은 privkey.pem 경로를 입력해주세요.

*추가 설정
1. 하나의 백엔드 서버만 사용하였어요. 로드 밸런싱을 사용하지 않았습니다. 로드 밸런싱 사용 시 upstream 블록에 여러 서버를 추가해주세요.
2. http의 기본 포트인 80으로 들어오는 요청은 모두 https로 리다이렉트 하였습니다.
3. https의 기본 포트인 443으로 들어오는 요청을 처리합니다.
4. 로그 파일의 경로를 설정해주었습니다. access_log, error_log
5. 정적 파일인 .static_root와 media 경로를 설정해주었습니다.
6. 일반적인 요청과 /ws로 들어오는 websocket 요청을 분리하여 처리하였으며 필요한 헤더 설정을 추가해주었습니다.

 

upstream app_server {
    server 127.0.0.1:8000;
}

server {
    listen 80;
    server_name example.com;
    rewrite ^/(.*) https://example.com/$1 permanent;
}

server {
    listen 443 ssl;
    server_name example.com;
    access_log /var/log/nginx/example.com_access.log combined;
    error_log /var/log/nginx/example.com_error.log error;

    ssl_certificate /{example_ssl_certificate_route}/fullchain.pem; 
    ssl_certificate_key /{example_ssl_certificate_key_route}/privkey.pem; 
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

    location /static/ {
        alias /.../.static_root/;
    }

    location /media {
        alias /.../media/;
    }

    location / {
        proxy_pass http://app_server;
        proxy_redirect off;

        proxy_set_header Host $http_host;
        proxy_set_header X-Real_IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /ws {
        proxy_pass http://app_server;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

 

daphne 설정하기

저는 systemd 서비스를 이용해 daphne을 구동했습니다. daphne.service 파일입니다.

*추가 설정

재시작 여부, 명령어 정의 등을 해줍니다.
ExecStart=/bin/bash -c 'source {가상환경 active 경로} && daphne -b 0.0.0.0 Project.routing(or asgi):application {추가 옵션} --access-log /var/log/daphne/daphne.log' : daphne을 실행시키기 위한 가상환경을 활성화 해주고, daphne을 구동시킵니다. 외부 접근 활성화를 위해 0.0.0.0으로 바인딩했으며 기본 포트는 8000입니다.
ExecReload=/bin/kill -s HUP $MAINPID : 재시작 명령어입니다.
ExecStop=/bin/kill -s TERM $MAINPID : 중지 명령어입니다.
Restart=on-abort : daphne 서비스가 중단될 경우 자동으로 다시 시작하도록 합니다. 
PrivateTmp=true : 서비스 실행 중 생성되는 파일은 프로세스가 종료될 때 삭제됩니다.
WantedBy=multi-user.target : 이 서비스가 다른 서비스와 함께 시작될 때 실행되는 순서를 결정합니다.

[Unit]
Description=daphne daemon

[Service]
User=DevelopmentAccount
Group=www-data
WorkingDirectory={프로젝트 경로}

Environment="PATH={가상환경 경로}"
ExecStart=/bin/bash -c 'source {가상환경 active 경로} && daphne -b 0.0.0.0 Project.routing(or asgi):application {추가 옵션} --access-log /var/log/daphne/daphne.log'

ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
Restart=on-abort
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Nginx & daphne 구동하기
이렇게 설정 후 아래 명령어를 실행해주면 정상적으로 작동합니다.

sudo systemctl daemon-reload
sudo systemctl enable daphne
sudo systemctl stop nginx
sudo systemctl stop daphne
sudo systemctl start daphne
sudo systemctl start nginx
sudo systemctl status nginx
sudo systemctl status daphne

위 명령어로 활성화 여부를 확인할 수 있습니다.

2. daphne (django application)에 보안 인증서 적용하기

1번과 달리 Nginx의 보안 인증서를 제거하고 daphne 설정만 변경하면 됩니다.
아까와 달리 -e 옵션을 사용해 application 단계에서 보안 연결을 사용합니다.

[Unit]
Description=daphne daemon

[Service]
User=DevelopmentAccount
Group=www-data
WorkingDirectory={프로젝트 경로}

Environment="PATH={가상환경 경로}"
ExecStart=/bin/bash -c 'source {가상환경 active 경로} && daphne -b 0.0.0.0 -e ssl:8443:privateKey={인증서 경로}/privkey.pem:certKey={인증서 경로}/fullchain.pem Project.routing(or asgi):application {추가설정} --access-log /var/log/daphne/daphne.log'

ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
Restart=on-abort
PrivateTmp=true

[Install]
WantedBy=multi-user.target

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함