如何为端口转发创建受限制的SSH用户?

ændrük 建议使用反向连接以便与其他人轻松建立SSH连接(用于远程帮助)。 为此,需要额外的用户来接受连接。 该用户需要能够通过服务器转发其端口(服务器充当代理)。

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

新用户必须无法

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

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

TL; DR – 回答底部,“应用限制”

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

配置sshd

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

  • SSH(1)
  • ssh_config中(5)
  • 的sshd(8)
  • sshd_config中(5)

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

在限制某些内容之前,您需要了解SSH的function。 通过手册页吐出产生:

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

从sshd(8)手册页的Authentication部分:

如果客户端成功validation自身,则会输入准备会话的对话框。 此时,客户端可以请求诸如分配伪tty,转发X11连接,转发TCP连接或通过安全信道转发认证代理连接之类的事情。

在此之后,客户端请求shell或执行命令 。 然后双方进入会话模式。 在这种模式下,任何一方都可以随时发送数据,并且这些数据被转发到/从服务器端的shell或命令以及客户端的用户终端转发。

限制SSHfunction的选项

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

  • ~/.ssh/authorized_keys – 包含允许连接的键,可以给出选项:
    • command="command" – 忽略用户提供的命令(如果有)。 请注意,除非明确禁止,否则客户端可以指定TCP和/或X11转发 。 请注意,此选项适用于shell,命令或子系统执行。
    • no-agent-forwarding – 当此密钥用于身份validation时,禁止身份validation代理转发。
    • no-port-forwarding – 当此密钥用于身份validation时,禁止TCP转发
    • no-X11-forwarding – “当此密钥用于身份validation时禁止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端口转发的目标。 转发规范必须是以下forms之一:

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

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

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

    修改系统范围的配置文件/etc/ssh/sshd_config允许应用配置,即使应用了基于密码的身份validation或者意外删除了~/.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 

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

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

    禁用AllowTcpForwarding也会禁止使用-R ,从而无法使用此类受限帐户转发单个端口。 PermitOpen localhost:62222假设服务器上的端口62222永远不会被使用,因为客户端可以愉快地连接到它并监听它。

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

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

    校验

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

     # 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服务器。如果您在计算机上有其他易受攻击的服务,则可能允许可能的攻击者运行命令,终止服务器等)

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

    • 像往常一样添加用户(’adduser’或任何其他工具)

    • 创建用户.ssh dir和.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 ) < 
    • 禁用对此帐户的密码访问权限。
     your_user $ sudo usermod --lock ssh_forwarder 

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

    你可以在'command ='中做很多其他事情。 有关更多信息,请参阅man authorized_keys并搜索“command”。

    如果你不喜欢按Enter键杀死连接的事实,你可以使用类似下面的'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,allowremoteopen = 10001'这样的东西对于允许ssh -R 6901:localhost:6901会很有用。

    这是一个解决方案。 它绝对可以改进,并且应该仔细检查远程端口的任何打开。 如果我的目标是允许我的祖母连接到我的局域网,那么我可以使用vnc查看她的屏幕,并且访问这些密钥仅限于她,我个人会觉得相当安全。 如果这是针对企业的,则需要进行更彻底的调查。 有一点需要注意的是ssh -N根本不请求shell,因此'command ='代码不会执行。

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