计算机网络体系结构
OSI七层模型
开放系统互连参考模型 (Open System Interconnect 简称OSI)是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。其目的是为异种计算机互连提供一个共同的基础和标准框架,并为保持相关标准的一致性和兼容性提供共同的参考。这里所说的开放系统,实质上指的是遵循OSI参考模型和相关协议能够实现互连的具有各种应用目的的计算机系统。
OSI采用了分层的结构化技术,共分七层,物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
TCP/IP模型
OSI模型比较复杂且学术化,所以我们实际使用的TCP/IP模型,共分4层,链路层、网络层、传输层、应用层。两个模型之间的对应关系如图所示:
无论什么模型,每一个抽象层建立在低一层提供的服务上,并且为高一层提供服务。
TCP/IP协议族
Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。协议采用了4层的层级结构。然而在很多情况下,它是利用 IP 进行通信时所必须用到的协议群的统称。也就是说,它其实是个协议家族,由很多个协议组成,并且是在不同的层, 是互联网的基础通信架构。
TCP和UDP
在上述表格中,网际协议IP是TCP/IP中非常重要的协议。负责对数据加上IP地址(有发送它的主机的地址(源地址)和接收它的主机的地址(目的地址))和其他的数据以确定传输的目标。
而TCP和UDP都是传输层的协议,传输层主要为两台主机上的应用程序提供端到端的通信。
但是TCP和UDP最不同的地方是,TCP提供了一种可靠的数据传输服务,TCP是面向连接的,也就是说,利用TCP通信的两台主机首先要经历一个建立连接的过程,等到连接建立后才开始传输数据,而且传输过程中采用“带重传的肯定确认”技术来实现传输的可靠性。TCP还采用一种称为“滑动窗口”的方式进行流量控制,发送完成后还会关闭连接。所以TCP要比UDP可靠的多。
UDP(User Datagram Protocol的简称, 中文名是用户数据报协议)是把数据直接发出去,而不管对方是不是在接收,也不管对方是否能接收的了,也不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编程验证。
注意:
我们一些常见的网络应用基本上都是基于TCP和UDP的,这两个协议又会使用网络层的IP协议。但是我们完全可以绕过传输层的TCP和UDP,直接使用IP,比如Linux中LVS,甚至直接访问链路层,比如tcpdump程序就是直接和链路层进行通信的。
上图中,其他一些协议的名称解释,了解即可:
ICMP 控制报文协议
IGMP internet组管理协议
ARP 地址解析协议
RARP 反向地址转化协议
地址和端口号
我们常听说 MAC 地址和 IP 地址。MAC地址就是在媒体接入层上使用的地址,也叫物理地址、硬件地址或链路地址,由网络设备制造商生产时写在硬件内部。MAC地址与网络无关,也即无论将带有这个地址的硬件(如网卡、集线器、路由器等)接入到网络的何处,都有相同的MAC地址,它由厂商写在网卡的BIOS里,从理论上讲,除非盗来硬件(网卡),否则是没有办法冒名顶替的。
IP 地址后者用来识别 TCP/IP 网络中互连的主机和路由器。IP地址基于逻辑,比较灵活,不受硬件限制,也容易记忆。
在传输层也有这种类似于地址的概念,那就是端口号。端口号用来识别同一台计算机中进行通信的不同应用程序。因此,它也被称为程序地址。
一台计算机上同时可以运行多个程序。传输层协议正是利用这些端口号识别本机中正在进行通信的应用程序,并准确地将数据传输。
端口号的确定
• 标准既定的端口号:这种方法也叫静态方法。它是指每个应用程序都有其指定的端口号。但并不是说可以随意使用任何一个端口号。例如 HTTP、FTP、TELNET 等广为使用的应用协议中所使用的端口号就是固定的。这些端口号被称为知名端口号,分布在 0~1023 之间;除知名端口号之外,还有一些端口号被正式注册,它们分布在 1024~49151 之间,不过这些端口号可用于任何通信用途。
• 时序分配法:服务器有必要确定监听端口号,但是接受服务的客户端没必要确定端口号。在这种方法下,客户端应用程序完全可以不用自己设置端口号,而全权交给操作系统进行分配。动态分配的端口号范围在 49152~65535 之间。
端口号与协议
• 端口号由其使用的传输层协议决定。因此,不同的传输层协议可以使用相同的端口号。
• 此外,那些知名端口号与传输层协议并无关系。只要端口一致都将分配同一种应用程序进行处理。
TCP/IP
TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于端到端的通讯。
TCP提供的是一种可靠的数据流服务,采用“带重传的肯定确认”技术来实现传输的可靠性。TCP还采用一种称为“滑动窗口”的方式进行流量控制,所谓窗口实际表示接收能力,用以限制发送方的发送速度。
如果IP数据包中有已经封好的TCP数据包,那么IP将把它们向‘上’传送到TCP层。TCP将包排序并进行错误检查,同时实现虚电路间的连接。TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。
TCP将它的信息送到更高层的应用程序,例如Telnet的服务程序和客户程序。应用程序轮流将信息送回TCP层,TCP层便将它们向下传送到IP层,设备驱动程序和物理介质,最后到接收方。
面向连接的服务(例如Telnet、FTP、rlogin、X Windows和SMTP)需要高度的可靠性,所以它们使用了TCP。DNS在某些情况下使用TCP(发送和接收域名数据库),但使用UDP传送有关单个主机的信息。
TCP三次握手
TCP 提供面向有连接的通信传输。面向有连接是指在数据通信开始之前先做好两端之间的准备工作。
所谓三次握手是指建立一个 TCP 连接时需要客户端和服务器端总共发送三个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发。
第一次握手:客户端将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给服务器端,客户端进入SYN_SENT状态,等待服务器端确认。
第二次握手:服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。
第三次握手:客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。
TCP的三次握手的漏洞
但是在TCP三次握手中是有一个缺陷的,就是如果我们利用三次握手的缺陷进行攻击。这个攻击就是SYN洪泛攻击。三次握手中有一个第二次握手,服务端向客户端应道请求,应答请求是需要客户端IP的,服务端是需要知道客户端IP的,攻击者就伪造这个IP,往服务器端狂发送第一次握手的内容,当然第一次握手中的客户端IP地址是伪造的,从而服务端忙于进行第二次握手但是第二次握手当然没有结果,所以导致服务器端被拖累,死机。
当然我们的生活中也有可能有这种例子,一个家境一般的IT男去表白他的女神被拒绝了,理由是他家里没矿,IT男为了报复,采用了洪泛攻击,他请了很多人伪装成有钱人去表白那位追求矿的女神,让女生每次想交往时发现表白的人不见了同时还联系不上了。
面对这种攻击,有以下的解决方案,最好的方案是防火墙。
无效连接监视释放
这种方法不停监视所有的连接,包括三次握手的,还有握手一次的,反正是所有的,当达到一定(与)阈值时拆除这些连接,从而释放系统资源。这种方法对于所有的连接一视同仁,不管是正常的还是攻击的,所以这种方式不推荐。
延缓TCB分配方法
一般的做完第一次握手之后,服务器就需要为该请求分配一个TCB(连接控制资源),通常这个资源需要200多个字节。延迟TCB的分配,当正常连接建立起来后再分配TCB则可以有效地减轻服务器资源的消耗。
使用防火墙
防火墙在确认了连接的有效性后,才向内部的服务器(Listener)发起SYN请求,
TCP四次挥手(分手)
四次挥手即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。
由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
- 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
- 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
- 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
- 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
- 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。