Собственный домен (first-party)
Предоставляйте виджет, подключение чата и офлайн-форму через поддомен своего сайта: требования, настройка, шаблоны nginx, Apache и Caddy, устранение неполадок.
При собственном домене чат работает через поддомен вашего сайта, например chat.your-domain.com. Ваш сервер принимает запросы виджета и передаёт их reactive.chat как обратный прокси. Эта страница предназначена для того, кто управляет этим сервером.
Что даёт собственный домен
Через ваш поддомен проходят:
- файлы виджета (
loader.jsи загружаемое после него ядро); - подключение чата (WebSocket), включая вложения файлов;
- офлайн-форма, которая используется, когда подключиться к чату не удаётся.
В результате:
- Нет запросов к сторонним доменам. По этим маршрутам браузеры посетителей общаются только с вашим поддоменом, а не с доменом reactive.chat.
- Блокировщики рекламы. Списки фильтров, блокирующие по доменному имени, больше не распознают чат по домену reactive.chat.
- Один адрес для Content Security Policy. В
script-srcиconnect-srcуказывается ваш поддомен вместо адресов reactive.chat. Вconnect-srcон нужен дважды: сwss://для подключения чата и сhttps://для офлайн-формы, загрузок и резервного канала HTTP (когда прокси блокирует WebSocket). - Доходит настоящий адрес посетителя. Ваш прокси сообщает нам адрес посетителя в специальном заголовке, защищённом секретным ключом. Защита от злоупотреблений (ограничение частоты и блокировки) тогда ведёт счёт по посетителям, а не по прокси, и в разговоре отображается адрес посетителя.
Чего это не означает
- Это не самостоятельный хостинг. Ваш сервер лишь пересылает запросы. Разговоры, вложения и настройки по-прежнему обрабатываются и хранятся в reactive.chat, как и без собственного домена.
- Это ничего не говорит о согласии. Нужно ли согласие посетителей и на что именно — отдельный вопрос. Собственный домен не меняет того, кто обрабатывает данные. Формулировки для политики конфиденциальности находятся в текстовом блоке для политики конфиденциальности.
- Ваш сервер видит трафик. TLS-соединение посетителя заканчивается на вашем прокси. Сообщения и вложения там ненадолго расшифровываются, а затем снова шифруются и передаются нам. Не записывайте тела запросов в журналы прокси.
Требования
- Собственный сервер или обратный прокси, доступный из интернета по HTTPS на порту 443 и имеющий право открывать исходящие HTTPS-соединения. Есть шаблоны для nginx (с модулем ssl), Apache 2.4.47 и новее и Caddy 2.
- Для Apache — модули mod_ssl, mod_proxy, mod_proxy_http, mod_proxy_wstunnel и mod_headers. Только с версии 2.4.47 Apache поддерживает
upgrade=websocket; для более старых версий в конце шаблона приведён обходной вариант с mod_rewrite. - Поддомен, используемый только для чата, например
chat.your-domain.com. Чату нужен весь хост; путь вродеwww.your-domain.com/chat/не подойдёт. Вводите только имя, безhttps://, порта и пути. Не допускаются IP-адреса, внутренние окончания вроде.local,.lanили.internalи имена в домене reactive.chat. - Тот же домен, что у сайта. Чат относится к первой стороне, только если поддомен принадлежит домену сайта, на котором он встроен. Иначе он тоже работает, но страница аккаунта указывает на различие.
- Запись DNS (A и/или AAAA), указывающая на ваш сервер. Все адреса имени должны быть публичными.
- TLS-сертификат для поддомена. Шаблоны nginx и Apache ожидают пути certbot (Let’s Encrypt); Caddy получает сертификат самостоятельно.
- Право изменять проект в аккаунте reactive.chat.
За балансировщиком нагрузки или CDN ваш прокси сначала видит адрес этого устройства, а не посетителя. В таком случае настройте получение настоящего адреса посетителя: в nginx модуль real_ip (set_real_ip_from, real_ip_header), в Apache mod_remoteip (RemoteIPHeader, RemoteIPTrustedProxy), в Caddy параметр trusted_proxies и место для подстановки {client_ip} вместо {remote_host}. Наша проверка не может распознать этот случай: она видит лишь, что задан корректный адрес, но не какой именно.
Пошаговая настройка
- Откройте страницу. Откройте проект в аккаунте. В разделе «Встраивание» находится ссылка Настроить собственный домен.
- Введите хост. В разделе «1. Хост» введите имя, например
chat.your-domain.com, и сохраните. - Создайте ключ. В разделе «2. Ключ прокси» нажмите Создать ключ. Ключ начинается с
rcpx_и показывается ровно один раз; мы храним лишь его хеш. Сразу скопируйте его. Это секрет, которому место только в конфигурации прокси — никогда на веб-странице, в браузерном скрипте или репозитории. - Вставьте шаблон. В разделе «3. Конфигурация сервера» есть готовые шаблоны nginx, Apache и Caddy. Сразу после создания ключа он уже в них; позднее они показывают
__RC_PROXY_KEY__, который нужно заменить ключом. При необходимости измените пути сертификатов, проверьте конфигурацию (nginx -tилиapachectl configtest) и перезагрузите сервер. - Проверьте. В разделе «5. Проверка» нажмите Проверить сейчас. Мы вызываем ваш поддомен извне и отдельно проверяем пять маршрутов (см. ниже). Сообщение не создаётся. Повторная проверка возможна не раньше чем через 10 секунд.
- Замените код встраивания. Только когда все пять шагов показывают «OK», замените текущий код на сайте кодом из раздела «4. Код встраивания».
Новый код выглядит так — оба адреса указывают на ваш поддомен:
<script src="https://chat.your-domain.com/loader.js"
data-rc-site-key="SITE_KEY"
data-rc-ws-url="wss://chat.your-domain.com/rc_wss/"
async></script>
Расположение файлов виджет берёт из src, подключение чата — из data-rc-ws-url, а из него выводит адрес офлайн-формы. Другие атрибуты, например data-rc-locale, остаются прежними; они описаны в разделе Встраивание виджета. Код на странице аккаунта также содержит фирменный цвет.
Пять шагов проверки
Каждый шаг показывает «OK», «Ошибка», «Примечание» или «Не проверено». Проверка пройдена, только если все пять показывают «OK»; примечание не считается успехом. Проверки используют только HTTPS на порту 443, не следуют перенаправлениям, на каждый шаг отводится 5 секунд.
- Разрешение имени. У имени должна быть запись DNS, и все его адреса должны быть публичными. Сообщается, если не найдены ни A, ни AAAA или хотя бы один адрес частный, локальный или зарезервированный — такие адреса мы не проверяем. Все следующие шаги подключаются именно к проверенному здесь адресу.
- loader.js через ваш домен. Мы загружаем
https://chat.your-domain.com/loader.jsи сравниваем файл с нашим. Если не удаётся подключиться, получить ответ или действительный сертификат, остальные шаги пропускаются («Не проверено»). Если прокси вместо файла отвечает перенаправлением, это ошибка. Если файл отличается от нашего, причина обычно в кеше прокси или неверной цели для/. - Ключ и адрес посетителя. Мы вызываем проверочный адрес в
/rc_wss/. Наш сервер отвечает, получил ли он действительный ключ и корректный адрес посетителя и к какому проекту относится ключ. Возможные ошибки: отсутствует заголовокX-RC-Proxy-Key; ключ неизвестен (опечатка, устарел или удалён; сразу после создания может пройти до 30 секунд); отсутствуетX-RC-Client-IPили в нём нет корректного адреса; ключ относится к другому проекту. Примечание появляется, если ключ действителен, но зарегистрирован для другого хоста. - Подключение чата (WebSocket). Мы открываем WebSocket-соединение через
wss://chat.your-domain.com/rc_wss/и ожидаем HTTP 101 с протоколомrc.v1. «Нет переключения на WebSocket» означает, что прокси не передаёт заголовкиUpgradeиConnection. - Офлайн-форма. Мы вызываем
https://chat.your-domain.com/api/offline/SITE_KEYс GET. Наша конечная точка отвечает HTTP 405, потому что принимает только POST; так мы узнаём, что запрос дошёл, не создавая сообщение. Другие результаты: источник отклонён (примечание, см. устранение неполадок), проект неактивен, цель требует аутентификации (HTTP 401).
Шаги 2–5 также могут сообщать HTTP 421 (заголовок Host, см. устранение неполадок). Если шаг 3 или 5 сообщает «Ответ не от reactive.chat», этот путь в прокси указывает на неверную цель.
Что прокси должен пересылать
/rc_wss/на сервер чата reactive.chat, с переключением на WebSocket и большим тайм-аутом (в шаблонах 3600 секунд). Загрузка файлов идёт по тому же пути; до 32 МБ на файл в зависимости от тарифа./api/offline/на тот же сервер. Виджет отправляет через него офлайн-форму.- Всё остальное — в сеть доставки reactive.chat. Оттуда поступают
loader.jsи другие файлы виджета.
Для всех трёх маршрутов:
- Заголовок Host и SNI содержат имя цели, а не ваш поддомен. На неизвестный хост наш сервер отвечает HTTP 421.
- Сертификат цели проверяется.
- Без cookie и учётных данных. Заголовки браузера
CookieиAuthorizationне передаются. - Без перенаправлений. Кеш не требуется. Если вы его добавляете, задайте короткий срок для
loader.js— в имени файла нет номера версии.
Для /rc_wss/ и /api/offline/ прокси также задаёт два заголовка при каждом запросе:
X-RC-Proxy-Key— ваш ключ.X-RC-Client-IP— адрес посетителя, который видит прокси.
«Задаёт» означает: всё, что браузер присылает под этими именами, перезаписывается и до нас не доходит. На маршруте к сети доставки оба заголовка очищаются; ключ передаётся только серверу чата.
Резервный канал HTTP через ваш домен
Если сеть посетителя не пропускает WebSocket, виджет автоматически переключается на резервный канал HTTP. Он использует тот же путь /rc_wss/ и не требует дополнительной записи в прокси. Нужны две вещи:
- Передавать ответы без буферизации. Прокси должен немедленно передавать ответы по
/rc_wss/: для nginxproxy_buffering offиproxy_cache off, для Apacheflushpackets=on, для Caddyflush_interval -1. Шаблоны ниже уже содержат эти настройки. - HTTPS в Content Security Policy. В
connect-srcнужен поддомен сwss://и сhttps://, напримерconnect-src 'self' wss://chat.your-domain.com https://chat.your-domain.com.
Шаблоны
Шаблоны ниже совпадают с шаблонами на странице аккаунта. На странице аккаунта уже подставлены ваш хост, актуальные для аккаунта целевые адреса и — сразу после создания — ваш ключ. Поэтому лучше копировать шаблон оттуда; здесь версии приведены для справки. Места для подстановки: chat.your-domain.com, SITE_KEY и __RC_PROXY_KEY__.
nginx
Размещается в контексте http, например как /etc/nginx/conf.d/chat.your-domain.com.conf. В RHEL и CentOS набор CA находится в /etc/pki/tls/certs/ca-bundle.crt вместо /etc/ssl/certs/ca-certificates.crt.
# reactive.chat - own domain (first-party proxy) for site key SITE_KEY
# Host: chat.your-domain.com
#
# Needs nginx >= 1.7 with the ssl module. Put this file into the http
# context (e.g. /etc/nginx/conf.d/chat.your-domain.com.conf), adjust the certificate
# paths if you do not use certbot, then: nginx -t && systemctl reload nginx
#
# The proxy key is a secret: never put it into a web page or a repository.
# X-RC-Proxy-Key and X-RC-Client-IP are always SET here - whatever a browser
# sends under these names is overwritten.
server {
listen 80;
listen [::]:80;
server_name chat.your-domain.com;
location /.well-known/acme-challenge/ { root /var/www/html; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name chat.your-domain.com;
ssl_certificate /etc/letsencrypt/live/chat.your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.your-domain.com/privkey.pem;
# Chat connection (WebSocket). Host header and SNI must be the upstream
# name - reactive.chat answers 421 to any other host.
# HTTP fallback (Server-Sent Events / long polling): its requests carry a
# short-lived connection token in the query string - EventSource cannot
# send headers. Same settings as /rc_wss/ below, but kept out of the
# access log.
location /rc_wss/h/ {
access_log off;
proxy_pass https://ws.reactive.chat/rc_wss/h/;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host ws.reactive.chat;
proxy_ssl_server_name on;
proxy_ssl_name ws.reactive.chat;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
proxy_set_header X-RC-Proxy-Key "__RC_PROXY_KEY__";
proxy_set_header X-RC-Client-IP $remote_addr;
proxy_set_header Cookie "";
proxy_set_header Authorization "";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
}
location /rc_wss/ {
proxy_pass https://ws.reactive.chat/rc_wss/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host ws.reactive.chat;
proxy_ssl_server_name on;
proxy_ssl_name ws.reactive.chat;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
proxy_set_header X-RC-Proxy-Key "__RC_PROXY_KEY__";
proxy_set_header X-RC-Client-IP $remote_addr;
proxy_set_header Cookie "";
proxy_set_header Authorization "";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
# Unbuffered: if a visitor's network blocks WebSockets, the widget
# falls back to Server-Sent Events / long polling on this path.
proxy_buffering off;
proxy_cache off;
# File attachments are uploaded through this path as well (PUT
# /rc_wss/upload/...). nginx allows 1 MB by default; reactive.chat
# accepts up to 32 MB per file depending on the plan.
client_max_body_size 32m;
proxy_request_buffering off;
}
# Offline form fallback (HTTP POST from the widget).
location /api/offline/ {
proxy_pass https://ws.reactive.chat/api/offline/;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host ws.reactive.chat;
proxy_ssl_server_name on;
proxy_ssl_name ws.reactive.chat;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
proxy_set_header X-RC-Proxy-Key "__RC_PROXY_KEY__";
proxy_set_header X-RC-Client-IP $remote_addr;
proxy_set_header Cookie "";
proxy_set_header Authorization "";
proxy_hide_header Set-Cookie;
client_max_body_size 32k;
proxy_read_timeout 30s;
}
# Smart Answer for site search (suche.js and the HTTP API). Same rules as
# the offline route: key and visitor address are set here.
location /api/suche/ {
proxy_pass https://ws.reactive.chat/api/suche/;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host ws.reactive.chat;
proxy_ssl_server_name on;
proxy_ssl_name ws.reactive.chat;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
proxy_set_header X-RC-Proxy-Key "__RC_PROXY_KEY__";
proxy_set_header X-RC-Client-IP $remote_addr;
proxy_set_header Cookie "";
proxy_set_header Authorization "";
proxy_hide_header Set-Cookie;
client_max_body_size 8k;
# The answer is a stream (Server-Sent Events): pass it on unbuffered.
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 120s;
}
# Widget files (loader.js, core.*.js ...). No caching required; if you
# add a cache, keep it short for loader.js (it is not versioned).
location / {
proxy_pass https://cdn.reactive.chat/;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host cdn.reactive.chat;
proxy_ssl_server_name on;
proxy_ssl_name cdn.reactive.chat;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
proxy_set_header X-RC-Proxy-Key "";
proxy_set_header X-RC-Client-IP "";
proxy_set_header Cookie "";
proxy_set_header Authorization "";
proxy_hide_header Set-Cookie;
}
}
# On RHEL/CentOS the CA bundle is /etc/pki/tls/certs/ca-bundle.crt.
# Behind a load balancer/CDN, $remote_addr is the balancer: configure the
# real_ip module so that it holds the visitor's address.
Apache
Шаблон содержит только VirtualHost для порта 443. Настройте перенаправление с порта 80 и сертификат так же, как для других хостов. SSLProxyVerifyDepth 5 обязателен: без него Apache проверяет цепочку сертификата цели лишь на один уровень, и соединение завершается ошибкой «Certificate Chain too long».
# reactive.chat - own domain (first-party proxy) for site key SITE_KEY
# Host: chat.your-domain.com
#
# Needs Apache >= 2.4.47 with mod_ssl, mod_proxy, mod_proxy_http,
# mod_proxy_wstunnel, mod_headers and mod_setenvif:
# a2enmod ssl proxy proxy_http proxy_wstunnel headers setenvif
# Adjust the certificate paths if you do not use certbot, then:
# apachectl configtest && systemctl reload apache2
#
# The proxy key is a secret: never put it into a web page or a repository.
<VirtualHost *:443>
ServerName chat.your-domain.com
# HTTP fallback requests (/rc_wss/h/...) carry a short-lived connection
# token in the query string - keep them out of the access log.
SetEnvIf Request_URI "^/rc_wss/h/" rc_no_log
# ${APACHE_LOG_DIR} is set on Debian/Ubuntu; elsewhere e.g. /var/log/httpd.
CustomLog ${APACHE_LOG_DIR}/chat.your-domain.com_access.log combined env=!rc_no_log
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/chat.your-domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/chat.your-domain.com/privkey.pem
# Upstream TLS: verified, SNI = upstream name (ProxyPreserveHost Off
# sends the upstream name as Host - reactive.chat answers 421 otherwise).
SSLProxyEngine on
SSLProxyVerify require
# Apache checks only ONE certificate deep by default; the upstream chain
# (leaf, intermediate, root) is longer: "Certificate Chain too long".
SSLProxyVerifyDepth 5
SSLProxyCheckPeerName on
SSLProxyCACertificateFile /etc/ssl/certs/ca-certificates.crt
ProxyRequests Off
ProxyPreserveHost Off
ProxyAddHeaders Off
# Whatever the browser sends under these names never reaches upstream.
RequestHeader unset X-RC-Proxy-Key early
RequestHeader unset X-RC-Client-IP early
RequestHeader unset Cookie early
RequestHeader unset Authorization early
# Longest path first. flushpackets=on on /rc_wss/: if a visitor's network
# blocks WebSockets, the widget falls back to Server-Sent Events / long
# polling on this path, and those must not be buffered.
ProxyPass "/rc_wss/" "https://ws.reactive.chat/rc_wss/" upgrade=websocket timeout=3600 flushpackets=on
ProxyPass "/api/offline/" "https://ws.reactive.chat/api/offline/" timeout=30
ProxyPass "/api/suche/" "https://ws.reactive.chat/api/suche/" timeout=120 flushpackets=on
ProxyPass "/" "https://cdn.reactive.chat/"
<Location "/rc_wss/">
RequestHeader set X-RC-Proxy-Key "__RC_PROXY_KEY__"
RequestHeader set X-RC-Client-IP "expr=%{REMOTE_ADDR}"
</Location>
<Location "/api/offline/">
RequestHeader set X-RC-Proxy-Key "__RC_PROXY_KEY__"
RequestHeader set X-RC-Client-IP "expr=%{REMOTE_ADDR}"
Header unset Set-Cookie
</Location>
<Location "/api/suche/">
RequestHeader set X-RC-Proxy-Key "__RC_PROXY_KEY__"
RequestHeader set X-RC-Client-IP "expr=%{REMOTE_ADDR}"
Header unset Set-Cookie
</Location>
</VirtualHost>
# Apache < 2.4.47 has no upgrade=websocket. Instead of the first ProxyPass:
# RewriteEngine on
# RewriteCond %{HTTP:Upgrade} =websocket [NC]
# RewriteRule ^/rc_wss/(.*) "wss://ws.reactive.chat/rc_wss/$1" [P,L]
# ProxyPass "/rc_wss/" "https://ws.reactive.chat/rc_wss/" timeout=3600 flushpackets=on
Caddy
Caddy получает сертификат самостоятельно; для WebSocket дополнительная настройка не нужна. header_up со значением заменяет всё, что браузер прислал под этим именем.
# reactive.chat - own domain (first-party proxy) for site key SITE_KEY
# Host: chat.your-domain.com
#
# Caddy 2 obtains the certificate itself. WebSockets need no extra setting.
# The proxy key is a secret: never put it into a web page or a repository.
# header_up with a value REPLACES what the browser sent under that name.
# If you enable access logging (log directive), skip the HTTP fallback
# requests - they carry a short-lived token in the query string:
# log_skip /rc_wss/h/* (Caddy < 2.8: skip_log /rc_wss/h/*)
chat.your-domain.com {
handle /rc_wss/* {
reverse_proxy https://ws.reactive.chat {
header_up Host ws.reactive.chat
header_up X-RC-Proxy-Key "__RC_PROXY_KEY__"
header_up X-RC-Client-IP {remote_host}
header_up -Cookie
header_up -Authorization
transport http {
tls_server_name ws.reactive.chat
}
flush_interval -1
}
}
handle /api/offline/* {
reverse_proxy https://ws.reactive.chat {
header_up Host ws.reactive.chat
header_up X-RC-Proxy-Key "__RC_PROXY_KEY__"
header_up X-RC-Client-IP {remote_host}
header_up -Cookie
header_up -Authorization
header_down -Set-Cookie
transport http {
tls_server_name ws.reactive.chat
}
}
}
handle /api/suche/* {
reverse_proxy https://ws.reactive.chat {
header_up Host ws.reactive.chat
header_up X-RC-Proxy-Key "__RC_PROXY_KEY__"
header_up X-RC-Client-IP {remote_host}
header_up -Cookie
header_up -Authorization
header_down -Set-Cookie
transport http {
tls_server_name ws.reactive.chat
}
# The answer is a stream (Server-Sent Events): pass it on unbuffered.
flush_interval -1
}
}
handle {
reverse_proxy https://cdn.reactive.chat {
header_up Host cdn.reactive.chat
header_up -X-RC-Proxy-Key
header_up -X-RC-Client-IP
header_up -Cookie
header_up -Authorization
header_down -Set-Cookie
transport http {
tls_server_name cdn.reactive.chat
}
}
}
}
Ключ прокси
- Ротация. Создать новый ключ немедленно выдаёт новый ключ. Предыдущий остаётся действительным 24 часа, чтобы можно было заменить его без перерыва; после замены проверьте ещё раз. Одновременно действуют не более двух ключей: повторная ротация в эти 24 часа немедленно аннулирует самый старый.
- Удаление. Удалить ключ немедленно аннулирует его, а также старый ключ, ещё действующий после ротации. Удалить собственный домен удаляет хост и ключ вместе. Сначала верните код встраивания на сайте к обычному виду.
- Если ключ отсутствует или неверен, чат продолжает работать: два заголовка просто не учитываются. Но каждый посетитель отображается с адресом вашего прокси. Поскольку защита от злоупотреблений считает подключения и запросы по адресам, она может ограничить или заблокировать весь прокси, а с ним сразу всех посетителей. Это относится и к офлайн-форме.
- Один проект на ключ. Ключ относится ровно к одному проекту и его зарегистрированному хосту. Если виджет с ключом сайта другого проекта подключается через прокси с действительным ключом, подключение чата отклоняется. Для ещё одного проекта настройте отдельный поддомен со своим ключом.
- Если ключ утёк: любой знающий его может указывать произвольные адреса посетителей для вашего проекта. Удалите его, затем создайте новый и установите в прокси. До этого чат продолжает работать, но с адресом прокси.
Устранение неполадок
HTTP 421 (Misdirected Request)
Наш сервер отклоняет заголовок Host: прокси отправляет ваше имя вместо имени цели. Заголовок Host и SNI должны содержать имя цели: в nginx proxy_set_header Host плюс proxy_ssl_server_name on с proxy_ssl_name, в Apache ProxyPreserveHost Off, в Caddy header_up Host и tls_server_name.
HTTP 502 или ошибки SSL при подключении к цели
Прокси не может установить TLS-соединение с нами или не доверяет сертификату.
- Apache: если в журнале ошибок написано «Certificate Chain too long», не хватает
SSLProxyVerifyDepth 5. - nginx: верен ли путь в
proxy_ssl_trusted_certificate(выше приведены пути для RHEL и CentOS)? Задано лиproxy_ssl_server_name on? - В целом: серверу должны быть разрешены исходящие подключения на порт 443.
HTTP 413 при загрузке вложений
Загрузки идут через /rc_wss/. Без отдельной настройки nginx принимает только 1 МБ, поэтому шаблон задаёт client_max_body_size 32m в разделе /rc_wss/. Если перед прокси стоит балансировщик нагрузки или CDN, его лимит должен быть не меньше.
Подключение чата без переключения протокола
Проверка сообщает «Нет переключения на WebSocket» с полученным вместо него кодом HTTP. Чат тогда продолжает работать через резервный канал HTTP, но подключается только после двух неудачных попыток WebSocket.
- nginx: в разделе
/rc_wss/нужныproxy_http_version 1.1,proxy_set_header Upgrade $http_upgradeиproxy_set_header Connection "upgrade". - Apache: версия 2.4.47 или новее с
upgrade=websocketи включённым mod_proxy_wstunnel; для более старых версий — обходной вариант в конце шаблона. - Перед прокси: стоящий перед ним CDN или балансировщик должен пропускать WebSocket.
HTTP 401 или 403 у офлайн-формы
- 401: по пути запрашивается аутентификация, обычно парольная защита на хосте прокси.
/api/offline/должен быть доступен без аутентификации. - 403 с примечанием об источнике: запрос доходит до нас, но источник не соответствует проекту. В «Разрешённых источниках» проекта должен быть домен вашего сайта — тот, на котором встроен чат, а не поддомен чата.
- 403 с «Ответ не от reactive.chat»: запрос отклоняется раньше, например межсетевым экраном веб-приложений или правилом доступа на вашем сервере.
DNS указывает на частный адрес
Проверка сообщает о непубличном адресе, если хотя бы один адрес имени частный, локальный или зарезервированный (например, 10.0.0.0/8, 192.168.0.0/16, 100.64.0.0/10 или fc00::/7). Частые причины — запись из внутреннего DNS или внутренний балансировщик нагрузки. Посетители тоже не могут достичь таких адресов; публичная запись должна указывать на публичный адрес.
Ручная проверка
Проверочный адрес из шага 3 можно вызвать самостоятельно:
curl -s https://chat.your-domain.com/rc_wss/eigene-domain-probe
При правильной настройке ответ такой:
{"rc":"eigene-domain-probe","v":1,"schluessel":"gueltig","client_ip":"gesetzt","site":"SITE_KEY","host":"chat.your-domain.com"}
Значения — немецкие слова: schluessel (ключ) может быть gueltig (действителен), unbekannt (неизвестен) или fehlt (отсутствует); client_ip — gesetzt (задан), fehlt (отсутствует) или ungueltig (некорректен). site и host включаются только при действительном ключе. Ответ никогда не содержит адреса.
Подробнее в документации
Подробное описание: Собственный домен и прокси первой стороны. Все главы собраны в документации.
Обновлено: