sgcWebSockets HTTP İstemcisini Sağlamlaştırmak | eSeGeCe Blog

sgcWebSockets HTTP İstemcisini Sağlamlaştırmak

· Bileşenler

Daha önce HTTP sunucusunu sağlamlaştırmak hakkında yazmıştık. Bu yazı hikâyenin diğer yarısıdır. Bir istemci normalde konuşmanın güvenilir tarafı olarak görülür, ama değildir: API anahtarlarınızı gönderir, uzak ana bilgisayarın döndürdüğü her yönlendirmeyi izler, tüm yanıtı belleğe okur ve yanıtın saklamasını istediği her çerezi saklar. Düşmanca ya da sadece ele geçirilmiş bir uç nokta, bu dört davranışın tamamını size karşı çevirebilir.

sgcWebSockets 2026.7, bu deliklerin her birini kapatan bir dizi istemci tarafı anahtar ekliyor. Bunların hepsi varsayılan olarak kapalıdır, dolayısıyla siz devreye almaya karar edene kadar yükseltme mevcut bir uygulamada hiçbir şeyi değiştirmez. Bu seçenekler alt seviye HTTP istemcisinde, hazır her REST ve AI istemcisinde, ayrıca HTTP/2 ve HTTP/3 istemcilerinde kullanılabilir.

Yönlendirmeyi izleyen kimlik bilgileri

Klasik istemci tarafı sızıntısı. Bir API'yi Authorization başlığıyla çağırırsınız, sunucu farklı bir ana bilgisayara işaret eden bir 302 ile yanıt verir ve istemci isteği başlık ve çerezlerle birlikte orada sadakatle tekrarlar. Taşıyıcı belirteciniz, konuşmayı asla amaçlamadığınız bir makineye teslim edilmiş olur. Yönlendirmenin kötü niyetli olması bile gerekmez, meşru ana bilgisayardaki açık bir yönlendirmeyi etkileyebilen bir saldırgan yeterlidir.

StripAuthOnCrossHostRedirect, bir yönlendirme özgün ana bilgisayardan ayrılır ayrılmaz Authorization ve Cookie başlıklarını düşürür. İstek yönlendirmeyi yine de izler, sadece kimlik bilgileriniz olmadan ulaşır.

uses
  sgcHTTP_Client;

var
  oHTTP: TsgcIdHTTP;
begin
  oHTTP := TsgcIdHTTP.Create(nil);
  try
    oHTTP.StripAuthOnCrossHostRedirect := True;

    oHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + vToken;
    vResponse := oHTTP.Get('https://api.example.com/v1/account');
  finally
    oHTTP.Free;
  end;
end;

Düz HTTP'ye düşüren yönlendirmeler

İkinci yönlendirme sorunu. https:// ile başlarsınız, sunucu http:// ile başlayan bir Location ile yanıt verir ve istemci isteği memnuniyetle açık metin olarak tekrarlar. Yol üzerindeki herhangi bir şey artık gövdeyi okuyabilir ve yanıtı yeniden yazabilir. Bu, tarayıcılarda HSTS'in tam olarak önlemek için var olduğu düşürmedir ve şimdiye kadar HTTP istemcisinin bir eşdeğeri yoktu.

NoInsecureRedirect, isteği HTTPS'ten HTTP'ye taşıyacak bir yönlendirmeyi reddeder. Yönlendirme izlenmek yerine reddedilir.

oHTTP.NoInsecureRedirect := True;

// A 302 from https://api.example.com to http://api.example.com
// is now blocked instead of silently downgraded.
vResponse := oHTTP.Get('https://api.example.com/v1/data');

İki yönlendirme anahtarı birbirinden bağımsızdır ve pratikte ikisini de istersiniz. Birincisini açın, farklı bir ana bilgisayara yapılan yönlendirme artık belirtecinizi taşımaz. İkincisini açın, bir yönlendirme artık taşıma güvenliğinizi ortadan kaldıramaz.

Boyut sınırı olmayan yanıtlar

Varsayılan bir HTTP istemcisi sunucunun gönderdiği her şeyi okur. Sunucu on gigabaytlık bir yanıt gövdesi gönderirse, ya da tek bir parçanın iki gigabaytlık uzunluk bildirdiği parçalı bir yanıt gönderirse, istemci bunun için yer ayırmaya çalışır. Bu, kendi işleminize karşı tek satırlık bir hizmet reddidir ve saldırganın bir şeyi kırmasını gerektirmez, sadece isteğinize beklediğinizden daha fazla veriyle yanıt vermesi yeterlidir.

İki sınır bunu kapatır. MaxResponseSize bir yanıt gövdesinin toplam boyutunu sınırlar, MaxChunkSize ise parçalı bir yanıtın tek bir parçasını sınırlar. Her ikisi de varsayılan olan sıfırı "sınırsız" kabul eder, dolayısıyla siz ayarlayana kadar hiçbir şey değişmez. Bir sınır aşıldığında okuma iptal edilir ve bir istisna fırlatılır, istemci tamponu büyütmeye devam etmez.

uses
  sgcHTTP_Client;

var
  oHTTP: TsgcIdHTTP;
begin
  oHTTP := TsgcIdHTTP.Create(nil);
  try
    oHTTP.MaxResponseSize := 10 * 1024 * 1024;  // 10 MB total, 0 = unlimited
    oHTTP.MaxChunkSize    := 1024 * 1024;       // 1 MB per chunk, 0 = unlimited

    vResponse := oHTTP.Get('https://api.example.com/v1/report');
  finally
    oHTTP.Free;
  end;
end;

Uç noktanın gerçekte ne döndürmesi gerektiğini yansıtan bir sayı seçin. Birkaç kilobaytla yanıt veren bir JSON API'yi çağırıyorsanız, birkaç megabaytlık bir sınır cömerttir ve sınırsız bir okumayı yine de sınırlı bir okumaya dönüştürür.

Bütün bir TLD için talep edilen çerezler

Bir yanıt, Domain özniteliğine sahip bir çerez gönderebilir. Kablo biçiminde hiçbir şey onun Domain=com ya da Domain=co.uk talep etmesini engellemez. Bunu kabul eden bir istemci artık çerezi o son ekin altındaki her ana bilgisayara göndermeye razıdır, ki bu maymuncuk dağıtmanın çerez karşılığıdır. Tarayıcılar yıllardır Genel Son Ek Listesi'ni kullanarak bunu reddediyor.

RejectPublicSuffixCookies aynı kuralı bileşene taşır. Alan adı gerçek bir kaydedilebilir alan adı yerine genel bir son ek olan bir çerez atılır. Bunu etkinleştirmenin istemcide çerez yönetimini de açtığını unutmayın, çünkü filtrelediği şey bir çerez kavanozudur.

oHTTP.RejectPublicSuffixCookies := True;

// Set-Cookie: session=abc; Domain=co.uk   ->  rejected
// Set-Cookie: session=abc; Domain=example.co.uk  ->  accepted

2026.7 ayrıca daha önce sessizce yanlış olan çerez ve yönlendirmeyle ilgili iki hatayı da düzeltiyor. Göreli Location başlıkları artık mutlak URL'lere doğru biçimde çözümleniyor, bir 307 veya 308 yönlendirmesi artık belirtimin gerektirdiği gibi istek yöntemini ve gövdesini koruyor ve son kullanma tarihi ayrıştırılamayan bir çerez atılmak yerine oturum çerezi olarak ele alınıyor. Her ikisi de mevcut olduğunda Max-Age hâlâ Expires'a üstün geliyor.

Büyük bir gövde yüklemek: Expect: 100-continue ve parçalı istekler

Her yeni seçenek saldırılarla ilgili değil, bunlardan ikisi bant genişliğini boşa harcamamakla ilgili. Reddedecek bir uç noktaya büyük bir gövde POST ederseniz (hatalı kimlik bilgileri, yanlış içerik türü, zaten tükenmiş bir kota), varsayılan davranış önce tüm gövdeyi kablo üzerinden göndermek ve 401'i sonradan okumaktır.

UseExpect100Continue, istek başlıklarını bir Expect: 100-continue ile gönderir ve sunucunun gövdeyi almaya razı olduğunu söylemesini bekler. Sunucu bunun yerine nihai bir durum kodu ile yanıt verirse, yükü hiç göndermezsiniz. Hiç onay gelmezse gövde yine de gönderilir, dolayısıyla başlığı yok sayan bir sunucu da çalışmaya devam eder.

UseChunkedTransferEncoding tersi durumu kapsar, boyutunu önceden bilmediğiniz bir yükleme. Gövde sabit bir Content-Length ile değil parçalar hâlinde gönderilir, böylece her şeyi önce tamponlamadan bir üreteçten, bir sıkıştırıcıdan veya bir borudan akış olarak gönderebilirsiniz.

uses
  Classes, sgcHTTP_Client;

var
  oHTTP: TsgcIdHTTP;
  oBody: TStream;
begin
  oHTTP := TsgcIdHTTP.Create(nil);
  try
    oHTTP.UseExpect100Continue       := True;   // ask before uploading
    oHTTP.UseChunkedTransferEncoding := True;   // size not known up front

    oBody := TFileStream.Create('large_upload.bin', fmOpenRead or fmShareDenyWrite);
    try
      vResponse := oHTTP.Post('https://api.example.com/v1/upload', oBody);
    finally
      oBody.Free;
    end;
  finally
    oHTTP.Free;
  end;
end;

Hazır API istemcilerindeki aynı anahtarlar

İlginç olan kısım bu özelliklerin nerede yaşadığıdır. Bunlar, kütüphanedeki hazır her REST istemcisinin temel sınıfı olan TsgcHTTPAPI_client üzerinde yeniden açığa çıkarılmıştır. Bu, altındaki alt seviye HTTP nesnesine uzanmadan, zaten kullandığınız bileşen üzerinde doğrudan ayarlayabileceğiniz anlamına gelir.

Bu, AI ve LLM istemcilerini (OpenAI, Anthropic, Gemini, DeepSeek, Grok, Mistral, Ollama), OAuth2 istemcisini, Google Cloud, WhatsApp, AWS SQS ve WebPush'u, ayrıca Amazon AWS ve Google Cloud API birimlerini kapsar.

uses
  sgcHTTP_API_OpenAI;

var
  oOpenAI: TsgcHTTP_API_OpenAI;
begin
  oOpenAI := TsgcHTTP_API_OpenAI.Create(nil);
  try
    oOpenAI.StripAuthOnCrossHostRedirect := True;   // never leak the API key
    oOpenAI.NoInsecureRedirect           := True;   // never fall back to http
    oOpenAI.RejectPublicSuffixCookies    := True;
    oOpenAI.MaxResponseSize              := 32 * 1024 * 1024;
    oOpenAI.MaxChunkSize                 := 1024 * 1024;

    // ... use the client as usual
  finally
    oOpenAI.Free;
  end;
end;

Bir LLM sağlayıcısına gönderilen bir API anahtarı, sağlayıcının alan adı dışına bir yönlendirmeyi izlemesini kesinlikle istemeyeceğiniz türden bir kimlik bilgisidir, dolayısıyla burası anahtarları açmanın size hiçbir maliyeti olmadığı ve çok şey kazandırdığı yerdir.

HTTP/2 ve HTTP/3

HTTP/2 istemcisi aynı korumaları seçenek nesnesi TsgcWSHTTP2Client_Options aracılığıyla alır ve HTTP/3 istemcisi yanıt sınırını doğrudan açığa çıkarır.

uses
  sgcHTTP;

var
  oHTTP2: TsgcHTTP2Client;
begin
  oHTTP2 := TsgcHTTP2Client.Create(nil);
  try
    oHTTP2.HTTP2Options.StripAuthOnCrossHostRedirect := True;
    oHTTP2.HTTP2Options.NoInsecureRedirect           := True;
    oHTTP2.HTTP2Options.MaxResponseSize              := 10 * 1024 * 1024;
  finally
    oHTTP2.Free;
  end;
end;

// HTTP/3
oHTTP3.MaxResponseSize := 10 * 1024 * 1024;

Güvenli bir TLS temeli için tek satır

TLS katmanı hiçbir şeyi doğrulamıyorsa yukarıdakilerin hiçbiri işe yaramaz. sgcWebSockets 2026.7 bunun için bir hazır ayar ekliyor. Kütüphanedeki her TLS seçenek nesnesi, WebSocket ve HTTP bileşenlerinde aynı şekilde, TsgcTLSPreset türünde bir Preset özelliği yayımlar. Varsayılan değeri, elle yapılandırdığınız her şeyi koruyan tlspCustom'dur.

Bunu tlspSecureDefaults olarak ayarlamak, tek satırda sertifika doğrulamasını, TLS 1.2 veya üstünü ve ana bilgisayar adı doğrulamasını açar.

uses
  sgcWebSocket_Types;

begin
  oHTTP.TLSOptions.Preset := tlspSecureDefaults;
  // certificate verification on, TLS 1.2+, hostname verification on
end;

Hazır ayarı yönlendirme anahtarları ve yanıt sınırlarıyla birleştirin, elinizde kiminle konuştuğunu doğrulayan, düşürmeyi reddeden, kimlik bilgilerini üçüncü bir tarafa vermeyen ve sınırsız bellek ayırmaya zorlanamayan bir istemci olur.

.NET

Yönetilen sürüm, aynı korumaları 2026.7 ile birlikte sunuyor. Yönlendirmede kimlik bilgisi kaldırma, HTTPS düşürme engeli, parça başına ve toplam yanıt sınırları, genel son ek çerezlerinin reddedilmesi, Expect: 100-continue ve parçalı istek gövdelerinin hepsi orada, HTTP/2 istemci kümesi dâhil. Aynı isimler, C# yazım biçimiyle.

client.StripAuthOnCrossHostRedirect = true;
client.NoInsecureRedirect           = true;
client.RejectPublicSuffixCookies    = true;
client.MaxResponseSize              = 10 * 1024 * 1024;
client.MaxChunkSize                 = 1024 * 1024;

Kullanılabilirlik

HTTP istemcisi sağlamlaştırma seçenekleri, sgcWebSockets 2026.7'de Delphi 7'den 13'e kadar ve C++Builder'da (Win32/Win64, Linux64, macOS, Android ve iOS), ayrıca .NET sürümünde kullanılabilir. Burada anlatılan her şey isteğe bağlıdır ve varsayılan olarak kapalıdır, dolayısıyla yükseltme doğrudan yerine geçer.

Etkin aboneliği olan müşteriler yeni derlemeyi müşteri alanından indirebilir. Deneme kullanıcıları güncellenmiş kurulum dosyasını esegece.com/products/websockets/download adresinden alabilir.

Sorularınız, geri bildirimleriniz veya uygulamanızın bu anahtarlardan hangilerini açması gerektiğine karar vermek için yardıma mı ihtiyacınız var? Bize ulaşın, kodu yazan kişilerden yanıt alacaksınız.