Mengkonfigurasi Apache2 ke proxy WebSocket?

40

Protokol WebSocket adalah perpanjangan dari protokol HTTP. Namun, modul proxy Apache2 tampaknya tidak tahu tentang hal itu, dan membuang header penting, mengubah panggilan menjadi panggilan HTTP standar.

Apakah ada cara untuk membuat Apache2 (1) memahami WebSocket atau (2) secara membabi buta meneruskan apa pun yang didapatnya?

Blixt
sumber

Jawaban:

23

Sekarang ada modul di Apache trunk bernama mod_proxy_wstunnel yang memungkinkan mod_proxy (ProxyPass / ProxyPassReverse) melewati lalu lintas WebSocket. Seseorang menulis posting blog tentang back-porting mod_proxy_wstunnel ke Apache 2.4 / 2.2 dan menyediakan tambalan untuk melakukannya.

Saya menemukan instruksi konkret untuk mengatur mod_proxy_wstunnel di Ubuntu (diuji dengan Ubuntu Server 11.10 dan Apache 2.2.20) dan mempostingnya di blog saya. Saya telah menyalinnya di bawah ini:

# Check apache version (should be 2.2.20 as of writing, if not adjust the next step)
dpkg -s apache2

# Checkout apache source
svn checkout http://svn.apache.org/repos/asf/httpd/httpd/tags/2.2.20/ httpd-2.2.20

# Get patch and apply it
wget http://cafarelli.fr/gentoo/apache-2.2.24-wstunnel.patch
cd httpd-2.2.20
patch -p1 < ../apache-2.2.24-wstunnel.patch

# Build Apache 
svn co http://svn.apache.org/repos/asf/apr/apr/branches/1.4.x srclib/apr
svn co http://svn.apache.org/repos/asf/apr/apr-util/branches/1.3.x srclib/apr-util
./buildconf
./configure --enable-proxy=shared --enable-proxy_wstunnel=shared
make

# Copy the module and recompiled mod_proxy (for new symbols) to the ubuntu apache installation and update the permissions to match the other modules
sudo cp modules/proxy/.libs/mod_proxy{_wstunnel,}.so /usr/lib/apache2/modules/
sudo chmod 644 /usr/lib/apache2/modules/mod_proxy{_wstunnel,}.so
echo -e "# Depends: proxy\nLoadModule proxy_wstunnel_module /usr/lib/apache2/modules/mod_proxy_wstunnel.so" | sudo tee -a /etc/apache2/mods-available/proxy_wstunnel.load

# Enable the module (also make any configuration changes you need)
sudo a2enmod proxy_wstunnel
sudo service apache2 restart
Andrew Moss
sumber
2
Ketika saya mengikuti panduan Anda, ada langkah yang tidak Anda miliki. Setelah melakukan apr checkout saya harus menjalankan ./buildconfiguntuk membuat file configure. Dan ada beberapa dependensi yang diminta untuk saya instal.
notbad.jpeg
apakah ini berhubungan dengan Glassfish 4 melalui wss: (SSL)
Archimedes Trajano
1
@ notbad.jpeg: Anda mungkin bermaksud ./buildconf (tidak ./buildconfig) :-)
Erik Forsberg
1
Hanya tanggapan saya ... ini diinstal dan dimuat di apache 2.2.22-1ubuntu1.10 dari Ubuntu 12.04, tetapi pada akhirnya tidak berhasil. Proxy menghapus header "Upgrade" (kode sumber mengatakan "RFC2616 13.5.1 mengatakan kita harus menghapus header ini"), yang merupakan header yang diharapkan server, bukan hanya satu hop, jadi itu tidak bekerja untuk saya, dan saya telah menggantinya dengan aturan DNAT iptables sebagai gantinya.
Peter
11

Tidak ada yang menunjukkan bahwa Apache httpd akan mendukung mereka dalam waktu dekat.

Jika Anda harus menjalankan soket web melalui apache, coba mod_pywebsocket . Saya sudah mencobanya, dan itu berhasil.

Berikut adalah beberapa alternatif yang saya sukai:

h0tw1r3
sumber
3

Silakan lihat di http://github.com/disconnect/apache-websocket

Modul apache-websocket adalah modul server Apache 2.x yang dapat digunakan untuk memproses permintaan menggunakan protokol WebSocket oleh server Apache 2.x.

Marat Denenberg
sumber
Saya melihat proyek github di atas. Itu tidak bertindak sebagai proxy. quoteThe module consists of a plugin architecture ...
guettli
1

Ini menambahkan untuk jawaban @Andrew Moss tentang cara mengkonfigurasi dengan benar VirtualHostuntuk bekerja dengan socket.io 1.0! Jangan ragu untuk melewatkan bagian tentang CentOS!


Jika Anda terjebak pada CentOS 6, berikut ini cara melakukannya:

  1. Unduh sumber backported untuk mod_proxy_wstunnelmodul di sini (baik mengkloning Intisari atau mengunduh file satu per satu)
  2. Instal semua yang diperlukan untuk membangun: yum install make gcc httpd-devel
  3. Menyiapkan lingkungan RPM Build (pada dasarnya pengguna tidakrivil dan beberapa direktori)
  4. Salin .cfile-ke dalam SOURCESsubfolder lingkungan dan .spec-file ke dalam SPECSsubfolder.
  5. Menjalankan rpmbuild -ba mod_proxy_wstunnel.spec
  6. Paket ini sekarang berada di SRPMSsubfolder
  7. Instal paket: rpm -i /path/to/package.rpm
  8. Keuntungan

Ini juga akan memuat modul secara otomatis di Apache, jadi Anda hanya perlu me-restart dengan service httpd restart.


Menyiapkan VirtualHostuntuk benar-benar melayani server Socket.io dan skrip klien (yang secara default tersedia di bawah http://your.server/socket.io/socket.io.js) sedikit lebih rumit di Apache 2.2, karena Bug dalam mod_proxymodul :

Diberi aturan penulisan ulang berikut:

RewriteRule    ^/ws(.*)$  ws://localhost:9000/ws  [P]

mod_rewrite memperlakukan ini suatu file tap sehingga log akses menunjukkan:

[26/Sep/2013:09:46:07 -0400] "GET /ws://localhost:9000/ws HTTP/1.1" 400 317

Jadi, Anda tidak dapat menggunakan ws-protocol dalam aturan penulisan ulang , karena itu akan secara internal berubah menjadi permintaan GET HTTP.

Namun ada solusinya:

<VirtualHost *:80>
        ServerName your.server

        # Proxy socket.io Websocket
        RewriteEngine On

        # socket.io 1.0+ starts all connections with an HTTP polling request
        RewriteCond %{QUERY_STRING} transport=polling       [NC]
        RewriteRule /(.*)           http://localhost:8081/$1 [P]

        ProxyRequests Off

        # Explicitly send the request for the client-script to HTTP:
        ProxyPass /socket.io/socket.io.js http://localhost:8081/socket.io/socket.io.js
        ProxyPassReverse /socket.io/socket.io.js http://localhost:8081/socket.io/socket.io.js

        # Anything else goes to the WebSocket protocol:
        ProxyPass /socket.io/ ws://localhost:8081/socket.io/
        ProxyPassReverse /socket.io/ ws://localhost:8081/socket.io/

        # Any additional stuff (the actual site) comes here
        ProxyPass / http://localhost:8081/
        ProxyPassReverse / http://localhost:8081/
</VirtualHost>

Ini memastikan bahwa semua yang dikirim untuk /socket.iopergi ke ws://-protocol, kecuali permintaan polling panjang (yang merupakan mekanisme mundur ketika WebSockets tidak tersedia) dan permintaan untuk perpustakaan klien.

Lukas Knuth
sumber