我不知道如何确切地命名我的问题。
场景是我有一台服务器,其中有一套适合我需要的 TUI 程序。
我希望网络的其他用户打开一些较小的东西,例如 raspi 或恐龙计算机,并且当它启动时,用户不会像平常一样看到用于本地登录的 getty...而是显示 ssh到服务器。仅当服务器未应答时,才会向用户提供本地登录信息。
我想这种类型的场景并不新鲜或激进......在我看来,它基本上是通过 ssh 通过 tcp/ip 连接的瘦客户端的概念
答案1
这确实是可以实现的:大约在 1998 年左右,我在大学里就做过类似的事情。
基本上,您需要配置getty
RasPi 的进程来调用您自己的自定义版本的程序login
而不是标准的/bin/login
.那部分很容易。
login
如果您不需要特别安全,或者只是进行原型设计,您的自定义替换甚至可以是脚本。但对于一个严肃的实现,我认为它应该是一个已编译的程序,为了安全:删除脚本解释器可以最大限度地减少要运行的代码量,因此更难设置竞争条件或针对它的其他攻击。
然而,我在你的设计中发现了一个可能的用户体验问题:当用户已经输入了他们的登录名时,他们可能会在密码提示出现后立即直接输入密码,几乎是一种反射动作,无需太多思考。如果 SSH 连接尝试不成功,并且自动重用相同的登录名进行本地登录尝试,则用户可能会认为自己已连接到服务器,并且当发现自己使用本地登录时会感到困惑。
最好需要进行深思熟虑的操作,例如切换到具有未修改getty
配置的第二个虚拟控制台以进行本地登录。您可以添加有关所需击键的说明,/etc/issue
以便getty
在登录提示之前显示它。作为副作用,您的自定义login
脚本或二进制文件可以大大简化为基本上:
#!/bin/sh
REMOTEUSER="$1"
exec ssh -oEscapeChar=none "$REMOTEUSER"@your.server.example
该-oEscapeChar=none
选项将阻止使用 OpenSSH 转义按键,因此用户将无法使用 SSH 客户端配置端口转发或执行其他恶作剧(感谢 Ferrybig 提醒我!)。
由于login
(或其任何替代者)将以 root 身份运行,因此最好在exec()
执行该ssh
命令之前切换到某个非 root 用户。这是编译后的程序会更加灵活的地方。
如果您有一点编程经验,我建议您下载/bin/login
您选择的 Linux 发行版的源代码包,看看是否可以破解它来执行此操作。
基本上,您需要进行两项更改:您可以让您的替代者使用仅为传出 SSH 连接保留的硬编码用户名,而不是使用提供给getty
它的用户名作为参数来选择要登录的用户名。login
。您无需exec()
在登录过程结束时使用用户的 shell,而是使用exec()
SSH 命令,将您获得的用户名getty
和服务器名称作为参数提供给它。
答案2
我倾向于在 中/etc/profile
使用类似的东西(假设用户的 shell 是 bash 或 ksh 或其他使用 的东西/etc/profile
)来执行此操作:
if [[ $(ps h -o cmd $(ps h -o ppid $$)) =~ $(basename "$SHELL") ]] \
|| id | grep -q '(sshgroup)' \
&& fping -q remotehost; then
set -e # exit on any error, incl. user pressing ^C during
# ssh-keygen or ssh-copy-id
# generate a key if it doesn't already exist
if [ ! -e ~/.ssh/id_rsa ] then
ssh-keygen
fi
# install it on remote host if ~/.ssh/key-installed doesn't exist
if [ ! -e ~/.ssh/key-installed ] ; then
ssh-copy-id -i ~/.ssh/id_rsa.pub remotehost
touch ~/.ssh/key-installed
fi
# rewrite the following if any users have a shell which doesn't
# support arrays (ash, dash, posix sh, etc)
ssh_args=(-oEscapeChar=none)
exec ssh "${ssh_args[@]}" remotehost
fi
中文:如果父进程不是用户的shell和该用户是以下组织的成员sshgroup
和远程主机响应 ping,然后响应 ssh 到远程主机(并且因为ssh
是exec
-ed,一旦 ssh 会话结束,用户将立即注销)。否则登录将照常进行。组成员身份之前已进行测试fping
,因此非成员不必等待“fping”结果。
本地和远程主机上的文件中的适当消息/etc/motd
可用于突出显示它们最终位于哪台计算机上。
如果用户在远程主机上没有 ssh 密钥~/.ssh/authorized_keys
,那么它也会要求输入密码。脚本片段中的ssh-keygen
和内容ssh-copy-id
是如何防止这种情况的最低限度示例。它可能也应该运行ssh-agent
,-t 86400
这样他们只需每天输入一次密钥的密码,而不是每次登录时。
像这样检查组成员身份可以轻松排除某些用户(例如 root 或非 root 管理员帐户)自动 sshed 到远程主机。您可以反转测试并自动 ssh 任何用户不是特定群体的成员。