2 puan yazan GN⁺ 2024-09-26 | 1 yorum | WhatsApp'ta paylaş

Blog Teknolojim

Bu web sunucusu, blogumu barındırmak için tasarlanmış minimal bir web sunucusudur. Baştan itibaren genel internete dayanacak kadar sağlam şekilde inşa edilmiştir. Reverse proxy gerektirmez. Gerçekte çalışırken http://playin.coz.is/index.html adresinde görülebilir. Eğlenceli ve kötü niyetli istek günlüklerini gigabaytlarca toplamak için Reddit'te hacklenmeyi istedim. Bunların bir kısmını attempts.txt içine kaydettim; daha sonra eğlencesine daha fazlasını inceleyeceğim.

Peki.. neden?

Kendi araçlarımı yapmaktan hoşlanıyorum ve her şeyin "battle-tested" olması gerektiğini duymaktan bıktım. Çökme olursa ne olacak? Hatalar düzeltilebilir.

Özellikler

  • Yalnızca Linux
  • HTTP/1.1, pipelining ve keep-alive bağlantıları uygulanmış
  • HTTPS desteği (BearSSL kullanarak TLS 1.2'ye kadar)
  • Minimum bağımlılık (HTTPS kullanıldığında libc ve BearSSL)
  • Yapılandırılabilir zaman aşımı
  • Erişim günlüğü, çökme günlüğü, log rotasyonu, disk kullanım sınırı
  • Transfer-Encoding: Chunked yok (411 Length Required yanıtı vererek istemciyi Content-Length ile yeniden göndermeye yönlendirir)
  • Tek çekirdekli (daha iyi bir VPS alınca değiştirilecek)
  • Statik dosya önbelleklemesi yok (henüz)

Kıyaslama

Bu projenin odağı sağlamlık olsa da kesinlikle yavaş değildir. nginx ile basit bir karşılaştırma (statik endpoint, ikisi de tek iş parçacıklı, 1K bağlantı sınırı):

nginx yapılandırması:

worker_processes 1;
events {
  worker_connections 1024;
}
http {
  server {
    listen 8080;
    location /hello {
      add_header Content-Type text/plain;
      return 200 "Hello, world!";
    }
  }
}

Derleme ve çalıştırma

Varsayılan olarak sunucu derlemesi yalnızca HTTP içindir:

$ make

Bu komut serve (release build), serve_cov (coverage build), serve_debug (debug build) çalıştırılabilirlerini üretir. Release build 80 numaralı portu, debug build ise 8080 numaralı portu dinler.

HTTPS'i etkinleştirmek için BearSSL'i klonlayıp derlemeniz gerekir:

$ mkdir 3p
$ cd 3p
$ git clone https://www.bearssl.org/git/BearSSL
$ cd BearSSL
$ make -j
$ cd ../../
$ make -B HTTPS=1

Aynı çalıştırılabilirler üretilir, ancak 443 (release) veya 8081 (debug) portunda güvenli bağlantılar etkin olur. cert.pem ve key.pem dosyaları çalıştırılabilirlerle aynı dizine yerleştirilmelidir. Adlarını ve konumlarını değiştirmek için şunları düzenleyin:

#define HTTPS_KEY_FILE "key.pem"
#define HTTPS_CERT_FILE "cert.pem"

Yerelde HTTPS ile test etmek için self-signed bir sertifika (ve özel anahtar) oluşturun:

openssl genpkey -algorithm RSA -out key.pem -pkeyopt rsa_keygen_bits:2048
openssl req -new -x509 -key key.pem -out cert.pem -days 365

Kullanım

Sunucu, docroot/ klasöründeki statik içeriği sunar. Bunu değiştirmek için respond fonksiyonunu düzenleyin:

typedef struct {
  Method method;
  string path;
  int major;
  int minor;
  int nheaders;
  Header headers[MAX_HEADERS];
  string content;
} Request;

void respond(Request request, ResponseBuilder *b) {
  if (request.major != 1 || request.minor > 1) {
    status_line(b, 505); // HTTP Version Not Supported
    return;
  }

  if (request.method != M_GET) {
    status_line(b, 405); // Method Not Allowed
    return;
  }

  if (string_match_case_insensitive(request.path, LIT("/hello"))) {
    status_line(b, 200);
    append_content_s(b, LIT("Hello, world!"));
    return;
  }

  if (serve_file_or_dir(b, LIT("/"), LIT("docroot/"), request.path, NULLSTR, false))
    return;

  status_line(b, 404);
  append_content_s(b, LIT("Nothing here :|"));
}

Burada request.path alanı üzerinden dallanarak endpoint ekleyebilirsiniz. Yol yalnızca istek tamponunun bir dilimidir. URI ayrıştırılmaz.

Testler

Sunucuyu düzenli olarak valgrind ve sanitizer'larla (address, undefined) çalıştırıyor ve wrk ile hedefliyorum. Ayrıca HTTP/1.1 spesifikasyonuna uygunluğu kontrol etmek için tests/test.py içine otomatik testler ekliyorum. Stresi sürdürmek için kendi web sitemi bununla barındırıyor ve çeşitli yerlere gönderiler paylaşıyorum. İnternette zayıf web sitelerini tarayan tüm botlar harika birer fuzzer oluyor.

Bilinen sorunlar

  • Sunucu, HTTP/1.0 istemcilerine HTTP/1.1 olarak yanıt veriyor

Katkı

Çoğunlukla DEV dalında çalışıyorum ve ara sıra MAIN'e birleştiriyorum. Pull request açarken DEV'i hedeflerseniz daha kolay olur.

GN⁺ Özeti

  • Bu proje, minimum bağımlılık ve sağlamlık hedefleyen bir web sunucusudur.
  • HTTP/1.1 ve HTTPS destekler; çeşitli günlük özellikleri ve yapılandırılabilir zaman aşımı sunar.
  • Kıyaslama sonuçları, nginx'ten daha hızlı yanıt süreleri gösterir.
  • Geliştiricilerin kendi araçlarını yapma ve hataları düzeltme sürecinden keyif alabilmesi için tasarlanmıştır.
  • Benzer özelliklere sahip projeler arasında Nginx ve Apache HTTP Server bulunur.

1 yorum

 
GN⁺ 2024-09-26
Hacker News yorumları
  • Ters proxy gerekmiyor: Jetty kullanarak uygulamayı ters proxy olmadan internete dağıtmış ve bir sorun yaşamamış

    • Güvenlik veya performans açısından somut bir gerekçe sunulmadan ters proxy kullanılması gerektiğini söyleyen çok kişi var
    • Ters proxy’nin gerçekten gerekli olup olmadığını sorguluyor
  • Kendi yaptığı C web sunucusu: Ticari bir web sitesini çalıştırmış olan bir C web sunucusu geliştirmiş

    • 128MB RAM ve 1 CPU ile çok fazla trafiği işlemiş
    • 20 yıl önce internet ortamının daha az düşmanca olduğunu belirtiyor
    • Botların harika birer fuzzer görevi gördüğünü, ama gerçek fuzzing’in de gerektiğini söylüyor
  • Servis inşa etmenin tatmini: Sistem API’lerini kullanarak temel bir servis kurmanın çok tatmin edici olduğunu söylüyor

    • poll() fonksiyonunun yüksek performans göstermesine şaşırmış
    • Bağlantı başına fonksiyonlar, ilgili struct’lar ve dizilerin nginx, redis, memcached’e benzediğini belirtiyor
    • Harika bir iş olduğunu söylüyor
  • Küçük proje tanıtımı: Boş zamanlarında başladığı eğlenceli bir projeyi tanıtıyor

  • Kore framework önerisi: C uygulaması yazarken dışa açık kısımları yazmak zahmetliyse Kore framework’ünü öneriyor

    • ACME sertifika yönetimi, Pgsql, curl, WebSocket gibi özellikler yerleşik geliyor
    • Lua/Python ile C’yi karıştırarak modül derleyip çalıştırabiliyorsunuz
  • İlginç bağlantı paylaşımı: sqlite.org’daki althttpd örneğinin günde 500 binden fazla HTTP isteğini işlediğini paylaşıyor

    • Aylık 40 dolarlık bir Linode üzerinde 200GB içerik sunuyor
    • HTTP isteklerinin %19’u CGI üzerinden Fossil kaynak kod deposuna erişiyor
  • Kendi araçlarını yapmanın keyfi: Her şeyin "battle-tested" olması gerektiği yönündeki görüşten yorulmuş

    • Hatalar düzeltilebilir
  • Chaos Communication Congress konuşması: Güvenlik özellikleri içeren, C ile yazılmış bir blog/web sunucusu hakkındaki konuşmayı hatırlatıyor

    • Değişmez depolama, yetki azaltma ve TLS sertifikalarına erişilememesi gibi özellikler içeriyordu
  • Kararlı web sitesi: Ana sayfada gösterilse bile çökmeyen bir web sitesi

  • Temellere dönüş: Yalnızca gerekenleri kullanarak temellere dönme yaklaşımını seviyor

    • Yazılımdaki gereksiz özelliklerin performansı nasıl etkilediğini sorguluyor
    • Geliştiriciyi tebrik ediyor