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_PRELOAD
和LD_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 环境变量的主要内容,如果未能解决你的问题,请参考以下文章