在screen会话中访问SSH客户端IP地址

4

通过环境变量(例如SSH_CONNECTION)可以访问连接的SSH客户端的IP地址,如

在SSH会话中查找客户端的IP地址所述。

然而,在GNU screen会话中,这些环境变量是由启动screen的人定义的。有没有办法获取SSH连接信息,例如从另一个主机进入已存在的screen会话的人?

我想不到一种方法来确定这一点,但在屏幕会话在不同人之间共享的情况下,这可能是有用的。


这个链接问题有几个答案,其中一些涉及环境变量以外的事情。 - n. m.
可能是这样,但我仍然想知道是否有一种方法可以确定在屏幕会话中由谁调用了某个脚本,特别是如果屏幕会话可能被不同的人共享。 - weiresr
您可以遍历当前进程的PPID并查看它们的环境变量和标准句柄(在Linux上通过/proc)。 - n. m.
@n.m. - 我仍然不明白这如何帮助我区分不同的客户端。假设两个客户端(两个用户)通过不同的IP连接SSH到机器上,比如作为root用户。如果他们都在给定的屏幕会话(screen -x)中活动,并且其中一个在此处调用脚本-是否有任何方法可以告诉我们哪个客户端(即通过SSH客户端IP)实际上执行了此操作?在这种情况下,PPID将是相同的。 - weiresr
2
嗯,不,这是不可能的。这就像让几个人在你的键盘上打字,然后试图确定谁打了什么。一个人可能打了 l,另一个人打了 s,还有另一个人按了回车键,那么是谁调用了 ls?这与 screen 完全相同。 - n. m.
好的,这正是我担心的。我曾经想过是否有其他方法可以解决。感谢您的回答 - 请放心将其放入完整的答案中,而不是评论中,我已为此悬赏 :) - weiresr
5个回答

1
如果以root身份启动screen会话,你可以这样做,但它不会完全可靠。
1. 如果两个用户在同一个screen窗口中输入,他们将在同一个shell中进行交互。一个人可以写一个命令,另一个人可以按键。 2. 您必须访问环境变量SSH_CONNECTION(或更好的是SSH_CLIENT),这仅在您是root或在screen会话中使用相同的用户时才可能。 假设您是screen会话中的root用户,则可以使用ps命令找到最后一个活动会话,并知道上一个活动的用户。
ps h -C screen katime -o pid,user

通过使用进程ID(pid),访问/proc/<pid>/environ文件,您可以获取SSH_CLIENT变量。
sed -z '/SSH_CLIENT/p;d' /proc/`ps h -C screen katime -o pid |head -1`/environ

--> SSH_CLIENT=257.31.120.12

这都假设你的屏幕是以root身份运行的。
您还可以选择记录所有活动连接。为此,我建议您存储连接的完整列表及其最后活动时间。
ps eh -C screen kstime -o pid,atime | while read pid stime; do echo -n "$stime: ";\
    gawk -v 'RS=\0' -F= '$1=="SSH_CLIENT" {print $2}' /proc/$pid/environ; done

Result:
00:00:00: 257.31.120.12 61608 22
00:07:11: 258.1.2.3.4 49947 22

请注意,如果您发现这更容易,还可以解析ps eh -C screen kstime -o args 命令的结果。 编辑: 以下是一个可用的Debian命令,用于获取当前连接到同一屏幕会话的所有用户:
 find /var/run/screen/
     -name $(pstree -sp $$ |sed 's/.*screen(\([0-9]*\)).*/\1/;q').*
     -printf "%h\n"
      | cut -f2 -d-

感谢您所付出的努力!正如您所说,并不是所有情况都适用,但对于我感兴趣的情况来说,这种方式已经足够覆盖了。 - weiresr

0

看看SSHLog:https://github.com/sshlog/agent/

这是一个守护进程,监视SSH登录以及用户活动。您可以获取已登录用户列表,他们连接的IP地址,记录他们的命令,甚至可以跳转到他们的会话并与他们共享终端。


0
您可以通过检查last命令的输出来列出所有连接的IP地址主机名,如果sshd是连接服务器的唯一方式。
ec2-user]# last
ec2-user pts/0        115.250.185.183  Sun May 29 13:49   still logged in
ec2-user pts/0        115.250.140.241  Sat May 28 07:26 - 10:15  (02:48)
root     pts/4        113.21.68.105    Tue May  3 10:15 - 10:15  (00:00)

另外(在Linux上),您可以检查/var/log/secure,其中sshd通常会记录所有连接的详细信息,即使它们没有成功登录。


到目前为止,这对我的问题没有太大帮助。我在机器上有一些脚本,可以由具有SSH访问权限的不同人员调用(来自不同的客户端IP)。当调用它们时,这些脚本会记录谁(即:客户端IP)何时调用它们。为了确定客户端IP,我使用SSH_CONNECTION的信息 - 除非使用屏幕会话(特别是共享会话),否则效果很好。我想知道是否有一种可靠的方法可以知道谁从屏幕会话中调用了脚本(可能有多个人同时登录)。 - weiresr
@weiresr 有趣的问题,但在我看来这是设计上不可能的。当您附加一个屏幕会话时,您会冒充启动会话的用户(或更好地说,会话中的程序)-带来所有的后果。 - hek2mgl
1
@hek2mgl 最近我看到的一件事是,你至少可以在屏幕上获取已连接显示器的列表(C-a:displays)。这样的东西可能有助于我朝着某个方向前进 - 但我不知道是否可能脚本化访问该信息,即使可以,它也无法告诉我(按设计)哪一个触发了某个命令,如果当前连接了多个显示器。 - weiresr
1
@weiresr 我编辑了自己的回答,添加了一个示例,展示如何使用 /var/run/screen 目录实现。 - Adam

0

如果您正在尝试支持多显示器模式('screen -x'),那么正如上面有人所说,您可能没有办法。

另一方面,如果您可以假定为单用户模式,则可以为screen命令创建一个包装器/别名,该别名将环境变量传递到screen中(参见'screen -X stuff ...');在这种情况下,您只是传递了SSH_CLIENT,它将具有适当的值。

如果您可以假定给定的用户名来自单个位置(或者,如果来自多个位置,则选择最近的位置),则可以对“last”命令的输出进行一些grep/sed操作。

client_ip=`last -ai | grep "still logged in" | grep "$USER " | grep -v '0.0.0.0' | tail -n 1 | sed 's/.* //g'`
echo "Hello $client_ip"

感谢您的输入,但在屏幕内部,SSH_TTY(就像SSH_CONNECTION一样)给出了启动屏幕的人的值。因此,如果我再次从另一个SSH会话进入现有屏幕,则似乎也无法通过这种方式获得我当前连接的TTY。 - weiresr
你是正确的。我不确定如何处理多显示器情况,但如果某种方式适用于您,我会思考单用户模式。 - Alireza
我主要对一般的-screen -x情况感兴趣,因为我们经常有多个人同时在同一个屏幕上。还是很有趣了解更多选项,谢谢 :) - weiresr

-1
如果您的屏幕通常在分离模式下启动,则在您的.screenrc文件中添加以下内容:
shell -$SHELL

然后你的屏幕将拥有所有变量。 对于当前运行的屏幕,你可以简单地运行。

source ~/.bash_profile

请将路径和文件名更改为适合您的环境。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接