Eigen domein en first-party proxy
Bied widgetbestanden, chatverbinding, offlineformulier en Smart Answer aan via een subdomein van uw website, met proxysleutel, echt bezoekersadres en sjablonen voor nginx, Apache en Caddy.
Met een eigen domein loopt de chat via een subdomein van uw website, bijvoorbeeld chat.your-company.com. Uw server ontvangt de verzoeken van de widget en geeft ze als reverse proxy door aan reactive.chat. Deze pagina is voor degene die die server beheert. De korte versie voor redacteuren staat onder Eigen domein (first-party).
Wat via het subdomein loopt
- Widgetbestanden —
loader.js, de daarna geladen core (core.<hash>.js) en de overige modules. - Chatverbinding — de WebSocket onder
/rc_wss/, inclusief de HTTP-fallback onder/rc_wss/h/en bestandsuploads onder/rc_wss/upload/. - Offlineformulier —
POST /api/offline/<SITE_KEY>, wanneer geen chatverbinding tot stand komt. - Smart Answer —
/api/suche/, als u het AI-antwoord in uw websitezoekfunctie gebruikt.
Wat het oplevert:
- Geen verzoeken naar domeinen van derden. Voor deze routes communiceren de browsers van uw bezoekers alleen met uw subdomein.
- Eén adres in uw Content Security Policy.
script-srcenconnect-srcvermelden uw subdomein in plaats van de adressen van reactive.chat (details onder Beveiliging en CSP). - Het echte bezoekersadres komt aan. Uw proxy geeft dit door in een aparte header, beveiligd met een geheime sleutel. Begrenzing en blokkering tellen dan per bezoeker in plaats van per proxy.
Wat het niet is:
- Geen zelfhosting. Gesprekken, bijlagen en instellingen worden nog steeds door reactive.chat verwerkt en opgeslagen.
- Geen uitspraak over toestemming. Een eigen domein verandert niet wie de gegevens verwerkt.
- Uw proxy ziet het verkeer. TLS eindigt bij uw proxy; leg daar geen request bodies vast en houd
/rc_wss/h/buiten het toegangslogboek (deze verzoeken bevatten een kortlevend verbindingstoken in de query).
Vereisten
- Een server of reverse proxy die openbaar via HTTPS op poort 443 bereikbaar is en uitgaande HTTPS-verbindingen kan maken. Er zijn sjablonen voor nginx (met de ssl-module), Apache 2.4.47 of nieuwer en Caddy 2.
- Voor Apache de modules
mod_ssl,mod_proxy,mod_proxy_http,mod_proxy_wstunnel,mod_headersenmod_setenvif. - Een subdomein uitsluitend voor de chat. De chat heeft de hele host nodig; een pad zoals
www.your-company.com/chat/werkt niet. Voer alleen de naam in — zonderhttps://, poort of pad. Niet toegestaan: IP-adressen, interne extensies zoals.local,.lan,.internalen namen onderreactive.chat. - Hetzelfde domein als de website. De chat is alleen first-party als het subdomein hoort bij het domein van de website waarop de chat is ingesloten.
- DNS (A en/of AAAA) met uitsluitend openbare adressen.
- Een TLS-certificaat voor het subdomein (de nginx-/Apache-sjablonen verwachten de certbot-paden; Caddy haalt het zelf op).
- Toestemming om het project te bewerken.
Instellen
- Open in uw account het project, gedeelte Insluiten → Eigen domein instellen.
- Voer onder 1. Host de naam in, bijvoorbeeld
chat.your-company.com, en sla op. - Klik onder 2. Proxysleutel op Sleutel aanmaken. De sleutel begint met
rcpx_en wordt precies één keer getoond; alleen een hash wordt opgeslagen. Hij hoort uitsluitend in de proxyconfiguratie — nooit op een webpagina, in een browserscript of in een repository. - Neem onder 3. Serverconfiguratie het sjabloon voor uw server over. Direct na het aanmaken bevat het de sleutel; later toont het
__RC_PROXY_KEY__. Test de configuratie (nginx -tofapachectl configtest) en herlaad de server. - Klik onder 5. Controleren op Nu controleren (maximaal elke 10 seconden). Er wordt geen bericht aangemaakt.
- Vervang pas als alle vijf controlestappen “OK” tonen het insluitfragment door dat uit 4. Insluitcode:
<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>
De widget haalt de locatie van zijn bestanden uit src, de chatverbinding uit data-rc-ws-url en leidt daarvan de adressen van het offlineformulier, uploads en de HTTP-fallback af. Alle andere attributen blijven ongewijzigd (Referentie van de scripttag).
Wat de proxy moet doorsturen
/rc_wss/→ chatserverhttps://ws.reactive.chat/rc_wss/, met WebSocket-upgrade, een lange time-out (sjablonen: 3600 s), zonder buffering en een bodylimiet van minstens 32 MB (uploads)./api/offline/→https://ws.reactive.chat/api/offline/(kleine body, sjabloon: 32 kB, 30 s)./api/suche/→https://ws.reactive.chat/api/suche/, zonder buffering (het antwoord is een Server-Sent Events-stream), body tot 8 kB, 120 s.- al het overige → distributienetwerk
https://cdn.reactive.chat/.
Voor alle routes:
- Host-header en SNI zijn de naam van het doel, niet uw subdomein. Een onbekende host krijgt HTTP 421 als antwoord.
- Het certificaat van het doel wordt geverifieerd.
- Geen cookies, geen toegangsgegevens.
CookieenAuthorizationvan de browser worden niet doorgegeven enSet-Cookiewordt niet teruggestuurd. - Geen omleidingen. Een cache is niet nodig; als u er een instelt, houd de cachetijd voor
loader.jskort — de bestandsnaam bevat geen versienummer (die van de core wel, zie Architectuur).
Voor /rc_wss/, /api/offline/ en /api/suche/ stelt de proxy bij elk verzoek twee headers in:
- X-RC-Proxy-Key — uw sleutel
rcpx_…. - X-RC-Client-IP — het bezoekersadres zoals uw proxy dat ziet.
“Instellen” betekent: alles wat een browser onder deze namen verstuurt, wordt overschreven. Op de route naar het distributienetwerk worden beide verwijderd.
Achter een loadbalancer of CDN ziet uw proxy eerst het adres van dat apparaat. Stel dan het overnemen van het echte adres in: nginx real_ip (set_real_ip_from, real_ip_header), Apache mod_remoteip (RemoteIPHeader, RemoteIPTrustedProxy), Caddy trusted_proxies en {client_ip} in plaats van {remote_host}. De controle herkent dit geval niet — ze ziet alleen dat een geldig adres is ingesteld.
nginx-sjabloon
De accountpagina vult host, doeladressen en sleutel al in — kopieer het sjabloon het beste daarvandaan. De versie hier dient als referentie; de tijdelijke aanduidingen zijn chat.your-company.com, SITE_KEY en __RC_PROXY_KEY__. Op RHEL/CentOS staat de CA-bundel 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;
}
}
Apache-sjabloon (2.4.47 of nieuwer)
Alleen de VirtualHost voor poort 443; stel de omleiding vanaf poort 80 en het certificaat in zoals voor uw andere hosts. SSLProxyVerifyDepth 5 is vereist — anders controleert Apache de keten van het doel slechts één niveau diep en meldt “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 vóór 2.4.47 ondersteunt upgrade=websocket niet. Vervang dan de eerste ProxyPass-regel door:
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 2-sjabloon
header_up met een waarde vervangt alles wat de browser onder die naam verstuurt. Als u toegangslogboeken inschakelt, sluit dan /rc_wss/h/* uit (log_skip, vóór 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
}
}
}
}
De vijf controlestappen
Elke stap toont “OK”, “Fout”, “Opmerking” of “niet gecontroleerd”. De controle is alleen met vijfmaal “OK” geslaagd. Er wordt uitsluitend via HTTPS op poort 443 gecontroleerd, zonder omleidingen, 5 seconden per stap.
- Naamomzetting — A/AAAA aanwezig, alle adressen openbaar. Alle volgende stappen verbinden met precies dit adres.
- loader.js via uw domein — het bestand wordt geladen en met het onze vergeleken. Zonder verbinding, antwoord of geldig certificaat worden de overige stappen overgeslagen. Een omleiding is een fout; een afwijkend bestand wijst op een cache of een verkeerd doel voor
/. - Sleutel en bezoekersadres — aanroep van
/rc_wss/eigene-domain-probe. Mogelijke fouten:X-RC-Proxy-Keyontbreekt; sleutel onbekend (direct na aanmaken maximaal 30 seconden vertraging);X-RC-Client-IPontbreekt of is ongeldig; de sleutel hoort bij een ander project. Een opmerking als de sleutel geldig is maar voor een andere host geregistreerd staat. - WebSocket —
wss://chat.your-company.com/rc_wss/moet antwoorden met HTTP 101 en subprotocolrc.v1. - Offlineformulier —
GET /api/offline/SITE_KEYmoet met 405 antwoorden (het endpoint accepteert alleen POST; zo wordt geen bericht aangemaakt).
U kunt het controleadres uit stap 3 zelf benaderen:
curl -s https://chat.your-company.com/rc_wss/eigene-domain-probe
Bij juiste inrichting:
{"rc":"eigene-domain-probe","v":1,"schluessel":"gueltig","client_ip":"gesetzt","site":"SITE_KEY","host":"chat.your-company.com"}
- schluessel —
gueltig(geldig),unbekannt(onbekend) offehlt(ontbreekt). - client_ip —
gesetzt(ingesteld),fehlt(ontbreekt) ofungueltig(ongeldig). - site, host — alleen met een geldige sleutel. Het antwoord geeft nooit een adres terug.
De proxysleutel
- Vernieuwen: Nieuwe sleutel aanmaken geeft direct een nieuwe sleutel uit; de vorige blijft 24 uur geldig. Er zijn maximaal twee geldige sleutels — bij opnieuw vernieuwen binnen 24 uur wordt de oudste direct ongeldig.
- Verwijderen: Sleutel verwijderen maakt de sleutel direct ongeldig (inclusief een oude sleutel uit een lopende vernieuwing). Eigen domein verwijderen verwijdert host en sleutel samen — zet eerst het fragment op uw website terug.
- Ontbrekende of onjuiste sleutel: de chat blijft werken, maar de twee headers worden genegeerd. Alle bezoekers verschijnen dan met het adres van uw proxy — en omdat de misbruikbeveiliging per adres telt, kan deze uw hele proxy en daarmee alle bezoekers tegelijk begrenzen.
- Eén project per sleutel: als een widget met de sitesleutel van een ander project via een proxy met een geldige sleutel verbinding maakt, wordt die verbinding afgewezen. Voor een volgend project hebt u een apart subdomein met eigen sleutel nodig.
- Sleutel uitgelekt: iedereen die hem kent, kan willekeurige bezoekersadressen voor uw project opgeven. Verwijder hem, maak een nieuwe aan en voer die in.
Problemen oplossen
- HTTP 421 (Misdirected Request): de proxy stuurt uw naam als host in plaats van de doelnaam. nginx:
proxy_set_header Hostplusproxy_ssl_server_name on/proxy_ssl_name; Apache:ProxyPreserveHost Off; Caddy:header_up Hostentls_server_name. - HTTP 502 / TLS-fout richting het doel: Apache zonder
SSLProxyVerifyDepth 5; nginx met een verkeerd pad inproxy_ssl_trusted_certificateof zonderproxy_ssl_server_name on; uitgaand HTTPS geblokkeerd. - HTTP 413 bij uploaden: zonder instelling accepteert nginx slechts 1 MB;
client_max_body_size 32min het gedeelte voor/rc_wss/(en minstens dezelfde limiet bij een daarvoor geplaatste loadbalancer). - Geen WebSocket-upgrade:
Upgrade/Connectionworden niet doorgegeven. De chat werkt dan via de HTTP-fallback, maar maakt pas na twee mislukte WebSocket-pogingen verbinding. - 401 voor het offlineformulier: er staat wachtwoordbeveiliging vóór
/api/offline/. - 403 met een opmerking over de origin: het websitedomein (niet het chatsubdomein!) ontbreekt onder Toegestane origins in het project.
- 403 “Het antwoord komt niet van reactive.chat”: een firewall of toegangsregel vóór het doel weigert het verzoek.
- DNS verwijst naar een privéadres (
10.0.0.0/8,192.168.0.0/16,100.64.0.0/10,fc00::/7…): het openbare record moet openbaar zijn.
Volgende: Transport en protocol · Beveiliging en CSP
Laatst bijgewerkt: