2 Punkte von GN⁺ 2024-09-26 | 1 Kommentare | Auf WhatsApp teilen
  • BlogTech ist ein C-basiertes Toolkit zur Verwaltung kleiner bis mittelgroßer Websites und bietet HTTPS, virtuelle Hosts, automatische Zertifikatsverwaltung auf ACME-Basis sowie einen Client zur Fernverwaltung von Servern
  • Es befindet sich derzeit in der Testphase; Version 0.4.x wurde zwar einige Wochen im Betrieb genutzt, wird aber nicht als stabiles Release präsentiert
  • Der Server läuft unter Linux und Windows, aber HTTPS wird nur unter Linux unterstützt; unter Windows können sowohl Client als auch Server nur HTTP verwenden
  • Die Remote-Dateiverwaltung erfolgt über --put, --get, --delete, und Anfragen, die Ressourcen verändern, werden mit HMAC/SHA256-Signaturen auf Basis eines gemeinsamen Geheimschlüssels authentifiziert
  • In Produktionsumgebungen werden ein HTTP-Server auf Port 80 und DNS-Einträge für die Domain benötigt; wenn ACME aktiviert ist, werden Zertifikate und private Schlüsseldateien automatisch erzeugt und Fehler in acme.log protokolliert

Zweck und aktueller Status von BlogTech

  • BlogTech ist ein Toolkit zur Verwaltung kleiner bis mittelgroßer Websites
  • Unterstützte Funktionen sind:
    • HTTPS

    • Virtuelle Hosts

      • Automatische Zertifikatsverwaltung über ACME
      • Client zur Fernverwaltung des Servers
      • Noch in der Testphase
      • Mit Version 0.4.x wurde https://coz.is/ einige Wochen lang erfolgreich betrieben
      • Eine ältere Single-File-Version befindet sich im Branch single_file

Build und grundlegende Ausführung

  • BlogTech läuft unter Linux und Windows
    • Für den Build unter Linux werden die OpenSSL-Entwicklungsbibliotheken und gcc benötigt
    • Für den Build unter Windows wird clang benötigt
  • Der Build erfolgt über plattformspezifische Skripte
    • Linux: ./build.sh
    • Windows: .\build.bat
  • Die Build-Artefakte sind:
    • Linux: blogtech
    • Windows: blogtech.exe
  • Unter Linux kann die Installation mit ./install.sh erfolgen
  • Ein Beispiel für den Start des Basis-Servers erstellt ein Verzeichnis docroot und setzt --serve, --document-root=docroot, --skip-auth-check
  • Der Standard-HTTP-Server lauscht auf 127.0.0.1:8080 und liefert die Inhalte aus docroot aus
  • Wenn docroot leer ist, wird beim Aufruf von http://127.0.0.1:8080/ ein 404 zurückgegeben

Remote-Dateiverwaltung und Authentifizierung

  • BlogTech kann im Client-Modus Dateien auf den Server hochladen
    • Datei-Upload mit --put
    • Herunterladen entfernter Dateien mit --get
    • Löschen entfernter Dateien mit --delete
  • Auch wenn Client und Server auf derselben Maschine laufen, funktioniert dies auf dieselbe Weise für Server auf entfernten Maschinen
  • Anfragen, die Ressourcen verändern, werden digital mit HMAC/SHA256-Signaturen signiert
  • Client und Server müssen denselben geheimen Schlüssel teilen, der üblicherweise in der Datei admin.pwd gespeichert wird
  • Die Passwortdatei wird mit der Option --auth-password-file angegeben
  • Wenn keine Passwortdatei vorhanden ist, werden alle authentifizierungspflichtigen Anfragen abgelehnt
  • Ein leeres Passwort wird ebenfalls abgelehnt
  • Während der Entwicklung kann mit --skip-auth-check jede Anfrage als authentifiziert behandelt werden
    • Bei Verwendung dieser Option wird --auth-password-file auch dann ignoriert, wenn es angegeben ist
    • Es sollte mit Vorsicht verwendet werden
  • Authentifizierungs-Header und Bedingungen für Replay

    • Authentifizierte HTTP-Anfragen enthalten X-BlogTech--Header
    • X-BlogTech-Nonce: Ein vom Client zufällig gewähltes Token
    • X-BlogTech-Timestamp: UNIX-Zeitstempel des Zeitpunkts, an dem die Anfrage zuerst signiert wurde
    • X-BlogTech-Expire: Gültigkeitsdauer der Anfrage in Sekunden ab dem Signaturzeitpunkt
    • X-BlogTech-Signature: Base64-kodierter HMAC der Anfrageinformationen
    • Die Signatur wird erzeugt, indem zunächst ein normalisierter Request-String erstellt, dann mit dem Authentifizierungspasswort als Schlüssel HMAC/SHA256 berechnet und das Ergebnis anschließend mit Padding Base64-kodiert wird
    • Nonces, die der Server bereits gesehen hat, werden im Speicher gehalten
    • Wenn der Server neu geladen wird, vergisst er frühere Nonces; noch nicht abgelaufene Anfragen können daher erneut abgespielt werden

Virtuelle Hosts und Verzeichniszuordnung

  • BlogTech kann mehrere Websites auf demselben Server hosten
  • Domains werden durch mehrfaches Angeben der Option --domain konfiguriert
  • BlogTech erstellt innerhalb des Document-Roots domainspezifische Verzeichnisse
    • default
    • websiteA.com
    • websiteB.com
  • Anfragen an einen bestimmten Host greifen auf das mit diesem Host verknüpfte Verzeichnis zu
  • Anfragen, die keinem bestimmten Ordner zugeordnet sind, verwenden das Verzeichnis default
  • Im Beispiel werden Dateien, die auf websiteA.com, websiteB.com und other.com hochgeladen werden, jeweils im Domain-Verzeichnis oder im Verzeichnis default gespeichert

HTTPS- und Zertifikatskonfiguration

  • HTTPS wird nur unter Linux unterstützt
  • Der zugrunde liegende HTTP-Stack cHTTP implementiert HTTPS mit OpenSSL
  • Unter Windows können sowohl Client als auch Server nur HTTP verwenden
  • Zum Aktivieren von HTTPS werden folgende Optionen benötigt
    • --https-enabled
    • --cert-file
    • --cert-key-file
  • Die Standard-Adresse für HTTPS ist 127.0.0.1:8443
  • Adresse und Port können mit den folgenden Optionen geändert werden
    • --https-addr=<addr>
    • --https-port=<port>
  • Für die Entwicklung kann mit einem OpenSSL-Befehl ein selbstsigniertes Zertifikat erzeugt werden
  • Browser erlauben kein normales Navigieren zu HTTPS-Servern mit selbstsignierten Zertifikaten
  • Bei cURL muss das Flag --insecure verwendet werden, um auf einen Server mit selbstsigniertem Zertifikat zuzugreifen
  • Wenn mehrere Zertifikate benötigt werden, kann zusätzlich --extra-cert übergeben werden
    • Das Standardzertifikat wird mit --cert-file, --cert-key-file bereitgestellt
    • Zusätzliche Zertifikate werden verwendet, wenn ein Client eine bestimmte Domain anfordert
  • Lange Kommandozeilenoptionen können in eine Konfigurationsdatei ausgelagert werden

Automatische Zertifikatsausstellung auf ACME-Basis

  • Das ACME-Protokoll ermöglicht es einem Webserver, automatisch bei einer Zertifizierungsstelle die Ausstellung eines Zertifikats anzufordern
  • BlogTech unterstützt einen Ablauf, bei dem der HTTPS-Modus ohne Zertifikat gestartet wird und das Zertifikat anschließend erzeugt wird
  • In Produktionsumgebungen sind folgende Bedingungen erforderlich
    • Der HTTP-Server läuft auf Port 80
    • Es existieren DNS-Einträge, die die Domain mit der Maschine verbinden, auf der der Server läuft
  • ACME wird mit --acme-enabled zusammen mit den HTTPS-Optionen aktiviert
  • Anders als im normalen HTTPS-Modus wird im ACME-Modus erwartet, dass noch kein Zertifikat vorhanden ist
  • Für die Zertifikatserstellung werden folgende Werte benötigt
    • --acme-domain
    • --acme-email
    • --acme-country
    • --acme-organization
    • --acme-agree-tos
  • Bei erfolgreicher Verarbeitung werden folgende Dateien erzeugt
    • acme_key.pem: Geheimer Schlüssel des ACME-Kontos
    • cert.pem: Ausgestelltes Zertifikat oder die mit --cert-file angegebene Datei
    • key.pem: Privater Schlüssel des Zertifikats oder die mit --cert-key-file angegebene Datei
  • Bei Fehlern werden Meldungen in acme.log protokolliert
  • Wenn --acme-domain mehrfach angegeben wird, können mehrere Domains per ACME verarbeitet werden
  • Das resultierende Zertifikat enthält alle angegebenen Domains

Test des ACME-Clients

  • Um den ACME-Client unter Linux zu testen, müssen Docker installiert und der Pebble ACME server geklont werden
  • In docker-compose.yml wird ein extra_hosts-Eintrag hinzugefügt, der die Test-Domain auf host-gateway abbildet
  • In /etc/hosts wird die Test-Domain auf 127.0.0.1 gemappt
  • Pebble wird mit docker compose up gestartet
  • BlogTech startet die Testinstanz mit ./blogtech -s --config=misc/pebble_blogtech.conf
  • Die Interaktion mit dem ACME-Server wird auf stdout ausgegeben
  • Bei Erfolg werden acme_key.pem, cert.pem, key.pem erzeugt
  • Ein Test der Zertifikatserneuerung kann durchgeführt werden, indem der Wert validityPeriod in pebble/test/config/pebble-config.json geändert wird
  • Mit der Option --acme-force-renewal-period=<maximum duration in ms> kann angewiesen werden, das Zertifikat auch dann zu erneuern, wenn es noch nicht abgelaufen ist

Konfigurationsdatei und automatisches Laden

  • BlogTech kann eine beliebige Anzahl von Kommandozeilenargumenten in eine Konfigurationsdatei auslagern
  • Beispielsweise können HTTPS- und ACME-bezogene Optionen in blogtech_server.conf geschrieben und dann mit --config=blogtech_server.conf verwendet werden
  • Wenn die Konfigurationsdatei exakt blogtech.conf heißt, lädt BlogTech sie automatisch
  • In diesem Fall kann es etwa mit ./blogtech --serve gestartet werden
  • Um das implizite Laden der Konfigurationsdatei zu ignorieren, wird --no-config verwendet

Crash-Logs und systemd-Daemon

  • Wenn BlogTech im Server-Modus abstürzt, wird eine Datei crash.bin erzeugt
  • Beim nächsten Serverstart wird crash.bin in crash.log umgewandelt, einen für Menschen lesbaren Stack-Trace
  • Die Umwandlung von Adressen in Symbolnamen oder Zeilennummern kann etwas unzuverlässig sein
  • BlogTech kann als systemd-Daemon installiert werden
  • Die Beispiel-Unit blogtech.service führt /root/blogtech/blogtech -s aus, startet bei Fehlern neu und setzt das Arbeitsverzeichnis auf /root/blogtech/
  • Serveroptionen werden automatisch aus /root/blogtech/blogtech.conf geladen
  • Nachdem die Service-Datei nach /etc/systemd/system/ kopiert wurde, wird sie mit den folgenden Befehlen aktiviert und gestartet
    • systemctl daemon-reload
    • systemctl enable blogtech
    • systemctl start blogtech
  • Die Verwaltung des Dienstes erfolgt mit systemctl start, systemctl stop, systemctl restart, journalctl -u blogtech

1 Kommentare

 
GN⁺ 2024-09-26
Meinungen auf Hacker News
  • Der Teil „Reverse Proxy nicht nötig“ hat mich schon immer verwundert.
    Wenn es keinen besonderen Grund gab, warum ein Reverse Proxy hilfreich wäre, habe ich eingebettete Jetty-Apps oft ohne vorgeschaltete Komponente direkt ins Internet gestellt, und es gab keine Probleme.
    Infrastruktur- oder Sicherheitsverantwortliche fragen dann, warum man kein nginx davor setzt, aber wenn man nach dem Grund fragt, nennen sie nur vage Sicherheit oder Performance, ohne konkret zu werden. Die konkreteste Antwort war Slowloris, aber das ist schon lange kein großes Problem mehr.
    Ich frage mich, ob Reverse Proxys kollektiv zu einem Cargo Cult geworden sind oder ob ich einen guten, allgemein gültigen Grund übersehe.

    • Für mich sorgt ein Reverse Proxy dafür, dass der Ursprungsserver ausschließlich die Anwendung ausliefert. TLS-Terminierung, Load Balancing, URL-Rewriting und bei Bedarf Sicherheitsfunktionen wie eine WAF können alle im Reverse Proxy erledigt werden; das ergibt eine Trennung der Zuständigkeiten.
      Insgesamt kann man so den Ursprungsserver schützen und dafür sorgen, dass er nur relevanten Traffic erhält. Auch wenn man Kunden Custom Domains anbietet, zeigt deren DNS auf den Reverse Proxy und nicht auf den Ursprungsserver; wenn nötig, kann man den Ursprungsserver austauschen, ohne sich um DNS-Änderungen bei Kunden kümmern zu müssen.
    • Ich betreibe in meinem Homelab mehrere Serverprogramme.
      Sie laufen jeweils auf unterschiedlichen Ports, aber ich möchte sie alle über verschiedene URLs öffentlich erreichbar machen und im Internet nur Port 443 freigeben.
      Außerdem möchte ich die TLS-Zertifikate für jede Domain automatisch erneuern. Für die erste Anforderung braucht man einen Reverse Proxy, und Caddy erledigt beides.
      Wenn man nur einen einzigen Server betreibt und dieser auch die TLS-Terminierung übernimmt, ist ein Reverse Proxy nicht zwingend nötig.
    • Bei den meisten Deployments ist der Performance-Einfluss eines Reverse Proxys vernachlässigbar, und die Konfiguration habe ich ohnehin vorbereitet.
      Später lassen sich TLS-Terminierung, URL-Rewriting und andere Aufgaben ohne großen Aufwand hinzufügen, deshalb habe ich mir die Nutzung angewöhnt, und bisher hat sich diese Gewohnheit ausgezahlt.
    • Wenn man eine Antwort geben will, die für verschiedene Arten von Servern vor Webanwendungen gilt: Es gibt einige Wege, auf denen zusätzliche Hardware sowohl bei Sicherheit als auch Performance hilft.
      Aus Sicherheitssicht möchte man im Gesamtsystem möglichst wenig Code und ein robustes Betriebssystem einsetzen. Eine Proxy-artige App kann deutlich einfacher sein als ein Web-/Anwendungsserver; sie kann eingehenden Traffic filtern, Eingaben validieren oder sie in eine Form umwandeln, die sicherer und schneller zu parsen ist. Man kann sie auch auf schwer angreifbaren Betriebssystemen wie OpenBSD, GenodeOS oder INTEGRITY-178B laufen lassen.
      Auch aus Verfügbarkeitssicht ist es oft sicherer, Load Balancing, Monitoring und Recovery in solchen Systemen unterzubringen, weil Anwendungsserver häufiger ausfallen können.
      Aus Performance-Sicht besteht der erste Vorteil darin, dass eine einfache, fokussierte App stark optimiert werden kann. Danach lassen sich Komprimierung oder Verschlüsselung per CPU- oder PCI-Hardwarebeschleuniger beschleunigen; das nennt man oft Offloading. Die kosteneffizienteste Konfiguration ist eine, bei der viele Allzweckserver von wenigen teuren Offloading-Servern profitieren. Manche leiten eingehenden Traffic per Load Balancing an den Server weiter, der ihn am besten verarbeiten kann, und reduzieren so den Einsatz teurer Ressourcen.
    • Ich glaube nicht, dass es eine allgemeine Regel für alle Server gibt.
      In einer Minimal-Konfiguration braucht man es nicht, aber selbst in einer Single-Host-Betriebsumgebung ermöglicht es Rolling Releases, Komprimierung, TLS, schnelle Auslieferung statischer Dateien und potenzielle A/B-Tests.
      Eine indirekte Schicht zwischen Request und Server kann ziemlich nützlich sein.
  • Cool. Ich habe früher auch selbst einen C-Webserver geschrieben; der Quellcode ist unten. Eine Zeit lang habe ich damit sogar eine kommerzielle Website betrieben.
    Es ist erstaunlich, wie klein und leichtgewichtig man einen HTTP/1.1-Webserver machen kann. Diese kommerzielle Site lief auf einer Maschine mit 128 MB RAM und einer CPU und bediente als Closed-Source, interaktives webbasiertes Chatsystem regelmäßig einen beträchtlichen Teil der Schulen im Vereinigten Königreich. Allerdings war das vor 20 Jahren, als das Internet weniger feindselig war als heute.
    Im Beitrag heißt es, Bots seien großartige Fuzzer, aber ich denke trotzdem, dass man auch ein wenig echtes Fuzzing machen sollte.
    http://git.annexia.org/?p=rws.git;a=tree
    Benötigt:
    http://git.annexia.org/?p=c2lib.git;a=tree
    http://git.annexia.org/?p=pthrlib.git;a=tree

    • Wenn man einen Webserver dieser Größe betreiben und sich nicht allzu sehr vor dem feindseligen Internet sorgen will, ist Rust eine gute Wahl.
      Meine Website https://blessed.rs läuft auf der kleinsten VM, die ich finden konnte, mit 256 MB RAM, verwendet aber normalerweise nur etwa 60 MB.
    • Das wirkt deutlich praktischer als mein kleiner, leichtgewichtiger HTTP/1.0-Webserver, aber rws ist vermutlich nicht ganz so klein und leichtgewichtig: http://canonical.org/~kragen/sw/dev3/server.s http://canonical.org/~kragen/sw/dev3/httpdito-readme
      Wirklich überraschend war, dass Linux-fork enorm schnell wird, wenn die Memory Map nur aus fünf 4-KB-Seiten besteht.
  • Das ist ein kleines Projekt, das ich zum Spaß in meiner Freizeit begonnen habe, und ich dachte, es könnte hier gefallen :)

    • Es ist eine interessante Übung, alte HTTP-Server-Bugs und CVEs durchzugehen und zu prüfen, ob sie auch meinen Code betreffen könnten und wie man sie beheben würde. So etwas selbst zu bauen macht Spaß.
    • Außerdem wollte ich ohnehin die C11-Concurrency-API ausprobieren, und aus der C++-Perspektive kommend war ich neugierig, wie diese Konstrukte in C funktionieren; deshalb wollte ich etwas Serverähnliches schreiben.
  • Großartig. Ich fand es schon immer und finde es immer noch sehr befriedigend, auf diese Weise mit den niedrigsten System-APIs einen minimalen Dienst hochzufahren
    Es wirkt fast magisch, erst recht, wenn man sieht, dass er echten Traffic verarbeitet. Dass ein ganz normales poll() solche Werte liefern kann, hat mich etwas überrascht, aber ich habe schon lange nicht mehr auf dieser Ebene mit Events oder Benchmarks gearbeitet
    Mir gefällt auch die Verwaltung der Verbindungen über Funktionen pro Verbindung und zugehörige Structs und Arrays, ebenso das Array der poll-Dateideskriptoren. Das erinnert an die Vorgehensweise vieler Open-Source-Pakete, die für hohen Durchsatz bekannt sind, wie nginx, Redis oder memcached

    • An der Uni mit C/C++ zu arbeiten, fühlte sich an, als würde einem der Kopf platzen. Es war eine sehr besondere und demütig machende Erfahrung, in der ein bisschen von allem steckte, was ich mag: Ingenieurwesen, Geschichte, Kultur, Linguistik usw.
      Das brachte mich zu der Ansicht, dass jeder alle möglichen Sprachen, ob Programmiersprachen oder natürliche Sprachen, kennen und ausprobieren sollte. In einer bestimmten Sprache zu denken ist eine einzigartige Erfahrung. Unterschiedliche Kontexte lassen alles anders wirken, und selbst wenn man am Ende Ähnliches tut, ändert sich die Perspektive
      Um zum Beispiel das Wesen von Linux oder Git wirklich zu verstehen, muss man diese Sprache sprechen und die Nuancen verstehen, die in der Übersetzung normalerweise verloren gehen. Ähnlich wie man Russisch sprechen und verstehen muss, um die wirkliche subjektive Bedeutung des russischen Wortes für „Wald“ zu begreifen
      Kontext verändert die Perspektive, und manchmal verändert er alles
    • Stimme völlig zu. Und wenn man es tatsächlich benutzt, ist es noch befriedigender. Jetzt werde ich auch neugierig auf E-Mail-Protokolle
      Ich war ebenfalls überrascht, dass ein gewöhnliches poll() so viel aushält. Ich dachte, ich würde irgendwann auf epoll umsteigen, aber poll() funktioniert ausgesprochen gut
    • Was die Leute offenbar vergessen: Auch all die großartigen und schicken Abstraktionen tun im Kern am Ende genau dasselbe. Sie öffnen einen Socket, lesen und schreiben
      Es gibt nichts Neues unter der Sonne
  • Das hier könnte ebenfalls interessant sein: https://news.ycombinator.com/item?id=27431910
    Stand 2024 verarbeitet die althttpd-Instanz von sqlite.org mehr als 500.000 HTTP-Requests pro Tag, etwa 5 bis 6 pro Sekunde, und liefert pro Tag rund 200 GB Content, etwa 18 Mbit/s, von einem Linode für 40 Dollar im Monat aus. Der Load Average dieser Maschine bleibt normalerweise in der Nähe von 0,5. Etwa 19 % der HTTP-Requests sind CGI-Aufrufe an mehrere Fossil-Quellcode-Repositories

    • Dieser Artikel hat mich stark inspiriert. Er hat mir klar gemacht, dass so etwas tatsächlich möglich ist
  • Wenn man eine C-App schreiben möchte, sich aber unwohl dabei fühlt, den Teil, der direkt am öffentlichen Internet hängt, selbst zu schreiben, ist Kore ein brauchbares Framework
    Es hat praktische eingebaute Funktionen wie ACME-Zertifikatsverwaltung, Pgsql, curl und WebSockets
    Grundsätzlich kann man Module bauen, ausführen und kombinieren; außerdem lassen sich Lua/Python und C mischen
    https://kore.io/

  • Endlich eine Website, die nicht stirbt, wenn sie auf die Startseite kommt

    • Mit einem CDN davor kann das jede Website
      Das soll nicht heißen, dass dieses Projekt nicht großartig wäre, aber wenn einem das in der Produktion wirklich wichtig ist und man überwiegend statischen Content ausliefert, sollte man einfach ein CDN verwenden. Das wird praktisch immer besser performen als fast alles, was man selbst schreibt. Es macht nur weniger Spaß
    • Zeigt der Link nicht auf GitHub? Dieser Kommentar verwirrt mich etwas
      Das Projekt ist sauber und cool, aber ich vermute, die meisten werden zu GitHub gehen und nicht zu einem Link, der die Webseite anzeigt. Übersehe ich etwas?
  • Mir gefällt die Stelle: „Ich habe Spaß daran, meine eigenen Tools zu bauen, und bin es etwas leid zu hören, dass alles praxiserprobt sein muss. Na und, wenn es abstürzt? Bugs kann man beheben :^)“

  • Ein vollständiger HTTP- und HTTPS-Server in nur 3,4k Zeilen C-Code? Um die Spezifikation vollständig einzuhalten, hätte ich ehrlich gesagt mit deutlich mehr gerechnet

    • HTTP/1.1 ist sehr einfach, wenn man den Großteil der Spezifikation ignoriert
      Wenn man nur GET-Requests annimmt und in der Antwort Content-Length setzt, reicht das für 99 % der User Agents. Auch der Umgang mit Transfer-Encoding und Byte-Range-Headern lässt den Code nicht massiv anwachsen
      HTTPS ist nur HTTP über einem TLS-Socket, und wenn man die Verschlüsselung nicht selbst implementiert, sollte genau das die Abstraktionsebene sein. Interessant und in der Praxis gar nicht so schlimm
    • Das wirkt für mich angemessen. OpenBSDs httpd(8) [1] hat aktuell, inklusive Dokumentation, auch etwas weniger als 15.000 Zeilen
      Wenn man ein paar Features weglässt und einige Annahmen trifft, wäre es nicht überraschend, wie dieses Projekt in den Bereich von 5.000 Zeilen zu kommen
      Das Ergebnis von $ wc -l * sind insgesamt 14815 Zeilen
      [1]: https://man.openbsd.org/httpd.8
    • In einem meiner Experimente habe ich einen einfachen eingebetteten C-Webserver verwendet, um eine Live-View zur Datenerfassung bereitzustellen; der hatte weniger als 250 Zeilen
      Natürlich würde ich ihn nicht ins öffentliche Internet stellen und er implementierte nur einen sehr kleinen Teil von HTTP/1.1, aber er funktioniert und benötigt malloc nur bei der Initialisierung
    • Es gibt noch einige weitere HTTP/1.1-Server dieser Größenordnung: https://www.acme.com/software/thttpd/benchmarks.html
  • Das erinnert mich an einen Vortrag beim Chaos Communication Congress über einen in C geschriebenen Blog-/Webserver
    Darin ging es um viele Sicherheitsfunktionen wie unveränderlichen Speicher, Privilege Dropping und darum, zu verhindern, dass der Blog Zugriff auf TLS-Zertifikate bekommt: https://www.youtube.com/watch?v=TaE28fJVPTk