80服务器因为重新装过系统, 在装ftp服务器的时候由于考虑到FTP服务器需要强大的配置功能, 所以就选择了proftp 而非 vsftp.
资源参考:
官网文档:
http://blog.guomin.net/2006/08/09/158/proftp 官网:
proftp 主要特色: 一个单一的和 Apache 的 httpd.conf 类似的配置文件
每个目录下的 .ftpaccess 文件(和 Apache 的. htaccess 类似)
很容易配置的,多个虚拟 FTP 服务器以及匿名 FTP 服务
可以单独运行也可以从 inetd/xinetd 启动
匿名 FTP 的根目录不需要特别的目录结构
系统的二进制文件和其他系统文件没有 SITE EXEC 命令
在单独运行方式下,以非特权用户运行,降低攻击风险
日志以及 utmp/wtmp 支持
Shadow 口令支持
安装:由于考虑到需要 mysql 对虚拟用户的支持, 而 proftp 源码安装才支持此功能, 所以先卸载 已RPM安装的 proftp, vsftp, mysql, 用源码安装 mysql, proftp;
01> 安装 mysql
安装 mysql-5.0.37-linux-i686-glibc23.tar.gz,
虽然是二进制安装的,拷贝到你要安装的目录下, 我这里是 /usr/local/mysql 目录下的
由于未知原因, 发现 /etc/rc.d/init.d 下面有个 mysql的启动脚本,因此只要对它的前两行改吧改吧
就很容易的用 chkconfig 添加到 service 命令的列表里,毕竟用service比较方便
启动脚本内容后面给出;
02> 安装 proftp
安装 proftpd-1.3.1rc2.tar.gz
# ./configure --prefix=/etc/proftpd --with-modules=mod_sql:mod_sql_mysql:mod_quotatab:mod_quotatab_sql --with-includes=/usr/local/mysql/include --with-libraries=/usr/local/mysql/lib
# /etc/proftpd/sbin/proftpd
测试
设计:
安装好后是对整个FTP服务目录结构及权限的设计, 我的设计如下:
目录/权限\组 admin tch stdun ustd gstd soser
chroot Y N Y Y Y Y
~ rw YY YY YY YY YY YN
/ rw YY YN NN NN NN YN
/pn rw YY YN -- -- -- NN
/temp rw YY YN -- -- -- YY
/cb rw YY YN -- -- -- YN
/un rw YY YN YY -- -- YN
其中 ~ 代表每个用户的主目录, 根目录为 用户 hit 的主目录 /home/hit, /pn 代表 /home/hit/personal
/cb 代表 /home/hit/club, /un 代表 "/home/hit/Student Union", -- 表示未设定, 因为根本访问不到
这里的所有的用户都是虚拟用户, 并且要对 tch, ustd, gstd 组的用户进行配额限制, 防止不良使用FTP服务.
创建本地群组://以下的用户是为了让proftp以用户nobody而非root来运行的, 若已经建立了此用户, 跳过
#groupadd -g 99 nobody
#useradd -g nobody nobody
//以下是为了对虚拟用户管理而创建的群组
#groupadd -g 1000 admin
#groupadd -g 1001 soser
#groupadd -g 1002 tch
#groupadd -g 1003 ustd
#groupadd -g 1004 gstd
#groupadd -g 1005 stdun
SQL脚本:
-- >>>>>>>>>>
proftpd.sql >>>>>>>>>>>>
/*
ftpgroup:
sos 相当于一个有公共密码的匿名用户组, 可以下载, 不能看 personal 目录下学生目录里的内容
但是可以向 temp , recommend 目录中写入
gstd 研究生组, 主目录本人目录, 执行 chroot
ustd 本科生组, 主目录本人目录, 执行 chroot
tch 教室组, 主目录本人目录, 但不执行 chroot, 只能在自己的主目录里可写
admin FTP管理员组, 拥有所有权限
*/
CREATE DATABASE IF NOT EXISTS proftpd;
USE proftpd;
DROP TABLE IF EXISTS `ftpgroup`;
CREATE TABLE `ftpgroup` (
`groupname` VARCHAR(64) NOT NULL,
`gid` SMALLINT NOT NULL,
`members` VARCHAR(64),
PRIMARY KEY (`groupname`, `gid`)
--`gid` SMALLINT NOT NULL AUTO_INCREMENT key,
--组的成员, 用逗号隔开
);-- TYPE=MyISAM COMMENT='ProFTP group table';
--ALTER TABLE `ftpgroup` AUTO_INCREMENT=100;
INSERT INTO `ftpgroup`(`groupname`, `gid`, `members`) VALUES ('nobody', 99, 'nobody'); /* 100 */
INSERT INTO `ftpgroup`(`groupname`, `gid`, `members`) VALUES ('admin', 1000, ''); /* 100 */
INSERT INTO `ftpgroup`(`groupname`, `gid`, `members`) VALUES ('soser', 1001, ''); /* 101 */
INSERT INTO `ftpgroup`(`groupname`, `gid`, `members`) VALUES ('tch', 1002, ''); /* 102 */
INSERT INTO `ftpgroup`(`groupname`, `gid`, `members`) VALUES ('ustd', 1003, ''); /* 103 */
INSERT INTO `ftpgroup`(`groupname`, `gid`, `members`) VALUES ('gstd', 1004, ''); /* 104 */
INSERT INTO `ftpgroup`(`groupname`, `gid`, `members`) VALUES ('stdun', 1005, ''); /* 105 */
--注意: 可以使用符号 来引用表名, 列名
DROP TABLE IF EXISTS `ftpuser`;
CREATE TABLE `ftpuser` (
`userid` VARCHAR(64) NOT NULL,
`passwd` VARCHAR(64) NOT NULL,
--用户id
`uid` INT NOT NULL AUTO_INCREMENT KEY,
`gid` INT NOT NULL,
--用户主目录
`homedir` VARCHAR(255),
--用户的系统Shell
`shell` VARCHAR(64) DEFAULT '/sbin/nologin',
`count` INT 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'
);
ALTER TABLE `ftpuser` AUTO_INCREMENT=1000;
INSERT INTO `ftpuser` (`userid`, `passwd`, `gid`, `homedir`)
VALUES ('adm', password('adm'), '1000', '/home/hit/');
INSERT INTO `ftpuser` (`userid`, `passwd`, `gid`, `homedir`)
VALUES ('sos', password('sos'), '1001', '/home/hit/');
-- 用户 hit 虽然和系统本地用户同名, 但是可以更改验证顺序通过,
-- 是为了老用户的习惯而设定
INSERT into `ftpuser`(`userid`, `passwd`, `gid`, `homedir`)
VALUES('hit',password('software'),'1001','/home/hit/');
INSERT INTO `ftpuser` (`userid`, `passwd`, `gid`, `homedir`)
VALUES ('dudu', password('dudu'), '1002', '/home/hit/personal/teacher/dudu');
INSERT INTO `ftpuser` (`userid`, `passwd`, `gid`, `homedir`)
VALUES ('041110108', password('041110108'), '1003', '/home/hit/personal/undergraduate student/041110108');
INSERT INTO `ftpuser` (`userid`, `passwd`, `gid`, `homedir`)
VALUES ('041110109', password('041110109'), '1004', '/home/hit/personal/graduate student/041110109');
INSERT INTO `ftpuser` (`userid`, `passwd`, `gid`, `homedir`)
VALUES ('yu', password('yu'), '1005', '/home/hit/Student Union');
--建立磁盘限额数据表
DROP TABLE IF EXISTS `quotalimits`;
CREATE TABLE `quotalimits` (
--由程序自动记录
`name` VARCHAR(64) NOT 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',
--上传最大字节数, 就是FTP用户空间容量
`bytes_in_avail` FLOAT NOT NULL DEFAULT '0',
--下载最大字节数
`bytes_out_avail` FLOAT NOT NULL DEFAULT '0',
--总共可传输的文件的最大字节数(速率)(上传和下载流量)
`bytes_xfer_avail` FLOAT NOT NULL DEFAULT '0',
--总共能上传的文件数
`files_in_avail` INT UNSIGNED NOT NULL DEFAULT '0',
--总共能从服务器下载文件的数目
`files_out_avail` INT UNSIGNED NOT NULL DEFAULT '0',
--总共可传输文件的数目(上传和下载)
`files_xfer_avail` INT UNSIGNED NOT NULL DEFAULT '0'
);
INSERT INTO quotalimits (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 ('041110108', 'user', 'false', 'soft', '1048576', '0','0','0','0','0');
INSERT INTO quotalimits (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 ('041110109', 'user', 'false', 'soft', '104857600', '0','0','0','0','0');
INSERT INTO quotalimits (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 ('dudu', 'user', 'false', 'soft', '314572800', '0','0','0','0','0');
DROP TABLE IF EXISTS `quotatallies`;
CREATE TABLE `quotatallies` (
`name` VARCHAR(64) NOT NULL,
`quota_type` ENUM('user','group','class','all') NOT NULL DEFAULT 'user',
`bytes_in_used` FLOAT NOT NULL DEFAULT '0',
`bytes_out_used` FLOAT NOT NULL DEFAULT '0',
`bytes_xfer_used` FLOAT NOT NULL DEFAULT '0',
`files_in_used` INT UNSIGNED NOT NULL DEFAULT '0',
`files_out_used` INT UNSIGNED NOT NULL DEFAULT '0',
`files_xfer_used` INT UNSIGNED NOT NULL DEFAULT '0');
GRANT ALL ON proftpd.* TO [email=proftpd@localhost]proftpd@localhost[/email] identified by 'proftpd';
配置:
让我们来使用配置文件
/etc/proftpd/etc/proftpd.conf 来介绍 proftp 的配置文件语法:
对于 "/home/hit/Student Union", /home/hit/club 目录的配置省略.
#########################
/etc/proftpd/etc/proftpd.conf ###################################
ServerName "FTP of SoS" #FTP服务显示给客户端的服务名称
ServerType standalone #独立运行的方式, 而不是 inetd 子进程的方式运行
DefaultServer on
Port 21 #FTP 端口, 标准端口 - 21
Umask 000 #FTP读写文件所用的 umask 值,
MaxInstances 60 #同时可有多少线程,
User nobody #FTP将以哪个用户来运行
Group nobody #FTP将以那个组来运行
#禁止所有用户执行 chmod 命令
DenyAll
#________________虚拟用户组列表 ________________________
# 以下都是组名, 存在于本地系统, 需要先用 groupadd 命令创建
AllowGroup admin #允许管理员组的所有用户登陆, 以下类似
AllowGroup soser
AllowGroup tch
AllowGroup gstd
AllowGroup ustd
AllowGroup stdun
AllowGroup web80
DenyAll #其他组的用户禁止登陆
# 注释掉所有的
标签可以禁止 匿名用户登陆
#_________________匿名用户设置_________________________
# #匿名用户名为 dd 的配置, 登陆目录为 ~ (主目录) 默认为 /var/ftp/pub
#
# #匿名用户名为 ftp 的主目录为 /home/hit
# User ftp #匿名用户名, 不存在于本地系统, 可以有多个
# Group ftp #该匿名用户所属的组, 组由 groupadd 添加
# AnonRequirePassword on #是否需要输入密码
# #对 命令 login 的限制, 为 允许所有
# AllowAll
#
# 匿名用户别名, 以下设置可以使 客户端使用 "ftp" 而不是 "anonymous" 来登陆
# UserAlias anonymous ftp
# 同时可以有多少匿名用户同时登陆
# MaxClients 10 "Sorry, max %m users -- try again later!"
# DisplayLogin welcome.msg # 设置欢迎信息
# DisplayChdir .message
# #禁止匿名用户写权限
# DenyAll
#
#
#___________________基本设置_________________________
TimeoutStalled 300 #下载延时大于 300 时断开连接
DisplayLogin welcome.msg #登陆欢迎信息
DisplayChdir .message #更换目录欢迎信息
DirFakeUser on sos #客户端 ls -l 时所看到的文件属主
DirFakeGroup on sos #客户端 ls -l 时所看到的文件属组
DirFakeMode 0000 #客户端 ls -l 时所看到的文件权限
# PAM(plugable authentication module ,可插拔认证模块), on 启用
# 因为需要用到 基于数据库的 虚拟用户, 所以要用到.
AuthPAM on
#@@@@@@@@@@@@@@ 目录访问权限控制 @@@@@@@@@@@@@@@@@@@@@
#如果虚拟用户存在而它的登陆目录不存在, 则该用户登陆时自动以给定的权限创
#建主目录 和 主目录不存在的父级目录
CreateHome on 777 dirmode 777
# 是否允许覆盖已有文件
AllowOverwrite on
#对每个用户的主目录 ~ 的权限设定
#对命令 write 的限制设定
AllowAll
# HideFiles 必须写在 Directory 标签里
# 对目录 /home/hit 的总体设置, 该目录是所有FTP用户的根目录
# 隐藏以 . 开头的(即隐藏)文件和用户 hit 的桌面目录 Destop
HideFiles ^(\..*|Desktop)$
# 隐藏不能够访问的文件
HideNoAccess on
#禁止 soser 和 tch 组的用户在该目录的写权限
DenyGroup soser
DenyGroup tch
# 设置临时文件目录的权限设置
#只有 组 admin 和 soser 的用户可以有写权限
DenyAll
AllowGroup admin
AllowGroup soser
# 防止通过匿名用户拷贝其他同学的作业
DenyGroup soser
DenyGroup soser
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# 只有 tch 组的用户登陆后不执行不执行 chroot 命令, 而其他组都限制在自己的主目录中
DefaultRoot ~ !tch
# 但是 tch 组的用户也必须设置一个新的根目录, 而不是操作系统的根目录 / .
DefaultRoot /home/hit tch
IdentLookups on
UseReverseDNS on
# emerg, alert, crit (empfohlen), error, warn. notice, info, debug
SyslogLevel emerg #日志记录级别
#日志记录文件
SystemLog /var/log/proftpd/emerg.log
#日志各种命令的记录格式
TransferLog /var/log/vsftpd/xfer.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"
# Log file/dir access
ExtendedLog /var/log/proftpd/access.log WRITE,READ write
# Record all logins
ExtendedLog /var/log/proftpd/auth.log AUTH auth
# Paranoia logging level....
ExtendedLog /var/log/proftpd/paranoid.log ALL default
################ MySql Info ####################################################
## groups 和 users 不能同时认证
SQLAuthTypes Backend Plaintext #先用 mysql 的password()来验证密码, 再用普通文本验证密码
SQLAuthenticate users usersetfast
# mysql 数据库的连接字符串, 第一个 proftpd 是表名, 第二个是用户名, 第三个是密码
SQLConnectInfo [email=proftpd@localhost]proftpd@localhost[/email] proftpd proftpd
# 数据库中记录用户信息的表名及相关信息的字段名
# ftpuser 是表名, 其后依次是必须的相关字段名,
# 格式为: SQLUserInfo [ user-table user-name passwd uid gid home-dir shell]
SQLUserInfo ftpuser userid passwd uid gid homedir shell
#貌似以 user 或 group 进行登陆验证中的一种均可, 所以以下的被注释掉了, ??? 望纠正
#SQLGroupInfo ftpgroup groupname gid members
#SQLDefaultGID 65534 #
#SQLDefaultGID 63333
#SQLDefaultUID 63333
#SQLMinUserGID 100
#SQLMinUserUID 500
#SQL日志文件, 指明文件就记录, 不指明就不记录, 可以帮助调错, 比如proftpd.conf 中的
#sql 语句有误等都可以通过该日志得知, 但是是建议关闭
#SQLLogFile /var/log/proftpd/sqlLog.log
#对用户登陆验证命令 PASS 执行的 SQL语句, 可以将日志记录到数据库中
# 对 命令PASS 执行名称为 "counter" 的SQL query, 它在随后有定义
SQLLog PASS counter
#名称为 "counter" 的SQL Qurey 的定义类型为 UPDATE, 语句为其后的字符串, 表名为 ftpuser
# 相关的转义字符 %u 等可以在 官网差 LogFormat , SQLNamedQuery 中找到
SQLNamedQuery counter UPDATE "count=count+1,accessed=now() \
WHERE userid='%u'" ftpuser
# xfer log in mysql
SQLLog STOR,DELE transfer1
SQLNamedQuery transfer1 UPDATE "modified=now() where \
userid='%u'" ftpuser
################ Quota Info ####################################################
#
#
QuotaDirectoryTally on
QuotaDisplayUnits "Kb"
QuotaEngine on
QuotaLock /etc/proftpd/quota.lock
QuotaLog "/var/log/proftpd/quota.log"
#允许显示磁盘限额信息,ftp登录后可执行"quote", "site quota"命令查看当前磁盘使用情况
QuotaShowQuotas on
#指定磁盘限额模块使用的数据库信息
#定义几个相关的 SQL Query
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 quotalimits 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 quotatallies 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}'" quotatallies
SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, \
%{4}, %{5}, %{6}, %{7}" quotatallies
# 为以下两个标签分配相关的 SQL Query 命令
QuotaLimitTable sql:/get-quota-limit
QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally
#
#
################################################################################
让 proftpd 支持 FXP:
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 60000:65534 -j ACCEPT