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:指定保存路径和文件名
执行后,系统会问你两次:
- 要不要设置passphrase(私钥密码)?
- 确认一遍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_config中PubkeyAuthentication是否为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端口,默认22IdentityFile:指定私钥路径ServerAliveInterval:每隔多少秒发一个心跳包,防止连接断开ServerAliveCountMax:连续多少次心跳无响应后断开连接ProxyJump:通过跳板机连接,非常实用
我的习惯:我会给每块Jetson板子单独配一个Host条目,命名规则是「板子型号-用途」。比如jetson-orin-dev、jetson-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 完整流程总结
来,我们捋一遍完整流程:
- 开发机上:生成密钥对(推荐ED25519)
- 开发机上:用
ssh-copy-id把公钥部署到Jetson - Jetson上:确认
~/.ssh目录权限700,authorized_keys权限600 - 开发机上:配置
~/.ssh/config,设置别名 - 开发机上:启动ssh-agent,添加私钥(如果设了passphrase)
- Jetson上:测试通过后,禁用密码登录
这套流程走完,你以后登录Jetson就是一句话的事:
ssh jetson-orin
没了。不用输IP,不用输用户名,不用输密码。SCP传文件、VS Code Remote、Ansible批量部署,全都自动走密钥认证。
这才是嵌入式开发该有的效率。