如何在 Go 中安全高效地将 SSH 公钥复制到远程服务器

本文介绍使用 Go 标准库 os/exec 直接将本地 SSH 公钥写入远程服务器 ~/.ssh/authorized_keys 的正确方法,避免 shell 字符串拼接风险,兼容 macOS/Linux 环境,且不依赖 ssh-copy-id。 本文介绍使用 go 标准库 `os/exec` 直接将本地 ssh 公钥写入远程服务器 `~/.ssh/authorized_keys` 的正确方法,避免 shell 字符串拼接风险,兼容 macos/linux 环境,且不依赖 `ssh-copy-id`。在 Go 中通过命令行方式(如 cat key.pub | ssh user@host 'cat >> ~/.ssh/authorized_keys')实现公钥分发看似直观,但原代码存在多个关键问题: ? 错误调用 exec.Command(identity, address):将两个独立命令(cat ... 和 ssh ...)作为参数传给单个 exec.Command,实际会尝试执行名为 cat /home/foo/.ssh/foobar.pub 的二进制文件(显然不存在); ? 未正确构建管道逻辑:Go 的 exec.Command 不会自动解析 shell 管道符 |,需显式设置 Stdin; ? 路径硬编码与拼接风险:~/.shh/authorized_keys(注意 typo:shh 应为 ssh)和字符串格式化易引入路径注入或权限错误; ? 忽略 SSH 连接前置条件:如目标用户 .ssh 目录权限(应为 700)、authorized_keys 文件权限(推荐 600),否则 OpenSSH 会拒绝加载。? 正确做法是:用 Go 原生读取公钥文件内容,并将其作为 stdin 流式传递给 ssh 进程。这样既规避了 shell 解析的不确定性,又提升安全性与可移植性。以下是完整、健壮的实现:import ( "io" "log" "os" "os/exec" "path/filepath")func copySSHPubKeyToServer(username, hostname, keyName string) error { // 1. 构建公钥文件路径(使用 filepath.Join 避免路径拼接漏洞) homeDir := os.Getenv("HOME") if homeDir == "" { return fmt.Errorf("HOME environment variable not set") } keyPath := filepath.Join(homeDir, ".ssh", keyName+".pub") // 2. 打开公钥文件 keyFile, err := os.Open(keyPath) if err != nil { return fmt.Errorf("failed to open public key %s: %w", keyPath, err) } defer keyFile.Close() // 3. 构建 ssh 命令:注意目标路径必须为 ~/.ssh/authorized_keys(修正 typo) // 使用绝对路径更可靠(如 $HOME/.ssh/authorized_keys),但 ~ 在 ssh 上下文中通常可被服务端 shell 展开 sshTarget := username + "@" + hostname cmd := exec.Command("ssh", sshTarget, "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys") // 4. 将公钥文件设为命令标准输入 cmd.Stdin = keyFile // 5. 捕获输出以便调试 output, err := cmd.CombinedOutput() if err != nil { log.Printf("SSH command failed (output: %s)", string(output)) return fmt.Errorf("failed to copy SSH key to %s: %w", sshTarget, err) } log.Printf("Successfully added %s.pub to %s's authorized_keys", keyName, sshTarget) return nil}? 关键注意事项: RedClaw 百度推出的手机端万能AI Agent助手

相关推荐
2401_891409262 小时前
量化数据13:港股分钟K线、Level2逐笔Tick、十档盘口和港股通历史数据的批量提取
数据库
实名上网宋凯宣7 小时前
Django
后端·python·django
w-w0w-w8 小时前
SQL注入
网络·数据库·sql
tianyuanwo8 小时前
NetBox 数据库详解:当“关系型数据库”被装进一个网络运维的领域模型里
运维·数据库·netbox
一条泥憨鱼8 小时前
【计算机网络】短连接、长连接与连接池:从 TCP 握手到池化复用的完整链路
网络·数据库·网络协议·tcp/ip·计算机网络
如若1238 小时前
【论文复现】CoFailMed:从零复现医学图像分割的共享失败审计,含完整代码流程与科研绘图
人工智能·python
IvorySQL8 小时前
深入 PostgreSQL WAL:从崩溃恢复到逻辑复制
数据库·postgresql
幽灵诶10 小时前
Mysql(基于测试的学习)
数据库·mysql
砚底藏山河10 小时前
python量化自定义周期 K 线合成
java·开发语言·数据库·python·金融
视觉小萌新10 小时前
AI Class 3 · Chapter 1:变量、字符串、list/dict、if/for(python学习-小白版-有经验可跳过)
python·学习·list