Linux sftp将用户限制为特定目录设置sftp chroot监狱

时间:2020-02-23 14:40:29  来源:igfitidea点击:

在本文中,将介绍有关如何在Linux中配置sftp服务器的分步指南,并提供详细说明以下主题的示例:

  • 在Linux上安装sftp

  • 配置sftp chroot

  • 创建sftp用户/创建sftp组

  • sftp将用户限制为特定目录

  • sftp chroot多个目录

sftp是类似于ftp的文件传输程序,它通过加密的ssh传输执行所有操作。

它还可能使用ssh的许多功能,例如公钥身份验证和压缩。

服务器环境

我已经在Linux服务器上的Oracle VirtualBox上使用CentOS 8创建了两个虚拟机。

我将使用这两个虚拟机来配置和验证sftp将用户限制为特定目录,并通过示例验证sftp chroot多个目录。
如果我们遇到任何问题,请使用此页面的注释部分告诉我,本文中的大多数步骤也应适用于其他Linux发行版,例如SuSE,Ubuntu等。

我们将在server2上配置sftp chroot监狱,并使用server1通过sftp用户hynman连接到server2

在Linux上安装sftp

在大多数Linux发行版中,应该默认安装sftp。
在RHEL/CentOS 7和8 Linux上,我们可以使用yum或者dnf安装sftp,它是RHEL/CentOS发行版中" openssh-clients" rpm的一部分。

提示:

根据发行版sftp可能属于不同的rpm,请检查发行版以安装sftp

[root@server1 ~]# which sftp
/usr/bin/sftp

建立SFTP使用者

我将为sftp创建sftp用户(" hynman"),以将用户限制为Linux在" server2"上的特定目录。

要创建sftp用户hynman,请使用以下命令。

[root@server2 ~]# useradd hynman

查看用户详细信息:

[root@server2 ~]# id hynman
uid=1003(hynman) gid=1003(hynman) groups=1003(hynman)

该用户的主目录由" hynman"拥有,并具有700个权限,因此除root用户外,其他用户都不能访问该目录。

[root@server2 ~]# ls -ld /home/hynman/
drwx------ 2 hynman hynman 4096 Mar 30 18:48 /home/hynman/

为sftp用户hynman分配密码:

[root@server2 ~]# passwd hynman
Changing password for user hynman.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

将sftp用户的shell更改为/bin/false而不是/bin/bash
没有有效的shell,将不允许sftp用户登录。

[root@server2 ~]# usermod --shell /bin/false hynman

验证用户的" hynman"属性

[root@server2 ~]# grep hynman /etc/passwd
hynman:x:1003:1003::/home/hynman:/bin/false

提示:

我们也可以使用useradd --shell/bin/false <username>在单个命令中创建没有有效shell的sftp用户

创建SFTP组(可选)

在本文中,为了演示sftp将用户限制到特定目录,我将使用sftp用户而不是sftp组。
但是,如果我们需要实现组级别的sftp chroot监狱,则还可以使用以下步骤创建sftp组:

[root@server2 ~]# groupadd sftpusers   <-- Here group name is "sftpusers"

将用户添加到此sftpusers组

[root@server2 ~]# usermod --gid sftpusers hynman  <-- Adding user "hynman" to group "sftpusers"

现在,我们可以将此组sftpusers用于sftp将用户限制到特定目录。

配置SFTP chroot监狱

要配置SFTP chroot监狱,我们将修改/etc/ssh/sshd_config

[root@server2 ~]# vim /etc/ssh/sshd_config
<output_trimmed>
#Comment sftp-server SubSystem and use internal-sftp
#Subsystem       sftp    /usr/libexec/openssh/sftp-server
Subsystem       sftp    internal-sftp
#Add this section to match for user "hynman"
Match user hynman
        ChrootDirectory /opt/sftp-jails/hynman    <-- Our sftp chroot jail directory
        X11Forwarding no
        AllowTcpForwarding no
        PermitTunnel no
        AllowAgentForwarding no
        ForceCommand internal-sftp

提示:

如果我们希望为Group配置sftp chroot监狱,则将Match user hynman替换为Match Group &lt;group_name>
其余部分可按需使用。
还要确认在同一配置文件中,OpenSSH是否配置为使用" internal-sftp"子系统:

其中

Match			Introduces a conditional block.  If all of the criteria on the Match line are satisfied, the keywords on the following lines 
			override those set in the global section of the config file, until either another Match line or the end of the file. If a 
			keyword appears in multiple Match blocks that are satisfied, only the first instance of the keyword is applied.
		
ChrootDirectory		The ChrootDirectory must contain the necessary files and directories to support the user's session. For an interactive session 
			this requires at least a shell, typically sh, and basic /dev nodes such as null, zero, stdin, stdout, stderr, and tty devices. 
			For file transfer sessions using SFTP no additional configuration of the environment is necessary if the in-process sftp-server
			is used, though sessions which use logging Jan require /dev/log inside the chroot directory on some operating systems.
					
X11Forwarding		This allows/denies the X11 forwarding. If set to yes, it can expose X11 to attacks; so this option must be taken with care. 
			Defaults to no. We prevent the forwarding to X11: there is no need for it and it can expose the system.
					
AllowTcpForwarding	This allow/denies TCP forwarding and can take as argument yes, all, no, or local and remote. The first two options allow the
			forwarding, the third denies it, and the local allows local forwarding only; remote enables remote forwarding only. There is 
			no shell or TCP forwarding for our example.
					
ForceCommand		Specifying a command of internal-sftp will force the use of an in-process SFTP server that requires no support files when 
			used with ChrootDirectory.
AllowAgentForwarding	Defines whether ssh-agent forwarding is allowed or not. Defaults to yes to increase the security, and since it is not really 
			needed for an sftp account, so we are going to disable it.
						
PermitTunnel	        This allows/denies the tunnel device forwarding. It takes yes, point-to-point , Ethernet, or no as arguments. Yes enables both 
			point-to-point and Ethernet forwarding. Defaults to no, and we want to be sure it is disabled since we do not need a tunnel for 
			an sftp account.					
SubSystem		The command sftp-server implements the SFTP file transfer subsystem. 
			Alternately the name internal-sftp implements an in-process SFTP server. This Jan simplify configurations using ChrootDirectory 
			to force a different filesystem root on clients.

为什么我们对ChrootDirectory使用internal-sftp而不是sftp-server?

收集自:OpenSSH:internal-sftp和sftp-server之间的区别

  • sftp-server和internal-sftp都是OpenSSH的一部分。
    sftp-server是一个独立的二进制文件。

  • " internal-sftp"只是一个配置关键字,它告诉sshd使用内置在sshd中的SFTP服务器代码,而不是运行另一个进程(通常是sftp-server)。

  • sftp-server现在是多余的,为了向后兼容而保留。

  • 内部sftp的主要优点是与ChrootDirectory指令一起使用时不需要支持文件。

  • 管理员可能依赖于登录shell程序配置来阻止某些用户登录。

  • 切换到" internal-sftp"将绕过该限制,因为不再涉及登录shell。

  • 使用sftp-server二进制文件(是一个独立的进程),我们可以使用一些技巧,例如在sudo下运行SFTP。

  • 对于SSH-1(如果有人还在使用它),根本不涉及Subsystem指令。

  • 使用SSH-1的SFTP客户端会明确告知服务器该服务器应运行的二进制文件。
    因此,传统的SSH-1 SFTP客户端具有" sftp-server"名称的硬编码。

接下来,重新启动sshd服务以激活sftp chroot监狱配置。

[root@server2 ~]# systemctl restart sshd

SFTP将用户限制为特定目录(使用密码身份验证)

.1:创建sftp chroot监狱目录

如果我们希望通过sftp限制用户主目录,则可以忽略这些步骤,而仅将/home/&lt;user>用作chroot监狱。
但是要覆盖sftp将用户限制到特定目录,我们需要一个目录结构。

在本文中,我们将在/opt/sftp-jails/<username>/exchange`上实现sftp chroot监狱。

[root@server2 ~]# mkdir -p /opt/sftp-jails

.2:在chroot监狱目录上分配权限

提示:

我们分配给sftp chroot目录的权限可能会根据要求而有所不同。
下面仅供参考,以对sftp进行POC(概念验证),将用户限制为特定目录。
我们可能会致命:sftp chroot监狱目录的权限的/var/log/messages中的chroot目录错误的所有权或者模式错误没有正确配置。

我们的sftp用户hynman将使用sftp登录到/opt/sftp-jails/&lt;username>

[root@server2 ~]# ls -ld /opt/sftp-jails/
drwxr-xr-x 3 root root 4096 Mar 30 18:29 /opt/sftp-jails/

用户将没有对/opt/sftp-jails/&lt;username>的写许可权。
在/opt/sftp-jails/<username> /下还有另一个目录交换,其中sftp用户将执行写操作。

[root@server2 ~]# ls -ld /opt/sftp-jails/hynman/
drwxr-xr-x 3 root root 4096 Mar 30 18:29 /opt/sftp-jails/hynman/

如我们所见,该用户目录由具有755许可权的root用户拥有,以允许用户hynman登录,而sftp将用户限制为特定目录/opt/sftp-jails/hynman

我们将用户所有者更改为" hynman",以允许他在此sftp chroot监狱目录中写入

[root@server2 ~]# chown hynman:root /opt/sftp-jails/hynman/exchange

还要将权限更改为750,以限制其他人在此" exchange"目录中写入

[root@server2 ~]# chmod 750 /opt/sftp-jails/hynman/exchange

验证权限:

[root@server2 ~]# ls -ld /opt/sftp-jails/hynman/exchange/
drwxr-x--- 2 hynman root 4096 Mar 30 18:29 /opt/sftp-jails/hynman/exchange/

下面是我们创建的用于配置sftp的目录树结构,将用户限制为特定目录

[root@server2 ~]# tree -paug /opt/
/opt/
└── [drwxr-xr-x root     root    ]  sftp-jails
    └── [drwxr-xr-x root     root    ]  hynman
        ├── [drwxr-x--- hynman   root    ]  exchange

.3:验证SSH和SFTP连接和权限

由于我们从server1阻止了sftp用户hynman的ssh访问,因此首先我们尝试使用hynman用户对SSH到server2进行操作,以确保此配置按预期工作。

[root@server1 ~]# ssh [email protected]
[email protected]'s password:
This service allows sftp connections only.
Connection to 10.10.10.13 closed.

正如预期的那样,此服务仅允许sftp连接。

如何修复packet_write_wait:连接到X.X.X.X端口22:管道断开?

如果配置有问题,则可能会得到packet_write_wait:连接到X.X.X.X端口22:管道错误而不是错误此服务仅允许sftp连接。
"

# ssh [email protected]
[email protected]'s password:
packet_write_wait: Connection to 10.10.10.13 port 22: Broken pipe

现在,此错误并未提供有关潜在问题的详细信息。
因此,在这种情况下,我们必须在我们尝试连接的服务器节点上检查/var/log/messages,对我们来说,这是server2
我们将使用journalctl分析错误packet_write_wait:与X的连接。

X.X.X端口22:管道损坏

使用journalctl -f我发现致命的错误:chroot目录的所有权或者模式错误

Mar 30 18:54:17 server2.example.com systemd[1]: Started User Manager for UID 1003.
Mar 30 18:54:17 server2.example.com sshd[10232]: pam_unix(sshd:session): session opened for user hynman by (uid=0)
Mar 30 18:54:17 server2.example.com sshd[10232]: fatal: bad ownership or modes for chroot directory "/opt/sftp-jails/hynman/exchange" [postauth]
Mar 30 18:54:17 server2.example.com sshd[10232]: pam_unix(sshd:session): session closed for user hynman

现在,此错误将导致致命错误:chroot目录本身的所有权不佳或者模式本身告诉我们,在/etc/ssh/sshd_config下提供的chroot目录的权限不正确。

在sshd_config的ChrootDirectory的手册页中,路径名的所有组件必须是root拥有的目录,任何其他用户或者组均不可写

因此,我们可以验证为chroot目录提供的权限,以解决致命问题:chroot目录的所有权或者模式不正确,并重新尝试ssh。

下次尝试使用" hynman"用户从" server1"到" server2"进行SFTP通信

[root@server1 ~]# sftp [email protected]
[email protected]'s password:
Connected to [email protected]. <-- The sftp connection is successful
sftp> pwd <-- Check your present working directory
Remote working directory: /
sftp> ls -lah		<-- List the directories and files in current directory
drwxr-xr-x    ? 0        0            4.0K Mar 30  2017 .
drwxr-xr-x    ? 0        0            4.0K Mar 30  2017 ..
drwxr-x---    ? 1003     0            4.0K Mar 30  2017 exchange
sftp> mkdir test <-- Create a directory named "test"
Couldn't create directory: Permission denied <-- Since there is no write permission for hynman user
                                                 in his home folder, he gets permission denied
sftp> cd exchange/<-- Navigate to exchange directory
sftp> mkdir hynman_dir <-- Create directory named hynman_dir
sftp> ls -l <-- List the directories and files in current directory
drwx------ 2 hynman hynman 4096 Mar 30 13:38 hynman_dir <-- Directory creation was successful
sftp> pwd <-- Present working directory
Remote working directory: /exchange
sftp> exit <-- To exit your session

第6步:设置无密码的sftpauthorized_keys

在上面的示例中,我们将sftp配置为将用户限制到特定目录,在该目录中,用户使用密码进行身份验证。
当我们尝试在脚本中使用sftp chroot jail来自动执行某些任务时,我们可能会遇到问题,因为每次sftp通信都会提示输入用户密码。

在此示例中,"我们将在服务器之间设置无密码的sftpauthorized_keys",以sftp将用户限制为特定目录。

.1:创建sftpauthorized_keys文件

server2上创建sftpauthorized_keys文件,该文件将存储来自server1的公钥内容。
其中我创建了一个隐藏文件夹.ssh,其中将创建authorized_keys文件。

提示:

我们可以使用任何路径来创建sftpauthorized_keys文件,但请确保sftp用户可以访问此文件。

[root@server2 ~]# cd /opt/sftp-jails/hynman

创建一个隐藏目录" .ssh",我们将其中存储我们的sftpauthorized_keys文件

[root@server2 hynman]# mkdir .ssh

.ssh目录必须由hynman用户拥有,并且不能被世界访问

[root@server2 hynman]# chown hynman:root .ssh
[root@server2 hynman]# chmod 700 .ssh
[root@server2 hynman]# ls -al
total 16
drwxr-xr-x 4 root   root 4096 Mar 30 19:20 .
drwxr-xr-x 3 root   root 4096 Mar 30 18:29 ..
drwxr-x--- 3 hynman root 4096 Mar 30 19:08 exchange
drwx------ 2 hynman root 4096 Mar 30 19:20 .ssh

创建sftpauthorized_keys文件

[root@server2 hynman]# touch .ssh/authorized_keys

更改此文件的所有权和权限

[root@server2 ~]# chown hynman:root .ssh/authorized_keys
[root@server2 ~]# chmod 600 .ssh/authorized_keys

验证权限:

[root@server2 .ssh]# ls -al
total 12
drwxr-xr-x 2 hynman root 4096 Mar 30 19:20 .
drwxr-xr-x 4 root   root 4096 Mar 30 19:20 ..
-rw------- 1 hynman root  410 Mar 30 19:17 authorized_keys

.2:生成SSH密钥对以设置无密码的sftp

我们正在使用root用户创建密钥对,而不使用任何密码来sftp将用户限制为特定目录。

私钥对将在/root/.ssh内的root用户的主文件夹下创建。

[root@server1 ~]# ssh-keygen -t rsa -P ""
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
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:
SHA256:waurDGhB1PvXepoJKcTADzia1qDZilHvC1BV+UnZnic [email protected]
The key's randomart image is:
+---[RSA 2048]----+
| .. .... o       |
|+  o  ..o .      |
|o*o .  ooo .     |
|+BBo    ooE .    |
|Bo.=o   S  o     |
|o=o. ..o .       |
|+.o..oo .        |
|.  +...oo.       |
|    +..+o        |
+----[SHA256]-----+

将公共密钥id_rsa.pub的内容复制到server2,并将其放置在我们在创建sftpauthorized_keys文件下创建的/opt/sftp-jails/hynman/exchange/.ssh/authorized_keys中。

在我们看到的下方,我将我的id_rsa.pub内容添加到了/opt/sftp-jails/hynman/exchange/.ssh/authorized_keys中。

[root@server1 ~]# cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7qO/cXiw8UZtgGIoCiVWF24CW3hdIQ4w1hA6L+cHts1Sg6ecJRFXZJmrv23TSmD9Xrw4HHAxECJJKAk1zSWzBYykvqNM6xpvbg8pnIRSLyA06Erf+FdyfFjpDXorJ+eE309H9fJH4ke1aXBvF5LddA1N+1yDjuAllekjL/6kL7e58D4+E6gJa2wGs8OdQM7YFEgPbQJPBn03WQLHR3O59S+zURvrHSmUTVPJ7VWVdJ6nrcMlraOMc0yshTK4QWkmsBEa3+fhEBk0qFxJBhI0Fn775omaquhD3RzKyySXn9vgw3bb36k99KzD3F/w5hoK4sehDnEZs9lTYz8I8FUeV [email protected]
[root@server2 ~]# cat /opt/sftp-jails/hynman/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7qO/cXiw8UZtgGIoCiVWF24CW3hdIQ4w1hA6L+cHts1Sg6ecJRFXZJmrv23TSmD9Xrw4HHAxECJJKAk1zSWzBYykvqNM6xpvbg8pnIRSLyA06Erf+FdyfFjpDXorJ+eE309H9fJH4ke1aXBvF5LddA1N+1yDjuAllekjL/6kL7e58D4+E6gJa2wGs8OdQM7YFEgPbQJPBn03WQLHR3O59S+zURvrHSmUTVPJ7VWVdJ6nrcMlraOMc0yshTK4QWkmsBEa3+fhEBk0qFxJBhI0Fn775omaquhD3RzKyySXn9vgw3bb36k99KzD3F/w5hoK4sehDnEZs9lTYz8I8FUeV [email protected]

.3:使用authorized_keys设置sftp chroot监狱

在我们现有的sshd_config的sftp chroot监狱配置中,我们将添加另一行,如sftp的authorized_keys位置突出显示。

[root@server2 ~]# cat /etc/ssh/sshd_config
Match user hynman
        ChrootDirectory /opt/sftp-jails/hynman/
        AuthorizedKeysFile /opt/sftp-jails/hynman/.ssh/authorized_keys
        X11Forwarding no
        AllowTcpForwarding no
        PermitTunnel no
        AllowAgentForwarding no
        ForceCommand internal-sftp

重新启动sshd服务以激活sftpauthorized_keys更改

[root@server2 ~]# systemctl restart sshd

下面是具有所有权限的sftp chroot监狱目录的树结构:

[root@server2 ~]# tree -paug /opt/
/opt/
└── [drwxr-xr-x root     root    ]  sftp-jails
    └── [drwxr-xr-x root     root    ]  hynman
        ├── [drwxr-x--- hynman   root    ]  exchange
        │   └── [drwx------ hynman   hynman  ]  hynman_dir
        └── [drwxr-xr-x hynman   root    ]  .ssh
            └── [-rw------- hynman   root    ]  authorized_keys
5 directories, 1 file

.4:验证SFTP连接和权限

执行从" server1"到" server2"的sftp连接。

[root@server1 ~]# sftp  [email protected]
Connected to [email protected].  <-- There was no password prompt and the connection was established 
sftp> exit

因此,我们的无密码sftpauthorized_keys配置成功并按预期工作。

为无密码sftp设置SSH客户端

默认情况下,执行sftp时,该工具会在用户的主文件夹下查找任何可用的密码,以执行无密码的sftp。
在我们的案例中,由于私钥存在于根目录的主文件夹中,因此无密码的SFTP可以正常工作。

但是,如果我们尝试使用任何其他用户进行sftp无密码连接,则它将失败。
下面我尝试在server1上使用amit用户执行sftp

[amit@server1 ~]$ssh [email protected]
[email protected]'s password:  <-- Prompting for password even when passwordless sftp is configured

如我们所见,sftp通信提示输入密码,并且无密码的" sftpauthorized_keys无法正常工作"。

为了克服sftp的这种限制,可以将用户限制为不带密码的特定目录,我们有两种解决方案:

解决方案1:使用私钥执行无密码的sftp

我们必须定义要用于执行sftp通信的私钥,才能执行无密码的sftp。
例如:

我将复制我在用户amit可以访问的路径下生成的私钥。

我创建了一个临时目录/tmp/sftp_keys,所有用户都可以访问

[root@server1 ~]# mkdir /tmp/sftp_keys
[root@server1 ~]# chmod 755 /tmp/sftp_keys/

将私钥从复制到此位置,并使其对server1的所有用户可读

[root@server1 ~]# cp .ssh/id_rsa /tmp/sftp_keys/
[root@server1 ~]# chmod 644 /tmp/sftp_keys/id_rsa

下一步尝试对server2执行无密码的sftp

[root@server1 ~]# su - amit
[amit@server1 ~]$sftp -i /tmp/sftp_keys/id_rsa [email protected]
Connected to [email protected]. <-- Passwordless sftp is working using sftp authorized_keys from sshd_config 
sftp> exit

解决方案2:为单个用户创建ssh配置文件

我们还可以为节点的单个用户创建本地ssh配置文件,以使用sftpauthrorized_keysserver2执行无密码的sftp。
为此,我们将在内部的amit用户的主文件夹(/home/amit/.ssh)下创建一个配置文件。
ssh目录

我们可以检查我为" amit"的主文件夹下的所有文件和目录分配的权限和所有权:

[amit@server1 ~]$tree -paug .
.
├── [-rw------- amit     amit    ]  .bash_history
├── [-rw-r--r-- amit     amit    ]  .bash_logout
├── [-rw-r--r-- amit     amit    ]  .bash_profile
├── [-rw-r--r-- amit     amit    ]  .bashrc
├── [drwx------ amit     amit    ]  .ssh
│   ├── [-rw------- amit     amit    ]  config
│   ├── [-rw------- amit     amit    ]  id_rsa
│   └── [-rw-r--r-- amit     amit    ]  known_hosts
└── [-rw------- amit     amit    ]  .viminfo
1 directory, 8 files

以下是/home/amit/.ssh/config的内容,我们可以根据需要进行修改以执行无密码sftp。
我已将私钥复制到`/home/amit /中。

我们之前创建的ssh`。

[amit@server1 ~]$cat .ssh/config
Host server2
AddressFamily inet
ConnectionAttempts 10
ForwardAgent no
ForwardX11 no
ForwardX11Trusted no
GatewayPorts no
HostBasedAuthentication no
HostKeyAlias sftp-alias
HostName 10.10.10.13
IdentityFile ~/.ssh/id_rsa
PasswordAuthentication no
Protocol 2
Compression yes
ServerAliveCountMax 3
ServerAliveInterval 15
TCPKeepAlive no
User hynman

接下来验证无密码的sftp通信

[amit@server1 ~]$sftp server2
Connected to server2. <-- Passwordless sftp is working using sftp authorized_keys from sshd_config 
sftp> exit

SFTP chroot多个目录

与sftp将用户限制到特定目录中的sshd_config配置文件类似,我们将为任意数量的用户或者组添加更多带有match块的模板,以在Linux中为多个目录实现sftp chroot jail。

例如,在下面的/etc/ssh/sshd_config配置中,我们为不同的用户和组执行sftp chroot多个目录

# sftp chroot jail only user hynman to folder /opt/sftp-jails/hynman
Match User hynman
   ChrootDirectory /opt/sftp-jails/hynman
   AllowTCPForwarding no
   X11Forwarding no
   ForceCommand internal-sftp
# sftp chroot jail only user amit to folder /opt/sftp-jails/amit
Match User amit
   ChrootDirectory /opt/sftp-jails/amit
   AllowTCPForwarding no
   X11Forwarding no
   ForceCommand internal-sftp
# sftp chroot jail users that are in group sftpusers to the folder /opt/sftp-jails/sftpusers
Match Group sftpusers
   ChrootDirectory /opt/sftp-jails/sftpusers
   AllowTCPForwarding no
   X11Forwarding no
   ForceCommand internal-sftp

本文中的所有其他步骤对于sftp chroot多个目录都是相同的,我们只需要注意单个sftp chroot监狱目录上的用户和组权限即可