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


106

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

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

新用户不能

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

综上所述,如何创建受限的SSH用户,该用户只能在没有特权的情况下连接到SSH服务器,因此可以通过该连接与他的计算机连接?


Answers:


166

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

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

配置sshd

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

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

在限制某些内容之前,您需要了解SSH的功能。遍历手册页可得出:

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

sshd(8)手册页Authentication部分中:

如果客户端成功进行身份验证,将进入准备会话的对话框。此时,客户端可以请求诸如 分配伪tty,转发X11连接,转发TCP连接或通过安全通道转发身份验证代理连接之类的操作。

之后,客户端要么请求外壳程序,要么执行命令。双方然后进入会话模式。在这种模式下,任何一方都可以在任何时间发送数据,并且这些数据将被转发到服务器端的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选项的用户登录外壳程序来调用。”
    • 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服务器。如果计算机上还有其他易受攻击的服务,则它可能允许攻击者运行命令,杀死服务器等)。

3
为此,useradd必须将添加的帐户解锁。可以通过用/etc/shadow星号(*)代替密码或使用设置密码来完成sudo passwd limited-user
Lekensteyn

2
因为SSH服务器运行sftp-server命令,所以SFTP起作用。使用ForceCommand,将不再执行此命令。
Lekensteyn

2
中的from=选项也很有用authorized_keys。它允许您将密钥的使用限制为具有特定IP地址或主机名的源。例如,from="1.1.1.1"from="10.0.0.?,*.example.com"。有关所有authorized_keys选项的信息,请参见手册页(linux.die.net/man/8/sshd)中的“ AUTHORIZED_KEYS文件格式”部分。
Donn Lee

2
“ AllowTcpForwarding local”禁止远程转发。(我不知道它是何时写的。)
Simon Sapin

1
请注意,这被持久的ssh连接所破坏,因此Host * ControlMaster auto,使用~/.ssh/config时,文件中不应包含类似内容ssh -N。如果您确实需要它,请使用ssh -N -o ControlMaster=no
nh2

3

我敢肯定,有很多解决方案,而且比我建议的解决方案更强大。但是,这可能足以满足您的需求。为了做到这一点,我假设用户能够进行基于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="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

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

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


3
这看起来很骇人,甚至不需要外壳,因为不需要执行任何命令。见的手册页ssh-N选项。必须有一种更清洁的方式来完成此任务。
Lekensteyn 2011年

确实如此。我也希望看到更清洁的解决方案。我确实认为,如果有“ permitremoteopen”选项,则将authorized_keys与无端口转发结合使用将是一个很好的解决方案。
smoser 2011年

我做了一些重新研究(见上文)。由于ssh -N根本不执行命令,因此command="something"关闭会话没有问题。
Lekensteyn 2011年

我想念什么吗?似乎chsh ssh_forwarder -s /bin/false 就是全部。
typelogic
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.