Golang SSH 加载 LD_PRELOAD 和 LD_LIBRARY_PATH 环境变量

Posted

技术标签:

【中文标题】Golang SSH 加载 LD_PRELOAD 和 LD_LIBRARY_PATH 环境变量【英文标题】:Golang SSH load LD_PRELOAD and LD_LIBRARY_PATH environment variables 【发布时间】:2017-08-01 17:42:28 【问题描述】:

我正在尝试使用 Golang SSH package 连接到远程服务器,但我的工作站和此远程服务器之间存在 SOCKS。

我可以通过简单地设置 LD_PRELOAD 和 LD_LIBRARY_PATH 然后运行来连接到服务器:

$ export LD_PRELOAD="/path/to/lib"
$ export LD_LIBRARY_PATH="/path/to/lib"
$ ssh user@hostname

但是当我在 Go 代码中设置这些变量时,它不起作用:

os.Setenv("LD_PRELOAD", "/path/to/file")
os.Setenv("LD_LIBRARY_PATH", "/path/to/file")

如果我在 Go 代码中设置这些变量并尝试以下操作,它会起作用:

ssh := exec.Command("ssh", "hostname")
output, _ := ssh.Output()
fmt.Println(string(output))

ssh PermitUserEnvironment 设置为yes

有没有办法“强制”Golang SSH 使用这些环境变量?

【问题讨论】:

LD_PRELOAD 和 LD_LIBRARY_PATH 与 ssh 本身无关,就是将一些共享库注入到您的 openssh 进程中。如果您不使用 openssh 二进制文件,则无法将其他共享库预加载到其中。 【参考方案1】:

(编辑:此答案不一定适用于 Go 1.8 及更高版本。请参阅 cmets 进行讨论)

LD_PRELOADLD_LIBRARY_PATH是程序启动时由dynamic linker处理的环境变量。如果您在程序中设置这些环境变量,它们不会对程序本身产生影响,因为链接器看不到它们。

另一方面,环境变量会影响您在程序内运行的外部应用程序(例如ssh 命令),因为链接器被赋予了解析应用程序使用的共享库的控制权。

如果你在运行 Go 程序之前设置这些环境变量,我想你会得到想要的效果。(这仅适用于编译程序链接到共享标准 C 库的情况. 更多详情请参阅下面@JimB 的 cmets。)

【讨论】:

不,这不会产生预期的效果,因为 Go 不使用 C 库套接字调用被覆盖。很有可能 Go 程序在运行时不使用任何 C 共享库(尽管 std 库在启用时使用 cgo 作为解析器和用户数据库),并且可能是完全静态链接的 @JimB 感谢您指出这一点!在快速验证确实如此之后,我已根据您的评论更新了我的答案。 你确定吗? ssh 包中的Dial() 函数使用net 包中的DialTimeout()。我编写了一个使用DialTimeout() 的简单程序,并且我能够使用LD_PRELOAD 通过SOCKS 代理建立隧道。 (这是在 Linux 上,CGO_ENABLED 设置为 true / undefined。go build 生成了一个我测试过的动态链接的可执行文件..) 哦对了,我忘了它只需要拦截Dial。但是我认为当前版本的 Go 已经开始默认使用本地拨号器,除非本地配置文件需要。你用的是什么版本的围棋? (即便如此,您仍然可以export GODEBUG=netdns=cgo 强制 cgo 解析器) 好吧,我就是这么想的。因此,如果您想依赖 LD_PRELOAD,则需要在 所有 情况下强制使用主机解析器,您可以使用 GODEBUG=netdns=cgo 或使用 netcgo 标记进行构建。

以上是关于Golang SSH 加载 LD_PRELOAD 和 LD_LIBRARY_PATH 环境变量的主要内容,如果未能解决你的问题,请参考以下文章

LD_PRELOAD加载动态库

使用Linux功能是否会禁用LD_PRELOAD

使用LD_PRELOAD拦截共享函数库的函数调用

如何防止 LD_PRELOAD 或 ld.so.preload 配置?

一种简单的hook方法--LD_PRELOAD变量

golang SSH客户端三件套 - 1远程连接 shell