← 回到技术随笔
· 7559 字

银河麒麟操作系统离线配置FTP服务方法

记录银河麒麟系统离线安装 vsftpd,并配置专用本地用户、访问目录、被动端口、防火墙和日志的方法。

适用范围:仅适用于本人拥有或已获明确授权维护的银河麒麟系统。本文以使用 APT 软件包管理的银河麒麟 V10 等版本为主要参考,其他产品线的软件包名称、配置路径和安全机制可能不同。

安全提醒:传统 FTP 会明文传输用户名、口令和文件内容,不适合直接暴露在互联网或不可信网络。能使用 SFTP、SCP 或 HTTPS 时应优先使用;确需 FTP 时,应限制来源地址、使用专用账号并尽量启用 FTPS。

阅读说明:命令中的用户名、目录、端口和地址均为示例,必须替换为现场规划值。执行前先使用 cat /etc/os-release 确认系统版本。

一、先离线安装 vsftpd

内网银河麒麟主机无法直接访问软件源时,不能只下载一个 vsftpd.deb 就开始安装。还要保证软件包版本、CPU 架构、系统版本和依赖关系都与目标机匹配。

1.1 确认离线目标机信息

先在离线目标机记录系统和软件包架构:

# 查看银河麒麟版本和基础系统信息。
cat /etc/os-release

# 查看 APT 使用的软件包架构,例如 amd64 或 arm64。
dpkg --print-architecture

# 查看当前软件源配置,便于准备机使用相同来源。
grep -RhsE '^[[:space:]]*deb([[:space:]]|$)' \
  /etc/apt/sources.list /etc/apt/sources.list.d/*.list 2>/dev/null

这里的 \ 表示同一条命令在下一行继续,不是两条命令。

联网准备机最好使用与目标机相同的银河麒麟版本、架构和软件源。若准备机已经安装了较多软件,APT 可能认为部分依赖无需重新下载,因此使用同版本的干净虚拟机准备离线包更稳妥。

1.2 在联网准备机下载软件包

# 更新联网准备机的软件包索引。
sudo apt-get update

# 创建独立的下载目录及 APT 临时目录。
sudo mkdir -p /var/tmp/vsftpd-offline/partial

# 允许 APT 访问下载目录,并让 _apt 用户写入 partial 临时目录。
sudo chmod 755 /var/tmp/vsftpd-offline
sudo chown _apt:root /var/tmp/vsftpd-offline/partial
sudo chmod 700 /var/tmp/vsftpd-offline/partial

# 只下载 vsftpd 及当前准备环境中缺少的依赖,不执行安装。
sudo apt-get install --download-only --reinstall \
  -o Dir::Cache::archives=/var/tmp/vsftpd-offline \
  vsftpd

# 查看已经下载的 DEB 包。
ls -lh /var/tmp/vsftpd-offline/*.deb

# 为传输文件生成 SHA-256 校验清单。
cd /var/tmp/vsftpd-offline
sha256sum ./*.deb | sudo tee SHA256SUMS >/dev/null

如果 APT 显示没有下载任何依赖,应确认准备机状态是否与目标机相同。不能把其他 Ubuntu、Debian 或不同银河麒麟版本的软件包直接混用。

.deb 文件和 SHA256SUMS 通过单位批准的移动介质或摆渡方式传入离线环境。

1.3 在离线目标机校验并安装

# 进入离线软件包所在目录。
cd /path/to/vsftpd-offline

# 验证文件在传输过程中没有发生变化。
sha256sum -c SHA256SUMS

# 使用 APT 安装当前目录中的全部 DEB 包并处理依赖顺序。
sudo apt install ./*.deb

# 查看 vsftpd 软件包是否已经安装。
dpkg-query -W -f='${Status}\t${Package}\t${Version}\n' vsftpd

# 查看服务单元是否存在。
systemctl status vsftpd --no-pager

如果提示缺少依赖,不要使用 dpkg --force-depends 强行跳过。应记录缺少的软件包和版本,返回联网准备机补齐。

也可以使用银河麒麟安装介质或单位内部 APT 源离线安装。只要本地源已经正确建立,安装命令与联网环境相同:

# 从已经配置好的本地 APT 源安装 vsftpd。
sudo apt-get update
sudo apt-get install vsftpd

二、先决定使用哪种账号方式

vsftpd 常见的账号模式有三种:

模式 适用场景 建议
匿名用户 公开下载文件 只开放下载,不开放匿名上传
系统本地用户 少量固定运维人员 配置简单,适合日常内部文件传输
虚拟用户 多账号、需要独立权限 隔离更灵活,但 PAM 和用户数据库配置更复杂

本文先配置最常用的“专用本地用户”模式。除非确有公开下载需求,否则建议关闭匿名登录。

三、备份默认配置

银河麒麟使用 APT 安装的 vsftpd,主配置文件通常是 /etc/vsftpd.conf。修改前先确认软件包实际文件:

# 查看 vsftpd 软件包安装了哪些配置文件。
dpkg -L vsftpd | grep -E '/etc/|vsftpd\.conf'

# 备份主配置文件,并在文件名中记录时间。
sudo cp -a /etc/vsftpd.conf \
  "/etc/vsftpd.conf.bak.$(date +%Y%m%d%H%M%S)"

# 查看 PAM 认证配置;此处只检查,不要随意修改。
sudo sed -n '1,160p' /etc/pam.d/vsftpd

# 查看禁止通过 FTP 登录的系统账号。
sudo sed -n '1,160p' /etc/ftpusers

/etc/ftpusers 通常会禁止 root 等高权限账号登录 FTP。不要为了让 root 登录而删除这些限制,应该创建权限更小的专用账号。

四、创建专用 FTP 账号和目录

下面创建账号 ftpops,将其限制在 /srv/ftp/ftpops。FTP 根目录由 root 管理,真正可写的目录放在根目录下面。

# 创建 FTP 根目录和上传目录。
sudo mkdir -p /srv/ftp/ftpops/upload

# 创建专用账号,不自动创建家目录,并禁止获得交互式 Shell。
sudo useradd -M -d /srv/ftp/ftpops \
  -s /usr/sbin/nologin ftpops

# 为 FTP 专用账号设置高强度口令。
sudo passwd ftpops

# 确保 nologin 是 PAM 允许识别的有效登录 Shell。
grep -qxF /usr/sbin/nologin /etc/shells \
  || echo /usr/sbin/nologin | sudo tee -a /etc/shells

# FTP 根目录归 root 所有,用户不能修改根目录本身。
sudo chown root:root /srv/ftp/ftpops
sudo chmod 755 /srv/ftp/ftpops

# 只把 upload 子目录交给 ftpops 写入。
sudo chown ftpops:ftpops /srv/ftp/ftpops/upload
sudo chmod 750 /srv/ftp/ftpops/upload

不建议为了省事把 /srv/ftp/ftpops 整个目录设为 777。那样既扩大了写权限,也容易与 chroot 的安全检查冲突。

五、配置本地用户登录

使用编辑器打开 /etc/vsftpd.conf,先删除或注释与以下项目冲突的旧配置,再按实际需要写入:

# 以独立服务方式监听 IPv4。
listen=YES

# listen 与 listen_ipv6 不能同时启用。
listen_ipv6=NO

# 禁止匿名用户登录。
anonymous_enable=NO

# 允许系统本地用户登录。
local_enable=YES

# 允许执行上传、删除、重命名和创建目录等写操作。
write_enable=YES

# 本地用户上传文件时使用 022 掩码。
local_umask=022

# 把本地用户限制在其家目录中。
chroot_local_user=YES

# 使用用户家目录作为登录后的根目录。
local_root=/srv/ftp/ftpops

# 启用用户白名单。
userlist_enable=YES

# 只有名单中的用户可以登录。
userlist_deny=NO

# 指定允许登录的用户列表。
userlist_file=/etc/vsftpd.user_list

# 启用被动模式。
pasv_enable=YES

# 限定被动模式数据端口范围,便于配置防火墙。
pasv_min_port=30000
pasv_max_port=30100

# 记录文件传输日志。
xferlog_enable=YES

# 使用 vsftpd 自有的可读日志格式。
xferlog_std_format=NO

# 在目录列表中显示本地时间。
use_localtime=YES

把专用账号加入白名单:

# 创建白名单文件,只允许 ftpops 登录。
echo ftpops | sudo tee /etc/vsftpd.user_list

# 仅允许 root 修改白名单。
sudo chown root:root /etc/vsftpd.user_list
sudo chmod 600 /etc/vsftpd.user_list

这里没有使用 allow_writeable_chroot=YES,而是让根目录只读、upload 子目录可写。这样权限边界更清晰。

如果需要为多个本地用户提供各自目录,不应把 local_root 固定为同一个账号目录。可以保留各用户的家目录作为根目录,或根据实际版本验证 user_sub_token 方案。

六、配置防火墙

先确认系统实际使用的防火墙,不要同时照抄 firewalld 和 UFW 两套命令:

# 检查 firewalld 是否正在运行。
systemctl is-active firewalld

# 检查 UFW 状态;系统未安装时会提示命令不存在。
sudo ufw status

6.1 使用 firewalld

下面以 public 区域为例。生产环境应替换为 FTP 服务实际网卡所属区域,并尽量通过 rich rule 限制来源网段。

# 查看活动区域及其绑定接口。
sudo firewall-cmd --get-active-zones

# 永久开放 FTP 控制连接。
sudo firewall-cmd --permanent \
  --zone=public --add-service=ftp

# 永久开放与 vsftpd 配置一致的被动数据端口。
sudo firewall-cmd --permanent \
  --zone=public --add-port=30000-30100/tcp

# 重新加载永久规则,使其生效。
sudo firewall-cmd --reload

# 查看最终开放的服务和端口。
sudo firewall-cmd --zone=public --list-all

6.2 使用 UFW

# 开放 FTP 控制端口。
sudo ufw allow 21/tcp

# 开放与 vsftpd 配置一致的被动端口范围。
sudo ufw allow 30000:30100/tcp

# 查看最终规则。
sudo ufw status numbered

如果只允许固定管理网段访问,应把规则进一步限制到该来源网段,而不是对所有地址开放。

七、启动并验证服务

# 设置 vsftpd 开机启动,并立即启动服务。
sudo systemctl enable --now vsftpd

# 修改配置后重新启动服务。
sudo systemctl restart vsftpd

# 查看服务状态和最近错误。
sudo systemctl status vsftpd --no-pager

# 查看本次启动的服务日志。
sudo journalctl -u vsftpd -b --no-pager

# 查看 21 端口是否正在监听。
sudo ss -lntp | grep ':21 '

不要只在服务器本机测试。还要从允许访问的客户端测试:

# 使用 FTP 客户端连接服务器;替换为实际地址。
ftp 192.0.2.20

登录后验证:

  1. 能否列出根目录和 upload 目录;
  2. 能否下载已有文件;
  3. 根目录是否禁止上传;
  4. upload 目录是否允许上传;
  5. 是否禁止越出根目录;
  6. 非白名单用户是否无法登录;
  7. 日志是否记录登录和传输行为。

FTP 客户端应使用被动模式。若能登录但无法列目录或传文件,通常要先检查被动端口、防火墙和 NAT,而不是反复修改目录权限。

八、查看日志和日常管理

# 查看 systemd 服务日志。
sudo journalctl -u vsftpd --since today

# 查看 vsftpd 文件传输日志。
sudo tail -n 100 /var/log/vsftpd.log

# 查看账号状态和密码有效期。
sudo passwd -S ftpops
sudo chage -l ftpops

# 查看上传目录当前权限。
namei -l /srv/ftp/ftpops/upload

日常维护建议:

  • 定期检查账号是否仍有使用必要;
  • 定期轮换口令;
  • 限制上传目录容量;
  • 对上传文件进行恶意代码检测;
  • 监控重复登录失败和异常来源地址;
  • 根据审计要求轮转并保留日志;
  • 不再使用 FTP 时关闭服务和防火墙规则。

停止服务:

# 立即停止服务,并取消开机启动。
sudo systemctl disable --now vsftpd

九、可选:配置匿名只读下载

只有确实需要公开下载时才启用匿名访问。匿名模式建议只读,不开放上传、删除或重命名。

# 允许匿名用户登录。
anonymous_enable=YES

# 禁止匿名上传。
anon_upload_enable=NO

# 禁止匿名创建目录。
anon_mkdir_write_enable=NO

# 禁止匿名执行删除、重命名等其他写操作。
anon_other_write_enable=NO

# 匿名用户根目录。
anon_root=/srv/ftp/public

准备只读目录:

# 创建匿名下载目录。
sudo mkdir -p /srv/ftp/public

# 目录归 root 所有,匿名用户不能写入。
sudo chown root:root /srv/ftp/public
sudo chmod 755 /srv/ftp/public

# 重启服务使配置生效。
sudo systemctl restart vsftpd

不要简单照搬“匿名免口令并开放全局写入”的配置。匿名上传目录容易被滥用,可能成为恶意文件中转站。

十、可选:启用 FTPS

FTPS 是在 FTP 上增加 TLS 加密,不等同于基于 SSH 的 SFTP。客户端必须明确支持 FTPS。

正式环境应使用单位证书系统签发的服务器证书。以下配置只说明关键参数:

# 启用 TLS 支持。
ssl_enable=YES

# 强制本地用户的登录过程使用 TLS。
force_local_logins_ssl=YES

# 强制本地用户的数据连接使用 TLS。
force_local_data_ssl=YES

# 指定服务器证书。
rsa_cert_file=/etc/ssl/certs/ftp-server.crt

# 指定证书私钥。
rsa_private_key_file=/etc/ssl/private/ftp-server.key

# 禁用已废弃的 SSL 协议。
ssl_sslv2=NO
ssl_sslv3=NO

私钥应由 root 持有并限制读取权限。启用后需要使用支持显式 FTPS 的客户端重新验证登录、目录列表、上传和下载。

十一、虚拟用户什么时候使用

原参考资料还介绍了基于 Berkeley DB 和 PAM 的虚拟用户。它适合以下场景:

  • 不希望每个 FTP 账号都成为系统账号;
  • 多个账号需要不同目录;
  • 各账号需要独立的上传、下载、删除权限;
  • 账号数量较多,需要集中维护。

虚拟用户配置涉及 db_load、PAM 服务文件、映射系统账号和每用户配置目录。不同银河麒麟版本的 PAM 模块路径、db-util 软件包名称和 vsftpd 编译选项可能不同,不能只复制一份配置文件就上线。

如果只有一两个内部运维账号,使用专用本地用户通常更直观;账号较多时,再根据当前系统版本单独设计和测试虚拟用户方案。

十二、常见故障排查

12.1 服务启动失败

# 查看服务失败原因。
sudo systemctl status vsftpd --no-pager
sudo journalctl -u vsftpd -b --no-pager

# 检查是否同时启用了 listen 和 listen_ipv6。
grep -nE '^(listen|listen_ipv6)=' /etc/vsftpd.conf

listen=YESlisten_ipv6=YES 不能同时使用。

12.2 提示 530 Login incorrect

依次检查:

  • 用户名和口令是否正确;
  • 用户是否在 /etc/vsftpd.user_list
  • userlist_deny 是否设为 NO
  • 用户是否被 /etc/ftpusers 禁止;
  • 用户 Shell 是否被 PAM 接受;
  • 账号是否锁定或过期;
  • PAM 日志中是否有拒绝原因。

12.3 提示 500 OOPS: vsftpd: refusing to run with writable root

说明被 chroot 的根目录可写。推荐把根目录设为 root 所有,只给下级 upload 目录写权限,不要直接使用 777 或依赖放宽检查。

12.4 能登录但看不到目录

重点检查:

  • 客户端是否使用被动模式;
  • pasv_min_portpasv_max_port 与防火墙是否一致;
  • 服务器是否位于 NAT 后;
  • 目录每一级是否有执行权限;
  • 防火墙区域是否选对;
  • 安全策略或 SELinux 是否拒绝访问。

如果 getenforce 显示 Enforcing,应查看审计日志并配置正确的安全策略,不要把永久关闭 SELinux 当作解决办法。

# 查看 SELinux 状态。
getenforce

# 查看近期与 vsftpd 相关的拒绝记录。
sudo ausearch -m AVC -ts recent | grep -i vsftpd

12.5 中文文件名或时间显示异常

先确认客户端编码、系统 Locale 和 utf8_filesystem 是否受当前 vsftpd 版本支持。时间显示可使用 use_localtime=YES。不建议直接修改系统提供的 vsftpd.service 文件;软件升级可能覆盖该文件。如确需添加 systemd 环境变量,应使用 systemctl edit vsftpd 创建覆盖配置,并做好测试。

十三、最后检查

  • [ ] vsftpd 软件包来源、版本和架构已核对。
  • [ ] 离线软件包哈希校验通过。
  • [ ] 原配置已经备份。
  • [ ] 未开放 root 登录。
  • [ ] 匿名登录已关闭,或只开放只读下载。
  • [ ] FTP 根目录不可写,上传目录权限独立。
  • [ ] 仅需要的账号在白名单中。
  • [ ] 被动端口与防火墙规则一致。
  • [ ] 已限制 FTP 服务的来源网络。
  • [ ] 登录、上传、下载和越权访问均已测试。
  • [ ] 日志能够记录登录和文件传输。
  • [ ] 明文 FTP 风险已评估,必要时已启用 FTPS 或改用 SFTP。