DevOps./Infra

Nginx로 Reverse Proxy 서버 만들기

PI.314 2022. 11. 21. 17:16

1. Reverse Proxy

우리의 WAS는 비즈니스 로직만 담당하도록 구성하고 싶어요. TLS와 같은 부수적인 기능으로 애플리케이션에 직접 영향을 주고 싶지 않아요. 그럴 때 중간에 대신 역할을 수행하는 녀석이 필요한데, 여기서는 Reverse Proxy가 그 녀석입니다.

 

Reverse Proxy는 클라이언트로부터의 요청을 받아서(필요하다면 주위에서 처리한 후) 적절한 웹 서버로 요청을 전송합니다. 웹 서버는 요청을 받아서 평소처럼 처리를 하지만, 응답을 클라이언트로 보내지 않고 Reverse Proxy로 반환합니다. 요청을 받은 Reverse Proxy는 그 응답을 클라이언트로 반환합니다.

 

통상의 Proxy Server는 LAN -> WAN의 요청을 대리로 수행합니다. 가령, 특정 웹 서비스에 접속하고 싶은데 해당 서비스에서 한국 IP 대역을 막아두었다면, 다른 국가를 통해 접속할 때 Proxy를 활용합니다. 반면 Reverse Proxy는 WAN -> LAN의 요청을 대리합니다. 즉, 클라이언트로부터의 요청이 웹서버로 전달되는 도중의 처리에 끼어들어서 다양한 전후처리를 시행할 수가 있게 됩니다.

 
 
 

* Reverse Proxy와 Load Balancer는 어떤 차이가 있을까요?

  • Reverse Proxy : 보안성 향상, 확장성 향상, 웹 가속(압축/SSL 처리로 백엔드 리소스 확보/캐싱)
  • Load Balancer : 부하분산, 서버상태 체크, 세션 관리

nginx는 Reverse Proxy, Load Balancer 두가지 역할을 수행할 수 있습니다.

 

2. Nginx 설치하기

a. Dockerfile

FROM nginx

COPY nginx.conf /etc/nginx/nginx.conf  

b. nginx.conf

events {}

http {
  upstream app {
    server 172.17.0.1:8080;
  }

  server {
    listen 80;

    location / {
      proxy_pass http://app;
    }
  }
}
$ docker build -t nextstep/reverse-proxy .
$ docker run -d -p 80:80 nextstep/reverse-proxy

실행결과

2. TLS 설정

서버의 보안과 별개로 서버와 클라이언트간 통신상의 암호화가 필요합니다. 평문으로 통신할 경우, 패킷을 스니핑할 수 있기 때문입니다.

certbot error

https://github.com/certbot/certbot-docker/issues/1

 

exec user process caused "exec format error" · Issue #1 · certbot/certbot-docker

I'm trying to run certbot on a Raspberry Pi 3 B+, but I get the error standard_init_linux.go:211: exec user process caused "exec format error". [slang@alarmpi ~]$ docker pull certbot/...

github.com

docker run -it --rm --name certbot \
  -v '/etc/letsencrypt:/etc/letsencrypt' \
  -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
  certbot/certbot certonly -d 'gyeom-subway-admin.kro.kr' --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory
sudo docker run -it --rm --name certbot  
-v '/etc/letsencrypt:/etc/letsencrypt'  
-v '/var/lib/letsencrypt:/var/lib/letsencrypt' certbot/certbot:arm32v6-latest certonly 
-d gyeom-subway-admin.kro.kr --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory

  • DNS를 설정하는 사이트에서 DNS TXT 레코드를 추가한 후, 제대로 반영되었는지 dig 명령어로 확인한 후에 인증서 설정 진행을 계속합니다.
dig -t txt _acme-challenge.gyeom-subway-admin.kro.kr +short
$ cp /etc/letsencrypt/live/gyeom-subway-admin.kro.kr/fullchain.pem ./
$ cp /etc/letsencrypt/live/gyeom-subway-admin.kro.kr/privkey.pem ./

 

📌 Dockerfile 을 아래와 같이 수정합니다.

FROM nginx

COPY nginx.conf /etc/nginx/nginx.conf 
COPY fullchain.pem /etc/letsencrypt/live/gyeom-subway-admin.kro.kr/fullchain.pem
COPY privkey.pem /etc/letsencrypt/live/gyeom-subway-admin.kro.kr/privkey.pem

📌 nginx.conf 파일을 아래와 같이 수정합니다.

events {}

http {       
  upstream app {
    server 172.17.0.1:8080;
  }
  
  # Redirect all traffic to HTTPS
  server {
    listen 80;
    return 301 https://$host$request_uri;
  }

  server {
    listen 443 ssl;  
    ssl_certificate /etc/letsencrypt/live/gyeom-subway-admin.kro.kr/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/gyeom-subway-admin.kro.kr/privkey.pem;

    # Disable SSL
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    # 통신과정에서 사용할 암호화 알고리즘
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

    # Enable HSTS
    # client의 browser에게 http로 어떠한 것도 load 하지 말라고 규제합니다.
    # 이를 통해 http에서 https로 redirect 되는 request를 minimize 할 수 있습니다.
    add_header Strict-Transport-Security "max-age=31536000" always;

    # SSL sessions
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;      

    location / {
      proxy_pass http://app;    
    }
  }
}

 

빌드 및 컨테이너 기동

$ docker stop proxy && docker rm proxy
$ docker build -t nextstep/reverse-proxy:0.0.2 .
$ docker run -d -p 80:80 -p 443:443 --name proxy nextstep/reverse-proxy:0.0.2

 

 


실행중인 컨테이너에 들어가서 nginx.conf 수정하는 방법

 sudo docker exec -it proxy /bin/bash

apt-get update

apt-get install vim

vim ./etc/nginx/nginx.conf