Невозможно заставить веб-сокеты работать через прокси-сервер Apache HTTPS (ошибка 302)

Я не могу заставить веб-сокеты работать на серверной части узла, используя прокси-сервер apache через HTTPS для подключения к экземпляру узла. Веб-узлы работают правильно, если не используется прокси (apache) http (s).

Мои настройки: у меня есть сервер apache с несколькими виртуальными хостами. У меня есть веб-страница HTTPS для моего сервера. com и HTTPS API с node / express / ws в поддомене api.myserver.com через прокси-сервер, который перенаправляет запросы к экземпляру node.js (несколько экземпляров на PM2), работающему на порту 3333.

Это мой apache виртуальный хост для поддомена:

<VirtualHost *:443>
    ServerName api.myserver.com
    ServerAdmin hello@myserver.com
    DocumentRoot /var/www/html/myserver/api
        Options -Indexes

    SSLEngine on                                                                
    SSLProtocol all -SSLv2                                                      
    SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM                

    SSLCertificateFile /etc/apache2/certs/STAR_myserver_co.crt
    SSLCertificateKeyFile /etc/apache2/certs/myserver_private_key.pem
    SSLCertificateChainFile /etc/apache2/certs/STAR_myserver_co.ca-bundle

    SSLProxyEngine On
    ProxyPreserveHost On
    ProxyRequests Off

    # This is for websocket requests
    ProxyPass /wss/ wss://localhost:3333/
    ProxyPassReverse /wss/ wss://localhost:3333/

    # This is for normal requests    
    ProxyPass / https://localhost:3333/
    ProxyPassReverse / https://localhost:3333/
</VirtualHost>

Это нормально работает для перенаправления соединений на серверную часть Express. Я установил mod_proxy, mod_proxy_http и mod_proxy_wstunnel.

Это серверная часть API node.js: сначала я инициализирую экспресс, сеансы и т. Д.

// express, session and mongodb session storage
var express = require('express')
var session = require('express-session')
var MongoStore = require('connect-mongo')(session)
var app = express()
// configure sessionStore and sessions, mongodb, etc...

// Certificates and credentials for HTTPS server
var fs = require('fs')
var privateKey  = fs.readFileSync(__dirname + '/certs/myserver_private_key.pem', 'utf8')
var certificate = fs.readFileSync(__dirname + '/certs/myserver_cert.pem', 'utf8')
var ca = fs.readFileSync(__dirname + '/certs/myserver_ca.pem', 'utf8')
var credentials = {key: privateKey, cert: certificate, ca: ca}

app.enable('trust proxy')
app.set("trust proxy", 1)

А затем я безопасно настраиваю сервер HTTPS, используя те же сертификаты, что и в APACHE :

// Setup HTTPS server
var https = require('https')
var server = https.createServer(credentials, app)
server.listen(appPort, 'localhost', function () {
    // Server up and running!
    var host = server.address().address
    var port = server.address().port
    console.log('myserver listening at https://%s:%s', host, port)
})

Наконец, я настраиваю соединения с веб-сокетами:

// setup Websockets
wss = new WebSocketServer({ server: server })
wss.on('connection', function connection(ws) {
    var cookies = cookie.parse(ws.upgradeReq.headers.cookie)
    var sid = cookieParser.signedCookie(cookies["connect.sid"], myserver_secret)
    // extract user credentials and data from cookie/sid,

    // get the session object
    sessionStore.get(sid, function (err, ss) {
        ...
    })
})

Затем мои клиенты просто пытаются безопасно подключиться к веб-сокетам (потому что, будучи приложением HTTPS, я не могу использовать небезопасное соединение ws: // с веб-сокетами):

window.WebSocket = window.WebSocket || window.MozWebSocket
webSocket = new WebSocket('wss://' + location.host + '/wss')

И то я всегда получаю ту же ошибку 302:

[Error] WebSocket connection to 'wss://api.myserver.com/wss' failed: Unexpected response code: 302

Если я тестирую на локальном сервере непосредственно экземпляр узла https: // localhost: 3333 / , он работает отлично, и веб-сокеты работают так, как должны.

Есть идеи, как решить эту проблему? Есть ли проблема с перенаправлениями ws, выполняемыми прокси-модулями Apache?

3
задан 15 November 2016 в 12:49
1 ответ

Már beállította a HTTPS-t az Apache-on, így biztonságos kapcsolatot kapott az ügyfél és a fizikai szerver között. Az Apache és a node.js alkalmazás közötti kapcsolatot a localhoston proxykolja, ezért az egyetlen lehetséges lehallgató fizikailag már a dobozán van. Azt mondta alkalmazásának, hogy bízza meg a proxyt a app.enable ('megbízható proxy'); app.set ("trust proxy", 1);

Miért állítaná be tehát a HTTPS-t is a node.js fájlhoz? Az egyik fő oka annak, hogy webalkalmazásainkat az apache / nginx / haproxy alkalmazással előtérbe helyezzük, a TLS-kiszállítás.

Amellett, hogy az X-Forwarded-For fejlécet a távoli kliens IP-jével kapjuk meg, lehetővé téve a proxyt. a bizalom is megkapja X-Forwarded-Proto , így az Express alkalmazás tudja, hogy a kapcsolat http vagy https volt-e. Ezért az Apache és a csomópont közötti https réteg kevéssé jár azon kívül, hogy bevezetné az általános költségeket az alkalmazásához.

Nem tudok segíteni a WebSocketek Apache-val való proxy-zásában. Akkor kezdtem el használni az Apache-t, amikor az még a httpd javításainak sorozata volt. Mielőtt abbahagytam volna a WebSocketeket, abbahagytam, és nem kockáztathatom meg, hogy leesjek a kocsiról. Túl sok fájdalmas emlék. Ha kíváncsi vagy, a következőképpen használom a haproxiát a WebSocketek továbbítására az egyik expressz alkalmazásomhoz:

mode      http
option    forwardfor
frontend http-in
bind :::80 v4v6
bind :::443 v4v6 ssl crt /etc/ssl/private
http-request  set-header X-Forwarded-Proto https if { ssl_fc }
http-request  set-header X-Forwarded-Port %[dst_port]
acl is_websocket hdr(Upgrade) -i WebSocket
acl is_websocket hdr_beg(Host) -i ws

redirect scheme https code 301 if !is_websocket !{ ssl_fc }
use_backend websocket_server if  is_websocket

backend websocket_server
timeout queue 5s
timeout server 86400s
timeout connect 86400s
server node_app 127.0.0.1:8080

backend ...others...
1
ответ дан 3 December 2019 в 07:24

Теги

Похожие вопросы