Dominio propio y proxy first-party
Cómo servir los archivos del widget, la conexión del chat, el formulario sin conexión y Smart Answer mediante un subdominio de su sitio web, con clave de proxy, dirección real del visitante y plantillas para nginx, Apache y Caddy.
Con un dominio propio, el chat funciona a través de un subdominio de su sitio web, por ejemplo chat.your-company.com. Su servidor recibe las solicitudes del widget y las reenvía a reactive.chat como proxy inverso. Esta página está dirigida a quien administra ese servidor. La versión breve para editores está en Dominio propio (first-party).
Qué pasa por el subdominio
- Archivos del widget –
loader.js, el núcleo que se carga después (core.<hash>.js) y los demás módulos. - Conexión del chat – el WebSocket en
/rc_wss/, incluida la alternativa HTTP en/rc_wss/h/y las cargas de archivos en/rc_wss/upload/. - Formulario sin conexión –
POST /api/offline/<SITE_KEY>, cuando no se puede establecer una conexión del chat. - Smart Answer –
/api/suche/, si utiliza la respuesta de IA en la búsqueda de su sitio web.
Qué obtiene:
- Sin solicitudes a dominios de terceros. Para estas rutas, los navegadores de sus visitantes solo se comunican con su subdominio.
- Una dirección en su política de seguridad de contenido.
script-srcyconnect-srcincluyen su subdominio en lugar de las direcciones de reactive.chat (detalles en Seguridad y CSP). - Se recibe la dirección real del visitante. Su proxy la comunica en una cabecera específica, protegida por una clave secreta. La limitación y el bloqueo cuentan entonces por visitante en lugar de por proxy.
Qué no implica:
- No es autoalojamiento. reactive.chat sigue procesando y almacenando las conversaciones, los archivos adjuntos y los ajustes.
- No determina los requisitos de consentimiento. Un dominio propio no cambia quién trata los datos.
- Su proxy ve el tráfico. TLS termina en su proxy; no registre allí los cuerpos de las solicitudes y excluya
/rc_wss/h/del registro de acceso (estas solicitudes llevan un token de conexión de corta duración en la consulta).
Requisitos
- Un servidor o proxy inverso accesible públicamente mediante HTTPS en el puerto 443 y capaz de establecer conexiones HTTPS salientes. Hay plantillas para nginx (con el módulo ssl), Apache 2.4.47 o posterior y Caddy 2.
- Para Apache, los módulos
mod_ssl,mod_proxy,mod_proxy_http,mod_proxy_wstunnel,mod_headersymod_setenvif. - Un subdominio dedicado exclusivamente al chat. El chat necesita el host completo; una ruta como
www.your-company.com/chat/no funciona. Introduzca solo el nombre, sinhttps://, puerto ni ruta. No se admiten direcciones IP, terminaciones internas como.local,.lan,.internalni nombres bajoreactive.chat. - El mismo dominio que el sitio web. El chat solo es first-party si el subdominio pertenece al dominio del sitio web donde se inserta.
- DNS (A y/o AAAA) únicamente con direcciones públicas.
- Un certificado TLS para el subdominio (las plantillas de nginx/Apache utilizan las rutas de certbot; Caddy lo obtiene por sí mismo).
- Permiso para editar el proyecto.
Configuración
- En su cuenta, abra el proyecto, sección Inserción → Configurar su dominio propio.
- En 1. Host, introduzca el nombre, por ejemplo
chat.your-company.com, y guarde. - En 2. Clave de proxy, pulse Crear clave. La clave empieza por
rcpx_y se muestra exactamente una vez; solo se almacena un hash. Debe figurar únicamente en la configuración del proxy, nunca en una página web, un script del navegador o un repositorio. - En 3. Configuración del servidor, copie la plantilla para su servidor. Justo después de crear la clave, la contiene; después muestra
__RC_PROXY_KEY__. Pruebe la configuración (nginx -toapachectl configtest) y recargue el servidor. - En 5. Comprobación, pulse Comprobar ahora (como máximo cada 10 segundos). No se crea ningún mensaje.
- Solo cuando los cinco pasos de comprobación muestren «OK», sustituya el código de inserción por el de 4. Código de inserción:
<script src="https://chat.your-company.com/loader.js"
data-rc-site-key="SITE_KEY"
data-rc-ws-url="wss://chat.your-company.com/rc_wss/"
async></script>
El widget obtiene la ubicación de sus archivos de src y la conexión del chat de data-rc-ws-url, y a partir de esta deduce las direcciones del formulario sin conexión, las cargas de archivos y la alternativa HTTP. Todos los demás atributos se mantienen (Referencia de la etiqueta de script).
Qué debe reenviar el proxy
/rc_wss/→ servidor de chathttps://ws.reactive.chat/rc_wss/, con actualización a WebSocket, un tiempo de espera largo (plantillas: 3600 s), sin almacenamiento en búfer y con un límite del cuerpo de al menos 32 MB (cargas de archivos)./api/offline/→https://ws.reactive.chat/api/offline/(cuerpo pequeño, plantilla: 32 kB, 30 s)./api/suche/→https://ws.reactive.chat/api/suche/, sin almacenamiento en búfer (la respuesta es un flujo de Server-Sent Events), cuerpo de hasta 8 kB, 120 s.- todo lo demás → red de distribución
https://cdn.reactive.chat/.
Para todas las rutas:
- La cabecera Host y SNI utilizan el nombre del destino, no su subdominio. Un host desconocido recibe HTTP 421.
- Se verifica el certificado del destino.
- Sin cookies ni credenciales. No se reenvían
CookieyAuthorizationdel navegador ni se devuelveSet-Cookie. - Sin redirecciones. No se necesita una caché; si configura una, mantenga un tiempo corto para
loader.js: el archivo no lleva un número de versión en su nombre (el núcleo sí; véase Arquitectura).
Para /rc_wss/, /api/offline/ y /api/suche/, el proxy establece dos cabeceras en cada solicitud:
- X-RC-Proxy-Key – su clave
rcpx_…. - X-RC-Client-IP – la dirección del visitante tal como la ve su proxy.
«Establece» significa que cualquier valor enviado por el navegador con esos nombres se sobrescribe. En la ruta hacia la red de distribución se vacían ambas.
Detrás de un balanceador de carga o una CDN, su proxy ve primero la dirección de ese dispositivo. En ese caso, configure la obtención de la dirección real: nginx real_ip (set_real_ip_from, real_ip_header), Apache mod_remoteip (RemoteIPHeader, RemoteIPTrustedProxy), Caddy trusted_proxies y {client_ip} en lugar de {remote_host}. La comprobación no detecta este caso; solo ve que se ha establecido una dirección válida.
Plantilla de nginx
La página de la cuenta ya introduce el host, las direcciones de destino y la clave; lo mejor es copiar la plantilla desde allí. La versión de aquí sirve como referencia; los marcadores son chat.your-company.com, SITE_KEY y __RC_PROXY_KEY__. En RHEL/CentOS, el paquete de certificados de CA se encuentra en /etc/pki/tls/certs/ca-bundle.crt.
server {
listen 80;
listen [::]:80;
server_name chat.your-company.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-company.com;
ssl_certificate /etc/letsencrypt/live/chat.your-company.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.your-company.com/privkey.pem;
# HTTP fallback (SSE / long polling): token in the query, do not 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;
}
# Chat connection (WebSocket) and uploads
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;
proxy_buffering off;
proxy_cache off;
client_max_body_size 32m;
proxy_request_buffering off;
}
# Offline form
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 (website search), answer as a stream
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;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 120s;
}
# Widget files
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;
}
}
Plantilla de Apache (2.4.47 o posterior)
Solo el VirtualHost para el puerto 443; configure la redirección desde el puerto 80 y el certificado como para sus demás hosts. Se necesita SSLProxyVerifyDepth 5; de lo contrario, Apache solo comprueba un nivel de la cadena del destino e indica «Certificate Chain too long».
<VirtualHost *:443>
ServerName chat.your-company.com
SetEnvIf Request_URI "^/rc_wss/h/" rc_no_log
CustomLog ${APACHE_LOG_DIR}/chat.your-company.com_access.log combined env=!rc_no_log
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/chat.your-company.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/chat.your-company.com/privkey.pem
SSLProxyEngine on
SSLProxyVerify require
SSLProxyVerifyDepth 5
SSLProxyCheckPeerName on
SSLProxyCACertificateFile /etc/ssl/certs/ca-certificates.crt
ProxyRequests Off
ProxyPreserveHost Off
ProxyAddHeaders Off
RequestHeader unset X-RC-Proxy-Key early
RequestHeader unset X-RC-Client-IP early
RequestHeader unset Cookie early
RequestHeader unset Authorization early
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 anterior a 2.4.47 no admite upgrade=websocket. En ese caso, sustituya la primera línea ProxyPass por:
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
Plantilla de Caddy 2
header_up con un valor sustituye lo que haya enviado el navegador con ese nombre. Si activa los registros de acceso, excluya /rc_wss/h/* (log_skip; antes de Caddy 2.8, skip_log).
chat.your-company.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
}
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
}
}
}
}
Los cinco pasos de comprobación
Cada paso muestra «OK», «Error», «Aviso» o «sin comprobar». La comprobación solo se supera con cinco «OK». Las comprobaciones utilizan únicamente HTTPS en el puerto 443, sin redirecciones, con 5 segundos por paso.
- Resolución de nombres – existen registros A/AAAA y todas las direcciones son públicas. Todos los pasos siguientes se conectan exactamente a esta dirección.
- loader.js a través de su dominio – se carga el archivo y se compara con el nuestro. Sin conexión, respuesta o certificado válido, se omiten los pasos restantes. Una redirección es un error; un archivo distinto apunta a una caché o un destino incorrecto para
/. - Clave y dirección del visitante – llamada a
/rc_wss/eigene-domain-probe. Posibles errores: faltaX-RC-Proxy-Key; clave desconocida (justo después de crearla puede tardar hasta 30 segundos); faltaX-RC-Client-IPo no es válida; la clave pertenece a otro proyecto. Un aviso si la clave es válida, pero está registrada para otro host. - WebSocket –
wss://chat.your-company.com/rc_wss/debe responder con HTTP 101 y el subprotocolorc.v1. - Formulario sin conexión –
GET /api/offline/SITE_KEYdebe responder con 405 (el endpoint solo acepta POST; así no se crea ningún mensaje).
Puede consultar personalmente la dirección de comprobación del paso 3:
curl -s https://chat.your-company.com/rc_wss/eigene-domain-probe
Con una configuración correcta:
{"rc":"eigene-domain-probe","v":1,"schluessel":"gueltig","client_ip":"gesetzt","site":"SITE_KEY","host":"chat.your-company.com"}
- schluessel –
gueltig(válida),unbekannt(desconocida) ofehlt(falta). - client_ip –
gesetzt(establecida),fehlt(falta) oungueltig(no válida). - site, host – solo con una clave válida. La respuesta nunca devuelve una dirección.
La clave de proxy
- Rotación: Crear nueva clave genera una nueva de inmediato; la anterior sigue siendo válida durante 24 horas. Hay como máximo dos claves válidas: volver a rotar dentro de esas 24 horas invalida la más antigua de inmediato.
- Eliminación: Eliminar clave la invalida de inmediato (incluida una anterior de una rotación en curso). Eliminar dominio propio elimina conjuntamente el host y la clave; antes, vuelva a cambiar el código de inserción de su sitio web.
- Clave ausente o incorrecta: el chat sigue funcionando, pero se ignoran las dos cabeceras. Todos los visitantes aparecen entonces con la dirección de su proxy y, como la protección contra abusos cuenta por dirección, puede limitar todo su proxy y, por tanto, a todos los visitantes a la vez.
- Un proyecto por clave: si un widget con la clave del sitio de otro proyecto se conecta mediante un proxy con una clave válida, se rechaza la conexión. Para otro proyecto necesita un subdominio independiente con su propia clave.
- Clave filtrada: quien la conozca puede indicar direcciones de visitante arbitrarias para su proyecto. Elimínela, cree una nueva e introdúzcala.
Solución de problemas
- HTTP 421 (Misdirected Request): el proxy envía su nombre como host en lugar del nombre del destino. nginx:
proxy_set_header Hostmásproxy_ssl_server_name on/proxy_ssl_name; Apache:ProxyPreserveHost Off; Caddy:header_up Hostytls_server_name. - HTTP 502 / error TLS hacia el destino: Apache sin
SSLProxyVerifyDepth 5; nginx con una ruta incorrecta enproxy_ssl_trusted_certificateo sinproxy_ssl_server_name on; HTTPS saliente bloqueado. - HTTP 413 al subir archivos: sin un ajuste, nginx solo acepta 1 MB;
client_max_body_size 32men la sección/rc_wss/(y al menos el mismo límite en un balanceador de carga anterior). - Sin actualización a WebSocket: no se reenvían
Upgrade/Connection. El chat funciona entonces mediante la alternativa HTTP, pero solo se conecta después de dos intentos fallidos de WebSocket. - 401 para el formulario sin conexión: hay una protección con contraseña delante de
/api/offline/. - 403 con un aviso sobre el origen: falta el dominio del sitio web (¡no el subdominio del chat!) en Orígenes permitidos del proyecto.
- 403 «La respuesta no procede de reactive.chat»: un cortafuegos o una regla de acceso delante del destino rechaza la solicitud.
- El DNS apunta a una dirección privada (
10.0.0.0/8,192.168.0.0/16,100.64.0.0/10,fc00::/7…): el registro público debe ser público.
Siguiente: Transporte y protocolo · Seguridad y CSP
చివరిగా నవీకరించినది: