Làm cách nào tôi có thể sử dụng HAproxy với SSL và nhận các tiêu đề X-Forwarded-For VÀ cho PHP biết rằng SSL đang được sử dụng?


20

Tôi có các thiết lập sau:

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

Đối với các yêu cầu HTTP, điều này hoạt động rất tốt , các yêu cầu được phân phối cho các máy chủ Apache của tôi rất tốt. Đối với các yêu cầu SSL, tôi đã có HAproxy phân phối các yêu cầu bằng cách sử dụng cân bằng tải TCP và nó đã hoạt động tuy nhiên vì HAproxy không hoạt động như một proxy, nên nó không thêm X-Forwarded-Fortiêu đề HTTP và các máy chủ Apache / PHP không biết máy khách địa chỉ IP thật.

Vì vậy, tôi đã thêm stunnelvào trước HAproxy, đọc rằng stunnel có thể thêm X-Forwarded-Fortiêu đề HTTP. Tuy nhiên, gói mà tôi có thể cài đặt vào pfSense không thêm tiêu đề này ... ngoài ra, điều này rõ ràng sẽ giết chết khả năng sử dụng các yêu cầu KeepAlive của tôi , thứ mà tôi thực sự muốn giữ. Nhưng vấn đề lớn nhất đã giết chết ý tưởng đó là stunnel đã chuyển đổi các yêu cầu HTTPS thành các yêu cầu HTTP đơn giản, vì vậy PHP không biết rằng SSL đã được bật và cố gắng chuyển hướng đến trang SSL.

Làm cách nào tôi có thể sử dụng HAproxy để tải số dư trên một số máy chủ SSL, cho phép các máy chủ đó biết cả địa chỉ IP của khách hàng biết rằng SSL đang được sử dụng? Và nếu có thể, làm thế nào tôi có thể làm điều đó trên máy chủ pfSense của mình?

Hay tôi nên bỏ tất cả những thứ này và chỉ sử dụng nginx?


3
Re: stunnel và X-Forwarded-For, xem ở đây .
Shane Madden

@Shane: Cảm ơn. Đó chính xác là nơi tôi đọc rằng tôi mất KeepAlive :-)
Josh

2
+1 cho sơ đồ ASCII xuất sắc. :-)
KyleFarris

@Alan Hamlett, liên kết của bạn là 404.
luckydonald

@luckydonald cảm ơn, đây là một liên kết cập nhật. Bạn có thể sử dụng Giao thức Proxy bằng cách thêm từ khóa gửi proxy vào cấu hình haproxy của mình. Tôi đã viết một bài đăng blog với các ví dụ ở đây: wakatime.com/blog/23-how-to-scale-ssl-with-haproxy-and-nginx
Alan Hamlett

Câu trả lời:


17

Bạn không cần phải bỏ tất cả, bạn chỉ có thể sử dụng nginx trước haproxy để hỗ trợ SSL, giữ tất cả cấu hình cân bằng tải của bạn. Bạn thậm chí không cần sử dụng nginx cho HTTP nếu bạn không muốn. Nginx có thể vượt qua cả X-Forwarded-For và tiêu đề tùy chỉnh cho biết SSL đang được sử dụng (và thông tin chứng chỉ ứng dụng khách nếu bạn muốn). Đoạn mã Nginx gửi thông tin bắt buộc:

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

Chỉ dành cho bản ghi, vì chủ đề này thường được đề cập liên quan đến HAProxy + SSL, HAProxy không hỗ trợ SSL gốc ở cả hai bên kể từ 1,5-dev12. Vì vậy, việc có X-Forwarded-For, HTTP vẫn tồn tại cũng như một tiêu đề cho máy chủ biết rằng kết nối được tạo qua SSL cũng đơn giản như sau:

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 ...
    ...

Tôi chắc chắn rằng vào thời điểm bạn nghĩ ra thứ gì đó khác biệt, nhưng ít nhất khách truy cập mới sẽ có được giải pháp dễ dàng ngay bây giờ :-)


Cảm ơn, đây là thông tin chung tốt ... câu hỏi của tôi là về HAproxy chạy trên pfSense vì vậy bây giờ tôi cần sử dụng nginx trước HAproxy, vì pfSense không hỗ trợ phiên bản HAProxy này (chưa)
Josh

Xin lỗi Josh, tôi không biết đủ về pfSense để biết liệu bạn có thể cập nhật các thành phần trên đó hay không, và vì bạn đang nói về việc cài đặt một gói, tôi tin rằng đó là trường hợp. Lần trước tôi đã thử nó là khoảng 5 năm trước vì vậy tôi không nhớ tất cả các chi tiết.
Willy Tarreau

1
Bây giờ tôi không hiểu nhiều về cấu hình haproxy, nhưng với phiên bản mới nhất, tôi đã phải thêm một acl: acl is-ssl dst_port 443và viết lại một dòng: reqadd X-Forwarded-Proto:\ https if is-sslNginx dường như xử lý khá tốt tiêu đề này
greg0ire

Điều này làm việc như một nét duyên dáng. Không cần nginx.
Jay Taylor

1
@ greg0ire đó là vì với haproxy mới nhất không có is_ssl mà thay vào đó là
ssl_fc

12

Đối với bất kỳ ai khác tìm thấy câu hỏi này, tôi đã làm theo lời khuyên của Ochoto và sử dụng nginx. Đây là các bước cụ thể tôi đã sử dụng để làm cho công việc này trên bộ định tuyến pfSense của mình :

  1. Sử dụng giao diện web pfsense, tôi đã cài đặt gói PfJailctl của pfsensegói "jail_template" trong System> Gói để tôi có thể tạo một nhà tù FreeBSD để biên dịch và cài đặt nginx trên hệ thống pfsense.

  2. Tôi đã cấu hình một nhà tù cho máy chủ nginx của mình trong Dịch vụ> Nhà tù , cung cấp cho nhà tù mới cùng tên máy chủ và địa chỉ IP của bí danh IP ảo mà tôi có HAproxy đang chạy. Tôi ràng buộc nhà tù với giao diện WAN. Tôi đã sử dụng mẫu tù mặc định và kích hoạt unionfs chứ không phải nullfs.

  3. Khi nhà tù đã được bắt đầu, tôi đã SSH vào hộp pfsense và chạy jlsđi tìm số của nhà tù. Sau đó tôi chạy jexec 1 shđi lấy vỏ trong nhà tù. Từ đó tôi thiết lập các cổng BSD và cài đặt nginx bằng cách sử dụng:

    portsnap extract
    portsnap fetch update
    cd /usr/ports/www/nginx
    make install clean
    
  4. Sau đó, tôi đã định cấu hình nginx để nghe trên cổng 443 và chuyển tất cả các yêu cầu tới HAproxy trên cổng 80, bao gồm cả IP thực và trạng thái SSL bên trong các tiêu đề HTTP. Hình của tôi usr/local/etc/nginx/nginx.confnhư:

    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. Sau đó tôi đã sửa đổi ứng dụng PHP của mình để phát hiện X-Forwarded-ProtoTiêu đề HTTP:

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

Vì vậy, thiết lập cuối cùng là:

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

2
Bạn nên vô hiệu hóa SSLv2 trừ khi bạn thực sự cần nó. gnu.org/software/gnutls/manual/html_node/ nam Tôi không biết tại sao Nginx vẫn hỗ trợ nó trong cấu hình mặc định của nó.
Ochoto

Cũng nhận ra rằng với 1024 kết nối worker, bạn sẽ hỗ trợ tối đa 512 máy khách đồng thời.
Ochoto

@Ochoto: Cảm ơn cả hai lời khuyên đó! Tôi chưa quen với HAproxy nhưng thậm chí còn ít quen thuộc hơn với nignx ...
Josh

7

Cấu hình của tôi cho phiên bản 1,5-dev-17 của 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

Nó sử dụng ssl_fcACL. Xin lưu ý rằng option http-server-closephần này rất quan trọng.


Cảm ơn! Tôi đang chạy HAProxy v1.4 vì vậy tôi không nghĩ mình có thể làm điều này, nhưng nó có thể giúp người khác.
Josh

Có, và 1.5 sẽ sớm ra mắt.
greg0ire

5

HAProxy không thể đạt được phụ trợ SSL mà không sử dụng chế độ TCP thô, mất X-Forwarded-For, nhưng, bạn có khả năng mã hóa lại lưu lượng truy cập bằng một stunnel nghe cho quá trình phụ trợ. Xấu, mặc dù.

Tôi thích cách tiếp cận của Ochoto hơn, với một lời cảnh báo: nginx là một bộ cân bằng tải có khả năng hoàn hảo; nếu bạn đang sử dụng nó, tôi sẽ nói sử dụng nó cho mọi thứ. Proxy proxy HTTPS sắp tới của bạn để tải các phụ trợ HTTPS cân bằng - và theo cách đó, không cần tiêu đề tùy chỉnh cho thông tin SSL (trừ khi bạn không cần chứng chỉ ứng dụng khách).


Tôi không chắc tại sao tôi lại bám lấy HAproxy. Tôi nghĩ đó là vì pfSense có gói dành cho nó và SOIS sử dụng nó. Không phải là một lý do tuyệt vời. :-)
Josh

Tôi lạc đề từ nginx đang tạo ra một bộ cân bằng tải có khả năng, trừ khi bạn sử dụng mô-đun không chuẩn upstream_fair, nó thực hiện một vòng tròn đơn giản (hoặc băm ip khách hàng) mà không tính đến nếu phụ trợ đích đã bận rộn với các yêu cầu và do đó tăng hàng đợi trong phụ trợ đó khi Có những phụ trợ khác miễn phí và chờ đợi một công việc. HAProxy cũng giám sát độc đáo các phụ trợ và hiển thị số liệu thống kê về chúng.
Ochoto

Nếu chỉ một trong những điều sau đây trở thành sự thật a) Nginx được theo dõi trạng thái tốt và cân bằng tải công bằng b) HAProxy được hỗ trợ SSL đàng hoàng Một người chỉ có thể hy vọng
Yavor Shahpasov

Tôi vừa triển khai một thiết lập bằng nginx -> haproxy -> nginx -> phụ trợ cho SSL, điều này là do thiếu hỗ trợ HTTPS trong haproxy như đã thảo luận ở đây, nhưng cũng vì nginx không hỗ trợ các tập lệnh kiểm tra sức khỏe http.
Geoffrey

2

Tôi đã thực hiện một giải pháp vào năm ngoái để tích hợp HAProxy với pfSense theo cách nó khai thác tất cả các tính năng của HAProxy và duy trì sự cách ly tốt với pfSense. Vì vậy, nó là một lựa chọn khả thi cho môi trường sản xuất . SSL bị chấm dứt trên HAProxy . Tôi đã cài đặt HAProxy bên trong nhà tù trong pfSense bằng ezjail và Cổng Collection . Bằng cách đó, rất dễ dàng để duy trì cả hai thành phần độc lập. Và bạn có thể cài đặt bất cứ phiên bản nào bạn muốn. Tôi bắt đầu với 1,5-dev13. Và kể từ đó nó hoạt động hoàn hảo cho tôi. Tôi đã ghi lại toàn bộ điều ở đây.

Cài đặt HAProxy trên pfSense

BTW Willy, cảm ơn rất nhiều vì một sản phẩm tuyệt vời như vậy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.