vsftpd 搭建文件服务器总结
廖云 2016-12-24
一、引言
最近在做一个项目,牵涉到多个后台(桌面端后台 和 app端后台),里面有文件上传、下载的功能,这就不能避免的有文件保存的问题了,以前都是保存在根目录的某个文件夹下,这样就导致文件管理极不方便,例如:1、每换一个平台部署服务,就要拷贝一次文件;2、如果服务以集群的方式部署在不同的机器上,文件很难进行共享。经过精心考虑后,决定把所有文件进行集中管理,减少后续文件管理的麻烦。
最开始,准备自己再写一个单独的项目,来管理文件,网上查了一下,原来先辈们早就意识到了这个问题,并把这个问题解决了,还无私的为我们提供了免费的工具,向他们致敬(做为一个程序狗,这句话可真是发自脏腑的,因为又可以少写很多代码...),最终决定使用vsftp来搭建这个文件服务器,本人服务器的操作系统是 CentOS6.5。
二、vsftp的安装
直接使用yum源安装就可以了
yum -y install vsftpd
三、vsftp配置
vsftp 安装成功以后,我们就可以根据自己项目的要求进行配置了,配置文件的位置为/etc/vsftpd/vsftpd.conf。
对于 vsftp 服务器,用户类型可分为三类:
1、匿名用户:vsftp中的匿名用户有两个,anonymous和ftp,它们的特点是 用户在客户端 只需要输入用户名,不需要输入密码就可以直接登陆。主要用于一些公共资源的分享,例如很多开源项目就以这种方式,供大家下载源代码。
2、本地用户 或者 真实用户:这种用户可以直接登陆服务器,登陆到Linux主机上。
3、虚拟用户:不能登陆到服务器主机上,只能以映射的方式映射到某个本地用户,这样相对于另外两种类型的用户安全性更高,所以,如果想证用户对FTP服务器站内具有写权限,但又不许访问系统其它资源,可以使用虚拟用户来提高系统的安全性。
闲话少说,针对该项目,决定使用 虚拟用户的 方式来访问 我的 FTP 服务器,打开 vsftp的配置文件 vim /etc/vsftpd/vsftpd.conf,具体配置和说明如下:
listen=YES
#绑定本机IP
listen_address=192.168.0.14
#禁止匿名用户登陆,为了系统安全,一定要禁止匿名用户登陆,它们是不需要
#密码就可以登陆的
anonymous_enable=NO
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
#允许本地用户访问,默认为YES
local_enable=YES
#设定虚拟用户的宿主目录,centos中已经有内置的ftp用户了
guest_username=ftp
#允许写入
write_enable=YES
#不允许FTP用户离开自己的主目录
chroot_list_enable=NO
#权限验证需要的加密文件,对应 /etc/pam.d/vsftpd文件
pam_service_name=vsftpd
#上传后的文件默认的权限掩码
local_umask=022
#启用虚拟用户功能
guest_enable=YES
#设置虚拟用户个人vsftp的 centos FTP 服务文件存放路径。存放虚拟用户个性#的 centos FTP 服务文件(注:配置文件名=虚拟用户名)
user_config_dir=/etc/vsftpd/vuser_conf
#最大连接数300
max_clients=300
#会话超时时间,默认为600秒,即 客户端连接到ftp但未操作,600秒后,会话会断开
idle_session_timeout=600
#数据传输超时时间,默认为120秒,即 文件输入过程超过120秒,还没有传输完成的话,中断传输
data_connection_timeout=120
#日志相关
xferlog_enable=YES
xferlog_std_format=YES
xferlog_file=/var/log/vsftpd.log
然后,要对虚拟用户进行认证:
首先,安装 Berkeley DB工具,(因为我们要用到一个叫做 db_load的命令)
yum install db4 db4-utils
接下来,创建一个文件 vuser.text ,用这个文件来保存虚拟用户的用户名和密码(注意:奇数行为用户名,偶数行为密码),如:
test
1234567
接下来,生成虚拟用户认证的 db 文件,命令如下:
db_load -T -t hash -f /etc/vsftpd/ vusers.text /etc/vsftpd/vusers.db
这样就会在 /etc/vsftpd/ 目录下生成一个 vusers.db文件,如果好奇的话,可以打开这个文件看一下,里面是一串加密后的乱码。
接下来,编辑我们的认证文件 /etc/pam.d/vsftpd文件,将这个文件里面的全部内容者注释掉,在最下面添加两行文字,如下:
auth required pam_userdb.sodb=/etc/vsftpd/vusers
account required pam_userdb.sodb=/etc/vsftpd/vusers
接下来,为虚拟用户配置文件,设置 访问的目录权限、读写权限......,如下:
mkdir /etc/vsftpd/vuser_conf/
vi /etc/vsftpd/vuser_conf/test //注:文件名与vusers.text里面的要一致
打开这个 test 文件,在里面添加内容,根据项目的不同,可能会配置的不一样
local_root=/var/sun/file //设置该用户的根目录
write_enable=YES
anon_umask=022
anon_world_readable_only=NO
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
接下来,设置根目录权限
mkdir -p /var/sun/file
chmod -R 755 /var/sun //注:主目录下不能有写的权限,vsftpd要求的。
chmod -R 777 /var/sun/file
接下来,设置 Selinux,或者直接关闭掉也可以
setsebool -P tcp_home_dir=1
setsebool -P allow_ftpd_full_access=1
接下来,设置防火墙,打开 21 22 端口,刷新防火墙,就可以使用vsftp服务器了。当然 当前配置下 只能以 主动模式使用vsftp文件服务器。
如果, 要以被动模式 (即:PASV模式,本人不推荐这种方式,应为用这种方式会在vsftp服务器开大量的端口,在高并发的情况下,如果处理不当,有耗尽服务器端口的可能,而且对于服务器来说,开启大量端口,是一种不安全的行为)使用vsftp服务器,需进行如下配置,打开 /etc/vsftpd/vsftpd.conf文件,在末尾添加以下内容
pasv_enable=YES
pasv_mini_port=40000
pasv_max_port=40080
pasv_promiscuous=YES
以上内容添加完以后,还需要开启以上设置的端口
-A INPUT -m state --state NEW -m tcp -p -dport 40000:40080 -j ACCEPT
然后,刷新防火墙,就可以使用 PASV 模式连接 FTP 服务器了。
四、用java 代码向 FTP 服务器上传文件
public staticvoid main(String[] args) {
FTPClientftp = null;
try {
ftp = newFTPClient();
intreply;
ftp.connect("192.168.0.14",21); // 连接FTP服务器
booleanbo= ftp.login("test","123456"); //登录
System.out.println("====>" +bo);
reply = ftp.getReplyCode(); //检验是否连接成功
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
System.out.println("连接失败");
}
ftp.setControlEncoding("UTF-8");
ftp.setSoTimeout(4000);
// 转移工作目录至指定目录下,该目录为用户主目录下的子目录,例如该上传、、//目录的完整目录为 /var/sun/file/operator/upload/images
ftp.changeWorkingDirectory("/operator/upload/images"); ftp.setFileType(FTP.BINARY_FILE_TYPE); // 设置为二进制
Filefile =newFile("D:/pic/123.jpg");
if (!file.isDirectory()){ //若不是文件夹
FileInputStreaminput =newFileInputStream(file);
// 上传,ftp必须是iso-8859-1编码
booleanflag= ftp.storeFile(newString("kkfsfdsf.jpg".getBytes("iso-8859-1"),"iso-8859-1"),input);
System.out.println("====>store " +flag);
// System.out.println(flag);
// file.delete();
input.close();
}
if (ftp.isConnected()){
ftp.disconnect();
}
}catch (Exceptione) {
e.printStackTrace();
}finally {
if (ftp !=null && ftp.isConnected()){
try {
ftp.disconnect();
}catch (IOExceptione) {
e.printStackTrace();
}
}
}
}
以上所完成的工作,只能说是 仅仅能将 文件 上传到服务器上面去了,但是在实际的项目开发中,肯定是还不能达到要求的,,比如端口占用的问题,这是vsftp的实现机制导致的问题,如果处理不当,可能会消耗掉服务器会部的端口,导致服务器不能被访问。针对这个问题,最好的解决方式是,利用 FTP 连接池来解决。不仅可以解决端被大量占用的问题,还可以大大加快执行效率,特别是在高并发的情况下。
解决方式请见下一期总结
(个人水平有限,以上可能有理解错误的地方,请各位大神批评指正,)