Nginx는 가볍고 강력한 웹 서버 프로그램이자 리버스 프록시입니다. 생소한 단어가 보입니다. 리버스 프록시란 무엇일까요?
포워드 프록시와 리버스 프록시
Proxy 라는 영단어는 대리인이라는 의미입니다. 즉 ‘프록시’ 는 연결을 중계해 주는 역할을 합니다. 어딘가에 접속하려 할 때, 대신 연결을 받아서 실제 접속하려는 대상에 접속해 결과를 받아 온 뒤, 클라이언트에게 제공해 줍니다. 물론, 클라이언트에게 결과를 제공해주기 전에 가공을 할 수도 있죠.
프록시에는 크게 2 종류가 있습니다. 포워드 프록시와 리버스 프록시입니다.
포워드 프록시의 경우 어떤 클라이언트가 example.com 에 접속하려 할 때, example.com 에 클라이언트가 직접 접속하는 것이 아니라, 포워드 프록시가 클라이언트의 요청을 받아 example.com 에 접속해 그 결과를 클라이언트에 전달해 줍니다.
캐싱이나 사이트 제한 등을 할 수 있어서 기업 네트워크 등에서 사용하며, 검열 회피를 위해 사용하는 프록시도 이러한 포워드 프록시의 일종입니다. 정확한 설명은 아니지만, 클라이언트 측에서 작동한다고 생각하면 편합니다.
반면 리버스 프록시 의 경우는 서버 측에서 작동합니다. 클라이언트가 어떠한 페이지를 보고 싶다고 요청 할 시, 리버스 프록시가 대신 내부 서버와 통신을 한 다음 클라이언트에게 제공해 줍니다.
그러니깐, 포워드 프록시는 ‘클라이언트’ 측에서 작동하면서 외부의 어떠한 서버에 접속을 대신 해 주는 것이고, 리버스 프록시의 경우는 서버 측에서 작동하면서 내부 서버에 대신 접속해 클라이언트에게 제공합니다.
리버스 프록시를 사용하는 이유
FreeNAS 는 jail 시스템 덕에 여러 개의 독립된 시스템이 독립된 주소를 가지고 동작합니다. 그래서 여러 개의 서버를 운영하는 것 처럼 사용하게 됩니다. 실제로 여러 개의 가상 서버를 운용하는 거긴 하죠. 그러니 리버스 프록시가 있으면 편리합니다.
NAT
NAT환경에서 여러 개의 서버를 운용하게 되면 내부 네트워크의 여러 서버들이 하나의 공인 IP 를 공유하게 됩니다. 이 상황에서 NAT 네트워크 밖으로 나갈 때는 문제가 없지만, 들어올 때는 문제가 발생합니다. ‘NAT 내부의 어떤 서버로 요청을 전달해야 하지?’
NAT 환경에서는 이런 문제를 해결하기 위해서 포트포워딩을 사용합니다. 외부 포트 80으로 접속이 들어올 경우 192.168.1.123:8080 으로 전달하라, 하는 식으로 말이죠.
그런데 문제는 여러 개의 서버를 운용할 때 발생합니다. 여러 개의 포트를 포트포워딩 하는 방법도 물론 있습니다. 하지만 그 경우, 클라이언트 입장에선 주소 뒤에 포트 넘버를 붙여서 접속해야 합니다. 블로그는 http://example.com:81 이고 미디어 서버는 http://example.com:82 같은 식으로 말이죠. 이건 너무 불편할 뿐만 아니라 직관적이지 않은 포트 번호를 기억하는 것은 비효율적입니다.
반면 리버스 프록시를 사용할 경우, 하나의 포트로 요청을 받아서 각 요청에 맞게 내부 서버로 요청을 전달해 줄 수 있습니다
blog.example.com 으로 접속하면 블로그로, media.example.com 은 미디어로 접근할 수 있도록 할 수 있다는 것이죠.
보안
리버스 프록시는 웹 방화벽 같은 기능을 할 수 있습니다. 리버스 프록시와 실제 서비스를 제공하는 서버가 분리되어 있기 때문에 방화벽 역할을 하게 되며, 접속자 입장에서는 내부 서버를 알 수 없기 때문에 서버 정보가 숨겨지니 보안상 좀더 안전합니다. ModSecurity 같은 보안 모듈을 설치하게 되면 방화벽의 역활을 더 잘 수행할수 있겠죠.
암호 통신
또한 암호화가 가능한데, 리버스 프록시가 내부 서버와 비 보안 통신을 한 후 암호화하여 클라이언트와 통신할 수 있기 때문에, 모든 내부 서버에 암호화 설정을 해 주지 않아도 되서 관리자의 부담이 줄어들고 클라이언트와 안전한 통신을 할 수 있다는 장점이 있습니다.
캐싱
또한, 리버스 프록시는 캐싱이 가능합니다. 리버스 프록시에서 캐싱을 할 경우, 내부 서버에 가해지는 부하가 줄어들기 때문에 좀더 빠른 사이트 운용이 가능해집니다.
구축 계획
Certbot 으로 Let’s Encrypt 인증서를 받아오고 갱신할 것이고,
OpenSSL 1.1.1 를 통해 TLS 1.3 을 지원하게 할 것이고,
ModSecurity 를 통해 Nginx가 웹 어플리케이션 방화벽으로 작동하게 할 것이며
Fail2Ban 으로 BruteForce 공격을 막을 것입니다.
종합하면, TLS 1.3 을 지원하는 Nginx 웹 어플리케이션 방화벽 리버스 프록시를 만들 것입니다.
Dataset 만들기
System/Logs/Nginx_WAF
리버스 프록시의 로그가 저장될 데이터셋입니다.
Jail 만들기
Jail의 이름은 Nginx_WAF
네트워크는 자신의 환경에 맞춰서 잡아 주시고,
자동 부팅 설정해 주세요.
마운트 포인트 설정
iocage exec Nginx_WAF mkdir -p /var/log/nginx/
Nginx의 로그가 저장될 디렉토리를 만들어주고
iocage stop Nginx_WAF
감옥을 정지시켜 줍니다.
/mnt/System/Logs/Nginx_WAF ↔ /var/log/nginx/
마운트 해 주세요.
필요한 패키지 설치
iocage console Nginx_WAF
감옥으로 로그인 해 주세요.
최신 레포로 변경
먼저 레포를 lastest 로 교체해 줍니다. 교체하는 방법은 ‘pkg 와 port – 레포 업데이트‘ 를 참고하시길 바랍니다.
패키지 레포 업데이트와 Porttree 받아오기
pkg update && pkg upgrade && portsnap auto
pkg 레포를 업데이트 하고, porttree 를 모두 받아 오고 나면 쉘로 돌아 올 것입니다.
pkg 를 통해 패키지 설치
pkg 를 통해 필요한 패키지를 설치해 주도록 하겠습니다.
pkg install openssl modsecurity3 portupgrade py36-fail2ban py36-certbot py36-certbot-dns-cloudflare ddclient modsecurity3-nginx
차례대로
- TLS 1.3 을 위한 openssl
- nignx 보안을 위한 modsecurity3
- port 업그레이드를 위한 portupgrade
- 브루트포스 공격을 막기 위한 fail2ban
- lets encrypt 인증서 발급과 갱신을 위한 certbot
- certbot 의 cloudflare 애드온
- ddns 를 위한 ddclient
- nginx 의 modsecurity3 라이브러리를 위한 modsecurity3-nginx 입니다.
위 명령을 입력하면 설치할 패키지의 목록과 아래 메세지가 나타날 것입니다.
Proceed with this action? [y/N]:
원하는 패키지를 설치하는 것이 맞는지 확인 한 후, y 를 눌러 설치합니다.
Port 로 Nginx 컴파일 설치
OpenSSL
기존에 openssl111 을 설치하신 분도 아래와 같이 변경해 주세요.
Nginx 을 컴파일할 때 OpenSSL 을 사용하도록 설정해야 합니다.
echo DEFAULT_VERSIONS+=ssl=openssl >> /etc/make.conf
FreeBSD 에도 기본적으로 OpenSSL 이 설치되어 있기는 하나, 현재 FreeNAS 에 탑재되어 있는 OpenSSL 버전은 1.0.2s 으로 TLS 1.3을 지원하지 않습니다. 그래서 현재 (1월14일) 최신 안정 버전인 openssl 1.1.1d 버전을 패키지로 설치해, 컴파일 시 그것을 사용하도록 설정한 것입니다.
Nginx 컴파일 옵션 설정하기
cd /usr/ports/www/nginx
nginx 포트로 이동한 후
make config
Nginx 의 컴파일 옵션을 설정해 줍니다.
키보드의 방향키로 이동하고 스페이스바는 체크, 엔터키는 확인입니다.
마우스로도 클릭할 수 있습니다.
아래로 쭉 내리면 MODSECURITY3 가 있습니다.
체크해 주고 엔터를 누르면 컴파일 옵션이 저장됩니다.
만약 Nginx 를 컴파일하는데 필요한 종속성 포트의 컴파일 옵션을 지정하고 싶다면
make config-recursive
명령을 통해서 모든 종속성의 컴파일 옵션을 전부 설정해 주면 됩니다.
컴파일하기
make install clean BATCH="YES"
BATCH=”YES” 는 컴파일 시 물어보든 모든 질문에 YES 로 답하겠다는 의미입니다.
시간이 좀 걸릴 수도 있습니다.
설치 확인
Nginx 설치 확인
nginx -V
출력에서 built with OpenSSL 1.1.1 와 –add-dynamic-module=/usr/ports/www/nginx/work/ModSecurity 가 있으면 정상적으로 컴파일 된 것입니다.
OpenSSL 1.1.1 설치 확인
OpenSSL 1.1.1 은 기본 프로그램이 아니기 때문에 시스템 영역이 아니라 유저 영역에 설치됩니다.
/usr/local/bin/openssl version
OpenSSL 1.1.1d 10 Sep 2019 와 같이 OpenSSL 1.1.1 이라고 나타나야 합니다.
pkg 에서 nginx 잠그기
port 로 어떤 프로그램을 설치했을 때, pkg 명령을 사용해 패키지를 업데이트 할 경우, pkg 가 port 로 설치한 프로그램을 컴파일 옵션 없이 재설치 해 버립니다. 그것을 막기 위해 패키지를 잠글 것입니다.
pkg lock -y nginx
nginx 를 잠궜습니다. 이제 잠금을 풀기 전까지는 pkg 와 port 둘 다 nginx 패키지를 수정할 수 없습니다.
업데이트 하는 방법
port 와 pkg 를 둘다 쓰니 업데이트 순서가 있습니다.
- pkg update 레포를 먼저 업데이트 한 다음
- pkg upgrade 설치한 프로그램을 업그레이드 하고
- pkg unlock -y nginx 패키지의 잠금을 풀고
- portsnap auto porttree를 최신 버전으로 업데이트 한 뒤
- portupgrade nginx nginx 를 업데이트 합니다.
- pkg lock -y nginx 패키지를 잠급니다.
한 번에 하기 위해선 아래 명령어를 사용하면 됩니다.
pkg update && pkg upgrade && pkg unlock -y nginx && portsnap auto && portupgrade nginx && pkg lock -y nginx
&& 은 앞의 명령어가 실행에 성공하였을 때 뒤의 명령어를 실행한다는 의미입니다.
마치면서
리버스 프록시를 어덯게 구축할지 설명하고 필요한 프로그램을 설치하였으며 업그레이드 하는 방법을 다루었습니다. 다음 포스팅에서는 Certbot 으로 Let’s Encrypt 인증서를 받도록 하겠습니다.