haproxy + stunnel + tetap hidup?

10

Saya ingin meletakkan stunnel di depan haproxy 1.4 untuk menangani lalu lintas HTTPS. Saya juga perlu stunnel untuk menambahkan header X-Forwarded-For . Ini dapat dicapai dengan tambalan "stunnel-4.xx-xforwarded-for.diff" dari situs web haproxy.

Namun, uraian menyebutkan:

Perhatikan bahwa tambalan ini tidak berfungsi dengan ...

Pertanyaan saya adalah: Apa artinya ini bagi saya? Saya tidak yakin,

  1. jika ini adalah tentang tetap hidup di antara
    • klien dan stunnel
    • stunnel dan haproxy
    • atau haproxy dan server backend?
  2. apa artinya ini untuk kinerja: Jika saya memiliki 100 ikon pada halaman web, apakah browser harus menegosiasikan 100 koneksi SSL penuh, atau dapatkah itu menggunakan kembali koneksi SSL, hanya membuat koneksi TCP baru?
Chris Lercher
sumber

Jawaban:

12

Ini tentang HTTP keep-live, yang memungkinkan beberapa permintaan sumber daya datang melalui satu sesi TCP (dan, dengan SSL, satu sesi SSL tunggal). Ini sangat penting untuk kinerja situs SSL, karena tanpa tetap hidup, sebuah jabat tangan SSL akan diperlukan untuk setiap sumber daya yang diminta.

Jadi, kekhawatiran di sini adalah satu sesi tetap-hidup besar dari klien sampai ke server backend. Ini adalah hal yang penting untuk kinerja, dan dianggap sebagai hal biasa untuk server HTTP modern, tetapi tambalan ini mengatakan tidak mendukungnya. Mari kita lihat mengapa ..


Sesi tetap-hidup adalah lebih banyak permintaan satu demi satu - setelah server menyelesaikan responsnya terhadap satu permintaan, server tidak mengirim FINpaket untuk mengakhiri sesi TCP; klien hanya dapat mengirim kumpulan header lainnya.

Untuk memahami apa yang dilakukan tambalan itu, berikut adalah contoh percakapan tetap hidup:

Klien:

GET / HTTP/1.1
Connection: keep-alive
Host: domain.com
...

Server:

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: Apache
Content-Length: 34
.... (other headers)
<html><head>content!</head></html>

Di sinilah koneksi non-tetap-hidup akan berhenti. Tapi, tetap-hidup memungkinkan klien untuk melepaskan yang lain:

GET /images/some/image.on.the.page.jpg HTTP/1.1
Connection: keep-alive
Host: domain.com
...

Untuk ID klien dalam proksi, beberapa proksi terbalik dapat ditambahkan di X-Forwarded-Forheader di setiap permintaan klien. Itu memberitahu server hulu dari mana permintaan berasal (alih-alih setiap permintaan yang dimulai dari IP proxy terbalik), untuk kewarasan dalam pencatatan dan kebutuhan aplikasi lainnya.

The X-Forwarded-Forsundulan perlu disuntikkan ke masing-masing dan setiap permintaan sumber daya klien dikirim melalui koneksi tetap-hidup, sebagai header lengkap dikirim setiap kali; penanganan X-Forwarded-Forheader dan terjemahan menjadi IP "nyata" dilakukan atas dasar per-permintaan, bukan per-TCP-keep-live-session. Dan hei, mungkin ada beberapa perangkat lunak reverse proxy yang mengagumkan di luar sana yang menggunakan sesi keep-live tunggal untuk melayani permintaan dari banyak klien.

Di sinilah tambalan ini gagal.


Patch di situs itu mengawasi buffer sesi TCP untuk akhir set pertama HTTP header di stream, dan menyuntikkan header baru ke dalam stream setelah akhir set header pertama. Setelah ini selesai, ia mempertimbangkan X-Forwarded-Forpekerjaan yang dilakukan, dan berhenti memindai akhir set header baru. Metode ini tidak memiliki kesadaran tentang semua header masa depan yang datang melalui permintaan berikutnya.

Tidak bisa menyalahkan mereka; stunnel tidak benar-benar dibangun untuk menangani dan menerjemahkan isi dari alirannya.

Efek yang akan terjadi pada sistem Anda adalah bahwa permintaan pertama aliran tetap-hidup akan mendapatkan X-Forwarded-Forheader disuntikkan dengan benar, dan semua permintaan berikutnya akan berfungsi dengan baik - tetapi mereka tidak akan memiliki header.

Kecuali jika ada tambalan injeksi tajuk lain di luar sana yang dapat menangani beberapa permintaan klien per koneksi (atau men-tweak ini dengan bantuan teman-teman kami di Stack Overflow), Anda mungkin perlu melihat opsi lain untuk penghentian SSL Anda.

Shane Madden
sumber
1
Jawaban yang bagus, terima kasih. Mengingatkan saya, mengapa mengajukan pertanyaan di sini adalah ide yang bagus.
Chris Lercher
1
Untuk memungkinkan tetap memiliki header injeksi di stunnel, perlu untuk dapat berbicara hampir semua HTTP yang akan menjadi pekerjaan yang sangat besar. Yang mengatakan, Anda juga dapat menggunakan protokol PROXY HAproxy (yang membutuhkan patch untuk stunnel atau alternatif stud ) menyuntikkan header di HAproxy. Lihat dokumen untuk info lebih lanjut (dari cache Google, karena situs HAproxy tampaknya sebagian turun ATM)
Holger Just
3

Mirip dengan apa yang saya posting di utas lain, HAProxy mendukung SSL asli di kedua sisi sejak 1.5-dev12. Jadi memiliki X-Forwarded-For, HTTP keep-live serta header yang memberitahu server bahwa koneksi dilakukan melalui SSL adalah sesederhana berikut ini:

listen front
    bind :80
    bind :443 ssl crt /etc/haproxy/haproxy.pem
    mode http
    option http-server-close
    option forwardfor
    reqadd X-Forwarded-Proto:\ https if { is_ssl }
    server srv1 1.1.1.1:80 check ...
    ...

Ini jauh lebih mudah daripada menambal stunnel dan jauh lebih baik daripada harus tetap hidup.

Willy Tarreau
sumber
Anda mungkin ingin menggunakan ssl_fc alih-alih is_ssl
josch
2

Memperluas jawaban excelent dari Shane, Anda dapat menggunakan Nginx sebagai terminator SSL di depan HAproxy. Itu benar menangani tetap hidup antara klien dan nginx yang merupakan sisi paling latensi dan membuat koneksi baru ke backend untuk setiap permintaan klien, mengirimkan X-FORWARDED-FOR di masing-masing.

Ochoto
sumber
1
Namun, jika Anda memerlukan soket web maka nginx tidak akan berfungsi.
w00t
Plus, mendukung cache sesi ssl.
3molo