컴퓨터 / Computer

varnish 쓸때 실제 접속자 ip 사용하기

공유지기 3 7,687 2016.08.24 22:42

0_fivEmSUN_cafc0046fceae53820e6e11ed19a3a0d3034ec3c.jpg 


지난 번에 varnish 설치하고 phpmyadmin 접속 안되는 현상이 나타났는데, 알고보니 http 접속 로그라든지 REMOTE_ADDR을 통해 접속자 ip 가져오는 것에 문제가 생겼다. 그리하여 이를 해결하고자 이 글을 추가해서 쓴다. 

 

varnish 동작 원리에 대해서는 글이 많으니 간단히 설명한다.

 

웹서버(httpd) -  varnish - 외부 접속자들

 

위 구조에서 외부 접속자들의 ip가 varnish를 지나서 웹 서버로 가면 모두 127.0.0.1로 표시가 된다. 아파치 로그 뿐만 아니라 그누보드나 자체 서비스의 로그에도 접속자 ip가 127.0.0.1로 기록된다. 이 문제가 phpmyadmin 문제와 결부가 되어 3가지 방법으로 해결을 시도하였다. 

 

1안 : 변수 변경

아파치에서 외부 ip를 확인하는 변수는 "REMOTE_ADDR"인데 이 변수를 다른 변수로 대체하여 사용하는 방법을 찾았다. 대체 가능한 변수는 "HTTP_X_FORWARDED_FOR"인데 웹 서버 설정에서 바꾸어야 할 부분이 있다. 

* httpd.conf

1. 추가 :  LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" varnishcombined

2. 수정

     ErrorLog logs/seven2015-error_log varnishcombined

     Customlog logs/seven2015-access_log varnishcombined

 

그리고 이렇게 하기 위해서 varnish 설정 파일을 수정해야 한다. 

* default.vcl : 주석 해제 

 sub vcl_pipe {

      set bereq.http.connection = "close";

     return (pipe);

 }

다른 부분은 그대로 두고 저 항목만 주석을 푼다. 

 

이제 저렇게 하고 운영 중인 체크박스와 그누보드를 아래와 같이 수정 작업하였다. 

* Checkbox 

 대체 :  REMOTE_ADDR -> HTTP_X_FORWARDED_FOR 

* GNUBoard

 - bbs/visit_insert_inc.php

 대체 :  REMOTE_ADDR -> HTTP_X_FORWARDED_FOR   

 - /common.php 

 대체 :  REMOTE_ADDR -> HTTP_X_FORWARDED_FOR   

 그런데 저렇게 수정하다보니 REMOTE_ADDR 변수가 들어가 있는 부분이 무척 많았다. 그리고 대다수 프로그램들이 REMOTE_ADDR을 쓰다보니 저렇게 수정하다보면 설치하는 프로그램 모두를 저렇게 바꾸어야 하는 수고가 든다. 


2안 : mod-rpaf 설치  (잘 안됨)

그래서 다른 방법을 찾아보니 누군가가 mod-rpaf를 쓰면 된다고 하였다. 그래서 아래 순서대로 진행을 해 보았다. 

* 다운 받기 (이게 원 사이트에 가면 잘 다운받을 수가 없어서 아래 구글에서 받았다.)

 - 파일 : https://code.google.com/p/nginxda/downloads/detail?name=mod_rpaf-0.6.tar.gz&can=2&q=

 - 위치 : /usr/local/src 

 

* 압축 풀기

 - tar xzvf mod_rpaf-0.6.tar.gz

 - cd mod_rpaf-0.6

* 설치 

 apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c

 

* httpd.conf 수정

 - 아래 추가 

LoadModule rpaf_module modules/mod_rpaf-2.0.so

# mod_rpaf Configuration

RPAFenable On

RPAFsethostname On

RPAFproxy_ips 127.0.0.1 10.0.0.1

RPAFheader X-Forwarded-For

 -> 127.0.0.1 -> 서버 ip로 변경  (10.0.0.1은 삭제)

 

저렇게 하고 httpd를 다시 실행시켰는데, 잘 동작하지 않았다. 첫번째 방법은 프로그램 설치할때만 작업을 해야 하는데, 이번 방법은 뭔가 적용이 잘 안되었다. 

 

3안 : 프로그램 추가 없이 변수 전달로 처리

이 방법을 쓰니 "HTTP_X_FORWARDED_FOR" 변수를 "REMOTE_ADDR" 변수로 연결하는데, 설치하는 프로그램에 관계없이 프로그램을 설치할때 httpd.conf만 잘 수정하면 된다.

 

* default.vcl 수정

 - 아래 항목을 추가

# Below is a commented-out copy of the default VCL logic.  If you

# redefine any of these subroutines, the built-in logic will be

# appended to your code.

 sub vcl_recv {

     if (req.restarts == 0) {

        if (req.http.x-forwarded-for) {

            set req.http.X-Forwarded-For =

                req.http.X-Forwarded-For + ", " + client.ip;

        } else {

            set req.http.X-Forwarded-For = client.ip;

        }

    }

  

 if (req.request != "GET" &&

       req.request != "HEAD" &&

       req.request != "PUT" &&

       req.request != "POST" &&

       req.request != "TRACE" &&

       req.request != "OPTIONS" &&

       req.request != "DELETE") {

#         /* Non-RFC2616 or CONNECT which is weird. */

         return (pipe);

     }

     if (req.request != "GET" && req.request != "HEAD") {

#         /* We only deal with GET and HEAD by default */

         return (pass);

     }

     if (req.http.Authorization || req.http.Cookie) {

#         /* Not cacheable by default */

         return (pass);

     }

   return (lookup);

  #   return (pipe);

 }

#

 sub vcl_pipe {

#     # Note that only the first request to the backend will have

#     # X-Forwarded-For set.  If you use X-Forwarded-For and want to

#     # have it set for all requests, make sure to have:

      set bereq.http.connection = "close";

#     # here.  It is not set by default as it might break some broken web

#     # applications, like IIS with NTLM authentication.

     return (pipe);

 }

 

 

* varnish 재실행

 - service varnish restart 

 

 

* varnish_client_ip.php 생성

/etc/httpd/conf.d/ 에 varnish_client_ip.php 를 생성한다. 내용은 아래와 같다.

<?php

if( isset( $_SERVER[ 'HTTP_X_FORWARDED_FOR' ] ) ) {

  $_SERVER[ 'REMOTE_ADDR' ] = $_SERVER[ 'HTTP_X_FORWARDED_FOR' ];

}

 

* httpd.conf

1. 추가 :  LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" varnish

 

2. 수정 (varnish도 varnishcombined도 

     ErrorLog logs/seven2015-error_log varnish

     Customlog logs/seven2015-access_log varnish

 

3. VirtualHost 수정

아래 코드를 넣는다. 

<Directory "/var/www/www.example.com">

    php_value auto_prepend_file "/etc/httpd/conf.d/varnish_client_ip.php"

</Directory>

 

4. 예제 

이제, 아래와 같은 샘플을 넣으면 된다. 

<VirtualHost 127.0.0.1:8080>

    ServerAdmin webmaster@dummy-host.example.com

    DocumentRoot /var/www/www.example.com

    ServerName www.example.com

    ErrorLog /var/log/httpd/example.com-error_log

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

    CustomLog /var/log/httpd/example.com_log varnish

    <Directory "/var/www/www.example.com">

       php_value auto_prepend_file "/etc/httpd/conf.d/varnish_client_ip.php"

    </Directory>

</VirtualHost>  

5. 아파치 재실행

/usr/sbin/apachectl restart

 

이 방법을 쓰면 127.0.0.1이 아니고 제대로 접속자 ip를 볼 수 있다. 그리고 설치하는 프로그램이나 코드도 변수 수정없이 할 수 있다. 

 

 

* 참조 

 - http://stackoverflow.com/questions/10024877/varnish-client-ip-not-logging-in-apache-logs

 - http://stackoverflow.com/questions/19311164/serverremote-addr-returns-127-0-0-1

 - http://old.drupion.com/resources/downloads/mod-rpaf

 - https://code.google.com/p/nginxda/downloads/detail?name=mod_rpaf-0.6.tar.gz&can=2&q=

 - http://www.techinfobest.com/getting-real-client-ip-through-varnish/

Comments

공유지기 2019.03.09 15:13
3안의 default.vcl 수정에서,

req.request 는 모두 req.method로 바꿔야 한다네요. varnish 4에서 바뀌었다고 합니다.


출처 : https://github.com/varnish/libvmod-vsthrottle/issues/9
공유지기 2019.03.09 15:17
그리고  sub vcl_recv 절 끝부분에 있는

  return (lookup);
  #  return (pipe);



  #  return (lookup);
    return (pipe);

로 바꿔줘야 합니다.
공유지기 2019.03.09 19:15
그리고 * varnish_client_ip.php 생성 이거도 안해도 됩니다.

고무줄 넓은생 노랑 1000 0159 7x1 500 1개입
칠성상회
당기는 1초 완성 리본장식 9cm 포장재료
칠성상회
앱코 COX CH60 사운드플러스 (화이트)
칠성상회
3M 810 매직테이프 50mm x 65M
바이플러스