一、前言
vsftpd是一款在Linux发行版中最受推崇的FTP服务器程序。特点是小巧轻快,安全易用。如果你想在你的Linux/Unix服务器上搭建一个安全、高性能、稳定性好的FTP服务器,那么vsftpd可能是你的首选应用。vsftpd意思为“very secure FTP daemon(非常安全的FTP进程)”,是一个基于GPL发布的类UNIX类操作系统上运行的服务器的名字(是一种守护进程),可以运行在诸如Linux、BSD、Solaris、HP-UX以及Irix等系统上面。vsftpd支持很多其他传统的FTP服务器不支持的良好特性。
二、安装vsftpd
yum -y install vsftpd #有网
#没网先下载rpm安装包再安装
rpm -ivh vsftpd安装包名 #没网
#设置开机启动
systemctl enable vsftpd.service
#启动
systemctl start vsftpd.service
#停止
systemctl stop vsftpd.service
#重启
systemctl restart vsftpd.service
#查看状态
systemctl status vsftpd.service
注:
1.我这里安装用的Linux版本为CentOS Linux release 7.7.1908 (Core)
2.以上都是Centos7的命令,7之前的命令为service vsftpd start
三、配置
#打开配置文件
vim /etc/vsftpd/vsftpd.conf
#修改配置 12 行
anonymous_enable=NO
#修改配置 33 行
anon_mkdir_write_enable=YES
#修改配置48行
chown_uploads=YES
#修改配置72行
async_abor_enable=YES
#修改配置82行
ascii_upload_enable=YES
#修改配置83行
ascii_download_enable=YES
#修改配置86行
ftpd_banner=Welcome to blah FTP service.
#修改配置100行
chroot_local_user=YES
#chroot_local_user与chroot_list_enable详解可阅读博客https://blog.csdn.net/bluishglc/article/details/42398811
#添加下列内容到vsftpd.conf末尾
use_localtime=YES
listen_port=21
idle_session_timeout=300
guest_enable=YES
guest_username=vsftpd
user_config_dir=/etc/vsftpd/vconf
data_connection_timeout=1
virtual_use_local_privs=YES
pasv_min_port=40000
pasv_max_port=40010
accept_timeout=5
connect_timeout=1
allow_writeable_chroot=YES
四、建立用户
#创建编辑用户文件
vim /etc/vsftpd/loginuser.txt
#第一行为用户名,第二行为密码。不能使用root作为用户名
test
123456
#生成用户数据文件
db_load -T -t hash -f /etc/vsftpd/loginuser.txt /etc/vsftpd/login.db
#设定PAM验证文件,并指定对虚拟用户数据库文件进行读取
chmod 600 /etc/vsftpd/login.db
#修改/etc/pam.d/vsftpd文件
vi /etc/pam.d/vsftpd
#先将配置文件中原有的auth及account的所有配置行均注释掉
auth required /lib64/security/pam_userdb.so db=/etc/vsftpd/login
account required /lib64/security/pam_userdb.so db=/etc/vsftpd/login
# 如果系统为32位,上面改为lib
#新建系统用户vsftpd,用户目录为/home/vsftpd
#用户登录终端设为/bin/false(即:使之不能登录系统)
useradd vsftpd -d /home/vsftpd -s /bin/false
chown -R vsftpd:vsftpd /home/vsftpd
注意:在执行“useradd 用户 -d 用户目录 -s /bin/false”的时候会遇到报错“useradd: 无法打开 /etc/gshadow”
解决:chattr -i /etc/gshadow
随后设置:chattr +i /etc/gshadow
#建立虚拟用户个人配置文件
mkdir /etc/vsftpd/vconf
cd /etc/vsftpd/vconf
#这里建立虚拟用户test配置文件
touch test
#编辑test用户配置文件,内容如下,其他用户类似
vi test
local_root=/home/vsftpd/test/
# 如果不加上面这一行或者不创建这个文件则默认的目录为/home/vsftpd
write_enable=YES
anon_world_readable_only=NO #只要ftp用户对文件有读权限即可下载
anon_upload_enable=YES #允许用户上传
anon_mkdir_write_enable=YES #允许用户创建文件夹
anon_other_write_enable=YES #允许用户删除文件和文件夹
#建立test用户根目录
mkdir -p /home/vsftpd/test/
chown -R vsftpd.vsftpd /home/vsftpd/test
如果不加修改属主这一步的话用test用户可以下载文件但是却无法上传文件,后面步骤报错如下:
ftp> put haha.txt
local: haha.txt remote: haha.txt
227 Entering Passive Mode (192,110,110,110,234,96).
553 Could not create file.
五、防火墙和selinux设置
IPtables 的设置方式:
vi /etc/sysconfig/iptables
#编辑iptables文件,添加如下内容,开启21端口
-A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 40000:40010 -j ACCEPT
firewall 的设置方式:
firewall-cmd --zone=public --add-service=ftp --permanent
firewall-cmd --zone=public --add-port=21/tcp --permanent
firewall-cmd --zone=public --add-port=40000-40010/tcp --permanent
#重启vsftpd服务器
systemctl restart vsftpd.service
关闭SELINUX:
vim /etc/selinux/config
#如果是enforcing将该参数改为disabled
SELINUX=disabled
#临时生效
setenforce 0
六、使用ftp工具连接测试
yum -y install ftp
[root@host1 ~]# ftp
ftp> open 192.110.110.110
Connected to 192.110.110.110 (192.110.110.110).
220 Welcome to blah FTP service.
Name (192.110.110.110:root): test
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls #其实就是上面文件配置的路径/home/vsftpd/下面
227 Entering Passive Mode (192,110,110,110,156,73).
150 Here comes the directory listing.
drwxrwxr-x 2 0 0 6 Jun 22 17:50 test
226 Directory send OK.
ftp> lcd /mnt/ #定位到你要上传文件的目录下
Local directory now /mnt
ftp> put hehe.txt
local: hehe.txt remote: hehe.txt
227 Entering Passive Mode (192,110,110,110,156,73).
150 Ok to send data.
226 Transfer complete.
12 bytes sent in 3.7e-05 secs (324.32 Kbytes/sec)
七、Java上传下载FTP工具类
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FtpUtils {
private static final Logger log = LoggerFactory.getLogger(FtpUtils.class);
// 上传文件
public static boolean fileUpload(String filePath, String url, String userName, String password, Integer port,
boolean mode, File file) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
connect(url, port, userName, password, mode, ftp);
} catch (Exception e) {
System.out.println("FtpUpload连接超时--->");
e.printStackTrace();
}
try {
result = upload(file, filePath, ftp);
} catch (Exception e) {
System.out.println("FtpUpload方法异常--->");
e.printStackTrace();
}
return result;
}
public static boolean upload(File file, String filePath, FTPClient ftp) {
boolean flag = true;
try {
String directory = filePath.substring(0, filePath.lastIndexOf("/") + 1);
if (!directory.equalsIgnoreCase("/")
&& !ftp.changeWorkingDirectory(new String(directory.getBytes("UTF-8"), "UTF-8"))) {
// 如果远程目录不存在,则递归创建远程服务器目录
int start = 0;
int end = 0;
if (directory.startsWith("/")) {
start = 1;
} else {
start = 0;
}
end = directory.indexOf("/", start);
while (true) {
String subDirectory = new String(filePath.substring(start, end).getBytes("UTF-8"), "UTF-8");
if (!ftp.changeWorkingDirectory(subDirectory)) {
if (ftp.makeDirectory(subDirectory)) {
ftp.changeWorkingDirectory(subDirectory);
} else {
flag = false;
}
}
start = end + 1;
end = directory.indexOf("/", start);
// 检查所有目录是否创建完毕
if (end <= start) {
break;
}
}
}
log.info("创建目录 " + filePath + " 结果:" + flag);
ftp.setControlEncoding("UTF-8"); // 中文支持
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
FileInputStream input = new FileInputStream(file);
ftp.changeWorkingDirectory(filePath);
ftp.storeFile(file.getName(), input);
input.close(); // 关闭输入流
ftp.logout(); // 退出连接
System.out.println("上传文件成功--->");
} catch (Exception e) {
flag = false;
System.out.println("upload方法异常--->");
e.printStackTrace();
}
return flag;
}
// 下载文件
public static boolean fileDown(String FTPurl, String FTPUserName, String FTPPassword, Integer FTPPort,
boolean FTPMode, String reomvepath, String fileName, String localPath) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
boolean ifConnect = connect(FTPurl, FTPPort, FTPUserName, FTPPassword, FTPMode,ftp);
System.out.println("ifConnect-->" + ifConnect);
} catch (Exception e) {
System.out.println("fileDown连接超时--->");
e.printStackTrace();
}
try {
download(reomvepath, fileName, localPath,ftp);
result = true;
} catch (Exception e) {
System.out.println("fileDown下载超时--->");
e.printStackTrace();
}
return result;
}
public static void download(String reomvepath, String fileName, String localPath,FTPClient ftp) throws Exception {
ftp.changeWorkingDirectory(reomvepath);
// 列出该目录下所有文件
FTPFile[] fs = ftp.listFiles();
// 遍历所有文件,找到指定的文件
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
// 根据绝对路径初始化文件
File localFile = new File(localPath + "/" + ff.getName());
// 输出流
OutputStream is = new FileOutputStream(localFile);
// 下载文件
ftp.retrieveFile(ff.getName(), is);
log.info(fileName + " 下载成功");
is.close();
}
}
ftp.logout(); // 退出连接
}
public static boolean connect(String url, int port, String username, String password, boolean mode, FTPClient ftp)
throws Exception {
boolean result = true;
try {
int reply;
// ftp.setConnectTimeout(10000);
// ftp.setDataTimeout(180000);
// ftp.setControlKeepAliveTimeout(configData.getKeepAliveTimeout());
ftp.connect(url, port);
ftp.login(username, password);
if (mode) {
ftp.enterLocalActiveMode(); // 主动模式
} else {
ftp.enterLocalPassiveMode(); // 被动模式
}
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
result = false;
return result;
}
} catch (Exception e) {
System.out.println("connect方法异常--->");
e.printStackTrace();
result = false;
}
return result;
}
public static void main(String[] args) {
File file=new File("/mnt/huiq/hehe.json");
boolean haha = fileUpload("/ylyjhmd","192.110.110.110","xiaoqiang","iloveyou",21,false,file);
boolean hehe = fileDown("192.110.110.110", "xiaoqiang", "iloveyou", 21, false,
"/ylyjhmd", "haha.json", "/mnt/huiq/");
}
}
maven配置:
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
参考:
CentOS7 FTP安装与配置
http://blog.sina.com.cn/s/blog_3edc5e2e0102vzv8.html