Linux-sftp文件传输

什么是sftp

sftp是Secure File Transfer Protocol的缩写,安全文件传送协议。
sftp与ftp有着几乎一样的语法和功能,但它可以为传输文件提供一种安全的加密方法,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的ftp要低得多,如果您对网络安全性要求更高时,可以使用sftp代替ftp。
sftp是SSH的一部分,其实在SSH软件包中,已经包含了一个叫作sftp的安全文件传输子系统,sftp本身没有单独的守护进程,它必须使用sshd守护进程(端口号默认是22)来完成相应的连接操作,所以从某种意义上来说,sftp并不像一个服务器程序,而更像是一个客户端程序。

启用sftp

必要条件

服务器安装的 openssh-server 版本至少得 4.8p1, 因为配置权限需要版本添加的新配置项 ChrootDirectory 来完成。

如何查看自己服务器上的ssh版本?尝试以下命令

1
ssh -V

实施步骤

1.检查sshd服务是否启用
比如在centos7上,使用systemctl status sshd命令查看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@server01 ~]# systemctl status sshd
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2022-03-29 21:59:41 CST; 1 months 29 days ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 885 (sshd)
CGroup: /system.slice/sshd.service
└─885 /usr/sbin/sshd -D

Mar 29 22:05:45 server01 sshd[1667]: Accepted password for root from 192.168.128.10 port 4006 ssh2
Mar 29 22:05:55 server01 sshd[1683]: Accepted password for root from 192.168.128.10 port 4008 ssh2
May 28 17:13:24 server01 sshd[2500]: Accepted password for hadoop from 192.168.128.10 port 10310 ssh2
May 28 17:13:35 server01 sshd[2510]: Accepted password for hadoop from 192.168.128.10 port 10323 ssh2
May 28 17:37:12 server01 sshd[2818]: Accepted password for hadoop from 192.168.128.10 port 10115 ssh2
May 28 17:42:32 server01 sshd[2900]: Accepted password for hadoop from 192.168.128.10 port 10613 ssh2
May 28 18:10:57 server01 sshd[3263]: Accepted password for root from 192.168.128.10 port 11028 ssh2
May 28 18:11:08 server01 sshd[3271]: Accepted password for root from 192.168.128.10 port 11030 ssh2
May 28 21:24:54 server01 sshd[4096]: Accepted password for root from 192.168.128.10 port 1193 ssh2
May 28 21:25:04 server01 sshd[4104]: Accepted password for root from 192.168.128.10 port 1196 ssh2

2.创建sftp组

1
groupadd sftp

3.创建一个用户sftpuser

1
useradd -g sftp -s /sbin/nologin sftpuser

选项说明:
-g : 将用户添加到’sftp’用户组。
-s : 设置用户的shell,默认是/bin/bash,这里是将sftpuser用户的默认shell设置为’/sbin/nologin’,这意味着该用户无法通过ssh方式登录服务器。

/bin/false的作用与/sbin/nologin类似,都是禁止用户登录服务器,两者的区别是:

  • /bin/false:是最严格的禁止登录设置。当用户设置为/bin/false时,执行登录操作则什么也不做只是返回一个错误状态,然后立即退出。所以将用户的shell设置为/bin/false,用户会无法登录,并且不会有任何提示。
  • /sbin/nologin:当用户的shell设置为 /sbin/nologin时,指定登录时会礼貌的向用户显示一条信息,并拒绝用户登录:This account is currently not available.

有一些软件,比如一些ftp服务器软件,对于本地非虚拟账户,只有用户有有效的shell才能使用ftp服务。这时候就可以使用/sbin/nologin使用户即不能登录系统,还能使用一些系统服务,比如ftp服务。/bin/false则不行,这是二者的重要区别之一。所以这里选择/sbin/nologin是比较合理的。

4.设置sftpuser用户的密码
执行passwd sftpuser命令设置密码。

1
2
3
4
5
6
7
[root@server01 ~]# passwd sftpuser
Changing password for user sftpuser.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.
[root@server01 ~]#

5.创建sftp根目录(root用户下创建)
创建此目录:/opt/sftp/data,这个目录将作为sftp服务的根目录。

1
mkdir -p /opt/sftp/data

6.配置sshd_config

1
vim /etc/ssh/sshd_config

找到如下这行,并注释掉,作用是禁用独立的“sftp-server”功能。

1
#Subsystem sftp /usr/libexec/openssh/sftp-server

并将以下配置粘贴到底部。

1
2
3
4
5
6
7
Subsystem sftp internal-sftp

Match User sftpuser # 此处设置控制的用户,也可以设置为组
ChrootDirectory /opt/sftp/data # #sftp主目录指定到/opt/sftp/data
X11Forwarding no # 用户不能使用端口转发
AllowTCPForwarding no # 用户不能使用端口转发
ForceCommand internal-sftp # 指定sftp命令

保存配置并退出。可以通过sshd -t命令测试配置文件是否正确,无任何输入则正确。

配置说明:

  • Subsystem sftp internal-sftp:指定使用sftp服务使用系统自带的“internal-sftp”,而不是使用子进程“sftp-server”。
    为什么用 internal-sftp 而不用默认的 sftp-server,这是因为:1) 这是一个进程内的 sftp 服务,当用户 ChrootDirectory 的时候,将不请求任何文件;2)更好的性能,不用为 sftp 再开一个进程。
  • Match User sftpuser:为用户“sftpuser”启用了sftp服务器。这里也可以配置成Match Group sftp,意思是为组“sftp”启用了 SFTP 服务器。如果要匹配多个组,多个组之间用逗号分割。
  • ChrootDirectory /opt/sftp/data:用chroot命令(英文全称:change root)将用户的根目录指定到/opt/sftp/data ,这样用户就只能在/opt/sftp/data下活动。

7.设置主目录权限

1
2
chown root:sftp /opt/sftp/data/   # 文件夹所有者必须为root,用户组可以不是root
chmod 755 /opt/sftp # 权限不能超过755,否则会导致登录报错,可以是755

8.重启sshd

1
systemctl restart sshd

9.关闭SELinux
查看SELinux状态:

  1. /usr/sbin/sestatus -v #如果SELinux status参数为enabled即为开启状态
    SELinux status: enabled
  2. getenforce #也可以用这个命令检查

如何关闭SELinux呢?有两种方式:临时关闭和永久关闭。
临时关闭(重启机器后失效):

1
setenforce 0        # setenforce 0设置为permissive模式;setenforce 1 设置为enforcing模式;

永久关闭(需要重启机器):
修改/etc/selinux/config文件,将SELINUX=enforcing改为SELINUX=disabled。
SELinux共有3个模式:enforcing (执行中)、permissive (不执行但产生警告)、disabled(关闭)。

关于为什么要关闭这功能,可以参考:https://www.zhihu.com/question/20559538

10.登录sftp(linux/Windows)

1
sftp sftpuser@ip地址

可以看到我们使用sftp命令可以连接成功,ssh则会连接失败。

如果连接不上,请先试用ping命令看两台服务器是否连通。

其它注意事项

  1. sftp是无法像ftp一样直接在浏览器地址栏打开的。
  2. 确保ChrootDirectory对应的根目录是root所有,权限是 750 或者 755。并且注意以下两点原则:
    • 这个根目录开始一直往上到系统根目录为止的目录拥有者都只能是 root,用户组可以不是 root。
    • 这个根目录开始一直往上到系统根目录为止都不可以具有群组写入权限。

sftp使用

前一节已经成功地连接上了sftp服务器,接下来讲一讲该怎么来使用了。

sftp命令

首先sftp连接成功之后,可以执行如下的一些命令。

  • help:查看帮助。
  • bye/exit/quit:这三个命令的功能是一样的,都是关闭当前SFTP连接。
  • ls:显示远程目录下文件。
  • lls:显示本地当前目录下文件。
  • cd:切换远程目录。
  • lcd:切换本地目录。
  • pwd:显示当前远程所在目录。
  • lpwd:显示本地当前所在目录。
  • rename:移动或重命名远程文件。(sftp帐户需要有远程目录的write权限)
  • mv:移动或重命名远程文件。(sftp帐户需要有远程目录的write权限)
  • rm:删除一个远程文件。(sftp帐户需要有远程目录的write权限)
  • rmdir:删除远程服务器目录。(sftp帐户需要有远程目录的write权限)
  • put:上传文件,如果要上传整个目录,使用put -r ${本地目录名称} ${远程目录名称},并且远程服务器上也需要创建一个和本地目录名称一样的目录。(sftp帐户需要有远程目录的write权限)
  • get:从服务器端下载文件。如果要下载整个远程目录,使用get -r ${远程目录名称}

上传与下载的权限

有时我们需要对sftp远程目录的权限做控制,比如对于某个目录,sftp帐户只能下载,而不能修改或上传里面的内容,如果sftp帐户需要上传,只能上传到另外一个目录。下面来操作一下,前面已经说到/opt/sftp/data这个目录是作为sftp服务器的根目录,我们在这个根目录下创建一个download目录,只用于下载,另外再创建一个can_any目录,sftp帐户即可以下载这个目录下的文件,也可以上传文件到该目录。其实做法很简单,就是把download目录的所有者设置为root,把can_any目录的所有者设置为sftp的帐户(本文中就是sftpuser这个用户)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@server01 data]# mkdir download
[root@server01 data]# cd download/
[root@server01 download]# touch downloadfile_01
[root@server01 download]# touch downloadfile_02
[root@server01 download]# ls -lh
total 0
-rw-r--r-- 1 root root 0 May 29 08:00 downloadfile_01
-rw-r--r-- 1 root root 0 May 29 08:00 downloadfile_02
[root@server01 download]# cd ..
[root@server01 data]# mkdir can_any
[root@server01 data]# chown sftpuser:sftp can_any/
[root@server01 data]# ls -lh
total 4.0K
-rw-r--r-- 1 root root 19 May 29 00:05 aaa.txt
-rw-r--r-- 1 root root 0 May 28 23:57 bbb.txt
drwxr-xr-x 2 sftpuser sftp 6 May 29 08:00 can_any
drwxr-xr-x 2 root root 52 May 29 08:00 download

在sftp服务器上操作完之后,用sftp帐户远程登录,操作如下

------ 本文完 ------