Kaip galime padėti?

Trumpai papasakokite, apie ką klausiate - atsakysime el. paštu.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
Į pradžios puslapį

Dominio propio (first-party)

Sirva el widget, la conexión del chat y el formulario sin conexión desde un subdominio de su sitio web: requisitos, configuración, plantillas para nginx, Apache y Caddy y solución de problemas.

Con un dominio propio, el chat funciona a través de un subdominio de su sitio web, por ejemplo chat.your-domain.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.

Qué aporta un dominio propio

Por su subdominio pasan:

Esto permite:

Qué no implica

Requisitos

Detrás de un balanceador de carga o una CDN, su proxy ve primero la dirección de ese dispositivo en lugar de la del visitante. En ese caso, configure la obtención de la dirección real del visitante: en nginx, el módulo real_ip (set_real_ip_from, real_ip_header); en Apache, mod_remoteip (RemoteIPHeader, RemoteIPTrustedProxy); en Caddy, la opción trusted_proxies y el marcador {client_ip} en lugar de {remote_host}. Nuestra comprobación no puede detectar este caso: solo ve que se ha establecido una dirección válida, no cuál.

Configuración paso a paso

  1. Abrir la página. Abra el proyecto en su cuenta. En la sección «Inserción» encontrará el enlace Configurar su dominio propio.
  2. Introducir el host. En «1. Host», introduzca el nombre, por ejemplo chat.your-domain.com, y guarde.
  3. Crear la clave. En «2. Clave de proxy», pulse Crear clave. La clave empieza por rcpx_ y se muestra exactamente una vez; solo guardamos un hash de ella. Cópiela de inmediato. Es secreta y solo debe figurar en la configuración de su proxy, nunca en una página web, un script del navegador o un repositorio.
  4. Insertar la plantilla. En «3. Configuración del servidor» encontrará plantillas listas para nginx, Apache y Caddy. Justo después de crear la clave ya la contienen; después muestran __RC_PROXY_KEY__, que debe sustituir por la clave. Ajuste las rutas de los certificados si es necesario, pruebe la configuración (nginx -t o apachectl configtest) y recargue el servidor.
  5. Comprobar. En «5. Comprobación», pulse Comprobar ahora. Accedemos a su subdominio desde el exterior y comprobamos cinco rutas por separado (véase más abajo). No se crea ningún mensaje. Solo se puede repetir la comprobación una vez transcurridos al menos 10 segundos.
  6. Sustituir el código de inserción. Solo cuando los cinco pasos muestren «OK», sustituya el código de inserción actual de su sitio web por el de «4. Código de inserción».

El nuevo código tiene este aspecto; ambas direcciones apuntan a su subdominio:

<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>

El widget obtiene la ubicación de sus archivos de src y la conexión del chat de data-rc-ws-url, a partir de la cual deduce la dirección del formulario sin conexión. Los demás atributos, como data-rc-locale, se mantienen; se describen en Insertar el widget. El código de la página de la cuenta también incluye el color de su marca.

Los cinco pasos de comprobación

Cada paso muestra «OK», «Error», «Aviso» o «sin comprobar». La comprobación solo se supera cuando los cinco muestran «OK»; un aviso no cuenta como superado. Las comprobaciones utilizan únicamente HTTPS en el puerto 443, no siguen redirecciones y disponen de 5 segundos por paso.

  1. Resolución de nombres. El nombre debe tener un registro DNS y todas sus direcciones deben ser públicas. Se informa si no se encuentra ni un registro A ni uno AAAA, o si al menos una dirección es privada, local o reservada; no comprobamos esas direcciones. Todos los pasos siguientes se conectan exactamente a la dirección comprobada aquí.
  2. loader.js a través de su dominio. Cargamos https://chat.your-domain.com/loader.js y comparamos el archivo con el nuestro. Si no se establece la conexión, no hay respuesta o no se obtiene un certificado válido, los pasos restantes se omiten («sin comprobar»). Si el proxy responde con una redirección en lugar del archivo, se considera un error. Si el archivo difiere del nuestro, la causa suele ser una caché en el proxy o un destino incorrecto para /.
  3. Clave y dirección del visitante. Accedemos a una dirección de comprobación bajo /rc_wss/. Nuestro servidor indica si ha recibido una clave válida y una dirección de visitante válida, y a qué proyecto pertenece la clave. Posibles errores: falta la cabecera X-RC-Proxy-Key; la clave es desconocida (mal escrita, obsoleta o eliminada; justo después de crearla puede tardar hasta 30 segundos); falta la cabecera X-RC-Client-IP o no contiene una dirección válida; la clave pertenece a otro proyecto. Aparece un aviso si la clave es válida pero está registrada para otro host.
  4. Conexión del chat (WebSocket). Abrimos una conexión WebSocket mediante wss://chat.your-domain.com/rc_wss/ y esperamos HTTP 101 con el protocolo rc.v1. «Sin actualización a WebSocket» significa que el proxy no reenvía las cabeceras Upgrade y Connection.
  5. Formulario sin conexión. Accedemos a https://chat.your-domain.com/api/offline/SITE_KEY mediante GET. Nuestro endpoint responde con HTTP 405 porque solo acepta POST; esto nos indica que la solicitud nos llega, sin crear un mensaje. Otros resultados: origen rechazado (un aviso, véase la solución de problemas), proyecto no activo, el destino requiere autenticación (HTTP 401).

Los pasos 2 a 5 también pueden indicar HTTP 421 (cabecera Host, véase la solución de problemas). Si el paso 3 o el 5 indica «La respuesta no procede de reactive.chat», esta ruta apunta a un destino incorrecto en su proxy.

Qué debe reenviar el proxy

Para las tres rutas:

Para /rc_wss/ y /api/offline/, el proxy también establece dos cabeceras en cada solicitud:

«Establece» significa que cualquier valor que envíe el navegador con esos nombres se sobrescribe y nunca nos llega. En la ruta hacia la red de distribución se vacían ambas cabeceras; la clave solo se envía al servidor de chat.

Alternativa HTTP a través de su dominio

Si la red de un visitante no deja pasar WebSocket, el widget cambia automáticamente a la alternativa HTTP. Utiliza la misma ruta /rc_wss/ y no necesita ninguna entrada adicional en el proxy. Se requieren dos cosas:

Las plantillas

Las plantillas siguientes coinciden con las de la página de la cuenta. Esa página ya introduce su host, las direcciones de destino válidas para su cuenta y, justo después de crearla, su clave. Por ello, lo mejor es copiar la plantilla desde allí; las versiones de aquí sirven como referencia. Los marcadores son chat.your-domain.com, SITE_KEY y __RC_PROXY_KEY__.

nginx

Debe colocarse en el contexto http, por ejemplo como /etc/nginx/conf.d/chat.your-domain.com.conf. En RHEL y CentOS, el paquete de certificados de CA se encuentra en /etc/pki/tls/certs/ca-bundle.crt en lugar de /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

La plantilla solo contiene 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: sin esta línea, Apache solo comprueba un nivel de la cadena de certificados del destino y la conexión falla con «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 obtiene el certificado por sí mismo; WebSockets no necesita ningún ajuste adicional. header_up con un valor sustituye lo que haya enviado el navegador con ese nombre.

# 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
            }
        }
    }
}

La clave de proxy

Solución de problemas

HTTP 421 (Misdirected Request)

Nuestro servidor rechaza la cabecera Host: su proxy envía su propio nombre en lugar del nombre del destino. La cabecera Host y SNI deben utilizar el nombre del destino: en nginx, proxy_set_header Host más proxy_ssl_server_name on con proxy_ssl_name; en Apache, ProxyPreserveHost Off; en Caddy, header_up Host y tls_server_name.

HTTP 502 o errores SSL hacia el destino

El proxy no puede establecer la conexión TLS con nosotros o no confía en el certificado.

HTTP 413 al subir archivos adjuntos

Las cargas pasan por /rc_wss/. Sin un ajuste específico, nginx solo acepta 1 MB; por ello, la plantilla establece client_max_body_size 32m en la sección /rc_wss/. Si hay un balanceador de carga o una CDN delante de su proxy, necesita como mínimo el mismo límite.

Conexión del chat sin actualización a WebSocket

La comprobación indica «Sin actualización a WebSocket» con el estado HTTP recibido en su lugar. El chat continúa entonces mediante la alternativa HTTP, pero solo se conecta después de dos intentos fallidos de WebSocket.

HTTP 401 o 403 en el formulario sin conexión

El DNS apunta a una dirección privada

La comprobación indica una dirección no pública si al menos una dirección del nombre es privada, local o reservada (por ejemplo, 10.0.0.0/8, 192.168.0.0/16, 100.64.0.0/10 o fc00::/7). Las causas habituales son un registro del DNS interno o un balanceador de carga interno. Sus visitantes tampoco pueden acceder a esas direcciones; el registro público debe apuntar a una dirección pública.

Comprobar manualmente

Puede consultar personalmente la dirección de comprobación del paso 3:

curl -s https://chat.your-domain.com/rc_wss/eigene-domain-probe

Con una configuración correcta, la respuesta es:

{"rc":"eigene-domain-probe","v":1,"schluessel":"gueltig","client_ip":"gesetzt","site":"SITE_KEY","host":"chat.your-domain.com"}

Los valores son palabras alemanas: schluessel (clave) es gueltig (válida), unbekannt (desconocida) o fehlt (falta); client_ip es gesetzt (establecida), fehlt (falta) o ungueltig (no válida). site y host solo se incluyen con una clave válida. La respuesta nunca contiene una dirección.

Más información en la documentación

En detalle: Dominio propio y proxy first-party. Encontrará todos los capítulos en la documentación.

Paskutinį kartą atnaujinta: