首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

Debian Linux下vsftpd+MySQL虛擬用戶實戰:PAM認證、目錄隔離與多租戶實現

     編輯:MySQL 綜合教學

vsftpd 作為 Linux 下安全性最高的 FTP 服務器之一,結合 MySQL 存儲虛擬用戶信息,通過 PAM 模塊實現認證授權,可構建無系統賬號、目錄隔離、配額控制的多租戶 FTP 服務。本文記錄 Debian/Ubuntu 環境下完整部署流程。

架構設計

FTP Client → vsftpd (PAM) → libpam-mysql → MySQL (ftpu.user 表)
                ↓
         本地系統用戶 ftpguest (映射虛擬用戶權限)
                ↓
         文件系統目錄 /home/ftp/{user}/ (虛擬用戶獨立根目錄)

第一步:安裝 vsftpd 與創建映射用戶


apt-get update && apt-get install -y vsftpd

# 創建虛擬用戶映射的本地系統用戶 (無登錄shell、無家目錄)
useradd -r -s /usr/sbin/nologin -d /var/empty ftpguest

# 創建 FTP 根目錄並授權
mkdir -p /home/ftp
chown ftpguest:nogroup /home/ftp
chmod 755 /home/ftp

第二步:安裝 MySQL 並構建虛擬用戶表


apt-get install -y mysql-server mysql-client

# 安全初始化
mysql_secure_installation

# 創建 FTP 虛擬用戶庫表
mysql -u root -p -e "
CREATE DATABASE ftpu CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE ftpu;
CREATE TABLE \`user\` (
    \`id\` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    \`username\` VARCHAR(50) NOT NULL UNIQUE COMMENT 'FTP用戶名',
    \`password\` CHAR(41) NOT NULL COMMENT 'PASSWORD()哈希值',
    \`homedir\` VARCHAR(255) NOT NULL DEFAULT '/' COMMENT '相對FTP根目錄的家目錄',
    \`enable\` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '1啟用 0禁用',
    \`quota_size\` BIGINT UNSIGNED DEFAULT 0 COMMENT '磁盤配額(bytes), 0不限制',
    \`quota_files\` INT UNSIGNED DEFAULT 0 COMMENT '文件數配額, 0不限制',
    \`create_time\` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    \`update_time\` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_enable (enable)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='FTP虛擬用戶表';

-- 插入測試用戶 (密碼: TestPass123!)
INSERT INTO \`user\` (username, password, homedir) VALUES 
('test1', PASSWORD('TestPass123!'), '/test1'),
('test2', PASSWORD('TestPass123!'), '/test2');

-- 創建 PAM 專用讀取用戶
CREATE USER 'pam_ftp'@'localhost' IDENTIFIED BY 'PamFtpPass123!';
GRANT SELECT ON ftpu.user TO 'pam_ftp'@'localhost';
FLUSH PRIVILEGES;
"

第三步:安裝並配置 PAM-MySQL 模塊


apt-get install -y libpam-mysql

# 配置 vsftpd PAM 服務
cat > /etc/pam.d/vsftpd << 'EOF'
#%PAM-1.0
auth    required    pam_mysql.so \
    user=pam_ftp \
    passwd=PamFtpPass123! \
    host=localhost \
    db=ftpu \
    table=user \
    usercolumn=username \
    passwdcolumn=password \
    crypt=3 \
    where="enable=1"

account required    pam_mysql.so \
    user=pam_ftp \
    passwd=PamFtpPass123! \
    host=localhost \
    db=ftpu \
    table=user \
    usercolumn=username \
    passwdcolumn=password \
    crypt=3 \
    where="enable=1"
EOF

關鍵參數:crypt=3 表示 MySQL PASSWORD() 哈希 (8.0+ 為 caching_sha2_password,需確認兼容性,建議應用層自行驗證或用明文對比方案)

第四步:配置 vsftpd 核心參數


cat > /etc/vsftpd.conf << 'EOF'
# 基礎運行
listen=YES
listen_ipv6=NO
anonymous_enable=NO
local_enable=YES

# 虛擬用戶核心配置
guest_enable=YES
guest_username=ftpguest
virtual_use_local_privs=YES

# 寫入權限
write_enable=YES
local_umask=022
anon_upload_enable=NO
anon_mkdir_write_enable=NO
anon_other_write_enable=NO

# 目錄限制 (關鍵:虛擬用戶見不到彼此目錄)
chroot_local_user=YES
chroot_list_enable=NO
allow_writeable_chroot=YES

# 用戶配置目錄 (實現每用戶獨立根目錄)
user_config_dir=/etc/vsftpd_user_conf

# 日誌
xferlog_enable=YES
xferlog_file=/var/log/vsftpd.log
xferlog_std_format=YES
dual_log_enable=YES
vsftpd_log_file=/var/log/vsftpd_xfer.log

# 性能與安全
idle_session_timeout=300
data_connection_timeout=120
max_clients=200
max_per_ip=20
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100
pasv_address=YOUR_PUBLIC_IP  # 被動模式公網IP
EOF

第五步:實現用戶級目錄隔離 (user_config_dir)


# 創建用戶配置目錄
mkdir -p /etc/vsftpd_user_conf

# 為每個虛擬用戶創建配置文件 (文件名 = 用戶名)
cat > /etc/vsftpd_user_conf/test1 << 'EOF'
local_root=/home/ftp/test1
EOF

cat > /etc/vsftpd_user_conf/test2 << 'EOF'
local_root=/home/ftp/test2
EOF

# 創建實際目錄並授權
mkdir -p /home/ftp/test1 /home/ftp/test2
chown -R ftpguest:nogroup /home/ftp/test1 /home/ftp/test2
chmod 755 /home/ftp/test1 /home/ftp/test2

# 可選:設置磁盤配額 (需文件系統支持 quota)
# setquota -u ftpguest 100M 200M 0 0 /home/ftp  (項目配額)

第六步:啟動驗證與測試


# 重啟 vsftpd
systemctl restart vsftpd
systemctl enable vsftpd

# 防火牆放行
ufw allow 20/tcp
ufw allow 21/tcp
ufw allow 40000:40100/tcp
ufw reload

# 測試連接 (命令行 FTP 客戶端)
ftp localhost
# Name: test1
# Password: TestPass123!
# ftp> ls
# ftp> put local_file.txt
# ftp> get remote_file.txt
# ftp> quit

# 或使用 FileZilla / WinSCP 圖形化客戶端測試

進階擴展:動態用戶管理腳本


#!/bin/bash
# manage_ftp_user.sh
# 用法: ./manage_ftp_user.sh add|del|disable|enable  [password] [homedir]

ACTION=$1
USER=$2
PASS=$3
HOMEDIR=${4:-"/$USER"}

case $ACTION in
  add)
    mysql -u root -p${MYSQL_ROOT_PASS} -e "
    USE ftpu;
    INSERT INTO \`user\` (username, password, homedir) VALUES ('$USER', PASSWORD('$PASS'), '$HOMEDIR');
    "
    mkdir -p /home/ftp$HOMEDIR
    chown ftpguest:nogroup /home/ftp$HOMEDIR
    cat > /etc/vsftpd_user_conf/$USER << EOF
local_root=/home/ftp$HOMEDIR
EOF
    echo "User $USER added"
    ;;
  del)
    mysql -u root -p${MYSQL_ROOT_PASS} -e "USE ftpu; DELETE FROM \`user\` WHERE username='$USER';"
    rm -f /etc/vsftpd_user_conf/$USER
    # 可選刪除目錄: rm -rf /home/ftp$HOMEDIR
    echo "User $USER deleted"
    ;;
  disable)
    mysql -u root -p${MYSQL_ROOT_PASS} -e "USE ftpu; UPDATE \`user\` SET enable=0 WHERE username='$USER';"
    echo "User $USER disabled"
    ;;
  enable)
    mysql -u root -p${MYSQL_ROOT_PASS} -e "USE ftpu; UPDATE \`user\` SET enable=1 WHERE username='$USER';"
    echo "User $USER enabled"
    ;;
  *)
    echo "Usage: $0 add|del|disable|enable  [password] [homedir]"
    ;;
esac

常見問題排查

現象原因解決
530 Login incorrectPAM認證失敗:密碼哈希不匹配/用戶禁用/where條件檢查 /var/log/auth.log;驗證 crypt 參數;確認 enable=1;MySQL 8.0+ PASSWORD() 已移除,需應用層驗證
500 OOPS: cannot change directorylocal_root 目錄不存在/權限錯誤確認目錄存在、ftpguest 擁有權、chroot 允許寫入
被動模式無法傳輸pasv_port_range 未放防火牆 / pasv_address 錯誤防火牆放行 40000-40100;pasv_address 設置公網IP
虛擬用戶能看到根目錄其他用戶文件夾chroot_local_user=NO 或 user_config_dir 未生效確認 chroot_local_user=YES;user_config_dir 路徑正確;配置文件名=用戶名

MySQL 8.0+ 兼容性說明

MySQL 8.0 移除了 PASSWORD() 函數,caching_sha2_password 為默認認證插件。libpam-mysql 的 crypt=3 可能不兼容。解決方案:

  1. 用戶表存儲 SHA2(CONCAT('salt', password), 256) 或 bcrypt 哈希,PAM 配置 crypt=0 (明文對比,需應用層在 PAM 對話中驗證,較複雜)
  2. 或降級 MySQL 用戶認證插件:ALTER USER 'ftp_user'@'%' IDENTIFIED WITH mysql_native_password BY 'pass'; (僅限兼容場景)
  3. 推薦:應用層管理用戶,vsftpd 通過外部腳本驗證 (如 pam_exec.so 調用 Python/Go 腳本查庫驗證),完全脫離 PAM-MySQL 限制
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved