sgcIndy 2026.6: TLS, TCP ve HTTP için Sunucu Güvenliği Sıkılaştırması

· Sürümler

sgcIndy 2026.6 dikkatini sunucu tarafına çeviriyor. Bu sürüm, TLS, TCP ve HTTP sunucu bileşenlerine bir dizi isteğe bağlı güvenlik sıkılaştırması seçeneği ekleyerek, altta yatan Indy kodunun hiçbir zaman karşı koymadığı bilinen birçok saldırı sınıfını kapatır: açık başarısız olan bir sertifika doğrulama geri çağrımı, yavaş damlayan Slowloris bağlantıları, sınırsız istek gövdeleri ve başlıkları ve HTTP istek kaçakçılığı. Ayrıca ilk ML-KEM-768 post-kuantum anahtar kapsülleme ilkellerini de sunar.

Her yeni koruma, önceki davranışı varsayılan olarak alır; bu nedenle siz açana kadar mevcut uygulamalar etkilenmez. Bu yazı, kullanıma hazır Delphi parçacıklarıyla her birini tek tek inceliyor.

Sıkılaştırılmış TLS sunucuları

En önemli düzeltme, OpenSSL eş doğrulama geri çağrımındadır. Standart Indy'de doğrulama geri çağrımı açık başarısız olabilir: bir sunucu istemci sertifikası istediğinde, nihai karar kullanıcı geri çağrımı tarafından yönlendiriliyor ve OpenSSL'in kendi kararını yok sayıyordu; dolayısıyla başarı döndüren bir geri çağrım süresi dolmuş, kendinden imzalı veya güvenilmeyen bir sertifikayı kabul ediyordu. Yeni TIdSSLOptions.StrictVerify bayrağı OpenSSL sonucunu zorunlu kılar; böylece özel bir OnVerifyPeer işleyicisi kararı yalnızca daha da kısıtlayabilir, asla gevşetemez.

Üç bayrak daha, başlıkların zaten bildirdiği ancak kütüphanenin hiçbir zaman uygulamadığı OpenSSL seçeneklerini devreye sokar: DisableCompression CRIME'ı azaltır, DisableRenegotiation OpenSSL 1.1.0h ve sonrasında istemci tarafından başlatılan yeniden anlaşmayı (CPU açısından asimetrik bir DoS) engeller ve ServerCipherPreference, anlaşmada istemcinin değil sunucunun şifre sırasının kazanmasını sağlar.

uses
  IdHTTPServer, IdSSLOpenSSL;

var
  oServer: TIdHTTPServer;
  oSSL: TIdServerIOHandlerSSLOpenSSL;
begin
  oServer := TIdHTTPServer.Create(nil);
  oSSL := TIdServerIOHandlerSSLOpenSSL.Create(oServer);

  oSSL.SSLOptions.CertFile    := 'server.pem';
  oSSL.SSLOptions.KeyFile     := 'server.key';
  oSSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_3];

  // opt-in hardening, every flag defaults to False
  oSSL.SSLOptions.StrictVerify           := True;  // enforce the OpenSSL verdict
  oSSL.SSLOptions.DisableCompression     := True;  // CRIME
  oSSL.SSLOptions.DisableRenegotiation   := True;  // renegotiation DoS
  oSSL.SSLOptions.ServerCipherPreference := True;  // server picks the cipher

  oServer.IOHandler := oSSL;
  oServer.Active := True;
end;

Bilinmeyen bir istemci sertifikasını gerçekten reddeden karşılıklı TLS istediğinizde, VerifyMode değerini StrictVerify ile birlikte [sslvrfPeer, sslvrfFailIfNoPeerCert] olarak ayarlayın.

Slowloris'i durdurmak

Bir Slowloris istemcisi birçok bağlantı açar ve her bir çalışan iş parçacığını meşgul tutmak için isteği asla tamamlamadan bir seferde bir bayt damlatır. Doğal savunma bir okuma zaman aşımı gibi görünür, ancak bilinmesi gereken bir incelik vardır: Indy'nin ReadTimeout değeri bir hareketsizlik zaman aşımıdır. Gelen her bayt bunu sıfırlar; bu nedenle birkaç saniyede bir bayt gönderen bir istemci bağlantıyı sonsuza kadar canlı tutar.

2026.6, SetReadDeadline aracılığıyla TIdIOHandler üzerine gerçek bir toplam okuma son tarihi ekler. Her okumada kontrol edilir; bu nedenle baytlar damlamaya devam ederken bile devreye girer. HTTP sunucusu bunu, istek satırını ve başlıklarını almak için geçen süreyi sınırlayan ve her keep-alive isteğinde sıfırlanan yeni RequestReadTimeout özelliği aracılığıyla otomatik olarak devreye sokar.

uses
  IdHTTPServer;

var
  oServer: TIdHTTPServer;
begin
  oServer := TIdHTTPServer.Create(nil);
  oServer.DefaultPort := 8080;

  // close any client that has not finished sending the request
  // line and headers within 5 seconds, even if it keeps dripping bytes
  oServer.RequestReadTimeout := 5000;

  oServer.Active := True;
end;

Özel bir TIdTCPServer için aynı son tarihi okuma döngünüzün çevresinde elle uygulayabilirsiniz. Temizlemek için 0 geçirin.

procedure TForm1.ServerExecute(AContext: TIdContext);
var
  vLine: string;
begin
  // bound the whole request to 5 seconds of total read time
  AContext.Connection.IOHandler.SetReadDeadline(5000);
  try
    vLine := AContext.Connection.IOHandler.ReadLn;
    // ... handle the request ...
  finally
    AContext.Connection.IOHandler.SetReadDeadline(0);
  end;
end;

HTTP sunucuları için istek sınırları

Bir istemcinin bildirdiği her şeyi okuyan bir HTTP sunucusu, kolay bir bellek tükenmesi hedefidir. Tek bir istek Content-Length: 2000000000 ilan edebilir ve sunucu iki gigabaytı arabelleğe almaya çalışır, ya da sonsuz bir parçalı (chunked) gövde akıtır, ya da milyonlarca başlık baytı gönderir. 2026.6, TIdCustomHTTPServer'a üç sınır ve bir kaçakçılık kontrolü ekler.

MaxRequestBodySize, Content-Length değerini ve toplam parçalı gövdeyi sınırlar ve aşıldığında 413 Payload Too Large yanıtı verir. MaxHeaderTotalSize, toplam başlık baytlarını sınırlar ve 431 Request Header Fields Too Large yanıtı verir. StrictRequestParsing, kasıtlı olarak belirsiz olan istekleri reddeder; örneğin hem Content-Length hem de Transfer-Encoding: chunked taşıyan bir mesaj (klasik istek kaçakçılığı vektörü) veya negatif bir parça boyutu için 400 Bad Request yanıtı verir. Parçalı sonek başlık döngüsü artık sınırlandırılmıştır; böylece bir saldırgan, sonsuz bir sonek satırı akışıyla bir bağlantıyı artık açık tutamaz.

oServer.MaxRequestBodySize := 10 * 1024 * 1024;  // 10 MB, else 413
oServer.MaxHeaderTotalSize := 64 * 1024;         // 64 KB, else 431
oServer.StrictRequestParsing := True;            // reject CL+TE smuggling, else 400

Ham TCP katmanında TIdIOHandler.MaxInputBufferSize, IOHandler üzerine kurulu herhangi bir protokol için birikimli giriş arabelleğini sınırlar; bu da uzunluk ön ekli bir okumanın veya aşırı büyük bir satırın arabelleği sınırsızca büyütmesini engeller.

// inside OnConnect / OnExecute of any Indy server
AContext.Connection.IOHandler.MaxInputBufferSize := 1024 * 1024;  // 1 MB cap

Tasarımı gereği isteğe bağlı

Bu seçeneklerin hiçbiri varsayılan davranışı değiştirmez. Alanların tümü varsayılan olarak kapalıdır (boyut ve zaman aşımı sınırları için 0, boolean bayraklar için False); bu nedenle 2026.6'ya yükseltilen bir proje, 2026.5'te olduğu gibi tam olarak aynı şekilde davranır. Dağıtımınızın ihtiyaç duyduğu korumaları tam olarak etkinleştirirsiniz ve aynı kod, Delphi 7'den RAD Studio 13'e ve Free Pascal'a kadar derlenir.

Bu sürümde ayrıca

2026.6, OpenSSL 3.5 ve sonrasında kullanılabilen ilk ML-KEM-768 post-kuantum kapsülleme ve kapsül açma ilkellerini sunar. Basit bir TBytes API'si sunarlar; böylece klasik ECDH değişiminin yanında hibrit bir el sıkışmaya bir post-kuantum anahtar kapsülleme adımı ekleyebilirsiniz.

Yapı tarafında, RAD Studio boşluk içeren bir yola kurulduğunda C++Builder paket derlemesi artık MSB1008 MSBuild hatasıyla başarısız olmuyor. DCC_BpiOutput parametresi artık tırnak içine alınmıştır.

Yükseltme

2026.6 doğrudan yerine geçen bir yükseltmedir. Her yeni koruma isteğe bağlı olduğundan, bozucu değişiklik yoktur ve geçiş yapılacak hiçbir şey yoktur. Yukarıdaki parçacıkları gözden geçirin ve sunucunuza uygun seçenekleri etkinleştirin.

sgcIndy ücretsizdir. En son yapıyı esegece.com/products/sgcindy/download adresinden indirin.

Sorularınız, geri bildirimleriniz mi var ya da sunucunuzu sıkılaştırmak için yardıma mı ihtiyacınız var? İletişime geçin, kodu yazan kişilerden yanıt alacaksınız.