안녕하세요. Humanscape Software Engineer David 입니다.
오늘은 nginx로 forward proxy 구현한 경험을 공유하려합니다.
forward proxy와 reverse proxy의 개념이 궁금하신 분은 링크를 참고해주세요.
왜 forward proxy를 구축하게 되었을까요?
Humanscape에는 Google cloud platform의 App engine로 운영되는 서버가 있습니다. 특정 기능을 개발하기 위해선 3rd party 업체와의 연동이 필요한데요, 해당 업체에서 white list 관리를 위해 우리 App engine 서버의 external IP를 알려달라는 요청이 있었습니다.
하지만.. 공식문서에도 나와 있듯이 App engine은 external IP를 지원하지 않습니다.(공식 문서 참고)
그래서 nginx를 이용해 GCE에 forward proxy 구현을 결정하게 됩니다.
Why nginx?
caddy는 유료라 패스했고, node.js나 python으로 구현하면 비즈니스 로직을 추가 할 수 있는 장점도 있었지만 배포관리를 해야하는 점과 우리에게 비즈니스 로직이 앞으로도 필요없을 것이라 판단하여 nginx로 결정하게 되었습니다. 혹시 더 좋은 의견이 있으면 언제든 댓글로 남겨주세요. :)
구현
다음과 같은 순서로 구현하게됩니다.
GCE 인스턴스 생성
nginx 설치 (with ngx_http_proxy_connect_module)
사용법
테스트
GCE 인스턴스 생성
GCP console(https://console.cloud.google.com/compute/instances)에서 create instance를 통해 프로젝트에 맞는 옵션으로 proxy server로 사용할 GCE 인스턴스를 생성해주세요. 아래 그림의 External IP가 우리가 3rd party 업체에 제공해야할 IP가 됩니다.
nginx-proxy-dev라는 이름의 인스턴스
그림과 같이 생성된 인스턴스에 SSH connet를 통해 접속합니다.
nginx 설치 (with ngx_http_proxy_connect_module)
nginx를 설치하고 proxy 설정에 필요한 모듈인nginx_http_proxy_connect_module을 설치해줍니다.
nginx는 현재(2019.10)최신버전인 1.17.0로 설치를 진행하겠습니다. (nginx 버전 선택시 nginx_http_proxy_connect_module 레포지토리 readme의 select patch에서 지원여부 확인 후 결정해주세요.)
$ wget http://nginx.org/download/nginx-1.17.0.tar.gz $ tar -xzvf nginx-1.17.0.tar.gz $ git clone https://github.com/chobits/ngx_http_proxy_connect_module.git $ cd nginx-1.17.0/ $ patch -p1 < ../ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_101504.patch $ ./configure --add-module=../ngx_http_proxy_connect_module $ make && make install
위 과정을 진행하는 동안 git, make 등의 명령어를 사용하기 위한 패키지들을 중간 중간 설치해주어야합니다. 설치과정은 생략합니다.
위 과정을 거치면 nginx 1.17.0 과 모듈에 대한 설정이 완료 됩니다.
이제 nginx.conf 를 변경해주어야 합니다.
worker_processes 1;
events { worker_connections 1024; }
http { keepalive_timeout 65;
server { listen 3128; server_name '서버의 도메인을 입력해주세요.';
access_log logs/access.log;
# dns resolver used by forward proxying resolver 8.8.8.8;
# forward proxy for CONNECT request proxy_connect; proxy_connect_allow 443 563; proxy_connect_connect_timeout 10s; proxy_connect_read_timeout 10s; proxy_connect_send_timeout 10s; location / { proxy_pass $scheme://$http_host$uri$is_args$args; } } }
nginx.conf 파일을 위와 같이 바꾸어주었습니다.
주의하여 살펴보아야 할 것은 3가지가 있습니다.
server_name 부분에 compute engine에 연결 된 서버 도메인을 넣어주세요.
nginx -s reload를 잊지 말아주세요.
compute engine에 conf 파일에서 지정한 서버 포트 (3128)에 대한 방화벽 설정을 해주세요.
사용법
curl https://github.com/ -v -x [서버 도메인]
테스트
사용법은 위와 같은데 우리의 목표였던 Single IP 반환이 제대로 되고 있는지 테스트 해보아야합니다.
시나리오는 로컬에 x-forwarded-for 헤더를 찍어주는 서버 구동 -> nginx forward proxy를 이용해 로컬 서버에 접속 으로 진행해보겠습니다.
로컬에 x-forwarded-for 헤더를 찍어주는 서버 구동
x-forwarded-for(XFF): HTTP Header 중 하나로 HTTP Server에 요청한 Client의 IP를 식별하기 위한 표준입니다.
XFF를 찍어주는 간단한 node 코드입니다.
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
console.log(ip);
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
위 서버를 3000번으로 띄워준 뒤 아래와 같이 접속하면 될 거 같지만 안타깝게도 로컬 서버에 바로 붙을 수 없습니다.
curl https://localhost:3000 -v -x [서버 도메인]
그래서 http://serveo.net/ 이라는 솔루션을 이용합니다.
serveo는 설치나 가입없이 간단히 로컬서버를 인터넷 상에 노출 시켜주는 서비스입니다.
ssh -R 80:localhost:3000 serveo.net
위 명령어를 통해 https://[abcd].serveo.net 와 같이 내 로컬에 접속할 수 있는 도메인이 생성되어 안내됩니다.
그럼 이제 도메인이 생겼으니 아래와 같이 테스트가 가능합니다.
curl https://[abcd].serveo.net:3000 -v -x [서버 도메인]
로컬서버에 콘솔에 forward proxy로 설정한 서버의 ip가 찍혔다면 따로 SSL 등록 없이 https 접속이 가능한 간단한 프록시 만들기 성공입니다.
감사합니다.
Get to know us better! Join our official channels below.
Telegram(EN) : t.me/Humanscape KakaoTalk(KR) : open.kakao.com/o/gqbUQEM Website : humanscape.io Medium : medium.com/humanscape-ico Facebook : www.facebook.com/humanscape Twitter : twitter.com/Humanscape_io Reddit : https://www.reddit.com/r/Humanscape_official Bitcointalk announcement : https://bit.ly/2rVsP4T Email : support@humanscape.io