【转】ssh登录原理以及ssh免密码登陆
一、什么是SSH?
简单说,SSH是一种网络协议,用于计算机之间的加密登录。
如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会泄露。
最早的时候,互联网通信都是明文通信,一旦被截获,内容就暴露无疑。1995年,芬兰学者Tatu Ylonen设计了SSH协议,将登录信息全部加密,成为互联网安全的一个基本解决方案,迅速在全世界获得推广,目前已经成为Linux系统的标准配置。
需要指出的是,SSH只是一种协议,存在多种实现,既有商业实现,也有开源实现。本文针对的实现是OpenSSH,它是自由软件,应用非常广泛。
此外,本文只讨论SSH在Linux Shell中的用法。如果要在Windows系统中使用SSH,会用到另一种软件PuTTY,这需要另文介绍。
二、最基本的用法
SSH主要用于远程登录。假定你要以用户名user,登录远程主机host,只要一条简单命令就可以了。
$ ssh user@host
如果本地用户名与远程用户名一致,登录时可以省略用户名。
$ ssh host
SSH的默认端口是22,也就是说,你的登录请求会送进远程主机的22端口。使用p参数,可以修改这个端口。
$ ssh -p 2222 user@host
上面这条命令表示,ssh直接连接远程主机的2222端口。
三、中间人攻击
SSH之所以能够保证安全,原因在于它采用了公钥加密。
整个过程是这样的:(1)远程主机收到用户的登录请求,把自己的公钥发给用户。(2)用户使用这个公钥,将登录密码加密后,发送回来。(3)远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。
这个过程本身是安全的,但是实施的时候存在一个风险:如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。因为不像https协议,SSH协议的公钥是没有证书中心(CA)公证的,也就是说,都是自己签发的。
可以设想,如果攻击者插在用户与远程主机之间(比如在公共的wifi区域),用伪造的公钥,获取用户的登录密码。再用这个密码登录远程主机,那么SSH的安全机制就荡然无存了。这种风险就是著名的"中间人攻击"(Man-in-the-middle attack)。
SSH协议是如何应对的呢?
四、口令登录
如果你是第一次登录对方主机,系统会出现下面的提示:
$ ssh user@host
The authenticity of host 'host (12.18.429.21)' 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主机的真实性,只知道它的公钥指纹,问你还想继续连接吗?
所谓"公钥指纹",是指公钥长度较长(这里采用RSA算法,长达1024位),很难比对,所以对其进行MD5计算,将它变成一个128位的指纹。上例中是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
系统会出现一句提示,表示host主机已经得到认可。
Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.
然后,会要求输入密码。
Password: (enter password)
如果密码正确,就可以登录了。
当远程主机的公钥被接受以后,它就会被保存在文件$HOME/.ssh/known_hosts之中。下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。
每个SSH用户都有自己的known_hosts文件,此外系统也有一个这样的文件,通常是/etc/ssh/ssh_known_hosts,保存一些对所有用户都可信赖的远程主机的公钥。
五、公钥登录
使用密码登录,每次都必须输入密码,非常麻烦。好在SSH还提供了公钥登录,可以省去输入密码的步骤。
所谓"公钥登录",原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。
需要依靠密匙,也就是你必须为自己创建一对密匙,并把公用密匙放在需要访问的服务器上。如果你要连接到SSH服务器上,客户端软件就会向服务器发出请求,请求用你的密匙进行安全验证。服务器收到请求之后,先在该服务器上你的主目录下寻找你的公用密匙,然后把它和你发送过来的公用密匙进行比较。如果两个密匙一致,服务器就用公用密匙加密“质询”并把它发送给客户端软件。客户端软件收到“质询”之后就可以用你的私人密匙解密再把它发送给服务器。用这种方式,你必须知道自己密匙的口令。但是,与第一种级别相比,第二种级别不需要在网络上传送口令。第二种级别不仅加密所有传送的数据,而且“中间人”这种攻击方式也是不可能的(因为他没有你的私人密匙)。但是整个登录的过程可能需要10秒,但是相比输入密码的方式来说10秒也不长。
这种方法要求用户必须提供自己的公钥。如果没有现成的,可以直接用ssh-keygen生成一个:
$ ssh-keygen
运行上面的命令以后,系统会出现一系列提示,可以一路回车。其中有一个问题是,要不要对私钥设置口令(passphrase),如果担心私钥的安全,这里可以设置一个。
运行结束以后,在$HOME/.ssh/目录下,会新生成两个文件:id_rsa.pub和id_rsa。前者是你的公钥,后者是你的私钥。
这时再输入下面的命令,将公钥传送到远程主机host上面:
$ ssh-copy-id user@host
好了,从此你再登录,就不需要输入密码了。
如果还是不行,就打开远程主机的/etc/ssh/sshd_config这个文件,检查下面几行前面"#"注释是否取掉。
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
然后,重启远程主机的ssh服务。
// ubuntu系统
service ssh restart// debian系统
/etc/init.d/ssh restart
六、authorized_keys文件
远程主机将用户的公钥,保存在登录后的用户主目录的$HOME/.ssh/authorized_keys文件中。公钥就是一段字符串,只要把它追加在authorized_keys文件的末尾就行了。
这里不使用上面的ssh-copy-id命令,改用下面的命令,解释公钥的保存过程:
$ ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub
这条命令由多个语句组成,依次分解开来看:(1)"$ ssh user@host",表示登录远程主机;(2)单引号中的mkdir .ssh && cat >> .ssh/authorized_keys,表示登录后在远程shell上执行的命令:(3)"$ mkdir -p .ssh"的作用是,如果用户主目录中的.ssh目录不存在,就创建一个;(4)'cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub的作用是,将本地的公钥文件~/.ssh/id_rsa.pub,重定向追加到远程文件authorized_keys的末尾。
写入authorized_keys文件后,公钥登录的设置就完成了。
ssh-agent是一种控制用来保存公钥身份验证所使用的私钥的程序。ssh-agent在X会话或登录会话之初启动,所有其他窗口或程序则以客户端程序的身份启动并加入到ssh-agent程序中。通过使用环境变量,可定位代理并在登录到其他使用ssh机器上时使用代理自动进行身份验证。
其实ssh-agent就是一个密钥管理器,运行ssh-agent以后,使用ssh-add将私钥交给ssh-agent保管,其他程序需要身份验证的时候可以将验证申请交给ssh-agent来完成整个认证过程。通过使用ssh-agent就可以很方便的在不的主机间进行漫游了,假如我们手头有三台server:host1、host2、host3且每台server上到保存了本机(supersun.biz)的公钥,因此我可以通过公钥认证登录到每台主机:
[root@supersun.biz ~]#ssh host1
Last login: Thu Oct 18 13:56:08 2007 from supersun
[root@host1 root]#
[root@supersun.biz ~]#ssh host2
Last login: Fri Oct 12 11:14:44 2007 from supersun
[root@host2 root]#
[root@supersun.biz ~]#ssh host3
Last login: Sat Sep 29 10:21:32 2007 from supersun
[root@host3 root]#
但是这三台server之间并没有并没有保存彼此的公钥,而且我也不可能将自己的私钥存放到server上(不安全),因此彼此之间没有公钥进 行认证(可以密码认证,但是这样慢,经常输密码,烦且密码太多容易忘)。但是如果我们启用ssh-agent,问题就可以迎刃而解了。
启用ssh-agent:
[root@supersun.biz ~]#eval `ssh-agent `
Agent pid 3526
添加私钥:
[root@supersun.biz ~]#ssh-add
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
编缉/etc/ssh/ssh_config文件:ForwardAgent yes
让ssh-agent能转发,这样就可以这样登陆了:supersun.biz---->host1---->host2,到此请注意,如果host1上没有设定转发的话就登不了host3了,设定了转发后可以进一步跳到rs3上了。
[root@supersun.biz ~]#ssh host1
Last login: Thu Oct 18 16:21:29 2007 from supersun
[root@host1 root]# vi /etc/ssh/ssh_config
[root@host1 root]# ssh host2
Last login: Thu Oct 18 16:20:28 2007 from supersun
[root@host2 root]# ssh host3
Last login: Thu Oct 18 16:10:39 2007 from supersun
[root@host3 root]#
到这里基本上已经大功告成了,还有一个小问题那就是总不能每次都手动运行ssh-agent吧!最省时的方法就是将它写到profile中去:
为了不把profile搞乱,我在在/etc/profile.d下建一个ssh-agent.sh文件:
[root@supersun.biz ~]#cat /etc/profile.d/ssh-agent.sh
#!/bin/sh
if [ -f ~/.agent.env ]; then
. ~/.agent.env >/dev/null
if ! kill -0 $SSH_AGENT_PID >/dev/null 2>&1; then
echo "Stale agent file found. Spawning new agent..."
eval `ssh-agent |tee ~/.agent.env`
ssh-add
fi
else
echo "Starting ssh-agent..."
eval `ssh-agent |tee ~/.agent.env`
ssh-add
fi
这样就不会生成太多的ssh-agent程序了,而且支持GUI环境。当我打开一个终端的话:
Stale agent file found. Spawning new agent...
Agent pid 2543
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
[root@supersun.biz ~]#
添加了新的密钥。
1.生成密匙对,我用的是rsa的密钥。使用命令 "ssh-keygen -t rsa"
#ssh-keygen -t rsa
//一路回车,不需要指定密码,就会在在当前用户的根目录下的.ssh目录生成id_rsa.pub公钥
2.将公钥放到服务器上(注意存放目录位置)
#scp ~/.ssh/id_rsa.pub 用户名@你的服务器的ip:~/.ssh/authorized_keys
//将本地生成的公钥拷贝到远程服务器对应用户下.ssh文件夹下并改名为authorized_keys
这样就完成了!使用ssh登录、scp或者sftp传输文件时都不需要密码了!
【转】ssh登录原理以及ssh免密码登陆的更多相关文章
- 实现一台Linux电脑连接另一台Linux(SSH实现linux之间的免密码登陆)
怎么实现一台Linux电脑连接另一台Linux电脑? 首先查看是否安装ssh服务:systemctl status sshd.service 启动服务:systemctl start sshd.ser ...
- ssh登录原理及免密登录配置
ssh登录原理参考: https://www.cnblogs.com/hukey/p/6248468.html ssh登录有两种方式: 1):用户名密码登录 2):基于秘钥的登录 ssh免密登录指的就 ...
- linux如何配置双机SSH信任然后双向免密码登陆
linux如何配置双机SSH信任然后双向免密码登陆 www.111cn.net 更新:2015-01-14 编辑:edit02_lz 来源:转载 有时为了方便管理多台Linux主机,想实现双机之间信任 ...
- ssh key 免密码登陆服务器,批量分发管理以及挂载远程目录的sshfs
ssh key 免密码登陆服务器,批量分发管理以及挂载远程目录的sshfs 第一部分:使用ssh key 实现服务器间的免密码交互登陆 步骤1: 安装openssh-clients [root@001 ...
- SSH免密码登陆详解
为了更好的理解SSH免密码登陆原理,我们先来说说SSH的安全验证,SSH采用的是”非对称密钥系统”,即耳熟能详的公钥私钥加密系统,其安全验证又分为两种级别. 1. 基于口令的安全验证 这种方式使用用户 ...
- linux centOS服务器部署ssh,免密码登陆linux
登陆centos,切换用户,切换到你要免密码登陆的用户,进入到家目录 2 创建钥匙, [xun@jzlinux ~]$ ssh-keygen -t rsa Generating public/priv ...
- [转] SSH免密码登陆以及穿越跳板机
原文链接:http://www.cnblogs.com/lucantang/p/3315329.html SSH免密码登陆以及穿越跳板机 1. 免密码直连 [user@hostA ~] $ssh ...
- 5.SSH 免密码登陆
SSH 免密码登陆 serverA 机器上 userA 用户,想要免密钥登陆到serverB机器上 1.集群中的所有机器 安装ssh 服务端sudo apt-get updatesudo apt-ge ...
- SSH配置免密码登陆
1.使用SSH-keygen,然后一路回车使之生成id_rsa何id_rsa.pub文件,id_rsa.pub为公匙文件. 2.使用命令:cat ~/.ssh/id_rsa.pub >> ...
随机推荐
- 【转载】DXUT进阶
原文:DXUT进阶 概要 这个指南涵盖了更多DXUT的高级应用. 这个指南里的大部分功能是可选的, 为了以最小的代价来增强你的应用程序. DXUT提供了一个简单的基于GUI系统的精灵和一个设备设置对话 ...
- CF 547 D. Mike and Fish
D. Mike and Fish http://codeforces.com/contest/547/problem/D 题意: 给定平面上n个点,将这些点染成红或者蓝色,要求每行.每列红色点与蓝色点 ...
- GlusterFS学习之路(三)客户端挂载和管理GlusterFS卷
一.客户端挂载 可以使用Gluster Native Client方法在GNU / Linux客户端中实现高并发性,性能和透明故障转移.可以使用NFS v3访问gluster卷.已经对GNU / Li ...
- C# VS,连接到oracle 报要升级到8.多少版本的错
1:确定服务器的oracle版本 2:本地的客户端版本要和服务器一致 3:操作系统位数要一致
- 「日常训练」Magic Stones(CodeForces-1110E)
题意 给定两个数组c和t,可以对c数组中的任何元素变换\(c_i\)成\(c_{i+1}+c_{i-1}-c_i\),问c数组在若干次变换后能否变换成t数组. 分析 这种魔法题目我是同样的没做过. ...
- JavaFX 学习笔记——jfoenix类库学习——raised风格按钮创建
创建按钮 JFXButton jfxb = new JFXButton("hello"); jfxb.getStyleClass().add("button-raised ...
- qt cout输出中文乱码解决记录
工具 -> 选项-> 文本编辑器-> 行为 -> 文件编码->默认编码改为System 乱码原因: 默认用utf-8编码,控制台默认gbk编码,编码不一致导致的乱码
- phpcms v9手机站不支持组图($pictureurls)的修改
phpcms v9自带的手机门户网站,有时候我们需要用到组图功能$pictureurls,我在做的时候发现,如果$pictureurls中只有一张图片会正常显示,但是如果有两张或两张以上的图片的时候, ...
- xshell—实现Linux与Windows之间的文件传递
在Windows系统上,通过xshell连接Linux系统. 第一种使用方式:从Linux系统上下载文件到Windows系统. 准备工作: $ sudo apt-get install lrzsz 安 ...
- 4个数的和为0 51nod 1267
给出N个整数,你来判断一下是否能够选出4个数,他们的和为0,可以则输出"Yes",否则输出"No". Input 第1行,1个数N,N为数组的长度(4 < ...