NGINX untuk membalikkan soket web proxy DAN mengaktifkan SSL (wss: //)?


136

Saya sangat tersesat dan baru membangun NGINX sendiri tetapi saya ingin dapat mengaktifkan soket web yang aman tanpa memiliki lapisan tambahan.

Saya tidak ingin mengaktifkan SSL di server websocket itu sendiri tetapi saya ingin menggunakan NGINX untuk menambahkan lapisan SSL ke semuanya.

Setiap halaman web di luar sana mengatakan saya tidak bisa melakukannya, tetapi saya tahu saya bisa! Terima kasih kepada siapa pun (saya sendiri) yang bisa menunjukkan caranya!

Jawaban:


185

Sekadar diketahui bahwa nginx sekarang telah mendukung Websockets pada rilis 1.3.13. Contoh penggunaan:

location /websocket/ {

    proxy_pass ​http://backend_host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 86400;

}

Anda juga dapat memeriksa nginx changelog dan dokumentasi proxy WebSocket .


Ini memiliki masalah batas waktu yang sama seperti yang dinyatakan di atas;)
3Eden

5
@ 3rdEden: Untuk masalah batas waktu, proxy_read_timeoutberfungsi, saya mengedit jawabannya.
Steve Kehlet

2
Di mana saya harus meletakkan konfigurasi ini dan apa itu backend_host?
Aysennoussi

3
@Sekai: locationArahan diletakkan di dalam serveratau locationarahan lain (lihat dokumen lokasi ). backend_hostadalah upstream(lihat dokumen hulu ) - satu atau sekelompok server yang akan Anda proksi.
Radko Dinev

1
Bagaimana dengan masalah batas waktu ini? Apakah kita harus benar-benar mengaturnya ke jumlah yang sangat besar untuk menghindarinya? Apakah sekarang tidak ada solusi yang lebih elegan?
Mohammed Noureldin

54

Jangan takut, karena sekelompok Programer Ops yang gagah berani telah menyelesaikan situasi dengan merek baru nginx_tcp_proxy_module

Ditulis pada Agustus 2012, jadi jika Anda berasal dari masa depan, Anda harus mengerjakan pekerjaan rumah.

Prasyarat

Asumsikan Anda menggunakan CentOS:

  • Hapus instance NGINX saat ini (sarankan menggunakan server dev untuk ini)
  • Jika memungkinkan, simpan file konfigurasi NGINX lama Anda sehingga Anda dapat menggunakannya kembali (termasuk init.d/nginxskrip Anda )
  • yum install pcre pcre-devel openssl openssl-devel dan lib lainnya yang diperlukan untuk membangun NGINX
  • Dapatkan nginx_tcp_proxy_module dari GitHub di sini https://github.com/yaoweibin/nginx_tcp_proxy_module dan ingat folder tempat Anda meletakkannya (pastikan tidak zip).

Bangun NGINX Baru Anda

Sekali lagi, asumsikan CentOS:

  • cd /usr/local/
  • wget 'http://nginx.org/download/nginx-1.2.1.tar.gz'
  • tar -xzvf nginx-1.2.1.tar.gz
  • cd nginx-1.2.1/
  • patch -p1 < /path/to/nginx_tcp_proxy_module/tcp.patch
  • ./configure --add-module=/path/to/nginx_tcp_proxy_module --with-http_ssl_module (Anda dapat menambahkan lebih banyak modul jika Anda membutuhkannya)
  • make
  • make install

Pilihan:

  • sudo /sbin/chkconfig nginx on

Setel Nginx

Ingatlah untuk menyalin file konfigurasi lama Anda terlebih dahulu jika Anda ingin menggunakannya kembali.

Penting: Anda perlu membuat tcp {}arahan di level tertinggi di conf Anda. Pastikan itu tidak ada dalam http {}arahan Anda .

Contoh konfigurasi di bawah ini menunjukkan server websocket hulu tunggal, dan dua proxy untuk SSL dan Non-SSL.

tcp {
    upstream websockets {
        ## webbit websocket server in background
        server 127.0.0.1:5501;
        
        ## server 127.0.0.1:5502; ## add another server if you like!

        check interval=3000 rise=2 fall=5 timeout=1000;
    }   

    server {
        server_name _;
        listen 7070;

        timeout 43200000;
        websocket_connect_timeout 43200000;
        proxy_connect_timeout 43200000;

        so_keepalive on;
        tcp_nodelay on;

        websocket_pass websockets;
        websocket_buffer 1k;
    }

    server {
        server_name _;
        listen 7080;

        ssl on;
        ssl_certificate      /path/to/cert.pem;
        ssl_certificate_key  /path/to/key.key;

        timeout 43200000;
        websocket_connect_timeout 43200000;
        proxy_connect_timeout 43200000;

        so_keepalive on;
        tcp_nodelay on;

        websocket_pass websockets;
        websocket_buffer 1k;
    }
}

5
Ini cukup membantu, tapi saya masih mendapatkan timeout 60secs. Saya berhasil memperbaikinya dengan menetapkan yang berikut: batas waktu 43200000; websocket_connect_timeout 43200000; websocket_read_timeout 43200000; websocket_send_timeout 43200000; proxy_connect_timeout 43200000; proxy_read_timeout 43200000; proxy_send_timeout 43200000;
jbg

2
Terima kasih telah berbagi itu! Saya kemudian menyadari bahwa saya memiliki masalah yang sama, dan secara kebetulan yaoweibin sendiri juga menjawab masalah GitHub saya dengan tautan ke komentar Anda pada Edisi # 28. Dunia kecil ...
crockpotveggies

1
Saya ingin menyajikan soket web dari port http yang sama dan hanya setelah browser diautentikasi. Sepertinya ini tidak bisa menangani soket web pada port yang sama. Bagaimana orang menangani ini?
uroc

1
Diperlukan beberapa modifikasi perangkat lunak untuk mendeteksi protokol yang masuk. Karena soket web sebenarnya dimulai sebagai jabat tangan HTTP (tingkat perangkat lunak yang lebih tinggi dari TCP) Anda harus mengubah aplikasi Anda untuk menangani lalu lintas TCP dan HTTP. Saya belum bisa merekomendasikan cara untuk melakukan ini.
crockpotveggies

2
Jika orang lain dari 2018 datang ke sini, arahan ini tidak berfungsi lagi. Pergi ke nginx.org/en/docs/http/websocket.html untuk instruksi terbaru atau lihat jawaban Harlan T Wood di bawah ini.
GaryO

37

Ini bekerja untuk saya:

location / {
    # redirect all HTTP traffic to localhost:8080
    proxy_pass http://localhost:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

- dipinjam dari: https://github.com/nicokaiser/nginx-websocket-proxy/blob/df67cd92f71bfcb513b343beaa89cb33ab09fb05/simple-wss.conf


3
Saya kesulitan membuat soket web TeamCity bekerja di belakang proxy terbalik saya. Anda # WebSocket supportsnipped melakukannya untuk saya. Saya sebelumnya mencoba untuk meneruskan port 400, tetapi bekerja lebih dari 443. Pembaca masa depan FYI :)
Mario Tacke

Sudahkah Anda menemukan solusinya? Karena saya harus juga menghadapi masalah yang sama stackoverflow.com/q/53411060/7713811
Nɪsʜᴀɴᴛʜ

Saya suka jawaban ini yang terbaik, karena banyak orang (seperti Anda) menggunakan / untuk kedua websockets dan HTTP2 biasa.
mikemaccana

@Setiap orang apa yang disebut Javascript?
Andrew Simpson

17

untuk .net core 2.0 Nginx dengan SSL

location / {
    # redirect all HTTP traffic to localhost:8080
    proxy_pass http://localhost:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
}

Ini berhasil untuk saya


apa kode c #. Saat ini saya menggunakan Windows / iis _server = WebSocketServer baru ("wss: //0.0.0.0: 8200 / MessageRelayer") {Certificate = new X509Certificate2 (PfxFileName, SslPassword), RestartAfterListenError = true};
Andrew Simpson

Saya menggunakan SignalR
Altair CA

Ini adalah satu-satunya solusi yang berhasil untuk saya. Terima kasih!
m-ketan

8

Bagi saya, itu turun ke proxy_passpengaturan lokasi. Saya perlu mengubah menggunakan protokol HTTPS, dan mengatur sertifikat SSL yang valid di sisi server node hal. Dengan begitu ketika saya memperkenalkan server simpul eksternal, saya hanya perlu mengubah IP dan yang lainnya tetap konfigurasi yang sama.

Saya harap ini membantu seseorang di sepanjang jalan ... Saya menatap masalah sepanjang waktu ... huh ...

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
upstream nodeserver {
        server 127.0.0.1:8080;
}
server {
        listen 443 default_server ssl http2;
        listen [::]:443 default_server ssl http2 ipv6only=on;
        server_name mysite.com;
        ssl_certificate ssl/site.crt;
        ssl_certificate_key ssl/site.key;
        location /websocket { #replace /websocket with the path required by your application
                proxy_pass https://nodeserver;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $connection_upgrade;
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_intercept_errors on;
                proxy_redirect off;
                proxy_cache_bypass $http_upgrade;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-NginX-Proxy true;
                proxy_ssl_session_reuse off;
            }
}

Saya mencoba localtion /horizon, tetapi tidak berhasil. Hanya localtion /atau location /websockifyberfungsi. Tidak tahu mengapa ...
njuguoyi

6

Artikel singkat dan bagus dari Pankaj Malhotra membahas bagaimana melakukan ini dengan NGINX dan tersedia di sini .

Konfigurasi dasar NGINX direproduksi di bawah ini:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream appserver {
    server 192.168.100.10:9222; # appserver_ip:ws_port
}

server {
    listen 8888; // client_wss_port

    ssl on;
    ssl_certificate /path/to/crt;
    ssl_certificate_key /path/to/key;


    location / {
        proxy_pass http://appserver;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

1
Apakah versi modern NGINX juga mengatasi masalah batas waktu?
crockpotveggies

2

Menggunakan nginx / 1.14.0

saya punya websocket-server yang berjalan di port 8097 dan pengguna terhubung dari ke wss di port 8098, nginx hanya mendekripsi konten dan meneruskannya ke server websocket

Jadi saya punya file konfigurasi ini (dalam kasus saya /etc/nginx/conf.d/default.conf)

server {
    listen   8098;
        ssl on;
        ssl_certificate      /etc/ssl/certs/combined.pem;
        ssl_certificate_key  /root/domain.key;
    location / {

        proxy_pass http://hostname:8097;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;

    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.