나스를 완전히 날려버리고 멘탈이 털린 상태로 처음부터 기억에 의존해서 재구축을 시작했다. 역시 비슷한 지점에서 막혔고, 아카이브 해 둔 북마크가 도움이 되었다. 그러니 이번에는 꼭 백업을 잘 하자는 다짐을 하며 삽질의 흔적을 다시 남긴다.
왜 Reverse Proxy 를 구축하나?
요즘 NAS 는 도커같은 컨테이너를 지원해서 매우 간단하게 어떤 서버를 구축 할 수 있다. TrueNAS 는 Jail 이 비스무리한 개념인데, 이런 컨테이너도 당연히 네트워크에 연결되어야 서버로서 동작할 수 있다. 그래서 IP 를 받아야 하는데, 가상의 공유기를 만들어서 IP 를 받는 NAT 방식이 있고, 가상의 네트워크를 만들어서 NAS 가 물려있는 공유기에게 IP 를 받는 VNET 방식이 있다. 차이가 있긴 하지만, 어느 쪽이든 내부 IP ( 주로 192.168 등으로 시작하는 ) 다.
그리고 인터넷에 연결된 공유기는 인터넷 회사( ISP ) 에서 보통 한 개의 IP 를 받는다. 그 IP 를 1.1.1.1 라고 하자. 인터넷의 누군가가 1.1.1.1 이라고 접속하면 일단 공유기가 ‘저요!’ 하고 손을 번쩍 든다. 근데 공유기는 서버가 아니기 때문에 그 부름에 답을 해 줄 수가 없다. 공유기 밑에는 서버가 붙어 있지만, 1.1.1.1 은 일단 공유기를 부르는 것이기 때문에, 공유기 아래의 서버 중 누구에게 대답을 시켜야 할지 모른다. 한참을 고민하던 공유기는 그냥 404 Not Found 에러를 돌려보낸다.
그래서 포트 포워딩을 이용해서 공유기 밑의 서버로 길을 터 준다. 미리 공유기에 포트 번호와 내부 IP 를 매칭해 놓고, 외부 IP 뒤에 포트 번호를 붙여서 접속을 한다. 1.1.1.1:3000 -> 192.168.0.30 이런 식으로.
포트 포워딩은 쉽고 간편하다. 무엇보다 속도가 빠르다. 그냥 숫자 보고 해당 서버로 연결시켜 주니까 별게 있나. 적당히 한두개 정도 쓰면 그냥 포트 포워딩으로 설정하는게 쉽고 빠르고 편하고 좋은데, 여기서 뭔가를 더 하려면 슬슬 답답해지기 시작한다. SSL 인증서 (이하 HTTPS) 같은거나, 서브 도메인 등등…
포트 포워딩을 이용해도 방법이 없는것은 아니지만, 인증서 같은 것도 각 서버별로 따로 관리해야 하고, 주소를 깔끔하게 줄이려면 외부 서비스를 이용해야 하는 등의 불편함이 있는데, 이걸 한방에 해결할 수 있는게 Reverse Proxy 다.
Web Application Firewall ( WAF ) 이라고 하는게 이 Reverse Proxy 를 이용한거다. 인증서도 한번에 몰아서 관리할 수 있고, 각 내부 IP 에 서브도메인을 할당하는 것도 바로 할 수 있다. 무엇보다 일단 Reverse Proxy 를 거쳐서 내부로 들어와야 하니까 보안 측면에서도 엄청나게 도움이 된다. Redis 같은 건 정말…
이유는 이 정도로 붙이고 TrueNAS 에 설정을 시작한다.
필요한 것
도메인이 있어야 한다. DDNS 서비스를 이용하건, 적당한 주소를 돈주고 사던 상관 없다. DDNS 서비스를 이용하면 서브도메인을 할당할 수가 없는데, Reversr Proxy 에서 도메인 주소 뒤에 경로를 이용할 수 있으니 별 문제 없다.
그리고 Jail 로 구축한 적당한 서버. 테스트 해 봐야 하니까.
동작 시나리오
TrueNAS 에는 여러개의 Jail 이 구동되고 있고, 각 Jail 은 VNET 으로 설정되어 공유기의 DHCP 로부터 내부 IP 를 받고 있다.
gerd.kr 이라는 도메인을 가지고 있고, www.gerd.kr, blog.gerd.kr 등 서브도메인을 이용하여 각 Jail 에 접속하려 한다.
브라우져를 열고 주소창에 blog.gerd.kr 이라고 치면 해당 도메인에 연결된 내부 ip (192.168.0.99) 의 jail 에서 구동되는 서비스가 동작한다.
작업 순서
- Jail 을 만든다.
- nginx 를 설치한다.
- 설정 파일을 편집한다.
- 각 서브도메인 혹은 IP 별로 설정 파일을 만든다.
Jail 을 만든다.
이름은 적당히, Base, 최신 Release, DHCP, VNET 으로 설정한다.
NginX 설치
만든 Jail 을 기동시키고, shell 을 눌러서 shell 을 연다. 그리고…
shell > pkg update && pkg upgrade -y
shell > pkg install nginx
아마 자동으로 rc.d 에 등록될텐데, 혹시 등록되지 않았다면 등록한다.
shell > sysrc nginx_enable=YES
설정 파일 편집
shell > cd /usr/local/etc/nginx
shell > vi nginx.conf
이 파일에 다 때려박아도 되지만, 파일이 커지면 생각보다 관리하기 힘들다. 새로운거 추가하기도 힘들고… 그래서 폴더를 따로 만들고, 각 가상서버 별로 설정 파일을 분리한다. 나는 http { … } 블록을 nginx.conf 에서 관리하고, 내부의 server { … } 블록을 개별 파일로 만들어 관리했다.
http { include mime.types; default_type application/octet-stream; sendfile on; #tcp_nopush on; keepalive_timeout 0; #keepalive_timeout 65; gzip on; include ./domains/*.conf; }
옵션은 똑같이 해도 안해도 그만이지만, 강조한 부분은 틀리면 안 된다. 나는 /usr/local/etc/nginx 폴더 안에 domains 라는 폴더를 만들고 이 폴더 안에 각 가상서버 별로 conf 파일을 만들거라 저렇게 경로를 설정했다. http { … } 블록 안에 원래 있던 server { … } 블록은 default.conf 라는 파일로 따로 분리하여 domains 에 저장했다. 내부 ip 를 쳐서 접속하면 이 default.conf 에 설정된 대로 동작한다.
서브도메인 ( 혹은 IP ) 별 설정
각 가상서버 별로 파일을 만들어 아래 내용을 붙여넣고 적당히 수정한다. server_name 별로 설정파일이 있어야 하고, 겹치면 안 된다.
server { listen 80; server_name blog.gerd.kr; location / { proxy_pass http://192.168.0.99; proxy_redirect off; proxy_set_header Connection ""; proxy_http_version 1.1; 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; proxy_set_header X-Forwarded-For-Proto $scheme; proxy_set_header X-Forwarded-For-Host $host; } }
이 파일을 아까 만든 domains 폴더에 적당한 이름.conf 로 저장한다.
확인
nginx 를 재시작해서 설정파일을 적용시킨다.
shell > service nginx restart
그리고 브라우져를 열어 서비스가 동작하는지 확인한다.