零、背景


在看 pm2 的 deploy 功能的时候,对 ssh 的不熟悉导致错误频出,包括之前对 github 的配置也用到了 SSH,所以找个机会整理一下。

一、介绍


SSH 是每一台 Linux 电脑的标准配置。

需要指出的是,SSH 只是一种协议,存在多种实现,既有商业实现,也有开源实现。本文针对的实现是 OpenSSH,它是自由软件,应用非常广泛。

[拓展]

1、SSL、SSH、OpenSSL、OpenSSH 的关系:


2、SSL 版本之间的关系:


所以 SSL 的规范叫法是 SSL/TLS

目前,应用最广泛的是 TLS 1.0。不过比如微信的小程序接口开发需要支持 TLS 大于等于 1.2。

3、scp(secure copy)


scp 是 linux 系统下基于 ssh 登陆进行的安全远程文件拷贝命令。

(1)从本地复制到远程
//复制文件
scp /Users/xjnotxj/Downloads/a.jpg root@1.2.3.4:/data/wwwroot
scp /Users/xjnotxj/Downloads/a.jpg root@1.2.3.4:/data/wwwroot/b.jpg //复制目录
scp -r /Users/xjnotxj/Downloads/folder/ root@1.2.3.4:/data/wwwroot/
(2)从远程复制到本地

前后顺序颠倒即可

二、用处


1、远程登录


SSH 登录机制:由上文可知,SSH 基于 SSL/TLS 协议,而它的机制有两种

(1)口令认证(需要密码(即口令))

首先我们访问 host 远程服务器:

$ ssh user@host

第一次访问的时候,会弹出提示:

$ ssh user@host

  The authenticity of host 'host (xx.xxx.xx.xxx)' can't be established.

  RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.

  Are you sure you want to continue connecting (yes/no)?

这段话的意思时:无法确认远程 host 主机的真实性,只知道它的公钥指纹,问你还想继续连接吗

之所以是公钥指纹而不是公钥,即用 fingerprint 代替 key,主要是 key 过于长(RSA算法生成的公钥最少也得 1024 位),很难直接比较。所以,对公钥进行 hash 生成一个 128 位的指纹,这样就方便比较了。

为什么会有提示?

因为要防止中间人攻击,因为 hacker 的服务器也可以冒充身份把它自己的公钥发给你。

什么是中间人攻击?

yes 后:

Warning: Permanently added 'host (xx.xxx.xx.xxx)' (RSA) to the list of known hosts.
Password: (enter password)

该 host 被追加到文件 ~/.ssh/known_hosts 中,然后就可以正常输入密码了,且以后再连接这个 host 就不会有提示了。

那如果在连接前就避免这种恼人的提示?

① ssh-keyscan / known_hosts

事先使用 ssh-keyscan 命令( gather ssh public keys )获取到远程主机的公钥,然后添加到信任列表 ~/.ssh/known_hosts 里 ,避免弹出这个警告。

ssh-keyscan -t rsa gitlab.xxx.com >> ~/.ssh/known_hosts

每个 SSH 用户都有 ~/.ssh/known_hosts 文件,此外系统也有一个这样的文件,通常是 /etc/ssh/ssh_known_hosts,保存一些对所有用户都可信赖的远程主机的公钥。

② StrictHostKeyChecking=no

ssh user@host -o StrictHostKeyChecking=no
  1. StrictHostKeyChecking=no

    最不安全的级别。相对安全的内网建议使用。如果连接和 key 不存在或不匹配,那么就自动添加到 ~/.ssh/known_hosts

  2. StrictHostKeyChecking=ask 

    默认的级别。如果连接和 key 不存在或不匹配,给出提示。

  3. StrictHostKeyChecking=yes 

    最安全的级别。如果连接与 key 不存在或不匹配,就直接拒绝连接。

(2)公钥认证(不需要密码,但事先得把本机的公钥放在服务器上)

① 生成本机公钥

先判断本机有没有之前生成过公钥?

cat ~/.ssh/id_rsa.pub

如果没有,执行下面:

ssh-keygen -t rsa 

ssh-keygen -t rsa -C "your.email@example.com" -b 4096
// github/gitlab 官方推荐这种写法

~/.ssh 下会新生成两个文件:id_rsa.pubid_rsa。前者是你的公钥,后者是你的私钥

-t 是选择 key 的类型,支持 dsa | ecdsa | ed25519 | rsa | rsa1,下面是最常用的 rsa 和 dsa 的比较:

name 加密类型 算法原理 安全性 加解密 加密速度 解密速度 数字签名 生成签名 速度 签名验证 速度 支持程度
rsa 非对称加密算法 大整数的分解(两个素数的乘积) 几乎一样 广泛
dsa 非对称加密算法 整数有限域离散对数 几乎一样 × 一般

结论:RSA 是目前最好也是使用最广泛的非对称加密算法。如 github/gitlab 和 pm2 官方文档都推荐。

② 拷贝本机公钥到远程服务器上

这里有两种方法:

a.ssh-copy-id

ssh-copy-id remote@myserver.com

于是远程主机将用户的公钥,保存在 ~/.ssh/authorized_keys

b.类 github 方法

github/gitlab 需要手工粘贴到 web 的设置页面里

③ 直接登录,不需要输入密码了

$ ssh user@host

④ 第一次访问时,会跟口令认证一样,弹出是否确认公钥继续连接的警告:

  The authenticity of host 'host (xx.xxx.xx.xxx)' can't be established.

  RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.

  Are you sure you want to continue connecting (yes/no)?

yes 后,依然会把 server 端的公钥存到 ~/.ssh/known_hosts 里。

详细的请参考口令认证对这部分的介绍。


注:如果还不行的解决方法:

打开远程主机的 /etc/ssh/sshd_config,检查下面几行前面"#"注释是否去掉。

  RSAAuthentication yes
  PubkeyAuthentication yes
  AuthorizedKeysFile .ssh/authorized_keys

然后重启 ssh

  // ubuntu系统
service ssh restart // debian系统
/etc/init.d/ssh restart

总结:

公钥认证虽然前期麻烦,需要手动将公钥放置在远程主机上,但是更加安全,可以有效杜绝中间人攻击,推荐使用 [勘误于20180719] 但是免密登录更加便捷,但依然无法杜绝中间人攻击。

https 是如何避免中间人攻击的?

通过 CA 证书中心来进行公证。

【拓展】github/gitlab 使用 SSH、HTTPS 哪个好?

① 是否输入密码

当你git clone、git fetch、git pull、git push使用 HTTPS URL,你会被要求输入 GitHub 的用户名和密码

当你git clone、git fetch、git pull、git push使用 SSH URL,你会被要求输入你的 SSH密钥密码

但一般我们在生成 SSH 密钥的时候没有设置密码的习惯。所以等于 SSH 的方式不需要输入密码。

windows 下也可以有存储密码的方法,用 git-credential-winstore 和 git-credential-manager-for-windows 存储 credential,安全性和便捷性同样可以保证。具体没用过,windows i refuse。

② 部署难度

类 linux 来说配置 ssh 是最简单的方式。毕竟 git 是 linus 写的软件。linus 又是 linux 的作者。

总结:对于我这个 mac 用户,还是用 SSH 更方便。


【错误案例】gitlab 服务器重装系统后,导致 git 命令报错。

报错信息:

例如 git pull 的时候,会报错:

The ECDSA host key for gitlab.xxx.com has changed,
and the key for the corresponding IP address 47.99.xxx.xxx
is unknown. This could either mean that
DNS SPOOFING is happening or the IP address for the host
and its host key have changed at the same time.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:1W5xjhI1dEniPSYrqiKygxxxxxxxxxxxxxxxxxxxxx.
Please contact your system administrator.
Add correct host key in /Users/xjnotxj/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /Users/xjnotxj/.ssh/known_hosts:20
ECDSA host key for gitlab.xxx.com has changed and you have requested strict checking.
Host key verification failed.
fatal: Could not read from remote repository.

原因:

上文提到过,远程登录 里的 口令认证 还是 公钥认证,都是会把 server 端的公钥存储到本机的 ~/.ssh/known_hosts ,以后每次连接都会检测公钥对不对得上。而对不上,就会抛错。

而在这个例子中,因为 gitlab 服务器重装了系统,导致了 server 端的公钥变了,所以跟我们本机 ~/.ssh/known_hosts 里之前存的不一样了,就抛了错。怕你受到中间人攻击。

解决方法:

打开本机的 ~/.ssh/known_hosts 文件,找到 server 端之前的公钥,删掉即可。

【错误案例】 ssh-copy-id 配置好后,ssh 登录还是要输入密码

问题:

我在远程服务器刚开了个账户叫 website,ssh-copy-id 配置好后,ssh 登录还是要输入密码。但:

1、登录到远程服务器,查看~/.ssh/authorized_keys,发现我本机的公钥已经存进去了。

2、我的 root 账户 ssh-copy-id 配置好后,ssh 登录正常,无需密码。

排查:

ssh user@remote -vvv 可以在 ssh 登录时打印出详细信息,于是我把 root 用户(左)跟 website 用户(右)的打印信息做了对比:

原因:

按照错误信息,google 了一番,最终找到了原因,是文件权限问题。

解决:

确保以下三个文件(夹)的权限设置正确:

// website 用户的权限
chmod 700 ~
// 750也可以 //ssh 相关权限
chmod 700 ~/.ssh/
chmod 600 ~/.ssh/authorized_keys
(3)使用别名登录主机

新建文件 ~/.ssh/config,并写入如下内容:

    Host myWebsite
HostName 1.2.3.4
User root
IdentityFile ~\.ssh\id_rsa

Host : 别名

HostName:目标主机名或 IP 地址

User:登陆的用户

IdentityFile:登陆的私钥

于是可以这样登录

//原来
$ ssh root@1.2.3.4
//现在
$ ssh myWebsite

具体实践看我另一篇《 一台电脑上的git同时使用两个github账户

(4)其他参数

//指定端口
$ ssh root@1.2.3.4 -p 8080 //调试模式
$ ssh -v root@1.2.3.4
(5)远程服务器管理 SSH 登录用户

① 查看所有在线用户 / 查看自己

简单:

[root@AY140506122759852282Z ~]#  who
root tty1 2018-01-05 15:11
root pts/0 2018-07-14 19:07 (xxx.81.48.19)
root pts/1 2018-07-14 19:00 (xxx.81.48.19) //查看自己
[root@AY140506122759852282Z ~]# who am i
root pts/1 2018-07-14 19:00 (xxx.81.48.19)

显示时间为登录时间

详细:

[root@AY140506122759852282Z ~]# w
19:07:26 up 190 days, 3:56, 3 users, load average: 1.24, 1.07, 1.06
USER TTY LOGIN@ IDLE JCPU PCPU WHAT
root tty1 05Jan18 190days 1.66s 1.66s -bash
root pts/0 19:07 26.00s 0.04s 0.04s -bash
root pts/1 19:00 6.00s 0.13s 0.00s w //指定特定用户
[root@AY140506122759852282Z ~]# w root

USER:登陆帐号

TTY:用户终端

LOGIN@:登陆时间

IDLE:登陆时长

JCPU:指所有与该终端相关的进程任务所耗费的 CPU 时间

PCPU:指 WHAT 域的任务执行耗费的 CPU 时间

WHAT:表示当前执行的任务

显示时间为登录时间、登录时长

② 踢掉某个在线用户

[root@AY140506122759852282Z ~]# pkill -kill -t pts/0

//强制
[root@AY140506122759852282Z ~]# pkill -9 -t pts/0

然后对方就会自动断开连接:

[root@AY140506122759852282Z ~]# Connection to xxx.124.109.112 closed.

③ 查看用户登录历史(包括在线)

[root@AY140506122759852282Z ~]# last -10
root pts/0 xxx.81.48.19 Sat Jul 14 19:07 still logged in
root pts/1 xxx.81.48.19 Sat Jul 14 19:00 still logged in
root pts/1 xxx.81.48.19 Sat Jul 14 18:59 - 18:59 (00:00)
root pts/1 xxx.81.48.19 Sat Jul 14 18:58 - 18:59 (00:00)
root pts/1 xxx.81.48.19 Sat Jul 14 18:57 - 18:58 (00:00)
root pts/0 xxx.81.48.19 Sat Jul 14 18:57 - 19:04 (00:07)
root pts/0 xxx.81.48.19 Sat Jul 14 17:18 - 17:23 (00:05)
root pts/1 xxx.81.48.19 Sat Jul 14 14:14 - 14:14 (00:00)
root pts/0 xxx.81.48.19 Sat Jul 14 14:13 - 14:14 (00:01)
root pts/0 xxx.81.48.19 Fri Jul 13 14:41 - 16:41 (02:00) //指定特定用户
[root@AY140506122759852282Z ~]# last -10 root

显示时间为登录时间、注销时间、登录时长

(6)退出SSH

exit

2、远程执行命令


ssh user@host 'ls /data'

列出远程主机 /data 下的目录

3、端口转发


待写,具体可先参考:

《SSH原理与运用(二):远程操作与端口转发》http://www.ruanyifeng.com/blog/2011/12/ssh_port_forwarding.html

《玩转SSH端口转发》

https://blog.fundebug.com/2017/04/24/ssh-port-forwarding/

4、实现 VPN(虚拟专用网络)


参考资料


1.【SSH原理与运用(一):远程登录】http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html

2.【Linux系统下如何查看已经登录用户】https://www.jb51.net/LINUXjishu/10876.html

SSH 学习笔记的更多相关文章

  1. SSH学习笔记

    Struts2登录模块处理流程: 浏览器发送请求http://localhost/appname/login.action,到web应用服务器: 容器接收到该请求,根据web.xml的配置,服务器将请 ...

  2. 【SSH学习笔记】用Struts2实现简单的用户登录

    准备阶段 在使用学习Struts2的时候首先要下载相应的架包 Struts2资源下载 这里建议下载第一个,在struts-2.5.14.1-all.zip里有很多实用的东西,不仅有架包还有官方为开发者 ...

  3. 【SSH学习笔记】浅谈SSH框架

    说在前面 本学期我们有一门课叫做Java EE,由陈老师所授,主要讲的就是Java EE 中的SSH框架. 由于陈老师授课风格以及自己的原因导致学了整整一学期不知道在讲什么,所以才有了自己重新学习总结 ...

  4. [SSH] SSH学习笔记 - 远程登录

    1.SSH登陆/登出命令 $ ssh <hostname> #登入 $ exit #登出 known_hosts 每个用户都有自己的known_hosts文件,路径:(username)/ ...

  5. 【SSH学习笔记】—从配置Struts1环境到简单实例

    以下我将从一个简单点的计算器实例,介绍struts1的环境配置,以及其重要的两个核心类:ActionForm和Action  简单计算器实现思路: 1.提供一个输入界面,输入两个数字和运算符(+.-. ...

  6. SSH学习笔记(二)

    # 1. 关于 SSH Server 的整体设定,包含使用的 port 啦,以及使用的密码演算方式 Port 22 # SSH 预设使用 22 这个 port,您也可以使用多的 port ! # 亦即 ...

  7. SSH学习笔记目录

    1.Spring_2000_Spring_Hibernate_HibernateTemplate

  8. pm2 官方文档 学习笔记

    一.安装 1.安装 npm install pm2 -g 2.更新 npm install pm2 -g && pm2 update pm2 update 是为了刷新 PM2 的守护进 ...

  9. Linux学习笔记 | 配置ssh

    目录: SSH的必要性 将默认镜像源修改为清华镜像源 Linux安装ssh软件 使用putty软件实现ssh连接 Windows下安装winscp SSH的必要性 一般服务器都位于远程而非本地,或者及 ...

随机推荐

  1. 代理设计模式 (静态代理设计模式)+ 动态代理(JDK和Cglib)

    一.代理设计模式 1.设计模式:前人总结一套解决特定问题的代码 2.代理设计模式优点: 2.1 保护真实对象 2.2 让真实对象职责更明确 2.3 扩展 3.代理设计模式 3.1 真实对象(老总) 3 ...

  2. 先加载js 后载控件

    可以使用如下 $(document).on('click','.classname',function(){});

  3. 实现1sym转换成2个sym送给CVI(VGA数据)

    CVI的时序如下 :de指示数据有效. 从下面的程序看,同步码的长度不会影响对有效数据的判断.同步码的作用更多的是用于计算行及一行的像素数目.方案一: 1 module vga_1sym_2_2sym ...

  4. Codeforces Round#415 Div.2

    A. Straight «A» 题面 Noora is a student of one famous high school. It's her final year in school - she ...

  5. 【设计模式】Javascript设计模式——状态模式(行为型)

    注:这个模式是非常聪明的,很有点数学中组合的意思,现在,来看下这个模式是怎么个思想. 问题提出:假如某个操作有三种可能,分别为1,2,3,还可能是组合,比如先执行1,再执行2或者先执行2再执行3或者1 ...

  6. 20145232 韩文浩 《Java程序设计》第1周学习总结

    教材学习内容总结 看到已经有人学到了第四章,真是_(:з」∠)_ 于是我也开始了我的Java之旅. 首先学习了几常见的dos命令行方式 dir: 列出当前目录下所有文件及文件夹 md :创建目录 rd ...

  7. 入手IntelliJ IDEA 常用配置

    Idea常用设置 下载地址:https://www.jetbrains.com/idea/ 激活服务器:http://idea.iteblog.com/key.php 代码补全取消区分大小写 Inte ...

  8. Navicat连接mysql8.0.1版本出现1251--Client does not support authentication protocol requested by server的解决

    转载自:https://blog.csdn.net/XDMFC/article/details/80263215 好不容易安装好mysql,但又出现了mysql客户端版本太低的问题.根据参考的这篇博客 ...

  9. hud 3123 GCC

    题目 输入:n 和 mod 输出: Output the answer of (0! + 1! + 2! + 3! + 4! + ... + n!)%m. Constrains 0 < T &l ...

  10. spark 中划分stage的思路

    窄依赖指父RDD的每一个分区最多被一个子RDD的分区所用,表现为 一个父RDD的分区对应于一个子RDD的分区 两个父RDD的分区对应于一个子RDD 的分区. 宽依赖指子RDD的每个分区都要依赖于父RD ...