Báwo la ràn yín lọ́wọ́?

Ẹ sọ fún wa ní ṣókí ohun tí ó dá lé — a ó dá yín lóhùn nípasẹ̀ ìméèlì.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
Sí ojú-ìbẹ̀rẹ̀

Özel alan adı (birinci taraf)

Widget, sohbet bağlantısı ve çevrimdışı formu web sitenizin bir alt alan adından sunun: gereksinimler, kurulum, nginx, Apache ve Caddy şablonları, sorun giderme.

Özel alan adıyla sohbet, web sitenizin bir alt alan adı üzerinden çalışır; örneğin chat.your-domain.com. Sunucunuz widget isteklerini alır ve ters proxy olarak reactive.chat hizmetine iletir. Bu sayfa, söz konusu sunucuyu yöneten kişiler içindir.

Özel alan adı ne sağlar?

Şunlar alt alan adınız üzerinden çalışır:

Bunun sonucunda:

Ne sağlamaz?

Gereksinimler

Yük dengeleyici veya CDN arkasında proxy, önce ziyaretçinin adresi yerine o cihazın adresini görür. Bu durumda gerçek ziyaretçi adresinin alınmasını yapılandırın: nginx üzerinde real_ip modülü (set_real_ip_from, real_ip_header), Apache üzerinde mod_remoteip (RemoteIPHeader, RemoteIPTrustedProxy), Caddy üzerinde trusted_proxies seçeneği ve {remote_host} yerine {client_ip} yer tutucusu. Kontrolümüz bu durumu saptayamaz: yalnızca geçerli bir adresin ayarlandığını görür, hangi adres olduğunu göremez.

Adım adım kurulum

  1. Sayfayı açın. Hesabınızda projeyi açın. “Yerleştirme” bölümünde Özel alan adı kur bağlantısını bulabilirsiniz.
  2. Ana makine adını girin. “1. Ana makine” altında adı girin, örneğin chat.your-domain.com, ardından kaydedin.
  3. Anahtarı oluşturun. “2. Proxy anahtarı” altında Anahtar oluştur düğmesine tıklayın. Anahtar rcpx_ ile başlar ve yalnızca bir kez gösterilir; yalnızca özetini saklarız. Hemen kopyalayın. Gizlidir ve yalnızca proxy yapılandırmanızda bulunmalıdır; web sayfasına, tarayıcı betiğine veya kod deposuna asla koymayın.
  4. Şablonu ekleyin. “3. Sunucu yapılandırması” altında nginx, Apache ve Caddy için hazır şablonlar vardır. Anahtarı oluşturduktan hemen sonra şablonlarda anahtarınız yer alır; daha sonra bunun yerine __RC_PROXY_KEY__ görünür ve bunu anahtarınızla değiştirmeniz gerekir. Gerekirse sertifika yollarını düzenleyin, yapılandırmayı sınayın (nginx -t veya apachectl configtest) ve sunucuyu yeniden yükleyin.
  5. Kontrol edin. “5. Kontrol” altında Şimdi kontrol et düğmesine tıklayın. Alt alan adınızı dışarıdan çağırır ve beş yolu ayrı ayrı kontrol ederiz (aşağıya bakın). Mesaj oluşturulmaz. Yeni kontrol en erken 10 saniye sonra yapılabilir.
  6. Kodu değiştirin. Yalnızca beş adımın tamamında “Tamam” göründüğünde web sitenizdeki mevcut yerleştirme kodunu “4. Yerleştirme kodu” altındaki kodla değiştirin.

Yeni kod aşağıdaki gibidir; her iki adres de alt alan adınızı gösterir:

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

Widget, dosyalarının konumunu src değerinden, sohbet bağlantısını data-rc-ws-url değerinden alır ve çevrimdışı form adresini bundan türetir. data-rc-locale gibi diğer öznitelikler aynı kalır; bunlar Widget’ı yerleştirme bölümünde açıklanır. Hesap sayfasındaki kod, marka renginizi de içerir.

Beş kontrol adımı

Her adımda “Tamam”, “Hata”, “Not” veya “kontrol edilmedi” görünür. Kontrol ancak beşinin tamamında “Tamam” görünürse başarılıdır; not, başarı sayılmaz. Kontroller yalnızca 443 numaralı port üzerinden HTTPS kullanır, yönlendirmeler izlenmez ve her adıma 5 saniye ayrılır.

  1. Ad çözümleme. Adın bir DNS kaydı bulunmalı ve tüm adresleri genel erişime açık olmalıdır. A veya AAAA kaydı bulunmaması ya da en az bir adresin özel, yerel veya ayrılmış olması bildirilir; bu tür adresleri kontrol etmeyiz. Sonraki adımların tümü burada kontrol edilen adresin aynısına bağlanır.
  2. Alan adınız üzerinden loader.js. https://chat.your-domain.com/loader.js dosyasını yükler ve kendi dosyamızla karşılaştırırız. Bağlantı kurulamaması, yanıt alınamaması veya geçerli sertifika bulunmaması durumunda kalan adımlar atlanır (“kontrol edilmedi”). Proxy dosya yerine yönlendirme döndürürse bu bir hatadır. Dosya bizimkinden farklıysa neden genellikle proxy önbelleği veya / için yanlış hedeftir.
  3. Anahtar ve ziyaretçi adresi. /rc_wss/ altında bir kontrol adresini çağırırız. Sunucumuz geçerli bir anahtar ve geçerli bir ziyaretçi adresi alıp almadığını ve anahtarın hangi projeye ait olduğunu bildirir. Olası hatalar: X-RC-Proxy-Key başlığı eksik; anahtar bilinmiyor (hatalı yazılmış, eskimiş veya kaldırılmış; oluşturulduktan hemen sonra tanınması 30 saniyeyi bulabilir); X-RC-Client-IP başlığı eksik veya geçerli adres içermiyor; anahtar başka bir projeye ait. Anahtar geçerli ancak farklı bir ana makine için kayıtlıysa not gösterilir.
  4. Sohbet bağlantısı (WebSocket). wss://chat.your-domain.com/rc_wss/ üzerinden WebSocket bağlantısı açar, rc.v1 protokolüyle HTTP 101 bekleriz. “WebSocket yükseltmesi yok” şu anlama gelir: proxy, Upgrade ve Connection başlıklarını iletmiyordur.
  5. Çevrimdışı form. https://chat.your-domain.com/api/offline/SITE_KEY adresini GET ile çağırırız. Uç noktamız yalnızca POST kabul ettiğinden HTTP 405 döndürür; böylece mesaj oluşturulmadan isteğin bize ulaştığı anlaşılır. Diğer sonuçlar: kaynak reddedildi (not; sorun giderme bölümüne bakın), proje etkin değil, hedef kimlik doğrulaması gerektiriyor (HTTP 401).

2–5. adımlar HTTP 421 de bildirebilir (Host başlığı; sorun giderme bölümüne bakın). 3. veya 5. adımda “Yanıt reactive.chat hizmetinden gelmiyor” bildiriliyorsa proxy yapılandırmanızda bu yol yanlış hedefi gösteriyordur.

Proxy neleri iletmelidir?

Üç yolun tamamı için:

/rc_wss/ ve /api/offline/ için proxy her istekte ayrıca iki başlık ayarlar:

“Ayarlar” şu demektir: tarayıcının bu adlarla gönderdiği her değer üzerine yazılarak değiştirilir ve bize asla ulaşmaz. Dağıtım ağına giden yolda her iki başlık da temizlenir; anahtar yalnızca sohbet sunucusuna gider.

Alan adınız üzerinden HTTP yedeği

Ziyaretçinin ağı WebSocket bağlantısına izin vermiyorsa widget otomatik olarak HTTP yedeğine geçer. Aynı /rc_wss/ yolunu kullanır ve proxy üzerinde ek kayıt gerektirmez. İki koşul vardır:

Şablonlar

Aşağıdaki şablonlar hesap sayfasındakilerle aynıdır. Hesap sayfası ana makine adınızı, hesabınız için geçerli hedef adresleri ve oluşturulduktan hemen sonra anahtarınızı otomatik doldurur. Bu nedenle şablonu oradan kopyalamanız en iyisidir; buradaki sürümler başvuru içindir. Yer tutucular chat.your-domain.com, SITE_KEY ve __RC_PROXY_KEY__ değerleridir.

nginx

http bağlamına yerleştirilir; örneğin /etc/nginx/conf.d/chat.your-domain.com.conf dosyasına. RHEL ve CentOS üzerinde CA paketi /etc/ssl/certs/ca-certificates.crt yerine /etc/pki/tls/certs/ca-bundle.crt konumundadır.

# 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

Şablon yalnızca 443 numaralı port için VirtualHost içerir. 80 numaralı porttan yönlendirmeyi ve sertifikayı diğer ana makinelerinizdeki gibi ayarlayın. SSLProxyVerifyDepth 5 gereklidir: bu ayar olmadan Apache, hedefin sertifika zincirini yalnızca bir düzey derinliğinde kontrol eder ve bağlantı “Certificate Chain too long” hatasıyla başarısız olur.

# 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 sertifikayı kendisi alır; WebSocket bağlantıları ek ayar gerektirmez. Bir değerle kullanılan header_up, tarayıcının bu adla gönderdiği değeri değiştirir.

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

Proxy anahtarı

Sorun giderme

HTTP 421 (Misdirected Request)

Sunucumuz Host başlığını reddediyordur: proxy, hedef adı yerine kendi adınızı gönderiyordur. Host başlığı ve SNI hedefin adı olmalıdır: nginx üzerinde proxy_set_header Host ile birlikte proxy_ssl_server_name on ve proxy_ssl_name; Apache üzerinde ProxyPreserveHost Off; Caddy üzerinde header_up Host ve tls_server_name.

Hedefe bağlantıda HTTP 502 veya SSL hataları

Proxy bize TLS bağlantısı kuramıyordur veya sertifikaya güvenmiyordur.

Ek yüklerken HTTP 413

Yüklemeler /rc_wss/ üzerinden yapılır. Özel bir ayar olmadan nginx yalnızca 1 MB kabul eder; bu nedenle şablon /rc_wss/ bölümünde client_max_body_size 32m ayarlar. Proxy önünde yük dengeleyici veya CDN varsa en az aynı sınıra sahip olmalıdır.

Yükseltmesiz sohbet bağlantısı

Kontrol, bunun yerine alınan HTTP durumuyla birlikte “WebSocket yükseltmesi yok” bildirir. Sohbet ardından HTTP yedeği üzerinden devam eder, ancak yalnızca iki başarısız WebSocket denemesinden sonra bağlanır.

Çevrimdışı formda HTTP 401 veya 403

DNS özel bir adresi gösteriyor

Adın en az bir adresi özel, yerel veya ayrılmışsa (örneğin 10.0.0.0/8, 192.168.0.0/16, 100.64.0.0/10 veya fc00::/7) kontrol, genel erişime açık olmayan bir adres bildirir. Sık rastlanan nedenler iç DNS kaydı veya iç yük dengeleyicidir. Ziyaretçileriniz de bu adreslere erişemez; genel DNS kaydı genel erişime açık bir adresi göstermelidir.

Elle kontrol

Kontrol adresini 3. adımda gösterildiği gibi kendiniz de çağırabilirsiniz:

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

Doğru kurulumda yanıt şöyledir:

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

Değerler Almanca sözcüklerdir: schluessel (anahtar) için gueltig (geçerli), unbekannt (bilinmiyor) veya fehlt (eksik); client_ip için gesetzt (ayarlanmış), fehlt (eksik) veya ungueltig (geçersiz) kullanılır. site ve host yalnızca geçerli anahtarla yanıtta yer alır. Yanıt hiçbir zaman adres içermez.

Dokümantasyonda daha fazlası

Ayrıntılı bilgi: Özel alan adı ve birinci taraf proxy. Tüm bölümler dokümantasyondadır.

Ìgbà àtúnṣe tó kẹ́yìn: