web-dev-qa-db-ja.com

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リクエストの場合、これは機能しますgreat。リクエストは私のApacheサーバーにうまく分散されます。 SSLリクエストの場合、TCPロードバランシングを使用してリクエストを分散するHAproxyがありましたが、HAproxyがプロキシとして機能しなかったため、X-Forwarded-For HTTPを追加していませんでした。ヘッダー、およびApache/PHP=サーバーはクライアントの実際のIPアドレスを知りませんでした。

そのため、HAproxyの前にstunnelを追加し、stunnelがX-Forwarded-For HTTPヘッダーを追加する可能性があることを読みました。ただし、pfSenseにインストールできるパッケージでは、このヘッダーは追加されません...また、 これにより、KeepAlive要求を使用する機能が明らかに停止します 、これは本当に保持したいです。しかし、その考えを打ち消した最大の問題は、stunnelがHTTPSリクエストをプレーンHTTPリクエストに変換したことでした。そのため、PHPは、SSLが有効であることを知らず、SSLサイトにリダイレクトしようとしました。

HAproxyを使用して複数のSSLサーバー間で負荷を分散し、それらのサーバーがクライアントのIPアドレスの両方にSSLが使用されていることを認識させるにはどうすればよいですか? ?できれば、pfSenseサーバーでそれを行うにはどうすればよいですか?

それとも私はこれをすべて落としてnginxを使うべきですか?

20
Josh

すべてを落とす必要はありません。負荷分散構成をすべて維持したまま、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;
17
Ochoto

記録のためだけに、このスレッドはHAProxy + SSLに関してしばしば言及されるため、1.5-dev12以降、HAProxyは両側でネイティブSSLをサポートしています。したがって、X-Forwarded-For、HTTPキープアライブ、および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 ...
    ...

あなたが何か別のことを思いついたときまでに、少なくとも新しいビジターは簡単な解決策を今すぐ得るでしょう:-)

37
Willy Tarreau

この質問を見つけた人のために、私はOchotoのアドバイスに従い、nginxを使用しました。これが私のpfSenseルーターでこれを機能させるために使用した特定の手順です:

  1. Pfsense Webインターフェイスを使用して、pfsense PfJailctlパッケージ と「jail_template」パッケージをSystem> Packagesの下にインストールしたので、FreeBSD jailを作成できますnginxをコンパイルしてpfsenseシステムにインストールします。

  2. Services> Jailsでnginxサーバーのjailを設定し、HAproxyを実行していた仮想IPエイリアスの同じホスト名とIPアドレスを新しいjailに与えました。刑務所をWANインターフェースにバインドしました。デフォルトの刑務所テンプレートを使用し、nullfsではなくunionfsを有効にしました。

  3. 刑務所が開始されたら、私はpfsenseボックスにSSHでログインし、jlsを実行して刑務所の番号を見つけました。その後、jexec 1 sh刑務所内にシェルを取得します。そこからBSDポートをセットアップし、nginxをインストールしました。

    portsnap extract
    portsnap fetch update
    cd /usr/ports/www/nginx
    make install clean
    
  4. 次に、ポート443でリッスンするようにnginxを構成し、実際のIPおよびHTTPヘッダー内の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. 次に、PHPアプリケーションを変更してX-Forwarded-Proto 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)  ]
12
Josh

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_fc ACL。 option http-server-close部分は非常に重要です。

7
greg0ire

HAProxyは、raw TCP=モードを使用してX-Forwarded-Forを失う)なしでSSLバックエンドをヒットすることはできませんが、バックエンド転送のリスニングトンネルを使用してトラフィックを再暗号化できる可能性があります。けれども。

Ochotoのアプローチの方が好きですが、注意点があります。nginxは完全に機能するロードバランサーです。あなたがそれを使用しているなら、私はそれをすべてに使用すると言うでしょう。着信HTTPSをプロキシして、バランスのとれたHTTPSバックエンドをロードします。これにより、SSL情報用のカスタムヘッダーは必要ありません(クライアント証明書が必要でない限り)。

5
Shane Madden

私は昨年、HAProxyのすべての機能を利用し、pfSenseで適切な分離を維持する方法でHAProxyをpfSenseと統合するにソリューションを実装しました。 実稼働環境の実行可能なオプションになるように。 SSLはHAProxyで終了します。刑務所にHAProxyをインストールしましたezSailとPorts Collectionを使用してpfSenseで。そうすれば、両方のコンポーネントを個別に保守するのが非常に簡単になります。そして、あなたはあなたが望むどんなバージョンでもインストールするかもしれません。 1.5-dev13から始めました。それ以来、私にとっては完全に機能しています。ここですべてを文書化しました。

pfSenseへのHAProxyのインストール

ところで、ウィリー、このような優れた製品をたくさんありがとう。

2
Dinesh Sharma