如何在 Linux 上排除 SFTP 权限被拒绝错误

LinuxBeginner
立即练习

介绍

SFTP(安全文件传输协议)是一个强大且安全的解决方案,用于通过网络传输文件。本教程将指导你理解 SFTP,解决“权限被拒绝(Permission Denied)”错误,以及在你的 Linux 系统上解决 SFTP 权限问题。你将学习如何设置 SFTP 服务器,创建具有适当权限的用户,并诊断文件传输期间发生的常见权限问题。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 88%。获得了学习者 100% 的好评率。

在 Ubuntu 上设置 SFTP 服务器

SFTP(安全文件传输协议)提供了一种在系统之间安全传输文件的方法。与常规 FTP 不同,SFTP 在传输过程中对命令和数据进行加密,保护你的信息免受未经授权的访问。

在这一步中,我们将在 Ubuntu 系统上设置一个基本的 SFTP 服务器。

安装 OpenSSH 服务器

首先,让我们确保你的系统是最新的,并安装 OpenSSH 服务器,它包括 SFTP 功能:

sudo apt update
sudo apt install -y openssh-server

运行这些命令后,你应该看到类似如下的输出:

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
openssh-server is already the newest version (1:8.9p1-3ubuntu0.1).

验证 SSH 服务状态

由于我们在 Docker 容器中,标准的 systemctl 命令将不起作用。让我们使用进程状态命令检查 SSH 服务是否正在运行:

ps aux | grep sshd

你应该看到输出表明 sshd 正在运行:

root      1234  0.0  0.1  12016  5604 ?        Ss   10:20   0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups

为 SFTP 创建一个测试用户

让我们创建一个专门用于测试 SFTP 功能的用户:

sudo adduser sftpuser

当提示时,输入一个简单的密码,例如 password123,你可以按 Enter 键跳过额外的用户信息字段。你应该看到类似如下的输出:

Adding user `sftpuser' ...
Adding new group `sftpuser' (1001) ...
Adding new user `sftpuser' (1001) with group `sftpuser' ...
Creating home directory `/home/sftpuser' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully

为 SFTP 传输创建测试文件

现在,让我们在我们的主目录中创建一些测试文件,我们将使用它们进行 SFTP 传输:

cd ~/project
echo "This is a test file for SFTP transfers" > testfile.txt
echo "This file has different permissions" > restrictedfile.txt

让我们验证文件是否已正确创建:

ls -l testfile.txt restrictedfile.txt

你应该看到类似如下的输出:

-rw-rw-r-- 1 labex labex 37 Sep 28 10:30 restrictedfile.txt
-rw-rw-r-- 1 labex labex 38 Sep 28 10:30 testfile.txt

默认情况下,这两个文件对所有者和组具有读写权限,对其他人具有只读权限。我们将在接下来的步骤中尝试更改这些权限。

理解文件权限及其对 SFTP 的影响

在我们探索 SFTP 权限问题之前,让我们先了解 Linux 文件权限系统及其如何影响 SFTP 操作。

Linux 文件权限基础

在 Linux 中,每个文件和目录都有三种类型的权限:

  • 读取(r):允许查看文件内容或列出目录内容
  • 写入(w):允许修改文件或在目录中创建/删除文件
  • 执行(x):允许执行文件或访问目录

这些权限被分配给三个用户类别:

  • 所有者:创建文件的用户
  • 组:分配给文件的组
  • 其他人:其他所有人

查看当前权限

让我们检查测试文件的当前权限:

ls -l ~/project/testfile.txt ~/project/restrictedfile.txt

你将看到类似如下的输出:

-rw-rw-r-- 1 labex labex 38 Sep 28 10:30 /home/labex/project/testfile.txt
-rw-rw-r-- 1 labex labex 37 Sep 28 10:30 /home/labex/project/restrictedfile.txt

权限字符串 -rw-rw-r-- 可以分解为:

  • 第一个字符 - 表示一个常规文件(对于目录将是 d
  • 接下来三个字符 rw- 显示所有者权限(读取、写入、无执行)
  • 接下来三个字符 rw- 显示组权限(读取、写入、无执行)
  • 最后三个字符 r-- 显示其他人的权限(仅读取)

修改文件权限

让我们修改文件的权限,以创建可能导致 SFTP 中出现“权限被拒绝”错误的场景:

## 使 testfile.txt 可供所有人读取,但仅供所有者写入
chmod 644 ~/project/testfile.txt

## 使 restrictedfile.txt 仅供所有者访问
chmod 600 ~/project/restrictedfile.txt

现在,让我们验证更改:

ls -l ~/project/testfile.txt ~/project/restrictedfile.txt

你应该看到更新后的权限:

-rw-r--r-- 1 labex labex 38 Sep 28 10:30 /home/labex/project/testfile.txt
-rw------- 1 labex labex 37 Sep 28 10:30 /home/labex/project/restrictedfile.txt

设置用于 SFTP 测试的目录

让我们创建一个专门用于 SFTP 测试的目录:

mkdir -p ~/project/sftp_test
echo "This file is in the SFTP test directory" > ~/project/sftp_test/test_file.txt
chmod 755 ~/project/sftp_test

现在,让我们创建一个具有受限权限的目录:

mkdir -p ~/project/restricted_sftp
echo "This file is in the restricted directory" > ~/project/restricted_sftp/restricted_file.txt
chmod 700 ~/project/restricted_sftp

让我们验证目录权限:

ls -ld ~/project/sftp_test ~/project/restricted_sftp

你应该看到:

drwxr-xr-x 2 labex labex 4096 Sep 28 10:35 /home/labex/project/sftp_test
drwx------ 2 labex labex 4096 Sep 28 10:35 /home/labex/project/restricted_sftp

sftp_test 目录可以被任何人访问,而 restricted_sftp 目录只能被所有者(labex 用户)访问。

体验和诊断 SFTP 权限被拒绝错误

在这一步中,我们将连接到我们的 SFTP 服务器,并亲身体验权限被拒绝错误。这将帮助我们理解权限设置如何影响 SFTP 操作。

本地连接到 SFTP 服务器

由于我们在本地环境中工作,我们可以使用 localhost 地址连接到我们的 SFTP 服务器。让我们使用我们之前创建的 sftpuser 进行连接:

sftp sftpuser@localhost

当提示输入密码时,输入你为 sftpuser 帐户设置的密码(例如,password123)。如果连接成功,你将看到类似以下的提示:

Connected to localhost.
sftp>

如果你遇到连接问题,可能是因为 SSH 服务在容器中没有正确运行。你可以尝试使用 exit 退出,并使用理论示例继续执行后续步骤。

基本 SFTP 命令

让我们探索一些基本的 SFTP 命令:

  1. 查看远程服务器上的当前目录:
sftp> pwd
Remote working directory: /home/sftpuser
  1. 列出当前目录中的文件:
sftp> ls
  1. 导航到不同的目录:
sftp> cd /tmp
sftp> pwd
Remote working directory: /tmp
  1. 返回你的主目录:
sftp> cd
sftp> pwd
Remote working directory: /home/sftpuser

尝试访问具有不同权限的文件

现在,让我们尝试从 SFTP 会话访问我们的测试文件:

  1. 尝试从我们的项目目录获取一个文件:
sftp> get /home/labex/project/testfile.txt
Fetching /home/labex/project/testfile.txt to testfile.txt
Permission denied

你将注意到一个“权限被拒绝”错误。这是因为 sftpuser 没有权限访问 labex 用户主目录中的文件。

退出 SFTP 会话

让我们退出 SFTP 会话以继续:

sftp> exit

理解权限被拒绝错误

SFTP 中出现“权限被拒绝”错误有几个常见原因:

  1. 文件权限:用户没有对文件的读/写访问权限
  2. 目录权限:用户无法访问包含文件的目录
  3. 所有权问题:文件/目录属于不同的用户或组
  4. 路径遍历限制:SFTP 配置可能将用户限制在某些目录中

让我们使我们的一个测试文件可供我们的 SFTP 用户访问:

## 创建一个可以被其他人访问的目录
mkdir -p /tmp/shared
echo "This is a shared file for SFTP testing" > /tmp/shared/shared_file.txt
chmod 777 /tmp/shared
chmod 666 /tmp/shared/shared_file.txt

现在,重新连接到 SFTP 并尝试访问此文件:

sftp sftpuser@localhost

连接后,尝试:

sftp> get /tmp/shared/shared_file.txt
Fetching /tmp/shared/shared_file.txt to shared_file.txt
/tmp/shared/shared_file.txt                        100%   36     1.0KB/s   00:00

这应该有效,因为我们已经向所有人授予了对目录和文件的读/写权限。

再次退出 SFTP 会话:

sftp> exit

使用调试模式的 SFTP

为了获得更多关于权限错误的信息,你可以在调试模式下使用 SFTP:

sftp -v sftpuser@localhost

详细输出将向你显示有关连接和发生的任何错误的详细信息:

debug1: Sending subsystem: sftp
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 2412, received 2876 bytes, in 0.1 seconds
Bytes per second: sent 30074.7, received 35857.2
debug1: Exit status 0

解决 SFTP 权限被拒绝错误

现在我们了解了权限如何影响 SFTP 访问,让我们学习如何解决常见的权限被拒绝错误。

解决方案 1:调整文件和目录权限

解决权限问题的最直接方法是调整文件和目录权限。让我们创建一个新的测试用例:

## 创建一个具有限制性权限的新测试文件
echo "This file has restricted permissions" > ~/project/restricted_access.txt
chmod 600 ~/project/restricted_access.txt

检查当前权限:

ls -l ~/project/restricted_access.txt

输出:

-rw------- 1 labex labex 35 Sep 28 11:05 /home/labex/project/restricted_access.txt

现在,让我们通过更改其权限使该文件可供其他人访问:

chmod 644 ~/project/restricted_access.txt
ls -l ~/project/restricted_access.txt

输出:

-rw-r--r-- 1 labex labex 35 Sep 28 11:05 /home/labex/project/restricted_access.txt

使用这些权限(644),文件所有者(labex)可以读取和写入文件,而组成员和其他人只能读取它。

解决方案 2:更改文件所有权

另一种解决方案是将文件的所有权更改为匹配 SFTP 用户。让我们创建另一个测试文件:

echo "This file will be owned by sftpuser" > ~/project/ownership_test.txt

现在,让我们将所有权更改为我们的 SFTP 用户:

sudo chown sftpuser:sftpuser ~/project/ownership_test.txt
ls -l ~/project/ownership_test.txt

输出:

-rw-rw-r-- 1 sftpuser sftpuser 36 Sep 28 11:10 /home/labex/project/ownership_test.txt

现在,该文件由 sftpuser 拥有,sftpuser 可以读取和写入它。

解决方案 3:创建共享目录

SFTP 文件共享的一个常见解决方案是创建一个具有适当权限的目录,多个用户可以访问该目录:

## 创建一个具有适当权限的新共享目录
mkdir -p /tmp/sftp_shared
sudo chown labex:labex /tmp/sftp_shared
chmod 755 /tmp/sftp_shared

## 创建一个可供所有人写入的用于上传的子目录
mkdir -p /tmp/sftp_shared/uploads
chmod 777 /tmp/sftp_shared/uploads

## 在共享目录中创建一个示例文件
echo "This file is in the shared SFTP directory" > /tmp/sftp_shared/sample.txt
chmod 644 /tmp/sftp_shared/sample.txt

让我们验证我们的设置:

ls -la /tmp/sftp_shared/

输出:

total 12
drwxr-xr-x 3 labex   labex   4096 Sep 28 11:15 .
drwxrwxrwt 4 root    root    4096 Sep 28 11:15 ..
-rw-r--r-- 1 labex   labex     39 Sep 28 11:15 sample.txt
drwxrwxrwx 2 labex   labex   4096 Sep 28 11:15 uploads

通过此设置:

  • 主目录可供所有人读取和执行,但仅可供所有者写入
  • 上传子目录可供所有人写入(适用于 SFTP 上传)
  • sample.txt 文件可供所有人读取,但仅可供所有者写入

此配置允许 SFTP 用户:

  • 导航到共享目录
  • 读取示例文件
  • 将文件上传到上传目录

解决方案 4:使用 ACL 实现更精细的控制

访问控制列表(ACL,Access Control Lists)提供了更详细的权限管理。让我们安装必要的软件包并使用 ACL:

sudo apt install -y acl

现在,让我们创建一个文件并使用 ACL 设置特定的权限:

echo "This file uses ACLs for permissions" > ~/project/acl_test.txt

## 设置基本权限
chmod 640 ~/project/acl_test.txt

## 添加 sftpuser 的 ACL 权限
sudo setfacl -m u:sftpuser:r ~/project/acl_test.txt

## 查看 ACL 设置
getfacl ~/project/acl_test.txt

输出:

## file: /home/labex/project/acl_test.txt
## owner: labex
## group: labex
user::rw-
user:sftpuser:r--
group::r--
mask::r--
other::---

此 ACL 配置允许:

  • 文件所有者(labex)读取和写入
  • sftpuser 读取文件
  • 组读取文件
  • 其他人无权访问

SFTP 权限管理最佳实践

在最后一步中,我们将介绍一些管理 SFTP 权限和有效排除权限问题的最佳实践。

创建一个专用的 SFTP 用户组

为 SFTP 用户创建一个专用组是一个好习惯:

sudo groupadd sftp_users
sudo usermod -a -G sftp_users sftpuser

验证用户是否已添加到组中:

groups sftpuser

输出:

sftpuser : sftpuser sftp_users

设置一个组管理的目录

现在,让我们创建一个由 sftp_users 组管理的目录:

## 为 SFTP 组创建一个新目录
sudo mkdir -p /tmp/sftp_group_shared
sudo chown labex:sftp_users /tmp/sftp_group_shared
sudo chmod 770 /tmp/sftp_group_shared

## 设置 SGID 位以确保新文件继承该组
sudo chmod g+s /tmp/sftp_group_shared

## 在此目录中创建一个测试文件
echo "This file is in the SFTP group directory" > /tmp/sftp_group_shared/group_file.txt

让我们验证权限:

ls -la /tmp/sftp_group_shared/

输出:

total 12
drwxrws--- 2 labex    sftp_users 4096 Sep 28 11:25 .
drwxrwxrwt 5 root     root       4096 Sep 28 11:25 ..
-rw-rw-r-- 1 labex    sftp_users   42 Sep 28 11:25 group_file.txt

组权限中的 s 表示设置了 SGID 位,这意味着在此目录中创建的新文件将继承 sftp_users 组。

SFTP 权限的常见故障排除命令

在排除 SFTP 权限问题时,这些命令特别有用:

  1. 检查文件权限:
ls -la /path/to/file
  1. 检查用户组:
groups username
  1. 检查当前用户和组 ID:
id
  1. 查看 SFTP 服务器日志:
## 在生产系统中,你将检查系统日志
## 对于我们的实验环境,我们可以模拟查看日志
grep "sshd" /var/log/auth.log | tail
  1. 从命令行测试文件访问:
sudo -u sftpuser cat /path/to/file

权限被拒绝错误决策树

当你遇到 SFTP 中的权限被拒绝错误时,请遵循此决策树:

  1. SFTP 用户可以访问父目录吗?

    • 使用以下命令检查:sudo -u sftpuser ls -la /path/to/directory/
    • 使用以下命令修复:chmod o+x /path/to/directory/
  2. SFTP 用户可以读取文件吗?

    • 使用以下命令检查:sudo -u sftpuser cat /path/to/file
    • 使用以下命令修复:chmod o+r /path/to/filesetfacl -m u:sftpuser:r /path/to/file
  3. SFTP 用户可以写入文件或目录吗?

    • 使用以下命令检查:sudo -u sftpuser touch /path/to/directory/test_file
    • 使用以下命令修复:chmod o+w /path/to/directory/setfacl -m u:sftpuser:w /path/to/directory/

创建一个用于 SFTP 权限的测试脚本

让我们创建一个简单的测试脚本,用于检查 SFTP 用户是否可以访问特定的文件和目录:

cat > ~/project/check_sftp_permissions.sh << 'EOF'
#!/bin/bash

USER="sftpuser"
echo "Testing SFTP permissions for user: $USER"
echo "-------------------------------------------"

## Test directories
for DIR in /tmp/shared /tmp/sftp_shared /tmp/sftp_group_shared /home/labex/project; do
  echo -n "Can $USER access $DIR? "
  if sudo -u $USER ls -la $DIR &>/dev/null; then
    echo "YES"
  else
    echo "NO"
  fi
done

## Test files
for FILE in /tmp/shared/shared_file.txt /tmp/sftp_shared/sample.txt /home/labex/project/testfile.txt; do
  echo -n "Can $USER read $FILE? "
  if sudo -u $USER cat $FILE &>/dev/null; then
    echo "YES"
  else
    echo "NO"
  fi
done

echo "-------------------------------------------"
echo "Testing complete!"
EOF

chmod +x ~/project/check_sftp_permissions.sh

现在运行测试脚本:

sudo ~/project/check_sftp_permissions.sh

你应该看到输出,指示 SFTP 用户可以访问哪些目录和文件。这有助于你快速识别权限问题。

管理 SFTP 权限的最终提示

  1. 使用最小权限原则:仅授予必要的最低权限
  2. 定期审核权限:使用 find 等工具来识别具有不适当权限的文件
  3. 记录你的权限结构:跟踪哪些用户和组有权访问哪些目录
  4. 考虑使用 SFTP chroot jail(chroot 监狱):对于生产环境,将用户限制在特定目录中
  5. 从用户的角度进行测试:始终通过以实际 SFTP 用户的身份进行测试来验证权限

总结

在本教程中,你已经学习了如何设置 SFTP 服务器,创建具有适当权限的用户,以及排除常见的权限被拒绝错误。你获得了以下方面的实践经验:

  • 在 Ubuntu 上安装和配置 SFTP 服务器
  • 了解 Linux 文件权限及其对 SFTP 访问的影响
  • 体验和诊断权限被拒绝错误
  • 实施各种解决方案来解决权限问题
  • 应用 SFTP 权限管理的最佳实践

这些技能将帮助你在安全的环境中有效管理文件传输,同时最大限度地减少与权限相关的问题。请记住,适当的权限管理对于维护安全但功能齐全的 SFTP 服务器至关重要,需要在安全需求和用户访问需求之间取得平衡。