我有一台 18.04 Ubuntu 服务器,我使用它通过 SSH 隧道绕过我国的互联网过滤/审查。为此,我使用命令创建了几个用户,adduser USERNAME --shell=/bin/false
并为他们提供了服务器 IP、服务器端口、用户名和密码(我称之为帐户),以便他们可以通过我的服务器建立隧道。现在我想确保每个帐户一次只能在一台设备上使用。换句话说,我想防止多台设备使用同一个帐户同时通过我的服务器建立隧道。
通过谷歌搜索,我找到了解决方案:我将以下内容放入文件中/root/checkConnections
:
#! /bin/bash
limit=$1
c=$(pgrep -xcu $PAM_USER sshd)
if [[ $c -ge "$limit" ]]; then
echo "Max $limit ssh connections allowed, but you have $c."
exit 1
fi
然后/etc/pam.d/sshd
我补充道:
session required pam_exec.so stdout /root/checkConnections 1
这段代码运行良好,完全符合我的要求,但它有一个明显的缺点:当我退出 putty 时,我无法再 ssh 到服务器!换句话说,当我尝试以 root 身份 ssh 到服务器时,它会立即将我踢出,不允许我登录,这就是我不得不重新安装服务器的原因。我该如何解决这个问题?
注意:我对 Linux 服务器世界还很陌生,所以请以简单的方式解释您的解决方案。
答案1
您找到的脚本通过计算尝试通过 SSH 登录的用户的进程数来工作sshd
。如果该数字大于或等于限制(在您的例子中为 1),则脚本将返回失败,从而阻止建立会话。
问题在于主 SSH 守护进程本身是sshd
属于 root 的进程。(在这个答案您可以看到sshd
它是一个守护进程,同时也sshd
属于普通用户。)当守护进程运行时,sshd
root 的进程数始终至少为 1。运行中的 SSH 守护进程的唯一存在会导致您的代码锁定 root。
可能的解决方案:
习惯以普通用户身份登录。登录后,在需要时使用
sudo
或su
成为 root 用户。这是一种常见做法。甚至可以使用以下命令禁用或限制通过 SSH 以 root 身份登录PermitRootLogin
/etc/ssh/sshd_config
你可能想这样做出于安全原因。作为普通用户,您应该能够登录。您的脚本将把您视为任何其他普通用户,即,将限制一个会话;但(与 root 不同)您将能够登录。
修改脚本,这样如果用户是 root,则无论
sshd
进程数有多少,脚本都会返回成功。一个简单的修复方法是像这样扩展if
:if [ "$PAM_USER" != root ] && [ "$c" -ge "$limit" ]; then
意思是“如果用户不是 root 并且达到限制,则... [稍后返回失败]”;但尽早检查用户而不是徒劳调用会更优雅
pgrep
。下面的代码使用了这种更优雅的方法。
如果我是你,我会合并这两个解决方案。我会以普通用户身份登录,并让该用户像 root 一样不受限制。
如果用户是root
或 ,则以下脚本返回成功vahid
。限制逻辑仅对其他用户生效。
#! /bin/sh
case "$PAM_USER" in
root|vahid )
exit 0 ;;
* )
limit="$1"
c="$(pgrep -xcu "$PAM_USER" sshd)"
if [ "$c" -ge "$limit" ]; then
echo "Max $limit ssh connections allowed, but you have $c."
exit 1
fi
;;
esac
我特意使用了sh
,它可能比 更轻(启动更快,占用资源更少)bash
。
此外,我认为这个条目在/etc/pam.d/sshd
:
session required pam_exec.so stdout /root/checkConnections 1
可能会被 绕过ssh -N
。由于您/bin/false
为其他用户设置了 ,我猜ssh -N
这就是您希望他们使用的。要使脚本即使在 的情况下也能正常工作ssh -N
,请指定account
而不是session
:
account required pam_exec.so stdout /root/checkConnections 1