Linux 如何在登录后限制 SSH 用户使用一组预定义的命令?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/402615/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to restrict SSH users to a predefined set of commands after login?
提问by Marcel
This is a idea for a security. Our employees shall have access to some commands on a linux server but not all. They shall e.g. have the possibility to access a log file (less logfile
) or start different commands (shutdown.sh
/ run.sh
).
这是一个安全的想法。我们的员工应该可以访问 linux 服务器上的一些命令,但不是全部。例如,它们应该有可能访问日志文件 ( less logfile
) 或启动不同的命令 ( shutdown.sh
/ run.sh
)。
Background information:
背景资料:
All employees access the server with the same user name: Our product runs with "normal" user permissions, no "installation" is needed. Just unzip it in your user dir and run it. We manage several servers where our application is "installed". On every machine there is a user johndoe
. Our employees sometimes need access to the application on command line to access and check log files or to restart the application by hand. Only some people shall have full command line access.
所有员工使用相同的用户名访问服务器:我们的产品以“普通”用户权限运行,不需要“安装”。只需将其解压缩到您的用户目录中并运行它。我们管理“安装”了我们的应用程序的几台服务器。每台机器上都有一个用户johndoe
。我们的员工有时需要通过命令行访问应用程序以访问和检查日志文件或手动重新启动应用程序。只有一些人应该拥有完整的命令行访问权限。
We are using ppk authentication on the server.
我们在服务器上使用 ppk 身份验证。
It would be great if employee1 can only access the logfile and employee2 can also do X etc...
如果employee1 只能访问日志文件而employee2 也可以执行X 等操作,那就太好了……
Solution:As a solution I'll use the command
option as stated in the acceptedanswer. I'll make my own little shell script that will be the only file that can be executed for someemployees. The script will offer several commands that can be executed, but no others. I'll use the following parameters in authorized_keys
from as stated here:
解决方案:作为解决方案,我将使用command
已接受答案中所述的选项。我将制作我自己的小 shell 脚本,它将成为某些员工可以执行的唯一文件。该脚本将提供几个可以执行的命令,但没有其他命令。我将authorized_keys
按照此处所述使用以下参数:
command="/bin/myscript.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-dss AAAAB3....o9M9qz4xqGCqGXoJw= user@host
This is enough security for us. Thanks, community!
这对我们来说已经足够安全了。谢谢,社区!
采纳答案by HD.
You can also restrict keys to permissible commands (in the authorized_keys file).
您还可以将密钥限制为允许的命令(在authorized_keys 文件中)。
I.e. the user would not log in via ssh and then have a restricted set of commands but rather would only be allowed to execute those commands via ssh (e.g. "ssh somehost bin/showlogfile")
即用户不会通过 ssh 登录,然后有一组受限的命令,而只能通过 ssh 执行这些命令(例如“ssh somehost bin/showlogfile”)
回答by Vinko Vrsalovic
What you are looking for is called Restricted Shell. Bash provides such a mode in which users can only execute commands present in their home directories (and they cannot move to other directories), which might be good enough for you.
您正在寻找的是Restricted Shell。Bash 提供了这样一种模式,在这种模式下,用户只能执行存在于其主目录中的命令(并且不能移动到其他目录),这对您来说可能已经足够了。
I've found this threadto be very illustrative, if a bit dated.
我发现这个线程非常具有说明性,如果有点过时的话。
回答by Chuah
You should acquire `rssh', the restricted shell
您应该获得“rssh”,这是受限制的 shell
You can follow the restriction guides mentioned above, they're all rather self-explanatory, and simple to follow. Understand the terms `chroot jail', and how to effectively implement sshd/terminal configurations, and so on.
您可以遵循上面提到的限制指南,它们都是不言自明的,并且易于遵循。了解术语“chroot jail”,以及如何有效地实现 sshd/终端配置等。
Being as most of your users access your terminals via sshd, you should also probably look into sshd_conifg, the SSH daemon configuration file, to apply certain restrictions via SSH. Be careful, however. Understand properly what you try to implement, for the ramifications of incorrect configurations are probably rather dire.
由于您的大多数用户通过 sshd 访问您的终端,您可能还应该查看 sshd_conifg,SSH 守护程序配置文件,以通过 SSH 应用某些限制。不过要小心。正确理解您尝试实施的内容,因为错误配置的后果可能相当可怕。
回答by Bryan Rehbein
Another way of looking at this is using POSIX ACLs, it needs to be supported by your file system, however you can have fine-grained tuning of all commands in linux the same way you have the same control on Windows (just without the nicer UI). link
另一种看待这个的方式是使用 POSIX ACL,它需要你的文件系统支持,但是你可以在 linux 中对所有命令进行细粒度调整,就像你在 Windows 上拥有相同的控制一样(只是没有更好的 UI )。关联
Another thing to look into is PolicyKit.
另一件需要研究的事情是PolicyKit。
You'll have to do quite a bit of googling to get everything working as this is definitely not a strength of Linux at the moment.
您必须进行大量的谷歌搜索才能使一切正常工作,因为目前这绝对不是 Linux 的强项。
回答by Kaz
ssh
follows the rsh
tradition by using the user's shell program from the password file to execute commands.
ssh
遵循rsh
传统,使用来自密码文件的用户 shell 程序来执行命令。
This means that we can solve this without involving ssh
configuration in any way.
这意味着我们可以ssh
在不涉及任何配置的情况下解决这个问题。
If you don't want the user to be able to have shell access, then simply replace that user's shell with a script. If you look in /etc/passwd
you will see that there is a field which assigns a shell command interpreter to each user. The script is used as the shell both for their interactive login ssh user@host
as well as for commands ssh user@host command arg ...
.
如果您不希望用户能够访问 shell,那么只需用脚本替换该用户的 shell。如果您查看,/etc/passwd
您会看到有一个字段为每个用户分配一个 shell 命令解释器。该脚本用作交互式登录ssh user@host
和命令的 shell ssh user@host command arg ...
。
Here is an example. I created a user foo
whose shell is a script. The script prints the message my arguments are:
followed by its arguments (each on a separate line and in angle brackets) and terminates. In the log in case, there are no arguments. Here is what happens:
这是一个例子。我创建了一个用户,foo
其 shell 是一个脚本。脚本打印消息my arguments are:
后跟其参数(每个在单独的行和尖括号中)并终止。在登录案例中,没有参数。这是发生的事情:
webserver:~# ssh foo@localhost
foo@localhost's password:
Linux webserver [ snip ]
[ snip ]
my arguments are:
Connection to localhost closed.
If the user tries to run a command, it looks like this:
如果用户尝试运行命令,它看起来像这样:
webserver:~# ssh foo@localhost cat /etc/passwd
foo@localhost's password:
my arguments are:
<-c>
<cat /etc/passwd>
Our "shell" receives a -c
style invocation, with the entire command as one argument, just the same way that /bin/sh
would receive it.
我们的“shell”接收一个-c
样式调用,将整个命令作为一个参数,与/bin/sh
接收它的方式相同。
So as you can see, what we can do now is develop the script further so that it recognizes the case when it has been invoked with a -c
argument, and then parses the string (say by pattern matching). Those strings which are allowed can be passed to the real shell by recursively invoking /bin/bash -c <string>
. The reject case can print an error message and terminate (including the case when -c
is missing).
如您所见,我们现在可以做的是进一步开发脚本,以便它识别使用-c
参数调用时的情况,然后解析字符串(例如通过模式匹配)。那些被允许的字符串可以通过递归调用/bin/bash -c <string>
. 拒绝案例可以打印错误消息并终止(包括-c
丢失的案例)。
You have to be careful how you write this. I recommend writing only positive matches which allow only very specific things, and disallow everything else.
你必须小心你如何写这个。我建议只写正匹配,只允许非常具体的事情,而不允许其他一切。
Note:if you are root
, you can still log into this account by overriding the shell in the su
command, like this su -s /bin/bash foo
. (Substitute shell of choice.) Non-root cannot do this.
注意:如果您是root
,您仍然可以通过覆盖su
命令中的 shell 来登录此帐户,如下所示su -s /bin/bash foo
。(替代选择的 shell。)非 root 不能这样做。
Here is an example script: restrict the user into only using ssh
for git
access to repositories under /git
.
这是一个示例脚本:将用户限制为仅ssh
用于git
访问/git
.
#!/bin/sh
if [ $# -ne 2 ] || [ "" != "-c" ] ; then
printf "interactive login not permitted\n"
exit 1
fi
set --
if [ $# != 2 ] ; then
printf "wrong number of arguments\n"
exit 1
fi
case "" in
( git-upload-pack | git-receive-pack )
;; # continue execution
( * )
printf "command not allowed\n"
exit 1
;;
esac
# Canonicalize the path name: we don't want escape out of
# git via ../ path components.
gitpath=$(readlink -f "") # GNU Coreutils specific
case "$gitpath" in
( /git/* )
;; # continue execution
( * )
printf "access denied outside of /git\n"
exit 1
;;
esac
if ! [ -e "$gitpath" ] ; then
printf "that git repo doesn't exist\n"
exit 1
fi
"" "$gitpath"
Of course, we are trusting that these Git programs git-upload-pack
and git-receive-pack
don't have holes or escape hatches that will give users access to the system.
当然,我们相信,这些混帐程序git-upload-pack
和git-receive-pack
不要有破洞或逃生舱,这将使用户对系统的访问。
That is inherent in this kind of restriction scheme. The user is authenticated to execute code in a certain security domain, and we are kludging in a restriction to limit that domain to a subdomain. For instance if you allow a user to run the vim
command on a specific file to edit it, the user can just get a shell with :!sh[Enter]
.
这是这种限制方案所固有的。用户经过身份验证以在某个安全域中执行代码,并且我们正在努力将该域限制为子域。例如,如果您允许用户vim
在特定文件上运行该命令以对其进行编辑,则该用户只需获取带有:!sh[Enter]
.
回答by Yeti
Why don't you write your own login-shell? It would be quite simple to use Bash for this, but you can use any language.
你为什么不编写自己的登录外壳?为此使用 Bash 会非常简单,但您可以使用任何语言。
Example in Bash
Bash 中的示例
Use your favorite editor to create the file /root/rbash.sh
(this can be any name or path, but should be chown root:root
and chmod 700
):
使用您最喜欢的编辑器创建文件/root/rbash.sh
(这可以是任何名称或路径,但应该是chown root:root
和chmod 700
):
#!/bin/bash
commands=("man" "pwd" "ls" "whoami")
timestamp(){ date +'%Y-%m-%s %H:%M:%S'; }
log(){ echo -e "$(timestamp)\t\t$(whoami)\t" > /var/log/rbash.log; }
trycmd()
{
# Provide an option to exit the shell
if [[ "$ln" == "exit" ]] || [[ "$ln" == "q" ]]
then
exit
# You can do exact string matching for some alias:
elif [[ "$ln" == "help" ]]
then
echo "Type exit or q to quit."
echo "Commands you can use:"
echo " help"
echo " echo"
echo "${commands[@]}" | tr ' ' '\n' | awk '{print " " ##代码##}'
# You can use custom regular expression matching:
elif [[ "$ln" =~ ^echo\ .*$ ]]
then
ln="${ln:5}"
echo "$ln" # Beware, these double quotes are important to prevent malicious injection
# For example, optionally you can log this command
log COMMAND "echo $ln"
# Or you could even check an array of commands:
else
ok=false
for cmd in "${commands[@]}"
do
if [[ "$cmd" == "$ln" ]]
then
ok=true
fi
done
if $ok
then
$ln
else
log DENIED "$cmd"
fi
fi
}
# Optionally show a friendly welcome-message with instructions since it is a custom shell
echo "$(timestamp) Welcome, $(whoami). Type 'help' for information."
# Optionally log the login
log LOGIN "$@"
# Optionally log the logout
trap "trap=\"\";log LOGOUT;exit" EXIT
# Optionally check for '-c custom_command' arguments passed directly to shell
# Then you can also use ssh user@host custom_command, which will execute /root/rbash.sh
if [[ "" == "-c" ]]
then
shift
trycmd "$@"
else
while echo -n "> " && read ln
do
trycmd "$ln"
done
fi
All you have to do is set this executable as your login shell. For example, edit your /etc/passwd
file, and replace your current login shell of that user /bin/bash
with /root/rbash.sh
.
您所要做的就是将此可执行文件设置为您的登录 shell。例如,编辑您的/etc/passwd
文件,并将该用户当前的登录 shell 替换/bin/bash
为/root/rbash.sh
.
This is just a simple example, but you can make it as advanced as you want, the idea is there. Be careful to not lock yourself out by changing login shell of your own and only user. And always test weird symbols and commands to see if it is actually secure.
这只是一个简单的示例,但您可以根据需要将其设置为高级,想法就在那里。小心不要通过更改您自己和唯一用户的登录外壳来锁定自己。并且总是测试奇怪的符号和命令,看看它是否真的安全。
You can test it with: su -s /root/rbash.sh
.
您可以使用以下命令对其进行测试:su -s /root/rbash.sh
。
Beware, make sure to match the whole command, and be careful with wildcards! Better exclude Bash-symbols such as ;
, &
, &&
, ||
, $
, and backticks to be sure.
当心,确保匹配整个命令,并小心通配符!更好地排除猛砸符号,例如;
,&
,&&
,||
,$
,和反引号以确保万无一失。
Depending on the freedom you give the user, it won't get much safer than this. I've found that often I only needed to make a user that has access to only a few relevant commands, and in that case this is really the better solution. However, do you wish to give more freedom, a jail and permissions might be more appropriate. Mistakes are easily made, and only noticed when it's already too late.
根据您给予用户的自由,它不会比这更安全。我发现通常我只需要让用户只能访问几个相关命令,在这种情况下,这确实是更好的解决方案。但是,您是否希望给予更多自由,监狱和权限可能更合适。错误很容易犯,只有在为时已晚时才会注意到。
回答by raf
[Disclosure: I wrote sshdo which is described below]
[披露:我写了下面描述的sshdo]
If you want the login to be interactive then setting up a restricted shell is probably the right answer. But if there is an actual set of commands that you want to allow (and nothing else) and it's ok for these commands to be executed individually via ssh (e.g. ssh user@host cmd arg blah blah), then a generic command whitelisting control for ssh might be what you need. This is useful when the commands are scripted somehow at the client end and doesn't require the user to actually type in the ssh command.
如果您希望登录是交互式的,那么设置受限 shell 可能是正确的答案。但是,如果您希望允许一组实际的命令(并且没有其他任何内容)并且可以通过 ssh 单独执行这些命令(例如 ssh user@host cmd arg blah blah),则可以使用通用命令白名单控制ssh 可能正是您所需要的。当命令在客户端以某种方式编写脚本并且不需要用户实际输入 ssh 命令时,这很有用。
There's a program called sshdo for doing this. It controls which commands may be executed via incoming ssh connections. It's available for download at:
有一个名为 sshdo 的程序可以执行此操作。它控制可以通过传入的 ssh 连接执行哪些命令。它可以在以下位置下载:
http://raf.org/sshdo/(read manual pages here) https://github.com/raforg/sshdo/
http://raf.org/sshdo/(在此处阅读手册页) https://github.com/raforg/sshdo/
It has a training mode to allow all commands that are attempted, and a --learn option to produce the configuration needed to allow learned commands permanently. Then training mode can be turned off and any other commands will not be executed.
它具有允许尝试的所有命令的训练模式,以及用于生成永久允许学习命令所需的配置的 --learn 选项。然后可以关闭训练模式,并且不会执行任何其他命令。
It also has an --unlearn option to stop allowing commands that are no longer in use so as to maintain strict least privilege as requirements change over time.
它还具有一个 --unlearn 选项,用于停止允许不再使用的命令,以便在需求随时间变化时保持严格的最低权限。
It is very fussy about what it allows. It won't allow a command with any arguments. Only complete shell commands can be allowed.
它对允许的内容非常挑剔。它不允许带有任何参数的命令。只允许完整的 shell 命令。
But it does support simple patterns to represent similar commands that vary only in the digits that appear on the command line (e.g. sequence numbers or date/time stamps).
但它确实支持简单的模式来表示类似的命令,这些命令仅在命令行上出现的数字(例如序列号或日期/时间戳)上有所不同。
It's like a firewall or whitelisting control for ssh commands.
这就像 ssh 命令的防火墙或白名单控制。
And it supports different commands being allowed for different users.
并且它支持允许不同用户使用不同的命令。
回答by Thomas
GNU Rushmay be the most flexible and secure way to accomplish this:
GNU Rush可能是实现这一目标的最灵活和最安全的方式:
GNU Rush is a Restricted User Shell, designed for sites that provide limited remote access to their resources, such as svn or git repositories, scp, or the like. Using a sophisticated configuration file, GNU Rush gives you complete control over the command lines that users execute, as well as over the usage of system resources, such as virtual memory, CPU time, etc.
GNU Rush 是一个受限用户 Shell,专为提供有限远程访问资源的站点而设计,例如 svn 或 git 存储库、scp 等。使用复杂的配置文件,GNU Rush 使您可以完全控制用户执行的命令行以及系统资源的使用,例如虚拟内存、CPU 时间等。