如何创建受限的 SSH 用户以进行端口转发?

如何创建受限的 SSH 用户以进行端口转发?

安德魯克建议反向连接以便与其他人建立轻松的 SSH 连接(用于远程帮助)。要实现这一点,需要有其他用户接受连接。该用户需要能够通过服务器转发其端口(服务器充当代理)。

我如何创建一个只能执行上述操作的受限用户?

新用户必须不是能够:

  • 执行shell命令
  • 访问文件或上传文件到服务器
  • 使用服务器作为代理(例如 webproxy)
  • 访问因防火墙而无法公开访问的本地服务
  • 终止服务器

总而言之,我如何创建一个受限的 SSH 用户,该用户只能在没有权限的情况下连接到 SSH 服务器,以便我可以通过该连接与他的计算机进行连接?

答案1

TL;DR - 转到答案底部,“应用限制”

添加受限用户包括两部分:1. 创建用户 2. 配置 SSH 守护进程 (sshd)

配置 sshd

了解 SSH 可能性的最佳途径是阅读相关的手册页:

SSH 客户端可以在哪里执行操作?

在限制某些操作之前,您需要了解 SSH 的功能。查阅手册页可得出以下结论:

  • Shell 命令执行
  • 通过 sftp 上传文件
  • 转发端口
    • 客户端将(未)使用的端口转发到服务器
    • 服务器将其端口转发给客户端
    • 服务器将另一台主机的端口转发给客户端(代理)
  • X11转发(显示转发)
  • 身份验证代理转发
  • 隧道设备的转发

来自验证部分sshd(8) 手册页

如果客户端成功验证身份,则会进入准备会话的对话框。此时客户端可能会请求以下内容 分配伪 tty、转发 X11 连接、转发 TCP 连接或转发身份验证代理连接通过安全通道。

此后,客户端可以请求 shell 或执行命令. 双方随后进入会话模式。在此模式下,任何一方都可以随时发送数据,这些数据在服务器端的 shell 或命令与客户端的用户终端之间进行转发。

限制 SSH 功能的选项

改变行为的文件及其选项包括:

  • ~/.ssh/authorized_keys- 包含允许连接的键,可以提供选项:
    • command="command"- 忽略用户提供的命令(如果有)。请注意,客户端可以指定 TCP 和/或 X11 转发,除非明确禁止. 注意此选项适用于 shell、命令或子系统的执行。
    • no-agent-forwarding- 当此密钥用于身份验证时,禁止身份验证代理转发。
    • no-port-forwarding- 当此密钥用于身份验证时禁止 TCP 转发
    • no-X11-forwarding- “当此密钥用于身份验证时禁止 X11 转发。”
    • permitopen="host:port"- 限制本​​地“ssh -L”端口转发,使得它只能连接到指定的主机和端口。
  • ~/.ssh/environment- 此文件在登录时被读入环境(如果存在)。环境处理默认被禁用,并通过 PermitUserEnvironment 选项进行控制
  • ~/.ssh/rc- 包含在用户主目录可访问之前运行的初始化例程。
  • /etc/ssh/sshd_config- 系统范围的配置文件
    • AllowAgentForwarding- 指定是否允许 ssh-agent(1) 转发。
    • AllowTcpForwarding
    • ForceCommand- “强制执行 ForceCommand 指定的命令,忽略客户端提供的任何命令以及 ~/.ssh/rc(如果存在)。使用带有 -c 选项的用户登录 shell 调用该命令。”
    • GatewayPorts- “指定是否允许远程主机连接到为客户端转发的端口。默认情况下,sshd(8) 将远程端口转发绑定到环回地址。这可以防止其他远程主机连接到转发端口。GatewayPorts 可用于指定 sshd 应允许远程端口转发绑定到非环回地址,从而允许其他主机连接。”
    • PermitOpen

      指定允许 TCP 端口转发的目标。转发规范必须采用以下形式之一:

      PermitOpen host:port
      PermitOpen IPv4_addr:port
      PermitOpen [IPv6_addr]:port
      

      可以通过用空格分隔来指定多个转发。可以使用“any”参数来删除所有限制并允许任何转发请求。默认情况下,所有端口转发请求均被允许。

    • PermitTunnel- 指定是否允许 tun(4) 设备转发。默认为“否”
    • X11Forwarding- 指定是否允许 X11 转发。默认为“否”

应用限制

修改系统范围的配置文件/etc/ssh/sshd_config允许即使应用了基于密码的身份验证或~/.ssh/authorized_keys意外删除了限制,配置仍可应用。如果您修改了全局默认值,则应取消注释相应的选项。

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

现在添加一个用户:

sudo useradd -m limited-user

ForceCommand如果将 shell 设置为非 shell,则可以省略该选项,如/bin/false(或/bin/true)/bin/false -c [command]不会执行任何操作。

现在客户端只能通过 SSH 连接到服务器环回地址上的端口 62222(它不会监听公共 IP 地址)

禁用AllowTcpForwarding还会禁止使用-R,从而使这种受限帐户无法用于转发单个端口。PermitOpen localhost:62222假定服务器上的端口 62222 从未使用过,因为客户端可以愉快地连接到该端口并对其进行监听。

如果系统范围配置中允许 TCP 转发并禁用基于密码的身份验证,您也可以使用每个密钥设置。~/.ssh/authorized_keys在 之前编辑并添加以下选项ssh-(选项 和 之间有一个空格ssh-):

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

核实

为了确保它按预期工作,需要运行一些测试用例。在下面的命令中,host如果未在中设置,则应将其替换为实际登录名~/.ssh/config。在命令后面,显示了应在客户端或服务器上执行的命令(如指定)。

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

结论

检查表:SSH 用户不应该能够:

  • 执行 shell 命令 -完毕
  • 访问文件或将文件上传到服务器 -完毕
  • 使用服务器作为代理(例如 webproxy) -完毕
  • 访问因防火墙而无法公开访问的本地服务 -部分,客户端无法访问除62222之外的其他端口,但可以监听并连接服务器端的62222端口
  • 终止服务器 –完毕 (请注意,这些检查仅限于 SSH 服务器。如果您的机器上有其他易受攻击的服务,则可能允许攻击者运行命令、杀死服务器等。)

答案2

我确信有很多解决方案可以解决这个问题,而且有很多比我建议的解决方案更强大。但是,这可能足以满足您的需求。为了做到这一点,我假设用户能够进行基于 ssh 密钥的身份验证(putty 或任何 unix ssh 都应该支持这一点)。

  • 像平常一样添加用户(“adduser”或任何其他工具)

  • 创建用户 .ssh 目录和 .ssh/authorized_keys

your_user $ sudo -Hu ssh_forwarder /bin/bash

ssh_forwarder $ cd ~
ssh_forwarder $ mkdir .ssh
ssh_forwarder $ ( umask 066 && cat > .ssh/authorized_keys ) <<EOF
no-agent-forwarding,no-X11-forwarding,command="read a; exit" ssh-rsa AAAB3NzaC1y....2cD/VN3NtHw== smoser@brickies
EOF
  • 禁用该帐户的密码访问。
your_user $ sudo usermod --lock ssh_forwarder

现在,用户进入您的系统的唯一方法是通过访问正确的 ssh 密钥,并且无论他们尝试运行什么,ssh 都会为他们运行“/bin/bash -c 'read a'”。'read a' 将简单地读取直到换行符,然后 shell 将退出,因此用户只需按'enter'即可终止连接。

您还可以在“command=”中执行许多其他操作。查看man authorized_keys并搜索“command”以获取更多信息。

如果您不喜欢按回车键终止连接,您可以对“command=”条目使用类似下面的内容:

command="f=./.fifo.$$ && mkfifo $f && trap \"rm -f $f\" EXIT && read a <$f && echo $a; exit;"

这只会在用户主目录中创建一个临时 fifo,然后尝试从中读取。不会有任何内容写入该文件,因此这将无限期挂起。此外,如果您想强制终止该连接,您可以执行以下操作:

 your_user$ echo GOODBYE | sudo tee ~ssh_forwarder/.fifo.*

这应该会使用很少的资源,并且脚本中不应该出现任何错误而导致 shell 终止。

sleep 1h; echo You have been here too long. Good bye.

我暂时还不知道如何允许用户远程转发 ( ssh -R) 但限制 ( ssh -L)。也许可以使用“permitopen”。 谷歌搜索没什么帮助。似乎可以使用类似“no-port-forwarding,permitremoteopen=10001”这样的命令来允许ssh -R 6901:localhost:6901

这是A解决方案。它绝对可以改进,任何远程端口的打开都应该受到严格审查。如果我的目标是允许我的祖母连接到我的局域网,这样我就可以使用 vnc 查看她的屏幕,并且只有她才能访问这些密钥,我个人会觉得相当安全。如果这是针对企业,则需要进行更彻底的调查。需要注意的一件事是ssh -N根本不请求 shell,因此“command=”代码不会执行。

其他可能更安全的机制可能包括为用户创建自定义 shell,甚至使用 apparmour 将其锁定。

答案3

尝试command="exit"

这将强制用户使用此命令进行端口转发

ssh -NfR EXTERNAL_PORT:localhost:INTERNAL_PORT usr@server -i key

相关内容