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アドレス。

そのため、stunnelstunnelがX-Forwarded-ForHTTPヘッダーを追加できることを読んで、HAproxyの前に追加しました。ただし、pfSenseにインストールできるパッケージはこのヘッダーを追加しません...また、これはKeepAliveリクエストを使用する機能を強制的に無効にします。しかし、そのアイデアを殺した最大の問題は、stunnelがHTTPSリクエストをプレーンなHTTPリクエストに変換したため、PHPがSSLが有効になっていることを知らず、SSLサイトにリダイレクトしようとしたことです。

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

または、これをすべて削除してnginxを使用する必要がありますか?


3
Re:stunnelおよびX-Forwarded-Forを参照してください
シェーンマッデン

@シェーン:ありがとう。それはまさに私がKeepAliveを失うことを読んだ場所です:
ジョシュ

2
優れたASCII作図のために+1。:-)
カイルファリス

@AlanHamlettは、あなたのリンクは 404です
luckydonald

@luckydonaldありがとう、ここに更新されたリンクがあります。haproxy構成にsend-proxyキーワードを追加することにより、プロキシプロトコルを使用できます。私はここに例を使用してブログ投稿を書きました:wakatime.com/blog/23-how-to-scale-ssl-with-haproxy-and-nginx
アランハムレット

回答:


17

すべてをドロップする必要はありません。haproxyの前でnginxを使用してSSLをサポートし、すべての負荷分散設定を維持できます。必要ない場合は、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キープアライブ、および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の使用する必要がある
ジョシュ

ジョシュ、申し訳ありませんが、pfSenseについては、そのコンポーネントを更新できるかどうかを知るのに十分な知識がありません。前回試したのは5年前だったので、詳細はすべて覚えていません。
ウィリータロー

1
私は今のところhaproxyの設定についてあまり理解していませんが、最新バージョンではacl:を追加しacl is-ssl dst_port 443、行を書き換える必要がありましたreqadd X-Forwarded-Proto:\ https if is-ssl
。NGINXは

これは魅力的でした。nginxは必要ありません。
ジェイテイラー

1
@ greg0ireことの最新haproxyで何is_sslしかしssl_fcではなく、存在しないため
josch

12

この質問を見つけた他の人のために、私はOchotoのアドバイスに従い、nginxを使用しました。pfSenseルーターでこれを機能せるために使用した具体的な手順は次のとおりです。

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

  2. Services> Jailsでnginxサーバーのjailを設定し、HAproxyを実行していた仮想IPエイリアスと同じホスト名とIPアドレスを新しいjailに与えました。刑務所をWANインターフェイスにバインドしました。デフォルトのjailテンプレートを使用し、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を構成し、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ヘッダーを検出するようにPHPアプリケーションを変更しました。

    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がまだサポートしている理由がわかりません。
オチョト

また、1024のワーカー接続を使用すると、最大512の同時クライアントをサポートできることに注意してください。
オチョト

@Ochoto:両方のヒントをありがとう!私は... HAproxyに新しいが、nignxでさえあまりよく知っている
ジョシュ・

7

haproxyの1.5-dev-17バージョンの私の構成:

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を実行しているので、これができるとは思いませんが、他の人には役立つかもしれません。
ジョシュ

はい、1.5はすぐにリリースされるはずです。
greg0ire

5

HAProxyは、生のTCPモードを使用せずにSSLバックエンドをヒットすることはできず、を失いX-Forwarded-Forますが、バックエンド通過のためのリスニングトンネルでトラフィックを再暗号化する可能性があります。しかし、Uい。

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


なぜHAproxyにしがみついているのかわかりません。pfSenseにはパッケージがあり、SOISがそれを使用しているからだと思います。どちらも大きな理由ではありません。:
ジョシュ

非標準モジュールのupstream_fairを使用しない限り、nginxは有能なロードバランサーを回避します他の無料のバックエンドがあり、ジョブを待っています。また、HAProxyはバックエンドを適切に監視し、それらに関する統計を表示します。
オチョト

のみ、次のいずれかに該当aはなる場合)nginxのは、まともな状態の追跡と公正なロードバランシングb)はHAProxyは、一つは、唯一の希望することができますまともなSSLのサポートを取得取得
Yavor Shahpasovを

SSLのnginx-> haproxy-> nginx-> backendを使用してセットアップを展開しました。これは、ここで説明したようにhaproxyでHTTPSがサポートされていないためです。
ジェフリー

2

昨年、HAProxyのすべての機能を活用し、pfSenseとの良好な分離を維持する方法でHAProxyをpfSense統合するソリューションを実装しました。そのため、実稼働環境で実行可能なオプションです。SSLはHAProxyで終了します。ezjailとPorts Collectionを使用して、pfSenseの jail内にHAProxyをインストールしました。そうすれば、両方のコンポーネントを独立して保守するのは非常に簡単です。また、必要なバージョンをインストールできます。1.5-dev13から始めました。それ以来、私にとっては完璧に機能しています。ここにすべてを文書化しました。

pfSenseにHAProxyをインストールする

ところで、ウィリー、このような素晴らしい製品をありがとう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.