NCP

[NCP] Load Balancer 사용 시 웹서버 로그에서 Client IP를 볼 수 있을까?

안녕하세요. ManVSCloud 김수현입니다.

오늘은 Naver Cloud Platform에서 LOAD BALANCER 사용 시에 웹서버 내 로그에 찍히는 IP가 Client IP가 찍히도록 설정하는 방법에 대해 포스팅 하겠습니다.

HTTP 헤더 중 하나인 X-Forwarded-For를 이용하는 방법과 각 소프트웨어의 모듈을 이용하여 Client IP를 식별하는 방법 두 가지에 대해서 알아보겠습니다.


테스트 기본 세팅

해당 이미지를 더블 클릭하시면 큰 화면으로 이미지를 자세히 볼 수 있습니다.

저는 VPC 환경에서 테스트를 진행하였습니다.
(Classic도 동일한 방법으로 가능합니다.)

centos-7.8-64로 생성해주었습니다.
서버 생성 후 Apache를 설치합니다.

[root@manvscloud-web-pub-kr2 ~]# yum install httpd httpd-devel -y
[root@manvscloud-web-pub-kr2 ~]# systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
[root@manvscloud-web-pub-kr2 ~]# systemctl start httpd

테스트 준비는 끝났습니다.
이제 LB가 없을 때, X-Forwarded-For를 사용할 때, 각 소프트웨어의 모듈을 사용할 때에 대해서 살펴보겠습니다.


Load Balancer가 없을 때

우선 Load Balancer가 없을 때 해당 서버로 접근 할 경우 정상적으로 Client IP가 찍힙니다.
(Client – Server)


Load Balancer를 추가했을 때

Application Load Balancer로 생성하였습니다.
index.jsp → index.html
tail -f /var/log/httpd/access_log

Load Balancer를 추가하게되면 위와 같이 Client IP가 아닌 LB의 사설 IP가 찍히게 됩니다.
(Client – LB – Server)

이제 LB가 있는 상태에서 Client IP를 볼 수 있도록 설정해보겠습니다.


X-Forwarded-For

[root@manvscloud-web-pub-kr2 html]# grep -n LogFormat /etc/httpd/conf/httpd.conf 
196:    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
197:    LogFormat "%h %l %u %t \"%r\" %>s %b" common
201:      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio

Apache의 LogFormat을 보면 현재 위와 같이 되어있습니다.
이 LogFormat을 조금 변경해줄 것입니다.

vi /etc/httpd/conf/httpd.conf 를 이용하여 196 라인에 LogFormat을 아래와 같이 변경 해주겠습니다.

    196     LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

기존 LogFormat 가장 앞부분에 %{X-Forwarded-For}i 을 추가해준 것입니다.
이를 추가해준 뒤에 Apache 재시작 1회 진행 후 다시 한 번 로그를 확인해보면 Client IP가 찍히게 됩니다.

웹 접속 시 Client IP가 추가된다.

이 설정은 Apache 뿐만 아니라 Nginx, Tomcat에서도 당연히 설정이 가능합니다.
아래 링크를 참고하면 좋을듯합니다.


Network Proxy Load Balancer

이제 Apache와 Nginx에 모듈을 추가하여 Client IP 식별하는 방법에 대해 알아볼 것입니다.

모듈을 설명하기 앞서 기존에 사용하던 ‘애플리케이션 로드밸런서’에서
‘네트워크 프록시 로드밸런서’로 변경해줄 것입니다.

LB 생성은 크게 다를 것이 없습니다.
다만 Target Group에서 조금 다르게 설정을 해줄 것입니다.

프로토콜은 PROXY_TCP로 해줍니다!
그리고 TargetGroup 설정에서 ProxyProtocol을 클릭해줍니다.

콘솔에서 해줄 작업은 이걸로 끝입니다. 이제 모듈을 추가하러 갑시다!


Apache Module

[root@manvscloud-web-pub-kr2 src]# apachectl -M | grep myfixip

Apache에서는 myfixip 모듈을 이용할 것입니다.
해당 모듈의 경우 기본 내장 모듈이 아니라 아래와 같이 추가해주어야합니다.

[root@manvscloud-web-pub-kr2 html]# cd /usr/local/src
[root@manvscloud-web-pub-kr2 src]# wget --no-check-certificate https://raw.githubusercontent.com/ggrandes/apache24-modules/master/mod_myfixip.c
[root@manvscloud-web-pub-kr2 src]# apxs -aic mod_myfixip.c 
[root@manvscloud-web-pub-kr2 src]# apachectl -M | grep myfixip
 myfixip_module (shared)

myfixip_module이 추가된 것을 확인할 수 있습니다.
이제 httpd.conf에 해당 모듈을 추가해주고 사용할 것입니다.

[root@manvscloud-web-pub-kr2 ~]# cat << EOF >> /etc/httpd/conf/httpd.conf
> LoadModule myfixip_module modules/mod_myfixip.so
> <IfModule mod_myfixip.c>
> RewriteIPResetHeader off
> RewriteIPAllow 10.0.0.0/16  
> </IfModule>
> EOF
[root@manvscloud-web-pub-kr2 ~]# systemctl restart httpd

RewriteIPAllow은 Load Balancer가 있는 대역을 추가해주면 됩니다.
위에서 추가한 Proxy LB로 접속하게 되면 이제 아래와 같이 Log가 남습니다.

Apache myfixip

정말 깔끔하게 Client IP가 보이고 있습니다.
이제 Apache와 함께 많이 사용되고 있는 Nginx에서 설정을 해보겠습니다.


Nginx Module

우선 Nginx는 아래 내용을 참고하면 간단하게 설치가 가능합니다.

[root@manvscloud-web-pub-kr2 ~]# vi /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
[root@manvscloud-web-pub-kr2 ~]# yum install nginx
[root@manvscloud-web-pub-kr2 ~]# systemctl start nginx

Nginx에서의 설정도 어렵지 않습니다.
Nginx에서는 realip module이 있는지 확인해주어야합니다.

nginx -V 2>&1 | grep 'http_realip_module'
해당 이미지와 같이 모듈이 존재한다면 준비는 완료되었습니다.

vi /etc/nginx/nginx.conf 로 nginx의 config파일을 아래와 같이 변경해줄 것입니다.

#    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
#                      '$status $body_bytes_sent "$http_referer" '
#                      '"$http_user_agent" "$http_x_forwarded_for"';

    log_format  main  '$proxy_protocol_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';


        proxy_set_header X-Real-IP         $proxy_protocol_addr;
        proxy_set_header X-Forwarded-For   $proxy_protocol_addr;

        server
        { 
                root    /usr/share/nginx/html;
                listen 80  proxy_protocol;
                set_real_ip_from 10.0.2.0/24;
                real_ip_header proxy_protocol;     
        }

기존 log_format은 주석처리하고 그 아래에 전부 새로 추가한 내용들입니다.

  1. $remote_addr$proxy_protocol_addr로 변경해줍니다.
  2. proxy_set_header을 추가해줍니다.
  3. proxy protocol과 real_ip 설정도 해줍니다.

설정이 끝난 뒤 nginx를 1회 재시작하고 로그를 확인해봅니다.

Apache와 동일하게 Nginx도 Proxy LB로 접속하면 Client IP가 그대로 남는 것을 확인할 수 있었습니다.

이로써 LOAD BALANCER 사용 시에도 웹서버 로그에서 CLIENT IP를 볼 수 있다는 것을 알 수 있습니다.
이 글을 읽으시는 분들께서도 해당 포스팅을 참고하여 서버에서 Client IP가 보이도록 설정해보시는 건 어떠신가요?

웹 로그에서 Client IP를 확인하는 일은 꽤 많은 것같습니다.
가끔 MaxClients 설정이 낮지않은데 MaxClients 수치보다 많은 프로세스로 인해 확인을 해보면 특정 IP가 ESTABLISHED와 CLOSE_WAIT 을 반복하여 대량의 CLOSE_WAIT를 남겨 MaxClients가 순식간에 늘어나는 것을 많이 보았습니다.

그 특정 IP를 log파일에서 여러 명령어와 조합하여 wc -l 로 뽑아내면 공격성 및 이상 접근으로 의심되는 접근을 빠르게 판단하고 차단 / 조치 할 수 있게되는 것 같습니다.

해당 포스팅은 여기서 마무리해보려 합니다.

긴 글 읽어주셔서 감사합니다.

Previous Post Next Post

You Might Also Like

2 Comments

  • Reply moddi 5월 6, 2021 at 12:28 오후

    오우 트러블슈팅에 한결 용이하겠군요! 잘 정리해두겠습니다 센세

    • Reply manvscloud 5월 7, 2021 at 2:22 오후

      오우 도움이 됐다니 매우 만족스럽습니다

    Leave a Reply