2 poin oleh GN⁺ 2024-09-26 | 1 komentar | Bagikan ke WhatsApp
  • BlogTech adalah toolkit berbasis C untuk mengelola situs web skala kecil hingga menengah, menyediakan HTTPS, virtual host, manajemen sertifikat otomatis berbasis ACME, dan klien untuk manajemen server jarak jauh
  • Saat ini masih dalam tahap pengujian; versi 0.4.x telah digunakan untuk beroperasi selama beberapa minggu, tetapi tidak dipresentasikan sebagai rilis stabil
  • Server berjalan di Linux dan Windows, tetapi HTTPS hanya didukung di Linux; di Windows, baik klien maupun server hanya dapat menggunakan HTTP
  • Manajemen file jarak jauh ditangani dengan --put, --get, --delete, dan permintaan yang mengubah resource diautentikasi dengan tanda tangan HMAC/SHA256 berbasis shared secret key
  • Di lingkungan produksi, diperlukan server HTTP pada port 80 dan record DNS domain; jika ACME diaktifkan, file sertifikat dan private key dibuat otomatis, dan kesalahan dicatat di acme.log

Tujuan dan status BlogTech saat ini

  • BlogTech adalah toolkit untuk mengelola situs web skala kecil hingga menengah
  • Fitur yang didukung adalah sebagai berikut
    • HTTPS

    • Virtual host

      • Manajemen sertifikat otomatis melalui ACME
      • Klien untuk manajemen server jarak jauh
      • Masih dalam tahap pengujian
      • Ada contoh versi 0.4.x yang berhasil melayani https://coz.is/ selama beberapa minggu
      • Versi lama satu file ada di branch single_file

Build dan eksekusi dasar

  • BlogTech berjalan di Linux dan Windows
    • Build Linux memerlukan library pengembangan OpenSSL dan gcc
    • Build Windows memerlukan clang
  • Build dilakukan dengan skrip khusus platform
    • Linux: ./build.sh
    • Windows: .\build.bat
  • Hasil build adalah sebagai berikut
    • Linux: blogtech
    • Windows: blogtech.exe
  • Di Linux, instalasi dapat dilakukan dengan ./install.sh
  • Contoh menjalankan server dasar adalah membuat direktori docroot dan menentukan --serve, --document-root=docroot, --skip-auth-check
  • Server HTTP dasar mendengarkan di 127.0.0.1:8080 dan menyajikan konten dari docroot
  • Jika docroot kosong, akses ke http://127.0.0.1:8080/ akan mengembalikan 404

Manajemen file jarak jauh dan autentikasi

  • BlogTech dapat mengunggah file ke server dalam mode klien
    • Mengunggah file dengan --put
    • Mengunduh file jarak jauh dengan --get
    • Menghapus file jarak jauh dengan --delete
  • Meski klien dan server dijalankan di mesin yang sama, maupun terhadap server di mesin jarak jauh, cara kerjanya sama
  • Permintaan yang mengubah resource ditandatangani secara digital dengan tanda tangan HMAC/SHA256
  • Klien dan server harus berbagi secret key yang sama, dan secara konvensi disimpan dalam file admin.pwd
  • File kata sandi ditentukan dengan opsi --auth-password-file
  • Jika file kata sandi tidak ada, semua permintaan yang memerlukan autentikasi akan ditolak
  • Kata sandi kosong juga ditolak
  • Selama pengembangan, --skip-auth-check dapat digunakan untuk memperlakukan semua permintaan sebagai terautentikasi
    • Jika opsi ini digunakan, --auth-password-file akan diabaikan meskipun ditentukan
    • Harus digunakan dengan hati-hati
  • Header autentikasi dan kondisi pengiriman ulang

    • Permintaan HTTP yang terautentikasi menyertakan header X-BlogTech-
    • X-BlogTech-Nonce: token yang dipilih secara acak oleh klien
    • X-BlogTech-Timestamp: UNIX timestamp saat permintaan pertama kali ditandatangani
    • X-BlogTech-Expire: waktu dalam satuan detik sejak saat penandatanganan selama permintaan valid
    • X-BlogTech-Signature: nilai HMAC dari informasi permintaan yang dienkode dalam Base64
    • Tanda tangan diperoleh dengan membuat string permintaan yang dinormalisasi, lalu menghitung HMAC/SHA256 menggunakan kata sandi autentikasi sebagai key, dan mengenkode hasilnya ke Base64 termasuk padding
    • Nonce yang sudah pernah dilihat server disimpan di memori
    • Jika server dimuat ulang, nonce sebelumnya akan dilupakan, sehingga permintaan yang belum kedaluwarsa dapat dikirim ulang

Virtual host dan pemetaan direktori

  • BlogTech dapat meng-host beberapa situs web pada server yang sama
  • Domain diatur dengan menentukan opsi --domain beberapa kali
  • BlogTech membuat direktori per domain di dalam document root
    • default
    • websiteA.com
    • websiteB.com
  • Permintaan yang masuk ke host tertentu mengacu pada direktori yang terhubung dengan host tersebut
  • Permintaan yang tidak terhubung ke folder tertentu mengacu pada direktori default
  • Dalam contoh, file yang diunggah ke websiteA.com, websiteB.com, other.com masing-masing disimpan di direktori domain atau direktori default

HTTPS dan pengaturan sertifikat

  • HTTPS hanya didukung di Linux
  • Ini karena library HTTP yang mendasarinya, cHTTP, mengimplementasikan HTTPS dengan OpenSSL
  • Di Windows, baik klien maupun server hanya dapat menggunakan HTTP
  • Untuk mengaktifkan HTTPS, opsi berikut diperlukan
    • --https-enabled
    • --cert-file
    • --cert-key-file
  • Alamat listen HTTPS default adalah 127.0.0.1:8443
  • Alamat listen dan port dapat diubah dengan opsi berikut
    • --https-addr=<addr>
    • --https-port=<port>
  • Selama pengembangan, sertifikat self-signed dapat dibuat dengan perintah OpenSSL
  • Browser tidak mengizinkan penelusuran server HTTPS yang menggunakan sertifikat self-signed
  • cURL harus menggunakan flag --insecure agar dapat mengakses server dengan sertifikat self-signed
  • Jika diperlukan beberapa sertifikat, --extra-cert dapat diberikan sebagai tambahan
    • Sertifikat default disediakan melalui --cert-file, --cert-key-file
    • Sertifikat tambahan digunakan saat klien meminta domain tertentu
  • Opsi command line yang panjang dapat dipindahkan ke file konfigurasi

Penerbitan sertifikat otomatis berbasis ACME

  • Protokol ACME memungkinkan web server secara otomatis meminta penerbitan sertifikat ke certificate authority
  • BlogTech mendukung alur memulai mode HTTPS tanpa sertifikat, lalu sertifikat dibuat
  • Di lingkungan produksi, syarat berikut diperlukan
    • Menjalankan server HTTP pada port 80
    • Membuat record DNS yang menghubungkan domain dengan mesin tempat server berjalan
  • ACME diaktifkan dengan menentukan --acme-enabled bersama opsi HTTPS
  • Berbeda dengan mode HTTPS biasa, dalam mode ACME sertifikat diharapkan belum ada
  • Untuk membuat sertifikat, nilai berikut diperlukan
    • --acme-domain
    • --acme-email
    • --acme-country
    • --acme-organization
    • --acme-agree-tos
  • Jika berhasil diproses, file berikut dibuat
    • acme_key.pem: private key yang terhubung dengan akun ACME
    • cert.pem: sertifikat yang diterbitkan atau file yang ditentukan dengan --cert-file
    • key.pem: private key yang terhubung dengan sertifikat atau file yang ditentukan dengan --cert-key-file
  • Jika terjadi kesalahan, pesan dicatat di acme.log
  • Jika --acme-domain ditentukan beberapa kali, beberapa domain dapat diproses dengan ACME
  • Sertifikat hasilnya mencakup semua domain yang ditentukan

Pengujian klien ACME

  • Untuk menguji klien ACME di Linux, Anda harus memasang Docker dan meng-clone Pebble ACME server
  • Pada docker-compose.yml, tambahkan entri extra_hosts yang menghubungkan domain pengujian ke host-gateway
  • Pada /etc/hosts, petakan domain pengujian ke 127.0.0.1
  • Pebble dijalankan dengan docker compose up
  • BlogTech menjalankan instance pengujian dengan ./blogtech -s --config=misc/pebble_blogtech.conf
  • Interaksi dengan server ACME dicetak ke stdout
  • Jika berhasil, acme_key.pem, cert.pem, key.pem dibuat
  • Pengujian perpanjangan sertifikat dapat dilakukan dengan mengubah nilai validityPeriod di pebble/test/config/pebble-config.json
  • Dengan opsi --acme-force-renewal-period=<maximum duration in ms>, BlogTech dapat diinstruksikan untuk memperpanjang sertifikat meskipun belum kedaluwarsa

File konfigurasi dan pemuatan otomatis

  • BlogTech dapat memindahkan jumlah argumen command line berapa pun ke file konfigurasi
  • Misalnya, opsi terkait HTTPS dan ACME dapat ditulis di blogtech_server.conf, lalu dijalankan dengan --config=blogtech_server.conf
  • Jika nama file konfigurasi persis blogtech.conf, BlogTech akan memuatnya secara otomatis
  • Dalam kasus ini, dapat dijalankan seperti ./blogtech --serve
  • Untuk mengabaikan pemuatan file konfigurasi implisit, gunakan --no-config

Log crash dan daemon systemd

  • Jika BlogTech crash dalam mode server, file crash.bin akan dibuat
  • Saat server berikutnya dimulai, crash.bin dikonversi menjadi crash.log, stack trace yang dapat dibaca manusia
  • Proses mengubah alamat menjadi nama simbol atau nomor baris mungkin agak tidak stabil
  • BlogTech dapat dipasang sebagai daemon systemd
  • Contoh blogtech.service menjalankan /root/blogtech/blogtech -s, memulai ulang saat gagal, dan mengatur direktori kerja ke /root/blogtech/
  • Opsi server dimuat otomatis dari /root/blogtech/blogtech.conf
  • Setelah menyalin file service ke /etc/systemd/system/, aktifkan dan mulai dengan perintah berikut
    • systemctl daemon-reload
    • systemctl enable blogtech
    • systemctl start blogtech
  • Manajemen service dilakukan dengan systemctl start, systemctl stop, systemctl restart, journalctl -u blogtech

1 komentar

 
GN⁺ 2024-09-26
Komentar Hacker News
  • Bagian “tidak perlu reverse proxy” selalu membuat saya heran
    Kalau tidak ada alasan khusus mengapa reverse proxy membantu, saya biasa mengekspos aplikasi Jetty embedded langsung ke internet tanpa lapisan depan, dan tidak ada masalah
    Orang infrastruktur atau keamanan bertanya mengapa tidak menaruh nginx di depannya, tetapi saat ditanya alasannya, mereka hanya bicara samar tentang keamanan atau performa tanpa rincian. Jawaban paling spesifik yang pernah saya dengar adalah slow loris, tetapi itu sudah lama bukan masalah besar
    Saya penasaran apakah reverse proxy secara kolektif sudah menjadi cargo cult, atau saya melewatkan alasan bagus yang berlaku umum

    • Bagi saya, reverse proxy membuat server asal hanya perlu menyajikan aplikasi. Terminasi TLS, load balancing, penulisan ulang URL, dan fitur keamanan seperti WAF bila diperlukan semuanya bisa ditangani di reverse proxy, sehingga terjadi pemisahan peran
      Secara keseluruhan, ini melindungi server asal dan membuatnya hanya menerima trafik yang relevan. Saat menyediakan domain kustom untuk pelanggan pun, DNS pelanggan menunjuk ke reverse proxy, bukan server asal, jadi jika perlu mengganti server asal, kita tidak perlu khawatir pelanggan harus mengubah DNS
    • Saya menjalankan beberapa program server di homelab
      Masing-masing berjalan di port berbeda, tetapi saya ingin semuanya bisa diakses publik lewat URL yang berbeda-beda dan hanya ingin mengekspos port 443 ke internet
      Saya juga ingin sertifikat TLS tiap domain diperbarui otomatis. Untuk kebutuhan pertama reverse proxy diperlukan, dan Caddy melakukan keduanya
      Jika hanya mengoperasikan satu server dan server itu juga melakukan terminasi TLS, reverse proxy tidak wajib diperlukan
    • Pada sebagian besar deployment, dampak performa reverse proxy bisa diabaikan, dan konfigurasinya juga sudah saya siapkan sebelumnya
      Karena nantinya terminasi TLS, penulisan ulang URL, dan pekerjaan lain bisa ditambahkan tanpa banyak repot, saya jadi memakainya sebagai kebiasaan, dan sejauh ini kebiasaan itu terbayar
    • Jika menjawab untuk berbagai jenis server yang ditempatkan di depan aplikasi web, ada beberapa cara perangkat tambahan bisa membantu baik dari sisi keamanan maupun performa
      Dari sisi keamanan, saya ingin seluruh sistem memakai kode sesedikit mungkin dan sistem operasi yang tangguh. Aplikasi bertipe proxy bisa jauh lebih sederhana daripada server web/aplikasi, dan juga bisa memfilter trafik masuk, memvalidasi input, atau mengubahnya menjadi bentuk yang lebih aman dan cepat untuk di-parse. Proxy itu juga bisa dijalankan di sistem operasi yang sulit diserang seperti OpenBSD, GenodeOS, atau INTEGRITY-178B
      Dari sisi ketersediaan, sering kali lebih aman menaruh load balancing, monitoring, dan recovery di sistem seperti ini, karena server aplikasi bisa lebih sering mati
      Dari sisi performa, keunggulannya pertama-tama adalah aplikasi yang sederhana dan terfokus bisa dioptimalkan tinggi. Setelah itu, kompresi atau enkripsi bisa dipercepat dengan akselerator CPU atau perangkat keras PCI, yang sering disebut offloading. Konfigurasi yang paling hemat biaya adalah banyak server serbaguna mendapatkan manfaat dari sedikit server offloading mahal. Sebagian juga mengurangi penggunaan sumber daya mahal dengan load balancing yang mengirim trafik masuk ke server yang paling mampu menanganinya
    • Saya tidak melihat ada generalisasi yang berlaku untuk semua server
      Dalam konfigurasi minimal memang tidak perlu, tetapi bahkan pada lingkungan operasi satu host, itu memungkinkan rolling release, kompresi, TLS, penyajian file statis yang cepat, dan potensi A/B testing
      Lapisan tidak langsung antara request dan server bisa cukup berguna
  • Keren. Saya juga dulu pernah menulis web server C sendiri, dan source-nya ada di bawah. Sempat dipakai menjalankan situs web komersial juga
    Menakjubkan betapa kecil dan ringannya HTTP/1.1 web server bisa dibuat. Situs komersial itu berjalan di mesin dengan RAM 128MB dan 1 CPU, dan secara rutin melayani banyak sekolah di Inggris sebagai sistem chat interaktif berbasis web yang closed source. Namun itu cerita 20 tahun lalu, saat internet belum sebermusuhan sekarang
    Artikel itu mengatakan bot berperan sebagai fuzzer yang bagus, tetapi menurut saya tetap sebaiknya melakukan sedikit fuzzing sungguhan
    http://git.annexia.org/?p=rws.git;a=tree
    Dependensi:
    http://git.annexia.org/?p=c2lib.git;a=tree
    http://git.annexia.org/?p=pthrlib.git;a=tree

    • Jika ingin menjalankan web server sebesar ini tanpa terlalu khawatir terhadap internet yang bermusuhan, Rust adalah pilihan yang bagus
      Situs web saya https://blessed.rs berjalan di VM terkecil yang bisa saya temukan, dengan RAM 256MB, tetapi biasanya hanya memakai sekitar 60MB
    • Ini terlihat jauh lebih praktis daripada HTTP/1.0 web server kecil dan ringan yang saya buat, tetapi saya kira rws tidak sekecil dan seringan itu: http://canonical.org/~kragen/sw/dev3/server.s http://canonical.org/~kragen/sw/dev3/httpdito-readme
      Hal yang benar-benar mengejutkan adalah fork di Linux menjadi sangat cepat jika memory map hanya terdiri dari lima halaman 4KB
  • Ini proyek kecil yang saya mulai di waktu luang untuk bersenang-senang, dan saya pikir orang-orang di sini akan menyukainya :)

    • Menelusuri bug HTTP server lama dan CVE untuk melihat apakah itu bisa memengaruhi kode saya dan bagaimana memperbaikinya menjadi latihan yang menarik. Membuat hal seperti ini sendiri memang menyenangkan
    • Kebetulan saya ingin mencoba API concurrency C11, dan sebagai orang yang datang dari C++, saya penasaran bagaimana struktur-struktur itu bekerja di C, jadi saya ingin menulis sesuatu yang mirip server
  • Luar biasa. Sejak dulu saya selalu berpikir bahwa menjalankan layanan minimal dengan memakai API sistem pada level serendah ini benar-benar memuaskan, dan sekarang pun masih begitu
    Rasanya nyaris seperti sihir, apalagi saat melihatnya menangani trafik sungguhan. Agak mengejutkan juga bahwa poll() biasa bisa menghasilkan angka seperti itu, tapi mungkin karena sudah lama saya tidak menangani event atau benchmark di level tersebut
    Saya juga suka pendekatan fungsi per koneksi beserta struct terkait, pengelolaan koneksi dengan array, dan array file descriptor untuk poll. Itu mengingatkan saya pada cara kerja berbagai paket open source yang dikenal punya throughput tinggi, seperti nginx, Redis, dan memcached

    • Saat mempelajari C/C++ di universitas, rasanya kepala saya mau meledak. Itu pengalaman yang sangat khas dan membuat rendah hati, berisi sedikit dari semua hal yang saya sukai—rekayasa, sejarah, budaya, linguistik, dan sebagainya
      Saya jadi berpikir semua orang sebaiknya mengetahui dan mencoba sebanyak mungkin bahasa, baik bahasa pemrograman maupun bahasa alami. Berpikir dalam suatu bahasa adalah pengalaman yang unik. Konteks yang berbeda membuat semuanya terasa berbeda, dan bahkan ketika pada akhirnya melakukan hal yang mirip, sudut pandangnya berubah
      Misalnya, untuk benar-benar memahami esensi Linux atau Git, kita perlu berbicara dalam bahasa itu dan memahami nuansa yang biasanya hilang dalam terjemahan. Mirip seperti untuk memahami makna subjektif sebenarnya dari kata “hutan” dalam bahasa Rusia, kita perlu berbicara dan memahami bahasa Rusia
      Konteks mengubah sudut pandang, dan kadang mengubah segalanya
    • Sepenuhnya setuju. Dan saat benar-benar dipakai, rasanya bahkan lebih memuaskan. Sekarang saya mulai penasaran juga dengan protokol email
      Saya juga terkejut bahwa poll() biasa bisa bertahan sejauh itu. Saya kira suatu saat harus pindah ke epoll, tapi poll() bekerja dengan sangat baik
    • Orang-orang tampaknya lupa bahwa semua abstraksi yang bagus dan keren itu, pada intinya, tetap melakukan hal yang sama. Membuka soket, membaca, dan menulis
      Tidak ada yang baru di bawah matahari
  • Ini juga mungkin menarik: https://news.ycombinator.com/item?id=27431910
    Per 2024, instance althttpd milik sqlite.org menangani lebih dari 500 ribu request HTTP per hari, sekitar 5–6 per detik, dan menyajikan sekitar 200GB konten per hari, sekitar 18Mbit/s, dari Linode seharga 40 dolar per bulan. Load average mesin ini biasanya berada di sekitar 0,5. Sekitar 19% request HTTP adalah CGI ke beberapa repositori kode sumber Fossil

    • Tulisan itu sangat menginspirasi saya. Itu membuat saya sadar bahwa hal seperti ini memang benar-benar mungkin
  • Jika ingin menulis aplikasi C tetapi merasa tidak nyaman menulis sendiri bagian yang langsung terpapar internet publik, Kore adalah framework yang cukup bagus
    Ada fitur bawaan yang praktis seperti manajemen sertifikat ACME, Pgsql, curl, dan WebSocket
    Pada dasarnya kita bisa membangun, menjalankan, dan menggabungkan modul, serta memungkinkan mencampur Lua/Python dengan C
    https://kore.io/

  • Akhirnya ada situs web yang tidak mati meski masuk halaman depan

    • Dengan CDN di depannya, situs apa pun bisa begitu
      Bukan berarti proyek ini tidak hebat, tetapi kalau hal seperti ini benar-benar penting di lingkungan produksi dan sebagian besar kontennya statis, pakai saja CDN. Performanya hampir selalu akan lebih baik daripada apa pun yang kita tulis sendiri. Hanya saja tidak menyenangkan
    • Bukankah tautannya mengarah ke GitHub? Komentar ini agak membingungkan
      Proyeknya rapi dan keren, tapi sepertinya kebanyakan orang akan pergi ke GitHub, bukan ke tautan yang menampilkan halaman web. Apakah saya melewatkan sesuatu?
  • Saya suka bagian yang berbunyi, “Saya senang membuat alat saya sendiri, dan saya agak lelah mendengar bahwa semuanya harus teruji di dunia nyata. Jadi kalau mati, lalu kenapa? Bug bisa diperbaiki :^)”

  • Server HTTP dan HTTPS lengkap hanya dengan 3,4 ribu baris kode C? Jujur saya kira untuk sepenuhnya mematuhi spesifikasi dibutuhkan jauh lebih banyak

    • HTTP/1.1 sangat sederhana kalau sebagian besar spesifikasinya diabaikan
      Kalau hanya menerima request GET dan menetapkan Content-Length pada respons, itu sudah cukup untuk 99% user agent. Menangani Transfer-Encoding dan header byte range pun tidak banyak menambah kode
      HTTPS hanyalah HTTP di atas soket TLS, dan kalau tidak mengimplementasikan kriptografi sendiri, tingkat abstraksinya memang kurang lebih segitu. Menarik, dan sebenarnya tidak seburuk itu
    • Ukuran ini terlihat masuk akal. httpd(8) [1] dari OpenBSD pun saat ini sedikit di bawah 15.000 baris, termasuk dokumentasi
      Jika menghapus beberapa fitur dan membuat beberapa asumsi, saya tidak akan terkejut kalau bisa masuk kisaran 5.000 baris seperti proyek ini
      Hasil $ wc -l * totalnya 14815 baris
      [1]: https://man.openbsd.org/httpd.8
    • Dalam salah satu eksperimen saya, saya memakai server web C embedded sederhana untuk menyediakan live view pengumpulan data, dan ukurannya kurang dari 250 baris
      Tentu saja saya tidak akan menaruhnya di internet publik dan itu hanya mengimplementasikan sebagian sangat kecil dari HTTP/1.1, tetapi ia bekerja dan hanya membutuhkan malloc saat inisialisasi
    • Ada beberapa server HTTP/1.1 lain dengan ukuran seperti ini: https://www.acme.com/software/thttpd/benchmarks.html
  • Saya teringat presentasi Chaos Communication Congress tentang blog/server web yang ditulis dalam C
    Isinya tentang banyak fitur keamanan seperti penyimpanan immutable, penurunan hak akses, dan memastikan blog tidak bisa mengakses sertifikat TLS: https://www.youtube.com/watch?v=TaE28fJVPTk