Delší dobu jsem přemýšlel, že napíši nějaké pořádné howto na toto téma. Nakonec jsem si našel čas a sepsal něco, co by měl pochopit úplně každý.

FTP server proftpd - mysql, quoty, šifrování (ftps), práva

Proftpd jsem si vybral jednoduše proto, jelikož ho delší čas používám. Stejně tak jako MySQL a né ldap. Vše má své pro i proti, rozhodnutí je na vás. Vše je postaveno na distribuci GNU/Debian(Lenny), ale věřím, že nebude problém použít tento návod i na jiné distribuce. Jelikož je proftpd velmi modulárním ftp serverem, tak si i ukážeme, jak si ho zkompilovat s vlastními moduly a moduly třetích stran. Směle tedy do toho :).

Nezbytené vystvětlivky - velmi stručně a rychle

FTP (File Transfer Protocol)
Nešifrovaný protokol pro přenos dat. Přenosová rychlost je dobrá, nicméně není určen k přenosu souborů o velké velikosti (může docházet k nekonzistenci dat, protokol není navržen pro možné výpadky spojení atd.). Je velmi pomalý při přenosu velkého počtu malých souborů (stále navazuje spojení atd.). Spojení probíhá na portu 21, samotný přenos dat pak na portu 20. Tzn, že ke komunikaci používá více portů.
FTP může probíhat ve dvou základních režimech :

aktivní : Server navazuje spojení(pro přenos dat : data connection), klient naslouchá, komunikace běží klasicky na portech 21 a 20. Problém nastavá u NATu.
pasivní : Data connection navazuje klient a to na portech vyšších jak 1024 (na serveru je definován rozsah portů, třeba několik stovek)

FTPS (File Transfer Protocol over SSL/TLS)
Rozšíření ftp protokolu o SSL/TLS šifrování. Začínají být problémy při NAT traversion. Jsou dvě metody :
Explicitní FTPS (FTPES) : Klient se připojí na port 21, zahajuje nešifrovanou komunikaci a žádá o aktivaci šifrovaného spojení TLS.
Implicitní FTPS : Starší způsob. Klient se připojuje na jiný port (většinou 990) a aktivace SSL je provedena před zasláním jakéhokoliv příkazu.

Secure FTP (FTP přes SSH)
Nejdříve se vytvoří pomocí ssh tunel, přes který poté běží samotná komunikace ftp. Dost lidí zaměňuje "Secure FTP" a "SFTP". Tak pozor nato, jedná se o dvě zcela rozdílné věci.

SFTP (SSH File Transfer Protocol)
Čímdálvíc rozšířenější protokol pro přenos dat. S klasickým FTP již nemá nic společného. SFTP k autentizaci a přenosu dat používá většinou porotokol SSH-2. Je vlastně takovou náhradou za velmi jednoduchý protokol scp.

My se tedy v článku zaměříme na FTP a FTPS s explicitním šifrováním.

Příprava prostředí

Nejdříve nainstalujeme příslušné balíčky (typ spouštění proftpd nastavíme jako standalone):

aptitude install mysql-server mysql-client libmysqlclient12-dev proftpd-basic proftpd-mod-mysql

Dále vytvoříme příslušnou skupinu :

groupadd -g 2001 proftpd

Instalací proftpd by se nám měl automaticky vtvořit i uživatel, komu ne, nechť si ho vytvoří :

useradd proftpd

Uživateli nastavíme domovský adresář a přiřadíme k příslušné skupině :

usermod -d /home/ftp -g proftpd -u 2001 proftpd -s /bin/false
chown -R proftpd:proftpd /home/ftp/

Nyní máme vytvořenou skupinu a uživatele, pod nimiž bude server běžet. Ještě musíme vytvořit uživatele a skupinu, pod jejichž právami si budou klienti ukládat svá data na ftp server.

groupadd ftpgroup -g 2002
useradd ftpuser -d /home/ftp -u 2002 -g ftpgroup -s /bin/false

Kompilace ze zdrojových kodů a moduly třetích stran

Pro ukázku možností proftpd jsem si zvolil kompilaci se všemi možnými standardními moduly a následujícími moduly třetích stran :

mod_md5 (instalace)
Tento modul umožňuje automaticky po uploadu souboru na ftp vytvořit soubor, ve kterém bude md5 hash uploadovaného souboru.

mod_sftp (instalace)
mod_sftp_sql (instalace)
Tyto dva moduly zahrnují podporu sftp (s sql) do proftpd. Výše jsme si říkali, že protokol sftp nemá nic s ftp společného, což je pravda, ale tento modul je takový wrap do ssh. Použitím tohoto modulu dosáhneme té výhody, že budeme moci využít některá nastvení proftpd.

mod_vroot (instalace)
Tento modul umožňuje podporu virtuálního chrootu klientů bez potřeby rootovských práv.

Další moduly je možno vidět zde :
Modules

Nejdříve si nainstalujeme programy a knihovny potřebné pro kompilaci :

aptitude install gcc g++ make bzip2 libmysql++-dev postgresql-server-dev-8.3 libldap2-dev libwrap0-dev checkinstall

Dále stáhnout a rozbalit archiv. Kdo chce přímo vývojovou verzi, tak si jí může stáhnout přímo z cvs :

aptitude install cvs
cvs -d :pserver:anonymous@proftp.cvs.sourceforge.net:2401/cvsroot/proftp -z3 co proftpd

Já mám odzkoušenou současnou stable verzi :

cd /usr/local/src/
wget -c ftp://ftp.proftpd.org/distrib/source/proftpd-1.3.2.tar.bz2
tar xvfj proftpd-1.3.2.tar.bz2

Stáhneme si moduly, rozbalíme a poté nakopíruje do příslušných míst :

wget -c http://www.castaglia.org/proftpd/modules/proftpd-mod-md5-0.3.3.tar.gz
wget -c http://www.castaglia.org/proftpd/modules/proftpd-mod-sftp-0.9.6.tar.gz
wget -c http://www.castaglia.org/proftpd/modules/proftpd-mod-sftp-sql-0.1.tar.gz
wget -c http://www.castaglia.org/proftpd/modules/proftpd-mod-vroot-0.8.5.tar.gz

tar xvfz proftpd-mod-md5-0.3.3.tar.gz
tar xvfz proftpd-mod-sftp-0.9.6.tar.gz
tar xvfz proftpd-mod-sftp-sql-0.1.tar.gz
tar xvfz proftpd-mod-vroot-0.8.5.tar.gz

cp mod_md5/mod_md5.c proftpd-1.3.2/contrib/
cp -r mod_sftp proftpd-1.3.2/contrib/
cp mod_sftp_sql/mod_sftp_sql.c proftpd-1.3.2/contrib/
cp mod_vroot/mod_vroot.c proftpd-1.3.2/contrib/

Nakonfigurujeme. Kdo neví, jak nato, pomůže si nainstalovat distribuční verzi proftpd a podívat se, jak je nakonfigurována (poté jí stačí opět odinstalovat) :

aptitude install proftpd-basic proftpd-mod-mysql

proftpd -V
Compile-time Settings:
  Version: 1.3.2 (stable)
  Platform: LINUX
  Built: Po čen 1 02:12:43 CEST 2009
  Built With:
    configure  '--prefix=/usr' '--with-includes=/usr/include/postgresql:/usr/include/mysql' '--mandir=/usr/share/man' '--sysconfdir=/etc/proftpd' '--localstatedir=/var/run' '--libexecdir=/usr/lib/proftpd' '--disable-sendfile' '--enable-facl' '--enable-dso' '--enable-autoshadow' '--enable-ctrls' '--with-modules=mod_readme' '--enable-ipv6' '--enable-nls' '--build' 'i486-linux-gnu' '--with-shared=mod_site_misc:mod_load:mod_ban:mod_quotatab:mod_sql:mod_sql_mysql:mod_sql_postgres:mod_dynmasq:mod_quotatab_sql:mod_ldap:mod_quotatab_ldap:mod_ratio:mod_tls:mod_rewrite:mod_radius:mod_wrap:mod_wrap2:mod_wrap2_file:mod_wrap2_sql:mod_quotatab_file:mod_quotatab_radius:mod_facl:mod_ctrls_admin:mod_ifsession' 'build_alias=i486-linux-gnu'
...

aptitude remove proftpd-basic proftpd-mod-mysql

Nyní se stačí jen podívat do changelogu nové verze, poupravit si drobnosti a jdeme nato (pozor! mod_ifsession musí být uveden až po mod_md5, nejlepší by stejně bylo, kdyby byl až nakonci):

cd proftpd-1.3.2
./configure --prefix=/usr --with-includes=/usr/include/postgresql:/usr/include/mysql 
--mandir=/usr/share/man --sysconfdir=/etc/proftpd --localstatedir=/var/run 
--libexecdir=/usr/lib/proftpd --enable-facl --enable-dso --enable-openssl 
--enable-autoshadow --enable-ctrls --with-modules=mod_readme --enable-ipv6 
--enable-nls --build i486-linux-gnu 
--with-shared=mod_unique_id:mod_vroot:mod_site_misc:mod_load:mod_ban:mod_quotatab:mod_sql:mod_sql_mysql:mod_sql_postgres:mod_dynmasq:mod_quotatab_sql:mod_ldap:mod_quotatab_ldap:mod_ratio:mod_tls:mod_rewrite:mod_radius:mod_wrap:mod_wrap2:mod_wrap2_file:mod_wrap2_sql:mod_quotatab_file:mod_quotatab_radius:mod_facl:mod_ctrls_admin:mod_sftp:mod_sftp_sql:mod_md5:mod_ifsession

Zkompilujeme, zabalíme do balíčku pomocí checkinstall a nainstalujeme (Checkinstall je dostačující a rychlá věc pro koncové balíčky, na kterých už nic jiného nezávisí. Pro jiné záležitosti bych si ho nedovolil použít.) :

make
checkinstall -D
dpkg -i proftpd_1.3.2-1_i386.deb

Nyní bychom měli mít nainstalovaný proftpd server s podorou všeho možného :).
Na závěr přikládám záznam výše provedencýh událostí proftpd_compile.log

Příprava MySQL

Nyní vytvoříme databázi pro proftpd a současně i uživatele :

mysql -u root -p
mysql> create database proftpd;
GRANT ALL PRIVILEGES ON proftpd.* TO proftpd@localhost IDENTIFIED BY 'mojeheslo';
FLUSH PRIVILEGES;

Tak, nyní můžeme začít vytvářet tabulky. První bude se skupinami :

mysql> use proftpd;
mysql> 
CREATE TABLE proftpd_group (
groupname varchar(16) NOT NULL default 'ftpuser',
gid smallint(6) NOT NULL default '2002',
members varchar(16) NOT NULL default 'ftpgroup',
KEY groupname (groupname)
) TYPE=MyISAM COMMENT='ProFTP group table';

Tabulky pro quoty musí být biginit. Pokud jsou jen init, tak mod_ifsessionmůže být velikost quoty maximálně 4GiB. Tj, ať se do tabulky pokusíte zapsat sebevětší číslo, tak víc jak 4294967295B tam nenacpete.

mysql> 
CREATE TABLE proftpd_quota (
name varchar(30) default NULL,
quota_type enum('user','group','class','all') NOT NULL default 'user',
per_session enum('false','true') NOT NULL default 'false',
limit_type enum('soft','hard') NOT NULL default 'soft',
bytes_in_avail bigint(10) unsigned NOT NULL default '0',
bytes_out_avail bigint(10) unsigned NOT NULL default '0',
bytes_xfer_avail bigint(10) unsigned NOT NULL default '0',
files_in_avail bigint(10) unsigned NOT NULL default '0',
files_out_avail bigint(10) unsigned NOT NULL default '0',
files_xfer_avail bigint(10) unsigned NOT NULL default '0'
) TYPE=MyISAM;

Tabulka "proftpd_quota_allies" slouží pro interní věci proftpd. Do ní nic nebudeme zapisovat.


mysql> 
CREATE TABLE proftpd_quota_allies (
name varchar(30) NOT NULL default '',
quota_type enum('user','group','class','all') NOT NULL default 'user',
bytes_in_used bigint(10) unsigned NOT NULL default '0',
bytes_out_used bigint(10) unsigned NOT NULL default '0',
bytes_xfer_used bigint(10) unsigned NOT NULL default '0',
files_in_used bigint(10) unsigned NOT NULL default '0',
files_out_used bigint(10) unsigned NOT NULL default '0',
files_xfer_used bigint(10) unsigned NOT NULL default '0'
) TYPE=MyISAM;

Tabulka pro virtuální uživatele :

mysql> 
CREATE TABLE proftpd_user (
id int(10) unsigned NOT NULL auto_increment,
userid varchar(32) NOT NULL default '',
passwd varchar(32) NOT NULL default '',
uid smallint(6) NOT NULL default '2002',
gid smallint(6) NOT NULL default '2002',
homedir varchar(255) NOT NULL default '',
shell varchar(16) NOT NULL default '/bin/false',
count int(11) NOT NULL default '0',
accessed datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (id),
UNIQUE KEY userid (userid)
) TYPE=MyISAM COMMENT='ProFTP user table';

Zapíšeme informace o lokálním uživately (ten, pod kterým má uživatel ftp práva) do db :

mysql> INSERT INTO `proftpd_group` (`groupname`, `gid`, `members`) VALUES ('ftpuser', 2002, 'ftpgroup');

Vytvoříme si testovacího uživatele s limitem ftp 15MiB :

mysql> INSERT INTO `proftpd_quota` (`name`, `quota_type`, `per_session`, `limit_type`, `bytes_in_avail`, `bytes_out_avail`, `bytes_xfer_avail`, `files_in_avail`, `files_out_avail`, `files_xfer_avail`) VALUES ('admin', 'user', 'true', 'hard', 15728640, 0, 0, 0, 0, 0);
mysql> INSERT INTO `proftpd_user` (`id`, `userid`, `passwd`, `uid`, `gid`, `homedir`, `shell`, `count`, `accessed`, `modified`) VALUES (1, 'admin', 'mojeheslo', 2002, 2002, '/home/ftp/', '/sbin/nologin', 0, '', '');
mysql> quit

Další uživatele vytváříme stejně, jen změníme hodnotu ID(o jeden výše) a userid/name (jméno uživatele :) ). V selectu jsou tučně vyznačeny. Toto jsou nezbytné položky dalšího nového uživatele. Volitelné položky jsou potom třeba "domovský adresář", "quota" atd.

Nastavení proftpd

Zde předkládám tři nutné konfigurační soubory. Jejich komentáře snad mluví za vše.

/etc/proftpd/proftpd.conf

#
# /etc/proftpd/proftpd.conf -- Toto je zakladni konfiguracni soubor proftpd.
# Pokud chceme uplatnit veskere zmeny, je treba reloadnout proftpd.
#

### Vloz konfiguracni soubor s DSO moduly :
Include /etc/proftpd/modules.conf

### Podporovat ipv6? :
UseIPv6                         on

### Jmeno serveru :
ServerName                      "Nas novy ftp server"

### Typ spusteni (standalone = daemon nebo inetd = superserver)
ServerType                      standalone

### Podpora RFC2228 - kazdy radek ma kod, coz je lehci pro komunikaci s klientem :
MultilineRFC2228                on

### Pokud prijde pozadavek na ip a ne na dns nazev(hlavne u VirtualServeru), 
# tak by server vyhodil nedostupnost sluzby, zapnuti direktivy toto resi :
DefaultServer                   on

### Nasledovat symlinky? :
ShowSymlinks                    off

### Casove limity, po kterych dojde k odpojeni (v sekundach):
# Casovy limit pro prihlaseni
TimeoutLogin                    120
# Bezprostredne po pripojeni bez jakehokoli pozadavku :
TimeoutNoTransfer               600
# Delka zivotnosti procesu prenosu dat, kterym se data prestala prenaset :
TimeoutStalled                  600
# Jak dlouho muze byt klient necinny po dokonceni prenosu dat :
TimeoutIdle                     1200

### Zobrazit uvitaci zpravu :
# (zadanim relativni cesty dame moznost uzivateli definovat si onu zpravu):
# DisplayLogin                    welcome.msg
# Zadanim absolutni cesty, bude nastaveni pro vsechny uzivatele stejne :
DisplayLogin                    /home/ftp/welcome.msg

### Nezobrazovat uvitaci text driv, nez je uzivatel prihlasen
DeferWelcome                    off

### Po otevreni adresare se objevi hlaska, zastarale, vetsina prohlizecu ignoruje :
DisplayChdir                    .message true

### ListOptions : definuje, jak bude vypadat vypis adresare :
# -l Jedna radka pro jeden soubor
# -A Vypis vsechny soubory vyjma "." a ".."
# -a Vypis vsechny soubory vcetne skrytych (tj. zacinajicich "." - napriklad .htaccess)
# -C Vypis do kolonek
# -d Vypis jen adresare (misto jejich obsahu)
# -F V pripade, ze dany soubor obsahuje identifikator souboru ("*", "/", "=", "@" or "|"), vypise jej take
# -h Vypisuje velikosti souboru v "citelnejsi" podobe (1K, 10MB, 2,4GB atd.)
# -L Vypisuje soubory, na ktere ukazuje symbolicky odkaz
# -l Podrobny vypis
# -n Pri vypisu ukaze jen cisla GID a UID pro skupiny/uzivatel misto jejich nazvu
# -R Bude prochazet adresare rekurzivne
# -r Vypise soubory v obracenem poradi
# -S Seradi a vypise soubory podle velikosti
# -t Seradi a vypise soubory podle data posledni upravy
ListOptions                     "-l"

### Zakazat rootovi prihlasit se na ftp :
RootLogin          off

### Nepozadujeme, aby mel uzivatel shell :
RequireValidShell               off

### Zabezpeceni proti nastaveni nebezpecnych filtru na masku regularniho vyrazu
DenyFilter                      \*.*/

### Pokud chceme, aby byli vsichni uzivatele
# pouze ve svych domovskych adresarich, tak pouzijeme "~"
DefaultRoot                     ~

### Port, na kterem ma proftpd naslouchat (stadardne 21)
Port                            21

### Pro pasivni prenos nastavime rozsah komunikacnich portu :
PassivePorts                  40000 44000

### Maximalni pocet instanci (hlavne proti DoS utoku), 
# funguje pouze v rezimu serveru jako standalone :
MaxInstances                    30

### Maximalni pocet klientu :
MaxClients      10 "Promin, maximalne %m uzivatelu -- zkus se pripojit pozdeji"

### Omezeni poctu pripojeni jednoho klienta
MaxClientsPerHost	        3	"Muzes byt pripojen pouze : %m"

### Maximalni pocet pokusu o prihlaseni :
MaxLoginAttempts                3

### Ma byt uzivatelske jmeno ziskano pres ident(RFC1413) ?
# Pokud je volba zapnuta, tak se dosti prodlouzi prihlasovani :
IdentLookups                    off 

### Pokud je volba zapnuta, server zjistuje existenci reverzniho zaznamu
# klienta (minoritni bezpecnostni prvek). Tim se ovsem opet zpomaluje prihlasovani.
UseReverseDNS                   off

### Ma se cas zobrazovat v GMT a ne lokalni? :
TimesGMT                        off

### Uzivatel a skupina, pod nimiz je server spusten :
User                            proftpd
Group                           proftpd

### Linuxovy umask noveho adresare a souboru :
Umask                           022  022

### Soubory mohou byt prepisovany :
AllowOverwrite                  on

### Povolit klientum znovu navazat na stahovani
AllowRetrieveRestart            on

### Povolit klientum znovu navazat na upload
AllowStoreRestart               on

### Povolit .ftpaccess soubory (trochu zpomaluje vypis slozky)
AllowOverride                   on

### Zakaze zobrazeni vsemoznych informaci o serveru(verzi apod) hnedle po prihlaseni
# (takovy maly bezpecnostni prvek)
ServerIdent                     Off

### Zamaskovat skutecne jmeno uzivatele souboru / adresare :
DirFakeUser                     on pepa

### Zamaskovat skutecne jmeno skupiny souboru / adresare :
DirFakeGroup                    on pepagroup

### Zamaskuje nastaveni prav na souboru :
DirFakeMode                     0000


### Pokud adresar uzivatele neexistuje, tak ho vytvori s pravy 755 :
CreateHome on 755 dirmode 755

### Maximalni cas procesoru v sekundach na proces :
#RLimitCPU 600 600
### Maximum pameti pouzitou na proces (v bajtech) :
#RLimitMemory 64M 64M
### Maximalni pocet otevrenych souboru na proces :
#RLimitOpenFiles 1024 1024

### Logujeme :
TransferLog /var/log/proftpd/xferlog
SystemLog   /var/log/proftpd/proftpd.log
# Zaznamenavat vsechny sql dotazy (jen v pripade ladeni, jinak nedoporucuji zapinat) :
#SQLLogFile /var/log/proftpd/sqllog.log

LogFormat default "%h %l %u %t \"%r\" %s %b"
LogFormat auth "%v [%P] %h %t \"%r\" %s"
LogFormat write "%h %l %u %t \"%r\" %s %b"

### Zaznamenavat pristupy k souborum a adresarum :
ExtendedLog /var/log/proftpd/proftpd.access_log WRITE,READ write

### Zapsat vsechna prihlaseni :
ExtendedLog /var/log/proftpd/proftpd.auth_log AUTH auth

### Paranoidni uroven zaznamu :
# ExtendedLog /var/log/proftpd/proftpd.paranoid_log ALL default

### Povolit logovani pomoci symlinku :
AllowLogSymlinks off

### Nastaveni pro acl aj. (vypnuto) :
<IfModule mod_ctrls.c>
ControlsEngine        off
ControlsMaxClients    2
ControlsLog           /var/log/proftpd/controls.log
ControlsInterval      5
ControlsSocket        /var/run/proftpd/proftpd.sock
</IfModule>

<IfModule mod_ctrls_admin.c>
AdminControlsEngine on
</IfModule>

### Vlozit konfiguracni soubor ohledne nastaveni sql :
Include /etc/proftpd/sql.conf

/etc/proftpd/sql.conf

Jen si nezapomeňte v tomto souboru změnit heslo dle svého.

#
# Ukazkovy Proftpd konfiguracni soubor pro SQL-based autentizaci.
#

<IfModule mod_sql.c>
#
# Vyberte SQL backend : MySQL nebo PostgreSQL.
# Oba moduly jsou nacitany v defaultnim nastaveni, specifukujte tedy, ktery backend ma byt pouzit
# a zakomentujte, nebo odkomentujte prislusne direktivy v /etc/proftpd/modules.conf.
# Opet lze pouzit hodnoty 'mysql' nebo 'postgres'.
#

### Jaky backend (databazi) pouzijeme :
SQLBackend      mysql

### Zapneme podporu SQL :
SQLEngine on
AuthOrder mod_sql.c

### Pouzit backend-crypted nebo crypted password
#SQLAuthTypes Backend Crypt
# hesla jsou ulozena v MD5 hashi (plati jen v pripade, ze je proftpd zkompilovan s touto moznosti) :
#SQLAuthTypes MD5

SQLAuthTypes Plaintext Crypt

### Pripojeni :
#===============
SQLConnectInfo proftpd@localhost proftpd mojeheslo
SQLUserInfo     proftpd_user userid passwd uid gid homedir shell
SQLGroupInfo    proftpd_group groupname gid members
SQLMinID        500

### Vytvorit automaticky adresar uzivatele - zastarale, v dalsi verzi nebude fungovat :
#SQLHomedirOnDemand on

SQLLog PASS updatecount
SQLNamedQuery updatecount UPDATE "count=count+1, accessed=now() WHERE userid='%u'" proftpd_user
SQLLog  STOR,DELE modified
SQLNamedQuery modified UPDATE "modified=now() WHERE userid='%u'" proftpd_user

### Uzivatelske quoty :
#=======================
QuotaEngine on
QuotaLog /var/log/proftpd/quota.log
QuotaDirectoryTally on
QuotaDisplayUnits Mb
QuotaShowQuotas on

SQLNamedQuery get-quota-limit SELECT "name, quota_type, per_session, limit_type, bytes_in_avail, bytes_out_avail, bytes_xfer_avail, files_in_avail, files_out_avail, files_xfer_avail FROM proftpd_quota WHERE name = '%{0}' AND quota_type = '%{1}'"

SQLNamedQuery get-quota-tally SELECT "name, quota_type, bytes_in_used, bytes_out_used, bytes_xfer_used, files_in_used, files_out_used, files_xfer_used FROM proftpd_quota_allies WHERE name = '%{0}' AND quota_type = '%{1}'"

SQLNamedQuery update-quota-tally UPDATE "bytes_in_used = bytes_in_used + %{0}, bytes_out_used = bytes_out_used + %{1}, bytes_xfer_used = bytes_xfer_used + %{2}, files_in_used = files_in_used + %{3}, files_out_used = files_out_used + %{4}, files_xfer_used = files_xfer_used + %{5} WHERE name = '%{6}' AND quota_type = '%{7}'" proftpd_quota_allies

SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, %{4}, %{5}, %{6}, %{7}" proftpd_quota_allies

QuotaLimitTable sql:/get-quota-limit
QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally

SQLNamedQuery gettally  SELECT "ROUND((bytes_in_used/1048576),2) FROM proftpd_quota_allies WHERE name='%u'"
SQLNamedQuery getlimit  SELECT "ROUND((bytes_in_avail/1048576),2) FROM proftpd_quota WHERE name='%u'"
SQLNamedQuery getfree   SELECT "ROUND(((proftpd_quota.bytes_in_avail-proftpd_quota_allies.bytes_in_used)/1048576),2) FROM proftpd_quota,proftpd_quota_allies WHERE proftpd_quota.name = '%u' AND proftpd_quota_allies.name = '%u'"

SQLShowInfo   LIST    "226" "Vyuzito %{gettally}MiB z %{getlimit}MiB. Jeste vam zbyva %{getfree}MiB volneho mista."

/etc/proftpd/modules.conf

#
# Tento soubor je pouzivan ke sprave DSO modulu a funkci.
# 

### Adresar, kde jsou DSO moduly umisteny :
ModulePath /usr/lib/proftpd

### Pouze root muze pripojovat a odpojovat moduly,
# ostatni mohou jen videt pripojene moduly :
ModuleControlsACLs insmod,rmmod allow user root
ModuleControlsACLs lsmod allow user *

LoadModule mod_ctrls_admin.c
LoadModule mod_tls.c

### Pokud chceme pouzit mysql(proftpd-mod-mysql), nebo postgresql (proftpd-mod-pgsql), tak odkomentujeme :
LoadModule mod_sql.c

### Pokud chceme pouzit ldap, tak odkomentujeme :
#LoadModule mod_ldap.c


### Direktivy 'SQLBackend mysql' nebo 'SQLBackend postgres' vyzaduji, kterou sql autorizaci maji pouzit.
# Odkomentujte tedy prislusny modul :
# Pri pouziti proftpd-mod-mysql odkomentujeme toto :
LoadModule mod_sql_mysql.c
# Pri pouziti proftpd-mod-pgsql odkomentujeme toto :
#LoadModule mod_sql_postgres.c

LoadModule mod_radius.c
LoadModule mod_quotatab.c
LoadModule mod_quotatab_file.c

### Pri pouziti proftpd-mod-ldap odkomentujeme toto :
#LoadModule mod_quotatab_ldap.c

### Nainstalovany proftpd-mod-pgsql nebo proftpd-mod-mysql pouziva tyto moduly :
LoadModule mod_quotatab_sql.c
LoadModule mod_quotatab_radius.c
LoadModule mod_wrap.c
LoadModule mod_rewrite.c
LoadModule mod_load.c
LoadModule mod_ban.c
LoadModule mod_wrap2.c
LoadModule mod_wrap2_file.c

#LoadModule mod_wrap2_sql.c
LoadModule mod_dynmasq.c


# Nechte tento modul posledni :
LoadModule mod_ifsession.c

Nyní stačí jen reloadnout proftpd :

/etc/init.d/proftpd restart

Šifrujeme

Kdo chce šifrovat, až se z něj bude prášit, tak směle do toho. Nejdříve budeme potřebovat openssl :

aptitude install openssl

Vygenerujeme certifikáty :

mkdir /etc/proftpd/ssl
openssl req -new -x509 -days 365 -nodes -out /etc/proftpd/ssl/proftpd.cert.pem -keyout /etc/proftpd/ssl/proftpd.key.pem
chown root:root /etc/proftpd/ssl/*
chmod 600 /etc/proftpd/ssl/proftpd.key.pem
chmod 644 /etc/proftpd/ssl/proftpd.cert.pem

Do /etc/proftpd/proftpd.conf přidáme následující řádek :

Include /etc/proftpd/tls.conf

Vytvoříme soubor /etc/proftpd/tls.conf a přidáme do něj :

#
# Ukazkovy konfiguracni soubor Proftpd pro FTPS spojeni.
#
# Pozor, FTPS zavadi nekolik omezeni pri NAT traversi.
# Pro vice informaci se podivejte na :
# http://www.castaglia.org/proftpd/doc/contrib/ProFTPD-mini-HOWTO-TLS.html
#

<IfModule mod_tls.c>

### Povolit proftpd TLS/SSL :
TLSEngine                               on

### Soubor s logem pro vse ohledne tls spojeni :
TLSLog                                  /var/log/proftpd/tls.log

### Typ protokolu - TLSv1, SSLv3, SSLv23(kompatibilita obou predchozich) :
TLSProtocol                             SSLv23

#
# Pokud chcete vygenerovat self-signed certifikat, pouzijte tento prikaz :
#
# openssl req -x509 -newkey rsa:1024 \
#          -keyout /etc/proftpd/ssl/proftpd.key.pem -out /etc/proftpd/ssl/proftpd.cert.pem \
#          -nodes -days 365
#
# Soubor proftpd.key.pem musi byt citelny pouze pro uzivatele root. Ostatni soubory mohou
# byt citelne pro kohokoli.
#
# chmod 0600 /etc/proftpd/ssl/proftpd.key.pem
# chmod 0640 /etc/proftpd/ssl/proftpd.cert.pem
#

### Cesty k certifikatum :
TLSRSACertificateFile                   /etc/proftpd/ssl/proftpd.cert.pem
TLSRSACertificateKeyFile                /etc/proftpd/ssl/proftpd.key.pem

### Soubor s certifikatem certifikacni autority (CA) pro overovani klientu :
#TLSCACertificateFile                    /etc/ssl/certs/CA.pem
# cesta k crtifikatum pro overovani klientu pomoci CA :
#TLSCACertificatePath                    /etc/ssl/certs/
# cesta ke zrusenemu/neduveryhodnemu certifikatu :
#TLSCARevocationFile                     /etc/ssl/revocate/CA.pem
# cesta ke zrusenym/neduveryhodnym certifikatum :
#TLSCARevocationPath

### Neoverovat klientuv certifikat :
TLSOptions                              NoCertRequest

### Nedotazovat se na klientuv certifikat :
TLSVerifyClient                         off

### Vyzadovat TLS spojeni, pokud je off, klient se bude moci pripojit i nesifrovane :
TLSRequired                             off

### Presne nevim, ale myslim si, ze to je sprava docasnych certifikatu :
# spojeni se navaze s trvalym certifikatem a dalsi komunikace a prenos dat
# probiha s docasnym. Da se nastavit platnost docasneho v navaznosti na
# case prenosu, objemu prenesenych dat atd.
# Tuto fci rozhodne moc klientu nepodporuje, takze se asi ani moc nepouziva.

# Nastavit tak, aby nebylo nutny, ale jen pozadovany/dobrovolny :
#TLSRenegotiate required off
# Po 1 hodine :
#TLSRenegotiate ctrl 3600
# Po preneseni 500MiB dat :
#TLSRenegotiate data 512000
# Timeout :
#TLSRenegotiate timeout 300
# Veskere nastaveni v jedne directive :
#TLSRenegotiate ctrl 3600 data 512000 required off timeout 300

</IfModule>

Nakonec už jen reloadneme proftpd:

/etc/init.d/proftpd reload

FTP klienti

Ftp klientů je celá řada, my si budeme jmenovat tři nejzákladnější.

FileZilla

Jeden z nejznámějších ftp klientů vůbec je FileZilla ftp klient. Pokud používáme explicitní způsob šifrovaného spojení, tak v tomto klientu musíme zadat adresu serveru jako :

ftpes://adresa

Pro implicitní způsob šifrování je

ftps://adresa

Krusader (kio-slaves)

Hojně využívanmým klientem je krusader alá KDE, alá kio-slaves. Aby nám fungovalo ftps v krusaderu (konqueroru apod.), je potřeba doinstalovat kio-ftps. Pro KDE3 je k dispozici verze 1a, viz : kio-ftps-0.1a.tar.gz. Kdo nemá součástí distribuce, kompiluje se trojčlenkou :

tar xvfz kio-ftps-0.1a.tar.gz
./configure
make
make install

Poté stačí do krusaderu zadat "ftps://adresa" a vualá, spojení navázáno.

Pro KDE4 je verze 0.2 : kio-ftps-0.2.tar.gz, která se kompiluje pomocí cmake, nepoužívám, nemohu odzkoušet.

GFTP

Pro GNOME je k dispozici gftp. Kdo dostane při pokusu o přihlášení na FTPS serveru tuto chybovou hlášku :

error 18:self signed certificate

Tak si vypněte ověřování certifikátu v nastavení, nabídka FTP -> Preference -> Engine SSL -> Ověřit protistranu SSL.
Další možností by mělo být umístění veřejného certifikátu vaší certifikační autority do adresáře certifikátů openssl. V debianu je v "/usr/lib/ssl/certs" V Arch linuxu jsou v "/usr/share/ca-certificates/" a míří na ně symlinky z "/etc/ssl/certs/"

Tipy a triky

Několik drobných tipů co a jak nastavit.

Práva k souborům, adresářům a .ftpaccess

Všechno šlape, uživatel funguje, ale vše v jeho adresáři jde smazat.
Resp. práva se chovají tak, že pokud má adresář práva třeba "root:root 755", tak soubor v onom adresáři s root:root 755 nejde smazat
Pokud má ovšem adresář třeba práva ftpuser:ftpgroup 755 a soubor root:root 700, tak soubor lze v klidu smazat a proftpd může klidně běžet i pod uživatelem "proftpd". Myslím si, že zato může mod_sql (Když se tváří, že běží pod uživatelem proftpd, tak by měl moci přistupovat jen k souborům a adresářům, ke kterým má onen uživatel práva)
Provedeme si příklad řešení práv třeba na testovací soubor (100MiB na rychlost) pro download. Vytvoříme si ho takto (adresář ftp má práva třeba ftpuser:ftpgroup 775):

dd if=/dev/zero of=/home/ftp/100MiB.iso bs=1024 count=102400
# práva souboru jsou trochu irelevantní, ale budiž :
chown proftpd:proftpd 100MiB.iso
chmod 755 100MiB.iso

Nyní nastavíme práva, aby šel jen číst a né mazat. Upravíme následovně proftpd.conf :

AllowOverride on
#DenyFilter                     \*.*/
PathDenyFilter "(\.ftpaccess)$"

Nesmíme zapomenout na reload serveru :

/etc/init.d/proftpd reload

Tímto jsme si povolili pomocí "AllowOverride" možnost použití konfiguračního souboru ".ftpaccess".
Pomocí "PathDenyFilter" jsme zakázali možnost přepsání onoho souboru uživatelem.

Konečně si vytvoříme soubor .ftpaccess v adresáři ftp uživatele (/home/ftp/.ftpaccess) a v případě, že chceme povolit pouhé čtení na náš testovací soubor, zapíšeme do něj :

PathDenyFilter "(\.ftpaccess|\100MiB.iso)$"

Do PathDenyFilter zapíšeme také zmíněný .ftpaccess. Definování PathDenyFilter v .ftpacces souboru má za následek nepoužití této direktivy v proftpd.conf.
.ftpaccess je načten při příchodu do adresáře, kde se nachází.Nyní mohou uživatelé tyto soubory jen číst. Pokud je klient již přihlášen, tak vytvořením onoho souboru nic nezmůžete, jelikož jej uživatel bude moci třeba smazat. Soubor se korektně načítá až při samotném přihlášení klienta. Resp. se mi zdá, že jen direktiva "PathDenyFilter" vyžaduje přihlášení klienta (BUG, nebo FEATURE ?). Ostatní lze měnit za chodu a klient hned změny pocítí.

Soubor .ftpaccess je určen na řešení drobých restrikcí. Nelze v něm používat direktivu "Directory", ač mi to částečně fungovalo. Pravidla se vždy aplikují na samotný adresář a podadresáře. Pokud v podadresáři vytvoříme.ftpaccess, tak budou platit pravidla zapsaná v něm atd. :

# zakaze upload (prepis) souboru 100MiB.iso, .ftpaccess a .htaccess :
PathDenyFilter "(\.ftpaccess|\.htaccess|\100MiB.iso)$"

# v aktualnim adresari budou vsichni moci cist, ale nikdo zapisovat (krome uzivatele "admin") :
<Limit Write>
  AllowUser admin
  DenyAll
  Order allow,deny
</Limit>

<Limit Read>
  AllowAll
</Limit>

# povolime pristup ze vsech ip adres krom jedne :
<Limit ALL>
  Deny 192.168.0.21
  Allow all
  Order deny,allow
</Limit>

# omezeni rychlosti pro tento adresar a podadresare :
TransferRate RETR 20:262144   # maximalni rychlost uploadu(od serveru ke klientovi) je 20KiB/s; do prenosu prvnich 256KiB dat je rychlost maximalni 

Práva trochu složitěji

Nyní se podíváme na trochu složitější definování práv, zakládáním tříd (classes) aj. Třídy lze definovat jen pomocí konfiguračních souborů proftpd. Aby nastavení vypadalo trochu přehledněji, vložíme si definice tříd stejně jako třeba nastavení sql, nebo tls do jiného souboru. Do proftpd.conf si doplníme :

Include /etc/proftpd/access.conf

Vytvoříme si soubor /etc/proftpd/access.conf a příklad nastavení by mohl vypadat nějak takto :

### seznam ip adres zlobivych uzivatelu :
<Class blacklist>
    From 192.168.0.5
    From 192.168.20.22
    From 192.168.30.0/24
    From 192.168.40.55
</Class>

### seznam VIP clenu :
<Class vip>
    From 192.168.5.1
    From 192.168.10.1
</Class>

### pokud se prihlasi uzivatel tonda, tak bude moci stahovat jen 20KiB/s
# (plati pouze pro adresar ~/pokus/*, vsude jinde to pojede naplno)
<IfUser tonda>
  <Directory ~/pokus/*>
       TransferRate RETR 20
  </Directory>
</IfUser>

### kdo neni clenem skupiny vip, tomu pojede stahovani z ftp max 40KiB/s
# a prvnich 256KiB dat se bude stahovat plnou rychlosti :
<IfGroup !vip>
       TransferRate RETR 40:262144
</IfGroup>

### kdo je clenem skupiny vip, tomu pojede stahovani 540KiB/s
<IfGroup vip>
       TransferRate RETR 540
</IfGroup>

### ti, jejichz IP, nebo rozsah adres, je definovan ve tride "blacklist"
# se nebudou moci prihlasit
<Limit LOGIN>
    DenyClass blacklist
    AllowAll
</Limit>

Dávejte si pozor na fyzická práva samotných adresářů.
Jak už bylo řečeno, všechny direktivy se nedají používat všude. Pokud vás zajímá nějaká direktiva, tak se na ní podívejte do dokumentace : List of Directives by Name

Nastavení modulů třetích stran

Nyní se podíváme na moduly třetích stran, jenž jsme si ručně zkompilovali spolu s proftpd.

Modul : mod_md5

Do souboru "/etc/proftpd/modules.conf" si doplníme následující řádek :

LoadModule mod_md5.c

# jako posledni by se mel vzdy nacitat tento modul :
LoadModule mod_ifsession.c

Do souboru "/etc/proftpd/access.conf" si doplníme následující řádky a vše by mělo fungovat :

### Jestlize se uploadne soubor do adresare "upload", tak se k nemu vytvori kontrolni md5 soucet
# podadresar test je vynechan (kdyz se tam soubor uploadne, tak se md5 soucet generovat nebude)
<IfModule mod_md5.c>
    MD5Engine on
    MD5Path ~/upload/
    MD5Path !~/upload/test
</IfModule>

### md5 soucet se bude generovat jen v pripade, ze uploadovat dany soubor bude uzivatel admin :
<Limit SITE_MD5>
    AllowUser admin
    DenyAll
</Limit>

Můžeme si funkčnost vytváření md5 hashů vyzkoušet takto :

#:/# ftp 127.0.0.1
Connected to 127.0.0.1.
220 ::ffff:127.0.0.1 FTP server ready
Name (127.0.0.1:root): admin
331 Password required for admin
Password:
230 User admin logged in
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd upload
250 CWD command successful
ftp> quote SITE MD5 frozenbubble.exe
quote site md5 frozenbubble.exe
200-2bbff112066c93871155d4cf1ada5d2d    frozenbubble.exe
200 Please contact webmaster@abclinuxu.cz if this digest is inaccurate
ftp>

Bohužel, po uploadnutí souboru na ftp server do příslušného adresáře nedojde k vytvoření dalšího souboru s md5 hashem :-/. Takže všechno funguje, ale vlastně nefunguje :).

Modul : mod_sftp a mod_sft_sql

Do "/etc/proftpd/modules.conf" doplníme :

LoadModule mod_sftp.c
LoadModule mod_sftp_sql.c

Do "/etc/proftpd/proftpd.conf" doplníme řádek :

Include /etc/proftpd/sftp.conf

A do souboru "/etc/proftpd/sftp.conf" vložíme :

### Nastaveni v pripade, ze bychom chteli mit ulozeny klice v databazi a treba overovat uzivatele ceertifikatama apod.
# Osobne nepotrebuji, takze jsem nezkousel.
# (museli bychom si zrejme pridat sloupecek do tabulky k uzivatelum, kde by byl klic ulozen):
#<IfModule mod_sql.c>
#    # Other mod_sql configuration here
#
#    # Define a SELECT statement to retrieve users' authorized SSH keys
#    SQLNamedQuery get-user-authorized-keys SELECT "key FROM sftpuserkeys WHERE name='%U'"
#
#    # Define a SELECT statement to retrieve hosts' authorized SSH keys
#    SQLNamedQuery get-host-authorized-keys SELECT "key FROM sftphostkeys WHERE host='%{0}'"
#</IfModule>

### Velmi jednoduche nastaveni sftp :
<IfModule mod_sftp.c>
    ### Zapneme podporu sftp :
    SFTPEngine on
    ### Soubor s logem :
    SFTPLog /var/log/proftpd/sftp.log

    ### Jelikoz se pouziva rozdilny zpusob prihlasovani, 
    # tak pro debug rezim pouzijeme nasledujici logovani :
    #TraceLog /var/log/proftpd/sftp-trace.log
    #Trace scp:20 sftp:20 ssh2:20


    ### Cesta ke klíčům pro autentizaci (pouzijeme stavajici klice ssh demona):
    SFTPHostKey /etc/ssh/ssh_host_dsa_key
    SFTPHostKey /etc/ssh/ssh_host_rsa_key

    ### Zapneme kompresi :
    SFTPCompression delayed

### Pokracujeme v prikladu s databazi (osobne nepotrebuji, takze jsem ani nezkousel) :
#  <IfModule mod_sftp_sql.c>
#      # Instead of using a file-based key store, we tell mod_sftp to use
#      # the SQL-based key store provided by mod_sftp_sql
#      SFTPAuthorizedUserKeys sql:/get-user-authorized-keys
#      SFTPAuthorizedHostKeys sql:/get-host-authorized-keys
#  </IfModule>

</IfModule>

Nyní už stačí jen restart a je hotovo :

/etc/init.d/proftpd restart

Přihlašujeme se na port 21, tzn., že třeba v krusaderu zadáme : sftp://192.168.0.55:21
Poté už je krásně vidět, jak se nám plní soubor se záznamy "/var/log/proftpd/sftp.log " :).
Nebuďte ovšem bláhoví. Kdo si myslí, že může provozovat ftp/ftps/sftp na jednom portu, tak se mílí. Pokud nastavíme sftp, budeme moci používat jen tento protokol.

Modul : mod_vroot

Do "/etc/proftpd/modules.conf" doplníme :

LoadModule mod_vroot.c

Do "/etc/proftpd/proftpd.conf" doplníme řádek :

Include /etc/proftpd/vroot.conf

A do souboru "/etc/proftpd/vroot.conf" vložíme :

<IfModule mod_vroot.c>
   VRootEngine on

   DefaultRoot ~

   ### Vsem uzivatelum namapujeme tento adresar 
   # (nefunguje soucasne s direktivou VRootServerRoot):
   VRootAlias upload /home/ftp/nejakaslozka/tamtaslozka

   ### Povolit symlinky :
   VRootOptions allowSymlinks

   ### Budeme logovat provoz :
   VRootLog /var/log/proftpd/vroot.log

</IfModule>

Bohužel, tento modul se mi nepodařil zprovoznit. Alias se vytvoří, ale do logu se nic nezapisuje a do žádného adresáře nemám přístup. Ani do těch, kam jsem dřív mohl. U proftpd hodně záleží na pořadí modulů při kompilování, třeba ho tedy jen neumím správně zkompilovat :).

Ladění

Pokud se nám něco nedaří a chceme ladit, tak spustíme Proftpd v debug režimu :

proftpd -d9 -n

V případě debianu stačí upravit soubor /etc/default/proftpd takto :

# Defaults for proftpd initscript

# Master system-wide proftpd switch. The initscript
# will not run if it is not set to yes.
RUN="yes"

# Default options.
# For more exhaustive logging, try "-d 3".
OPTIONS="-d 9 -n"

A restartovat server :

/etc/init.d/proftpd restart

Závěr

Nyní máme nainstalovaný a kompletně funkční proftpd server. Samotný server běží pod uživatelem a skupinou profptd. Uživatelské soubory spadají pod uživatele ftpuser a skupinu ftpgroup.
Proftpd není rozhodně dokonalý ftp server, ale není ani nikterak špatný. Konfigurace mi přijde přehledná a práce s direktivami intuitivní. Jeho možnosti a rozšíření jsou velké, ač bohužel někdy né zcela funkční (Ve virtualboxu jsem měl i problémy s fitry na IP adresy, jenž proftpd umožňuje.). Také by mně zajímalo, zda má někdo zkušenosti s nějakýma externíma modulama. V případě, že ano, může se o zkušenosti s nimi podělit pod článkem. To samozřejmě platí i o tipech na další různé možnosti nastavení.

Zdroje

http://proftpd.org
http://www.castaglia.org
http://www.howtoforge.com/proftpd_mysql_virtual_hosting
http://www.debianhelp.co.uk/proftpweb.htm