HN’de yayınlandı: C web sunucusuyla web sitesi barındırma
(github.com/cozis)- 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.xsürümüylehttps://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,--deleteile 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.logdosyası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.xsürümüylehttps://coz.is/adresini birkaç hafta başarıyla servis etmiş bir örnek vardır- Eski tek dosyalı sürüm
single_filedalı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
gccgerekir - Windows derlemesi için
clanggerekir
- Linux derlemesi için OpenSSL geliştirme kütüphaneleri ve
- Derleme platforma özgü betiklerle yapılır
- Linux:
./build.sh - Windows:
.\build.bat
- Linux:
- Derleme çıktıları şunlardır
- Linux:
blogtech - Windows:
blogtech.exe
- Linux:
- Linux’ta
./install.shile kurulabilir - Temel sunucu çalıştırma örneğinde
docrootdizini oluşturulur ve--serve,--document-root=docroot,--skip-auth-checkbelirtilir - Varsayılan HTTP sunucusu
127.0.0.1:8080üzerinde dinler vedocrootiçeriğini sunar - Boş
docrootdurumundahttp://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
--putile dosya yükleme--getile uzak dosya indirme--deleteile 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.pwddosyasında saklanır - Parola dosyası
--auth-password-fileseç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-checkile tüm istekler kimliği doğrulanmış gibi işlenebilir- Bu seçenek kullanıldığında
--auth-password-filebelirtilmiş olsa bile yok sayılır - Dikkatli kullanılmalıdır
- Bu seçenek kullanıldığında
-
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 tokenX-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üreX-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
- Kimliği doğrulanmış HTTP istekleri
Sanal hostlar ve dizin eşleme
- BlogTech aynı sunucuda birden fazla web sitesini barındırabilir
- Alan adları
--domainseçeneği birden çok kez belirtilerek ayarlanır - BlogTech, belge kökü içinde alan adına özel dizinler oluşturur
defaultwebsiteA.comwebsiteB.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.comadreslerine yüklenen dosyalar sırasıyla alan adı dizinine veyadefaultdizinine 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
--insecurebayrağı kullanılmalıdır - Birden fazla sertifika gerekiyorsa ek olarak
--extra-certverilebilir- Varsayılan sertifika
--cert-file,--cert-key-fileile sağlanır - Ek sertifikalar, istemci belirli bir alan adını istediğinde kullanılır
- Varsayılan sertifika
- 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-enabledbelirtilerek 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 anahtarcert.pem: Verilen sertifika veya--cert-fileile belirtilen dosyakey.pem: Sertifikayla ilişkili özel anahtar veya--cert-key-fileile belirtilen dosya
- Hata oluşursa mesajlar
acme.logdosyasına kaydedilir --acme-domainbirden ç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.ymliçinde test alan adınıhost-gateway’e bağlayanextra_hostsöğesi eklenir/etc/hostsiçinde test alan adı127.0.0.1olarak eşlenir- Pebble
docker compose upile başlatılır - BlogTech,
./blogtech -s --config=misc/pebble_blogtech.confile 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.pemoluşturulur - Sertifika yenileme testi,
pebble/test/config/pebble-config.jsoniçindekivalidityPerioddeğ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.confiçine yazıldıktan sonra--config=blogtech_server.confile çalıştırılabilir - Yapılandırma dosyasının adı tam olarak
blogtech.confise 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-configkullanılır
Çökme günlükleri ve systemd daemon’u
- Sunucu modunda BlogTech çökerse
crash.bindosyası oluşturulur - Bir sonraki sunucu başlatılışında
crash.bin, insan tarafından okunabilir bir stack trace olancrash.logdosyası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 -skomutunu ç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ırsystemctl daemon-reloadsystemctl enable blogtechsystemctl start blogtech
- Servis yönetimi
systemctl start,systemctl stop,systemctl restart,journalctl -u blogtechile yapılır
1 yorum
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
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
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
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
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
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
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
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 :)
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çinBağlantı başına fonksiyon ve ilgili struct'lar, bağlantıları array ile yönetme biçimi,
polldosya 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ıyorHerkesin 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
Ben de sıradan bir
poll()'un bu kadar dayanabilmesine şaşırdım. Bir noktadaepoll'a geçerim diye düşünmüştüm amapoll()gayet iyi çalışıyorGü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
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ı
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
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
Sadece GET istekleri alıp yanıta
Content-Lengthkoyarsanız kullanıcı aracılarının %99'u için yeterli.Transfer-Encodingve byte range header'larını işlemek de kodu çok büyütmezHTTPS, 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
httpd(8)[1]'i de dokümantasyon dahil şu anda 15.000 satırın biraz altındaBirkaç ö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
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
mallocgerekiyorC 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