2 puan yazan GN⁺ 2024-09-26 | 1 yorum | WhatsApp'ta paylaş
  • BlogTech, küçük ve orta ölçekli web sitelerini yönetmek için C tabanlı bir araç takımıdır; HTTPS, sanal host, ACME tabanlı otomatik sertifika yönetimi ve uzaktan sunucu yönetim istemcisi sunar
  • Şu anda test aşamasındadır; 0.4.x sürümüyle https://coz.is/ birkaç hafta boyunca çalıştırılmış olsa da kararlı sürüm olarak sunulmamaktadır
  • Sunucu Linux ve Windows’ta çalışır, ancak HTTPS yalnızca Linux’ta desteklenir; Windows’ta hem istemci hem de sunucu yalnızca HTTP kullanabilir
  • Uzaktan dosya yönetimi --put, --get, --delete ile yapılır; kaynakları değiştiren istekler paylaşılan gizli anahtar tabanlı HMAC/SHA256 imzası ile doğrulanır
  • Üretim ortamında 80 numaralı portta çalışan bir HTTP sunucusu ve alan adı DNS kayıtları gerekir; ACME etkinleştirildiğinde sertifika ve özel anahtar dosyalarını otomatik oluşturur, hatalar acme.log dosyasına yazılır

BlogTech’in amacı ve mevcut durumu

  • BlogTech, küçük ve orta ölçekli web sitelerini yönetmeye yönelik bir araç takımıdır
  • Desteklenen özellikler şunlardır
    • HTTPS

    • Sanal host

      • ACME üzerinden otomatik sertifika yönetimi
      • Sunucuyu uzaktan yönetmek için istemci
      • Henüz test aşamasındadır
      • 0.4.x sürümüyle https://coz.is/ adresini birkaç hafta başarıyla servis etmiş bir örnek vardır
      • Eski tek dosyalı sürüm single_file dalındadır

Derleme ve temel çalıştırma

  • BlogTech Linux ve Windows üzerinde çalışır
    • Linux derlemesi için OpenSSL geliştirme kütüphaneleri ve gcc gerekir
    • Windows derlemesi için clang gerekir
  • Derleme platforma özgü betiklerle yapılır
    • Linux: ./build.sh
    • Windows: .\build.bat
  • Derleme çıktıları şunlardır
    • Linux: blogtech
    • Windows: blogtech.exe
  • Linux’ta ./install.sh ile kurulabilir
  • Temel sunucu çalıştırma örneğinde docroot dizini oluşturulur ve --serve, --document-root=docroot, --skip-auth-check belirtilir
  • Varsayılan HTTP sunucusu 127.0.0.1:8080 üzerinde dinler ve docroot içeriğini sunar
  • Boş docroot durumunda http://127.0.0.1:8080/ adresine erişildiğinde 404 döner

Uzaktan dosya yönetimi ve kimlik doğrulama

  • BlogTech, istemci modunda dosyaları sunucuya yükleyebilir
    • --put ile dosya yükleme
    • --get ile uzak dosya indirme
    • --delete ile uzak dosya silme
  • İstemci ve sunucu aynı makinede çalıştırılsa da, uzak bir makinedeki sunucu için de aynı şekilde çalışır
  • Kaynakları değiştiren istekler HMAC/SHA256 imzası ile dijital olarak imzalanır
  • İstemci ve sunucu aynı gizli anahtarı paylaşmalıdır; geleneksel olarak admin.pwd dosyasında saklanır
  • Parola dosyası --auth-password-file seçeneğiyle belirtilir
  • Parola dosyası yoksa kimlik doğrulama gerektiren tüm istekler reddedilir
  • Boş parola da reddedilir
  • Geliştirme sırasında --skip-auth-check ile tüm istekler kimliği doğrulanmış gibi işlenebilir
    • Bu seçenek kullanıldığında --auth-password-file belirtilmiş olsa bile yok sayılır
    • Dikkatli kullanılmalıdır
  • Kimlik doğrulama başlıkları ve yeniden gönderim koşulları

    • Kimliği doğrulanmış HTTP istekleri X-BlogTech- başlıklarını içerir
    • X-BlogTech-Nonce: İstemcinin rastgele seçtiği token
    • X-BlogTech-Timestamp: İsteğin ilk imzalandığı andaki UNIX zaman damgası
    • X-BlogTech-Expire: İmzalama anından itibaren isteğin geçerli olduğu saniye cinsinden süre
    • X-BlogTech-Signature: İstek bilgilerinin HMAC’inin Base64 ile kodlanmış değeri
    • İmza, normalize edilmiş bir istek dizesi oluşturulduktan sonra kimlik doğrulama parolası anahtar olarak kullanılarak HMAC/SHA256 hesaplanması ve sonucun padding dâhil Base64 olarak kodlanmasıyla elde edilir
    • Sunucunun daha önce gördüğü nonce’lar bellekte saklanır
    • Sunucu yeniden yüklendiğinde önceki nonce’ları unuttuğu için, süresi dolmamış istekler yeniden gönderilebilir

Sanal hostlar ve dizin eşleme

  • BlogTech aynı sunucuda birden fazla web sitesini barındırabilir
  • Alan adları --domain seçeneği birden çok kez belirtilerek ayarlanır
  • BlogTech, belge kökü içinde alan adına özel dizinler oluşturur
    • default
    • websiteA.com
    • websiteB.com
  • Belirli bir host üzerinden gelen istekler, o host ile ilişkili dizine başvurur
  • Belirli bir klasörle ilişkilendirilmemiş istekler default dizinine başvurur
  • Örnekte websiteA.com, websiteB.com, other.com adreslerine yüklenen dosyalar sırasıyla alan adı dizinine veya default dizinine kaydedilir

HTTPS ve sertifika ayarları

  • HTTPS yalnızca Linux’ta desteklenir
  • Bunun nedeni, altta yatan HTTP kütüphanesi cHTTP’nin HTTPS’i OpenSSL ile uygulamasıdır
  • Windows’ta hem istemci hem de sunucu yalnızca HTTP kullanabilir
  • HTTPS’i etkinleştirmek için şu seçenekler gerekir
    • --https-enabled
    • --cert-file
    • --cert-key-file
  • Varsayılan HTTPS dinleme adresi 127.0.0.1:8443’tür
  • Dinleme adresi ve port şu seçeneklerle değiştirilebilir
    • --https-addr=<addr>
    • --https-port=<port>
  • Geliştirme sırasında OpenSSL komutuyla kendinden imzalı sertifika oluşturulabilir
  • Tarayıcılar, kendinden imzalı sertifika kullanan HTTPS sunucularında gezinmeye izin vermez
  • cURL’ün kendinden imzalı sertifika kullanan sunuculara erişebilmesi için --insecure bayrağı kullanılmalıdır
  • Birden fazla sertifika gerekiyorsa ek olarak --extra-cert verilebilir
    • Varsayılan sertifika --cert-file, --cert-key-file ile sağlanır
    • Ek sertifikalar, istemci belirli bir alan adını istediğinde kullanılır
  • Uzun komut satırı seçenekleri yapılandırma dosyasına taşınabilir

ACME tabanlı otomatik sertifika verilmesi

  • ACME protokolü, web sunucularının sertifika otoritelerinden otomatik olarak sertifika verilmesini istemesini sağlar
  • BlogTech, HTTPS modunda sertifika olmadan başlayıp sertifikanın oluşturulduğu bir akışı destekler
  • Üretim ortamında şu koşullar gerekir
    • HTTP sunucusunu 80 numaralı portta çalıştırmak
    • Sunucunun çalıştığı makineyle alan adını bağlayan DNS kaydı oluşturmak
  • ACME, HTTPS seçenekleriyle birlikte --acme-enabled belirtilerek etkinleştirilir
  • Normal HTTPS modundan farklı olarak, ACME modunda sertifikanın mevcut olmaması beklenir
  • Sertifika oluşturmak için şu değerler gerekir
    • --acme-domain
    • --acme-email
    • --acme-country
    • --acme-organization
    • --acme-agree-tos
  • Başarıyla işlendiğinde şu dosyalar oluşturulur
    • acme_key.pem: ACME hesabıyla ilişkili gizli anahtar
    • cert.pem: Verilen sertifika veya --cert-file ile belirtilen dosya
    • key.pem: Sertifikayla ilişkili özel anahtar veya --cert-key-file ile belirtilen dosya
  • Hata oluşursa mesajlar acme.log dosyasına kaydedilir
  • --acme-domain birden çok kez belirtilirse birden fazla alan adı ACME ile işlenebilir
  • Ortaya çıkan sertifika, belirtilen tüm alan adlarını içerir

ACME istemci testi

  • Linux’ta ACME istemcisini test etmek için Docker kurulmalı ve Pebble ACME server klonlanmalıdır
  • docker-compose.yml içinde test alan adını host-gateway’e bağlayan extra_hosts öğesi eklenir
  • /etc/hosts içinde test alan adı 127.0.0.1 olarak eşlenir
  • Pebble docker compose up ile başlatılır
  • BlogTech, ./blogtech -s --config=misc/pebble_blogtech.conf ile bir test instance’ı çalıştırır
  • ACME sunucusuyla etkileşimler stdout’a yazdırılır
  • Başarılı olursa acme_key.pem, cert.pem, key.pem oluşturulur
  • Sertifika yenileme testi, pebble/test/config/pebble-config.json içindeki validityPeriod değeri değiştirilerek yapılabilir
  • --acme-force-renewal-period=<maximum duration in ms> seçeneği kullanılarak sertifikanın süresi dolmamış olsa bile yenileme talimatı verilebilir

Yapılandırma dosyası ve otomatik yükleme

  • BlogTech, istenen sayıda komut satırı argümanını yapılandırma dosyasına taşıyabilir
  • Örneğin HTTPS ve ACME ile ilgili seçenekler blogtech_server.conf içine yazıldıktan sonra --config=blogtech_server.conf ile çalıştırılabilir
  • Yapılandırma dosyasının adı tam olarak blogtech.conf ise BlogTech bunu otomatik olarak yükler
  • Bu durumda ./blogtech --serve şeklinde çalıştırılabilir
  • Örtük yapılandırma dosyası yüklemesini yok saymak için --no-config kullanılır

Çökme günlükleri ve systemd daemon’u

  • Sunucu modunda BlogTech çökerse crash.bin dosyası oluşturulur
  • Bir sonraki sunucu başlatılışında crash.bin, insan tarafından okunabilir bir stack trace olan crash.log dosyasına dönüştürülür
  • Adresleri sembol adlarına veya satır numaralarına dönüştürme süreci biraz kararsız olabilir
  • BlogTech bir systemd daemon’u olarak kurulabilir
  • Örnek blogtech.service, /root/blogtech/blogtech -s komutunu çalıştırır, hata durumunda yeniden başlatır ve çalışma dizinini /root/blogtech/ olarak ayarlar
  • Sunucu seçenekleri /root/blogtech/blogtech.conf üzerinden otomatik olarak yüklenir
  • Servis dosyası /etc/systemd/system/ içine kopyalandıktan sonra şu komutlarla etkinleştirilip başlatılır
    • systemctl daemon-reload
    • systemctl enable blogtech
    • systemctl start blogtech
  • Servis yönetimi systemctl start, systemctl stop, systemctl restart, journalctl -u blogtech ile yapılır

1 yorum

 
GN⁺ 2024-09-26
Hacker News yorumları
  • Ters proxy gereksiz” kısmı bana hep tuhaf gelmiştir
    Ters proxy'nin özellikle fayda sağladığı bir neden yoksa, gömülü Jetty uygulamalarını önünde hiçbir şey olmadan doğrudan internete açardım ve sorun yaşamazdım
    Altyapı ya da güvenlik ekipleri neden önüne nginx koymadığımı soruyor ama nedenini sorduğumda güvenlik ya da performans hakkında muğlak şeyler söylüyorlar; somutluk eksik. Aldığım en somut yanıt slow loris'ti, ama o da uzun zamandır büyük bir sorun değil
    Ters proxy'nin topluca bir cargo cult hâline mi geldiğini, yoksa genel olarak geçerli iyi bir nedeni benim mi kaçırdığımı merak ediyorum

    • Benim için ters proxy, origin sunucunun yalnızca uygulama sunmaya odaklanmasını sağlıyor. TLS sonlandırma, yük dengeleme, URL yeniden yazma ve gerektiğinde WAF gibi güvenlik işlevlerinin hepsi ters proxy'de ele alınabiliyor; böylece görev ayrımı sağlanıyor
      Genel olarak origin sunucuyu koruyup yalnızca ilgili trafiği almasını sağlayabiliyorsunuz. Müşterilere özel alan adı sunduğunuz durumlarda da müşteri DNS'i origin sunucuyu değil ters proxy'yi gösterdiği için, gerekirse origin sunucuyu değiştirseniz bile müşteri DNS değişiklikleriyle uğraşmanız gerekmiyor
    • Homelab'imde birden fazla sunucu programı çalıştırıyorum
      Her biri farklı portlarda çalışıyor, ama hepsinin farklı URL'ler üzerinden herkese açık şekilde erişilebilir olmasını ve internete yalnızca 443 portunu açmak istiyorum
      Her alan adının TLS sertifikasının otomatik yenilenmesini de istiyorum. İlk gereksinim için ters proxy gerekiyor; Caddy ise ikisini de yapıyor
      Tek bir sunucu işletiyorsanız ve o sunucu TLS sonlandırmayı da yapıyorsa, ters proxy şart değil
    • Çoğu dağıtımda ters proxy'nin performans etkisi ihmal edilebilir düzeyde ve yapılandırmam da önceden hazır oluyor
      Sonradan TLS sonlandırma, URL yeniden yazma ve başka işleri büyük zahmet olmadan ekleyebildiğim için alışkanlık olarak kullanmaya başladım; şimdiye kadar da bu alışkanlık karşılığını verdi
    • Web uygulamalarının önüne konan farklı sunucu türleri için geçerli bir yanıt verecek olursam, ek bir bileşenin güvenlik ve performans açısından yardımcı olabildiği birkaç yol var
      Güvenlik tarafında, tüm sistemde mümkün olduğunca az kod ve sağlam bir işletim sistemi kullanmak istersiniz. Proxy türü bir uygulama, web/uygulama sunucusundan çok daha basit olabilir; gelen trafiği filtreleyebilir, girdileri doğrulayabilir ya da daha güvenli ve hızlı ayrıştırılabilecek bir biçime dönüştürebilir. OpenBSD, GenodeOS, INTEGRITY-178B gibi saldırılması zor işletim sistemlerinde de çalıştırılabilir
      Erişilebilirlik açısından da yük dengeleme, izleme ve kurtarmayı bu tür sistemlere koymak çoğu zaman daha güvenlidir. Çünkü uygulama sunucuları daha sık çökebilir
      Performans tarafında ise önce basit ve odaklı bir uygulamanın yüksek düzeyde optimize edilebilmesi avantajı vardır. Sonrasında CPU ya da PCI donanım hızlandırıcılarıyla sıkıştırma veya şifreleme hızlandırılabilir; buna genellikle offloading denir. Maliyet/verim açısından en iyi yapı, çok sayıda genel amaçlı sunucunun az sayıdaki pahalı offloading sunucusundan faydalanmasıdır. Bazıları da yük dengeleme yoluyla gelen trafiği en iyi işleyecek sunucuya göndererek pahalı kaynak kullanımını azaltır
    • Tüm sunucular için geçerli bir genelleme olduğunu düşünmüyorum
      Minimal kurulumda gerekmez, ama tek host'lu işletim ortamında bile rolling release, sıkıştırma, TLS, hızlı statik dosya sunumu ve olası A/B testlerini mümkün kılar
      İstek ile sunucu arasındaki dolaylı bir katman epey kullanışlı olabilir
  • Harika. Ben de eskiden kendi C web sunucumu yazmıştım; kaynak kodu aşağıda. Bir süre ticari bir web sitesini de çalıştırdı
    Bir HTTP/1.1 web sunucusunun ne kadar küçük ve hafif yapılabildiği şaşırtıcı. O ticari site 128 MB RAM ve 1 CPU'lu bir makinede çalışıyordu; kapalı kaynaklı, etkileşimli web tabanlı bir sohbet sistemi olarak Birleşik Krallık'taki epey çok okula düzenli hizmet veriyordu. Tabii bu, internetin bugüne kıyasla daha az düşmanca olduğu 20 yıl öncesinin hikâyesi
    Yazıda botların harika bir fuzzer görevi gördüğü söylenmiş, ama yine de gerçek fuzzing de biraz yapılmalı diye düşünüyorum
    http://git.annexia.org/?p=rws.git;a=tree
    Gerekenler:
    http://git.annexia.org/?p=c2lib.git;a=tree
    http://git.annexia.org/?p=pthrlib.git;a=tree

    • Bu boyutta bir web sunucusu çalıştırırken düşmanca internet konusunda çok endişelenmemek istiyorsanız Rust iyi bir seçim
      Web sitem https://blessed.rs bulabildiğim en küçük VM olduğu için 256 MB RAM'li bir makinede çalışıyor, ama genelde yalnızca yaklaşık 60 MB kullanıyor
    • Bu, benim küçük ve hafif HTTP/1.0 web sunucumdan çok daha pratik görünüyor; yine de rws'nin onun kadar küçük ve hafif olduğunu sanmıyorum: http://canonical.org/~kragen/sw/dev3/server.s http://canonical.org/~kragen/sw/dev3/httpdito-readme
      Asıl şaşırtıcı olan, bellek haritası yalnızca beş adet 4 KB sayfadan ibaret olduğunda Linux'ta fork'un inanılmaz hızlanmasıydı
  • Eğlence için boş zamanımda başladığım küçük bir proje; buradakilerin hoşuna gider diye düşündüm :)

    • Eski HTTP sunucusu hatalarını ve CVE'leri gözden geçirip kendi kodumu etkileyip etkilemeyeceğine, nasıl düzeltebileceğime bakmak ilginç bir alıştırma oluyor. Böyle şeyleri kendin yapmak eğlenceli
    • Tam da C11 eşzamanlılık API'sini kurcalamak istiyordum; C++ tarafından gelen biri olarak bu yapıların C'de nasıl çalıştığını merak ettiğim için sunucu benzeri bir şey yazmak istedim
  • Harika. En düşük seviyedeki sistem API'lerini kullanarak bu şekilde minimal bir servis ayağa kaldırmanın gerçekten tatmin edici olduğunu eskiden beri düşünürdüm, hâlâ da öyle görüyorum
    Neredeyse sihir gibi; gerçek trafiği işlediğini görünce daha da öyle. Sıradan bir poll()'un bu kadar iyi rakamlara ulaşabilmesi biraz şaşırtıcıydı ama sanırım o seviyede event'lerle ya da benchmark'larla uğraşmayalı uzun zaman olduğu için
    Bağlantı başına fonksiyon ve ilgili struct'lar, bağlantıları array ile yönetme biçimi, poll dosya tanımlayıcı array'i de hoş. nginx, Redis, memcached gibi yüksek iş hacmiyle bilinen birçok açık kaynak pakette yapılanları hatırlatıyor

    • Üniversitede C/C++ ile uğraşırken beynim yanıyormuş gibi hissetmiştim. Mühendislik, tarih, kültür, dilbilim gibi sevdiğim şeylerin hepsinden biraz barındıran, çok özel ve insanı alçakgönüllü kılan bir deneyimdi
      Herkesin mümkün olan tüm dilleri, ister programlama dili ister doğal dil olsun, bilip denemesi gerektiğini düşünmeye başladım. Bir dilde düşünmek benzersiz bir deneyim. Farklı bağlamlar her şeyi farklı hissettiriyor; sonunda benzer şeyler yapsanız bile bakış açınız değişiyor
      Örneğin Linux'un ya da Git'in özünü gerçekten anlamak için o dili konuşmanız, çeviride genellikle kaybolan nüansları anlamanız gerekir. Rusçada “orman” kelimesinin gerçek öznel anlamını anlamak için Rusça konuşup anlamanız gerekmesine benzer
      Bağlam bakış açısını değiştirir; bazen de her şeyi değiştirir
    • Tamamen katılıyorum. Üstelik gerçekten kullanınca daha da tatmin edici oluyor. Artık e-posta protokolü de ilgimi çekmeye başladı
      Ben de sıradan bir poll()'un bu kadar dayanabilmesine şaşırdım. Bir noktada epoll'a geçerim diye düşünmüştüm ama poll() gayet iyi çalışıyor
    • İnsanlar unutuyor gibi: bütün o harika ve güzel soyutlamalar da özünde aynı şeyi yapıyor. Soket açıyor, okuyor ve yazıyorlar
      Güneşin altında yeni bir şey yok
  • Bu da ilginç olabilir: https://news.ycombinator.com/item?id=27431910
    2024 itibarıyla sqlite.org'un althttpd instance'ı günde 500 binden fazla HTTP isteği, saniyede yaklaşık 5-6 istek işliyor; günde yaklaşık 200 GB içerik, yaklaşık 18 Mbit/s bant genişliğini aylık 40 dolarlık bir Linode üzerinden sunuyor. Bu makinenin load average'ı genellikle 0,5 civarında kalıyor. HTTP isteklerinin yaklaşık %19'u çeşitli Fossil kaynak kod depolarına giden CGI'lar

    • Bu yazıdan çok ilham aldım. Böyle bir şeyin gerçekten mümkün olduğunu fark etmemi sağladı
  • C uygulaması yazmak istiyor ama açık internete doğrudan temas eden kısmı kendiniz yazmaktan rahatsız oluyorsanız, Kore iyi bir framework
    ACME sertifika yönetimi, Pgsql, curl, WebSocket gibi kullanışlı yerleşik özellikleri var
    Temelde modüller derleyip çalıştırabilir ve birleştirebilirsiniz; Lua/Python ile C'yi karıştırmak da mümkün
    https://kore.io/

  • Sonunda ilk sayfaya çıkınca ölmeyen bir web sitesi çıktı

    • Önünde CDN varsa herhangi bir site bunu yapabilir
      Bu projenin harika olmadığı anlamına gelmiyor ama üretim ortamında bunu gerçekten önemsiyorsanız ve çoğunlukla statik içerik sunuyorsanız doğrudan CDN kullanın. Kendi yazacağınız neredeyse her şeyden her zaman daha iyi performans verir. Sadece o kadar eğlenceli değildir
    • Link GitHub'a gitmiyor mu? Bu yorum biraz kafamı karıştırdı
      Proje temiz ve hoş görünüyor ama çoğu kişi web sayfasını gösteren linke değil GitHub'a gider gibi. Bir şeyi mi kaçırıyorum?
  • “Kendi araçlarımı yapmaktan keyif alıyorum ve her şeyin savaşta sınanmış olması gerektiğinin söylenmesinden biraz yoruldum. Ölürse ne olmuş? Bug'ı düzeltiriz :^)” kısmını sevdim

  • Sadece 3,4 bin satır C koduyla tam bir HTTP ve HTTPS sunucusu mu? Spesifikasyona tamamen uymak için açıkçası çok daha fazlası gerekir sanıyordum

    • HTTP/1.1, spesifikasyonun çoğunu görmezden gelirseniz çok basit
      Sadece GET istekleri alıp yanıta Content-Length koyarsanız kullanıcı aracılarının %99'u için yeterli. Transfer-Encoding ve byte range header'larını işlemek de kodu çok büyütmez
      HTTPS, TLS soketi üzerindeki HTTP'den ibaret; şifrelemeyi kendiniz implement etmiyorsanız soyutlama seviyesi tam olarak bu olmalı. Eğlenceli ve pratikte o kadar da kötü değil
    • Bu kadarı makul görünüyor. OpenBSD'nin httpd(8) [1]'i de dokümantasyon dahil şu anda 15.000 satırın biraz altında
      Birkaç özelliği çıkarıp bazı varsayımlar koyarsanız, bu projedeki gibi 5.000 satır bandına girmesine şaşırmam
      $ wc -l * çıktısına göre toplam 14815 satır
      [1]: https://man.openbsd.org/httpd.8
    • Deneylerimden birinde veri toplama için canlı görünüm sunmak üzere basit bir gömülü C web sunucusu kullanmıştım; 250 satırdan azdı
      Tabii açık internete koymazdım ve HTTP/1.1'in çok küçük bir kısmını implement ediyordu ama çalışıyor ve sadece başlatma sırasında malloc gerekiyor
    • Bu boyutta birkaç HTTP/1.1 sunucusu daha var: https://www.acme.com/software/thttpd/benchmarks.html
  • C ile yazılmış bir blog/web sunucusu hakkındaki Chaos Communication Congress sunumu aklıma geldi
    Değişmez depolama, yetki düşürme, blog'un TLS sertifikalarına erişmesini engelleme gibi birçok güvenlik özelliği eklemişti: https://www.youtube.com/watch?v=TaE28fJVPTk