我有一台计算机,它被设置为服务器,上面装有 Ubuntu 18.0.4,我与朋友共享,并使用 sftp 上传/下载文件。最近我的一个朋友一直在进行大量传输,占用了大部分带宽,因此我想通过 ssh 限制他的用户的带宽。我该怎么做?非常感谢!
答案1
合作用户
如果用户很友好并且合作,请让他或她使用可配置速度限制的 SFTP 客户端(例如 FileZilla)。这可能是最简单的解决方案。
我的这个答案提供了一种在 Linux 中限制普通 SSH 连接的方法ssh
。由于许多工具(包括 CLI sftp
)ssh
在后台使用传输,因此只需输入如下一行
ProxyCommand pv -qL 20K | nc %h %p | pv -qL 10K
~/.ssh/config
限制每个用户。正确使用后,用户Match
将能够限制他们仅连接到您的服务器。
不一定合作用户
我明白你想要一个在你的服务器上工作并且不依赖于用户合作意愿的限制器。据我所知,类似于链接答案中的客户端限制器的限制器不能应用于服务器端的任意 SSH 连接。但是,它可以应用于流经子系统的数据sftp
。
在你的/etc/ssh/sshd_config
里面有一行
Subsystem sftp internal-sftp
或者
Subsystem sftp /usr/lib/sftp-server
我们将使用包装器来sftp-server
实现限制器。幸运的是,它通过标准流sftp-server
进行通信sshd
。这使得我们创建包装器的任务相对容易。
另一方面,不能Subsystem
在sshd_config
下使用Match
,它是一个全局设置。这意味着,很遗憾,我们不能只为一个用户使用我们的包装器。我们将为任何用户使用它,包装器的任务是告知它在哪个用户下运行并采取相应的行动。
基本包装器可能是这样的:
#!/bin/sh
case "$USER" in
abuser )
pv -qL 20K | /usr/lib/sftp-server "$@" | pv -qL 10K
;;
* )
exec /usr/lib/sftp-server "$@"
;;
esac
最左边pv
限制从客户端流向服务器的数据;最右边pv
限制从服务器流向客户端的数据。
现在有一个问题:如果abuser
连接两次或更多次,每个包装器将仅限制其自己的带宽。用户可以通过一次通过多个连接传输多个文件来绕过限制器。我认为将它们作为一个包进行限制并不容易(如果可能的话),至少在这种方法中不是。
一个有用的解决方案是检测另一个包装器是否abuser
工作,如果工作正常,则拒绝任何传输。这将强制abuser
一次只使用一个 SFTP 连接,并且此连接将受到适当限制。
为此,请以 root 身份创建一个目录(例如)/sftp_wrapper
。在其中创建一个名为的空常规文件abuser.lockfile
和一个名为的脚本sftp-server-limited
。目录和脚本应归root:root
锁文件所有。为目录、包装器和锁文件abuser:root
设置模式。755
755
400
假设您处于/sftp_wrapper
(重要!)并且您是 root,则以下 shell 代码将设置这些内容(user=abuser
在粘贴代码之前自定义行):
user=abuser
chown root:root .
chmod 755 .
: > "$user".lockfile
chown "$user":root "$user".lockfile
chmod 400 "$user".lockfile
cat > sftp-server-limited << EOF
#!/bin/sh
case "\$USER" in
$user )
exec 9</sftp_wrapper/$user.lockfile
flock -w 1 9 || exit 1
pv -qL 20K | /usr/lib/sftp-server "\$@" | pv -qL 10K
;;
* )
exec /usr/lib/sftp-server "\$@"
;;
esac
EOF
chmod 755 sftp-server-limited
现在告诉你sshd
使用包装器而不是sftp-server
或internal-sftp
。sshd_config
找到该Subsystem sftp …
行并使其:
Subsystem sftp /sftp_wrapper/sftp-server-limited
通过调用重新加载sshd
:
systemctl reload sshd.service
完毕。
笔记:
在我们的中,
sftp-server-limited
我使用了相当低的值pv -L
,因此在测试中,该方法显然是有效的。请根据需要进行调整。由于值如此之低,如果客户端想要中断传输(例如,在交互式中Ctrl+ ),那么他们可能必须等待几秒钟,直到某些缓冲区刷新。c
sftp
锁定
flock
非常可靠。当所有使用 创建的描述符的进程exec 9<…
退出时,锁定会自动释放。无需手动解锁,并且永远不应该有陈旧的锁定(除非存在陈旧的进程)。该脚本使用
case
并可轻松扩展以覆盖更多“特殊”用户。不过对于每个这样的用户,您将需要一个单独的锁定文件。确保
flock
并pv
已安装。包装器仅适用于
sftp
子系统。当限制用户一次只能连接一个 SFTP 时,请注意,用户的连接可能会中断,在您的服务器注意到这一事实之前,用户将无法再次连接。因此,尽早检测到断开的连接是很好的。您可以通过在服务器上设置相当低的
ClientAlive*
值来实现这一点。示例:sshd_config
ClientAliveInterval 15 ClientAliveCountMax 4
看这个答案了解这些到底是做什么用的。