4、密钥认证与免密登录:RSA/ED25519密钥对生成、公钥部署到Jetson、SSH config文件配置与别名登录

每次SSH登录都要输密码,说实话,挺烦的。

尤其是你一天要连几十次Jetson,输密码输到手指酸。更别提那些自动化脚本、SCP传文件、VS Code Remote开发——密码认证根本走不通。

所以,密钥认证是远程开发的必修课。今天我把这套流程拆开揉碎了讲,你跟着做一遍,以后登录Jetson就跟打开本地终端一样快。

4.1 为什么选密钥认证?

密码认证有个硬伤:它依赖「你知道什么」。密钥认证依赖「你有什么」——你手里有一把私钥,Jetson上存着对应的公钥。

私钥不出你的电脑,公钥随便给。黑客就算攻破了服务器,拿到的也只是公钥,没有私钥照样进不来。

我个人习惯,所有嵌入式设备一律禁用密码登录。为什么?

  • 安全:暴力破解密码的脚本满大街都是,但破解RSA 4096位密钥?算了吧
  • 方便:配一次,用到天荒地老
  • 自动化:脚本、CI/CD、Ansible,全都依赖密钥认证

核心原则:私钥永不离机,公钥随意部署。

4.2 选RSA还是ED25519?

这是个经典选择题。我直接给结论:

算法 密钥长度 安全性 性能 兼容性
RSA 2048/4096位 高(4096位) 较慢 极好(所有SSH客户端都支持)
ED25519 256位 极高(相当于RSA 3000+位) 极快 好(OpenSSH 6.5+支持)

我的建议:优先用ED25519。Jetson的Linux内核版本够新,完全兼容。ED25519密钥短、生成快、安全性还更高。

但如果你要连一些老旧的嵌入式设备(比如某些工业级ARM板,SSH版本还停留在5.x),那就老老实实用RSA 2048位。

我的经验:我在一个项目里遇到过Jetson Nano连一个老款路由器做跳板机,ED25519死活不认。查了半天,发现那路由器的Dropbear版本太旧。最后换成RSA 2048,问题解决。所以,如果你不确定目标设备的SSH版本,RSA 2048是最稳妥的选择。

4.3 生成密钥对

在你的开发机上操作(Windows用PowerShell,Linux/macOS用终端)。

生成ED25519密钥对:

ssh-keygen -t ed25519 -C "jetson-dev-key" -f ~/.ssh/jetson_ed25519

生成RSA 4096位密钥对:

ssh-keygen -t rsa -b 4096 -C "jetson-dev-key" -f ~/.ssh/jetson_rsa

参数说明:

  • -t:指定算法类型
  • -b:RSA专用,指定位数
  • -C:注释,方便你区分多把密钥
  • -f:指定保存路径和文件名

执行后,系统会问你两次:

  1. 要不要设置passphrase(私钥密码)?
  2. 确认一遍passphrase。

这里有个坑:passphrase要不要设?

设了,每次用私钥都要输一次密码,但私钥文件被盗了对方也用不了。不设,私钥文件丢了就完了。

我个人习惯:开发机设passphrase,配合ssh-agent缓存。这样只用输一次密码,后续免密。CI/CD或自动化脚本用的密钥,不设passphrase,但严格控制文件权限。

生成完成后,你会看到两个文件:

~/.ssh/jetson_ed25519      # 私钥(自己留着,权限600)
~/.ssh/jetson_ed25519.pub  # 公钥(部署到Jetson)

警告:私钥文件权限必须设为600(仅所有者可读写)。如果权限不对,SSH会直接拒绝使用这把密钥。

chmod 600 ~/.ssh/jetson_ed25519

4.4 公钥部署到Jetson

公钥部署有三种方式,我按推荐程度排序:

方式一:ssh-copy-id(最推荐)

ssh-copy-id -i ~/.ssh/jetson_ed25519.pub jetson@192.168.1.100

这条命令会自动把公钥追加到Jetson的~/.ssh/authorized_keys文件里。一次搞定,不用手动操作。

方式二:手动追加

如果Jetson上没有ssh-copy-id命令(某些精简系统确实没有),那就手动来:

# 在开发机上查看公钥内容
cat ~/.ssh/jetson_ed25519.pub

# 复制输出内容,然后SSH登录Jetson
ssh jetson@192.168.1.100

# 在Jetson上执行
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "你的公钥内容" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

方式三:SCP上传(适合批量部署)

scp ~/.ssh/jetson_ed25519.pub jetson@192.168.1.100:/tmp/
ssh jetson@192.168.1.100 "cat /tmp/jetson_ed25519.pub >> ~/.ssh/authorized_keys && rm /tmp/jetson_ed25519.pub"

避坑指南:我曾经帮同事排查一个问题,密钥部署了但死活登不上。最后发现是authorized_keys文件的权限不对——他设成了644。记住,这个文件必须是600,目录必须是700。SSH对权限检查非常严格,差一点都不行。

4.5 验证密钥登录

部署完成后,测试一下:

ssh -i ~/.ssh/jetson_ed25519 jetson@192.168.1.100

如果一切正常,你会直接登录成功,不需要输密码。如果还是提示输入密码,检查以下几点:

  • Jetson上/etc/ssh/sshd_configPubkeyAuthentication是否为yes
  • Jetson上~/.ssh目录权限是否为700
  • Jetson上~/.ssh/authorized_keys权限是否为600
  • 公钥内容是否完整复制(注意不要有多余换行或空格)

4.6 SSH config文件配置与别名登录

每次都要输ssh -i ~/.ssh/jetson_ed25519 jetson@192.168.1.100,太长了。而且IP地址记不住。

SSH config文件就是来解决这个问题的。

在开发机上编辑~/.ssh/config文件(没有就新建):

# Jetson Orin NX - 开发板
Host jetson-orin
    HostName 192.168.1.100
    User jetson
    Port 22
    IdentityFile ~/.ssh/jetson_ed25519
    ServerAliveInterval 60
    ServerAliveCountMax 3

# Jetson Nano - 测试板
Host jetson-nano
    HostName 192.168.1.101
    User nvidia
    Port 2222
    IdentityFile ~/.ssh/jetson_rsa
    ServerAliveInterval 30

# 跳板机配置(如果Jetson在内网)
Host jetson-prod
    HostName 10.0.0.50
    User jetson
    ProxyJump jump-server
    IdentityFile ~/.ssh/jetson_ed25519

配置好之后,登录就变成了:

ssh jetson-orin
ssh jetson-nano
ssh jetson-prod

是不是清爽多了?

几个关键参数说明:

  • Host:你给这个连接起的别名,随便取
  • HostName:目标IP或域名
  • User:登录用户名
  • Port:SSH端口,默认22
  • IdentityFile:指定私钥路径
  • ServerAliveInterval:每隔多少秒发一个心跳包,防止连接断开
  • ServerAliveCountMax:连续多少次心跳无响应后断开连接
  • ProxyJump:通过跳板机连接,非常实用

我的习惯:我会给每块Jetson板子单独配一个Host条目,命名规则是「板子型号-用途」。比如jetson-orin-devjetson-nano-test。这样一看名字就知道连的是哪块板子,不会搞混。

4.7 进阶:ssh-agent与密钥缓存

如果你给私钥设了passphrase,每次SSH都要输一次密码,那免密登录的意义就打了折扣。

解决方案:用ssh-agent缓存私钥。

启动ssh-agent并添加私钥:

# 启动agent
eval "$(ssh-agent -s)"

# 添加私钥
ssh-add ~/.ssh/jetson_ed25519

# 查看已添加的密钥
ssh-add -l

添加时输入一次passphrase,之后在当前会话中所有SSH连接都不需要再输密码了。

如果你用的是macOS,还可以把私钥添加到钥匙串:

ssh-add --apple-use-keychain ~/.ssh/jetson_ed25519

这样重启电脑后都不用重新添加,系统自动帮你加载。

避坑指南:我曾经在Ubuntu上遇到过一个问题——每次打开新终端都要重新运行ssh-add。后来发现是ssh-agent没有在登录时自动启动。解决方案是在~/.bashrc~/.zshrc里加一段判断:

if [ -z "$SSH_AUTH_SOCK" ]; then
    eval "$(ssh-agent -s)" > /dev/null
    ssh-add ~/.ssh/jetson_ed25519 2>/dev/null
fi

这样每次打开终端,agent自动启动,密钥自动加载。省心多了。

4.8 安全加固:禁用密码登录

密钥认证跑通之后,我建议你立即禁用密码登录。这样即使有人猜到了你的用户名和密码,也进不来。

在Jetson上编辑/etc/ssh/sshd_config

# 找到下面两行,修改为:
PasswordAuthentication no
ChallengeResponseAuthentication no
# 确保下面这行是yes
PubkeyAuthentication yes

重启SSH服务:

sudo systemctl restart sshd

重要提醒:在禁用密码登录之前,务必确认密钥认证已经能正常工作。否则你把自己锁在外面,就只能去接显示器和键盘了。我见过不止一个同事犯过这种错误……

4.9 完整流程总结

来,我们捋一遍完整流程:

  1. 开发机上:生成密钥对(推荐ED25519)
  2. 开发机上:用ssh-copy-id把公钥部署到Jetson
  3. Jetson上:确认~/.ssh目录权限700,authorized_keys权限600
  4. 开发机上:配置~/.ssh/config,设置别名
  5. 开发机上:启动ssh-agent,添加私钥(如果设了passphrase)
  6. Jetson上:测试通过后,禁用密码登录

这套流程走完,你以后登录Jetson就是一句话的事:

ssh jetson-orin

没了。不用输IP,不用输用户名,不用输密码。SCP传文件、VS Code Remote、Ansible批量部署,全都自动走密钥认证。

这才是嵌入式开发该有的效率。