SlimFTPd

Pro přístup ke svým datům tradičně používám FTP protokol, hlavně pro jeho širokou podporu a dobré možnosti nastavení. Jako server jsem dlouho používal War FTP Daemon, který ale poněkud ustrnul ve vývoji. Lákal mě přechod na SlimFTPd, velice malý a rychlý server, vadou na kráse ale byla cena a některé chybějící featury. Uvolnění SlimFTPd jako open-source v říjnu 2006 vyřešilo první problém a přimělo mě sem tam do kódu sáhnout a doplnit si ty části, které mi chyběly. Dnes už používám výhradně SlimFTPd.

FTP serverů existuje celá řada. Proč by měl někdo používat SlimFTPd? V první řadě proto, že je to velice malý, jednoduchý a rychlý server, což by se mohlo s trochou štěstí projevit i na jeho bezpečnosti (do mála kódu se obvykle nevejde tolik chyb jako do obřích balíků). Mě se na něm zvlášť líbí jeho „unixová filozofie“ – celý server je tvořen jedním spustitelným souborem a jedním textovým konfiguračním souborem. Nepotřebuje instalaci, nezapisuje do registrů, nemá žádné přehnané nároky na prostředky, nezabývá se žádnými efektními zbytečnostmi, jen si tiše (a neviditelně) běží na pozadí a plní svoji funkci. A mimochodem – je schopen pracovat i pod omezeným uživatelem, nepotřebuje administrátorská práva.

Nicméně, ve své standardní verzi má několik vlastností, které se mi nelíbí, a několik chybějících featur, které bych potřeboval. Některé z nich jsem tedy sám implementoval. Jsou to zejména tyto:

Kompatibilita s MingW

Jedním z kritických problémů Cčkových programů je to, že je vesměs neumím zkompilovat – autoři buď předpokládají zkušeného céčkového programátora – což nejsem -, nebo třeba i začátečníka, který ale má nějaký user-friendly software nástroj (nejlépe Microsoftí Visual Studio) – což nemám (dá se stáhnout zdarma, ale já prostě nedokážu přenést přes srdce tu obrovskou haldu dat, kterými mi zaplní disk, a zásahů, které provede v registrech). S DevC++ jsem zhruba na půl cesty – mám prostředí, které nepotřebuje instalaci a nezabere moc místa, ale dokáže zařídit kompilaci, se kterou si normálně neporadím. Jediná potíž byla v tom, že SlimFTPd s MingW, který je jádrem DevC++, nespolupracuje. První nutnou úpravou tedy bylo přeprogramování chybějících funkcí, abych program vůbec mohl zkompilovat.

Podpora skupin uživatelů

Jedna věc, která mi na SlimFTPd chyběla opravdu hodně, byla jeho naprostá nepodpora skupin uživatelů: Pro každého uživatele bylo nutné celou konfiguraci nastavit úplně od nuly, což zvlášť oceníte v okamžiku, kdy je třeba předělat všechny cesty nebo všem uživatelům přidat práva na nový adresář. (Je mimochodem zajímavé, že nepodpora skupin je v FTP a zejména SFTP/FTPS serverech skoro nepsaným standardem, a pokud už vůbec podporována je, tak jen na velmi základní úrovni). Do SlimFTPd jsem tedy zapracoval skupiny tak, jak bych si to představoval já: U každého uživatele je možné použít jednu nebo víc direktiv Parent, které přiřadí uživateli nastavení z pojmenované skupiny (nebo uživatele – v SlimFTPd jsem skupiny implementoval tak, že skupina je vlastně běžným uživatelem, jehož heslo se ale vždy vyhodnotí jako chybné). Ukázka konfigurace to řekne lépe než tisíc slov:

<Group "everyone">
	Mount / C:\Ftp\FtpRoot
	Mount /upload C:\Ftp\Users\{$username}
	Mount /public C:\Ftp\Public
	Allow / Read List
	Allow /upload All
</Group>
<Group "download">
	Parent "everyone"
	Mount /download C:\Download
</Group>
<Group "private">
	Mount /disk-c C:\
	Mount /disk-d D:\
<User "anonymous">
	Parent "everyone"
	Password ""
</User>
<User "pepak">
	Parent "everyone"
	Parent "private"
	Password "12345"
</User>

Uživatel může být členem libovolně mnoha skupin, skupiny mohou být samy členy dalších skupin. Není mi úplně jasné, proč je takováhle struktura pro drtivou většinu ostatních FTP serverů tak nepřekonatelným problémem.

Pozn.: Řetězec {$username} bude v okamžiku přihlášení uživatele nahrazen uživatelským jménem. Tak mohu nastavit například uploadovací adresář na jediném místě a přitom mít pro každého uživatele jiný.

Podpora pro omezené síťové prostředí

Zajímavé je, že i v dnešní době masivního rozšíření různých osobních firewallů, NATů, dynamických IP adres a dalších radovánek stále existují mnohé FTP servery, které na to všechno kašlou a nechávají na uživateli, ať si pořídí pořádné připojení. SlimFTPd má ode mě rozšířenou podporu pro omezené prostředí:

Direktiva PassivePortRange umožňuje definovat rozsah portů, které bude SlimFTPd otvírat pro pasivní přenosy. Oč jde: původně FTP fungovalo jen v tzv. aktivním režimu – uživatel se připojil k serveru, a když chtěl přenášet data, řekl serveru, „připoj se ke mě na adresu X port Y a já si tam přijmu data“. Což je z dnešního hlediska k ničemu, protože jen menšina klientů je vůbec schopna otevřít tímto způsobem porty, a když už, tak k tomu často není z bezpečnostních důvodů ochotna. Proto byl zaveden tzv. pasivní režim, kdy naopak server řekne klientovi, „připoj se ke mě na adresu X port Y a já ti tam pošlu data“ – předpokládá se přitom, že server si dokáže zařídit otevřené porty spíš než klienti (už proto, že u serveru se to nastaví na jednom místě zatímco u klientů by se to muselo nastavovat pro každého klienta zvlášť). Jenže i server může mít určitá omezení, případně není bezpečné mu otevřít všechny porty. K tomu tato direktiva: mohu serveru říct, které porty má používat, například příkazem PassivePortRange 1024 5000.

Ještě důležitější je direktiva PassiveIPAddress, která řekne serveru, jakou adresu „X“ (viz výše) má klientovi hlásit. V neomezeném prostředí to není problém – server sedí na adrese 1.2.3.4 a tu také hlásí klientovi. Za NATem je to ovšem horší, protože server sice možná sedí na adrese 1.2.3.4, ale to je adresa vnitřní sítě, ke které se klient nemůže připojit, ani kdyby se na hlavu stavěl – on potřebuje znát veřejnou adresu, což může být třeba 5.6.7.8. A co hůř, ta adresa se může v průběhu času měnit. Mnohé FTP servery to řeší prostě tak, že problém neřeší vůbec a uspokojí se tím, že „o to se postará router“. Že to ne každý router dokáže a ne každý to dokáže správně, si hlavu nedělají. Já jsem radši zavedl další konfigurační direktivu, která tu adresu explicitně stanoví – a to v podobě doménového jména, které se vždy až v okamžiku použití převede na IP adresu: PassiveIPAddress ftp.server.cz.

Šifrování komunikace

Standardní FTP je zcela nešifrované – příkazy serveru (včetně přihlašovacích údajů) i přenášená data jsou přepravována zcela nechráněně. Toho si samozřejmě spousta lidí všimla a vymyslela různé varianty jako SFTP, FTPS, Secure FTP apod., případně rovnou úplně jiný protokol (SCP). Rozlišení, jak které z nich funguje, není až tak podstatné, protože vesměs vyžadují upraveného klienta (tzn. nejsou kompatibilní se standardní implementací FTP) a hlavně – až na naprosté výjimky mají zcela nedostatečné možnosti nastavení (kritizoval jsem neexistenci skupin – u šifrovaných FTP často nejde ani vytvářet uživatele, přebírají se uživatelé z operačního systému).

Já jsem si tedy stanovil tři požadavky: Šifrování bude prováděno formou obecného šifrovaného tunelu*). Server musí umět všechno to, co umí i v nešifrovaném režimu. Musí být podporování všichni FTP klienti. Zdálo by se obtížné tyto požadavky splnit, ale ve skutečnosti to bylo velice jednoduché – velice mi pomohla výše zmíněná direktiva PassiveIPAddress v kombinaci s tím, jak šifrované tunely fungují: obvykle jsou psány tak, že na localhostu otevřou jeden nebo více portů, data na ně přicházející jsou zašifrována a odeslána na druhý konec tunelu, kde se zase rozšifrují a pošlou na cílové místo. Řídící kanál FTP se tak dá zašifrovat docela jednoduše: Pokud server běží na adrese X a portu Y, stačí zařídit tunel, který spojí lokální port Y (localhost:Y) se vzdáleným portem Y (X:Y) a v klientu se připojit ne k vzdálenému portu (X:Y), ale k portu lokálnímu (localhost:Y). Datový kanál se tak zašifrovat nedá, protože server bude klientovi hlásit vzdálenou adresu a ne adresu lokální a datová komunikace tedy tunel úplně odejde. Pokud ovšem šikovně použijete direktivu PassiveIPAddress, můžete celý problém elegantně vyřešit. Vyžaduje to jen dvě věci: mít pro každého uživatele dva různé uživatelské účty (šifrovaný a nešifrovaný) a možnost nastavit různou PassiveIPAddress pro různé uživatele:

# standardni adresa
PassiveIPAddress ftp.server.cz
# tohle je nesifrovany uzivatel
<User "pepak">
	Password "12345"
	Mount / C:\
	Allow / Read List
</User>
# a tohle sifrovany; ani nepotrebuje heslo,
# pokud jsou parametry tunelu tajne
<User "pepakENC">
	Parent "pepak"
	PassiveIPAddress 127.0.0.1
</User>

Mohu použít libovolného FTP klienta, jakého mám zrovna po ruce. To, jestli použiju šifrované nebo nešifrované spojení, pak určím adresou FTP serveru a přihlašovacím jménem: Pokud mám tunel k dispozici, připojím se k localhost:21 uživatelským jménem pepakENC (zde dokonce bez hesla). Když tunel nemám nebo se bojím ho použít, připojím se k ftp.server.cz:21 uživatelským jménem pepak a heslem 12345.

Pozn.: Proč šifrovaný tunel a ne VPN, se kterou bych šifrování FTP dostal úplně bezpracně: Protože Windowsovské implementace VPN vyžadují předběžnou instalaci s administrátorskými právy, zatímco tunely mohou běžet v uživatelském režimu i zcela bez instalace.

Přesun konfiguračního a logovacího souboru

Jedna drobná muška SlimFTPd, která asi drtivou většinu uživatelů trápit nebude, je umístění pracovních souborů (konfiguračního a logovacího): standardně je SlimFTPd ukládá do adresáře, kde má EXE soubor. Mě to trochu omezovalo, protože 1) do adresáře exe souborů nerad přiděluji právo zápisu, a 2) když už tam právo zápisu povolím, tak jenom proto, že to je ramdisk, který se po každém restartu inicializuje na výchozí hodnotu (což by poněkud snižovalo účinek změn v konfiguraci…). Přidal jsem proto commandlajnové argumenty (haha, že už jste si mysleli, že tu budu mít jeden článek, ve kterém se „command line“ nevyskytne?) -log a -conf, které umožní tyto soubory přesunout jinam.

Podpora Yubikey

Člověk se často dostane do situace, kdy musí použít nedůvěryhodný počítač. Šifrovaný tunel v takové situaci nepomůže – je hezká věc pro zabránění útokům typu man-in-the-middle, ale má jednu nevýhodu: Pokud ho použiju na zkompromitovaném počítači, může se docela klidně stát, že mi ten kompromitovaný počítač celý tunel zkopíruje a přepošle svému pánovi k dalšímu použití. Jenže co dělat, když ten nedůvěryhodný počítač (třeba u zákazníka nebo ve škole) použít musím? Odpovědí je „jednorázové heslo“: Tak ať si ho útočník zachytí, stejně mu to bude málo platné, protože při příštím použití už to heslo bude odmítnuto jako neplatné!

Pro implementaci Yubikey do SlimFTPd jsem využil posledně popsanou knihovnu PkYubikey, v podstatě přesně podle toho, jak jsem v onom článku popsal (geneze celého systému byla ostatně opačná – napřed jsem implementoval PkYubikey do SlimFTPd a ověřil funkčnost, a teprve potom jsem začal psát článek o tom, jak se dá PkYubikey použít). Majitel serveru si zaregistruje svůj Yubikey utilitou PkYubikey.exe s parametrem -r pod nějaké jméno, a následně toto jméno zapíše do konfigurace SlimFTPd:

<User "pepak">
	Yubikey "pepak"
</User>

Takhle to má ovšem drobnou nevýhodu: Pokud by mi někdo Yubikey ukradl, mohl by – do doby, než se dostanu k serveru, abych mu změnil konfiguraci – se k FTP přihlašovat pod mým uživatelským účtem. Proto jsem zavedl i možnost použít současně heslo i Yubikey: Začátek uživatelova hesla se napřed porovná s heslem k účtu, a pokud to sedí, zbytek se použije jako jednorázové heslo Yubikey. Takže i kdybych o Yubikey přišel, zloději to k ničemu nebude, protože nebude znát moje tajné heslo. Naopak útočník, který zachytí zmáčknuté klávesy nebo přímo proběhlou komunikaci, sice zjistí moje tajné heslo, ale bez schopnosti vytvořit jednorázové Yubikeyovské heslo, mu to stejně k připojení nebude stačit.

Download

SlimFTPd byl uvolněn pod licencí BSD. U všech verzí jsou přiloženy i kompletní zdrojové kódy. Z knihovny PkYubikey jsou přiloženy jen potřebné spustitelné soubory, zdrojové kódy je možné stáhnout ze stránky o PkYubikey.

  • SlimFTPd 3.181 Pepak 0.15 (144 KB, 28.6.2011) – Opraven nedostatek ve vyhodnocování pasivní IP adresy – pokud byla zadána doménovým jménem a tomuto jménu odpovídalo víc IP adres, mohlo se stát, že se klientovi poslala adresa neveřejná, na kterou se pochopitelně nemohl připojit. Nyní jsou vždy preferovány veřejné adresy.
  • SlimFTPd 3.181 Pepak 0.14 (143 KB, 25.10.2010) – Všechny spustitelné soubory byly digitálně podepsány.
  • SlimFTPd 3.181 Pepak 0.13 (179 KB, 22.9.2009) – první veřejná verze.
  • SlimFTPd 3.181 (60 KB, 14.5.2007) – původní verze od Marka Whitlocka.

Podobné příspěvky:

4 komentáře “SlimFTPd”

  1. avatar pepak napsal:

    Připojení: V dnešní době už bych o FTP vůbec neuvažoval. Jdi do SFTP, Bitvise SSH Server moje požadavky zvládá docela dobře (až na Yubikey).

  2. avatar Připojení napsal:

    Díky za článek. Detail je naprosto úžasný, především v šifrování mi otevřel oči. Díky

  3. avatar pepak napsal:

    Verze 0.15: Opraven nedostatek ve vyhodnocování pasivní IP adresy – pokud byla zadána doménovým jménem a tomuto jménu odpovídalo víc IP adres, mohlo se stát, že se klientovi poslala adresa neveřejná, na kterou se pochopitelně nemohl připojit. Nyní jsou vždy preferovány veřejné adresy.

  4. avatar pepak napsal:

    Verze 0.14: Všechny spustitelné soubory byly digitálně podepsány.

Leave a Reply

Themocracy iconWordPress Themes

css.php