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

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

(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를 사용해야합니까?



답변

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;

답변

이 스레드는 종종 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 ...
    ...

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


답변

이 질문을 발견 한 다른 사람을 위해 나는 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)  ]

답변

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

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


답변

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

pfSense에 HAProxy 설치

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


답변