Haproxy에서 acl을 log에 기록하기

2019-09-08

목차

Reverse Proxy 로 활용중인 haproxy 를 운영하면서 한가지 불편한 점이 있었는데, 설정을 통해서 정의한 custom variable(ACL) 을 log에 기록하는 방법을 알기가 어려웠다는 점이었다. cfg 파일에 acl 로깅을 활성화 하는 방법에 대해서 알아보았다.

Haproxy 의 ACL 설정

reverse proxy 로 활용하면서 header 의 값을 판단하거나, source 의 IP 대역을 확인하거나, 또는 기타 특정 backend 연결을 위해서 acl을 정의한다.

    # ACL "vpc-network" 선언
    acl vpc-network src 10.10.1.0/16

    # ACL "allow_url" 선언
    # whitelist url 목록 파일 지정
    acl accept_url url_beg -i -f /etc/haproxy/accept_url.list

    # ACL "found-header" 선언
    acl found-header req.hdr_val(my_custom_header) -m found

조건에 따른 분기 처리를 위한 변수 획득

예를들어 header 의 특정 값을 변수로 획득하여 조건에 따라 다른 백엔드 서버로 요청을 처리를 하고 싶다고 가정해보자. 이 값을 내부 변수로 획득하기 위해서는 몇가지 설정을 통해서 처리할 있다.

apache 에서는 다음과 같이 처리할 수 있다.

#apache

    # my_custom_header 라는 값이 존재하는지 확인하고 이 값을 
    # CUSTOM_HEADER 라는 변수에 할당한다.
    SetEnvIf my_custom_header (.+) CUSTOM_HEADER=$1

    # 로그에 CUSTOM_HEADER 라는 변수값을 기록한다.
    LogFormat "%{CUSTOM_HEADER}e %{Host}i %D [%{%FT%T%z}t] \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

nginx 에서는 다음과 같이 처리할 수 있다.

#nginx 

    # http_my_custom_header 라는 값을 찾아 custom_header 라는 변수에 할당한다
    # 값이 없다면 공백으로 지정
    # 값지 존재한다면 해당값을 변수에 저장한다.
    map $http_my_custom_header $custom_header {
        "-"     "";
        default $http_my_custom_header;
    }

    # custom_header 라는 변수값을 로그에 기록한다.
    log_format main         '$custom_header $forward_ip $http_host $request_time [$time_iso8601] ';

haproxy document 를 확인하면 애석하게도 acl 을 곧바로 로그에 남기는 방법이 존재하지 않는다. apache 나 nginx 보다는 조금 불편한 방법을 거쳐야 한다. 다음과 같이 해보자.

#haproxy

    # request header 에 들어 있는 my_custom_header 라는 변수값을 찾아 이를
    # req.my_custom_variable 이라는 값으로 지정한다.
    http-request set-var(req.my_custom_variable) req.hdr(my_custom_header)
    
    # 특정 acl 에 따라서 string 값으로 지정할 수 있다.
    http-request set-var(req.my_custom_variable) str("other_value") if my_acl
    
    # 길이 제한 10으로 이 값을 capture 하자.
    http-request capture var(req.my_custom_variable) len 10
    
    # 위에서 캡처한 값을 로그에 기록한다.
    # 캡쳐한 값이 여러개라면 index 번호는 0, 1, 2.. 순으로 늘어난다.
    log-format "%[capture.req.hdr(0)]\ %Tt [%trl]\ \"%HM\ %HU\ %HV\"\ %ST\ %B\"

이렇게 하면 원하는 값을 acl 에 따라서 지정할 수 있고, 이를 로그에서 확인할 수 있다. 나의 경우에는 내부 내트워크 에서 접속인지 아닌지 로그에서 바로 확인하는 용도로 사용한다. 테스트는 haproxy 1.9 버전에서 정상적으로 동작하는 것을 확인했다.

요약

haproxy 에서 acl 값을 log 에 바로 남기는 방법을 알아보았다. apache 처럼 바로 acl 을 변수값으로 확인해서 기록하는 방법이 있으면 편하겠지만. 조금 불편한 방법을 거쳐야 한다. 또한 capture 한 값을 index 값처럼 0, 1, 2.. 로 확인하려니 설정이 지저분해지는 단점이 있다.

참고


comments powered by Disqus