ฉันจะใช้ HAproxy กับ SSL และรับส่วนหัว X-Forwarded- สำหรับและบอก PHP ว่าใช้งาน SSL ได้อย่างไร


20

ฉันมีการตั้งค่าต่อไปนี้:

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

สำหรับคำขอ HTTP นี้ใช้งานได้ดีการร้องขอถูกแจกจ่ายไปยังเซิร์ฟเวอร์ Apache ของฉันไม่เป็นไร สำหรับการร้องขอ SSL ฉันมี HAproxy กระจายการร้องขอโดยใช้ TCP load balancing และทำงานได้เนื่องจาก HAproxy ไม่ได้ทำหน้าที่เป็นพร็อกซีมันไม่ได้เพิ่มX-Forwarded-Forส่วนหัว HTTP และเซิร์ฟเวอร์ Apache / PHP ไม่รู้จักลูกค้า ที่อยู่ IP จริง

ดังนั้นฉันเพิ่มstunnelด้านหน้า HAproxy การอ่านว่า stunnel สามารถเพิ่มX-Forwarded-Forส่วนหัว HTTP ได้ อย่างไรก็ตามแพคเกจที่ฉันสามารถติดตั้งลงใน pfSense ไม่ได้เพิ่มหัวข้อนี้ ... เช่นกันสิ่งนี้ทำให้ฉันไม่สามารถใช้คำขอ KeepAliveซึ่งฉันต้องการเก็บไว้จริงๆ แต่ปัญหาที่ใหญ่ที่สุดที่ทำลายความคิดนั้นคือ stunnel แปลงคำขอ HTTPS เป็นคำขอ HTTP ธรรมดาดังนั้น PHP ไม่ทราบว่า SSL ถูกเปิดใช้งานและพยายามเปลี่ยนเส้นทางไปยังไซต์ SSL

ฉันจะใช้ HAproxy เพื่อโหลดบาลานซ์ในเซิร์ฟเวอร์ SSL จำนวนหนึ่งได้อย่างไรทำให้เซิร์ฟเวอร์เหล่านั้นรู้ทั้งที่อยู่ IP ของลูกค้าและรู้ว่ามีการใช้งาน SSL อยู่หรือไม่ และถ้าเป็นไปได้ฉันจะทำบนเซิร์ฟเวอร์ pfSense ได้อย่างไร

หรือฉันควรจะวางทั้งหมดนี้และเพียงแค่ใช้ nginx?


3
Re: stunnel และX-Forwarded-Forดูที่นี่
เชนแมดเดน

@Shane: ขอบคุณ นั่นคือสิ่งที่ฉันอ่านว่าฉันแพ้ KeepAlive :-)
จอช

2
+1 สำหรับการสร้างไดอะแกรม ASCII ที่ยอดเยี่ยม :-)
KyleFarris

@AlanHamlett ลิงก์ของคุณคือ 404
luckydonald

@luckydonald ขอบคุณนี่คือลิงค์ที่อัพเดท คุณสามารถใช้ Proxy Protocol ได้โดยเพิ่มคีย์เวิร์ด send-proxy เข้ากับการกำหนดค่า haproxy ของคุณ ฉันเขียนโพสต์บล็อกพร้อมด้วยตัวอย่างที่นี่: wakatime.com/blog/23-how-to-scale-ssl-with-haproxy-and-nginx
Alan Hamlett

คำตอบ:


17

คุณไม่จำเป็นต้องทิ้งทุกอย่างคุณสามารถใช้ nginx ต่อหน้า haproxy เพื่อรองรับ SSL ทำให้การกำหนดค่าการทำโหลดบาลานซ์ทั้งหมดของคุณ คุณไม่จำเป็นต้องใช้ nginx สำหรับ HTTP หากคุณไม่ต้องการ 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 รองรับ SSL ดั้งเดิมทั้งสองด้านตั้งแต่ 1.5-dev12 ดังนั้นการมี 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ดังนั้นตอนนี้ฉันต้องใช้ nginx ต่อหน้า HAproxy นิ่งเพราะ pfSense ไม่รองรับ HAProxy รุ่นนี้ (ยัง)
Josh

ขอโทษด้วย 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" ภายใต้ระบบ> แพ็คเกจดังนั้นฉันสามารถสร้างคุก FreeBSD ที่จะรวบรวมและติดตั้ง nginx บนระบบ pfsense

  2. ฉันกำหนดค่าคุกสำหรับเซิร์ฟเวอร์ nginx ของฉันภายใต้บริการ> คุกทำให้คุกใหม่มีชื่อโฮสต์และที่อยู่ IP เดียวกันของชื่อแทน IP เสมือนซึ่งฉันใช้ HAproxy ฉันผูกคุกเข้ากับอินเตอร์เฟส WAN ฉันใช้แม่แบบคุกเริ่มต้นและเปิดใช้งาน unionfs มากกว่า nullfs

  3. เมื่อเริ่มต้นคุกฉัน SSHed ในกล่อง pfsense และวิ่งjlsไปหาหมายเลขคุก จากนั้นฉันก็วิ่งjexec 1 shไปเอากระสุนเข้าไปในคุก จากนั้นฉันตั้งค่าพอร์ต BSD และติดตั้ง nginx โดยใช้:

    portsnap extract
    portsnap fetch update
    cd /usr/ports/www/nginx
    make install clean
    
  4. ฉันกำหนดค่า nginx ให้ฟังพอร์ต 443 และส่งคำร้องขอทั้งหมดไปที่ HAproxy บนพอร์ต 80 รวมถึง IP จริงและสถานะ SSL ในส่วนหัว HTTP 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-ProtoHTTP Header:

    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

การกำหนดค่าของฉันสำหรับ 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 ดังนั้นฉันไม่คิดว่าฉันจะทำได้ แต่อาจช่วยคนอื่นได้
Josh

ใช่และ 1.5 ควรจะออกในไม่ช้า
greg0ire

5

HAProxy ไม่สามารถเข้าถึง SSL แบ็กเอนด์โดยไม่ใช้โหมด TCP ดิบการสูญเสียX-Forwarded-Forแต่คุณอาจเข้ารหัสการรับส่งข้อมูลอีกครั้งด้วยการฟัง stunnel สำหรับการส่งผ่านแบ็กเอนด์ แต่น่าเกลียด

ฉันชอบวิธีการของ Ochoto ที่ดีกว่าโดยมีข้อแม้: nginx เป็นตัวปรับสมดุลโหลดที่มีความสามารถอย่างสมบูรณ์ ถ้าคุณใช้มันฉันจะบอกว่าใช้มันกับทุกสิ่ง พร็อกซี HTTPS ขาเข้าของคุณเพื่อโหลดแบ็กเอนด์ HTTPS ที่สมดุล - และด้วยวิธีนี้ไม่จำเป็นต้องมีส่วนหัวที่กำหนดเองสำหรับข้อมูล SSL (เว้นแต่คุณต้องการใบรับรองไคลเอ็นต์)


ฉันไม่แน่ใจว่าทำไมฉันถึงยึดมั่นกับ HAproxy ฉันคิดว่าเป็นเพราะ pfSense มีแพ็คเกจสำหรับมันและ SOIS ใช้มัน ไม่มีเหตุผลอย่างใดอย่างหนึ่ง :-)
Josh

ฉันพูดนอกเรื่องจาก nginx beeing load balancer ที่มีความสามารถเว้นแต่คุณจะใช้โมดูลที่ไม่ได้มาตรฐาน upstream_fair มันจะทำการปัดแบบรอบง่ายๆ (หรือแฮช IP ของไคลเอ็นต์) โดยไม่คำนึงถึงว่าแบ็กเอนด์ปลายทางนั้นยุ่งกับคำขอแล้ว มีแบ็กเอนด์อื่น ๆ ฟรีและรองาน HAProxy ยังตรวจสอบแบ็กเอนด์และแสดงสถิติเกี่ยวกับพวกมันด้วย
Ochoto

หากสิ่งใดสิ่งหนึ่งต่อไปนี้กลายเป็นจริงก) Nginx ได้รับการติดตามสถานะที่เหมาะสมและการปรับสมดุลภาระงานอย่างเป็นธรรม b) HAProxy ได้รับการสนับสนุน SSL ที่เหมาะสมเราหวังได้เพียงอย่างเดียว
Yavor Shahpasov

ฉันเพิ่งปรับใช้การตั้งค่าโดยใช้ nginx -> haproxy -> nginx -> แบ็กเอนด์สำหรับ SSL นี่เป็นเพราะขาดการสนับสนุน HTTPS ใน haproxy ตามที่อธิบายไว้ที่นี่ แต่เพราะ nginx ไม่สนับสนุนสคริปต์ตรวจสอบสถานะ http
Geoffrey

2

ฉันใช้โซลูชันเมื่อปีที่แล้วเพื่อรวม HAProxy เข้ากับ pfSenseในลักษณะที่ใช้ประโยชน์จากคุณสมบัติทั้งหมดของ HAProxy และคงการแยกที่ดีกับ pfSense เพื่อที่จะเป็นตัวเลือกที่ทำงานได้สำหรับสภาพแวดล้อมการผลิต SSL ถูกยกเลิกใน HAProxy ผมติดตั้ง HAProxy ภายในคุกใน pfSense ใช้ ezjail และพอร์ตการเก็บ ด้วยวิธีนี้มันง่ายมากที่จะรักษาส่วนประกอบทั้งสองอย่างอิสระ และคุณอาจติดตั้งเวอร์ชันที่คุณต้องการ ฉันเริ่มต้นด้วย 1.5-dev13 และตั้งแต่นั้นมันก็ทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน ฉันมีเอกสารทั้งหมดที่นี่

การติดตั้ง HAProxy บน pfSense

BTW Willy ขอบคุณมากสำหรับผลิตภัณฑ์ที่ยอดเยี่ยม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.