Egen domän och förstapartsproxy
Så distribuerar du widgetfiler, chattanslutning, offlineformulär och Smart Answer via en underdomän till din webbplats – med proxynyckel, besökarens riktiga adress och färdiga mallar för nginx, Apache och Caddy.
Med egen domän går chatten via en underdomän till din webbplats, till exempel chat.your-company.com. Din server tar emot widgetens anrop och skickar dem vidare till reactive.chat som omvänd proxy. Den här sidan är till för den som driver servern. Den korta versionen för redaktörer finns under Egen domän (förstapart).
Vad som går via underdomänen
- Widgetfiler –
loader.js, kärnan som laddas därefter (core.<hash>.js) och övriga moduler. - Chattanslutning – WebSocket under
/rc_wss/, inklusive HTTP-reserven under/rc_wss/h/och filuppladdningar under/rc_wss/upload/. - Offlineformulär –
POST /api/offline/<SITE_KEY>, när ingen chattanslutning kan upprättas. - Smart Answer –
/api/suche/, om du använder AI-svar i webbplatssökningen.
Vad du får:
- Inga anrop till tredjepartsdomäner. För dessa vägar kommunicerar besökarnas webbläsare bara med din underdomän.
- En adress i din Content Security Policy.
script-srcochconnect-srcanger din underdomän i stället för adresserna till reactive.chat (mer under Säkerhet och CSP). - Besökarens riktiga adress kommer fram. Din proxy skickar den i ett särskilt huvud, säkrat med en hemlig nyckel. Begränsning och blockering räknas då per besökare i stället för per proxy.
Vad det inte är:
- Ingen egen drift av tjänsten. Konversationer, bilagor och inställningar behandlas och lagras fortfarande av reactive.chat.
- Inget ställningstagande om samtycke. Egen domän ändrar inte vem som behandlar uppgifterna.
- Din proxy ser trafiken. TLS avslutas vid din proxy; logga inte anropens meddelandekroppar där och undanta
/rc_wss/h/från åtkomstloggen (dessa anrop har en kortlivad anslutningstoken i frågesträngen).
Förutsättningar
- En server eller omvänd proxy som är offentligt tillgänglig via HTTPS på port 443 och kan upprätta utgående HTTPS-anslutningar. Det finns mallar för nginx (med ssl-modulen), Apache 2.4.47 eller senare och Caddy 2.
- För Apache, modulerna
mod_ssl,mod_proxy,mod_proxy_http,mod_proxy_wstunnel,mod_headersochmod_setenvif. - En underdomän som bara används för chatten. Chatten behöver hela värden; en sökväg som
www.your-company.com/chat/fungerar inte. Ange bara namnet – utanhttps://, port eller sökväg. Inte tillåtet: IP-adresser, interna ändelser som.local,.lan,.internaloch namn underreactive.chat. - Samma domän som webbplatsen. Chatten är förstapart bara om underdomänen hör till domänen för den webbplats där den bäddas in.
- DNS (A och/eller AAAA) med enbart offentliga adresser.
- Ett TLS-certifikat för underdomänen (nginx-/Apache-mallarna förutsätter certbot-sökvägarna; Caddy hämtar det självt).
- Behörighet att redigera projektet.
Konfiguration
- Öppna projektet i kontot, avsnittet Inbäddning → Ställ in egen domän.
- Under 1. Värd anger du namnet, till exempel
chat.your-company.com, och sparar. - Under 2. Proxynyckel klickar du på Skapa nyckel. Nyckeln börjar med
rcpx_och visas exakt en gång; bara en hash sparas. Den hör uteslutande hemma i proxykonfigurationen – aldrig på en webbsida, i ett webbläsarskript eller i ett kodarkiv. - Under 3. Serverkonfiguration hämtar du mallen för din server. Direkt efter att nyckeln skapats innehåller den nyckeln; senare visas
__RC_PROXY_KEY__. Testa konfigurationen (nginx -tellerapachectl configtest) och ladda om servern. - Under 5. Kontroll klickar du på Kontrollera nu (högst var 10:e sekund). Inget meddelande skapas.
- Först när alla fem kontrollsteg visar ”OK” ersätter du inbäddningskoden med den från 4. Inbäddningskod:
<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>
Widgeten hämtar platsen för sina filer från src, chattanslutningen från data-rc-ws-url och härleder adresserna för offlineformulär, uppladdningar och HTTP-reserv från den. Alla andra attribut förblir som de är (Referens för skripttaggen).
Vad proxyn måste vidarebefordra
/rc_wss/→ chattserverhttps://ws.reactive.chat/rc_wss/, med WebSocket-uppgradering, lång tidsgräns (mallar: 3 600 s), utan buffring och med en gräns för meddelandekroppen på minst 32 MB (uppladdningar)./api/offline/→https://ws.reactive.chat/api/offline/(liten meddelandekropp, mall: 32 kB, 30 s)./api/suche/→https://ws.reactive.chat/api/suche/, utan buffring (svaret är en Server-Sent Events-ström), meddelandekropp upp till 8 kB, 120 s.- allt annat → leveransnätverket
https://cdn.reactive.chat/.
För alla vägar:
- Host-huvudet och SNI är målets namn, inte din underdomän. En okänd värd besvaras med HTTP 421.
- Målets certifikat verifieras.
- Inga cookies, inga inloggningsuppgifter. Webbläsarens
CookieochAuthorizationskickas inte vidare, ochSet-Cookiereturneras inte. - Inga omdirigeringar. En cache krävs inte; om du använder en, håll lagringstiden kort för
loader.js– filen har inget versionsnummer i namnet (det har kärnan, se Arkitektur).
För /rc_wss/, /api/offline/ och /api/suche/ sätter proxyn två huvuden i varje anrop:
- X-RC-Proxy-Key – din nyckel
rcpx_…. - X-RC-Client-IP – besökarens adress så som proxyn ser den.
”Sätter” betyder: allt som en webbläsare skickar under dessa namn skrivs över. På vägen till leveransnätverket tas båda bort.
Bakom en lastbalanserare eller CDN ser proxyn först den enhetens adress. Ställ då in att den riktiga adressen hämtas: nginx real_ip (set_real_ip_from, real_ip_header), Apache mod_remoteip (RemoteIPHeader, RemoteIPTrustedProxy), Caddy trusted_proxies och {client_ip} i stället för {remote_host}. Kontrollen upptäcker inte detta fall – den ser bara att en giltig adress har angetts.
nginx-mall
Kontosidan fyller redan i värd, måladresser och nyckel – kopiera helst mallen därifrån. Versionen här är en referens; platshållarna är chat.your-company.com, SITE_KEY och __RC_PROXY_KEY__. På RHEL/CentOS finns CA-paketet under /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-mall (2.4.47 eller senare)
Bara VirtualHost för port 443; ställ in omdirigeringen från port 80 och certifikatet som för dina andra värdar. SSLProxyVerifyDepth 5 krävs – annars kontrollerar Apache målets certifikatkedja bara en nivå djupt och rapporterar ”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 före 2.4.47 känner inte till upgrade=websocket. Ersätt då den första ProxyPass-raden med:
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-mall
header_up med ett värde ersätter allt webbläsaren skickade under detta namn. Om du aktiverar åtkomstloggar, undanta /rc_wss/h/* (log_skip, före 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 fem kontrollstegen
Varje steg visar ”OK”, ”Fel”, ”Information” eller ”inte kontrollerat”. Kontrollen är godkänd först när alla fem visar ”OK”. Kontrollerna använder bara HTTPS på port 443, utan omdirigeringar, 5 sekunder per steg.
- Namnuppslagning – A/AAAA finns, alla adresser är offentliga. Alla efterföljande steg ansluter till exakt denna adress.
- loader.js via din domän – filen laddas och jämförs med vår. Utan anslutning, svar eller giltigt certifikat hoppas de återstående stegen över. En omdirigering är ett fel; en avvikande fil tyder på en cache eller ett felaktigt mål för
/. - Nyckel och besökaradress – anrop till
/rc_wss/eigene-domain-probe. Möjliga fel:X-RC-Proxy-Keysaknas; nyckeln är okänd (direkt efter att den skapats kan det ta upp till 30 sekunder);X-RC-Client-IPsaknas eller är ogiltig; nyckeln hör till ett annat projekt. En informationsnotis om nyckeln är giltig men registrerad för en annan värd. - WebSocket –
wss://chat.your-company.com/rc_wss/måste svara med HTTP 101 och underprotokolletrc.v1. - Offlineformulär –
GET /api/offline/SITE_KEYmåste svara med 405 (slutpunkten tar bara emot POST; på så sätt skapas inget meddelande).
Du kan själv anropa kontrolladressen från steg 3:
curl -s https://chat.your-company.com/rc_wss/eigene-domain-probe
Vid korrekt konfiguration:
{"rc":"eigene-domain-probe","v":1,"schluessel":"gueltig","client_ip":"gesetzt","site":"SITE_KEY","host":"chat.your-company.com"}
- schluessel –
gueltig(giltig),unbekannt(okänd) ellerfehlt(saknas). - client_ip –
gesetzt(angiven),fehlt(saknas) ellerungueltig(ogiltig). - site, host – bara med en giltig nyckel. Svaret returnerar aldrig en adress.
Proxynyckeln
- Rotation: Skapa ny nyckel utfärdar genast en ny; den föregående är giltig i 24 timmar. Högst två nycklar är giltiga – en ny rotation inom de 24 timmarna gör den äldsta omedelbart ogiltig.
- Borttagning: Ta bort nyckel gör den omedelbart ogiltig (även en äldre nyckel från en pågående rotation). Ta bort egen domän tar bort värd och nyckel tillsammans – byt först tillbaka kodsnutten på din webbplats.
- Saknad eller felaktig nyckel: chatten fortsätter fungera, men de två huvudena ignoreras. Alla besökare visas då med proxyns adress – och eftersom skyddet mot missbruk räknar per adress kan det begränsa hela proxyn och därmed alla besökare samtidigt.
- Ett projekt per nyckel: om en widget med ett annat projekts webbplatsnyckel ansluter via en proxy med giltig nyckel avvisas anslutningen. För ytterligare ett projekt behöver du en separat underdomän med egen nyckel.
- Nyckeln har läckt: alla som känner till den kan ange godtyckliga besökaradresser för ditt projekt. Ta bort den, skapa en ny och ange den.
Felsökning
- HTTP 421 (Misdirected Request): proxyn skickar ditt namn som värd i stället för målets namn. nginx:
proxy_set_header Hosttillsammans medproxy_ssl_server_name on/proxy_ssl_name; Apache:ProxyPreserveHost Off; Caddy:header_up Hostochtls_server_name. - HTTP 502 / TLS-fel mot målet: Apache utan
SSLProxyVerifyDepth 5; nginx med fel sökväg iproxy_ssl_trusted_certificateeller utanproxy_ssl_server_name on; utgående HTTPS blockerat. - HTTP 413 vid uppladdning: utan inställning tar nginx bara emot 1 MB;
client_max_body_size 32mi avsnittet/rc_wss/(och minst samma gräns i en framförliggande lastbalanserare). - Ingen WebSocket-uppgradering:
Upgrade/Connectionskickas inte vidare. Chatten går då via HTTP-reserven, men ansluter först efter två misslyckade WebSocket-försök. - 401 för offlineformuläret: lösenordsskydd ligger framför
/api/offline/. - 403 med information om ursprunget: webbplatsens domän (inte chattens underdomän!) saknas under Tillåtna ursprung i projektet.
- 403 ”Svaret kommer inte från reactive.chat”: en brandvägg eller åtkomstregel framför målet avvisar anropet.
- DNS pekar på en privat adress (
10.0.0.0/8,192.168.0.0/16,100.64.0.0/10,fc00::/7…): den offentliga posten måste vara offentlig.
Nästa: Transport och protokoll · Säkerhet och CSP
Síðast uppfært: