PostgreSQL和Proftpd
所以你想要设置一个ftp服务器,你需要高级功能,你不知道在哪里转? 尝试proftpd。
第1部分:使用postgresql后端设置proftpd
本教程非常适用,我将仅覆盖proftpd,并且只能使其与Postgres一起运行。 假设对proftpd和Postgres的基本了解。 本教程将让您快速运行proftpd,并使其使用数据库,如果该数据库具有触发器,则此配置的可能性几乎是无止境的。
获得Proftpd
首先你需要proftpd,我将使用Ubuntu的Dapper; 有一个由Francesco Paolo Lovergine提供的名为“proftpd-pgsql”的元包,它将设置一个使用以下模块编译的proftpd的副本。 作为旁注,当proftpd附带mod时,conf文件是标准的proftpd样板。 我强烈建议您查看mod_sql文档,而sub-par仍然很方便 - proftpd站点上的文档很旧,使用这些文件 : 链接到文档 。 此外,厌倦的版本,proftpd现在是1.3,虽然我将使用1.2.10 - Dapper中使用的版本
编译到这个版本的proftpd的mods如下
mod_core.c继续执行命令以获取proftpd-pgsql:
mod_xfer.c
mod_auth_unix.c
mod_auth_file.c
mod_auth.c
mod_ls.c
mod_log.c
mod_site.c
mod_auth_pam.c
mod_quotatab.c
mod_sql.c
mod_sql_postgres.c
mod_quotatab_sql.c
mod_ratio.c
mod_tls.c
mod_rewrite.c
mod_radius.c
mod_wrap.c
mod_quotatab_file.c
mod_delay.c
mod_readme.c
mod_ifsession.c
mod_cap.c
apt-get install proftpd-pgsql
设置权限
为了我的目的,(记住,我是宇宙的中心),我需要的是一维结构,因为组存储在不同的级别而不是unix权限。 所以所有文件都应该有静态权限 - 我只关心所有者和所有者的组。 我的计划是使proftpd默认用户ftp属于自己正确命名的组,我将要创建 - 'ftp'。 然后我打算让Postgres成为这个团体的成员,参见第2部分的推理。 我需要两个成为同一个组的成员,我需要proftpd chroot文件夹为775,所以整个组可以添加(移动)文件,我还使用用户'ftp'拥有的文件夹,组'ftp '。 我用以下脚本完成了这个。
groupadd ftp usermod -G ftp ftp usermod -G ftp,postgres postgres chown ftp:ftp ./ftp_directory/ chmod 775 ./ftp_directory/
设置Postgres
现在,我们将准备好我们的sql表。 我设计利用模式,这是“ftp”的前缀。 在桌子上是为了。 我把所有的表格都放在一个ftp模式中,有一件事情值得一下,我对这个项目的权限是非常有限制的,因为我不知道mod_sql是多么的安全。 在这样做的时候,我创建了一个名为proftp的特殊用户,用于我的数据库中的proftpd(比proftpd使用更多的应用程序),该用户被限制在auth_table上进行选择,并插入到file_log表中。 我*高度*建议你采取这种政策的某种形式。 至少这样可以防止某些程度的破坏性的sql注入攻击或信息泄漏,在mod_sql代码不像我们想要的那样安全的情况下。 一个快速的google显示了mod_sql代码库以前的安全问题。 mod_sql发送到db的每个查询都附加了一个“LIMIT 1”子句,并且mod_delay也默认配置,我发现这个项目足够了。
我的sql init脚本如下。
ALTER USER proftp UNENCRYPTED PASSWORD 'dealermadeftp'; CREATE SCHEMA ftp; GRANT USAGE ON SCHEMA ftp TO proftp; CREATE TABLE ftp.users ( pkid serial PRIMARY KEY, userid text NOT NULL UNIQUE, passwd text, uid int, gid int, homedir text, shell text ); GRANT SELECT ON ftp.users TO proftp; INSERT INTO ftp.users ( userid, passwd ) VALUES ( 'ecarroll', 'adm1n' ); INSERT INTO ftp.users ( userid, passwd ) VALUES ( 'jgallagher', 'adm1n' ); CREATE TABLE ftp.file_log ( pkid serial PRIMARY KEY, userid text REFERENCES ftp.users(userid), abs_path text, file text, dns text, time_transaction text, ts_in timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP ); GRANT INSERT ON ftp.file_log TO proftp; GRANT UPDATE ON TABLE ftp.file_log_pkid_seq TO proftp;
连接到您的数据库,并运行:
\i script_name
或者,您可以使用send'--file script_name'作为命令行争用的psql
那些在较小的数据库(使用本教程与mysql),你可能想用varchar替换文本; 但是,由于Postgres的设计没有优势。
设置proftpd
这部分是棘手的,如果你使用1.3 - 再次这个教程是1.2.10,稍微变化。
我已将这部分添加到我的默认proftpd模板文件conf,位于/etc/proftpd.conf:
AuthOrder mod_sql.c SQLAuthTypes Plaintext Empty SQLAuthenticate users SQLConnectInfo proftpd@localhost proftp dealermadeftp SQLDefaultUID 110 # CHANGE FOR YOUR FTP USERS UID FOUND IN /etc/passwd SQLDefaultGID 1001 # CHANGE FOR YOUR FTP USERS GID, FOUND IN /etc/groups SQLDefaultHomedir /home/ftp RequireValidShell off SQLUserInfo ftp.users userid passwd uid gid homedir shell SQLNegativeCache off SQLLogFile /var/log/proftpd-sql SQLLog STOR newfile SQLNamedQuery newfile FREEFORM "INSERT INTO ftp.file_log(userid,abs_path,file,dns,time_transaction) VALUES ('%U','%f','%J','%V','%T')" # %U => userid # %D => --Nothing, # %f => abs_path # %J => file # %h => dns_remote, %V => dns_local # %a => remote_ip, %L => local_ip # %t => localtime # %T => transfer_time
*模板变量被注释,仅供您自己参考。 conf的简短说明如下:
- 这里我们将AuthOrder设置为mod_sql.c,反过来启用mod_sql
- 我选择使用Plaintext密码,或者如果我没有分配一个密码,则允许使用空密码。 (我稍后会对数据库中的密码实施SHA1的触发器)
- 然后我将SQLAuthenticate设置为用户,我选择不为此项目使用组,如果您需要组,可以在这些表上找到更多的信息: 本网站上的文档
- SQLConnectInfo是“数据库@主机用户密码”格式的dsn,
- SQLDefaultUID,SQLDefaultGID,SQLDefaultHomedir,配置默认值,将我的大部分列留为NULL,我很少会覆盖此。
- RequireValidShell也被设置为关闭,如果将其设置为on,并且提供无效的shell,那么将会验证失败。
- SQLUserInfo对应于Postgres表,它是一个文字映射,再次是“ftp”。 指定认证表的架构
- SQLNegativeCache,缓存认证失败,
- SQLLogFile用于在配置服务器时进行详细日志记录。 当我去生产时,我将禁用
- SQLLog指定你想要记录的ftp操作,因为我的用户只能上传,我只记录STOR,格式为'ftpaction query_to_execute'
- SQLNamedQuery检查这个文档中的语法,以便更好的解释我使用的格式是'qryname FREEFORM custom_query_here',我这样做主要是因为我希望捕获很多proftpd的模板变量,还有其他更简单的语法
而已。 如果所有人都去计划,你应该开始工作。 现在当有人上传文件时,应该是这样的结果:
proftpd=# select * from ftp.file_log; pkid | userid | abs_path | file | dns | time_transaction | ts_in ------+----------+------------------------+---------------+-------+------------------+------------------------------- 1 | ecarroll | /home/ftp/foo/testfile | /foo/testfile | AMD64 | 0.000 | 2006-06-11 20:49:12.623375-05 (1 row)
第二部分:超越“工作”
...但是*工作是不够的吧? 让我们继续回答在配置faq for proftpd中发布的以下问题:
上载后可以将文件从上传目录中旋转出来吗?
答案是肯定可以的。 我将通过一个存储过程来实现这一点,即文件被移动到正确的方式 - 即时 - 没有一个守护进程。
您将首先需要在系统上安装* un * trusted plperlu,这可以实现
apt-get install postgresql-plperl-8.1
那么你需要在数据库中安装plperlu
createlang plperlu your_database_here
接下来,我们需要创建一个快速的perl脚本触发器,这将触发每个插入到我们的ftp_log表中
CREATE OR REPLACE FUNCTION ftp_file() RETURNS TRIGGER AS $$ use warnings; use Cwd; use File::Basename; use File::Spec; use File::Copy; move ( $_TD->{new}{abs_path}, File::Spec->catfile( '/home/ftp/', basename($_TD->{new}{file}) ) ); return; $$ LANGUAGE 'plperlu' VOLATILE; CREATE TRIGGER ftp_file BEFORE INSERT ON ftp.file_log FOR EACH ROW EXECUTE PROCEDURE ftp_file() ;
这个sql脚本的安装方式与先前的安装方式相同(用于创建表的方法)