← Blog

· 15 min čtení #rust#mqtt#iot#unikernel#open source

urMQTT: stavíme MQTT broker, který je zároveň operačním systémem

Vývojářské poznámky o urMQTT, unikernelu napsaném v Rustu, který sám o sobě je MQTT broker: jeden ELF s vlastním TCP/IP, TLS 1.3, brokerem a SQLite, spouštěný z jediného ISO.

Zařízení ve vozidlech, na parkovištích a ve skříních s elektronikou mají jednu společnou vlastnost: posílají malé zprávy, zřídka, ale je jich mnoho a jsou neustále připojená. Roky je připojujeme k MQTT brokerům a roky nás trápí stejná otázka. Proč potřebujeme pro něco tak jednoduchého celý Linux, OpenSSL, runtime nějakého jazyka, SSH, správce balíčků a teprve pak broker? Každá z těchto vrstev přináší vlastní zranitelnosti, spotřebovává vlastní paměť a přidává další věc, která se může porouchat, a flotila zařízení od serveru potřebuje jen tři věci: aby držel velké množství téměř nečinných spojení, aby spolehlivě autentizoval každé zařízení a aby doručil zprávy bez ztrát.

Tak vznikl urMQTT: unikernel, který je MQTT broker. Jádro, TCP/IP, TLS 1.3, MQTT a vestavěná databáze v jediném binárním programu v Rustu, který se spouští z jediného ISO. Žádné procesy, žádná systémová volání, žádný shell. První platforma, na které vzniká a je testován, je aarch64, a stejný kód míří na x86_64, přes UEFI i klasický BIOS, a na skutečný hardware: cílem je jedno ISO, které nabootuje na všech. Projekt je open source pod licencí MIT nebo Apache 2.0 a v tomto textu chceme zaznamenat, kde jsme, jak je uvnitř poskládaný a co jsme se cestou naučili.

Co přesně znamená „unikernel"

Běžný broker je program, který běží na operačním systému. urMQTT pod sebou žádný operační systém nemá: zavádí se sám přes firmware UEFI a bootloader Limine, nastavuje si vlastní stránkové tabulky, programuje řadič přerušení a časovač, nachází zařízení virtio přes PCIe, získá adresu pomocí DHCP a naslouchá na jediném portu. Všechno, co by jinak dělalo jádro, ovladače, síťový zásobník a aplikace, je tady jediný ELF běžící na úrovni EL1.

Srovnání s typickou instalací mluví samo za sebe:

Typický broker na Linuxu urMQTT
Vystavené služby SSH, broker, často i port pro metriky nebo administraci pouze TCP 8883 (MQTT přes TLS 1.3 s mTLS)
Kód v obrazu jádro, userland, libc, OpenSSL, runtime jeden ELF v Rustu (plus vendorovaný SQLite)
Vzdálená správa shell, konfigurační soubory, aktualizace balíčků nic. Nová verze je nové ISO
Paměť na nečinné spojení kilobajty (vyrovnávací paměti socketu, objekty TLS, halda) cíl ≤ 512 B
Vícejádrový model vlákna a zámky nebo jedna smyčka událostí vlákno na jádro, bez sdíleného stavu, zpracování do konce
Integrita kódu možná jsou mapování, která jsou zároveň zapisovatelná i spustitelná W^X, zamčené stránkové tabulky, PAC/BTI

Priority jsou v tomto pořadí: bezpečnost, škálovatelnost, vícejádrový výkon, malá stopa a neměnná instalace. Kdykoli jsou dva cíle v rozporu, vítězí ten, který je na tomto seznamu výše.

Kde jsme teď

Projekt je v pre-alfa fázi, ale uzavřeli jsme sedmnáct vývojových milníků, od M0 do M17. Dnes urMQTT obsluhuje MQTT 3.1.1 přes TLS 1.3 s povinnými klientskými certifikáty a stav ukládá do SQLite na surovém disku. Stručně, co už funguje:

  • Jádro: vlastní vektory výjimek s dekódovanými hlášeními, vlastní stránkové tabulky s vynuceným W^X, ochranné stránky, PAC a BTI tam, kde je procesor má, GICv3 a GICv2, generický časovač, SMP až do 64 jader.
  • Detekce hardwaru z DTB nebo ACPI do jednoho popisu platformy, s totožným výsledkem z obou zdrojů.
  • Ovladače: PCIe ECAM, MSI-X, virtio-net, virtio-blk, virtio-scsi a virtio-rng, a také CSPRNG osazený hardwarovou entropií.
  • Síť: vlastní DHCPv4, ARP, ICMP a přísné IPv4, dále vlastní TCP pouze pro stranu serveru: SYN cookies, hierarchické kolo časovačů, NewReno, slučování ACK, bez stavu TIME_WAIT.
  • TLS: pouze TLS 1.3, povinné mTLS, identita zařízení z CN nebo SAN URI; handshake zajišťuje rustls, po něm následuje vlastní vrstva záznamů s AES-128-GCM a ChaCha20-Poly1305. Obnovení relace pomocí PSK ticketů, seznam odvolaných certifikátů, řízení příjmu už při handshaku.
  • MQTT: kodek bez kopírování, fuzzovaný a testovaný se skutečnými klienty mosquitto; QoS 0 a 1, zástupné znaky, retained zprávy, závěť (LWT), trvalé relace, ACL s omezením na devices/{id}/#, limity rychlosti na zařízení.
  • Úložiště: SQLite uvnitř jádra přes VFS nad surovým diskem, v režimu WAL, s kontrolou integrity při startu; registr zařízení, odvolání, retained zprávy, trvalé relace s frontami zpráv pro zařízení, která jsou offline; na každé jádro samostatný telemetrický žurnál s CRC u každého záznamu a obnovou po pádu.
  • Provoz a dohled: watchdog časovač pro obslužné rutiny, kontrola zdraví, omezené logování, syslog a statsd přes UDP, řízení příjmu, které přežije bouře opakovaných připojení.
  • Dodání: bitově shodné opakované sestavení ověřované v CI, ISO a surový obraz disku GPT, podpisy minisign, návody pro KVM, Proxmox a Hetzner.

Každý krok je označen milníkem, který jej přinesl, a soubor docs/PROGRESS.md v repozitáři je jediným zdrojem pravdy o tom, co skutečně funguje.

Architektura ve třech obrázcích

Celý návrh je popsán v docs/ARCHITECTURE.md a důvody každého důležitějšího rozhodnutí jsou zapsány jako ADR v docs/DECISIONS.md. Zde je přehled.

Vrstvy

Vrstvy urMQTT: od brokeru přes kodek MQTT, TLS, TCP a síť až po ovladače virtio a architektonickou vrstvu, vše v jediném ELF na úrovni EL1.
Vrstvy urMQTT: od brokeru přes kodek MQTT, TLS, TCP a síť až po ovladače virtio a architektonickou vrstvu, vše v jediném ELF na úrovni EL1.

Odshora dolů: broker (relace, strom témat, QoS, retained zprávy, závěti, ACL, limity), kodek MQTT, TLS, TCP, síťová vrstva a pak ovladače. Vedle této hlavní cesty stojí úložiště (SQLite a telemetrický žurnál) a pod vším správa paměti, detekce platformy a konfigurace přeložená v době sestavení do konstant, spolu s vestavěným certifikátem CA, serverovým certifikátem a klíčem. Hypervizor se zařízeními virtio je jediné, co je mimo obraz.

Vlákno na jádro, bez sdíleného stavu

Model provádění: každé datové jádro má vlastní smyčku a vlastní část brokeru a nejvyšší jádro spouští pouze SQLite. Jádra spolu komunikují výhradně přes prstence SPSC.
Model provádění: každé datové jádro má vlastní smyčku a vlastní část brokeru a nejvyšší jádro spouští pouze SQLite. Jádra spolu komunikují výhradně přes prstence SPSC.

Každé datové jádro točí vlastní smyčku s vlastním zásobníkem TCP, stavy TLS, částí brokeru (relace a strom témat), cache haldy a oddílem telemetrie. Jádra nesdílejí žádný měnitelný stav, jen omezené prstence bez zámků, po jednom pro každou uspořádanou dvojici jader. Nejvyšší jádro spouští SQLite a nic jiného.

Síťová karta má dnes jeden pár front, který drží jádro 0. To každý tok MQTT podle Toeplitzova hashe jeho čtveřice směruje na jedno z pracovních jader a odesílá to, co pracovní jádra vrátí. Relace žije na svém domovském jádře, určeném hashem identifikátoru klienta, takže převzetí, závěti a trvanlivost nikdy nepřekračují hranice jader. Spojení, které přistane na jiném jádře, si tam ponechá svůj TCP a TLS, a běžný MQTT předává domovskému jádru s řízením toku založeným na kreditech. Každá směrovaná zpráva se rozesílá také ostatním částem brokeru, z nichž každá drží repliku retained zpráv.

Tento model drží pohromadě tři pravidla. Zpracování do konce: přijatý paket se zpracuje celý na jednom jádře, od TCP přes dešifrování TLS na místě, parsování MQTT a směrování až po šifrovanou odpověď, bez front úloh a bez kopírování do aplikačních vyrovnávacích pamětí. Adaptivní dotazování: pod zátěží se přijímací fronty aktivně dotazují, v klidu se jádro vrací k přerušením a WFI; obslužné rutiny přerušení pouze potvrdí přerušení a označí práci. Watchdog časovač: tik 10 ms na jádro zachytí obslužné rutiny, které překročí svůj rozpočet.

Život jednoho PUBLISH

Cesta jedné zprávy PUBLISH s QoS 1: od záznamu TLS na síťové kartě přes dešifrování, kontrolu ACL a směrování až po PUBACK sloučený s TCP ACK v jediném segmentu.
Cesta jedné zprávy PUBLISH s QoS 1: od záznamu TLS na síťové kartě přes dešifrování, kontrolu ACL a směrování až po PUBACK sloučený s TCP ACK v jediném segmentu.

Zařízení pošle záznam TLS. Síťová karta jej předá smyčce jádra deskriptorem, bez kopírování. Smyčka zkontroluje TCP, dešifruje TLS na místě a parsuje MQTT z vypůjčené vyrovnávací paměti, poté v paměti zkontroluje ACL, limit rychlosti a cestu stromem témat. Pokud má o toto téma zájem jiné jádro, dostane směrovací zprávu s odkazem na obsah a identifikátorem tématu; databáze dostane telemetrický záznam nebo aktualizaci retained zprávy, v dávce. Odpověď PUBACK se šifruje přímo do odchozí vyrovnávací paměti a sloučí se s TCP ACK, takže zařízení odchází jediný segment. Jiné jádro zpráva stojí jedno šifrování na odběratele v okamžiku odeslání.

Kolik stojí jedno spojení

Cílem je nejvýše 512 bajtů na nečinné TLS spojení, s ambicí dosáhnout 256. Dokud spojení odpočívá, nic se pro něj nedrží ve vyrovnávací paměti: přijatá data se zpracovávají přímo ze síťového rámce a vyrovnávací paměti pro odesílání, záznamy a MQTT existují jen tehdy, když je něco nedokončeno nebo nepotvrzeno. Jádro to samo měří: přesné čítače haldy v požadovaných bajtech i v blocích, které zabírají, zapisované každých deset sekund jako halda nad základní úrovní na otevřené spojení.

Část Velikost Jak
Řídicí blok TCP 96 B zabalené příznaky, 16bitové RTT/RTO, slot v kole časovačů, žádné vyrovnávací paměti v klidu
Slot v tabulce TCP 4–8 B pouze index spojení, tabulka nejvýše z poloviny plná
Spojení a stav záznamů TLS 1.3 152 B tajemství a sekvence na směr (40 B); klíč a IV se odvozují pro každý záznam
Spojení MQTT 48 B identita a závěť na haldě jen po dobu, kdy existují
Relace MQTT, horká podoba 64 B jedno předplatné v řádku, internované identifikátory uzlů
Předplatné devices/<id>/cmd/# 0 uzlů stromu uloženo relativně k identifikátoru relace, společné všem zařízením

Naměřeno pod HVF se čtyřmi virtuálními jádry, z toho třemi pracovními, přičemž každé zařízení drží spojení mTLS a jedno předplatné s QoS 1, včetně zaokrouhlování alokátoru:

Spojení Bajtů na spojení
960 531 B
9 922 494 B
10 197 474 B

Fond síťových rámců je pevný, zhruba 2 MiB, což je přibližně 200 B na spojení při deseti tisících spojení a asi 2 B při milionu. Více jsme změřit nedokázali: uživatelská síť QEMU na macOS přestala přijímat spojení na 10 197, zhruba na hranici 10 240 deskriptorů procesu QEMU. Číslo klesá, jak se pevné části rozkládají na více spojení, takže neroste s jejich počtem.

Bezpečnostní model

Bezpečnost je první priorita a vyhrává všechny rozpory s ostatními cíli. Model má několik vrstev:

  • Jeden port. TCP 8883, pouze TLS 1.3, povinné klientské certifikáty podepsané CA vestavěnou do obrazu. Identifikátor klienta MQTT musí být shodný s identifikátorem zařízení z certifikátu.
  • Žádný vstup. Žádný shell, konzolový vstup, SSH, administrační API, dynamický kód, SQL dostupný po síti ani souborový systém.
  • Paměťová bezpečnost. Rust, s forbid(unsafe_code) v protokolových balíčcích; každý blok unsafe má komentář // SAFETY:, který kontroluje lint, a na vnější vstup nedochází k panice: clippy v balíčcích na datové cestě zakazuje unwrap, expect, indexování a panic!.
  • Zmírnění zneužití. W^X se vynucuje kódováním deskriptorů a bitem SCTLR_EL1.WXN a revidují se při každém startu. Stránkové tabulky jsou po startu pouze pro čtení, bez zapisovatelného aliasu. Dolní polovina adresního prostoru je vyloučena. Každý zásobník má ochranné stránky a výjimky běží na samostatném zásobníku. PAC a BTI se zapínají, když je procesor podporuje, a ověřují to kouřové testy.
  • Odolnost proti zneužití. SYN cookies; řízení příjmu odmítá nová spojení, ještě před jakoukoli kryptografií, když je halda nízká, když databáze zaostává, když je příliš mnoho probíhajících handshaků na jádro nebo na zdrojovou adresu nebo když je rychlost handshaků příliš vysoká. Limity rychlosti na zařízení, omezené fronty, TCP okno vázané na protitlak brokeru, omezené logování, watchdog časovač a kontrola zdraví.
  • Neměnnost. Konfigurace, CA a serverový klíč jsou vestavěny do obrazu. Změna čehokoli znamená nový obraz.

Model hrozeb je zapsán v docs/SECURITY.md.

Úložiště bez souborového systému

Data žijí na samostatném disku, virtio-blk nebo virtio-scsi, na kterém není souborový systém. Rozvržení je minimální a vlastní:

LBA 0      [ superblok: magické číslo · verze rozvržení · uuid · tabulka oblastí · CRC-32C ]
LBA 8, 16  [ tabulka velikostí souborů, sloty A/B (vítězí nejnovější platný) ]
LBA 64     [ hlavní databáze SQLite ½ ][ SQLite WAL ⅛ ][ žurnál 1 MiB ][ telemetrický žurnál: 8 oddílů … ]
poslední 4 KiB [ prostor pro sebetest blokového zařízení při startu ]

SQLite (vendorovaná verze 3.54.1, s kontrolou otisku při sestavení) je přeložen do jádra clangem, bez standardní knihovny, a používá pevnou haldu memsys5. Jeho VFS mapuje tři pevné soubory na oblasti disku. Běží v režimu WAL s locking_mode=EXCLUSIVE, takže nepotřebuje index ve sdílené paměti, a se synchronous=FULL; pokud quick_check při startu najde chybu, systém se bezpečně zastaví. V databázi jsou registr zařízení, odvolání, retained zprávy a trvalé relace s frontami zpráv QoS 1 pro zařízení, která nejsou připojena.

Jádro pro databázi, to s nejvyšším číslem, spouští SQLite a nic jiného. Datová rovina mu posílá změny stavu přes prstenec SPSC bez zámků; ono je shromažďuje do jedné transakce každých 5 ms nebo každých 512 operací a potvrzení vrací druhým prstencem. Prázdný disk se naformátuje při prvním startu; nic jiného se nikdy nepřeformátovává.

Telemetrie jde jinou cestou. Každý přijatý PUBLISH na tématech z storage.telemetry_topics odchází do oddílu telemetrického žurnálu svého jádra: prstenec segmentů s CRC u každého záznamu, osolený sekvencí segmentu, takže se staré průchody prstencem nikdy znovu neobjeví. Jádra předávají záznamy databázi vlastním prstencem, bez kopírování, a ta je zapisuje každých 5 ms nebo každých 256 KiB. Při startu obnova zachová každý zapsaný záznam, odřízne nedokončený konec a pokračuje v novém segmentu. Uchovávání je podle velikosti, přes prstenec, i podle stáří, přes retention_days. Ověřili jsme to s milionem záznamů a s kill -9 uprostřed zápisu.

Čísla

Nástroj pro zátěž v tools/loadgen dělá tři věci: bouři handshaků TLS 1.3 s mTLS a CONNECT, dlouhodobá spojení s PINGREQ, která každou sekundu publikují telemetrii, a bouře opakovaných připojení. make bench na Apple M4 Pro pod HVF dává:

Pracovní jádra handshaků/s v hostu škálování přes uživatelskou síť QEMU (spojení/s)
1 862 1,00× 789
2 1 724 2,00× 636
4 3 438 3,99× 536

Číslo v hostu, kde jsou klient i server uvnitř téhož virtuálního stroje a každé pracovní jádro běží samo za sebe, ukazuje, že datová rovina škáluje lineárně. Síťové číslo je omezeno jednovláknovou uživatelskou sítí QEMU, ne hostem; i to je zapsáno jako ADR-032.

Bouře opakovaných připojení testujeme tak, že se všechna zařízení připojí najednou, odmítnuté pokusy opakují se zpožděním a pak všechna spadnou bez DISCONNECT. Parametr heap_limit_mb= ve vývojovém režimu přiměje řízení příjmu považovat haldu za menší, než je, takže bouři větší než halda lze vyzkoušet s malým počtem socketů. V jednom takovém kole s 3 000 zařízeními se připojilo 1 368 za 36 sekund a 5 619 pokusů bylo řádně odmítnuto, při limitu 8 MiB; paměť se po bouři vrátila.

Jak pracujeme

Projekt řídí psaná specifikace, PROMPT.md, s plánem milníků, a každý milník končí stejným rituálem: make check a make smoke zelené, jeden commit se štítkem M<n>, zápis v docs/PROGRESS.md a ADR pro každé rozhodnutí, které není zřejmé. Pravidla jsou krátká a nevyjednáváme o nich: žádná panika na vnější vstup, unsafe jen v hardwarových balíčcích a balíčcích FFI a vždy s komentářem, žádné alokace na horké cestě, komentář u každého pořadí atomických operací, každý limit pochází z konfigurace a záměrné provizorní části selhávají nahlas.

CI dělá víc, než bychom stihli ručně: fmt, clippy pro host i pro aarch64-unknown-none, typos, actionlint a shellcheck; testy na Linuxu a macOS na arm64; sestavení jádra pro vývojovou i produkční konfiguraci s velikostí ELF v souhrnu; start pod QEMU se všemi scénáři kouřového testu a ukládáním sériových logů; cargo-deny pro bezpečnostní upozornění, licence a zdroje; minutu fuzzingu na každý z jedenácti cílů a v noci deset minut na cíl s korpusem v cache. K tomu CodeQL, OpenSSF Scorecard, Dependabot a vydání s původem SLSA. Každá cizí akce je připnutá na úplný SHA commitu.

Reprodukovatelnost chápeme doslova: make repro sestaví HEAD dvakrát v čerstvých pracovních stromech a porovná ELF, ISO i surový obraz bajt po bajtu. Vydání jsou podepsána minisign a artefakty lze ověřit pomocí gh attestation verify. Produkční obraz obsahuje soukromý klíč serveru, takže samotné ISO je tajemství; obrazy u vydání na GitHubu jsou vývojové, s dočasnými klíči, a slouží jen k vyzkoušení.

Co jsme se naučili

Několik lekcí, které změnily plán:

  • Vlastní TCP se přece jen vyplatilo. Prototyp běžel na smoltcp a dobře nám sloužil do M13. Server, který drží stovky tisíc spojení, ale nepotřebuje klientské TCP, potřebuje SYN cookies, kolo časovačů a stav o 96 bajtech. V M14 jsme smoltcp nahradili vlastním zásobníkem pouze pro stranu serveru, s testy simulované ztráty a fuzzingem segmentů.
  • Paměť měřte zevnitř. Odhady na spojení byly k ničemu, dokud jádro samo nezačalo počítat haldu v blocích alokátoru, a ne v požadovaných bajtech. Teprve pak jsme viděli, kam 512 bajtů skutečně odchází, a sestoupili jsme na 494.
  • Nástroj pro testování je součást produktu. Největším omezením nebylo jádro, ale uživatelská síť QEMU a počet efemérních portů na vývojovém počítači. Pro sto tisíc a více spojení je potřeba vmnet-shared na macOS nebo Linux s KVM, rozhraním tap a více klientskými adresami.
  • SQLite bez operačního systému je možné, ale jen za přísných podmínek: pevná halda, exkluzivní zamykání bez sdílené paměti, VFS, které o souborech neví, a řízení příjmu, které nepustí databázi do zpoždění.
  • Bouře opakovaných připojení jsou běžný stav, ne výjimka. Když spadne mobilní síť a vrátí se, tisíce zařízení klepou současně. Proto řízení příjmu odmítá spojení před jakoukoli kryptografií a každé odmítnuté spojení stojí téměř nic.

Co následuje

Práce po M17 je naplánována ve třech směrech a pořadí mezi nimi je zapsáno v docs/PLAN.md. Nic z toho zatím není postaveno.

  • Jedno ISO pro více platforem. Stejný soubor urmqtt-<env>-<verze>.iso a jeden surový obraz GPT, které se zavádějí na aarch64 UEFI, x86_64 UEFI a x86_64 BIOS, ve virtuálních strojích i na skutečném hardwaru, počínaje jedním Intel PC. Stále zařízení se vším uvnitř, reprodukovatelné a podepsané.
  • Surový disk, bez souborového systému. Specifikace formátu na úrovni bajtů, hostitelský nástroj urmqtt-disk, který sdílí parsery s jádrem, zarovnání oblastí na 1 MiB, růst disku s daty, discard pro tence alokované disky, snímky databáze A/B, kontrola bitů a volitelně šifrování AES-256-XTS s hardwarovým AES.
  • Prokazatelně bezpečné. Odvolání a seznam povolených zařízení za běhu přes podepsaný řídicí kanál, bez nového obrazu; diferenciální a konformační testování vlastního TLS a TCP; KASLR, ochrana zásobníku, kCFI, MTE a zpevněný alokátor; SQLite izolovaný na úrovni EL0; Secure Boot; SBOM a cargo-vet; a nakonec balíček pro externí audit.

Platformy, které nabízejí jen zařízení jiná než virtio, jako AWS ENA nebo Azure MANA, zatím nejsou podporovány. Raspberry Pi 4 a 5 jako hostitel KVM, Hetzner CAX a Oracle Ampere A1 jsou zdokumentovány a podporovány kódem, ale zatím nebyly vyzkoušeny na skutečné službě.

Vyzkoušejte

Repozitář je na github.com/zeljan-alduk/urMQTT. S Rustem s připnutým nightly toolchainem a QEMU stačí make certs, make run a jeden klient mosquitto k prvnímu PUBLISH přes mTLS na vlastním počítači. Upozornění ze začátku platí i na konci: je to pre-alfa a vše, co funguje, je napsáno v docs/PROGRESS.md. Hlášení chyb, otázky k návrhu a bezpečnostní hlášení podle pokynů v SECURITY.md jsou vítány. O každém dalším milníku se zde ozveme.

Komentáře

Pravidla komentování

Pravidla komentování

Komentáře slouží ke sdílení zkušeností a otázek k tématům blogu. Tato pravidla udržují diskuzi užitečnou pro všechny.

  1. Slušnost Žádné urážky, výhrůžky, obtěžování, nenávistné projevy ani diskriminace z jakéhokoli důvodu. Kritizujte argument, ne osobu.
  2. K tématu Komentář se má týkat příspěvku nebo diskuze pod ním.
  3. Bez reklamy a spamu Žádná inzerce, řetězové zprávy ani odkazy bez kontextu. Odkazy a obrázky jsou vítány, když diskuzi obohacují.
  4. Soukromí ostatních Nezveřejňujte osobní údaje jiných lidí: celá jména soukromých osob, adresy, telefony, e-maily, fotografie bez souhlasu.
  5. Autorská práva Zveřejňujte jen obsah, který smíte sdílet. Při citaci uveďte zdroj.
  6. Jedna identita Používejte jednu přezdívku a nevydávejte se za někoho jiného.
  7. Potvrzení e-mailem Komentář se zveřejní až po potvrzení odkazu zaslaného e-mailem. Adresa se nezobrazuje a k ničemu jinému se nepoužívá; nepotvrzené komentáře se po 48 hodinách mažou.
  8. Moderace Komentáře porušující pravidla skrýváme nebo mažeme bez upozornění a diskuzi můžeme uzamknout. Rozhodnutí moderátorů jsou konečná.
  9. Odpovědnost Za obsah komentáře odpovídá jeho autor. Komentáře nevyjadřují názory ALDO TECH.
  10. Nahlášení Nevhodný obsah nahlaste na info@aldo.tech.