Post View

nginx로 reverse proxy server 구축하기

얼마 전 작성했던 '단위 테스트의 부재로 인한 문제점...' 이라는 글이 구글에서 검색되고 있는걸 확인했습니다.
그런데, url이 https://www.kurien.net이 아니라 https://www.kurien.co.kr로 나오고 있네요...?
딱 봐도 문제가 많을 것 같지만, 제일 문제되는 부분은 https://www.kurien.co.kr로 접근 시 SSL 인증서가 적용이 되어있지 않았기 때문에 위험하다는 오류가 발생한다는 점이었습니다.

해결을 위해 고민을 해본 결과 https://www.kurien.co.kr로 접속을 하더라도 https://www.kurien.net으로 이동하게끔 해두면 구글 측에서 알아서 사이트 정보를 다시 수집할 것이라고 생각했습니다.
그래서 tomcat의 환경설정을 수정하려고 검색을 하니 <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" /> 코드를 tomcat의 server.xml에 입력한 뒤,
conf/Catalina/localhost/ 폴더 안에 rewrite.config 파일을 추가 및 rewrite 내용 작성을 하면 적용된다고 합니다.
 * 참조: https://datajoy.tistory.com/116

결과는 실패...
왜인지는 모르겠지만 오류로그를 확인해보니 org.apache.catalina.valves.rewrite.RewriteValve class 파일이 없다고 하네요.

지금까지는 tomcat의 설정을 수정해서 SSL을 적용하거나 HTTP 접근 시 HTTPS로 이동되도록 작업해왔으나, 이번엔 검색을 해도 이렇다 할 해결책이 안나와서 결국 예전에 다른 프로젝트에서 썼던 reverse proxy를 구축하기로 했습니다.

먼저 proxy server는 클라이언트가 서버로 접근할 때 사이에서 간접적으로 통신을 하게 해주는 역할을 합니다.
이런 proxy server는 foward proxy server와 reverse proxy server가 있는데요,
foward proxy server의 경우 클라이언트 측에서 특정 proxy server를 통해 서버로 접속하는 형태로 이루어지고,
reverse proxy server의 경우에는 서버측에서 클라이언트로부터 보내진 통신을 원하는 지정된 서버로 전달하는 역할을 합니다.
자세한 사항은 아래의 참조를 통해 확인하시길 추천드립니다.
 * 참조: 프록시 서버(https://ko.wikipedia.org/wiki/프록시_서버)
 * 참조: 포워드 프록시, 리버스 프록시(https://www.lesstif.com/system-admin/forward-proxy-reverse-proxy-21430345.html)

저의 경우에는 nginx를 사용해본 경험이 있었기 때문에 www.kurien.co.kr과 같은 제가 예상하지 않은 경로를 통해 서버로 접속할 때 https://www.kurien.net으로 변경되도록 하기 위해서 reverse proxy server를 구축하게 되었습니다.
제 서버에는 docker를 사용하여 서비스들이 구축되어 있으므로 docker에 nginx를 추가했습니다.

docker run --name nginx -d -p 80:80 -p 443:443 -v /home/kurien/services/nginx/:/etc/nginx -v /home/kurien/services/nginx/modules:/usr/lib/nginx/modules nginx

만약 docker를 사용하지 않으시는 분은 데비안 계열 리눅스 기준 apt-get, 레드햇 계열 리눅스 기준 yum을 통해 nginx를 받으셔도 됩니다.

nginx 설치가 되었다면 nginx 설정이 있는 /etc/nginx/conf.d 폴더로 이동해서 default.conf를 삭제한 뒤, www.kurien.net.conf 파일을 추가했습니다.

server {
    listen       80;
    server_name  www.kurien.net kurien.net;

    location / {
        return         301 https://www.kurien.net$request_uri;
    }
}

server {
    listen       443 ssl http2 default_server;
    listen       [::]:443 ssl http2 default_server;
    server_name  www.kurien.net kurien.net;

    if ($host !~* 'www.kurien.net') {
        return 301 https://www.kurien.net$request_uri;
    }

    ssl_certificate "/etc/nginx/key/www.kurien.net/cert.pem";
    ssl_certificate_key "/etc/nginx/key/www.kurien.net/privkey.pem";

    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-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://tomcat:8080;
        proxy_http_version 1.1;
    }
}

위처럼 설정한 뒤 nginx를 재시작 하면 tomcat의 경로로 매칭이 됩니다.

위의 코드에서 주의해야할 점은 ssl_certificate와 ssl_certificate_key는 실제 SSL 키의 위치를 지정해야 하고,
제 경우에는 proxy_pass를 통해 이동하는 경로가 http://tomcat:8080;과 같은 이상한 주소로 되어있습니다.
이것은 제가 docker를 통해 network 환경을 구성해두었기 때문에 위와같은 형태로 사용되는건데요.
docker를 사용하지 않는다면 http://192.168.x.x:8080나 도메인을 가진 주소라면 http://www.example.com 같은 형태로 톰캣이 실행되는 URL을 지정해주면 됩니다.

그리고 설정을 보면 proxy_set_header X-Real-IP $remote_addr;라는 내용이 있는데요.
proxy를 통해 tomcat으로 접속되는 경우 request.getRemoteAddr();를 사용한다면 항상 proxy server의 아이피가 찍힙니다...
이런 문제 때문에 프록시에서 X-Real-IP라는 헤더에 nginx가 전달받은 $remote_addr을 추가하여 tomcat으로 전송해주어야 하며,
프로그램 상에서도 request.getHeader("X-Real-IP");를 통해서 받아야 합니다.
* 참조: https://www.lesstif.com/software-architect/proxy-client-ip-x-forwarded-for-xff-http-header-20775886.html

일단 이렇게 reverse proxy server 구축이 끝났는데요.
작업이 다 끝나면 확인을 해봐야겠죠?
이제는 https://www.kurien.co.kr로 접속을 하더라도 https://www.kurien.net으로 이동되는 것을 확인할 수 있습니다.

reverse proxy는 위와 같은 역할 이외에도 DNS 변경 대신 설정만 바꾸는 형태로 중단 없이 웹서버 이전이 가능하고,
cache 기능을 통해 성능을 향상 할 수 있는 등의 여러가지 장점이 있으니 한번쯤 공부해두시는 것을 추천합니다.

Comments