SSH与TLS双向认证对比
服务器获取客户端公钥主要通过三种路径:在SSH认证中由客户端将公钥文件主动上传至服务器,在TLS握手时通过客户端证书直接提取,或通过Diffie‑Hellman等密钥交换协议间接派生,下文逐一拆解每种场景的实现步骤与原理,并对比不同方案的安全性与适用场景。
SSH服务器如何添加客户端公钥:标准操作流程
SSH公钥认证是服务器获得客户端公钥最直观的场景,客户端生成密钥对后,将公钥内容追加到服务器端~/.ssh/authorized_keys文件中,服务器即可使用该公钥验证客户端的签名。
操作步骤
- 客户端生成密钥对:
ssh‑keygen -t rsa -b 4096 -C "your_email@example.com" - 将公钥传输到服务器:
ssh‑copy-id user@server_ip,或手动执行cat ~/.ssh/id_rsa.pub | ssh user@server_ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" - 设置服务器端文件权限:
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys - 验证:
ssh user@server_ip应无需密码直接登录
关键点
- 服务器不会主动生成客户端的公钥,公钥必须由客户端产生并传递。
ssh‑copy-id工具会自动处理目录权限和追加操作,较手动方式更安全。- 一台服务器可以存储多个客户端的公钥,每个公钥占据一行。
- 业内专家指出,公钥文件权限设置不正确是免密登录失效的常见原因,
authorized_keys文件必须对除属主外的用户无写权限。
服务器获取客户端公钥原理:TLS双向认证中的证书提取
在HTTPS双向认证(mTLS)场景下,服务器通过客户端证书获得公钥,握手阶段服务器发送CertificateRequest请求,客户端将证书链发送给服务器,服务器从证书的
SubjectPublicKeyInfo字段中提取公钥,并利用证书签发机构的公钥验证证书合法性。
流程拆解
- 服务器发送
CertificateRequest,指定可接受的CA列表。 - 客户端发送
Certificate消息,包含符合要求的客户端证书。 - 服务器验证证书签名、有效期、吊销状态后,提取公钥。
- 若服务器使用该公钥加密随机数,则客户端必须拥有对应私钥才能解密,完成双向身份认证。
适用场景
- 企业内部应用间的API通信,要求客户端持有合法证书。
- 金融级接口调用,对客户端身份验证强度要求高。
- 与SSH公钥上传相比,TLS证书方式不需要逐台服务器手动添加公钥,只需维护统一的CA即可管理大量客户端,规模化部署效率更高。
客户端公钥传输到服务器方式对比:SSH上传与TLS证书
| 对比维度 | SSH公钥认证 | TLS双向认证 |
|---|---|---|
| 公钥传输方式 | 客户端手动上传或ssh‑copy-id |
握手阶段自动携带 |
| 公钥管理 | 分散在每台服务器的authorized_keys文件 |
集中由CA签发,服务器端配置信任链 |
| 安全性 | 依赖公钥文件完整性,私钥泄露风险 | 证书链验证,可集成OCSP/CRL吊销 |
| 配置复杂度 | 低,单台或少量服务器友好 | 较高,需要搭建或使用已有CA |
| 适用规模 | 推荐20台以内 | 适合大规模集群或微服务架构 |
行业共识认为,双向认证在安全性上优于静态公钥文件,但SSH公钥方式凭借其简单直接,仍被相当一部分中小团队采用,选择哪种方式取决于你对运维成本和认证强度的权衡。
公钥认证服务器配置工具:OpenSSH与Nginx实际设置
OpenSSH公钥认证设置
编辑/etc/ssh/sshd_config,确保以下参数开启:
PubkeyAuthentication yesAuthorizedKeysFile .ssh/authorized_keysPasswordAuthentication no(关闭密码登录以增强安全性)
重启服务:systemctl restart sshd
Nginx 客户端证书验证配置
在server块中启用:
ssl_client_certificate /etc/nginx/ca.crt;
ssl_verify_client on;
ssl_verify_depth 1;
我们可以通过配置实现获取客户端公钥两种常用方式:对于SSH,将公钥写入authorized_keys;对于TLS,指定CA证书路径并开启验证,Nginx会自动提取客户端证书中的公钥供后续处理。
检查客户端公钥是否成功上传服务器的命令
- 查看
authorized_keyscat ~/.ssh/authorized_keys - 验证SSH公钥指纹:
ssh‑keygen -lf ~/.ssh/id_rsa.pub - 查看TLS握手日志:
openssl s_client -connect server:443 -cert client.pem -key client.key
实操中容易卡住的几个细节
权限问题
SSH公钥认证长期无法生效,多数是因为.ssh目录权限大于700,或authorized_keys权限大于600,服务器会严格检查文件属主和权限,任何偏离都会导致公钥被忽略。
公钥格式错误
复制公钥时误拷贝了换行或额外字符,建议使用ssh‑keygen -y -f private_key重新生成公钥字符串,确保格式正确。
CA证书链不完整
TLS双向认证中,服务器必须拥有完整的CA证书链才能验证客户端证书,如果只配置了根证书,而客户端证书由中间CA签发,验证会失败,需要将中间CA证书一并配置到
ssl_client_certificate指向的文件中。
关于服务器获取客户端公钥的常见问题
服务器怎么获得客户端的公钥生成?
服务器无法参与客户端公钥的生成,公钥必须由客户端在本地通过密钥生成工具(如ssh‑keygen、openssl genrsa)产生,然后通过安全通道(如SSH拷贝、HTTPS上传)交付给服务器,服务器仅负责存储或验证公钥,不会主动生成。
SSH服务器如何添加客户端公钥才能避免被覆盖?
使用追加模式而非覆盖模式。ssh‑copy-id工具会自动追加,手动操作时使用cat file >> authorized_keys(双大于号),切勿使用>单大于号,否则会清空已有公钥,若需批量添加,可编写脚本逐行追加,或使用配置管理工具如Ansible的authorized_key模块。
客户端公钥丢失后服务器端如何清理?
登录服务器,编辑对应客户端用户的authorized_keys文件,删除该公钥所在行,若无法确定是哪一行,可通过公钥指纹匹配:在服务器执行ssh‑keygen -lf .ssh/authorized_keys列出所有公钥指纹,再与客户端本地ssh‑keygen -lf id_rsa.pub的输出比对,确认后手动删除。
服务器通过客户端证书获取公钥时,如何验证证书的有效性?
服务器会检查证书的签名是否由受信任的CA签发、证书是否在有效期内、是否已被吊销(通过OCSP或CRL)。ssl_verify_client on开启后,Apache/Nginx等服务器会自动完成这些校验,拒绝无效证书的握手请求,整个验证过程在握手阶段完成,无需额外手工操作。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/554413.html



