在 Ubuntu(root) 上搭建标准 FTP(vsftpd)服务器,带被动模式端口、用户创建、目录与权限配置,可直接落地执行。
一、部署脚本(保存为 setup_ftp.sh
,root 执行)
#!/usr/bin/env bash
set -euo pipefail### ====== 可按需修改的变量 ======
FTP_USER="ftpuser" # 要创建的FTP账户
FTP_PASS="MyPassword123!" # 账户密码(请修改)
FTP_BASE="/srv/ftp" # FTP根目录(每用户目录 = $FTP_BASE/$FTP_USER)
PASV_MIN=40000 # 被动模式端口范围(防火墙需放行)
PASV_MAX=40100
# 外网IP(服务器直接暴露公网可自动探测;若在NAT/家庭路由后,务必改成路由器的公网IP)
EXTERNAL_IP="$(hostname -I | awk '{print $1}')"
# EXTERNAL_IP="你的公网IP" # 若在NAT后面,请取消注释并填写正确公网IP
### =============================echo "[1/7] 安装 vsftpd..."
apt update
DEBIAN_FRONTEND=noninteractive apt install -y vsftpdecho "[2/7] 创建 FTP 用户与目录..."
id -u "$FTP_USER" &>/dev/null || adduser --disabled-password --gecos "" "$FTP_USER"
echo "${FTP_USER}:${FTP_PASS}" | chpasswdmkdir -p "${FTP_BASE}/${FTP_USER}"
chown -R "${FTP_USER}:${FTP_USER}" "${FTP_BASE}/${FTP_USER}"
chmod 755 "${FTP_BASE}"
chmod 755 "${FTP_BASE}/${FTP_USER}"echo "[3/7] 备份并生成 vsftpd 配置..."
cp -a /etc/vsftpd.conf /etc/vsftpd.conf.bak.$(date +%F-%H%M%S)cat >/etc/vsftpd.conf <<EOF
listen=YES
listen_ipv6=NOanonymous_enable=NO
local_enable=YES
write_enable=YES# 允许本地用户被chroot到自己的目录,同时目录可写
chroot_local_user=YES
allow_writeable_chroot=YES# 每用户目录:/srv/ftp/\$USER
user_sub_token=\$USER
local_root=${FTP_BASE}/\$USER# 显示隐藏文件(以点开头)
force_dot_files=YES# 被动模式(配合防火墙/NAT)
pasv_enable=YES
pasv_min_port=${PASV_MIN}
pasv_max_port=${PASV_MAX}
pasv_address=${EXTERNAL_IP}# 更友好的文件名编码
utf8_filesystem=YES# 安全相关(根据需要调整)
pam_service_name=vsftpd
seccomp_sandbox=NO
EOFecho "[4/7] 配置防火墙(如启用UFW)..."
if command -v ufw >/dev/null 2>&1; thenufw allow 21/tcp || trueufw allow ${PASV_MIN}:${PASV_MAX}/tcp || true
fiecho "[5/7] 启动并设为开机自启..."
systemctl enable --now vsftpd
systemctl restart vsftpd
systemctl --no-pager status vsftpd | sed -n '1,10p' || trueecho "[6/7] 打印连接信息:"
cat <<INFO===================== FTP 信息 =====================
服务器IP: ${EXTERNAL_IP}
端口: 21
协议: FTP (建议客户端使用 Passive / 被动模式)
账号: ${FTP_USER}
密码: ${FTP_PASS}
用户目录: ${FTP_BASE}/${FTP_USER}
被动端口: ${PASV_MIN}-${PASV_MAX} (记得在安全组/路由器放行)
=====================================================INFOecho "[7/7] 快速自检(本机连):"
echo " ftp -inv ${EXTERNAL_IP} <<'EOF'"
echo " user ${FTP_USER} ${FTP_PASS}"
echo " ls"
echo " bye"
echo " EOF"echo "完成。若服务器在NAT/路由后,请将 vsftpd.conf 中 pasv_address 改为公网IP后重启: systemctl restart vsftpd"
使用
vi setup_ftp.sh # 粘贴上面的脚本,按需改 FTP_USER/FTP_PASS 等
chmod +x setup_ftp.sh
./setup_ftp.sh
二、常见网络与NAT说明
- 云服务器:在提供商的安全组放行 TCP 21 和
${PASV_MIN}-${PASV_MAX}
。 - 家庭路由/NAT:路由器做端口映射:
- TCP 21 → 服务器内网IP:21
- TCP 40000–40100 → 服务器内网IP:40000–40100
并把脚本里的EXTERNAL_IP
改成路由器的公网IP。
三、客户端连接建议
- 推荐 FileZilla Client,连接时选 传输模式:被动(Passive)。
- 纯 FTP 不加密;若需加密可改用 FTPS(显式TLS) 或直接使用 SFTP(更安全,端口22,和本脚本不同)。
四、快捷新增用户脚本(可选)
以后想再加一个用户,保存为 add_ftp_user.sh
:
#!/usr/bin/env bash
set -euo pipefail
FTP_USER="${1:?用法: $0 用户名}"
FTP_PASS="${2:?用法: $0 用户名 密码}"
FTP_BASE="/srv/ftp"id -u "$FTP_USER" &>/dev/null || adduser --disabled-password --gecos "" "$FTP_USER"
echo "${FTP_USER}:${FTP_PASS}" | chpasswdmkdir -p "${FTP_BASE}/${FTP_USER}"
chown -R "${FTP_USER}:${FTP_USER}" "${FTP_BASE}/${FTP_USER}"
chmod 755 "${FTP_BASE}/${FTP_USER}"echo "已创建用户 ${FTP_USER},目录 ${FTP_BASE}/${FTP_USER}"
使用:
chmod +x add_ftp_user.sh
./add_ftp_user.sh user2 "StrongPass#2"
FTP_USER="ftpuser" # 要创建的FTP账户
FTP_PASS="MyPassword123!" # 账户密码(请修改)
FTP_BASE="/srv/ftp" # FTP根目录(每用户目录 = $FTP_BASE/$FTP_USER)结果:
root@localhost:~# chmod +x setup_ftp.sh
root@localhost:~# ./setup_ftp.sh
[1/7] 安装 vsftpd...
Hit:1 http://mirrors.aliyun.com/ubuntu focal InRelease
Get:2 http://mirrors.aliyun.com/ubuntu focal-updates InRelease [128 kB]
Get:3 http://mirrors.aliyun.com/ubuntu focal-backports InRelease [128 kB]
Get:4 http://mirrors.aliyun.com/ubuntu focal-security InRelease [128 kB]
Get:5 http://mirrors.aliyun.com/ubuntu focal-updates/main amd64 DEP-11 Metadata [276 kB]
Get:6 http://mirrors.aliyun.com/ubuntu focal-updates/restricted amd64 DEP-11 Metadata [212 B]
Get:7 http://mirrors.aliyun.com/ubuntu focal-updates/universe amd64 DEP-11 Metadata [446 kB]
Get:8 http://mirrors.aliyun.com/ubuntu focal-updates/multiverse amd64 DEP-11 Metadata [940 B]
Get:9 http://mirrors.aliyun.com/ubuntu focal-backports/main amd64 DEP-11 Metadata [8,004 B]
Get:10 http://mirrors.aliyun.com/ubuntu focal-backports/restricted amd64 DEP-11 Metadata [216 B]
Get:11 http://mirrors.aliyun.com/ubuntu focal-backports/universe amd64 DEP-11 Metadata [30.5 kB]
Get:12 http://mirrors.aliyun.com/ubuntu focal-backports/multiverse amd64 DEP-11 Metadata [212 B]
Get:13 http://mirrors.aliyun.com/ubuntu focal-security/main amd64 DEP-11 Metadata [74.6 kB]
Get:14 http://mirrors.aliyun.com/ubuntu focal-security/restricted amd64 DEP-11 Metadata [212 B]
Get:15 http://mirrors.aliyun.com/ubuntu focal-security/universe amd64 DEP-11 Metadata [159 kB]
Get:16 http://mirrors.aliyun.com/ubuntu focal-security/multiverse amd64 DEP-11 Metadata [940 B]
Fetched 1,380 kB in 1s (2,147 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
All packages are up to date.
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:vsftpd
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 115 kB of archives.
After this operation, 334 kB of additional disk space will be used.
Get:1 http://mirrors.aliyun.com/ubuntu focal-updates/main amd64 vsftpd amd64 3.0.5-0ubuntu0.20.04.2 [115 kB]
Fetched 115 kB in 0s (849 kB/s)
Preconfiguring packages ...
Selecting previously unselected package vsftpd.
(Reading database ... 208600 files and directories currently installed.)
Preparing to unpack .../vsftpd_3.0.5-0ubuntu0.20.04.2_amd64.deb ...
Unpacking vsftpd (3.0.5-0ubuntu0.20.04.2) ...
Setting up vsftpd (3.0.5-0ubuntu0.20.04.2) ...
Created symlink /etc/systemd/system/multi-user.target.wants/vsftpd.service → /lib/systemd/system/vsftpd.service.
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for systemd (245.4-4ubuntu3.24) ...
[2/7] 创建 FTP 用户与目录...
Adding user `ftpuser' ...
Adding new group `ftpuser' (1003) ...
Adding new user `ftpuser' (1003) with group `ftpuser' ...
Creating home directory `/home/ftpuser' ...
Copying files from `/etc/skel' ...
[3/7] 备份并生成 vsftpd 配置...
[4/7] 配置防火墙(如启用UFW)...
Rules updated
Rules updated (v6)
Rules updated
Rules updated (v6)
[5/7] 启动并设为开机自启...
Synchronizing state of vsftpd.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable vsftpd
● vsftpd.service - vsftpd FTP serverLoaded: loaded (/lib/systemd/system/vsftpd.service; enabled; vendor preset: enabled)Active: active (running) since Sun 2025-09-14 03:59:55 CST; 15ms agoProcess: 225256 ExecStartPre=/bin/mkdir -p /var/run/vsftpd/empty (code=exited, status=0/SUCCESS)Main PID: 225257 (vsftpd)Tasks: 1 (limit: 9413)Memory: 620.0KCGroup: /system.slice/vsftpd.service└─225257 /usr/sbin/vsftpd /etc/vsftpd.conf[6/7] 打印连接信息:===================== FTP 信息 =====================
服务器IP: 172.30.0.6
端口: 21
协议: FTP (建议客户端使用 Passive / 被动模式)
账号: ftpuser
密码: MyPassword123!
用户目录: /srv/ftp/ftpuser
被动端口: 40000-40100 (记得在安全组/路由器放行)
=====================================================[7/7] 快速自检(本机连):ftp -inv 172.30.0.6 <<'EOF'user ftpuser MyPassword123!lsbyeEOF
完成。若服务器在NAT/路由后,请将 vsftpd.conf 中 pasv_address 改为公网IP后重启: systemctl restart vsftpd
root@localhost:~# ls