如何在AWS Lambda中通过Paramiko使用公钥连接非AWS on-prem服务器
问题结论:无法仅使用on-prem主机的公钥完成Paramiko SSH连接认证
核心原理说明
SSH公钥认证的逻辑是非对称加密的签名-验签机制:
- 你手里的on-prem主机公钥属于服务端主机密钥对的公钥部分,仅用于你作为客户端校验所连接的主机是否为合法目标,防范中间人攻击,不能用于证明你作为客户端的登录身份。
- 用于客户端身份认证的是另一套独立的客户端密钥对:你需要将该密钥对的公钥提前部署到on-prem主机对应用户的
~/.ssh/authorized_keys文件中,发起连接时由客户端(也就是AWS Lambda)持对应的私钥完成身份签名验证,才能成功登录。
正确操作步骤
- 生成客户端认证密钥对:在本地执行命令
ssh-keygen -t ed25519 -f lambda_ssh_key,执行时无需设置密码,得到公钥文件lambda_ssh_key.pub和私钥文件lambda_ssh_key - 配置on-prem主机权限:将
lambda_ssh_key.pub的内容追加到on-prem主机登录用户的~/.ssh/authorized_keys文件中,同时设置正确的目录/文件权限:chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys - 配置Lambda侧的私钥存储:将私钥内容存入AWS Secrets Manager或Systems Manager Parameter Store,给Lambda执行角色配置对应密钥的读取权限,禁止硬编码私钥到代码中
- Paramiko连接示例代码:
import paramiko import boto3 import io import base64 from botocore.exceptions import ClientError # 从Secrets Manager读取私钥 secretsmanager = boto3.client('secretsmanager') try: get_secret_value_response = secretsmanager.get_secret_value( SecretId='替换为你存储私钥的Secret ID' ) except ClientError as e: raise e private_key_content = get_secret_value_response['SecretString'] private_key = paramiko.Ed25519Key.from_private_key(io.StringIO(private_key_content)) # 配置SSH客户端 ssh = paramiko.SSHClient() # 加载你已有的on-prem主机公钥,用于验证主机身份 ssh.get_host_keys().add('替换为on-prem主机IP', 'ssh-ed25519', paramiko.Ed25519Key(data=base64.b64decode('替换为on-prem主机公钥的base64内容部分'))) # 连接主机 ssh.connect(hostname='替换为on-prem主机IP', username='替换为登录用户名', pkey=private_key) # 传输文件用SFTPClient sftp = ssh.open_sftp() sftp.put('Lambda侧待传输文件路径', 'on-prem主机目标存储路径') sftp.close() ssh.close()
额外注意事项
- 如果你不需要校验主机身份(不推荐,存在中间人攻击风险),可以临时设置
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())跳过主机公钥校验,此时你手里的on-prem主机公钥可以不用配置 - 确保Lambda所在网络可以和on-prem主机的22端口连通,通常需要配置AWS Direct Connect或者VPN打通VPC和本地机房网络
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

