Disassembler

Artificial intelligence is no match for natural stupidity.
19únor2016

Textové protokoly - Úvod (1)


Už jsem dlouho nic nenapsal. Ne že bych neměl nápady nebo nepracoval na ničem zajímavém, ale polovina věcí, které obvykle dělám, je kryta různými NDA nebo jinými úmluvami značně omezujícími mou sdílnost a druhá polovina je natolik specifická, že by pravděpodobně stejně nikoho nezajímala. Ale kdyby byl zájem o popis migrace WebSphere Application Serveru nebo o veselé historky z troubleshootingu SLAB memory managementu linuxového kernelu, tak samozřejmě můžu sloužit. Řekl jsem si tedy, že zkusím naopak napsat o něčem, co provozuji dnes a denně. Ladění a zkoušení komunikace se serverovými aplikacemi za použití nejrůznějších plaintextových protokolů.

Předmluva a obsah


Vybral jsem si záměrně pouze plaintextové protokoly aplikační vrstvy, protože na rozdíl od binárních protokolů k jejich použití není potřeba žádný klientský software přímo implementující daný protokol, ale je možno se připojit přímo na socket a vést konverzaci rovnou mezi člověkem a počítačem. Tedy alespoň v rámci možností. Jsem si celkem jist, že o jednotlivých protokolech bude potřeba zmínit celkem dost faktů a jak znám svou grafomanii, určitě se budu snažit sdělit co nejvíce informací, příkladů a tipů, které považuji za užitečné. Takže už dopředu vím, že s jedním článkem bych spolehlivě unavil jak sebe, tak i případné čtenáře. Povídání tedy rozdělím podle jednotlivých protokolů.

Odkazy budu doplňovat průběžně, podle toho jak budou příslušné díly vznikat.

Další textové protokoly, které můžete znát, jsou například SIP a XMPP (Jabber). O těch nejspíše psát nebudu. SIP je poněkud komplikovaný tím, že používá i UDP a že slouží pouze k navázání VoIP spojení. Samotné vyjednání parametrů přenosu pak zajišťuje jiný protokol, například SDP, a vlastní multimediální tok je stejně binární, takže ten si bez příslušného klienta těžko vyzkoušíte. XMPP je plně plaintextový, pomineme-li opět případný přenos souborů nebo multimédií. Jelikož jsem se v něm už několik let nevrtal, necítím se natolik pevný v kramflecích, abych o něm něco napsal. Navíc se jedná o XML stream, který sice je člověkem jakžtakž čitelný, ale není přímo vhodný k tomu, aby jej člověk i ručně vytvářel.

Klíčové nástroje


Jak jsem již zmínil, ke komunikaci se serverem skrze plaintext nepotřebujete žádný udělátor přímo hovořící daným protokolem. Co ale bezpodmínečně potřebujete, je nástroj, který vám umožní se k socketu příslušné serverové služby vůbec připojit. V zásadě máte několik možností, v závislosti na charakteristice požadovaného spojení.

Jedná-li se o prachobyčejný nezajímavý a nezabezpečený TCP socket, dá se na něj napíchnout starým dobrým telnetem. Historicky se jako telnet označuje binární protokol umožňující emulaci terminálu a vzdálenou správu zařízení, a také klient, skrze kterého je možno se tímto protokolem připojit. Moderní telnet klienti vás ale umí spojit i s jinými porty, bez pokusu o vyjednání parametrů telnetového terminálu, takže vám umožní si nerušeně klábosit se serverem. Jelikož telnet jakožto protokol nepodporuje šifrování ani ověřování, dávno se v moderním světě přestal používat, takže z původního záměru dnes zbyla akorát ona klientská aplikace se stejnojmenným názvem. Telnet klient existuje snad ve všech linuxových a unixových distribucích a používá se velice jednoduše.

telnet host port

Pomocí panelu Zapnout nebo vypnout funkce systému Windows se dá doinstalovat také na Windows. Tam ale spíše doporučuji užití alternativních klientů, jako třeba PuTTY. V tom je pro připojení plaintextovým protokolem potřeba zvolit typ připojení Raw, nikoliv Telnet).

Nemáte-li rádi telnet, můžete použít jednoho ze dvou dalších prověřených nástrojů. Prvním z nich je netcat, druhým pak socat. Obě utility slouží k navazování síťových spojení a zejména při skriptování udělají daleko lepší službu než telnetový klient. Mohou dokonce zajišťovat i serverovou část, v případě, že potřebujete rychle splácat nějaký skriptík, který má data po síti i odesílat. Na rozdíl od telnetu taky oba nástroje umí použít i UDP, ale toho se u plaintextových protokolů využívá jen vzácně. S netcatem se pak klientská část TCP spojení se dá navázat se stejnými parametry a syntaxí jako u telnetu.

netcat host port

U socatu je to poněkud komplikovanější, protože vyžaduje explicitní nastavení obou stran komunikace, i když vás v tomto případě zajímá jen jedna.

socat - tcp-connect:host:port

Osamocená pomlčka zde značí, že klientská strana používá ke vstupu stdin a k výstupu stdout.

Kryptonit


V případě, že je TCP socket na relační vrstvě šifrován pomocí TLS (případně zastaralým SSL), přichází na řadu extrémně užitečná a kryptografickými featurami nabitá knihovna OpenSSL. Ta mimo samotné dynamické knihovny libssl, použitelné programátory ve svých aplikacích, obsahuje hromadu komandlajnových utilit, díky kterým se veškerá administrace a testování aplikací šifrujících pomocí TLS stane hračkou. Jednou z mnoha takových nástrojů je s_client. Který vás dokáže připojit na zabezpečený socket a zároveň na vás vychrlí přehršel informací o serverovém certifikátu, použitých algoritmech a šifrách a dalších věcí náležících do procesu navázání a vyjednání parametrů TLS spojení (tzv. handshake). Nebudu v tomto článku popisovat informace, které se z výpisu dají získat a vysvětlovat, co znamenají, protože je toho fakt hromada. Spíš v budoucnu očekávejte článek zabývající se výhradně popisem toho, co se při navazování TLS spojení děje. OpenSSL knihovna je opět dostupná snad na všech *nixových distribucích a pro Windows se dá z různých stránek třetích stran stáhnout jako zkompilovaný balíček. K připojení pak slouží příkaz

openssl s_client -connect host:port

K tomuto příkazu se dá navěšet hromada dalších parametrů různě upravujících chování klientské části TLS spojení. Například se zde dá vynutit protokol nebo sada šifer a otestovat, zda jsou vzdáleným serverem podporovány. Velice užitečné zejména během posledního roku, kdy celý IT svět řeší POODLE a různé jiné zranitelnosti. Jednoduše příkazu dodáte třeba parametr -ssl3, čímž vynutíte použití SSL 3. V případě, že se spojení s tímto parametrem nepodaří navázat, ale bez něj ano, znamená to, že server SSL 3 nepodporuje a pudl si ani neštěkne.

Dále můžete pro navázání zabezpečeného spojení opět použít socat, ale ten je stejně závislý na přítomnosti OpenSSL knihoven a jeho použití je poněkud komplikovanější.

socat - openssl-connect:host:port,verify=0

Parametr verify=0 na konci odstraňuje nutnost ověření certifikátu. Pokud by tento parametr nebyl nastaven, bylo by nutno socatu dodat certifikát cílového serveru (nebo jeho trust chain), aby mohlo dojít k úspěšnému ověření a navázání spojení. To se hodí v situacích, kdy má váš skript mít absolutní jistotu, že nedochází k nějakým MitM útokům nebo jiným nekalostem. U člověkem prováděného debugování je takové opatření ale poněkud na obtíž.

Chytrá horákyně


Některé protokoly implementují zajímavou věc – volitelné šifrování. Nejprve se klient na socket připojí nešifrovaně a může začít s transakcí. A pokud chce (a pokud takovou věc vůbec podporuje), může oznámit serveru, že by rád šifroval. Až teprve pak se spojení upgraduje na TLS a tentýž přenos bez nutnosti přerušení TCP spojení dále probíhá šifrovaně. Z výše uvedených protokolů tuto featuru podporuje SMTP, POP3, IMAP, FTP a XMPP a ve všech se vyžádá příkazem STARTTLS. Problém je, že tato spojení jsou v podstatě zároveň šifrovaná i nešifrovaná, takže telnet tu funguje jen do té doby, než se vyžádá STARTTLS a výše uvedený příklad s openssl s_client naopak počítá s tím, že spojení je implicitně šifrované už od samého začátku. Naštěstí ale i na tuto variantu pánové a dámy z OpenSSL Software Foundation mysleli, takže s_client přímo implementuje -starttls parametr, za který se už jen přihodí kterýže to protokol se má použít před samotným odstartováním TLS. V případě SMTP tedy může příkaz vypadat třeba takto

openssl s_client -connect mailserver:25 -starttls smtp

Všude dobře, doma nejlíp


Poslední možností spojení, nejrychlejší, ale zato pravděpodobně nejméně zajímavou a s nejmenší nutností debugování, je unixový domain socket. Ze všech výše uvedených protokolů na takovém socketu má zřejmě smysl provozovat jen SMTP, resp. jeho lokální derivát, LMTP. Ten je užitečný zejména ve scénáři, kdy maily prochází různými filtry, antispamy a podobnými externími aplikacemi nad rámec samotného MTA, kdy je potřeba řešit taková předávání a případnou reinjektáž co nejrychleji a nejúsporněji, bez zbytečné práce s navazováním TCP/IP spojů, o kterých už dopředu víte, že skončí na stejném stroji ze kterého pochází. Pro připojení k unixovému socketu lze využít opět nástrojů socat a netcat. A aby to nebylo zas tak jednoduché, netcat existuje ve dvou variantách - netcat-traditional a netcat-openbsd, z nichž s unixovými sockety umí zacházet jen netcat-openbsd. Spojení se pak dá navázat jako

netcat -u socket

resp.

socat - unix-connect:socket

Rekapitulace


Takže znova a pěkně popořádku. Jaké že to máme nástroje a k čemu jsou dobré.

V následujících částech seriálu budu předpokládat, že se bavíme zejména o komunikaci se vzdálenými servery, takže netcat a socat zanechám v tomto článku a dál budu pokračovat jen s telnetem a OpenSSL klientem. Ono na tom stejně až tolik nezáleží, protože protokolům aplikační vrstvy je úplně putna jakým způsobem jste na server přišli.