# 前言
本文主要讨论telnet,ssh和https用途及原理。
# telnet
它是teletype network的缩写,现在成为一个专有名词,表示远程登录协议和方式,Telnet协议是TCP/IP中的应用层协议。RFC 854定了该协议规范。
它为用户提供了在本地计算机操作远程主机工作的能力,有客户端和服务器端,用户使用客户端输入用户名密码登录服务器端后进行控制。连接客户端和服务器的双方是网络虚拟终端(Network Virtual Terminal,NVT),服务器端和客户端都必须将它们的物理终端和NVT进行相互转换。
NVT是带有输入和输出的字符设备,用户击键产生的数据被发送到服务器进程,服务器端进程回送的响应输出到显示器上,NVT ASCII代表7比特的ASCII字符集,网间协议族都是用NVT ASCII,每个7比特都以8比特发送,最高位为0。
Telnet通信两个方向都是带内信令方式,字节0xff(十进制255)叫做IAC(interpret as command,意思是"作为命令来解释"),该字节后面一个字节才是命令字节。它的命令集如下:
# ssh
ssh为Secure Shell的缩写,由IETF的网络小组(Network Working Group)所制定,SSH为建立在应用层基础上的安全协议,专为远程登录会话和其他网络服务提供安全性的协议,利用SSH协议和有效防止远程管理过程中的信息泄露问题。
传统的网络服务程序如ftp,pop和telnet在本质上是不安全的,他们在网络上用明文传送口令和数据,容易被"中间人"(man in the middle)截取,也就是"中间人"冒充真正的服务器接收你传给服务器的数据,然后再冒充你把数据传给真正的服务器,这样服务器和你之间被"中间人"做手脚就会出现严重的问题,通过使用SSH,你可以把传输的数据进行加密,"中间人"的攻击就不可能实现了,而且能防止DNS欺骗和IP欺骗,使用SSH,它传输的数据是经过压缩的,可以加快传输速度,SSH有很功能使它既可以代替Telnet又可以为FTP,PoP甚至为PPP提供安全"通道"。
SSH有两种登陆方式:基于口令登陆和基于公钥登陆,下面来看下这两种方式:
# 基于口令登陆
上面的过程使用非对称加密,看似安全,但还是有漏洞的,SSH不像https协议那样有证书中心(CA)公证服务器的公钥,如果有人一开始截获了登陆请求,那么他冒充远程主机还是可以使用中间人攻击。如下图:
虽然发起这种中间攻击要比之前所说的中间攻击难点,但还是不安全的。避免这种攻击的关键在于如何确定服务器的公钥是服务器的,SSH中通常如果第一次登陆就会出现下面的提示:
The authenticity of host 'ssh-server.example.com (1.1.1.1)' can't be established. RSA key fingerprint is ff:34:78:98:34:34:32:f1:23:b3:34:67:a5:d8:92:3c. Are you sure you want to continue connecting (yes/no)?
这是什么意思呢?服务器将自己的公钥指纹发过来,然后客户端查找自己本地的known_hosts文件,如果没有找到就会发出上面的信息,说明该主机是没有连接过的,让SSH客户端自己来决定是否相信远程主机,如果回答yes,那么会提示下面信息:
Warning: Permanently added '1.1.1.1' (ECDSA) to the list of known hosts.
这样便会将该服务器的公钥指纹存入known_hosts,然后下次连接该服务器时,从该文件中查找到服务器的公钥指纹,那么便会跳过警告部分。
为什么这里是用公钥的指纹,而不是公钥呢?应该是因为公钥过长的原因,RSA算法生成的公钥有1024位,但是对公钥hash生成128位的指纹,相比之下指纹更好比较。
由于known_hosts存在,当远程主机重装系统,它会重新生成公钥,再登陆远程主机时,由于known_hosts文件记录了原来的公钥,这就提示指纹验证错误,此时需要删除known_hosts文件。
当写一些自动化脚本自动登陆远程主机时,但是由于known_hosts机智必须要我们手动输入yes才能完成登陆,这会让自动化登陆无法完成,可以通过修改配置文件中的StrictHostKeyChecking ask改为StrictHostKeyChecking no。
# 公钥免密登陆
注意上图中的会话密钥协商都是相互通信的,上面为了突出整体流程,放在了服务器端单向给客户端的里面。
# SSH实践操作
客户端生成密钥对。
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa -C "your_email@example.com" 选项说明: -t 指定生成密钥类型,可以是rsa,dsa,ecdsa -P 指定密码,加密私钥 -f 指定存放密钥文件位置,公钥文件默认和私钥同目录,公钥的文件以.pub为后缀 -C 指定注释
1
2
3
4
5
6
7
8将本地主机的密钥复制到远程主机的authorized_keys文件里
ssh-copy-id -i ~/.ssh/id_rsa.pub user@host 参数说明: -i 指定要拷贝本地的公钥位置
1
2
3
4
# 管理本地的私钥
ssh-agent是私钥管理工具,在下面情况时我们会考虑使用它:
- 使用不同的密钥连接不同的主机时需要手动指定对应密钥,此时ssh代理帮我们选择对应的密钥进行认证,不需手动指定密钥即可进行连接。
- 当私钥设置了密码,又虚频繁地使用私钥进行认证时,ssh代理可以帮我们免去重复的密码输入。
# 启动ssh代理
启动ssh代理有两种方式:
ssh-agent $SHELL
eval `ssh-agent`
2
第一种方式会在当前shell中启动一个默认shell,作为当前shell的子shell,如果退出当前shell时,会自动关闭ssh-agent。
第二种方式直接启动一个ssh-agent进程,当退出当前的shell时不会自动关闭,所以在退出当前bash之前,手动关闭这个进程,如果是在ssh-agent中,可以使用ssh-agent -k来关闭进程,如果已经退出了,那么只好使用kill命令了。
# 使用ssh代理
通过前面的命令启动ssh代理后,下面就要使用它了,在此之前,先来看下之前不使用代理时是怎样的,我们之前使用ssh命令默认是使用~/.ssh/id_rsa,如果我们生成的密钥不是这个名称,就需要在ssh连接时指定:
ssh -i /private-key-path root@1.1.1.1
而使用ssh-agent时:
ssh-agent bash
ssh-add /private/key/path
ssh root@1.1.1.1
2
3
这样连接不同的服务器时,或者重复连接同一个服务器时,便不用再根据服务器指定相应的密钥文件,更轻松快捷。
# 管理ssh-agent私钥
下面是ssh-agent的常用命令:
ssh-add -l 查看添加了哪些私钥
ssh-add -L 查看密钥的同时列出相应的公钥
ssh-add /private/key/path 删除指定私钥
ssh-add -D 一次性清空代理中的所有私钥
ssh-add -x 对代理加锁
ssh-add -X 对代理解锁
2
3
4
5
6
# 使用ssh-agent代理时的问题
虽然使用代理时一旦用ssh-add添加了密钥便不用再手动使用密钥来连接指定服务器,但是每次重启ssh-agent又需要重新ssh-add密钥,针对这样的情况,有以下几种解决方案:
# 使用SSHConfig
ssh目录下可以存放配置文件,比如~/.ssh/config,它的写法如下:
Host 别名
HostName 主机名
User 用户名
PreferredAuthentications 用什么方式认证,有publickey,password,keyboard-interactive等
IdentityFile 密钥文件的路径
2
3
4
5
这样它会根据配置文件中的别名直接去找相应的密钥文件,要连接的主机名等等。
# 脚本自动化
可以在bashrc中添加如下:
eval "$(ssh-agent -s)"
ssh-add /private/key/path
2
这样每次打开shell时便可以直接连接。
# KeePass和KeeAgent
KeePass是一个密码管理工具,它能记录下windows上的密码,邮箱密码,网站密码等等。而KeeAgent是KeePass的一个插件,能在KeePass的数据库中存储SSH密钥,用以被其他程序使用。
# 添加密钥到keychain或者凭据管理器
这个只适用于Mac OS,在Mac上可以使用下面命令将私钥添加到keychain中。
ssh-add -K [path/to/your/ssh-key]
# https
HTTPS全称为Hyper Text Transfer Protocol over Secure Socket Layer或Hypertext Transfer Protocol Secure。是安全版的HTTP,在HTTP下面加入SSL层,提供身份验证与加密通讯方法。这样HTTPS中的数据便不会像HTTP协议中那样明文传输,而是通过协商好的密钥,在发送端加密,在接收端解密。
# SSL
网络从底层向上分物理层,数据链路层,网络层,运输层和应用层,我们上面说的SSL(Secure Socket Layer)协议是在运输层和应用层之间,该协议由Netscape在1994年开发,最新版本是1996年的SSL 3.0,后来IETF在SSL基础上设计了运输层安全协议TLS(Transport Layer Security)。下面来看下为什么会需要这个安全协议呢?
# 应用场景
以某用户购物为例,在这个过程中他需要一些安全措施:
- 顾客所浏览的服务器是属于真正的厂商,服务器身份必须被鉴别。
- 顾客在购物过程中的,购物报文在传输过程中没有被篡改,需要确保报文不被修改,保证完整。
- 网上的入侵者不能截获信用卡号等敏感信息,信息传输过程中需要加密。
# SSL工作原理
SSL对客户端和服务器端之间传送的数据进行加密和鉴别,它在双发联络阶段(握手阶段)对将要使用的加密算法和双方共享的会话密钥进行协商,完成服务器和客户端之间的鉴别,在握手阶段结束后,所有传送的数据都使用在握手阶段商定的会话密钥。
在第三阶段,浏览器收到服务器发来的证书,在自己的可信CA表中查找服务器的发行者CA是否在列表里,如果不在,后面的加密和鉴别连接就不能进行下去,如果在,浏览器就能使用CA相应的公钥对证书解密,得到服务器的公钥。
从上面流程再根据举的实例,我们发现SSL主要提供下面三个功能:
- SSL服务器鉴别,客户端从自己的可信CA列表查找是否是我们连接的服务器。
- 加密SSL会话,客户端和服务器所有交互数据都在发送端加密,在接收端解密,还提供了一种检测信息是否被攻击者篡改的机制。
- SSL客户鉴别,允许服务器证实客户端身份。
# ipsec
这个和https没有关系,只是和ssl有些关联,顺带说一下,前面提到过SSL是运输层和应用层之间的,而ipsec则是网络层上的安全协议,它指的是IP数据报中的所有数据都是加密的,网络层还提供源点鉴别(source authentication),当目的站收到IP数据报时,确信这是从该数据报的源IP地址的主机发出来的。
← 网络中的加密原理与手段 Http协议 →