我试图强制通过 SSH 登录的用户在 IP 命名空间内拥有 shell。
/etc/passwd
我尝试过用类似的东西替换外壳,ip netns exec sshns /bin/bash
但没有成功。
还有其他想法吗?有可能吗?它会安全还是根本不安全?
答案1
通过更改登录 shell 来处理此问题(如 OP 的示例中所示)的问题是,当用户连接到sshd
主网络命名空间时,即使您让他们的 shell 在另一个命名空间内运行,但他们的端口转发仍将在默认网络命名空间中运行。
我提出的解决方案还解决了包含到命名空间和 shell 的端口转发问题。它可能仅限于使用本地帐户,因为通过网络(NIS、SMB 等)对远程系统进行身份验证可能不起作用,因为身份验证阶段将从网络命名空间内执行。
我需要 shell 和端口转发才能在目标命名空间中运行无需在默认名称空间和包含名称空间之间创建网络/路由。
以下是实现此目的的一些方法/工具:
xinetd
- 感谢 Stéphane Chazelas 指出这一点。对于单个或静态数量的命名空间并将其转发到它们xinetd
似乎是更好的选择。例如文件/etc/xinetd.d/sshd-netns-foo
service sshdnetns
{
type = UNLISTED
socket_type = stream
protocol = tcp
port = 222
wait = no
user = root
server = /sbin/ip
server_args = netns exec NameSpaceName /usr/sbin/sshd -i
}
socat
- 对于多个命名空间,需要独立启动/停止转发到它们socat
是一个很好的选择。在默认命名空间中运行:
socat tcp-listen:222,fork,reuseaddr \
exec:'ip netns exec NameSpaceName /usr/sbin/sshd -i',nofork
ncat
- 如果socat
不可用,那么ncat
(在我的 RHEL 盒子上nc
)可以完成这项工作。缺点ncat
是通过管道sshd
连接ncat
而不是直接连接到套接字,因此sshd
看不到客户端 IP,因此日志不太有用。您最终还会运行一个额外的中间ncat
过程。
ncat --keep-open --sh-exec "exec ip netns exec NameSpaceName /usr/sbin/sshd -i" -l 222
可能还有其他工具。
sshd -i
这在自定义端口 222 上接受默认命名空间中的 SSH 连接,并且每个连接在目标命名空间内启动一次。
这为我解决了这个问题,但您还需要限制可以登录每个命名空间的用户。创建特定于命名空间的 sshd 配置:
mkdir -pv /etc/netns/NameSpaceName/
cp -Rp /etc/ssh /etc/netns/NameSpaceName/
为每个文件添加访问控制sshd_config
,例如默认/etc/ssh/sshd_config
:
AllowUsers user1 user2
...并且在/etc/netns/NameSpaceName/ssh/sshd_config
AllowUsers restrictedUser1 restrictedUser2
...还要看看AllowGroups
指令
现在重新创建名称空间以使目录绑定生效
我的简短测试显示用户访问控制按预期工作,但我并没有真正使用它,所以它供您验证。
我尝试将单独的/etc/passwd
,/etc/shadow
和/etc/group
文件放入/etc/netns/NameSpaceName/
单独的用户列表中,但在我的快速测试中不起作用:useradd test
在命名空间内失败。
笔记:
如果您不喜欢自定义端口,您可以使用双主端口,例如 macvlan,或者只是添加另一个 IP 地址并监听专用 IP 上的默认端口。
所有身份验证、shell、子系统、端口转发等均由 处理,sshd
因此我不必破解其他任何内容。
它确实有sshd -i
像这样运行的缺点,请阅读man sshd
寻找-i
选项。您可以通过在命名空间内全职运行sshd
并将转发守护进程更改为如下所示来轻松解决该问题:
nc --keep-open --sh-exec "exec ip netns exec NameSpaceName nc localhost 22" -l 222
我想知道是否可以使用挂载和/或用户命名空间(除了网络命名空间)来更巧妙地解决这个问题。我对这些没有经验。
可能有更好的方法来实现这一目标,我对其他人的想法非常感兴趣。
答案2
您只能将用户的 shell 设置为单个命令的完整路径名,不带参数。
如果要运行多个命令或带参数的命令,请编写一个 shell 脚本,使其可执行,并将用户的 shell 设置为该脚本。
例如
printf '#!/bin/sh\n%s\n' 'exec ip netns exec sshns /bin/bash "$@"' > /usr/local/bin/myshell.sh
chmod a+rx /usr/local/bin/myshell.sh
chsh -u user -s /usr/local/bin/myshell.sh
我不知道是否ip netns exec sshns /bin/bash
有效。我还没有测试过 - 它对我来说看起来不是一个有效的命令,但假设它是一个有效的命令,或者你可以想出一个,即使用 shell 脚本作为用户的 shell 可以工作,我测试了它只是exec /usr/bin/zsh
在脚本中。