Проксировать WebSocket.
От: Oxotnik  
Дата: 07.03.13 19:00
Оценка:
Есть вебсервер lighttpd, который выдает относительно статическую вебстраницу. Этот lighttpd связан через FastCGI с модулем бизнес-логики на С++, т.е. вебстраницу по большому счету модуль С++ формирует.
На вебстранице есть джаваскрипт, который может устанавливать соединение по WebSocket-у. Есть сервер на вебсокетах, написанный на Qt (как часть модуля логики С++).
В принципе это все работает, но не устраивает тот факт, что Qt-шный вебсокет сервер торчит в сеть своим отдельным портом.
Необходимо сделать так, что бы клиент (браузер) соединялся с lighttpd по HTTPS и дальше при работе джаваскрипта проксировал WSS соединение на Qt-шный вебсокет сервер.
Вопросы:
1. Как проксировать вебсокет за вебсервер?
2. Как при этом должен работать Qt-шный вебсокет сервер, т.е. на каком порту и как сидеть — чего слушать? (что бы не торчал открытым портом в сеть).
3. Самое главное — необходима SSL авторизация одна по HTTPS, и что бы потом по вебсокету сертификаты не трогать.
4. Такое вообще возможно?
Т.е. нужен один канал связи HTTPS, который на вебсервере разветвлялся еще и на вебсокет.
PS: lighttpd в принципе можно заменить на что нибудь другое, главное, что бы была связь по FastCGI, т.к. вся логика вне вебсервера находится.
PPS: извините если коряво описал задачу, но с вебом, серверами и админством знаком мало.
Re: Проксировать WebSocket.
От: Anton Batenev Россия https://github.com/abbat
Дата: 10.03.13 11:48
Оценка:
Здравствуйте, Oxotnik, Вы писали:

O> 1. Как проксировать вебсокет за вебсервер?


Последние версии nginx научились поддерживать web-сокеты "из коробки".

O> 2. Как при этом должен работать Qt-шный вебсокет сервер, т.е. на каком порту и как сидеть — чего слушать? (что бы не торчал открытым портом в сеть).


В случае наличия проксирующего сервера бэкенд можно садить на любой порт (127.0.0.1:8080 например).
avalon/1.0.432
Re[2]: Проксировать WebSocket.
От: Аноним  
Дата: 10.03.13 15:00
Оценка:
Здравствуйте, Anton Batenev, Вы писали:

AB>Здравствуйте, Oxotnik, Вы писали:


O>> 1. Как проксировать вебсокет за вебсервер?


AB>Последние версии nginx научились поддерживать web-сокеты "из коробки".


O>> 2. Как при этом должен работать Qt-шный вебсокет сервер, т.е. на каком порту и как сидеть — чего слушать? (что бы не торчал открытым портом в сеть).


AB>В случае наличия проксирующего сервера бэкенд можно садить на любой порт (127.0.0.1:8080 например).


Извините за глупые вопросы, но осмелюсь спросить:
1. Может ли nginx проксировать HTTPS соединение и внутри него WSS соединение в WS соединение?
2. Если не сможет, то будет ли по одному и тому же сертификату авторизовываться клиент по HTTPS и по WSS ?
Re[3]: Проксировать WebSocket.
От: Anton Batenev Россия https://github.com/abbat
Дата: 11.03.13 13:04
Оценка:
Здравствуйте, Аноним, Вы писали:

> Извините за глупые вопросы, но осмелюсь спросить:

> 1. Может ли nginx проксировать HTTPS соединение и внутри него WSS соединение в WS соединение?
> 2. Если не сможет, то будет ли по одному и тому же сертификату авторизовываться клиент по HTTPS и по WSS ?

К сожалению, я не пробовал еще проксировать через nginx, однако, в теории, этому не должно быть никаких препятствий — SSL это всего лишь транспорт, а под ним может быть как HTTP так и WebSocket. Разные location в конфигурации nginx могу проксировать соединения на разные бэкенды (что подтверждается документацией).
avalon/1.0.432
Re[4]: Проксировать WebSocket.
От: Oxotnik  
Дата: 12.03.13 05:16
Оценка:
В общем все получилось.
Кому интересно вот конфиг Nginx-а:


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen          443 ssl;   # порт https
        server_name     localhost; # ваш сайт

        ssl_certificate        /usr/local/nginx/sert/cert.pem;
        ssl_certificate_key    /usr/local/nginx/sert/cert.key; 
        if ( $scheme = "http" ) {
          rewrite ^/(.*)$    https://$host/$1 permanent;
        }

        location / {
            root   html;
            index  index.html index.htm;
        }

        location = /websocket {                               #собственно само проксирование вебсокета
        proxy_pass http://127.0.0.1:8086;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
......

}

вебсокет на клиенте создается вот так:

websocket = new WebSocket( "wss://hostName/websocket" );
Re[5]: Проксировать WebSocket.
От: Anton Batenev Россия https://github.com/abbat
Дата: 12.03.13 16:52
Оценка:
Здравствуйте, Oxotnik, Вы писали:

Только вот небольшая рекомендация:

http {
    ssl_certificate           /usr/local/nginx/sert/cert.pem;
    ssl_certificate_key       /usr/local/nginx/sert/cert.key;
    ssl_dhparam               /usr/local/nginx/sert/dh4096.pem;
    ssl_session_cache         shared:SSL:10m;
    ssl_session_timeout       5m;
    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers               RC4:HIGH:!aNULL:!MD5:!CAMELLIA;
    ssl_prefer_server_ciphers on;
    ......
}


Файлик dh4096.pem создается командой типа:

$ openssl dhparam -5 -out /usr/local/nginx/sert/dh4096.pem 4096


После чего рекомендуется проверить настройки HTTPS на ssllabs.com.

Если в системе установлен openssl < 1.x (проверяется командой openssl version), то я бы собрал nginx c последней версией openssl. Строка конфигурации для сборки выглядит как-то так:

./configure \
    --prefix=/etc/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --with-pcre-jit \
    --with-debug \
    --with-file-aio \
    --with-http_addition_module \
    --with-http_dav_module \
    --with-http_geoip_module \
    --with-http_gzip_static_module \
    --with-http_image_filter_module \
    --with-http_realip_module \
    --with-http_secure_link_module \
    --with-http_stub_status_module \
    --with-http_ssl_module \
    --with-http_sub_module \
    --with-http_xslt_module \
    --with-ipv6 \
    --with-sha1=openssl-1.0.1e/crypto/sha \
    --with-md5=openssl-1.0.1e/crypto/md5 \
    --with-openssl=openssl-1.0.1e \
    --error-log-path=/var/log/nginx/error.log \
    --http-client-body-temp-path=/var/lib/nginx/body \
    --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
    --http-log-path=/var/log/nginx/access.log \
    --http-proxy-temp-path=/var/lib/nginx/proxy \
    --http-scgi-temp-path=/var/lib/nginx/scgi \
    --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
    --lock-path=/var/lock/nginx.lock \
    --pid-path=/var/run/nginx.pid


Профит будет заключаться в поддержке TLSv1.1 и TLSv1.2 плюс на свой страх и риск можно будет убрать из ssl_ciphers опцию "RC4" (современные браузеры не подвержены BEAST attack).
avalon/1.0.432
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.