sftp
环境说明
[root@sftp ~]# cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
[root@sftp ~]# ssh -V
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
[root@sftp ~]# uname -a
Linux sftp.localdomain 3.10.0-1127.19.1.el7.x86_64 #1 SMP Tue Aug 25 17:23:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
- sftp是Secure File Transfer Protocol的缩写,安全文件传送协议。可以为传输文件提供一种安全的加密方法。sftp与ftp 有着几乎一样的语法和功能。SFTP 为 SSH的一部分,是一种传输档案至Blogger伺服器的安全方式。
- 其实在SSH软件包中,已经包含了一个叫作SFTP(Secure File Transfer Protocol)的安全文件传输子系统,SFTP本身没有单独的守护进程,它必须使用sshd守护进程(端口号默认是22)来完成相应的连接操作,所以从某种意义上来说,SFTP并不像一个服务器程序,而更像是一个客户端程序。
- SFTP同样是使用加密传输认证信息和传输的数据,所以,使用SFTP是非常安全的。但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低得多,如果您对网络安全性要求更高时,可以使用SFTP代替FTP。
- SFTP是一种安全的交互式文件传输程序,其工作方式与FTP(文件传输协议)类似。然而sFTP比FTP更安全,它通过加密SSH传输处理所有操作。它可以配置使用几个有用的SSH功能,如公钥认证和压缩。它连接并登录到指定的远程机器,然后切换到交互式命令模式,在该模式下用户可以执行各种命令。
直接使用sshd配置文件配置sftp
[root@sftp ~]# cp /etc/ssh/sshd_config{,-bak$(date +%Y%m%d)}
[root@sftp ~]# vim /etc/ssh/sshd_config
132 # Subsystem sftp /usr/libexec/openssh/sftp-server
134 Subsystem sftp internal-sftp -l INFO -f AUTH
#这行指定使用sftp服务使用系统自带的internal-sftp
···
最后添加以下内容
Match Group sftp #匹配sftp组
ChrootDirectory /sftp/%u #定义组目录
X11Forwarding no
AllowTcpForwarding no
#ForceCommand internal-sftp -l INFO -f local5
#ForceCommand internal-sftp -l INFO -f AUTH
ForceCommand internal-sftp -l INFO -f AUTH -u 2
[root@sftp ~]# mkdir /sftp
[root@sftp ~]# groupadd sftp
[root@sftp ~]# systemctl restart sshd
创建sftp用户 含创建脚本
[root@sftp ~]# vim create_sftp_user.sh
创建脚本
#!/bin/bash
##################################################################
# 用于创建 sftp 用户
# LastUpdate:
# Mender:
# updateDescription: 创建sftp账号须将对方的公钥放于我对应账户下
#################################################################
curr_user=$(whoami)
if [ ${curr_user} != "root" ];then
echo -e "\n 请使用 root 用户执行该脚本 .\n"
exit
fi
Usage(){
echo -e "\n Usage : sh create_sftp_user.sh UserName [ GroupName ] \n"
}
if [ $# -lt 1 ];then
Usage
exit
fi
UserName=$1
if [[ ${UserName} =~ ^[a-z][a-z0-9_]+$ ]];then
:
else
echo -e "\n 用户名不合规范 .\n"
exit
fi
id ${UserName} &>/dev/null
if [ $? -eq 0 ];then
echo -e "\n 该用户已存在或者非法,请检查.\n"
exit
fi
if [ $# -eq 1 ];then
GroupName=sftp
else
GroupName=$2
egrep -q "^${GroupName}\:" /etc/group
if [[ $? -ne 0 ]];then
echo -e "\n ${GroupName} 用户组不存在 .\n"
exit
fi
fi
useradd -s /sbin/nologin ${UserName}
usermod -g ${GroupName} -G ${UserName} ${UserName}
echo -e "\n 创建用户 完成 .\n"
passwd -x 9999 ${UserName}
echo -e "\n 设置20年不过期 完成 .\n"
ssh_dir=/home/${UserName}/.ssh
key_dir=/opt/sshkey/${UserName}
mkdir -p ${ssh_dir} ${key_dir}
ssh-keygen -t rsa -P '' -f ${key_dir}/${UserName}
echo -e "\n 生成密钥对 完成 ."
cat ${key_dir}/${UserName}.pub >>${ssh_dir}/authorized_keys
echo -e "\n 配置公钥授信 完成 ."
chown ${UserName}.${GroupName} /home/${UserName}/.ssh -R
chmod 755 ${ssh_dir}
chmod 600 ${ssh_dir}/authorized_keys
echo -e "\n 权限配置 完成 ."
if [ $# -eq 1 ];then
mkdir -p /sftp/${UserName}/{upload,download}
chmod 755 /sftp/${UserName}
chown ${UserName}.${GroupName} /sftp/${UserName}/{upload,download}
echo -e "\n sftp目录以及权限配置 完成 ."
else
mkdir -p /sftp/${GroupName}/${UserName}/{upload,download}
chmod 755 /sftp/${GroupName}/${UserName}
chmod 775 /sftp/${GroupName}/${UserName}/*
chown ${UserName}.${GroupName} /sftp/${GroupName}/${UserName}/{upload,download}
echo -e "\n sftp目录以及权限配置 完成 ."
fi
cp ${key_dir}/${UserName} /tmp/
echo -e "\n\n [ 密钥文件位于 /tmp/${UserName} ,请将该私钥文件导出,放置于客户端服务器上 ]\n\n"
echo -e "\n\n [ 请将合作方公钥文件内容追加至/home/${UserName}/.ssh/authorized_keys中 ]\n\n"
创建用户 testuser
进行测试
[root@sftp ~]# chmod +x create_sftp_user.sh
[root@sftp ~]# ./create_sftp_user.sh testuser
创建用户 完成 .
调整用户密码老化数据testuser。
passwd: 操作成功
设置20年不过期 完成 .
Generating public/private rsa key pair.
Your identification has been saved in /opt/sshkey/testuser/testuser.
Your public key has been saved in /opt/sshkey/testuser/testuser.pub.
The key fingerprint is:
SHA256:4uldZ+yj/o2yOzMuLnZ8Ia0OTR6ZNeW0oreZZ5cO2EA root@sftp
The key's randomart image is:
+---[RSA 2048]----+
| o |
| + . |
| E o |
| * o |
| . S.o |
| . *.ooO . |
| +.oo*.O o |
| .oo=.**.* |
| ..=+=*X+.o |
+----[SHA256]-----+
生成密钥对 完成 .
配置公钥授信 完成 .
权限配置 完成 .
sftp目录以及权限配置 完成 .
[ 密钥文件位于 /tmp/testuser ,请将该私钥文件导出,放置于客户端服务器上 ]
[ 请将合作方公钥文件内容追加至/home/testuser/.ssh/authorized_keys中 ]
使用测试机器client进行登陆测试
[root@client ~]# scp root@192.168.10.10:/tmp/testuser ./
root@192.168.10.10's password:
testuser 100% 1679 1.0MB/s 00:00
[root@client ~]# echo "This is a test file" >testfile.txt
[root@client ~]# sftp -i testuser testuser@192.168.10.10
Connected to 192.168.10.10.
sftp> ls
download upload
sftp> cd upload/
sftp> put testfile.txt
Uploading testfile.txt to /upload/testfile.txt
testfile.txt 100% 20 29.0KB/s 00:00
server端查看
[root@sftp ~]# cd /sftp/testuser/upload/
[root@sftp upload]# ls
testfile.txt
[root@sftp upload]# cat testfile.txt
This is a test file
创建sftp服务
清除之前的环境,还原机器
创建sftp服务的配置文件
可以直接复制sshd_config进行修改
[root@sftp ~]# cd /etc/ssh/
[root@sftp ssh]# cat sftpd_config
Port 23456
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
MaxSessions 200
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication yes
ChallengeResponseAuthentication no
GSSAPIAuthentication no
GSSAPICleanupCredentials no
UsePAM yes
X11Forwarding yes
TCPKeepAlive yes
ClientAliveInterval 120
ClientAliveCountMax 0
UseDNS no
PidFile /var/run/sftpd.pid
MaxStartups 2000
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem sftp internal-sftp -l INFO -f AUTH
Match Group sftp
ChrootDirectory /sftp/%u
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp -l INFO -f AUTH
#AllowGroups sftp2 sftp
#Match User sftp2
#ChrootDirectory /sftp/sftp2
#X11Forwarding no
#AllowTcpForwarding no
#ForceCommand internal-sftp -l INFO -f AUTH -u 2
#Match Group sftp2
#ChrootDirectory /sftp/sftp2/%u
#X11Forwarding no
#AllowTcpForwarding no
#ForceCommand internal-sftp -l INFO -f AUTH -u 2
创建sftp服务关键文件
[root@sftp ~]# vim /etc/ssh/sshd_config
132 # Subsystem sftp /usr/libexec/openssh/sftp-server
[root@sftp ~]# mkdir /sftp
[root@sftp ~]# groupadd sftp
[root@sftp ~]# cp /usr/sbin/sshd /usr/sbin/sftpd
[root@sftp ~]# cp /etc/pam.d/sshd /etc/pam.d/sftpd
[root@sftp ~]# cp /etc/sysconfig/sshd /etc/sysconfig/sftpd
[root@sftp ~]# cp /usr/lib/systemd/system/sshd.service /usr/lib/systemd/system/sftpd.service
[root@sftp ~]# vim /usr/lib/systemd/system/sftpd.service
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service
Wants=sshd-keygen.service
[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/sftpd
PIDFile=/var/run/sftpd.pid
ExecStart=/usr/sbin/sftpd -D $OPTIONS -f /etc/ssh/sftpd_config
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target
启动sftpd服务
[root@sftp ~]# systemctl restart sftpd.service
[root@sftp ~]# systemctl status sftpd.service
● sftpd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sftpd.service; disabled; vendor preset: disabled)
Active: active (running) since 六 2023-01-07 16:32:41 CST; 6s ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 2679 (sftpd)
CGroup: /system.slice/sftpd.service
└─2679 /usr/sbin/sftpd -D -f /etc/ssh/sftpd_config
1月 07 16:32:41 sftp systemd[1]: Starting OpenSSH server daemon...
1月 07 16:32:41 sftp sftpd[2679]: Server listening on 0.0.0.0 port 23456.
1月 07 16:32:41 sftp sftpd[2679]: Server listening on :: port 23456.
1月 07 16:32:41 sftp systemd[1]: Started OpenSSH server daemon.
[root@sftp ~]# netstat -anpt | grep 2345
tcp 0 0 0.0.0.0:23456 0.0.0.0:* LISTEN 2679/sftpd
tcp6 0 0 :::23456 :::* LISTEN 2679/sftpd
使用上面脚本创建用户
[root@sftp ~]# sh create_sftp_user.sh sftp_testuser
访问测试
[root@client ~]# scp root@192.168.10.10:/tmp/sftp_testuser ./
root@192.168.10.10's password:
sftp_testuser 100% 1679 2.1MB/s 00:00
[root@client ~]# sftp -P 23456 -i ./sftp_testuser sftp_testuser@192.168.10.10
Connected to 192.168.10.10.
sftp> ls
download upload
sftp> cd upload/
sftp> put test_file.txt
Uploading test_file.txt to /upload/test_file.txt
test_file.txt 100% 20 30.0KB/s 00:00
sftp-server
与 internal-sftp
sftp-server 和 internal-sftp 都是 OpenSSH 的一部分。 sftp-server 是一个独立的二进制文件。 internal-sftp 只是一个配置参数,它告诉 sshd 使用 sshd 内置的 SFTP 服务器代码,而不是像sftp-server运行另一个进程。
与独立的 sftp-server 二进制文件相比, internal-sftp 的诞生时间要晚得多(2008 年的 OpenSSH 4.9p1)。在新版的redhat8及centos8中internal-sftp已经成为默认,保留sftp-server的目的只是为了更好的兼容。
从功能的角度来看,sftp-server和internal-sftp几乎完全相同。 它们是使用相同的源代码构建的。
internal-sftp的主要优点是,当与ChrootDirectory指令一起使用时,它不需要任何支持文件。
对于Subsystem指令:
指定sftp-server实现SFTP文件传输子系统或者internal-sftp实现进程内SFTP服务,这可以简化使用ChrootDirectory强制配置以在客户端上强制使用不同的文件系统root的配置。
对于ForceCommand指令:
指定internal-sftp命令将强制使用与ChrootDirectory一起使用时不需要支持文件的进程内SFTP服务。
对于ChrootDirectory指令:
ChrootDirectory必须包含支持用户会话所需的文件和目录。对于交互式会话,这至少需要一个shell(通常是sh)和基本/ dev节点,例如null,zero,stdin,stdout,stderr和tty设备。对于使用SFTP的文件传输会话,如果使用进程内sftp服务器,则无需对环境进行其他配置,但使用日志记录的会话可能需要在某些操作系统上的chroot目录中使用/ dev / log(请参阅sftp-server以获取细节)。
例:
通过internal-sftp的ChrootDirectory实现限制sftp_users用户组内的用户目录
# For normal SFTP(Without Chroot) add the following configuration in sshd_config file.
Subsystem sftp /usr/libexec/openssh/sftp-server -P remove,rmdir,rename,posix-rename
# For Chroot SFTP add the following configuration in sshd_config file.
Subsystem sftp internal-sftp
Match Group sftp_users
ChrootDirectory %h
ForceCommand internal-sftp -P remove,rmdir,rename,posix-rename
X11Forwarding no
AllowTcpForwarding no
此处的ChrootDirectory中的 %h代表的是home,即用户的家目录