[우분투, 민트] nginX에서 reverse proxy(리버스 프록시) 사용하기
리버스 프록시 서버는 일반적으로 네트워크 DMZ(방화벽에 의해 보호되지 않는 영역이라고 생각하시면 됩니다.)에 배치되어 인터넷 사용자에 의한 공격으로부터 내부 서버를 보호하는 보안 기능을 수행함으로써 회사 인트라넷 등의 HTTP 서버를 보호하는 보안 장치로 볼수 있습니다. 노출되어있는 네트워크에 단일화된 서버를 놓고 HTTP 서비스에 대한 단일 액세스 지점을 제공함으로써 여러가지 장점을 제공하게 됩니다.
리버스 프록시 서버가 배치되면 리버스 프록시 서버와 연관된 URL만 웹 브라우저 사용자에게 공개됩니다. 인터넷의 사용자는 이 URL을 사용하여 리버스 프록시 서버에 액세스합니다. 리버스 프록시 서버는 인터넷 사용자의 이러한 요청을 처리하고 이 요청을 적절한 내부 웹서버로 경로를 재지정합니다. 리버스 프록시 서버는 서버에 지정된 리버스 프록시 서버 액세스에 사용되는 URL을 내부 웹서버의 실제 URL로 맵핑합니다. 또한, 반대의 경우 각각의 내부 서버로부터 인터넷 사용자로 전송되는 모든 트래픽은 단일 네트워크 주소에서 전송됩니다.
덧붙여, HTTP 서비스를 이용하여 웹서버에서 URL을 매핑하기 때문에 포트포워딩을 이용해서 여러개의 포트를 이용해서 지저분하게 각각의 서버로 연동시키는것이 아니라 단일 Port를 이용해서 들어온 요청에 대해 리버스 프록시 서버가 URL 매핑을 시키기 때문에 웹서비스에 액세스하는 사용자들은 서버별로 각각의 포트번호를 외우거나 찾을 필요가 없습니다. 말로 설명하는 것보다 도식화된 다이어그램을 보면 더욱 쉽게 이해할 수 있습니다. 다음 다이어그램을 참고하십시요.
개인이나 가정 혹은 소호 비지니스용으로 설치된 웹서버의 경우 아래의 그림처럼 도식화 시킬수 있습니다.
위와 같은 경우 우리가 가장 쉽게 웹서버를 구현하는 일반적인 방법은 무엇일까요 ? 아마도 공유기를 이용한 포트포워딩 일것입니다. 1,2,3,4 각각의 웹서버에 192.168.0.xxx 의 가상 아이피를 할당하고 Port 80, 88, 8000, 8080등의 포트번호를 이용해서 특정 포트를 요청하면 공유기자체에서 해당포트를 사용하는 웹서버를 요청하는 방법으로 많이들 사용하실겁니다.
이 경우 URL이 난잡해지고 관리가 귀찮아지는 경향이 있습니다. 일단 일반 사용자들이 http://url:80/, http://url:88/, http://url:8000/, http://url:8080/ 이런식으로 해당 사이트마다 포트번호를 알고 있어야 되기 때문에 서버가 늘어날수록 접근과 관리측면에서도 어려움이 따르게 됩니다.
맨 처음 설명드린 것처럼 위의 일반적인 경우와 그림을 보면 딱 하나가 달라진 점이 리버스 프록시 서버를 담당하는 서버가 네트워크에서 액세스를 받고 URL 매핑에 의해 동일한 Port 80으로 각각의 웹서버로 요청을 하고 응답을 받아 인터넷상의 사용자에게 보내줍니다. 위 그림에서는 웹서버 모두 Port 80을 사용할수 있다는 개념으로 적어둔 것이지 내부적으로 다른 포트를 사용해도 무방합니다. 사용자들에게는 리버스 프록시 서버가 요청하고 응답을 보내주기 때문에 다른 포트번호를 사용한다고해서 사용자들이 그 포트번호를 알 필요도 없고 딱히 관리하기 어렵지도 않습니다.
위와 같은 다이어그램을 보면 쉽게 다음과 같은 리버스 프록시의 장점을 생각할 수 있습니다.
1. 서버의 부하를 덜어줄수 있는 로드 밸런싱 처리
2. 각 서버의 부하를 덜어준 만큼 웹서버 속도 증대
3. 보안과 익명성
4. 중앙 집중식 log 작성과 감시
5. 캐쉬사용
이외에도 백업서버를 이용한 장애시 긴급 서비스 운영도 생각 해볼수 있습니다.
그럼 이제 nginX 웹서버를 이용해 실제로 리버스 프록시 서버를 설정하여 운영하도록 해봅니다.
리버스 프록시를 이용하면서도 SSL 설정을 적용할수도 있습니다. 하지만, 여기서는 가장 기본적인 리버스 프록시를 설정하는 방법에 대해서만 기술하려 합니다. 사실 아직까지 제 서버가 SSL을 설치하지 않아서 제대로 이야기를 풀어나갈 자신이 없어서 다음 기회에 SSL을 적용하고 나면 다시한번 SSL을 적용한 리버스 프록시에 대해 이야기를 풀어보겠습니다.
먼저 리버스 프록시 서버를 담당할 웹서버에서 nginX 설정을 지정해야 합니다.
/etc/nginx/sites-available에 설정되어 있는 제 설정파일들 입니다. test.akal.co.kr 이라는 가상호스트 URL을 이용해 설정할 생각입니다.
-rw-r--r-- 1 root root 1118 5월 6 11:42 akal.co.kr -rw-r--r-- 1 root root 2598 6월 29 2015 default -rw-r--r-- 1 root root 298 5월 17 15:13 test.akal.co.kr <- 리버스 프록시 매핑URL -rw-r--r-- 1 root root 299 5월 17 15:13 hostname-xxx.akal.co.kr <- 리버스 프록시 매핑URL -rw-r--r-- 1 root root 258 5월 17 15:13 another-xxxx.co.kr <- 리버스 프록시 매핑URL
파일명과 마찬가지로 세가지 URL에 대해서 모두 매핑이 가능합니다. 가상호스트를 이용해서 지정할수도 있고, 완전한 다른 URL을 지정해도 됩니다. 하나의 파일로 생성해도 되지만 유지보수의 편의성과 한눈에 파악하기 좋아서 저는 URL 방식의 파일명을 사용합니다. 아래의 그림과 함께 참고하시면 이해가 쉬우실 겁니다.
test.akal.co.kr 파일 설정 내용
server { listen 80; server_name test.akal.co.kr; location / { proxy_redirect off; proxy_pass_header Server; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_pass http://192.168.0.xxx/; <- 가상아이피 주소로 매핑한다. } }
nginx는 test.akal.co.kr 을 통해 들어온 요청을 192.168.0.xxx 서버로 전환합니다. 이때 포토번호를 변조하셔도 됩니다. 또한 가상아이피가 아닌 리얼 아이피를 사용하는 곳에서는 리얼아이피를 지정해주셔도 됩니다.
리버스프록시 서버에서 요청을 받고 응답하기 위해서는 하단의 웹서버(192.168.0.xxx)에도 nginx는 설치되어 있어야 합니다. 똑같은 /etc/nginx/sites-available 디렉토리내에 test.akal.co.kr 이라는 가상호스트에 대한 설정을 해줍니다.
hostname-xxx.akal.co.kr 이라는 서버도 사용하시려면 마찬가지 해당서버에도 마찬가지 작업을 해주어야 합니다. 다른 도메인 서버도 마찬가지 입니다.
server { listen 80; server_name test.akal.co.kr; client_max_body_size 20M; charset utf-8; root /home/userid/www; index index.html index.php index.htm; location / { try_files $uri $uri/ /index.php?q=$uri&$args; } location ~ \.(php|html|htm)$ { fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; fastcgi_index index.php; fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
일반적인 nginx 설정입니다. php7.0-fpm이 설정되어 있네요. 이 하단의 웹서버는 리버스 프록시 서버에서 요청한 내용을 듣고 nginx에서 응답을 합니다. 이로써 아주 간단하게 리버스 프록시 서버 설정이 끝났습니다. 너무 쉬웠나요 ?
기본적인 내용이라 추가되지 않았었는데 혹시 해서 다시 추가합니다.
nginx는 /etc/nginx/sites-available 에 파일을 작성하고 /etc/nginx/sites-enabled 에서 심볼릭 링크를 걸어두면 실제 nginx 에서는 siteds-enabled 디렉토리에서 include를 하기 때문에 반드시 sites-enabled에 심볼릭 링크를 걸어야 합니다.
$ cd /etc/nginx/sites-enabled $ sudo ln -s /etc/nginx/sites-available/test.akal.co.kr test.akal.co.kr $ sudo service nginx restart
동작여부 확인은 너무 쉽습니다. nginx에서 설정한 홈디렉토리에 index.html 혹은 다른 여타 html 파일이나 php 파일을 만들어 놓고 웹브라우저에서 URL 도메인을 쳐보시고 제대로 작동하는지만 확인하시면 확인은 끝입니다.
언제라고 확답은 못하겠지만 Upstream을 이용한 로드밸런싱이나 SSL과 캐쉬 사용등도 더 열심히 공부해서 추후에 다뤄보겠습니다.
위 예에서 akal과 eilsin이 각각 어디를 가리키는 지 앞에 있는 그림과 연결해서 설명해주시면 좋겠습니다
앗 test.eilsin.co.kr 은 미처 수정하지 못한 오타입니다. test.akal.co.kr 로 정정했습니다.
그림과 연결해서 설명하는 것은 파일을 만들어서 이삼일내로 보강하도록 하겠습니다. 지적감사합니다.
마침 일이 빨리 끝나서 집에 오자마자 수정 해두었습니다. 다시한번 감사드립니다.
이걸 알았다면 진작에 이렇게 세팅했을텐데 추후에 추가하려고 하니 머리가 복잡합니다. 이미 letsencrypt와 self signed ssl등이 돌아가고 있어서 더 그렇게 느껴지네요. ㅠㅠ
한두개의 서버만 운영할때는 비효율적일수도 있겠습니다만, 서버의 중요도나 서버의 대수가 많을때는 리버스 프록시를 활용하는 것이 확실히 좋은 답이 될 것 같습니다. 크게 어렵지는 않습니다 ^-^;
안녕하세요
지금 저에게 딱 필요한 것이였는데
배우고 갑니다.
감사합니다.
도움이 되어서 다행입니다 🙂
안녕하세요.
2번째 그림인 [리버스 프록시 서버를 사용한 경우]의 그림에서 실제로 랜선을 연결하는 구성을 할때
1. 공유기와 리버스 프록시 사의 물리적 연결은 그냥 랜선을 1:1로 꼽아서 연결하면 되겠고
2. 리버스프록시와 하위서버간의 연결은 중간에 스위치 허브를 두고 랜선을 1:다수로 연결해야 하나요?
실제로 랜선연결을 어떻게 해야 하는지 조금 헷갈립니다.
그냥 공유기에 리버스프록시와 하위서버를 모두 연결해도 될것 같지만, 그렇게 되면 복잡한 데이터 전송이 일어날거 같거든요.
너무 몰라서 질문이 제대로 전달 되었는지 모르겠습니다. ㅎㅎ
1. 말씀대로 공유기와 리버스 프록시 서버는 랜선을 꼽아서 연결 하시면 됩니다.
2. 하위서버들은 그냥 공유기에 연결하셔도 됩니다. 공유기 자체에 허브 기능이 있습니다.
3. 웹서버는 포트를 지정하지 않으면 기본적으로 80번 포트를 사용합니다. 공유기에서 포트포워딩을 이용해서 80번 포트로 들어온 요청은 전부다 리버스 프록시 서버로 보내게 되겠죠 ?! 그럼 리버스 프록시 서버가 하위서버들의 주소를 호출해서 요청을 다시 보내고 답변을 받은 후에 그 내용을 요청한 컴퓨터에게 다시 전달하는 역할을 합니다.
4. 만약 리버스 프록시 서버가 없다면 하위 서버들은 80번 포트를 사용할 수 없습니다. 포트의 중복사용은 불가능하기 때문이죠. 그냥 간단하게 우편 배달을 할때 명확한 번지수를 모르면 배달할수 없다고 생각하시면 되겠습니다. ^-^;
친절한 설명 감사합니다~
공유기에 모두 꼽는다는 가정하에, 외부에서 요청이 1건 들어오면
1. 공유기 > 리버스프록시
2. 리버스 프록시 > 하위서버 전송(공유기를 통해)
3. 하위서버 > 리버스 프록시(공유기를 통해)
4. 리버스 프록시 > 공유기
이렇게 4번의 부하를 공유기가 부담해야 하는데,
리버스프록시와 하위서버간의 데이터 전송도 공유기를 통해서 해야 하니
리버스프록시와 하위서버간의 전송은 또 다른 내부 네트워크 망을 통해 이뤄지는게 좀 더 맞지 않나는 생각이 드는데, 어떻게 생각하세요? 인터넷을 찾아봐도 국내 관련 포스팅은 여기에 대한 구체적인 설명이 없더라고요. 외국에선 보이긴 하지만…
https://drive.google.com/open?id=1TlbwdwqfVGZS_1nPgv6Y65gEclwJ1o6r
첨부 이미지를 보면
왼쪽 구성에서 공유기 입장에선 프록시와 서버간의 전송도 처리해줘야 하지만,
오른쪽 구성에서 공유기는 그냥 프록시와만 통신하면 되는 구조입니다.
보통 웹사이트가 50 request를 처리한다 치면
왼쪽 구성에서 공유기는 200건(in/out 합쳐 4배)을 전송 처리해야 하는 격이 되고
오른쪽 구성에서 공유기는 100건(in/out 합쳐 2배)의 전송을 처리해야 하는거 같은데,
제가 뭘 몰라서 놓쳐서 이런 생각을 하는건지 어떤건지 잘 모르겠습니다.
어떻게 생각하세요?
일단 서비스의 양과 대역폭에 의해서 결정되어야 한다고 봅니다. 동시 접속이 50 Request면 작은 서비스도 아니고 개인이 공유기로 구현할 서비스도 아닌것 같습니다. 네이버 파워블로거의 하루방문자가 2만명 정도인것을 상정해보면 4.32초에 한명꼴입니다. 물론 산술적 계산에 의한 것이기 때문에 동시접속이 몰리는 시간대나 동시에 몰리는 상황이 발생할때도 물론 있겠죠.
제가 이런 수치를 말씀드리는 이유는…50 request 를 동시에 처리하는 경우도 거의 없지만 (일단 요즘 웹서비스도 비동기식 처리죠 ^-^) 그정도면 이미 공유기로 서비스할 내용이 아닌겁니다.
제가 공유기를 이용한 프록시 서버를 올린 이유는 저가형 시스템을 이용하거나 혹은 라즈베리 파이 라던지 여러가지 상황에서 서버를 반드시 분리해야 하는 경우가 있습니다. 이런 경우에 프록시 서버를 사용하면 충분히 쉽게 시스템을 구성할수 있다는 취지구요. 요즘 공유기 기가와이파이를 지원해서 왠만한 대역의 사용자수는 충분히 커버가 됩니다 🙂 물론 프록시 서버는 대형 시스템에서도 로드밸런싱을 위해서 사용되는 시스템이기 때문에 프록시 서버의 하드웨어적인 사양도 좋아야겠지요.
계속해서 네트워크 라인을 물고 있는 토렌트들과 달리 웹 서비스는 request 신호를 보내고 answer 를 받아서 신호에 맞게 그때그때 처리하기 때문에 네트워크 부하가 생각만큼 심하지도 않을거라고 생각합니다. 걱정하시고 말씀하신 정도의 트래픽을 예상하신다면 그건 개인이 공유기로 시스템을 구현할 내용과는 이미 거리가 멀어진것 같습니다 🙂
참고로 현재 사이트도 공유기와 HP N54L 마이크로 서버를 이용해서 서비스 중인데, 평균 일일 700명 정도이고 많을때는 3,000명 정도가 들어왔는데 프록시 서버에서 문제가 생기는 경우는 전혀 없었습니다.
https://brunch.co.kr/@alden/11
이런글도 참고해보시면 좋겠네요. 로드밸런싱을 위한 upstream 설정인데… 프록시 서버와 마찬가지로 앞단에 있는 서버에 부하가 생기긴 하겠지만 충분히 감당할만하고 분산하는 것이 더 이롭지 않을까 하는 내용이 있습니다. ^-^;
감사합니다. 잘 몰라서 막~ 질문드렸는데 너무너무 감사합니다. 좋은 주말 되시길… 감사합니다
블로그 잘 봤습니다 ㅎㅎ
해당 글의 부분 인용을 하려고 하는데 출처를 남기고 인용을 해도 될련지요?
넵 출처를 남겨주시면 더 감사하죠. 댓글 감사합니다.
리버시 프록시에서 webdav 를 지원하는지요? 도커로 nginx proxy manager 로 연결된 webdav 가 제대로 동작하지 않습니다. 설정이 부족한것 같은데 이리 저리 바꿔봐도 잘 안되어 문의드려봅니다.
제가 글을 너무 늦게 봤네요. 일이 바빠서 T-T
WebDAV는 설정보다 nginX 모듈을 따로 설치해야 합니다. 그게 아니라면 해당 모듈이 설치되어 있는 nginX를 받아서 설치해야 작동하죠.
https://akal.co.kr/?p=1172
이 글을 참고하시기 바랍니다.
그리고, 도커에서의 사용은 제가 안해봐서 모르겠습니다. 죄송합니다.
제 설정은 여기에 올려두었습니다.
http://www.ppomppu.co.kr/zboard/view.php?id=nas&page=1&divpage=8&no=39843