← Blog

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

urMQTT na skutečném VPS: ISO, handshake za 0,24 ms, vlastní disk a zpevněné jádro

Co se stalo se třemi sliby z prvního textu o urMQTT (jedno ISO, surový disk bez souborového systému, prokazatelná bezpečnost) po prvních čtyřech dnech vývoje, s měřeními, tabulkami a seznamem toho, co ještě není hotové.

V prvním textu o urMQTT jsme popsali unikernel, který je MQTT broker, až po milník M17, a skončili jsme třemi sliby pod nadpisem „Co následuje": jedno ISO, které nabootuje na více platformách, surový disk bez souborového systému a bezpečnost, kterou lze dokázat, a ne jen tvrdit. Nic z toho tehdy nebylo postavené. Tento text sleduje, co se stalo s každým slibem, ve stejném pořadí jako dříve: co jsme plánovali, co jsme postavili, co nás překvapilo a co zůstává otevřené. Cestou ukážeme i to, jak dlouho to trvalo, protože i to je součást příběhu.

Jedna poznámka předem: projekt je pořád pre-alfa. Čísla v textu měří kód a testy, ne zralost v produkci, a první vydání je záměrně omezené na VPS s KVM. Bare metal zůstává na později.

Jak to vypadalo v čase

První commit vznikl 28. října 2026 ve 23:48 (M0). Do 31. října ve 23:00 má repozitář 119 commitů, rozložených jako 3, 39, 38 a 39 podle kalendářních dní. Hned řekněme, jak je to možné: projekt vzniká s Claude Code a commity nesou trailery Co-Authored-By: Claude. Čtyři kalendářní dny historie neznamenají, že jeden člověk napsal za čtyři dny 90 000 řádků; znamenají, že plán, implementace, testy a ADR se píšou v krátkých uzavřených smyčkách a každý krok končí stejným ověřovacím rituálem jako dřív. Čísla níže vypovídají o množství kódu a testů, ne o tom, kolik skutečné práce to všechno obnášelo.

Růst projektu během čtyř dnů s milníky od M0 po dnešek: tisíce řádků Rustu (od 1,6 do 89,8), počet funkcí #[test] (od 27 do 739) a počet ADR (od 13 do 104), spolu se sloupci commitů za den (39, 38 a 39 za 29., 30. a 31. října).
Růst projektu během čtyř dnů s milníky od M0 po dnešek: tisíce řádků Rustu (od 1,6 do 89,8), počet funkcí #[test] (od 27 do 739) a počet ADR (od 13 do 104), spolu se sloupci commitů za den (39, 38 a 39 za 29., 30. a 31. října).

Graf ukazuje tři křivky, které rostou téměř společně, což je záměr: testy a zapsaná rozhodnutí kód doprovázejí, a nezaostávají za ním. Sklon je nejstrmější 29. října, kdy vzniká celá cesta od jádra k brokeru. Dál se řádky přidávají pomaleji, ale testy rostou rychleji než kód (27 testů na 1,6 tisíce řádků na začátku, 739 na 89,8 tisíce dnes).

Milník Commit Čas Řádků Rustu Testů ADR
M0 9412a9c 28.10. 23:48 1 592 27 13
M5 a61083b 29.10. 01:32 9 314 88 24
M9 4be8cc9 29.10. 02:21 15 729 149 28
M11 4800904 29.10. 03:43 22 737 180 30
M13 a558d5e 29.10. 05:22 26 556 193 32
M17 7df4f98 29.10. 08:48 33 504 232 36
S1 ecf72ec 30.10. 00:46 41 910 299 45
X8 fb1504a 30.10. 19:08 56 341 456 59
PERF 76f7c36 31.10. 14:19 72 511 618 76
dnes HEAD 31.10. 23:00 89 790 739 104

Řádky jsou všechny soubory .rs mimo vendor/ a fuzz/, testy jsou funkce #[test]. Co který úsek přidal, podle data z historie gitu:

Datum Milníky Co bylo přidáno
29.10. M0 až M17 jádro, síť, TLS, broker, SQLite, více jader, vlastní TCP, zpevnění, reprodukovatelné vydání
29.10. večer a 30.10. X0 až X10, S1, H2, H3 (X0 začíná 29.10. ve 20:54) port na x86_64, univerzální ISO, jeden disk a samoinstalační ISO, kontroly TLS, útočné klienty
31.10. O1 až O4, T1, PERF, H4, H5, H9, S2 až S6 přehled a konzole přes MQTT, živý režim a diagnostika, SNTP, zrychlení, zpevnění, verifikace, dodavatelský řetězec, úložiště

Slib 1: jedno ISO pro více platforem

Co jsme plánovali. Jeden soubor, který nabootuje na aarch64 UEFI, x86_64 UEFI a x86_64 BIOS. Co jsme postavili. Port na x86_64 (X0 až X10) a univerzální ISO s bootloaderem Limine, jediné hybridní ISO, z něhož se zavádějí všechny tyto kombinace; kouřové testy ho spouštějí na čtyřech virtuálních strojích. Nabídka má tři položky: urMQTT (živý režim, běží z RAM, nic nezapisuje na disk), instalace na disk stroje, na kterém běží (instalace zapíše GPT a data a poté stroj vypne) a Diagnostika (detekce hardwaru a měření).

Zaváděcí nabídka ISO zachycená na VPS: položky „urMQTT", „Install urMQTT on this machine's disk" a „Diagnostic: hardware detection and benchmarks" s odpočtem do automatického spuštění. Snímek je z testovacího ISO s delším odpočtem; výchozí hodnota je 10 sekund.
Zaváděcí nabídka ISO zachycená na VPS: položky „urMQTT", „Install urMQTT on this machine's disk" a „Diagnostic: hardware detection and benchmarks" s odpočtem do automatického spuštění. Snímek je z testovacího ISO s delším odpočtem; výchozí hodnota je 10 sekund.

Prvním skutečným cílem byl VPS, ne fyzický počítač: rozhodnutí zní, že první vydání podporuje jen VPS (KVM) a bare metal přijde po něm. Testovali jsme na VPS u Contabo s procesorem AMD EPYC (rodina 23, Zen 1), 4 vCPU a 8 GiB RAM, se sítí virtio-net a diskem virtio-scsi. První pokus nás překvapil: ISO připojené jako virtuální CD spustilo výchozí položku, produkční obraz odmítl běžet z média jen pro čtení a resetoval se, takže vznikla nekonečná smyčka nabídka, jádro, reset bez čehokoli čitelného. Dnes fatální chyba v produkčním obrazu nechá zprávu na konzoli 60 sekund před resetem a z optického média vypíše, že bylo spuštěno z média jen pro čtení, a zastaví se. Živý režim v RAM (O3) později tento problém pro běžný případ obešel.

Diagnostická položka vznikla z této zkušenosti: stroj, který nevidíme, se musíme umět zeptat, co má. Vypisuje CPU, RAM, síť, disky a zařízení PCI, měří propustnost paměti, disk a kryptografii a stejná měření vypisuje jako JSON na sériový port. Zápis na disk je povolený jen v nepřiděleném prostoru a až po zadání WIPE; na snímku níže byl přeskočen.

Diagnostická obrazovka na VPS u Contabo (AMD EPYC, KVM, 4 vCPU): systém, paměť, disk, zařízení PCI, propustnost a latence RAM a kryptografická měření, včetně 244 us na mTLS handshake, X25519 48 us, podpis ECDSA 35,7 us a ověření 107 us.
Diagnostická obrazovka na VPS u Contabo (AMD EPYC, KVM, 4 vCPU): systém, paměť, disk, zařízení PCI, propustnost a latence RAM a kryptografická měření, včetně 244 us na mTLS handshake, X25519 48 us, podpis ECDSA 35,7 us a ověření 107 us.

Co zůstává otevřené. Skutečný hardware. Po prvním vydání přijde bare metal (zavádění z USB, NVMe a AHCI, síťová karta skutečného počítače) spolu s IOMMU a Secure Bootem, protože bez IOMMU může zlovolné nebo vadné zařízení zapisovat do celé paměti. V této verzi o tom nic netvrdíme.

Handshake: z 1,2 ms na 0,24 ms

První měření diagnostiky na VPS dalo nepříjemné číslo: mTLS handshake, jen kryptografie na straně serveru, trval 1,2 ms. Na aarch64 jsme už používali hardwarové instrukce AES a SHA, ale x86_64 nemělo nic podobného pro veřejný klíč: RustCrypto je přenositelné a constant-time, a tedy i pomalé. Srazily to tři změny.

  • Pro P-256 jsme převzali assembler nistz256 z OpenSSL a ring (ADR-130), spolu s tabulkami s pevnou bází pro podpis a ověření podpisu CA (ADR-110, ADR-111).
  • X25519 bylo přepsáno na čtyři 64bitové končetiny s instrukcemi MULX/ADX (ADR-131).
  • Poté jsme zprofilovali i zbytek (ADR-132, ADR-200).
Handshake na VPS: 1200 us před, 237 us po assembleru a tabulkách; A/B srovnání memcpy při stejném spuštění, 278,8 us se starým, 229,4 us s novým; a před a po u X25519 (146 na 48 us), podpisu ECDSA (673 na 34 us) a ověření (309 na 90 us).
Handshake na VPS: 1200 us před, 237 us po assembleru a tabulkách; A/B srovnání memcpy při stejném spuštění, 278,8 us se starým, 229,4 us s novým; a před a po u X25519 (146 na 48 us), podpisu ECDSA (673 na 34 us) a ověření (309 na 90 us).
Měření na VPS (server, mikrosekundy) Před Po
mTLS handshake, celá kryptografie 1200 kolem 240 (237 v měření z grafu, 244 na snímku)
X25519 146 48
podpis ECDSA 673 34
ověření ECDSA 309 90 (107 na snímku)
handshake, starý memcpy, stejný boot 278,8 229,4 (-17,7%)

Čísla se mezi spuštěními liší asi o 10 %, proto jsme zapsali rozsah místo jedné hodnoty. Celkově je to zhruba pětkrát méně CPU času na handshake.

Co jsme se naučili o memcpy. Když kryptografie klesla, profil ukázal něco, co jsme nečekali: funkce mem* (memcpy, memmove, memset) spotřebovávaly 7 % handshaku, 13 až 39 % cesty TLS záznamu (39 % pro 64 B, 13 % pro 4 KiB) a 17 až 34 % rozdělování PUBLISH. Nahradili jsme je assemblerem SSE2 pro x86_64 (ADR-200), s diferenciálními testy proti referenční implementaci pro všechny velikosti, zarovnání a překryvy. Na jedno volání je to 55 až 75 cyklů oproti 7 až 12 pro 1 až 64 bajtů.

Vlevo: podíl času serveru ve funkcích mem* před přepsáním (handshake 7 %, TLS záznam 64 B 39 %, 256 B 37 %, 1 KiB 24 %, rozdělování 17 až 34 %). Vpravo: o kolik je každá cesta rychlejší potom (handshake 17,7 %, 64 B 26,4 %, 256 B 19,6 %, 1 KiB 16,1 %, 4 KiB 6,6 %, rozdělování 7 až 34 %).
Vlevo: podíl času serveru ve funkcích mem* před přepsáním (handshake 7 %, TLS záznam 64 B 39 %, 256 B 37 %, 1 KiB 24 %, rozdělování 17 až 34 %). Vpravo: o kolik je každá cesta rychlejší potom (handshake 17,7 %, 64 B 26,4 %, 256 B 19,6 %, 1 KiB 16,1 %, 4 KiB 6,6 %, rozdělování 7 až 34 %).
Cesta Podíl mem* před Rychlejší po
handshake 7% 17,7%
TLS záznam 64 B 39% 26,4%
TLS záznam 256 B 37% 19,6%
TLS záznam 1 KiB 24% 16,1%
TLS záznam 4 KiB 13% 6,6%
rozdělování zpráv 17 až 34% 7 až 34%

Jak číst graf: čím menší záznam, tím větší část času jde na kopírování, a tím větší je i zisk. U malých zpráv, které tvoří většinu provozu MQTT, to je to, co se počítá.

Co to neznamená. Na nativním x86_64 jsme OpenSSL 3.5.5 (ADR-130) měřili jen jako referenci pro assembler, ne jako srovnání produktů. Srovnání Linuxu s Mosquittem na stejném VPS (úkol X11) jsme ještě neudělali. Proto netvrdíme, že urMQTT je rychlejší než Linux: nebylo to změřeno. Čísla výše srovnávají urMQTT samo se sebou.

Přetížení bylo druhým výsledkem. Na VPS, z jednoho Macu (RTT 35 ms), dalo 128 klientů 618 handshaků za sekundu, 256 klientů 393 a 512 klientů 67, s tisíci odmítnutých spojení. Nebyla to plošina, ale zhroucení. Příčiny jsme našli v kódu (dvě jsou potvrzené v QEMU/HVF, na VPS se zopakovat nedaly), několik najednou: odmítnuté spojení vracelo klienta přes další segment, který nese platnou cookie SYN, odmítnutí pomocí RST říkalo klientovi, aby to hned zkusil znovu, a příjem byl O(fronta). Oprava (ADR-080 až ADR-082) zahazuje SYN, který by nebyl přijat, pamatuje si odmítnuté toky, drží příjem v O(1) a počítá handshaky na jádro. Je možné (hypotéza, neověřeno), že část příčiny byla i na straně klienta: nástroj pro zátěž zavíral spojení jako první, takže jeden Mac s 16 384 efemérními porty a TIME_WAIT 30 sekund byl omezen na zhruba 550 spojení za sekundu. Proto skutečný strop serveru stále nemáme změřený.

Slib 2: surový disk, ale opatrný

Co jsme plánovali. Zachovat vlastní rozvržení bez souborového systému a doplnit vše, co souborový systém obvykle dává: zarovnání, růst, discard, zálohy a kontroly. Proč ne souborový systém. Diskutovali jsme o tom a rozhodnutí se potvrdilo: urMQTT zapisuje jednu databázi, jeden telemetrický žurnál a vlastní metadata, nepotřebuje adresáře, oprávnění ani názvy souborů, a každá další vrstva by byla další kód v důvěryhodné části a další způsob, jak může zápis tiše zmizet. Disk je GPT s oddílem ESP a jedním datovým oddílem urMQTT, na kterém je vlastní rozvržení.

Co jsme postavili (S2 až S6).

  • Rozvržení v2 (S2). Topologie disku, zarovnání na 1 MiB nebo optimální velikost I/O, celé fyzické bloky, A/B dvojice superbloků s generací (ADR-140). Rozvržení v1 jádro odmítne s jasnou zprávou a migruje ho offline nástroj urmqtt-disk migrate (ADR-141): výchozí je zkušební průchod, kopíruje se a teprve potom přepíná, s návratem a vkládáním chyb při každém zápisu.
  • Růst (S3). Při startu může disk narůst (nikdy se nezmenšuje) a na virtio-blk i za běhu, přes přerušení změny konfigurace (ADR-142, ADR-143).
  • Discard a write-zeroes (S4). Tence přidělené disky vracejí prostor hostiteli. V testu klesl soubor qcow2 na hostiteli z 62 na 16 MiB poté, co vypršely telemetrické segmenty, a obnova nikdy nedůvěřuje obsahu, který byl zahozen.
  • Záloha databáze na disku (S5). Kopie A/B pomocí online backup API SQLite po krocích po 16 stránkách: nejdelší krok 4,6 ms oproti 445 ms při kopírování jedním voláním. Commity během kopie měly maximum 2,4 ms oproti 2,2 ms bez ní. Pokud quick_check při startu selže, databáze se obnoví z kopie.
  • Čištění a omezený start (S6). Scrubber čte disk s omezeným rozpočtem I/O a hlásí poškozené záznamy a start čte jen nejnovější segment každého oddílu, takže doba startu neroste s velikostí telemetrické oblasti. Tím jsme uzavřeli problém, který jsme si předem spočítali: na velkém disku by úplná obnova trvala od minut do desítek minut.

Celá skupina kouřových testů pro úložiště prochází na obou architekturách: 79 úspěšných, 0 neúspěšných, na aarch64 pod HVF a na x86_64 pod TCG. Měřili jsme také, že S4 databázi nezpomalil: 53,3 tisíce vložení za sekundu v dávkách před i po, bez měřitelného rozdílu.

Co překvapilo. Kolik z „jednoduchého" rozvržení tvoří okrajové případy: virtio-scsi a virtio-blk hlásí topologii různými způsoby a neúplný zápis uprostřed migrace musí vždy ponechat alespoň jednu platnou verzi. Proto každý zápis na cestě migrace a růstu prošel vkládáním chyb.

Co zůstává otevřené. Stránky SQLite nemají kontrolní součet, takže změněný bit uvnitř hodnoty v řádku databáze neodhalí; telemetrické záznamy a obsah kopií mají CRC a odhalí se. Šifrování disku (S7) není hotové.

Slib 3: prokazatelně bezpečné, nakolik to dokážeme

Zpevnění (H4). Alokátor maže uvolněnou paměť a kontroluje ji při opětovném použití, odhaluje dvojí uvolnění, váže ukazatele volného seznamu pomocí XOR a nuluje klíče při uvolnění (ADR-170). Ochrana zásobníku (-Zstack-protector=strong, 1315 funkcí, a SQLite s -fstack-protector-strong, ADR-171). Hlášení chyb v produkci neobsahují registry ani adresy (ADR-172). KASLR na obou architekturách: jádro je PIE a Limine ho posouvá asi o 19 bitů, a náhodně se umísťují halda, zásobníky a okno MMIO (ADR-173). Na aarch64 MTE označuje haldu (ADR-174), ale jen pod TCG: HVF a x86 ho nemají. kCFI jsme vyhodnotili a nepřijali, protože překladač na připnutém nightly padá s vnitřní chybou; IOMMU je odloženo spolu s bare metalem (ADR-175, ADR-176).

Cena je změřená, ne předpokládaná. Na cestě handshaku (dp-bench, aarch64 HVF, plné handshaky TLS 1.3 + mTLS + CONNECT):

Krok 1 jádro 4 jádra Změna
bez zpevnění 1941 7620
+ alokátor 1898 7429 -2,2% až -2,5%
+ ochrana zásobníku 1845 7243 dohromady -4,9% až -5%
+ PIE a značky kolem 1800 kolem 6750 na zatíženém počítači, zašuměné

Celkově je tedy cena na cestě handshaku zhruba 5 % pro části měřené čistě a s PIE a značkami vychází asi 7 % na jednom a asi 11 % na čtyřech jádrech, ale toto měření je zašuměné. Považujeme ji za přijatelnou, ale neopakovali jsme ji na x86_64 VPS.

Stojí za to porovnat s číslem z prvního textu (862 handshaků za sekundu na jednom jádře). Stejný nástroj dnes, s ovladačem hardwarového šifrování na aarch64 (X0b) a řadou zrychlení, která od té doby přišla, dává před zpevněním 1941. Příspěvek každé změny jsme neizolovali, takže o příčině nic netvrdíme.

Jak je to ověřeno, a co ne. H5 přidal Miri na podmnožinu hostitelských crate, důkazy Kani, sanitizery, model-fuzzer pro ACL a hlášení o pokrytí. Kani dokázal record_len v TLS, parse v TCP a dvě aritmetiky kola časovačů. Nedokázáno (vypršel čas): oba dekodéry MQTT, obě parsování konfigurace a chování kola časovačů; úloha CI pro Kani proto zatím neblokuje. Miri neumí spouštět assembler. Dodavatelský řetězec (H9): SBOM CycloneDX s 215 komponentami, cargo-vet prochází s 39 plně zrevidovanými a 140 výjimkami, a cargo-deny je nakonfigurováno tak, že upozornění na zranitelnosti bere jako selhání CI (tyto úlohy CI byly zatím ověřeny jen lokálně, ne na GitHubu, a negativní test nebyl spuštěn), spolu s VULNERABILITY-HANDLING.md. Poctivý stav: ze 67 verzí cizích crate linkovaných do jádra je 53 výjimek, ne revizí. Vet dokazuje, že množinu závislostí nelze změnit bez viditelného rozdílu, ne že TCB byla zkontrolována. Vlastní revizi žádného crate jsme nenapsali.

SNTP (T1) je v tomto smyslu malý příběh o bezpečnosti: je volitelné, jen vůči soukromým serverům IPv4, s maximálním skokem a podmínkou shody zdrojů (medián, většina do jedné sekundy). Hodiny, které může kdokoli na cestě posunout, nejsou hodiny, kterým smíme věřit při platnosti certifikátů.

Na Macu: aarch64 nativně a x86_64 emulací

Vyvíjíme na Macu a ten má dva způsoby, jak spustit stejný kód, a jsou velmi odlišné.

aarch64 pod HVF x86_64 pod TCG
Co to je nativní provádění, rychlost blízká skutečnému procesoru QEMU emuluje instrukce
Handshake v hostu asi 0,58 ms (poprvé měřeno kolem M13); dp-bench dnes 1941/s na jádro asi 3,3 ms
Scénáře kouřových testů TLS rychlé asi 15 minut na scénář
MTE ne (na HVF není) x86 ho nemá; označování haldy funguje jen pro hosta aarch64 pod TCG
K čemu slouží skutečná měření správnost: ověřuje se cesta x86, čísla nejsou výkon

Pravidlo je jednoduché: čísla pod TCG jsou emulace a necitujeme je jako výkon. Výkon x86 měříme jen na skutečném VPS. Proto kryptografická čísla výše pocházejí z VPS u Contabo, ne z Macu.

Lekce

  • Měřte na skutečném stroji, než začnete optimalizovat. První přístup byl optimalizovat to, co jsme považovali za pomalé; teprve diagnostika na VPS ukázala 1,2 ms a kam přesně čas odchází.
  • Přetížení je samostatná vlastnost. Systém, který je rychlý pod zátěží, se může nad ní zhroutit; odmítnutí musí být levnější než přijetí.
  • Profil překvapuje. Největší jednotlivý zisk pro malé zprávy nebyl v kryptografii, ale v kopírování paměti.
  • Disk bez souborového systému vyžaduje víc práce, ne méně. To, co souborový systém obvykle dává (zarovnání, růst, discard, kopie, kontroly), musíme napsat a ověřit sami, každý krok s vkládáním chyb.
  • Poctivost v číslech. Měření paměti na sdíleném VPS kolísají až 10krát mezi spuštěními a o kódu nic nevypovídají, proto je neuvádíme. Kryptografická čísla jsou stabilní do asi 10 %.
  • Rychlost vývoje není zralost. Testy a ADR rostou s kódem, ale čtyři dny nejsou skutečný provoz.

Co následuje

  • H6: SQLite izolované na úrovni EL0, aby chyba v databázi neotevřela jádro.
  • H7: zbytek bezpečnosti času (NTS a zpracování skoků); SNTP je teprve první krok.
  • X11: srovnání s Linuxem a Mosquittem na stejném VPS, teprve pak má smysl mluvit o relativní rychlosti.
  • Vydání: první veřejné vydání pro VPS (KVM), s podepsanými artefakty a návody.
  • Po vydání: bare metal (X12 až X16), IOMMU a Secure Boot a šifrování disku.

Kód je na github.com/zeljan-alduk/urMQTT a docs/PROGRESS.md je pořád jediným zdrojem pravdy o tom, co skutečně funguje. Pre-alfa, jako dřív; hlášení chyb a bezpečnostní hlášení podle pokynů v SECURITY.md jsou vítána.

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.