SSL과 함께 HAproxy를 사용하고 X-Forwarded-For 헤더를 가져오고 SSL이 사용 중임을 PHP에 알리려면 어떻게해야합니까?


20

다음과 같은 설정이 있습니다.

(internet) ---> [  pfSense Box  ]    /-> [ Apache / PHP server ]
                [running HAproxy] --+--> [ Apache / PHP server ]
                                    +--> [ Apache / PHP server ]
                                     \-> [ Apache / PHP server ]

HTTP 요청의 경우 이것은 훌륭하게 작동 하며 요청은 Apache 서버에 잘 분배됩니다. SSL 요청의 경우 TCP로드 균형 조정을 사용하여 요청을 배포하는 HAproxy가 있었지만 HAproxy가 프록시로 작동하지 않아 X-Forwarded-ForHTTP 헤더를 추가하지 않았 으며 Apache / PHP 서버가 클라이언트의 실제 IP 주소.

따라서 stunnelHAproxy 앞에 추가하여 stunnel을 읽고 X-Forwarded-ForHTTP 헤더를 추가 할 수 있습니다 . 그러나 pfSense에 설치할 수있는 패키지에는이 헤더가 추가되지 않습니다 ... 또한 KeepAlive 요청을 사용할 수있는 능력이 없어 집니다. 실제로 유지하고 싶습니다. 그러나 그 아이디어를 죽인 가장 큰 문제는 stunnel이 HTTPS 요청을 일반 HTTP 요청으로 변환했기 때문에 PHP가 SSL이 활성화되어 SSL 사이트로 리디렉션하려고 시도한다는 것을 알지 못했습니다.

HAproxy를 사용하여 여러 SSL 서버에서로드 밸런싱을 수행하여 해당 서버가 클라이언트의 IP 주소 알고 SSL이 사용 중임을 알 수있는 방법은 무엇입니까? 그리고 가능하다면 pfSense 서버에서 어떻게 할 수 있습니까?

아니면이 모든 것을 버리고 nginx를 사용해야합니까?


3
다시 : stunnel 및 여기를X-Forwarded-For 참조 하십시오 .
Shane Madden

@Shane : 감사합니다. 그것이 내가 KeepAlive를 잃었다는 것을 정확히 읽은 곳입니다 :-)
Josh

2
탁월한 ASCII 다이어그램을 위해 +1 :-)
KyleFarris

@AlanHamlett, 귀하의 링크 는 404입니다.
luckydonald

@luckydonald 감사합니다, 여기에 업데이트 된 링크가 있습니다. haproxy 구성에 send-proxy 키워드를 추가하여 프록시 프로토콜을 사용할 수 있습니다. 여기 예제와 함께 블로그 포스트를 작성했습니다 : wakatime.com/blog/23-how-to-scale-ssl-with-haproxy-and-nginx
앨런 Hamlett

답변:


17

SSL을 지원하기 위해 haproxy 앞에서 nginx를 사용하여 모든 부하 분산 구성을 유지할 수 있습니다. 원하지 않으면 HTTP에 nginx를 사용할 필요조차 없습니다. Nginx는 X-Forwarded-For와 SSL이 사용 중임을 나타내는 사용자 정의 헤더 및 원하는 경우 클라이언트 인증서 정보를 모두 전달할 수 있습니다. 필요한 정보를 보내는 Nginx 설정 스 니펫 :

proxy_set_header SCHEME $scheme;      # http/https
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header CLIENT_CERT $ssl_client_raw_cert;

37

이 스레드는 종종 HAProxy + SSL과 관련하여 참조되므로 HAProxy는 1.5-dev12 이후 양쪽에서 기본 SSL을 지원합니다. 따라서 X-Forwarded-For, HTTP keep-alive 및 서버가 SSL을 통해 연결되었음을 알리는 헤더는 다음과 같이 간단합니다.

listen front
    bind :80
    bind :443 ssl crt /etc/haproxy/haproxy.pem
    mode http
    option http-server-close
    option forwardfor
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    server srv1 1.1.1.1:80 check ...
    ...

나는 당신이 뭔가 다른 것을 생각해 냈을 때 확신하지만 적어도 새로운 방문자는 이제 쉬운 해결책을 얻을 것입니다 :-)


이것은 일반적으로 좋은 정보 감사합니다입니다 ... 내 질문 HAproxy에 대해이었다 pfSense에서 실행 그래서 지금 내가 pfSense는 (아직) HAProxy의이 버전을 지원하지 않기 때문에, 여전히 HAproxy 앞에 nginx를 사용할 필요가
조쉬

죄송합니다. Josh, pfSense에 대해 구성 요소를 업데이트 할 수 있는지 여부를 알 수 없으며 패키지 설치에 대해 이야기 한 것이 사실이라고 생각합니다. 마지막으로 시도한 것은 약 5 년 전 이었으므로 모든 세부 사항을 기억하지 못합니다.
Willy Tarreau

1
나는 현재 haproxy 설정에 대해 많이 이해하지 못하지만 최신 버전에서는 acl을 추가 acl is-ssl dst_port 443하고 라인을 다시 작성해야했습니다. reqadd X-Forwarded-Proto:\ https if is-sslNginx는이 헤더를 상당히 잘 처리하는 것 같습니다
greg0ire

이것은 매력처럼 작동했습니다. nginx가 필요하지 않습니다.
Jay Taylor

1
@ greg0ire는 최신 haproxy에는 is_ssl이 없지만 ssl_fc가 없기 때문에
josch

12

이 질문을 발견 한 다른 사람을 위해 나는 Ochoto의 조언을 따르고 nginx를 사용했습니다. 내 pfSense 라우터 에서이 작업 수행하는 데 사용한 특정 단계는 다음과 같습니다 .

  1. pfsense 웹 인터페이스를 사용하여 시스템> 패키지 아래에 pfsense PfJailctl 패키지 와 "jail_template"패키지를 설치하여 pfsense 시스템에서 nginx를 컴파일하고 설치할 FreeBSD jail을 만들 수있었습니다.

  2. Services> Jails 에서 nginx 서버에 대한 감옥을 구성 하여 새 jail에 HAproxy를 실행 한 가상 IP 별명의 호스트 이름과 IP 주소를 지정했습니다. 감옥을 WAN 인터페이스에 묶었 다. 기본 감옥 템플릿을 사용하고 nullfs 대신 unionfs를 활성화했습니다.

  3. 교도소가 시작되면 나는 pfsense 상자에 들어가서 jls교도소 번호를 찾기 위해 달려 갔다 . 나는 jexec 1 sh감옥에 껍질을 갖기 위해 달려 갔다 . 거기에서 BSD 포트를 설정하고 다음을 사용하여 nginx를 설치했습니다.

    portsnap extract
    portsnap fetch update
    cd /usr/ports/www/nginx
    make install clean
    
  4. 그런 다음 포트 443에서 수신하도록 nginx를 구성하고 HTTP 헤더 내부의 실제 IP 및 SSL 상태를 포함하여 포트 80에서 HAproxy에 모든 요청을 전달합니다. 내 usr/local/etc/nginx/nginx.conf모습은 :

    worker_processes  1;
    
    events {
        worker_connections  2048;
    }
    
    http {
        upstream haproxy {
            server 209.59.186.35:80;
        }
    
        server {
            listen       443;
            server_name  my.host.name default_server;
            ssl                  on;
            ssl_certificate      my.crt;
            ssl_certificate_key  my.key;
            ssl_session_timeout  5m;
    
            ssl_protocols  SSLv3 TLSv1;
            ssl_ciphers  HIGH:!aNULL:!MD5;
            ssl_prefer_server_ciphers   on;
    
            location / {
                proxy_pass http://haproxy;
    
                proxy_set_header Host $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 https;
            }
        }
    
    }
    
  5. 그런 다음 X-Forwarded-ProtoHTTP 응용 프로그램을 수정하여 HTTP 헤더 를 감지했습니다 .

    function usingSSL()
    {
        return (
           (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' )
            || (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
                   && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https' ));
    }
    

최종 설정은 다음과 같습니다.

(internet) ---> [ -> nginx -> haproxy -]--> (pool of apache servers)
                [    (pfSense server)  ]

2
실제로 필요한 경우가 아니면 SSLv2를 비활성화해야합니다. gnu.org/software/gnutls/manual/html_node/… Nginx가 여전히 기본 설정에서 왜 그것을 지원하는지 모르겠습니다.
Ochoto

또한 1024 개의 작업자 연결로 최대 512 개의 동시 클라이언트를 지원할 수 있습니다.
Ochoto

@Ochoto :이 두 가지 팁에 감사드립니다! 저는 HAproxy를 처음 사용하지만 nignx에 대해서는 잘 모르고 있습니다.
Josh

7

1.5-dev-17 버전의 haproxy에 대한 내 구성 :

global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 notice
        #log loghost    local0 info
        maxconn 4096
        #chroot /usr/share/haproxy
        user haproxy
        group haproxy
        daemon
        #debug
        #quiet

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        option  http-server-close
        retries 3
        option redispatch
        fullconn 1000        
        maxconn 1000
        timeout queue 600s
        timeout connect 5s
        timeout client 600s
        timeout server 600s

frontend http-in
        bind *:80
        bind *:443 ssl crt /usr/local/etc/ssl/certs
        reqadd X-Forwarded-Proto:\ https if { ssl_fc }
        default_backend varnish-ha
        option forwardfor
backend varnish-ha
  server hafront1 10.1.69.1:6081  minconn 100 maxqueue 10000

ssl_fcACL을 사용합니다 . 이 option http-server-close부분은 매우 중요합니다.


감사! HAProxy v1.4를 실행 중이므로이를 수행 할 수 없다고 생각하지만 다른 사람들에게 도움이 될 수 있습니다.
Josh

예, 1.5가 곧 나옵니다.
greg0ire

5

HAProxy는 원시 TCP 모드를 사용하지 않고 SSL 백엔드에 도달 할 수 없지만을 잃을 수 X-Forwarded-For는 있지만 백엔드 전송을위한 수신 대기로 트래픽을 다시 암호화 할 수 있습니다. 미운.

필자는 Ochoto의 접근 방식이 더 좋다는 점을주의해야합니다. nginx는 완벽하게 작동하는로드 밸런서입니다. 당신이 그것을 사용한다면, 나는 그것을 모든 것에 사용한다고 말하고 싶습니다. 균형 잡힌 HTTPS 백엔드를로드하도록 들어오는 HTTPS를 프록시 처리합니다. 그러면 클라이언트 인증서가 필요하지 않은 한 SSL 정보를위한 사용자 지정 헤더가 필요하지 않습니다.


왜 HAproxy에 집착하고 있는지 잘 모르겠습니다. pfSense에 패키지가 있고 SOIS가 사용하기 때문이라고 생각합니다. 둘 다 큰 이유는 아닙니다. :-)
Josh

비표준 모듈 upstream_fair를 사용하지 않는 한 대상 백엔드가 이미 요청으로 바빠서 백엔드에서 대기열을 늘리는 경우를 고려하지 않고 간단한 라운드 로빈 (또는 클라이언트 IP 해시)을 수행하지 않으면 가능한로드 밸런서이기 때문에 nginx와 다릅니다. 다른 백엔드가 비어 있고 작업을 기다리고 있습니다. HAProxy는 또한 백엔드를 잘 모니터링하고 이에 대한 통계를 표시합니다.
Ochoto

단지 다음 중 하나에 해당 될 것입니다 경우) Nginx에 괜찮은 상태 추적 및 공정의 부하 분산 b)는 HAProxy는 하나의 유일한 희망 할 수있는 괜찮은 SSL 지원을 얻는다 얻는다
보르 Shahpasov을

방금 SSL에 대해 nginx-> haproxy-> nginx-> 백엔드를 사용하여 설정을 배포했습니다. 이는 여기에서 설명한 haproxy에서 HTTPS 지원이 부족하기 때문이지만 nginx는 http 상태 확인 스크립트를 지원하지 않기 때문입니다.
Geoffrey

2

작년 에 HAProxy의 모든 기능을 활용하고 pfSense와의 우수한 격리를 유지하는 방식으로 HAProxy를 pfSense와 통합 하는 솔루션을 구현했습니다 . 따라서 프로덕션 환경에 적합한 옵션입니다 . SSL은 HAProxy에서 종료됩니다 . ezjail 및 Ports Collection을 사용하여 pfSense 의 감옥 HAProxy를 설치했습니다 . 이렇게하면 두 구성 요소를 독립적으로 유지 관리하는 것이 매우 쉽습니다. 그리고 원하는 버전을 설치할 수 있습니다. 1.5-dev13으로 시작했습니다. 그 이후로 그것은 나를 위해 완벽하게 작동하고 있습니다. 나는 모든 것을 여기에 기록했다.

pfSense에 HAProxy 설치

BTW Willy, 훌륭한 제품에 감사드립니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.