Proč je CURL bez User-Agent problém?

[gtranslate]

Občas se na nás obrací zákazníci s dotazem, proč jejich skript, monitoring nebo integrace najednou dostává odpověď 401, zatímco stejná URL v prohlížeči funguje bez problémů. Ve velké části případů je odpověď překvapivě jednoduchá: požadavek přichází bez hlavičky User-Agent, nebo s prázdnou hodnotou. A to je z pohledu moderní webové bezpečnosti problém. Pojďme si vysvětlit proč, co na to říkají standardy a jak to správně vyřešit.

Co říká standard

Hlavička User-Agent není žádná novinka ani kosmetická záležitost. Definuje ji přímo základní specifikace protokolu HTTP, aktuálně RFC 9110 (HTTP Semantics), v sekci 10.1.5. Formulace je jednoznačná: klient by měl (SHOULD) posílat hlavičku User-Agent v každém požadavku. Terminologie SHOULD podle RFC 2119 znamená, že vynechání je přípustné jen ve výjimečných, dobře odůvodněných případech, a klient si musí být vědom důsledků.

Požadavek bez User-Agent tedy technicky není nevalidní HTTP. Je ale v rozporu s doporučením standardu, a to z dobrého důvodu. Specifikace přímo uvádí, k čemu hlavička slouží: k identifikaci klienta pro účely statistik, ladění problémů a přizpůsobení odpovědí. Klient, který se odmítá jakkoli identifikovat, se dobrovolně vzdává možnosti, aby s ním server jednal jako s legitimním protějškem.

Curl sám o sobě User-Agent posílá

Důležitý fakt, který se v diskuzích často přehlíží: curl posílá User-Agent zcela automaticky. Každý běžný požadavek přes curl obsahuje hlavičku ve tvaru:

User-Agent: curl/8.5.0

Stejně se chovají wget, Python requests, Guzzle, Axios i prakticky všechny další HTTP knihovny. Když tedy na server dorazí požadavek úplně bez User-Agent, znamená to jediné: někdo si hlavičku aktivně odstranil (typicky přepínačem -A "" nebo -H "User-Agent:"), nebo jde o vlastní nízkoúrovňovou implementaci HTTP klienta. Ani jedno není chování běžného legitimního software. Naopak, je to typický otisk skenerů zranitelností, spam botů, scraperů a dalších automatizovaných nástrojů, které se snaží nebýt identifikovatelné.

Chybějící User-Agent jako bezpečnostní signál

Právě proto se absence nebo prázdná hodnota User-Agent stala v oboru zavedeným indikátorem podezřelého provozu. Několik konkrétních příkladů z praxe:

OWASP Core Rule Set, referenční sada pravidel pro ModSecurity a další WAF řešení, obsahuje pravidlo 920320 (Missing User Agent Header), které chybějící hlavičku přímo penalizuje ve skóre anomálií. Velké CDN a bezpečnostní služby, včetně Cloudflare nebo AWS WAF, s chybějícím či prázdným User-Agent pracují jako s jedním ze signálů pro challenge nebo blokaci. Analýzy provozu dlouhodobě ukazují, že podíl škodlivých požadavků mezi provozem bez User-Agent je řádově vyšší než v běžném provozu.

Blokování nebo omezování požadavků bez User-Agent tedy není žádný exces. Je to standardní průmyslová praxe, kterou uplatňuje většina seriózních provozovatelů infrastruktury.

Jak k tomu přistupuje WEDOS Protection

Naše ochrana WEDOS Protection se chová stejně jako výše zmíněná řešení. Požadavky bez User-Agent hlavičky, případně s prázdnou hodnotou, vyhodnocuje jako rizikový provoz a blokuje je. Stejná pravidla platí i na hostinzích VEDOS Hosting, kde ochrana běží nad weby zákazníků.

Není to samoúčelné opatření. Reálné útoky, které na chráněné infrastruktuře denně vidíme, ve významné míře přicházejí právě bez identifikace klienta. Blokace tohoto provozu odfiltruje značnou část automatizovaných skenů a útoků ještě předtím, než se dostanou k aplikaci, a to s prakticky nulovým dopadem na legitimní návštěvníky. Běžný uživatel s prohlížečem, vyhledávací roboty ani korektně napsané integrace se s tímto pravidlem nikdy nepotkají.

Jak má správný User-Agent vypadat

Pokud provozujete vlastní skript, monitoring, integraci nebo bota, doporučujeme posílat User-Agent, který splňuje tři jednoduché zásady: identifikuje, co jste zač, uvádí verzi a nabízí kontakt nebo odkaz, kde se o vašem klientovi dá zjistit víc. Osvědčený formát vypadá takto:

User-Agent: NazevSluzby/1.0 (+https://www.example.cz/bot-info; admin@example.cz)

V curl to znamená jediný přepínač:

curl -A "NazevSluzby/1.0 (+https://www.example.cz/bot-info)" https://cilova-url.cz/

Tento vzor používají i velcí hráči. Googlebot, monitoring služby nebo API klienti renomovaných firem se vždy jasně identifikují a uvádějí URL s informacemi o svém provozu. Provozovatel serveru si pak může ověřit, o koho jde, nastavit pro něj výjimky, nebo ho v případě problémů kontaktovat. Je to základní projev slušnosti mezi stroji na internetu.

Čemu se naopak vyhnout: kratší hodnotě než čtyři znaky, prázdné hodnotě, samotnému výchozímu curl/8.x u produkčních integrací (funguje, ale nic neříká o vaší službě) a padělání User-Agent prohlížeče. Vydávat skript za Chrome nebo Firefox je krátkozraké, protože moderní ochrany včetně té naší ověřují konzistenci klienta i jinými metodami a nekonzistentní otisk vede k horšímu skóre, ne lepšímu.

Proč je lepší opravit klienta než žádat o výjimku na IP

Častá první reakce zní: „Tak mi tu IP adresu prostě povolte.“ Rozumíme tomu, ale je to horší řešení než jednořádková oprava na straně klienta, a to z několika praktických důvodů.

Výjimka na IP oslabuje ochranu. Whitelist typicky neznamená „pusť requesty bez User-Agent“, ale „na tuto IP neaplikuj kontroly“. Pokud je zdrojem sdílený server, cloudová instance nebo služba třetí strany, výjimku s vámi sdílí i všechno ostatní, co z té adresy běží, včetně případně kompromitovaného souseda. A cloudové IP adresy se navíc recyklují: instance zanikne, adresu dostane někdo cizí a výjimka na ní zůstává, dokud si na ni někdo nevzpomene.

Whitelist je závazek do budoucna, oprava je jednorázová. IP adresy se mění při každé migraci, změně poskytovatele, škálování nebo přechodu na IPv6. Monitorovací a integrační služby dnes navíc běžně běží distribuovaně z desítek adres, které se průběžně obměňují. Každá taková změna znamená nový ticket, výpadek a čekání. Správně nastavený User-Agent naproti tomu cestuje s klientem: nastavíte ho jednou a funguje odkudkoli.

Oprava funguje všude, výjimka jen u nás. Výjimku na IP vám můžeme zřídit na naší infrastruktuře, ale stejný skript bez User-Agent narazí i u Cloudflare, AWS WAF a dalších poskytovatelů, kteří toto chování penalizují úplně stejně. Opravou klienta vyřešíte problém globálně, whitelistem jen lokálně a dočasně.

A nakonec ten nejjednodušší argument: poměr úsilí. Výjimka znamená komunikaci, evidenci, údržbu a trvalé bezpečnostní riziko. Oprava znamená jeden přepínač v curl nebo jeden řádek v konfiguraci knihovny. Není moc situací, kde je správné řešení zároveň to výrazně levnější, tady ano.

Shrnutí

User-Agent je hlavička doporučená přímo HTTP standardem (RFC 9110), kterou všechny běžné klienty posílají automaticky. Její absence je spolehlivým signálem záměrně upraveného, typicky automatizovaného a často škodlivého klienta, a proto ji ochrany typu OWASP CRS, Cloudflare, AWS WAF i WEDOS Protection penalizují nebo blokují. Řešení je triviální: identifikujte se. Jeden přepínač v curl nebo jeden řádek v konfiguraci vaší knihovny a váš provoz přestane vypadat jako útok.