网络协议-应用层协议-远程登陆协议
Posted stringarray
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络协议-应用层协议-远程登陆协议相关的知识,希望对你有一定的参考价值。
远程登录协议
通过 TELNET 模拟实现 HTTP 和 SMTP 客户端
所谓远程登录指的是从本地计算机登录到网络另一端的计算机(通常是服务器或者云主机实例),远程登录成功后,就可以直接使用这些主机上的应用,还可以对这些计算机进行参数配置。
适用于远程登录的协议主要有两种:TELNET 和 SSH(Secure SHell)。我们首先来介绍 TELNET。
TELNET 基于 TCP 连接将向主机发送文字命令并在主机上执行,常用于登录路由器或高性能交换机等网络设备进行相应的设置。
TELNET 客户端是指利用 TELNET 协议实现远程登录的客户端程序,很多情况下,它的程序名就是 telnet 命令。TELNET 客户端通常与目标主机的 23 号端口连接,并与监听这个端口的服务端程序 telnetd 进行交互。
注:在 Windows 系统中,要启用 TELNET 客户端,需要在「控制面板->程序和功能->启用或关闭 Windows 功能」中勾选「TELNET客户端」并确定方能在命令行中使用。
telnet
命令格式如下:
telnet 主机名(或IP) TCP端口号
端口号为 80 时连接 HTTP、为 25 时连接 SMTP、为 21 时连接到 FTP。比如我们可以通过 telnet
连接到 www.baidu.com 的 80 端口:
这种方法还可用于测试服务器指定端口是否可用。我们还可以通过客户端 telnet
命令模拟 HTTP 请求,比如我们现在通过 GET
方法访问百度首页(输入请求头后两次回车才会返回响应):
还可以直接构建查询请求:
理论上支持所有类型的 HTTP 请求,只要你构造的 HTTP 请求头和请求实体符合 HTTP 协议规范(关于 HTTP 协议我们后面会详细介绍)。
当然,TELNET 不仅构建限于 HTTP 请求,我们还可以通过它来模拟邮件发送,以 163 邮箱为例,在开始之前,我们先把用户名和密码通过 Base64 编码进行加密处理,然后通过客户端 telnet
命令构建 SMTP 请求发送邮件:
~ telnet smtp.163.com 25 // 通过 25 号端口登录 163 SMTP 服务器
Trying 220.181.12.12...
Connected to smtp.163.com.
Escape character is ‘^]‘.
220 163.com Anti-spam GT for Coremail System (163com[20141201])
HELO localhost // 通过 HELO 指令向服务器打招呼,并告知客户端机器的名字,可以随便取
250 OK
AUTH LOGIN // 通过认证指令发起认证请求
334 dXNlcm5hbWU6
// 这里输入Base64编码后的用户名,注意用户名不要带 @163.com 后缀
334 UGFzc3dvcmQ6
// 这里输入Base64编码后的密码
235 Authentication successful
MAIL FROM:<yaojinbu@163.com> // 通过 MAIL FROM 指令指定发件箱
250 Mail OK
RCPT TO:<yaojinbu@outlook.com> // 通过 RCPT TO 指令指定收件箱
250 Mail OK
DATA // 通过 DATA 指令声明开始编写邮件正文,最后一行必须是 .
354 End data with <CR><LF>.<CR><LF>
From:yaojinbu@163.com
To:yaojinbu@outlook.com
Subject:TELNET MAIL
This is a mail from TELNET CLIENT!
.
250 Mail OK queued as smtp8,DMCowACXJ5aCjplcp0_eMg--.60339S2 1553567438
QUIT // 邮件发送成功,断开连接
221 Bye
Connection closed by foreign host.
这个时候,到收件箱就能看到刚刚通过 TELNET 客户端发送出去的邮件了,关于上述命令及返回的 SMTP 响应码后面介绍 SMTP 协议的时候还会详细介绍,这里我们主要是为了熟悉 TELNET 客户端的使用。
此外,TELNET 客户端作为仿真客户端,理论上还可以用于模拟所有应用层协议通信,比如基于 FTP 进行文件传输等,这里我们可以看到,通过遵循相应的应用层协议规范,我们完全可以自己实现简单的 HTTP、电子邮件和文件传输客户端,日常在操作系统上所使用的浏览器、Outlook、邮箱大师、FileZilla 等客户端软件不过是在此基础上提供了更加丰富的功能和更好的用户体验而已,了解这些底层的协议规范并模拟其实现,可以帮助我们更好的理解日常使用软件、工具的底层原理,也能帮助我们阅读很多框架和工具的底层源码,最终编写更加健壮的代码。
TELNET 虽然很简单,功能也比较齐全,但是在传输过程中没有对数据进行加密,有被窃听的风险,所以我们来介绍一种更加安全的远程登录协议 —— SSH。
SSH 的基本使用与底层原理探究
基本使用
TELNET 无需任何认证即可发送内容,容易造成通信窃听和非法侵入的危险。SSH 是英文 Secure Shell 的简写,顾名思义,可以加密通信内容,是加密的远程登录协议,通过在网络中建立安全隧道来实现 SSH 客户端与服务器之间的连接,可以在不安全的网络中为网络服务提供安全的传输环境。
SSH 本身是一种协议,有多种实现,最常见的就是开源的 OpenSSH,我们在日常使用过程中最多的场景就是通过它来实现远程登录,既可以在终端直接通过 ssh 命令登录远程主机:
ssh <用户名>@<主机名或IP地址>
比如,要以 root 身份登录主机名为 homestead 的机器,可以通过 ssh root@homestead 进行连接。如果需要密码验证的话,下一步会提示你输入密码。
也可以通过客户端工具比如 PuTTY、Xshell、SecureCRT 等进行远程操作:
服务器上有对应的后台守护进程 sshd
响应客户端 SSH 远程连接,默认监听端口号是 22,当然,你也可以自定义这个端口号然后在连接时通过 -p
选项指定:
ssh -p 2222 root@homestead // 远程 sshd 端口号是 2222
关于 SSH 的基本使用就是这样,比较简单,登录成功后,即可通过命令行在远程主机上进行操作和配置。下面我们来看看 SSH 协议的原理,它是如何确保传输通道的安全的。
底层原理
SSH 之所以能够保证安全,原因在于它采用了公钥加密。
整个过程是这样的:
- 远程主机收到用户的登录请求,把自己的公钥发给用户;
- 用户使用这个公钥,将登录密码加密后,发送回来;
- 远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。
这个过程本身是安全的,但是实施的时候存在一个风险:如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。因为不像 HTTPS 协议,SSH 协议的公钥是没有认证中心(CA)公证的,也就是说,都是自己签发的。
可以设想,如果攻击者插在用户与远程主机之间,用伪造的公钥,获取用户的登录密码,再用这个密码登录远程主机,那么 SSH 的安全机制就荡然无存了。这种风险就是著名的「中间人攻击」。
SSH 协议是如何应对这种攻击的呢?实际上,在通过 SSH 首次进行远程登录的时候,系统会要求你比对返回的公钥是否与目标服务器上的公钥信息一致。
如果你是第一次登录远程主机,系统会出现下面的提示:
思是无法确认远程主机的真实性,只知道它的公钥指纹,问你是否还想继续连接。之所以提示 ECDSA 类型的公钥指纹,是因为指纹比公钥的长度要短,所以更容易比较。
那怎么知道远程主机的公钥指纹应该是多少?这个可以通过 ssh-keyscan
命令结合ssh-keygen
得到。ssh-keyscan
命令可获取服务器公钥:
ssh-keyscan -t ECDSA -p 22 laravelacademy.org
而 ssh-keygen
命令可以计算公钥的指纹:
ssh-keygen -E sha256 -lf ~/.ssh/known_hosts
只要计算一下服务器上的相应公钥的指纹,并与客户端获取的指纹进行比对一致,就能确定连接的是否是公钥对应的服务器。
注:某些 SSH 终端默认提供的是 MD5 格式的公钥指纹,此时,只需将 -E 指定的参数设置为 md5 即可。
如果输入 yes
确认,则系统会提示远程主机已经得到认可:
Warning: Permanently added ‘laravelacademy.org,114.215.241.29‘ (ECDSA) to the list of known hosts.
同时服务器 SSH 公钥会添加到本地的 ~/.ssh/known_hosts
文件里面。然后终端会提示你输入密码登录远程主机:
xueyuanjun@laravelacademy.org‘s password:
如果密码正确,就可以登录了。下次再连接这台主机,由于 ~/.ssh/known_hosts
文件里已经包含了对应的公钥信息,就会跳过警告部分,直接提示输入密码。
一般而言,系统中每个用户都有自己的 known_hosts
文件,此外还有一个系统级的 /etc/ssh/ssh_known_hosts
文件,用于保存对所有用户都可信赖的远程主机的公钥。
使用公钥登录
每次都要输入密码登录,有些繁琐,你还可以配置每次直接使用公钥进行登录,所谓「公钥登录」,原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录,不再要求密码。
生成私钥公钥文件
如果你的本地主机不包含 ~/.ssh/id_rsa
文件,可以通过运行如下命令生成:
ssh-keygen -t rsa
每次执行上述命令后产生的私钥文件都不同,如果 ~/.ssh/id_rsa
文件已经存在,会提示是否覆盖,选择 n 不覆盖,如果该文件不存在则会生成该文件(提示需要输入的地方都可以留空)。
运行该命令会生成 ~/.ssh/id_rsa
和 ~/.ssh/id_rsa.pub
两个文件,分别存储私钥和公钥,接下来我们通过 scp
命令将公钥文件拷贝到远程服务器的 .ssh
目录下(如果服务器上没有该目录,先创建这个目录)
scp ~/.ssh/id_rsa.pub root@your-server-ip:~/.ssh
将公钥添加到授权KEY
登录到远程服务器,运行如下命令将公钥文件内容追加到 ~/.ssh/authorized_keys
文件:
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
如果服务器上没有 ~/.ssh/authorized_keys
这个文件,可以运行如下命令将 ~/.ssh/id_rsa.pub
文件拷贝过来:
cp id_rsa.pub authorized_keys
接下来,我们在本地主机测试通过 ssh 登录远程服务器:
注意将上述命令中的 IP 地址替换成自己的服务器公网 IP,这样一来,就可以无需输入密码即可登录远程服务器了,非常方便。
以上是关于网络协议-应用层协议-远程登陆协议的主要内容,如果未能解决你的问题,请参考以下文章