Назад | Перейти на главную страницу

Обратный прокси-сервер Nginx WebSocket сохраняет возврат 200 вместо 101

Я сейчас пытаюсь hack.chat на моем личном сервере работает.

Короче говоря, он состоит из двух серверов. Первый - это простой httpd-сервер, обслуживающий javascript и CSS. Вторая, система чата, - это сервер node.js, к которому javascript подключается с помощью websocket. А вот и проблемы.

Я хочу, чтобы все это использовало порт 80 с другим доменным именем на одном IP, используя отдельный серверный блок в Nginx.

Я последовал за документ веб-сокета Nginx но это не работает. Когда веб-сокет пытается подключиться, он всегда получает код возврата 200, тогда как, если я хорошо понял, он должен получить 101 (протокол переключения).

Моя версия Nginx - 1.8.0, а мой сервер работает на gentoo с Linux 4.0.5.

Вот дамп соответствующих файлов конфигурации nginx:

nginx.conf:

user nginx nginx;
worker_processes 1;

error_log /var/log/nginx/error_log info;

events {
    worker_connections 1024;
    use epoll;
}

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

    log_format main
        '$remote_addr - $remote_user [$time_local] '
        '"$request" $status $bytes_sent '
        '"$http_referer" "$http_user_agent" '
        '"$gzip_ratio"';

    client_header_timeout 10m;
    client_body_timeout 10m;
    send_timeout 10m;

    connection_pool_size 256;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 2k;
    request_pool_size 4k;

    gzip on;
    gzip_min_length 1100;
    gzip_buffers 4 8k;
    gzip_types text/plain;

    output_buffers 1 32k;
    postpone_output 1460;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 75 20;

    ignore_invalid_headers on;

    include /etc/nginx/sites-enabled/*;
}

сайты с поддержкой / чат:

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

server{
    listen 0.0.0.0:80;
    server_name chat.axellink.fr;

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

    access_log /var/log/nginx/chat_access;
    error_log /var/log/nginx/chat_error debug;
}

Когда я смотрю на access_log, он показывает ответ 200, и в error_log нет ошибок. К сожалению, сервер node.js не дает мне журнала (или я не знаю, как его просмотреть).

Заранее благодарим вас за любой ответ.

РЕДАКТИРОВАТЬ

Спасибо mc0e, мне удалось получить ответ от сервера hack.chat 101. Сравнивая то, что на самом деле происходит между nginx и node.js, с тем, что происходит при прямом подключении, я увидел, что при прямом обновлении заголовка: websocket установлен, но nginx делает не. Поэтому я исправил мои сайты с поддержкой / чат на:

server{
    listen 0.0.0.0:80;
    server_name chat.axellink.fr;

    location / {
        proxy_pass http://127.0.0.1:6060;
        proxy_http_version 1.1;
        proxy_set_header Upgrade "websocket";
        proxy_set_header Connection "Upgrade";
    }

    access_log /var/log/nginx/chat_access;
    error_log /var/log/nginx/chat_error debug;
}

Я также удалил блок карты, поскольку он использовался для закрытия заголовка соединения вместо обновления.

Однако все еще не работает. hack.chat возвращает 101 с Connection: Upgrade и Upgrade: websocket, но каким-то образом nginx возвращает 101 с Connection: keep-alive (как то, что я вижу в firefox): /

РЕДАКТИРОВАТЬ

Сделал ngrep для связи nginx, он отправляет пакет, который hack.chat возвращает ему, а firefox жалуется на перекрестное происхождение. Я постараюсь избегать перекрестного происхождения.

ПОСЛЕДНИЙ РЕДАКТИРОВАНИЕ

Хорошо, теперь, когда я дома, я сделал тест, и он отлично сработал. Довольно сюрприз, что моя последняя проблема была из-за моего рабочего прокси, будем надеяться, что это кеш, иначе все было бы бесполезно.

Вот последний из моих советов, который избегает перекрестного происхождения:

server{
        listen 0.0.0.0:80;
        server_name chat.axellink.fr;

        location / {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_set_header X-NginX-Proxy true;
                proxy_pass http://127.0.0.1:8081;
        }

        location /chat/ {
                proxy_pass http://127.0.0.1:6060;
                proxy_http_version 1.1;
                proxy_set_header Upgrade "websocket";
                proxy_set_header Connection "Upgrade";
        }

        access_log /var/log/nginx/chat_access;
        error_log /var/log/nginx/chat_error debug;
}

Судя по тому, как я читал док-станцию ​​nginx websocket, когда ваш прокси-сервер nginx видит заголовки Upgrade, он передает их в hack.chat. Затем hack.chat должен ответить 101-м ответом.

Прежде всего, вы хотите иметь возможность отлаживать фактические транзакции HTTP и hack.chat, чтобы знать, в вашем клиентском приложении, на веб-сервере или в сообщениях hack.chat, проблема. Это также позволит вам получить точный HTTP-ответ, который, по вашему мнению, в настоящее время вы не знаете, как получить. Если проблема связана с сервером, возможно, вы все еще хотите получить более качественные журналы того, что пошло не так.

Вы можете захватить http-трафик с помощью tcpdump или ngrep. Я бы пошел на ngrep. Это даст вам вывод в вашем терминале.

ngrep 'Host: chat.axellink.fr' port 80

Вероятно, вы захотите запустить это на своем веб-сервере, хотя, если у вас есть среда рабочего стола, которая может запускать ngrep, вы можете запустить его там. Если вы запустите его на сервере, вы также можете зафиксировать взаимодействие между nginx и вашим чат-сервером.

ngrep '.' port 6060

Выходных данных терминала часто бывает достаточно, чтобы увидеть, что вам нужно, но вы также можете использовать флаг '-O' для ngrep для записи данных в файл дампа pcap, как tcpdump делает с '-w'. Затем вы можете вернуть этот файл на свой рабочий стол, чтобы просмотреть его с помощью графического клиента, такого как wirehark.

Возможно, вы сможете определить проблему, но если нет, запишите различные взаимодействия и добавьте их в свой вопрос.

Есть ли проблема с javascript, запрашивающим связь hack.chat в другом домене, отличном от того, с которого обслуживается javascript? Это может быть актуально: https://stackoverflow.com/questions/20093070/unable-to-create-cross-domain-websocket-connection-to-node-js-socket-io-server