sftp和ftp是两种不同的文件传输协议,sftp是基于ssh协议的加密ftp传输协议,是作为SSH2的一个子服务工作的,只要sshd服务器启动了它就可用。vsftpd是一款ftp服务器,支持ftp协议,不支持sftp协议。
SFTP工作模式
搭建sftp环境
1.查看openssh软件版本
sftp服务用户只能访问特定的文件目录,需要openssh的版本在4.8以上
[root@localhost ~]# rpm -qa|grep -i openssh openssh-5.3p1-94.el6.x86_64 openssh-clients-5.3p1-94.el6.x86_64 openssh-server-5.3p1-94.el6.x86_64 openssh-askpass-5.3p1-94.el6.x86_64 [root@localhost ~]# ssh -V OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 [root@localhost ~]#
2.新增用户、创建sftp的根目录、文件上传目录data
[root@localhost ~]# groupadd sftp [root@localhost ~]# useradd -g sftp -s /sbin/nologin justin [root@localhost ~]# echo "51cto" | passwd --stdin justin 更改用户 justin 的密码 。 passwd: 所有的身份验证令×××已经成功更新。 [root@localhost ~]# mkdir -p /app/share [root@localhost ~]# ll -d !$ ll -d /app/share drwxr-xr-x 2 root root 4096 5月 21 18:41 /app/share [root@localhost ~]# cd /app/share/ [root@localhost share]# mkdir data [root@localhost share]# chmod a+w .
ftp的根目录默认不允许设置为777权限,可以是权限是 750 或者 755,且必须是root用户所有,否则ftp将无法访问。如果属组或者其他用户需要上传文件,可以在FTP的根目录下创建个上传文件夹,这个文件夹权限可以根据实际情况修改。
由ChrootDirectory指定的目录开始一直往上到系统根目录为止的目录拥有者都只能是root。
指定Match Group sftp_group的用户目录属组必须是sftp_group,且只有属主能拥有写权限,权限最大设置只能是755。如果不能遵循这2点,即使是该目录仅属于某个用户,也可能会影响到所有的SFTP用户。
新建用户的家目录,权限是700,但这样sftp登陆的话,是看不到目录下的列表的,所以,需要修改成750或者755的权限.错误的目录权限设定会导致在log中出现”fatal: bad ownership or modes for chroot directory XXXXXX”的内容
3.配置sshd_config
[root@localhost ~]# cp /etc/ssh/sshd_config{,29170521bak} [root@localhost ~]# vim /etc/ssh/sshd_config 132 #Subsystem sftp /usr/libexec/openssh/sftp-server 注释掉改行 133 Subsystem sftp internal-sftp #新增该行 134 Match User justin #多个用户名之间用逗号分割 135 X11Forwarding no #如果不希望该用户能使用端口转发的话就加上这2行,加你no 136 ForceCommand internal-sftp 137 ChrootDirectory /app/share #多用户使用ChrootDirectory /home/%u指定目录 [root@localhost ~]# service sshd restart
Match Group sftpusers 指定用户组sftpusers
ChrootDirectory /app/share 设置chroot将用户锁在家目录,%h=家目录 ForceCommand internal-sftp 该参数强制执行内部sftp
X11Forwarding yes X11转发允许在 SSH 客户端上显示应用程序的图形部分,而程序逻辑依然在远程服务器上执行.
注意:当前重启这个服务的窗口千百万不能关闭,如果配置错误,ssh重启失败,你可能就进不去了,就得到机房中弄了。
4、客户端登陆验证
[root@localhost ~]# sftp justin@10.15.43.197 Connecting to 10.15.43.197... justin@10.15.43.197's password: Write failed: Broken pipe Couldn't read packet: Connection reset by peer [root@localhost ~]#
这个问题是ChrootDirectory的权限问题,由ChrootDirectory指定的目录开始一直往上到系统根目录为止的目录拥有者都只能是root,权限最大设置只能是755。
查看sftp服务端
[root@localhost share]# ll -d drwxr-xr-x 3 root root 4096 5月 22 10:12 . [root@localhost share]# chmod a+w . [root@localhost share]# ll -d drwxrwxrwx 3 root root 4096 5月 22 10:12 . [root@localhost share]# ll -d /app/share/ drwxrwxrwx 3 root root 4096 5月 22 10:12 /app/share/ [root@localhost share]# chmod 755 /app/share/ [root@localhost share]# chmod 755 /app/share/ [root@localhost share]# ll -d drwxr-xr-x 3 root root 4096 5月 22 10:12 . [root@localhost share]# chmod a+w data [root@localhost share]# ll 总用量 4 drwxrwxrwx 2 root root 4096 5月 22 10:12 data [root@localhost share]#
上面修改data目录权限时候误操作了sftp的根目录
修改后可以正常上传文件
[root@localhost ~]# sftp justin@10.15.43.197 Connecting to 10.15.43.197... justin@10.15.43.197's password: Permission denied, please try again. justin@10.15.43.197's password: sftp> ls data sftp> put /root/sftp.txt Uploading /root/sftp.txt to /data/sftp.txt /root/sftp.txt 100% 5 0.0KB/s 00:00 sftp> ls
至此,可以客户端可以通过密码方式访问sftp服务
5、配置通过RSA/DSA密钥认证
除了可以用UNIX密码(unix passwd/shadow)方式访问sftp外,还可以选择RSA/DSA密钥认证方式访问sftp.
RSA:由RSA公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的;
DSA(Digital Signature Algorithm):数字签名算法,是一种标准的 DSS(数字签名标准);同时这两种加密算法都是非对称加密算法.
服务端通过下面两个选项来控制是否采用公/密钥的方式进行身份验证
RSA密钥认证
5.1、sftp服务端:
服务端通过下面48、49两个选项来控制是否采用公/密钥的方式进行身份验证,66选项为sftp的访问方式,设置为no为强制使用密钥访问,而不是用户名及密码,设置为yes则表示密钥或帐号密码都可以访问,该项为全局的,设置为yes后可以在后面具体哪个组或者用户访问权限里单独设置。如果设置为no就只能使用密码访问。
[root@localhost ~]# cat /etc/ssh/sshd_config 48 PubkeyAuthentication yes #改成PubkeyAuthentication no则关闭公/私钥认证 49 AuthorizedKeysFile %h/.ssh/authorized_keys 66 PasswordAuthentication yes [root@localhost ~]# service sshd restart
%h 表示用户家目录
5.2、客户端:
用ssh-keygen生成一对RSA(公/私钥),将公钥COPY到Sftp服务端。
[root@localhost ~]# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): #密钥存放位置 Enter passphrase (empty for no passphrase): #直接回车密码为空,如果设置了需要记住该密码,后面会用到 Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. #私钥 Your public key has been saved in /root/.ssh/id_rsa.pub. #公钥 The key fingerprint is: 96:b1:3f:f7:4f:3c:ea:16:cd:81:23:35:fc:66:44:62 root@localhost.localdomain The key's randomart image is: +--[ RSA 2048]----+ | .E.. | | .+.. | | . . = | | + . o = | | S . * .| | . . . + | | o . ..o| | o o...| | oo...| +-----------------+ [root@localhost ~]# cd /root/.ssh/ [root@localhost .ssh]# ls id_rsa id_rsa.pub [root@localhost .ssh]# ssh-copy-id -i id_rsa.pub justin@10.15.43.197 justin@10.15.43.197's password: Now try logging into the machine, with "ssh 'justin@10.15.43.197'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. [root@localhost .ssh]#
这样在/root/.ssh/下生成两个文件id_rsa及id_rsa.pub,其中id_rsa是私钥,id_rsa.pub是公钥,私钥是客户端用的,将公钥通过ssh-copy-id命令把本机的公钥追到要登陆IP的对应账号justin的 .ssh/authorized_keys里
ssh-copy-id 将公共密钥填充到一个远程机器上的authorized_keys文件中,也会给远程主机的用户主目录(home)和~/.ssh, 和~/.ssh/authorized_keys设置合适的权限。
ssh-copy-id [-i [identity_file]] [user@]machine
-i:指定公钥文件
如果ssh的端口不是22,可用下面命令
[root@localhost .ssh]# ssh-copy-id -i id_rsa.pub "-p 23 justin@10.15.43.197"
authorized_keys的权限检查
StrictModes指定是否要求在接受连接请求前对用户主目录和相关的配置文件进行宿主和权限检查。
authorized_keys的默认权限是600,~/.ssh目录权限是700,修改成其他的将无法通过,我手动设置成755后无法通过密钥验证,打开strictmodes选项,此时提示输入密码
sftp服务端
[root@localhost .ssh]# vim /etc/ssh/sshd_config strictmodes yes [root@localhost .ssh]# service sshd restart
client端
[root@localhost ~]# sftp justin@10.15.43.197 Connecting to 10.15.43.197... justin@10.15.43.197's password:
5.3、sftp服务端
[root@localhost ~]# cd /home/justin/.ssh/ [root@localhost .ssh]# ls id_rsa.pub [root@localhost .ssh]# cat id_rsa.pub >> authorized_keys [root@localhost .ssh]# ls authorized_keys id_rsa.pub [root@localhost .ssh]# service sshd restart
现在客户端可以通过密钥无密码的访问sftp了
客户端
[root@localhost .ssh]# sftp justin@10.15.43.197 Connecting to 10.15.43.197... sftp> pwd Remote working directory: / sftp> ls data sftp> cd data sftp> ls sftp.txt sftp>quit [root@localhost .ssh]# ssh keygen@10.15.43.100 [keygen@localhost ~]$
至此,RSA密钥认证成功,如果后面重装过系统,可能会认证失败,需要清除以前的记录
[root@localhost .ssh]# ssh-keygen -R 192.168.100.132
[root@localhost .ssh]# ssh-keygen -R 192.168.100.132
6、SSH的日志级别
SSH有如下9个日志级别:QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.默认是INFO,DEBUG和DEBUG1是等价的,DEBUG级别一般用于调试.
LogLevel INFO
[root@localhost .ssh]# tail -f /var/log/secure May 23 11:17:18 localhost sshd[62460]: pam_unix(sshd:session): session opened for user justin by (uid=0) May 23 11:17:18 localhost sshd[62462]: subsystem request for sftp
LogLevel VERBOSE
[root@localhost .ssh]# vim /etc/ssh/sshd_config LogLevel VERBOSE [root@localhost .ssh]# service sshd restart [root@localhost .ssh]# tail -f /var/log/secure May 23 13:57:12 localhost sshd[63363]: Set /proc/self/oom_score_adj to 0 May 23 13:57:12 localhost sshd[63363]: Connection from 10.15.43.124 port 56573 May 23 13:57:12 localhost sshd[63363]: Found matching RSA key: 96:b1:3f:f7:4f:3c:ea:16:cd:81:23:35:fc:66:44:62 May 23 13:57:12 localhost sshd[63364]: Postponed publickey for justin from 10.15.43.124 port 56573 ssh2 May 23 13:57:12 localhost sshd[63363]: Found matching RSA key: 96:b1:3f:f7:4f:3c:ea:16:cd:81:23:35:fc:66:44:62 May 23 13:57:12 localhost sshd[63363]: Accepted publickey for justin from 10.15.43.124 port 56573 ssh2 May 23 13:57:12 localhost sshd[63363]: pam_unix(sshd:session): session opened for user justin by (uid=0) May 23 13:57:12 localhost sshd[63363]: User child is on pid 63365 May 23 13:57:12 localhost sshd[63365]: Changed root directory to "/app/share" May 23 13:57:12 localhost sshd[63365]: subsystem request for sftp
LogLevel VERBOSE
[root@localhost ~]# vim /etc/ssh/sshd_config LogLevel VERBOSE [root@localhost ~]# /etc/init.d/sshd restart [root@localhost .ssh]# tail -f /var/log/secure May 23 11:21:06 localhost sshd[62620]: Set /proc/self/oom_score_adj to 0 May 23 11:21:06 localhost sshd[62620]: Connection from 10.15.43.124 port 53422 May 23 11:21:06 localhost sshd[62620]: Found matching RSA key: 96:b1:3f:f7:4f:3c:ea:16:cd:81:23:35:fc:66:44:62 May 23 11:21:06 localhost sshd[62621]: Postponed publickey for justin from 10.15.43.124 port 53422 ssh2 May 23 11:21:06 localhost sshd[62620]: Found matching RSA key: 96:b1:3f:f7:4f:3c:ea:16:cd:81:23:35:fc:66:44:62 May 23 11:21:06 localhost sshd[62620]: Accepted publickey for justin from 10.15.43.124 port 53422 ssh2 May 23 11:21:06 localhost sshd[62620]: pam_unix(sshd:session): session opened for user justin by (uid=0) May 23 11:21:06 localhost sshd[62620]: User child is on pid 62622 May 23 11:21:06 localhost sshd[62622]: Changed root directory to "/app/share" May 23 11:21:06 localhost sshd[62622]: subsystem request for sftp
/var/log/secure被删除后需要重启rsyslog、sshd服务。
[root@localhost .ssh]# service rsyslog restart ;service sshd restart
sftp日志
修改服务端ssh_conf文件
[root@justin ~]# vim /etc/ssh/sshd_config 33 LogLevel INFO 96 UsePAM yes 133 Subsystem sftp internal-sftp -l INFO -f local7 136 Match User justin 137 X11Forwarding no 138 ForceCommand internal-sftp -l INFO -f local7 139 ChrootDirectory /app/soft [root@justin ~]# vim /etc/rsyslog.conf auth,authpriv.*,local7.* /var/log/sftp.log [root@justin ~]# systemctl restart sshd [root@justin ~]# systemctl restart rsyslog
FTP over SSH2
FTP over SSH2协议是基于ftp协议的。在此协议中SSH2服务器起了一个桥梁作用,把数据在客户端和ftp之间转发。ftp协议本身包括两个通道,一个是控制通道,另一个是数据通道。FTP over SSH2有两种情况,半安全连接(Less Secure Connection)和安全连接(Full Secure Connection)。在半安全连接时,ftp客户端先和SSH2服务器连接,在这个连接中无论控制通道和数据通道都是加密的。但是SSH2服务器和 ftp服务器之间就不是加密的了。
1、SSH2服务器和FTP服务器在同一台服务器上
安全连接
2、SSH2服务器和FTP服务器在多台服务器上
如果ftp服务器运行在另外一台机器上,SSH2服务器和ftp直接就是明文传输。
半安全连接
1、FTP架构
如同其他的很多通讯协议,FTP通讯协议也采用客户机 / 服务器(Client / Server )架构。用户可以通过各种不同的FTP客户端程序,借助FTP协议,来连接FTP服务器,以上传或者下载文件。
2、FTP通讯端口知识
FTP服务器和客户端要进行文件传输,就需要通过端口来进行。FTP协议需要的端口一般包括两种:
控制链路--------TCP端口21
所有你发往FTP服务器的命令和服务器反馈的指令都是通过服务器上的21端口传送的。
数据链路--------TCP端口20
数据链路主要是用来传送数据的,比如客户端上传、下载内容,以及列目录显示的内容等。
3、FTP连接的两种方式
在数据链路的建立上,FTP Server为了适应不同的网络环境,支持两种连接模式:主动模式(Port)和被动模式(Pasv)。其实这两种连接模式主要是针对数据链路进行的,和控制链路无关。
PORT(主动模式)
FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时,客户端随机开放一个端口(1024以上),发送 PORT命令到FTP服务器,告诉服务器客户端采用主动模式并开放端口;FTP服务器收到PORT主动模式命令和端口号后,通过服务器的20端口和客户端开放的端口连接,发送数据,原理如下图:
采用主动模式连接服务器的客户端,当它位于NAT或者防火墙的保护之后时会碰到连接失败的问题。这是因为当防火墙接到服务器发送过来的信息的时候,并不知道应该发送给内部网络中的哪一台客户端造成的。
PASV(被动模式)
FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时,发送PASV命令到FTP服务器, 服务器在本地随机开放一个端口(1024以上),然后把开放的端口告诉客户端, 客户端再连接到服务器开放的端口进行数据传输,原理如下图:
从上面的解释中我们可以看到, 主动模式传送数据时是“服务器”连接到“客户端”的端口;被动模式传送数据是“客户端”连接到“服务器”的端口。主动模式需要客户端必须开放端口给服务器,很多客户端都是在防火墙内,开放端口给FTP服务器访问比较困难。被动模式只需要服务器端开放端口给客户端连接就行了。
连接采用何种模式是有FTP客户端软件决定。