一、引言

最近在工作中,我遇到了这么一个需求:

我们需要每天给客户环境发送一个打包文件,对此,客户环境提供了一个 sftp 服务来接收我们的文件

这是一个非常简单的需求场景,但是这个需求对于我项目的要求就是:

我需要在自己的代码中调用一个 shell 脚本,在这个 shell 脚本中,我需要完成 sftp 指定文件到客户环境的任务

很快的,你就会发现在 shell 脚本中编写调用 sftp 的代码并不是那么容易:

你会发现,sftp 是一个交互性的命令,如果你不处理掉 sftp 的交互行为,你就无法成功在项目代码中调用它完成每日向客户环境发送文件的工作。

我们都知道,sftp 包含在 ssh 组件里面,ssh 一共包含了 3 个工具:ssh、sftp、scp。意思是,我们只要能够去掉 sftp 的交互行为,就相当于同时可以去掉 sftp、ssh、scp 这 3 个工具的交互行为。这里,我们的问题就变成了:

我们如何能够去掉 ssh 的输入密码的交互行为呢?

通过我查询资料,我了解到了以下两个可行的方案:

  1. 使用 expect 工具
    通过识别到 ssh 向用户询问的 password 的词汇,来写入固定密码字符串的应答来解决这个问题。这种方法就像是 expect 工具充当了我们用户输入密码。
  2. 配置 ssh 公私钥
    通过配置公私钥模式(用过 github 的同学应该都有印象),我们就可以实现本地 ssh 到远端服务器的免密登录。

这两个方案我都有所了解,但是因为 expect 的方法需要安装 expect 工具,这在我们线上环境上来说,是一件相对来说挺麻烦的事情,因此我果断选择了配置 ssh 公私钥的方式。

如果你还是想要尝试下 expect 工具的方式,我这里可以推荐你一篇博客:
Linux expect详解

但是 ssh 配置公私钥的方式,也不是那么一帆风顺的(至少我就是 T_T)。但是我们程序员就是要敢于挑战未知,编程的乐趣不就是去探索去解决问题吗。

接下来,我们就来好好看看怎么配置 ssh 公私钥方式免密登录吧:)

二、先别急,让我们…

我知道你肯定已经迫不及待想要配置起来了,但是在配置之前,我需要做这么两件事情,一件是统一术语,一件则是描述下 ssh 的公私钥模式的原理。之所以要统一术语,是因为在我查询资料的过程中,我发现对于 ssh 的双方,谁是客户端谁是服务端,谁是上传文件方(sftp 模式)谁是接收文件方,不同的博客博主有着自己不同的定义。没有一个统一的定义,就会发生混乱,这点让我很是头痛。至于原理,这是当然的了,很多人或许就像我一样,甚至连谁去生成公私钥都不知道。

1. 术语整理

但是在开始配置之前,我觉得还是有必要简单的介绍下环境和术语,这样会有助于你厘清楚这中间的概念:

术语 描述
客户端 发起 ssh/sftp/scp 请求的主机环境,也就是想要免密登录目标主机的那个环境
服务端 应答 ssh/sftp/scp 请求的主机环境,也就是检查登录密码的那个环境
模拟机 A 127.0.0.1,本地 wsl linux Ubuntu 18.04 环境,作为客户端
模拟机 B 192.168.214.128, 本地虚拟机 Manjaro 18.1.3 环境,作为服务端

2. ssh/sftp/scp 的公私钥免密模式原理

这里,我简单画了一个时序图来描述这中间的原理:

客户端服务端发送 ssh/sftp/scp 请求获取到客户端对应的公钥产生随机数并使用公钥加密获取到本地私钥使用私钥解密发送服务端进行一系列检查告知客户端是否可以登录客户端服务端

这个时序图可以说非常详细了:

由客户端负责生成公私钥,其中公钥放在服务端,私钥放在客户端。

当客户端发起请求的时候,服务端寻找对应的客户端的公钥,并产生一个随机数进行加密,再传回客户端,目的是为了验证客户端的合法性。

当客户端收到了服务端的加密文本后,就会使用私钥去解密,再发送给服务端。

服务端 sshd 程序收到了客户端的应答后,通过检查解密文本是否就是自己生成的随机数就可以得知客户端是否合法。同时,服务端还会对一些目录权限和权属进行检查。

二、让我们配置起来…

在了解了必要的背景知识后,现在就可以开始配置起来了!

1. 客户端:生成公私钥

执行下列命令:

ssh-keygen -t rsa

其中屏幕显示的提示均可以一路回车默认。此时,就会在 $HOME/.ssh 目录下生成 id_rsa、id_rsa.pub 文件。其中 id_rsa 就是私钥文件,id_rsa.pub 就是公钥文件。

2. 客户端:发送公钥文件给服务端,并且安装

将客户端 $HOME/.ssh 文件夹下的 id_rsa.pub 公钥文件发送到服务端的 $HOME/.ssh 路径下:

scp $HOME/.ssh/id_rsa.pub wangying@192.168.214.128:/home/wangying/.ssh

3. 服务端:安装公钥文件

得到了公钥文件,随即进行安装:

cat id_rsa.pub >> authorized_keys

这里是将客户端发过来的公钥文件追加到 authorized_keys 文件中。这里需要注意的是,如果服务端没有 .ssh 文件夹,你可以新建一个。

4. 客户端:尝试登录,自动添加服务端信息

在客户端尝试登录,随即会自动在 $HOME/.ssh/known_hosts 文件中添加服务端信息:

ssh wangying@192.168.214.128

如图:

这里,我已经配置成功了,客户端已经可以免密登录上去了:)

如果你到了这一步,也能成功免密登录上去,那么恭喜你!

但是问题总不会这么简单,早晚有一天你会发现,你按照我上面的步骤仔细的配置完成,但还是出现了问题。

5. 配置失败:检查下列事项

如果你配置完后,发现并不能成功 ssh/sftp/scp 上去,则需要检查下列事项:

事项 备注
两个主机的 .ssh 目录的属主、属组为当前用户与用户组
两个主机的 .ssh 目录的权限应该是 700
服务端的 .ssh 目录下的 authorized_keys 的权限应该是 644
客户端的 .ssh 目录下的 id_rsa 的权限应该是 600
两个主机的 .ssh 目录下的 id_rsa.pub 的权限应该是 644
服务端的用户 $HOME 目录的权限应该是 755 理论上说,只要组和其他用户没有 w 权限即可

目录权限:

r w x
4 2 1

修改权限:

chmod 700 .ssh

修改组别:

chgrp wangying .ssh

修改属主

chown wangying /home/wangying

三、T_T 配置出了问题…

我们在上一节中已经描述的非常清楚了,但是总会还是会发生问题,这里,我也在其他环境中配置 sftp 免密登录过程中遇到了不少坑,但是都一一解决掉了。这里我简单模拟下那些配置失败的情况,在失败中去学习解决问题的办法,这也是很有意义的。

1. 模拟错误:服务端的用户目录 $HOME 不是 755 权限

这里,我们拿着上面配置成功的环境,修改下服务端的 $HOME 目录的权限:

chmod 777 /home/wangying


现在,我们再回去客户端尝试 ssh 服务端,立马就会发现免密失败了:

出现问题不是可怕的,可怕的是我们不知道怎么去寻找原因。

2. 客户端:ssh 调试模式查看可疑日志

我们只需要在运行 ssh 的时候添加 -vvv 参数,即可进入 ssh 调试模式,就可以看到 ssh 在连接过程中的那些步骤:

ssh -vvv wangying@192.168.214.128

我们甚至可以对比其他成功的 ssh 连接的调试日志,经过对比,我发现了下面这些可疑的日志信息:

debug1: Offering public key: /home/wangying/.ssh/id_rsa RSA SHA256:a0qaby4PMHI7B8E+Jn/XQnAn6yFrRNvFsh5FAS5Hohw
debug3: send packet: type 50
debug2: we sent a publickey packet, wait for reply
debug3: receive packet: type 51
debug1: Authentications that can continue: publickey,password
debug1: Trying private key: /home/wangying/.ssh/id_dsa
debug3: no such identity: /home/wangying/.ssh/id_dsa: No such file or directory
debug1: Trying private key: /home/wangying/.ssh/id_ecdsa
debug3: no such identity: /home/wangying/.ssh/id_ecdsa: No such file or directory
debug1: Trying private key: /home/wangying/.ssh/id_ed25519
debug3: no such identity: /home/wangying/.ssh/id_ed25519: No such file or directory
debug1: Trying private key: /home/wangying/.ssh/id_xmss
debug3: no such identity: /home/wangying/.ssh/id_xmss: No such file or directory
debug2: we did not send a packet, disable method
debug3: authmethod_lookup password
debug3: remaining preferred: ,password
debug3: authmethod_is_enabled password
debug1: Next authentication method: password

对比 ssh 成功的调试日志:

debug3: authmethod_lookup publickey
debug3: remaining preferred: keyboard-interactive,password
debug3: authmethod_is_enabled publickey
debug1: Next authentication method: publickey
debug1: Offering public key: /home/wangying/.ssh/id_rsa RSA SHA256:a0qaby4PMHI7B8E+Jn/XQnAn6yFrRNvFsh5FAS5Hohw
debug3: send packet: type 50
debug2: we sent a publickey packet, wait for reply
debug3: receive packet: type 60
debug1: Server accepts key: /home/wangying/.ssh/id_rsa RSA SHA256:a0qaby4PMHI7B8E+Jn/XQnAn6yFrRNvFsh5FAS5Hohw
debug3: sign_and_send_pubkey: RSA SHA256:a0qaby4PMHI7B8E+Jn/XQnAn6yFrRNvFsh5FAS5Hohw
debug3: sign_and_send_pubkey: signing using rsa-sha2-512
debug3: send packet: type 50
debug3: receive packet: type 52
debug1: Authentication succeeded (publickey).

我们很容易对比得知到异常:失败的日志中, we did not send a packet, disable method之后,就是 automethod_lookup password,这块就定下来是需要用户输入密码了;而在成功的日志中,这块直接就是 authmethod_lookup publickey

因此可以大胆猜测,ssh 根本就没找到公钥文件。

3. 服务端:查看系统安全日志 /var/log/secure

通过查看服务端的系统安全日志,我们就可以得知 sshd 进程在处理客户端的 ssh 请求的过程中的一些错误信息:

tail -f /var/log/secure

看到可疑日志:

Dec 9 09:31:08 manjaro sshd[29298]: Authentication refused: bad ownership or modes for directory /home/wangying

看到这个错误是不是就一目了然了呢:)

4. 其他尝试…

你甚至可以修改服务端 $HOME 目录的属主(我一个环境就是这个问题 T_T):

chown wy /home/wangying

也会出现一样的报错,通过 ssh 的调试日志和系统的安全日志查看 ssh 登录异常情况,我们就能找到线索并且解决问题。

四、总结

到这里,我就把我这回 ssh 免密配置过程中爬的坑基本都讲完了。这篇博客写了蛮久的,从晚上 11 点写到了凌晨 1 点。冬天的夜晚非常冷,但是我的心还是蛮热的。

这就是编程的魅力吧~~~
这就是探索的魅力吧~~~
这就是活着的意义吧~~~

To be Stronger:)

玩转 ssh 免密登录配置:使用两个环境模拟配置成功和其他几种失败的情况相关推荐

  1. scp配置免密传输文件、ssh免密登录

    文章目录 前言 一.服务器A配置密匙 二.将生成的密钥id_rsa.pub中内容复制到服务器B,放入/user/.ssh/authorized_keys文件中 1.打开服务器A的id_rsa.pub ...

  2. ssh免密登录配置(两行命令搞定)

    最简单的ssh免密登录的配置 1.准备工作 2.命令行操作 3.互相免密登录 1.准备工作 确保两台服务器的用户名字相同,这里以用户名是username,服务器A要免密登录到服务器B为例子.注意:以下 ...

  3. SSH免密登录(内含批量配置脚本)

    原文地址:itweknow.cn/detail?id=6- ,欢迎大家访问. 在我们的集群环境搭建过程中可能会很需要SSH免密登录,互相之间传文件只需要一个SCP命令,连密码都不用输,很方便.那么这篇 ...

  4. Hadoop-2.8.0集群搭建、hadoop源码编译和安装、host配置、ssh免密登录、hadoop配置文件中的参数配置参数总结、hadoop集群测试,安装过程中的常见错误

    25. 集群搭建 25.1 HADOOP集群搭建 25.1.1集群简介 HADOOP集群具体来说包含两个集群:HDFS集群和YARN集群,两者逻辑上分离,但物理上常在一起 HDFS集群: 负责海量数据 ...

  5. ssh免密登录配置方法及配置

    ssh免密登录配置方法及配置 直接上步骤,记我们本机为机器A,而机器B.机器C等是我们的服务器,我们要配置的是A到B.C等的 ssh 免密登录. 1 在机器A上生成秘钥对 ssh-keygen 会得到 ...

  6. Hadoop2——SSH免密登录功能配置

    SSH免密登录功能配置 我有三台虚拟机,其中一台主机,两台克隆机 192.168.159.130 hadoop01 (主机) 192.168.159.128 hadoop02 192.168.159. ...

  7. 华为/华三交换机配置SSH免密登录

    数据通信 - 建设篇 第二章 华为/华三交换机配置SSH免密登录 数据通信 - 建设篇 系列文章回顾 下章内容 华为/华三交换机配置SSH免密登录 背景介绍 实施步骤 堡垒机Linux后台使用ssh- ...

  8. 杨校老师课堂之集群内SSH免密登录功能配置

    SSH免密登录功能配置 1. 在主节点虚拟机内进行如下操作: [root@hadoop1 tmp]# ssh-keygen -t rsaGenerating public/private rsa ke ...

  9. Hadoop学习之SSH免密登录配置(以三台虚拟机为例,完全分布式)

    目录 1.更改主机名(便于进行操作) 方法一 ​编辑 方法二 2.配置SSH免密登录 1.生成秘钥 2.移动秘钥 3.秘钥分配 4.验证免密登录 1.更改主机名(便于进行操作) 本文操作需在root用 ...

最新文章

  1. java list 自定义类型转换_java – 可以从List生成平面XML结构的XStream自定义转换器?...
  2. 解决IDEA自动重置LanguageLevel和JavaCompiler版本的问题
  3. spring boot一:入门
  4. MUI多端发布开发指南(终于把MUI的使用场景说清楚了)
  5. wxWidgets:wxWebViewEvent类用法
  6. linux增加swap分区大小
  7. 计算机桌面堆,桌面堆 Desktop heap设置
  8. Design Compiler指南——概述和基本流程
  9. 10、自学——Linux的学习进度与任务【用户和用户组相关操作】
  10. 高仿蓝奏云单页下载页面源码
  11. 常用JDK系统环境变量配置
  12. 全新 ENVI Modeler 遥感建模工具
  13. 请简述一下RS485通讯连接方式及其应用?
  14. handlersocket mysql_Mysql插件之HandlerSocket的安装、配置、使用
  15. DOS命令是如何操作目录和文件夹的?
  16. LeetCode 285. 二叉搜索树中的中序后继
  17. ORA-01400: cannot insert NULL into | 通过SQL链接服务器 往Oracle库的表中 插入默认值问题
  18. 如何高效进行大规模分类?
  19. 简单实现敏感词过滤功能
  20. python3 + Scrapy爬虫学习之创建项目

热门文章

  1. steam验证登录失败_如何向Steam添加两方面身份验证
  2. python画小猪佩奇——给最爱的人一份甜甜的温暖
  3. 代码:法向质心法提取线激光条纹中心线(CPP+OpenCV)
  4. 树莓派Pico直流步进电机接口技术及电机运动控制MicroPython+pioasm编程方法
  5. Prometheus监控告警搭建(一)
  6. CoreImage核心图像图像处理
  7. js验证固定电话、手机号码
  8. [luogu] P1637 三元上升子序列 树状数组
  9. 【C】指针的相关运算练习题
  10. oracle有条件执行插入语句