제육's 휘발성 코딩
반응형

AWS Nginx

운영 환경에서 웹 애플리케이션 앞단에 Nginx를 도커로 사용하여 Reverse Proxy를 구성해보자.

도커 설치

sudo apt-get update && \
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \
sudo apt-key fingerprint 0EBFCD88 && \
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \
sudo apt-get update && \
sudo apt-get install -y docker-ce && \
sudo usermod -aG docker ubuntu && \
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
sudo chmod +x /usr/local/bin/docker-compose && \
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
  • 설치 환경 Ubuntu 22.0.4

 

Reverse Proxy

image

리버스 프록시는 TLS와 같은 부수적인 기능에 영향을 받지않고 WAS에서 비즈니스 로직만 담당하도록 구성하고 싶을 때 사용하는 기능이다. 클라이언트로부터 요청을 받으면 WAS로 요청을 전송하고, 리버스 프록시로 반환한다. 리버스 프록시는 해당 응답을 클라이언트로 반환한다.

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

Nginx를 사용해서 리버스 프록시를 구성해보자. Nginx는 Event-Driven 동작 방식으로 서버로 들어오는 여러 개의 커넥션을 Event-Handler를 통해 비동기방식으로 처리한다. 진행 중인 작업이 종료되면 이벤트가 발생하며, 그 다음 작업을 처리한다.

Dockerfile

FROM nginx

COPY nginx.conf /etc/nginx/nginx.conf  
  • FROM은 도커 허브에 있는 nginx 이미지를 가져오는 것을 의미한다.
  • COPY 는 로컬에있는 파일을 이미지에 넣을 수 있다.

 

nginx.conf

events {}

http {
  upstream app {
    server 172.17.0.1:8080;
  }

  server {
    listen 80;

    location / {
      proxy_pass http://app;
    }
  }
}
  • nginx.conf는 nginx의 메인 설정 정보가 담긴 파일이다.
    • events 블록 : 주로 네트워크의 동작방법과 관련된 설정값을 가진다.
    • http
      • upstream app : upstream 변수는 server 설정에서 nginx가 받아들인 요청을 어떤 서버로 흘려보낼 것인지를 결정할 때 사용된다. 도커 컨테이너의 네트워크 인터페이스를 보면 기본 ip는 172.17.0.1로 배정된다.
      • server : nginx가 받아들이는 포트(80)를 지정하고, / 로 시작하는 path로 접근하면, 설정한 app으로 돌려준다는 의미를 갖고 있다.
$ docker build -t nextstep/reverse-proxy .
$ docker run -d -p 80:80 nextstep/reverse-proxy
  • 해당 설정을 토대로 이미지를 만들어서 실행해보자. 물론 EC2 인스턴스 (외부망)에서 80포트의 접근을 허용해줘야 한다. 별도의 nginx 설치 없이 도커를 사용해서 8080포트 접근시 80포트로 포트포워딩을 할 수 있다.

 

TLS 설정

$ docker run -it --rm --name certbot \
  -v '/etc/letsencrypt:/etc/letsencrypt' \
  -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
  certbot/certbot certonly -d '[도메인 주소]' --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory
  • 서버의 보안과 별개로 서버와 클라이언트간 통신상의 암호화가 필요하다. 평문으로 통신할 경우 패킷을 스니핑당할 수 있기 때문이다.
  • 다음과 같이 letsencrypt를 활용해서 무료로 TLS 인증서를 사용할 수 있다.

 

image

  • TLS 생성 도중에 유효한 URL인지 확인을 위해 DNS TXT 레코드를 확인하라는 문구가 나오면 생성한 도메인 사이트에 등록하자. 현재 예제에선 C클래스를 사용하고 있기 때문에 IP연결(A) 부분에 www 가 없도록 설정해야한다.
  • 참고로 무료 도메인 사이트를 사용해서 DNS를 등록하였다. https://xn--220b31d95hq8o.xn--3e0b707e/

image

  • 다음과 같이 DNS TXT 레코드가 제대로 반영되었는 지 확인 후에 인증서 설정을 진행하자.
$ cp /etc/letsencrypt/live/[도메인 주소]/fullchain.pem ./
$ cp /etc/letsencrypt/live/[도메인 주소]/privkey.pem ./
  • 생성한 인증서로 TLS 설정을 하기위해 인증서를 복사하자.

 

Dockerfile

FROM nginx

COPY nginx.conf /etc/nginx/nginx.conf 
COPY fullchain.pem /etc/letsencrypt/live/sasca-subway.kro.kr/fullchain.pem
COPY privkey.pem /etc/letsencrypt/live/sasca-subway.kro.kr/privkey.pem
  • Dockerfile을 다음과 같이 수정하자.

 

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/[도메인 주소]/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/[도메인 주소]/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;    
    }
  }
}
  • Nginx 설정으론 HTTP 접근 시 HTTPS 리다이렉트를 위해 server 블록을 80(HTTP)과 443(HTTPS)으로 나눠준다. 그 다음 80으로 접근하는 모든 요청을 HTTPS로 301(Redirect)로 보내준다.
$ docker stop nextstep/reverse-proxy && docker rm nextstep/reverse-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
  • 기존에 생성한 컨테이너를 삭제하고, 새로 이미지를 생성한 후 80포트와 443포트를 열어 실행하자.

 

image

  • 다음과 같이 HTTPS로 정상 리다이렉트 되었다.

REFERENCES


https://icerabbit.tistory.com/116

https://hyeon9mak.github.io/nginx-upstream-multi-server/

https://phsun102.tistory.com/45 

https://edu.nextstep.camp/

반응형
profile

제육's 휘발성 코딩

@sasca37

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요! 맞구독은 언제나 환영입니다^^