Dominio personalizzato e proxy first-party
Distribuire file del widget, connessione della chat, modulo offline e Smart Answer tramite un sottodominio del sito, con chiave del proxy, indirizzo reale del visitatore e modelli per nginx, Apache e Caddy.
Con un dominio personalizzato, la chat passa attraverso un sottodominio del Suo sito, ad esempio chat.your-company.com. Il Suo server accetta le richieste del widget e le inoltra a reactive.chat come proxy inverso. Questa pagina è destinata a chi gestisce quel server. La versione breve per chi cura i contenuti è in Dominio personalizzato (first-party).
Che cosa passa attraverso il sottodominio
- File del widget:
loader.js, il nucleo caricato in seguito (core.<hash>.js) e gli altri moduli. - Connessione della chat: WebSocket sotto
/rc_wss/, incluso il fallback HTTP sotto/rc_wss/h/e i caricamenti sotto/rc_wss/upload/. - Modulo offline:
POST /api/offline/<SITE_KEY>, quando non è possibile stabilire la connessione della chat. - Smart Answer:
/api/suche/, se usa la risposta IA nella ricerca del sito.
I vantaggi:
- Nessuna richiesta a domini di terzi. Per questi percorsi, i browser dei visitatori comunicano solo con il Suo sottodominio.
- Un indirizzo nella Content Security Policy.
script-srceconnect-srcelencano il sottodominio al posto degli indirizzi reactive.chat (dettagli in Sicurezza e CSP). - Arriva l’indirizzo reale del visitatore. Il proxy lo comunica in un’intestazione dedicata, protetta da una chiave segreta. Limitazioni e blocchi contano quindi per visitatore anziché per proxy.
Che cosa non è:
- Non è hosting autonomo. Conversazioni, allegati e impostazioni continuano a essere elaborati e conservati da reactive.chat.
- Non determina il consenso necessario. Il dominio personalizzato non cambia chi tratta i dati.
- Il proxy vede il traffico. TLS termina sul proxy; non vi registri i corpi delle richieste ed escluda
/rc_wss/h/dal registro degli accessi (queste richieste contengono un token di connessione di breve durata nella query).
Requisiti
- Un server o proxy inverso raggiungibile pubblicamente tramite HTTPS sulla porta 443 e capace di effettuare connessioni HTTPS in uscita. Sono disponibili modelli per nginx (con modulo ssl), Apache 2.4.47 o successivo e Caddy 2.
- Per Apache, i moduli
mod_ssl,mod_proxy,mod_proxy_http,mod_proxy_wstunnel,mod_headersemod_setenvif. - Un sottodominio usato solo per la chat. La chat richiede l’intero host; un percorso come
www.your-company.com/chat/non funziona. Inserisca solo il nome, senzahttps://, porta o percorso. Non sono consentiti indirizzi IP, suffissi interni come.local,.lan,.internale nomi sottoreactive.chat. - Lo stesso dominio del sito. La chat è first-party solo se il sottodominio appartiene al dominio del sito in cui è incorporata.
- DNS (A e/o AAAA) con soli indirizzi pubblici.
- Un certificato TLS per il sottodominio (i modelli nginx/Apache prevedono i percorsi di certbot; Caddy lo ottiene autonomamente).
- Permesso di modificare il progetto.
Configurazione
- Nell’account apra il progetto, sezione Incorporamento → Configura un dominio personalizzato.
- In 1. Host, inserisca il nome, ad esempio
chat.your-company.com, e salvi. - In 2. Chiave del proxy, faccia clic su Genera chiave. La chiave inizia con
rcpx_e viene mostrata una sola volta; ne viene conservato solo un hash. Deve trovarsi esclusivamente nella configurazione del proxy, mai in una pagina web, uno script del browser o un repository. - In 3. Configurazione del server, prenda il modello adatto. Subito dopo la creazione contiene la chiave; in seguito mostra
__RC_PROXY_KEY__. Verifichi la configurazione (nginx -toapachectl configtest) e ricarichi il server. - In 5. Verifica, faccia clic su Verifica ora (al massimo ogni 10 secondi). Non viene creato alcun messaggio.
- Solo quando tutti e cinque i passi mostrano «OK», sostituisca il codice di incorporamento con quello di 4. Codice di incorporamento:
<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>
Il widget ricava la posizione dei file da src, la connessione della chat da data-rc-ws-url e da questa gli indirizzi di modulo offline, caricamenti e fallback HTTP. Tutti gli altri attributi restano invariati (Riferimento del tag script).
Che cosa deve inoltrare il proxy
/rc_wss/→ server della chathttps://ws.reactive.chat/rc_wss/, con upgrade WebSocket, timeout lungo (modelli: 3600 s), senza buffering e limite del corpo di almeno 32 MB (caricamenti)./api/offline/→https://ws.reactive.chat/api/offline/(corpo piccolo, modello: 32 kB, 30 s)./api/suche/→https://ws.reactive.chat/api/suche/, senza buffering (la risposta è un flusso Server-Sent Events), corpo fino a 8 kB, 120 s.- tutto il resto → rete di distribuzione
https://cdn.reactive.chat/.
Per tutti i percorsi:
- Intestazione Host e SNI corrispondono al nome della destinazione, non al Suo sottodominio. Un host sconosciuto riceve HTTP 421.
- Il certificato della destinazione viene verificato.
- Nessun cookie, nessuna credenziale.
CookieeAuthorizationdel browser non vengono inoltrati eSet-Cookienon viene restituito. - Nessun reindirizzamento. Non serve una cache; se la configura, mantenga breve la durata per
loader.js, che non ha versione nel nome (il nucleo sì; vedere Architettura).
Per /rc_wss/, /api/offline/ e /api/suche/, il proxy imposta due intestazioni su ogni richiesta:
- X-RC-Proxy-Key: la Sua chiave
rcpx_…. - X-RC-Client-IP: l’indirizzo del visitatore come lo vede il proxy.
«Imposta» significa che ciò che il browser invia con questi nomi viene sovrascritto. Sul percorso verso la rete di distribuzione entrambe vengono rimosse.
Dietro un bilanciatore di carico o una CDN, il proxy vede inizialmente l’indirizzo di quel dispositivo. Configuri quindi l’acquisizione dell’indirizzo reale: nginx real_ip (set_real_ip_from, real_ip_header), Apache mod_remoteip (RemoteIPHeader, RemoteIPTrustedProxy), Caddy trusted_proxies e {client_ip} al posto di {remote_host}. La verifica non rileva questo caso: vede solo che è impostato un indirizzo valido.
Modello nginx
La pagina dell’account compila già host, indirizzi di destinazione e chiave: è preferibile copiare il modello da lì. La versione qui è di riferimento; i segnaposto sono chat.your-company.com, SITE_KEY e __RC_PROXY_KEY__. Su RHEL/CentOS il bundle CA è in /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;
}
}
Modello Apache (2.4.47 o successivo)
Solo il VirtualHost per la porta 443; configuri il reindirizzamento dalla porta 80 e il certificato come per gli altri host. SSLProxyVerifyDepth 5 è necessario; altrimenti Apache verifica solo un livello della catena della destinazione e segnala «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 precedente a 2.4.47 non riconosce upgrade=websocket. In tal caso sostituisca la prima riga ProxyPass con:
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
Modello Caddy 2
header_up con un valore sostituisce ciò che il browser ha inviato con quel nome. Se attiva i registri degli accessi, escluda /rc_wss/h/* (log_skip, prima di 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
}
}
}
}
I cinque passi della verifica
Ogni passo mostra «OK», «Errore», «Nota» o «non verificato». La verifica è superata solo con cinque «OK». Le verifiche usano solo HTTPS sulla porta 443, senza reindirizzamenti, 5 secondi per passo.
- Risoluzione del nome: A/AAAA presenti, tutti gli indirizzi pubblici. Tutti i passi successivi si collegano esattamente a questo indirizzo.
- loader.js tramite il Suo dominio: il file viene caricato e confrontato con il nostro. Senza connessione, risposta o certificato valido, i passi rimanenti vengono saltati. Un reindirizzamento è un errore; un file diverso indica una cache o una destinazione errata per
/. - Chiave e indirizzo del visitatore: chiamata a
/rc_wss/eigene-domain-probe. Possibili errori:X-RC-Proxy-Keymancante; chiave sconosciuta (subito dopo la creazione, ritardo fino a 30 secondi);X-RC-Client-IPmancante o non valido; chiave di un altro progetto. Una nota se la chiave è valida ma registrata per un host diverso. - WebSocket:
wss://chat.your-company.com/rc_wss/deve rispondere con HTTP 101 e sottoprotocollorc.v1. - Modulo offline:
GET /api/offline/SITE_KEYdeve rispondere con 405 (l’endpoint accetta solo POST; così non viene creato alcun messaggio).
Può chiamare personalmente l’indirizzo di verifica del passo 3:
curl -s https://chat.your-company.com/rc_wss/eigene-domain-probe
Con configurazione corretta:
{"rc":"eigene-domain-probe","v":1,"schluessel":"gueltig","client_ip":"gesetzt","site":"SITE_KEY","host":"chat.your-company.com"}
- schluessel:
gueltig(valida),unbekannt(sconosciuta) ofehlt(mancante). - client_ip:
gesetzt(impostato),fehlt(mancante) oungueltig(non valido). - site, host: solo con una chiave valida. La risposta non restituisce mai un indirizzo.
La chiave del proxy
- Rotazione: Crea nuova chiave ne emette subito una; la precedente resta valida per 24 ore. Esistono al massimo due chiavi valide; un’ulteriore rotazione entro 24 ore invalida subito la più vecchia.
- Rimozione: Rimuovi chiave la invalida subito (inclusa una vecchia chiave di una rotazione in corso). Rimuovi il dominio elimina host e chiave insieme; prima ripristini il codice sul sito.
- Chiave mancante o errata: la chat continua a funzionare, ma le due intestazioni vengono ignorate. Tutti i visitatori appaiono con l’indirizzo del proxy; poiché la protezione dagli abusi conta per indirizzo, può limitare tutto il proxy e quindi tutti i visitatori contemporaneamente.
- Un progetto per chiave: se un widget con la chiave del sito di un altro progetto si collega tramite un proxy con chiave valida, la connessione viene rifiutata. Per un altro progetto serve un sottodominio separato con la propria chiave.
- Chiave divulgata: chiunque la conosca può dichiarare indirizzi arbitrari dei visitatori per il Suo progetto. La rimuova, ne crei una nuova e la inserisca.
Risoluzione dei problemi
- HTTP 421 (Misdirected Request): il proxy invia il Suo nome come host anziché quello della destinazione. nginx:
proxy_set_header Hostpiùproxy_ssl_server_name on/proxy_ssl_name; Apache:ProxyPreserveHost Off; Caddy:header_up Hostetls_server_name. - HTTP 502 / errore TLS verso la destinazione: Apache senza
SSLProxyVerifyDepth 5; nginx con percorso errato inproxy_ssl_trusted_certificateo senzaproxy_ssl_server_name on; HTTPS in uscita bloccato. - HTTP 413 nei caricamenti: senza impostazione, nginx accetta solo 1 MB;
client_max_body_size 32mnella sezione/rc_wss/(e almeno lo stesso limite in un bilanciatore a monte). - Nessun upgrade WebSocket:
Upgrade/Connectionnon vengono inoltrati. La chat usa allora il fallback HTTP, ma si collega solo dopo due tentativi WebSocket falliti. - 401 per il modulo offline: una protezione con password precede
/api/offline/. - 403 con una nota sull’origine: manca il dominio del sito (non il sottodominio della chat!) in Origini consentite nel progetto.
- 403 «La risposta non proviene da reactive.chat»: un firewall o una regola di accesso prima della destinazione rifiuta la richiesta.
- Il DNS punta a un indirizzo privato (
10.0.0.0/8,192.168.0.0/16,100.64.0.0/10,fc00::/7…): il record pubblico deve essere pubblico.
Successivo: Trasporto e protocollo · Sicurezza e CSP
अंतिम अपडेट: