智能卡ssh认证需pcscd与opensc协同运行,路径须绝对且可读,pin由ssh-agent缓存,selinux可能拦截pkcs11.so;任一环节静默失效均导致认证失败。

OpenSC 和 pcscd 服务必须同时运行
智能卡 SSH 认证不是插上卡就自动生效的,底层依赖 PC/SC 框架与 OpenSC 的协同。如果 pcscd 没启动,或 opensc-pkcs11.so 找不到卡,ssh 就会静默跳过智能卡密钥——连错误都不报,只回退到密码登录。
-
sudo systemctl start pcscd并启用开机自启(sudo systemctl enable pcscd) - 确认 OpenSC 已安装:Debian/Ubuntu 装
opensc包,RHEL/CentOS 装opensc+pcsc-lite - 用
pkcs11-tool --module /usr/lib/opensc-pkcs11.so -T测试模块是否能枚举令牌;若报CKR_TOKEN_NOT_RECOGNIZED,大概率是pcscd没跑,或卡没被识别
ssh_config 中 PKCS#11Provider 路径必须绝对且可读
OpenSSH 9.0+ 支持直接通过 PKCS#11Provider 加载智能卡密钥,但路径写错、权限不对、或用了相对路径,都会让 SSH 完全忽略该行,不提示、不报错、也不尝试。
- 路径必须是绝对路径:
PKCS#11Provider /usr/lib/opensc-pkcs11.so,不能写成libopensc-pkcs11.so或./opensc-pkcs11.so - 确保用户对
.so文件有读权限(ls -l /usr/lib/opensc-pkcs11.so),否则 SSH 会静默失败 - 如果系统是多架构(如 aarch64/x86_64 混合),注意路径可能是
/usr/lib64/opensc-pkcs11.so,别硬套 x86 习惯
私钥提取不是必须步骤,但绕不开 PIN 缓存机制
有人想把智能卡里的私钥导出成 id_rsa 用,这是错的——合规智能卡(如 PIV、CNSA 卡)根本禁止私钥导出。SSH 必须实时调用 PKCS#11 接口签名,每次连接都需输入 PIN,体验差就在这里。
- 可用
ssh-add -s /usr/lib/opensc-pkcs11.so把令牌“加载”进 ssh-agent,之后同一 session 内免重复输 PIN(但 agent 重启后仍要重输) - 不要试图用
pkcs11-tool --read-object提取私钥,多数卡返回CKR_ATTRIBUTE_SENSITIVE或直接拒绝 - 某些环境(如 GNOME Keyring)会拦截 PIN 输入,导致
ssh-add -s卡住;此时改用终端直连,或临时停用 keyring
sshd 侧无需额外配置,但 SELinux 可能拦住 pkcs11.so
服务端不用装 OpenSC,也不用改 sshd_config——智能卡认证完全在客户端完成,服务端只认标准 SSH 公钥格式。但如果你在 RHEL/CentOS 上遇到连接中断、日志里只有 Connection closed by authenticating user,很可能是 SELinux 阻止了 sshd 进程加载 PKCS#11 模块(即使你只在 client 端用,agent 转发时也可能触发)。
- 先临时设为 permissive:
sudo setenforce 0,确认是否解决;若是,说明 SELinux 策略限制了 pkcs11 模块访问 - 允许 sshd 加载第三方库:
sudo setsebool -P ssh_sysadm_login on或定制策略模块(audit2allow -a -M mysshpkcs) - 检查
ausearch -m avc -ts recent | grep sshd是否有avc: denied ... pkcs11.so类似记录
pcscd、模块路径、PIN 输入上下文、SELinux 策略,任一环断掉都只会让你以为“卡没反应”,实际它早就在某处默默放弃了。










