我的网络中有以下设置:
Internet <--> Bastion <--> Local Network
我有多个用户,每个用户都被分配到特定的机器。换句话说:每个用户只能访问其中一台服务器。例如:用户 1 --> 机器 1,用户 2 --> 机器 2,等等。
这些用户将从我的网络外部进行连接,并且我已经考虑了许多选项,如何通过我的堡垒主机将他们的连接转发到我的网络。
最终我选择了 Match Blocks 和 forcecommand。
因此,我在堡垒上的 /etc/ssh/sshd_config 如下所示:
Match User User1
ForceCommand ssh User1@Machine1 $SSH_ORIGINAL_COMMAND
User1 连接到堡垒主机,堡垒主机自动与 Machine1 建立连接。
据我了解,ForceCommand 认为,User1 无法真正访问堡垒主机,因为他的所有操作都将首先由匹配块处理,因此会重新路由到 Machine1。但这真的是真的吗?这足以成为一个安全的设置吗?无论如何,用户都被关在 Machine1 上,因此他在那里没有太多的可能性。
答案1
我使用堡垒主机的方式是使用ProxyCommand
和-W
标志,如本例所示:
ssh -o ProxyCommand='ssh -W %h:%p user@bastion' user@machine
我出于安全原因使用这种方法。客户端和目标机器之间的通信是端到端加密和身份验证的,这意味着即使堡垒被攻破,它仍然是安全的。被攻破的堡垒主机提供的安全性不亚于没有堡垒的端到端使用 ssh。
它还消除了使用任何代理转发的需要。客户端可以首先使用基于密钥的身份验证来访问堡垒,然后再次访问目标主机,而无需为任何一方提供可用于滥用客户端上存在的私钥的代理连接。
它还限制了我在堡垒主机上所依赖的代码。我根本不需要在堡垒上执行任何命令。-W
意味着没有命令标志以及一个端口转发,这个端口转发是堡垒主机需要允许的全部。
考虑到这种方法,我的建议是尽可能锁定堡垒主机,只允许使用上述结构的命令。
堡垒上的文件~/.ssh/authorized_keys
可以由 root 拥有(从文件系统根目录到它的路径上的所有目录也可以由 root 拥有),这样即使有人设法以堡垒主机上的非特权用户身份闯入,也可能降低文件被修改的风险。
authorized_keys
可以使用选项command
、、、、、来限制客户端的权限,以及使用来限制端口转发以仅允许访问该用户可以访问的主机上的端口 22 no-agent-forwarding
。no-pty
no-user-rc
no-X11-forwarding
permitopen
原则上,即使多个用户在堡垒上共享一个用户名,这种方法也是安全的。但是,在堡垒上使用单独的用户名可以稍微提高隔离度。
答案2
您可以轻松绕过 ForceCommand,因为它会在您的 shell 启动时启动。这实际上意味着首先处理您的 shell rc 文件,然后处理 ForceCommand(如果您允许的话)。exec sh
在您的 shell rc 文件中简单地执行此操作将生成另一个 shell,并让 ForceCommand 一直等待,直到您退出此 shell。
所以底线是;如果用户可以通过 ftp、sftp、scp 或其他方式编辑他的 shell rc(比如 .bashrc),那么 ForceCommand 并不是真正值得依赖的东西。
答案3
我想大多数情况下这样做是没问题的,但安全问题在于还没有人考虑过这个问题。没有任何保证。
例如,很长一段时间以来,没有人认真考虑过如何在 bash 中从环境变量创建函数,但最近人们意识到这可能会被颠覆,而其中一个影响是,如果用户的 shell 是 bash,ForceCommand 就可以被绕过(至少在 authorized_keys 文件中实现)。Bash 已经修复,希望您的版本是最新的,但这种情况还是会发生。
我不完全确定定义 ForceCommand 是否与在 authorized_keys 文件中定义这些命令实际上相同。我还没有仔细研究过。
答案4
我还有一个想法。对于堡垒服务器上的每个用户,您可以在 /etc/passwd 中将其 shell 定义为一个 bash 脚本,该脚本仅运行 ssh user1@machine1、user2@machine2 等。这样,您就可以确保他们在服务器本身上没有任何有效的 shell,并且他们只是连接到他们应该连接的机器。