计算机网络是一个将分散的、具有独立功能的计算机系统,通过通信设备与线路连接起来,由功能完善的软件实现资源共享和信息传递的系统。简言之,计算机网络就是一些互联的、自治的、计算机系统的集合。
IP:网际协议 IP 是 TCP/IP体系中两个最主要的协议之一,是TCP/IP体系结构网际层的核心。配套的有:
地址解析协议 ARP(Address Resolution Protocol)
网际控制报文协议 ICMP(Internet Control Message Protocol)
网际组管理协议 IGMP(Internet Group Management Protocol
(ICMP 很好的讲解 https://blog.csdn.net/baidu_37964071/article/details/80514340)
ICMP 是为了更有效地转发IP数据报和提高交付成功的机会,是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。它封装在 IP数据报中,但是不属于高层协议。ICMP 报文分为差错报告报文和询问报文。==Ping 是 ICMP 的一个重要应用,因为走得是网络层,所以不需要端口号,主要用来测试两台主机之间的连通性。==Ping 的原理是通过向目的主机发送 ICMP Echo 请求报文,目的主机收到之后会发送Echo回答报文。Ping会根据时间和成功响应的次数估算出数据包往返时间以及丢包率。
OSI中的层 | 功能 | TCP/IP协议族 |
---|---|---|
应用层 | 文件传输,电子邮件,文件服务,虚拟终端 | TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet |
表示层 | 数据格式化,代码转换,数据加密 | 没有协议 |
会话层 | 解除或建立与别的接点的联系 | 没有协议 |
传输层 | 提供端对端的接口 | TCP,UDP |
网络层 | 为数据包选择路由 | IP,ICMP,RIP,OSPF,BGP,IGMP |
数据链路层 | 传输有地址的帧以及错误检测功能 | SLIP,CSLIP,PPP,ARP,RARP,MTU |
物理层 | 以二进制数据形式在物理媒体上传输数据 | ISO2110,IEEE802,IEEE802.2 |
物理地址、硬件地址,由网络设备制造商生产时写在硬件内部。MAC地址与网络无关,它由厂商写在网卡的BIOS里。
MAC地址通常表示为12个16进制数,每2个16进制数之间用冒号隔开,如:08:00:20:0A:8C: 6D就是一个MAC地址,其中前6位16进制数08:00:20代表网络硬件制造商的编号,它由IEEE分配,而后3位16进制数0A:8C:6D代表该制造商所制造的某个网络产品(如网卡)的系列号。
由于IP只是逻辑上标识,任何人都随意修改,因此不能用来标识用户;而 MAC地址则不然,它是固化在网卡里面的。从理论上讲,除非盗来硬件(网卡),否则是没有办法冒名顶替的。
基于MAC地址的这种特点,局域网采用了用MAC地址来标识具体用户的方法。具体实现:在交换机内部通过“表”的方式把MAC地址和IP地址一一对应,也就是所说的IP、MAC绑定。
具体的通信方式:接收过程,当有发给本地局域网内一台主机的数据包时,交换机接收下来,然后把数据包中的IP地址按照“表”中的对应关系映射成MAC地址,转发到对应的MAC地址的主机上,这样一来,即使某台主机盗用了这个IP地址,但由于他没有这个MAC地址,因此也不会收到数据包。
综上可知,只有IP而没有对应的MAC地址在这种局域网内是不能上网的,于是解决了IP盗用问题。
网络上主机、路由器之间的通信在网络层看来是根据IP地址,路由转发IP数据报的过程。但实际上主机H1的IP数据报(网络层)向下交给数据链路层就被封装成MAC帧从HA1到HA3,然后路由器R1收到MAC帧后,向网络层传输并且解封去掉MAC帧的首部,就能看到IP然后路由器进行路由选择,继续前面的传到数据链路层封装成MAC帧,如此循环直到到达目的主机所在的路由器然后发送给目的主机。(这里是用ARP协议将IP地址转换成MAC地址的)
**帧头:**目的MAC地址、源MAC地址、类型字段(标志上一层使用的是什么协议)
**数据部分:**即网络层传下来的IP数据报
**帧尾:**4字节长,包含的信息是帧校验序列(使用CRC校验)
网络层实现主机之间的通信,而链路层实现具体每段链路之间的通信。因此在通信过程中,IP 数据报的源地址和目的地址始终不变,而 MAC 地址随着链路的改变而改变。ARP 为 IP 地址到对应的硬件MAC地址提供动态映射。
ARP 实现由 IP 地址得到 MAC 地址
ARP攻击的第一步就是ARP欺骗
由上述“ARP协议的工作过程”我们知道,ARP协议基本没有对网络的安全性做任何思考,当时人们考虑的重点是如何保证网络通信能够正确和快速的完成——ARP协议工作的前提是默认了其所在的网络是一个善良的网络,每台主机在向网络中发送应答信号时都是使用的真实身份。不过后来,人们发现ARP应答中的IP地址和MAC地址中的信息是可以伪造的,并不一定是自己的真实IP地址和MAC地址,由此,ARP欺骗就产生了。
ARP 首部:
总结:
arp 总共 28 个字节。
记忆方法: 以太网先目地后源,ARP 先发送端后目地端。先硬件后协议。
1)缓存:主机的地址映射是基于高速缓存的,动态更新的。地址刷新是有时间限制的。 可以通过下次更新之前修改计算机上的地址缓存,造成拒绝服务攻击或者 ARP 欺骗。
2)广播: 攻击者可以伪装 ARP 应答。
3)ARP 应答没有认证,都是合法的。可以在不接受到请求的时候就发出应答包。
若 ARP 请求是从一个网络的主机发送给另一个网络上的主机,那么连接这两个网络的路由器就可以回答该请求,这个过程叫做 ARP 代理。ARP 代理路由器响应 ARP 请求的 MAC 地址为路由器的 MAC 地址而非 ARP 请求的主机的 MAC 地址。
ARP 代理的应用环境:
两个物理网络之间的路由是使用相同的网络号,两个路由器设置成 ARP 代理,实现相互隐瞒物理网络
免费ARP报文与普通ARP请求报文的区别在于普通的ARP请求报文,其ARP封装内的“目的IP地址”是其他机器的IP地址,而免费ARP的请求报文,其ARP封装内的“目的IP地址”是其自己的IP地址。指主机发送 ARP 查找自己的 IP 地址,即数据链路层 SIP=DIP
作用有两个:
1)免费ARP主要用于检测IP地址冲突。当一台主机发送了免费ARP请求报文后,如果收到了ARP响应报文,则说明网络内已经存在使用该IP 的主机。
2)如果发送免费 ARP 的主机改变了 MAC 地址,可以通过发送免费 ARP 的方式告知其他主机端更新 ARP 表(通知作用)
Maximum Transmission Unit,缩写MTU,中文名是:最大传输单元。MTU是数据链路层的概念。MTU限制的是数据链路层的payload,也就是上层协议的大小,例如IP,ICMP等。
举一个最简单的场景,你在家用自己的笔记本上网,用的是路由器,路由器连接电信网络,然后访问了www.baidu.com
,从你的笔记本出发的一个以太网数据帧总共经过了以下路径:
笔记本 -> 路由器 -> 电信机房 -> 服务器
其中,每个节点都有一个MTU值,如下:
1500 1500 1500
笔记本 -> 路由器 -> 电信机房 -> 服务器
假设现在我把笔记本的MTU最大值设置成了1700,然后发送了一个超大的ip数据包(2000),这时候在以外网传输的时候会被拆成2个包,一个1700,一个300,然后加上头信息进行传输。
1700 1500 1500
笔记本 -> 路由器 -> 电信机房 -> 服务器
路由器接收到了一个1700的帧,发现大于自己设置的最大值:1500,如果IP包DF标志位为1,也就是不允许分包,那么路由器直接就把这个包丢弃了,根本就不会到达电信机房,也就到不了服务器了,所以,到这里我们就会发现,MTU其实就是在每一个节点的管控值,只要是大于这个值的数据帧,要么选择分片,要么直接丢弃。
其实一个标准的以太网数据帧大小是:1518
,头信息有14字节,尾部校验和FCS占了4字节,所以真正留给上层协议传输数据的大小就是:1518 - 14 - 4 = 1500,那么,1518这个值又是从哪里来的呢?
假设MTU值和IP数据包大小一致,一个IP数据包的大小是:65535,那么加上以太网帧头和尾,一个以太网帧的大小就是:65535 + 14 + 4 = 65553
,看起来似乎很完美,发送方也不需要拆包,接收方也不需要重组。
那么假设我们现在的带宽是:100Mbps
,因为以太网帧是传输中的最小可识别单元,再往下就是0101所对应的光信号了,所以我们的一条带宽同时只能发送一个以太网帧。如果同时发送多个,那么对端就无法重组成一个以太网帧了,在100Mbps
的带宽中(假设中间没有损耗),我们计算一下发送这一帧需要的时间:
( 65553 * 8 ) / ( 100 * 1024 * 1024 ) ≈ 0.005(s)
在100M网络下传输一帧就需要5ms,也就是说这5ms其他进程发送不了任何数据。如果是早先的电话拨号,网速只有2M的情况下:
( 65553 * 8 ) / ( 2 * 1024 * 1024 ) ≈ 0.100(s)
100ms,这简直是噩梦。其实这就像红绿灯,时间要设置合理,交替通行,不然同一个方向如果一直是绿灯,那么另一个方向就要堵成翔了。
假设MTU值设置为100,那么单个帧传输的时间,在2Mbps带宽下需要:
( 100 * 8 ) / ( 2 * 1024 * 1024 ) * 1000 ≈ 5(ms)
时间上已经能接受了,问题在于,不管MTU设置为多少,以太网帧头尾大小是固定的,都是14 + 4,所以在MTU为100的时候,一个以太网帧的传输效率为:
( 100 - 14 - 4 ) / 100 = 82%
写成公式就是:( T - 14 - 4 ) / T
,当T趋于无穷大的时候,效率接近100%
,也就是MTU的值越大,传输效率最高,但是基于上一点传输时间的问题,来个折中的选择吧,既然头加尾是18,那就凑个整来个1500,总大小就是1518,传输效率:
1500 / 1518 = 98.8%
100Mbps传输时间:
( 1518 * 8 ) / ( 100 * 1024 * 1024 ) * 1000 = 0.11(ms)
2Mbps传输时间:
( 1518 * 8 ) / ( 2 * 1024 * 1024 ) * 1000 = 5.79(ms)
总体上时间都还能接受
数据链路层的最小 MTU 为 64 字节。对于 IEEE802.3,两个站点的最远距离不超过 2500m,由 4 个中继器连接而成,其冲突窗口为 51.2us(2 倍电缆传播延迟加上 4 个中继器的双向延迟).对于 10Mbps 的 IEEE802.3 来说,这个时间等于发送 64 字节,即 512 位的时间,64 字节就是由此而来的。如果一个站点已经传输了 512bit,就认为它已经占用了这个信道。
版本号: IPV4 就是 4,IPV6 就是 6 (4)
**首部长度:**4 个字节为单位。最小为 5,最大为 15。所以最小长度 20 个字节,最大为 60个字节。(4)
服务类型: Qos 用,目前不怎么使用。(8)
**总长度:**字节为单位。 最多可以传送 65535 字节的 IP 数据包。(16)
标识字段(8)
标志 (3)
段偏移(5)与分片有关。
生存时间 TTL:==经过一个路由器减一。 字段为 0 时,数据报被丢弃,并且发送 ICMP 报文通知源主机。==目的是防止数据报在选路时无休止地在网络中流动。(8)
协议:区分上层协议 (8)
首部校验和:仅对首部进行校验。(16)【对比: ICMP,IGMP,TCP,UDP:对首部和数据进行校验】
源地址:(32)
目的地址:(32)
IPv4用32位的二进制位来表示一台主机的网络地址;而IPv6用128位二进制位来表示一台主机的网络地址。
双协议栈:即让一部分主机(路由)支持双协议(IPv6+IPv4),然后双协议栈主机通过DNS判断目的主机地址是IPv4还是IPv6,如果是IPv6,就打包成IPv6数据报。中间路由转发过程中,如果下一跳的路由是支持IPv4的,那么会把当前的IPv6数据报的首部给转换成IPv4数据报的首部,最后再恢复成IPv6数据报的首部(最后恢复过程中,IPv6数据报首部的某些字段无法恢复,用0填充)
隧道技术:在1Pv6数据报要进入IPv4网络时,把1Pv6数据报封装成为IPv4数据报,当IPv4数据报离开IPv4网络中的隧道时,再把数据部分(即原来的 IPv6数据报)交给主机的1Pv6协议枝。
看IP数据报首部的“标志位”和“段偏移”
标志位:主要用于确定有多少个分片。标志字段在IP报头中占3位,第1位作为保留,置0;第2位,分段,有两个不同的取值:该位置0,表示可以分段;该位置1,表示不能分段;第3位,更多分段,同样有两个取值:该位置0,表示这是数据流中的最后一个分段,该位置1,表示数据流未完,后续还有分段,当一个数据报没有分段时,则该位置0,表示这是唯一的一个分段。
当目的主机接收到一个IP数据报时,会首先查看该数据报的标识符,并且检查标志位的第3位是置0或置1,以确定是否还有更多的分段,如果还有后续报文,接收主机则将接收到的报文放在缓存直到接收完所有具有相同标识符的数据报,然后再进行重组。
段偏移:13位的偏移量字段用来表示分段的数据报在整个数据流中的位置,即相当于分片数据报的顺序号。
因为一些数据链路(以太网)需要填充一些数据以达到最小长度。因为以太网帧的最小长度是 46 个字节+(太网帧头尾大小14 + 4),但是 IP 长度可能更短,所以需要总长度来确定 IP 数据部分的内容。
(1) 先把校验和字段置 0。
(2) 对首部中每个 16 位比特进行二进制反码求和。
(3) 结果存在检验和字段中。
(4) 收到一份 IP 数据包后,同样对首部中每个 16bit 二进制反码求和。
(5) 最后结果全为 1,表示正确,否则表示错误。
(6) 如果是错误的,IP 就丢弃该数据报,但是不生成差错报文,由上层去处理。
共同点:用到的算法都是一样的。
区别:IP 计算的时候没有将数据包括在内。ICMP,IGMP,TCP,UDP 同时覆盖首部和数据检验码
路由器在收到IP数据报告后执行的分组转发步骤如下:
路由表:
根据最长匹配原则,找到条目,发送到指定的路由器。如果不能找到,返回一个“主机不可达”或“网络不可达”的错误。
路由选择协议:
内部网关协议RIP(Routing Information Protocol):RIP是一种分布式的基于距离向量的路由选择协议。
内部网关协议OPSF(Open Shortest Path First):OSPF是使用分布式的链路状态协议。
外部网关协议BGP(Border Gateway Protocol):边界网关协议。
(1) IP 路由选择是逐跳进行的。IP 并不知道到达任何目的的完整路径,只提供下一跳地址。
(2) 为一个网络指定一个路由器,而不是为每个主机指定一个路由器。这样可以缩小路由表规模。
结果取决于该 IP 数据报是由主机产生的还是被转发的。
如果数据报是由本机产生的,那么就给发送该数据报的应用程序返回一个差错,或者是“主机不可达差错”或者是“网络不可达差错”。
如果是被转发的数据报,就给原始发送一份 ICMP 主机不可达的差错报文。
当路由器收到待转发的数据报,不是将下一跳路由器的 IP 地址填入 IP 数据报,而是送交下层的网络接口软件。网络接口软件使用 ARP 协议 负责将下一跳路由器的 IP 地址转换成硬件地址,并将此硬件地址放在链路层的 MAC 帧的首部,然后根据这个硬件地址找到下一跳路由器。
DHCP服务:此服务可以网络中的计算机自动分配IP地址,用户机从DHCP服务器获取IP地址的过程被称为DHCP的租约过程,也就是说此时计算机获得的IP地址不是永久的。一般的租约期限为8天。
用户机从DHCP服务器获取IP地址的过程被称为DHCP的租约过程,也就是说此时计算机获得的IP地址不是永久的。一般的租约期限为8天。一台新加入到网络的计算机获取IP地址的过程分为五个步骤。
用户机再次登录该局域网时,若IP地址没有过期,那么用户机就会向DHCP服务器发送一个request请求广播,如果该IP地址没有被分配出去那么DHCP服务器会发送一个DHCP ACK的确认信息,此时用户机就可以上网。如果IP地址已经被分配就重复初次获取IP地址的步骤。
一般的DHCP服务器分配出去的IP地址租约期限为8天,到了第四天客户机就会向DHCP服务器发送续约的请求。所以到了租约期的50%时,就会更新租约。若DHCP服务器无法响应,那么用户机会持续向服务器发送续约请求,直到到期后若服务器依然无响应,那么IP地址会自动释放用户机便无法上网。
NAT(网络地址转换协议):将本地内部机器(局域网)通过NAT服务器(至少拥有一个公有IP)与外网通信,NAT服务器通过端口来识别内部机器
VPN(虚拟专用网络协议):路由器将加密后的内网IP数据报封装在外网IP数据报的数据部分,在外网进行传输(即隧道技术)
划分网络号与主机号形式,掩码的意思就是掩盖掉主机号,剩余的就是网络号。
将子网掩码和 IP 地址按位计算 AND,就可得到网络号。
子网掩码还有一个作用,那就是划分子网。
子网划分实际上是将主机地址分为两个部分:子网网络地址和子网主机地址。
形式如下:
公有地址(Public address):由 Inter NIC(因特网信息中心)负责。这些 IP 地址分配给注册并向Inter NIC提出申请的组织机构,公有 IP 全球唯一,通过它直接访问因特网(直接能上网)。主要有A、B、C、D、E五类地址:
A类:地址范围是1.0.0.0 到 127.255.255.255,主要分配 给大量主机而局域网网络数量较少的大型网络;
B类:地址范围是128.0.0.0 到191.255.255.255,一般用于国际性大公司和政府机构;
C类:地址范围是192.0.0.0 到223.255.255.255,用于一般小公司校园网研究机构等;
D类:地址范围是224.0.0.0 到 239.255.255.255,用于特殊用途,又称做广播地址;
E类:地址范围是240.0.0.0 到255.255.255.255,暂时保留。
私有地址(Private address):属于非注册地址,专门为组织机构内部使用,说白了,私有 IP 不能直接上网。主要有A、B、C三类,
A类地址范围是10.0.0.0-10.255.255.255 ,
B类地址范围是172.16.0.0-172.31.255.255,
C类地址范围是192.168.0.0-192.168.255.255。
127.0.0.0 到127.255.255.255 为系统环回地址。
而我们平时通过运营商(主要是电信、移动、联通宽带等)上网,通过家用路由器之后,就会变成私有IP,大家可能会疑问,我们可以上网啊,怎么会是私有 IP 呢?
其实我们不是通过私有IP上网的,是通过公有IP。通俗的讲,运营商有公有IP,但是IPV4下IP资源有限,所以这些IP不能每个人分配单独分配一个IP,所以需要动态给上网的用户。 这个过程有点类似于,我们买了一些笔,然后将这些笔分给全班学生使用,当然运行商动态分配公有IP的过程比这个复杂多了。
利用端口映射功能还可以将一台外网IP地址机器的多个端口映射到内网不同机器上的不同端口。
端口映射是 NAT 的一种,它将外网主机的 IP 地址的一个端口映射到内网中一台机器,提供相应的服务。当用户访问该 IP 的这个端口时,服务器自动将请求映射到对应局域网内部的机器上。
路由器的两个端口:
WAN:接外部 IP 地址用,通常指的是出口,转发来自内部 LAN 接口的 IP 数据包,这个口的 IP 是唯一的。
LAN:接内部 IP 地址用,LAN 内部是交换机。
局域网的私网IP地址和互联网的公网地址是通过NAT技术进行转换的。
作用:
A 电脑的 IP 是局域网 IP(192.168.31.11),这个 IP(192.168.31.11)是从路由器的 lan口分配的。
当我们上百度的时候,经过路由器的 wan口,进行相应的IP、端口转化:192.168.31.11:80 -> 10.221.0.24:8080,所以,从 wan口出去的地址为:10.221.0.24:8080。
最后,经过运营商,运营商那边会做相应的端口映射(而且是动态端口映射),子网 IP(10.221.0.24:8080)转化为公网 IP(128.0.0.1:8888),通过这个公网 IP 去访问百度服务器。
同理,B 的过程也是一样。通过这样的层层端口映射,最终保证地址(IP + 端口)的唯一性。A 和 B访问百度服务器,尽管它们的局域网 IP 是一样的,但是最终它们访问百度的地址(IP +端口)是唯一的,所以,百度服务器回复时,原路返回时能够区分到底给谁回。
ICMP 一般认为是在三层的。主要传递一些差错报文和其他需要注意的信息。
ICMP 分为两类,一类是 ICMP 查询报文,另一类是 ICMP 差错报文。
三层设备(路由器)给该主机的IP数据报进行分组转发时,没有找到相应路径,向源 IP 发回 ICMP 主机不可达
1)ICMP 差错报文。
2)目的地址是广播地址或者多播地址的 IP 数据报。
3)链路层广播的数据报
4)不是 IP 分片的第一片
5)源地址不是单个主机的数据包。
? 主机
? |
? |
——————————————————————
| |
| |
R1 R2
1)主机发送 IP 数据报给 R1,因为主机的默认路由指向的下一跳是 R1。
2)R1 收到数据报并且检查它的路由表,发现 R2 是发送该数据报的下一跳。当他将数据报发送给 R2 的时候,发现发送的接口与接受的端口是一样的,因此同时发送一个 ICMP 重定向报文给主机。
3)R1 接受到 ICMP 重定向报文后,接下来的数据报就发送给 R2,而不再发送给 R1。
重定向报文只能有路由器生成。
重定向报文是为主机而不是为路由器使用的。
网络层 网络层 网络层
Ping 是 ICMP 的一个重要应用,主要用来测试两台主机之间的连通性。Ping 的原理是通过向目的主机发送 ICMP Echo 请求报文,目的主机收到之后会发送Echo回答报文。Ping会根据时间和成功响应的次数估算出数据包往返时间以及丢包率。
网际控制报文协议——ICMP可以更有效地转发IP数据报和提高交付成功的机会,是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。它封装在 IP 数据报中,但是不属于高层协议。ICMP 报文分为差错报告报文和询问报文。
参考文章:《对于 Ping 的过程,你真的了解吗?》https://mp.weixin.qq.com/s/DfQT3Vw2xaq60YIil-7Yxw
UDP没有拥塞控制,因此网络中的拥塞也不影响到主机的发送频率。而某些实时应用要求以稳定的速率发送,能容忍一些数据的丢失,但是不允许有较大的时延,而UDP刚好满足这些应用的需求。
UDP数据报包含两部分,分别是UDP首部和用户数据。整个UDP数据报作为IP数据报的数据部分封装在IP数据报中。UDP首部由8字节组成,分别是4个2字节的字段:
通过重传、滑动窗口与拥塞控制等来保证。
在TCP协议中RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。
服务器程序端口未打开而客户端来连接,最为常见。去telnet一个未打开的TCP的端口可能会出现这种错误。这个和操作系统的实现有关。在某些情况下,操作系统也会完全不理会这些发到未打开端口请求,例如WINDOWS 7 。
比如在下面这种情况下,主机241向主机114发送一个SYN请求,表示想要连接主机114的40000端口,但是主机114上根本没有打开40000这个端口,于是就向主机241发送了一个RST。这种情况很常见。特别是服务器程序core dump之后重启之前连续出现RST的情况会经常发生。
用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间为100ms。接收数据超时时,会发送RST包。
如果服务端某个socket已经关闭,但依然收到客户端的数据也会产生RST。
为了准确无误地把数据送达目标处,TCP协议采用了三次握手策略。
如下图所示,下面的两个机器人通过3次握手确定了对方能正确接收和发送消息(图片来源:《图解HTTP》)。
简单示意图:
具体过程:
刚开始, 客户端和服务器都处于 CLOSE 状态.此时, 客户端向服务器主动发出连接请求, 服务器被动接受连接请求.
1, TCP服务器进程先创建传输控制块TCB, 时刻准备接受客户端进程的连接请求, 此时服务器就进入了 LISTEN(监听)状态
2, TCP客户端进程也是先创建传输控制块TCB, 然后向服务器发出连接请求报文,此时报文首部中的同步标志位SYN=1, 同时选择一个初始序列号 seq = x, (需要注意的是, 序号并不是从 0 开始的, 而是由发送方随机选择的初始序列号 ( Initial Sequence Number, ISN )开始 )此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定, SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
3, TCP服务器收到请求报文后, 如果同意连接, 则发出确认报文。确认报文中的 ACK=1, SYN=1, 确认序号是 x+1, 同时也要为自己初始化一个序列号 seq = y, 此时, TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据, 但是同样要消耗一个序号。
4, TCP客户端进程收到确认后还, 要向服务器给出确认。确认报文的ACK=1,确认序号是 y+1,自己的序列号是 x+1。ACK报文段可以携带数据,但如果不携带数据则不消耗序号。在这种情况下,下一个数据报的序号仍然是seq=x+1。
5, 此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。
三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。
第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常
第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常
第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常
所以三次握手就能确认双发收发功能都正常,缺一不可。
为了防止先前已经失效的连接请求报文突然又传送到了服务器,从而产生错误。
如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送的第一个请求连接在网络中滞留,但并且没有丢失。由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时之前滞留的那一次请求连接,因为网络通畅了, 到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让服务器再次进入到ESTABLISHED状态,但客户端还是CLOSED状态,这将导致不必要的错误和资源的费。
如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。
在前两次握手的时候双方都随机选择了自己的初始段序号,并且第二次握手的时候 客户端收到了自己的ACKnumber,确认了自己的序列号,而服务端还没有确认自己的序列号,没有收到ACKnumber, 如果这时候两次握手下就进行数据传递, 序号没有同步,数据就会乱序。
因为三次已经可以满足需要了, 四次就多余了.
SYN 同步序列编号(Synchronize Sequence Numbers) 是 TCP/IP 建立连接时使用的握手信号
接收端传回发送端所发送的SYN是为了告诉客户端,我接收到的信息确实就是你所发送的信号。
回传ACK则是为了确认从服务端到客户端的通信
DDOS本是利用大量的合理请求造成资源过载,占用大量网络资源,导致正常用户服务不可用。
常见的DDOS攻击有SYN flood、UDP flood、ICMP flood等。其中SYN flood是一种最为经典的DDOS攻击(SYN洪水攻击)
**SYN flood :**首先伪造大量的源IP地址,分别向服务器端发送大量的SYN包,此时服务器端会返回SYN/ACK包,因为源地址时伪造的,所以伪造的IP并不会应答服务器端没有收到伪造IP的回应,会重试3-5次并且等待一个SYN Time(一般为30秒至2分钟),如果超时则丢弃这个连接。攻击者大量发送这种伪造源地址的SYN求,服务端将会消耗非常多的资源(CPU和内存)来处理这种半连接,同时还要不断地对这些IP进行SYN+ACK重试,最后的结果是服务器无暇理睬正常的连接请求导致拒绝服务。
数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。
任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。
举个例子:A 和 B 打电话,通话即将结束后,A 说“我没啥要说的了”,B回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”,A 回答“知道了”,这样通话才算结束。
上面讲的比较概括,推荐一篇讲的比较细致的文章:https://blog.csdn.net/qzcsu/article/details/72861891
建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
TCP套接字的唯一标识是一个五元组(源IP地址,源端口号,目的IP地址,目的端口号,协议)
多个不同的套接字可以拥有相同的目的端口号80,由于源ip或端口号不同,TCP套接字就可以唯一标识,通信就可以进行。同时,一个端口号只能被一个进程所监听。
listen函数接收客户端的连接请求,accept函数把建立好连接的socket从就绪队列拿出一个,如果就绪队列为空(没有就绪连接) 则会阻塞。
注意:端口是用来区分应用的,而不是区分连接!!!
服务器:server通常固定在某个本地端口上监听,等待client的连接请求,所以五元组中后三个是固定的,因此最大tcp连接为客户端ip数×客户端port数,对IPV4,不考虑ip地址分类等因素,最大tcp连接数约为2的32次方(ip数)×2的16次方(port数),也就是server端单机最大tcp连接数约为2的48次方。上面给出的是理论上的单机最大连接数,在实际环境中,受到机器资源、操作系统等的限制,特别是sever端,其最大并发tcp连接数远不能达到理论上限。
**客户端:**client每次发起tcp连接请求时,除非绑定端口,通常会让系统选取一个空闲的本地端口(local port),该端口是独占的,不能和其他tcp连接共享。因为tcp首部port字段16位,所以普通服务只有65536 - 1024个端口可用(0-1023保留为知名服务端口)。在计算资源够的情况下,可以保持 64512 个长连接。
服务端进入了CLOSE_WAIT状态说明服务器端已经到了响应客户端关闭时请求的FIN, 但还没有发出自己的FIN。
**解决办法:**一般是因为代码不严谨,服务端阻塞在某个操作上。
MSL(最大分段寿命),即一个 TCP 分段可以存在于互联网系统中的最大时间,TCP允许不同的实现可以设置不同的MSL值。通常为4分钟
在高并发短连接的TCP服务器上,服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量socket处于TIME_WAIT状态。
主动关闭连接的一方才会产生TIME_WAIT
一些爬虫服务器或者WEB服务器,(如果在安装的时候没有做内核参数优化的话)上经常会遇到这个问题
第一种使用netstat(性能一般)
netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
LAST_ACK 14
SYN_RECV 348
ESTABLISHED 70
FIN_WAIT1 229
FIN_WAIT2 30
CLOSING 33
TIME_WAIT 18122
状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉
第二种使用ss命令(性能较高)
ss -s
显示:
Total: 4122 (kernel 0)
TCP: 37241 (estab 3157, closed 33193, orphaned 858, synrecv 0, timewait 33176/0), ports 0
Transport Total IP IPv6
* 0 - -
RAW 1 1 0
UDP 4 4 0
TCP 4048 4048 0
INET 4053 4053 0
FRAG 0 0 0
可以看到timewait的链接有3万多个
TCP 本地端口数量,上限为
65535
(6.5w),这是因为 TCP 头部使用16 bit
,存储「端口号」,因此约束上限为65535
。
(1)服务器维护每一个连接需要一个socket,也就是每个连接会占用一个文件描述符,而文件描述符的使用是有上限的,如果持续高并发,会导致一些连接失败。
(2)由于TIME-WAIT状态的连接存在,服务器进程无法立即重启,因为端口被占用的问题。(双十一,Tmall服务器)
(3)占一定的内存,一个4k(但不是主要危害)
解决办法:
net.ipv4.tcp_tw_reuse = 1
socket重用:允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;如果新的时间戳比之前TIME_WAIT连接的时间戳大的话(大于1s),则可直接复用原有的TIME_WAIT连接。即:TIME-WAIT状态的连接,仅仅1秒后就可以被重用了。
net.ipv4.tcp_tw_recycle = 1
表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout
修改系默认的 TIMEOUT 时间
可设置套接字选项为SO_REUSEADDR,该选项的意思是,告诉操作系统,如果端口忙,但占用该端口TCP连接处于TIME_WAIT状态,并且套接字选项为SO_REUSEADDR,则该端口可被重用。如果TCP连接处于其他状态,依然返回端口被占用。该选项对服务程序重启非常有用。
计算方式:在数据传输的过程中,将发送的数据段都当做一个16位的整数。将这些整数加起来。并且前面的进位不能丢弃,补在后面,最后取反,得到校验和。
发送方:在发送数据之前计算检验和,并进行校验和的填充。
接收方:收到数据后,对数据以同样的方式进行计算,求出校验和,与发送方的进行比对。
注意:如果接收方比对校验和与发送方不一致,那么数据一定传输有误。但是如果接收方比对校验和与发送方一致,数据不一定传输成功。
序列号:TCP传输时将每个字节的数据都进行了编号,这就是序列号。
确认应答:TCP传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答。也就是发送ACK报文。这个ACK报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。
序列号的作用不仅仅是应答的作用,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据。这也是TCP传输可靠性的保证之一。
重传机制的其中一个方式,就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的 ACK
确认应答报文,就会重发该数据,也就是我们常说的超时重传。
TCP 会在以下两种情况发生超时重传:
RTT
(Round-Trip Time 往返时延),从下图我们就可以知道:
RTT
就是数据从网络一端传送到另一端所需的时间,也就是包的往返时间。
超时重传时间是以 RTO
(Retransmission Timeout 超时重传时间)表示。
当超时时间 RTO 较大时,重发就慢,丢了老半天才重发,没有效率,性能差;
当超时时间 RTO 较小时,会导致可能并没有丢就重发,于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。
超时重传时间 RTO 的值应该略大于报文往返 RTT 的值。
自动重传请求(Automatic Repeat-reQuest,ARQ)是OSI模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认报文,它通常会重新发送。ARQ包括停止等待ARQ协议和连续ARQ协议。
优点: 简单
缺点: 信道利用率低,等待时间长
1) 无差错情况:
发送方发送分组,接收方在规定时间内收到,并且回复确认.发送方再次发送。
2) 出现差错情况(超时重传):
停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认,就重传前面发送过的分组(认为刚才发送过的分组丢失了)。因此每发送完一个分组需要设置一个超时计时器,其重传时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为 自动重传请求 ARQ 。另外在停止等待协议中若收到重复分组,就丢弃该分组,但同时还要发送确认。连续 ARQ 协议 可提高信道利用率。发送维持一个发送窗口,凡位于发送窗口内的分组可连续发送出去,而不需要等待对方确认。接收方一般采用累积确认,对按序到达的最后一个分组发送确认,表明到这个分组位置的所有分组都已经正确收到了。
由于TCP传输时保证能够在任何环境下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。
在Linux中(BSD Unix和Windows下也是这样)超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。重发一次后,仍未响应,那么等待2500ms的时间后,再次重传。等待4500ms的时间继续重传。以一个指数的形式增长。累计到一定的重传次数,TCP就认为网络或者对端出现异常,强制关闭连接。
3) 确认丢失和确认迟到
连续 ARQ 协议可提高信道利用率。发送方维持一个发送窗口,凡位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累计确认,对按序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。
优点: 信道利用率高,容易实现,即使确认丢失,也不必重传。
缺点: 不能向发送方反映出接收方已经正确收到的所有分组的信息。 比如:发送方发送了 5条 消息,中间第三条丢失(3号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫 Go-Back-N(回退 N),表示需要退回来重传已经发送过的 N 个消息。
回退n帧ARQ可以看做是滑动窗口协议,这就是说接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,这就表示:到这个分组为止的所有分组都已正确收到了。
但网络状况不好的时候会出现,如发送窗口为 10 时,一次发送 10 个数据包,前面两个正确返回了,但第三个丢失了,这时发送方就得重新从第三个包开始,把后面的再传一遍,接收方发现前面的 3 - 10 这几个帧失序并丢弃,所以网络不佳的情况下可能会比停止等待ARQ还慢。
滑动窗口:
例子:
TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据,并定期的向接收端发送窗口探测数据段,让接收端把窗口大小告诉发送端。
注:16位的窗口大小最大能表示65535个字节(64K),但是TCP的窗口大小最大并不是64K。在TCP首部中40个字节的选项中还包含了一个窗口扩大因子M,实际的窗口大小就是16为窗口字段的值左移M位。每移一位,扩大两倍。
在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。
为了进行拥塞控制,TCP 发送方要维持一个拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。
TCP的拥塞控制采用了四种机制,即 慢启动 、 拥塞避免 、快重传 和 快恢复。在网络层也可以使路由器采用适当的分组丢弃策略(如主动队列管理 AQM),以减少网络拥塞的发生。
为了防止 cwnd 增长过大引起网络拥塞,设置一个慢开始阈值(ssthresh 状态变量)
当 cwnd<ssthresh,使用慢开始算法
当 cwnd=ssthresh,既可使用慢开始算法,也可以使用拥塞避免算法
当 cwnd>ssthresh,使用拥塞避免算法
拥塞发生
当网络出现拥塞,也就是会发生数据包重传,重传机制主要有两种:
发生超时重传的拥塞发生算法
就把慢开始阈值设置为出现拥塞时的发送窗口大小的一半。然后把拥塞窗口设置为 1,执行慢开始算法。 如图所示:
有了 FRR,就不会因为重传时要求的暂停被耽误。 当有单独的数据包丢失时,快速重传和恢复(FRR)能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时,它则不能很有效地工作。
因为如果连接是稳定运行的,并且出现了丢包,这可能是因为一个新的连接启动并占用了你的一些带宽。你应该将窗口减少一半,因为你可用的带宽已经减少了一半。而且,如果有两个以上的连接共享带宽,则将窗口减半是保守的——在高流量密集时保持保守可能是明智的。
1、什么是 tcp 粘包?
发送方发送的多个数据包,到接收方缓冲区首尾相连,粘成一包,被接收。
2、原因
(1)发送方原因
TCP默认使用Nagle算法(主要作用:减少网络中报文段的数量),而Nagle算法主要做两件事:
(2)接收方原因
TCP接收到数据包时,并不会马上交到应用层进行处理,而是接收到的数据包保存在接收缓存里,然后应用程序主动从缓存读取收到的分组。这样一来,如果TCP接收数据包到缓存的速度大于应用程序从缓存中读取数据包的速度,多个包就会被缓存,应用程序就有可能读取到多个首尾相接粘到一起的包。
3、处理方法
(1)发送方
对于发送方造成的粘包问题,可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭算法。
(2)接收方
接收方没有办法来处理粘包现象,只能将问题交给应用层来处理。
(2)应用层
应用层的解决办法简单可行,不仅能解决接收方的粘包问题,还可以解决发送方的粘包问题。
解决办法:循环处理,应用程序从接收缓存中读取分组时,读完一条数据,就应该循环读取下一条数据,直到所有数据都被处理完成,但是如何判断每条数据的长度呢?
TCP为了保证可靠传输并减少额外的开销(每次发包都要验证),采用了基于流的传输,基于流的传输不认为消息是一条一条的,是无保护消息边界的(保护消息边界:指传输协议把数据当做一条独立的消息在网上传输,接收端一次只能接受一条独立的消息)。
UDP则是面向消息传输的,是有保护消息边界的,接收方一次只接受一条独立的信息,所以不存在粘包问题。
举个例子:有三个数据包,大小分别为2k、4k、6k,如果采用UDP发送的话,不管接受方的接收缓存有多大,我们必须要进行至少三次以上的发送才能把数据包发送完,但是使用TCP协议发送的话,我们只需要接受方的接收缓存有12k的大小,就可以一次把这3个数据包全部发送完毕。
域名解析协议,www.xxx.com 转换成 ip,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的 ip 地址,也提供逆向从IP地址反查域名的服务。
DNS 协议运行在 UDP 协议之上,使用端口号 53
为什么不用域名来直接进行通信呢?
总结一点就是IP地址是面向主机的,而域名则是面向用户的。
hosts文件
域名和IP的对应关系保存在一个叫hosts文件中。最初,通过互联网信息中心来管理这个文件,如果有一个新的计算机想接入网络,或者某个计算IP变更都需要到信息中心申请变更hosts文件。其他计算机也需要定期更新,才能上网。但是这样太麻烦了,就出现了DNS系统。
在域名解析的过程中仍然会优先查找hosts文件的内容。
1、域名的层次结构
域名系统必须要保持唯一性。为了达到唯一性的目的,因特网在命名的时候采用了层次结构的命名方法:
域名服务主要是基于UDP实现的,服务器的端口号为53。关于域名的层次结构,如下图所示:
eg :我们熟悉的,www.baidu.com
2、域名的分级
域名可以划分为各个子域,子域还可以继续划分为子域的子域,这样就形成了顶级域、二级域、三级域等。如下图所示:
其中顶级域名分为:国家顶级域名、通用顶级域名、反向域名。
国家顶级域名 | 中国:cn, 美国:us,英国uk… |
---|---|
通用顶级域名 | com公司企业,edu教育机构,gov政府部门,int国际组织,mil军事部门 ,net网络,org非盈利组织… |
反向域名 | arpa,用于PTR查询(IP地址转换为域名) |
域名是分层结构,域名服务器也是对应的层级结构。
有了域名结构,还需要有一个东西去解析域名,域名需要由遍及全世界的域名服务器去解析,域名服务器实际上就是装有域名系统的主机。
由高向低进行层次划分,可分为以下几大类:
分类 | 作用 |
---|---|
根域名服务器 | 最高层次的域名服务器,本地域名服务器解析不了的域名就会向其求助 |
顶级域名服务器 | 负责管理在该顶级域名服务器下注册的二级域名 |
权限域名服务器 | 负责一个区的域名解析工作 |
本地域名服务器 | 当一个主机发出DNS查询请求时,这个查询请求首先发给本地域名服务器 |
注:一个域名服务器所负责的范围,或者说有管理权限的范围,就称为区
我们需要注意的是:
每个层的域名上都有自己的域名服务器,最顶层的是根域名服务器
每一级域名服务器都知道下级域名服务器的IP地址
为了容灾, 每一级至少设置两个或以上的域名服务器
当一个用户在地址栏输入www.taobao.com时,DNS解析有大致十个过程:
通过攻击DNS服务器或者伪造DNS服务器,把目标网站域名解析到错误的IP地址从而实现用户无法访问目标网站或进行其它恶意行为。
传统的基于 UDP 协议的公共 DNS 服务极易发生 DNS 劫持
解决方案:
域名解析请求直接发送到HTTPDNS服务端,从而绕过运营商的本地DNS(相当于本地域名服务器)
通过代理绕过运行商本地DNS
修改主机的dns服务器地址相当于修改了本地域名服务器
URI(Uniform Resource Identifier) 是统一资源标志符,可以唯一标识一个资源。
URL(Uniform Resource Location) 是统一资源定位符,可以提供该资源的路径。它是一种具体的 URI,即 URL 可以用来标识一个资源,而且还指明了如何 locate 这个资源。
URI的作用像身份证号一样,URL的作用更像家庭住址一样。URL是一种具体的URI,它不仅唯一标识资源,而且还提供了定位该资源的信息。
格式:
案例:
POST /search HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint,
application/msword, application/x-silverlight, application/x-shockwave-flash, */*
Referer: http://www.google.cn/
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)
Host: www.google.cn
Connection: Keep-Alive
Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g;
NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-
FxlRugatx63JLv7CWMD6UB_O_r
hl=zh-CN&source=hp&q=domety
请求行
请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET /index.html HTTP/1.1。
HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。
请求头
请求头部由键/值对组成,每行一对,键和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息
典型的常用请求头有:
User-Agent:产生请求的客户端类型。
Accept:客户端可识别的内容类型列表。
Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
Accept-Encoding: 客户端使用的编码环境和编码方式
Accept-Language: 客户端语言环境
Authorization:授权信息,一般用于存放授权之后的信息
Connection:表示是否需要持久连接
Content-Length:表示请求数据正文的长度
Cookie:这个与服务器端做交互的,存储保持会话的重要信息 Referer:表示该次请求的来源,一般用于做防盗链
Content-Type字段类型
换行符
CR+LF
请求体
请求体通常不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。
格式:
案例:
HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Content-Type: text/html; charset=UTF-8
Content-Encoding: UTF-8
Content-Length: 138
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
ETag: "3f80f-1b6-3e1cb03b"
Accept-Ranges: bytes
Connection: close
<html>
<head>
<title>An Example Page</title>
</head>
<body>
Hello World, this is a very simple HTML document.
</body>
</html>
状态行
状态行由HTTP协议的版本、响应状态代码和状态代码的文本描述3个字段组成,它们用空格分隔。例如,HTTP/1.1 200 OK。
状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。
常见的状态码及其描述:
1xx
类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
2xx
类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。
3xx
类状态码表示客户端请求的资源发送了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。
**301 Moved Permanently:**永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
**302 Found:**表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。
301 和 302 都会在响应头里使用字段 Location
,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。
**304 Not Modified:**不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,用于缓存控制。(etag、if-none-match)
4xx
类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。
5xx
类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。
响应头
响应头部与请求头部类似,为响应报文添加了一些附加信息,例如:
301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。他们的不同在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。
Host
客户端发送请求时,用来指定服务器的域名。有了 Host
字段,就可以将请求发往「同一台」服务器上的不同网站。
Content-Lengt
服务器在返回数据时,会有 Content-Length
字段,表明本次回应的数据长度。
Connection
用于表示本次连接采取的是长连接还是短连接。
Content-Type
用于服务器回应时,告诉客户端,本次数据是什么格式。
Accept
客户端请求的时候,声明自己可以接受哪些数据格式。
Content-Encoding
说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式 (gzip)
在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源(如JavaScript文件、图像文件、CSS文件等),每遇到这样一个Web资源,浏览器就会重新建立一个HTTP会话。
而从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:
Connection:keep-alive
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
典型应用场景:
HTTP 是一种不保存状态,即无状态(stateless)协议。也就是说 HTTP 协议自身不对请求和响应之间的通信状态进行保存。那么我们保存用户状态呢?
cookie和Session 机制的存在就是为了解决这个问题,Session 的主要作用就是通过服务端记录用户的状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了(一般情况下,服务器会在一定时间内保存这个 Session,过了时间限制,就会销毁这个Session)。
在服务端保存 Session 的方法很多,最常用的就是内存和数据库(比如是使用内存数据库redis保存)。既然 Session 存放在服务器端,那么我们如何实现 Session 跟踪呢?大部分情况下,我们都是通过在 Cookie 中附加一个 Session ID 来方式来跟踪。
Cookie 被禁用怎么办?
最常用的就是利用 URL 重写把 Session ID 直接附加在URL路径的后面。
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
当服务器返回给客户端一个Http响应信息时,其中如果包含Set-Cookie这个头部,说明:
Session是一种记录客户状态的机制,不同于Cookie的是Cookie保存在客户端浏览器中,而==Session保存在服务器上。==客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
Session在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建Session的方法,在Java中是通过调用HttpServletRequest
的getSession
方法(使用true作为参数)创建的。当一个用户第一次访问某个网站时会自动创建HttpSession,每个用户可以访问他自己的HttpSession。 创建Session的同时,服务器会为该Session生成唯一的session id, 这个session id在随后的请求中会被用来重新获得已经创建的Session。
Session被创建之后,就可以调用Session相关的方法往Session中增加内容了, 而这些内容只会保存在服务器中,发到客户端的只有session id。可以通过HttpServletRequest对象的getSession方法获得HttpSession。 通过HttpSession的setAttribute方法可以将一个值放在HttpSession中, 通过调用HttpSession对象的getAttribute方法,同时传入属性名就可以获取保存在HttpSession中的对象。
当客户端再次发送请求的时候,会将这个session id带上,服务器接受到请求之后就会依据session id找到相应的Session,从而再次使用Session。
Session保存在服务器端。为了获得更高的存取速度,服务器一般把Session放在内存中。每个用户都会有一个独立的Session。这个Session使用一个Session ID来标识这个Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。
Session在用户第一次访问服务器的时候自动创建。需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session。 如果尚未生成Session,也可以使用request.getSession(true)强制生成Session。
Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session"活跃(active)"了一次。
例如,当浏览器第二次发送请求,会将前一次服务器响应中的Session ID放在请求中一并发送到服务器上,服务器从请求中提取出Session ID,并和保存的所有Session ID进行对比,找到这个用户对应的Session。
由于会有越来越多的用户访问服务器,因此Session也会越来越多。为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。
保存session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器
由于cookie可以被人为的禁止,必须有其它的机制以便在cookie被禁止时仍然能够把session id传递回服务器,经常采用的一种技术叫做URL重写,就是把session id附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id
另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器
<input type="hidden" name="ExPws" value="dd">
安全性: Session 比 Cookie 安全,Session 是存储在服务器端的,Cookie 是存储在客户端的。
存取值的类型不同:Cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。
有效期不同: Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭(默认情况下)或者 Session 超时都会失效。
存储大小不同: 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。
Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。
Cookie 一般用来保存用户信息 比如①我们在 Cookie 中保存已经登录过得用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了;②一般的网站都会有保持登录也就是说下次你再访问网站的时候就不需要重新登录了,这是因为用户登录的时候我们可以存放了一个 Token 在 Cookie 中,下次登录的时候只需要根据 Token 值来查找用户即可(为了安全考虑,重新登录一般要将 Token 重写);③登录一次网站后访问网站其他页面不需要重新登录。
Session 的主要作用就是通过服务端记录用户的状态。 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。
Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端。相对来说 Session 安全性更高。如果要在 Cookie 中存储一些敏感信息,不要直接写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。
最常用的就是利用 URL 重写把 Session ID 直接附加在URL路径的后面。
(Access)Token是访问资源接口(API)时所需要的资源凭证,每一次请求都需要携带 token,需要把 token 放到 HTTP 的 Header 里
基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用解析 token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库
refresh token用来更新access token
标准答案:
加分答案:
GET和POS本质上都是TCP连接,上述区别的根本原因在于,HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。例如,(大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。如果在GET的Request Body中偷带数据,但是不保证该数据会被处理。
此外==,GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把httpheader和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)==。
因此,应该注意:
GET与POST都有自己的语义,不能随便混用。 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。
通常浏览器在发送请求时都会带着“Accept-Encoding”头字段,里面是浏览器支持的压缩格式列表,例如gzip、deflate、br等,这样服务器就可以从中选择一种压缩算法,放进“Content-Encoding”响应头里,再把原数据压缩后发给浏览器。
缺点:gzip等压缩算法通常只对文本文件有较好的压缩率,而图片、音频视频等多媒体数据本身就已经是高度压缩的,再用gzip处理也不会变小(甚至还有可能会增大一点),所以它就失效了。
大文件分解成多个小块,把这些小块分批发给浏览器,浏览器收到后再组装复原。
这种“化整为零”的思路在HTTP协议里就是“chunked”分块传输编码,在响应报文里用头字段“Transfer-Encoding: chunked”来表示,意思是报文里的body部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送。
分块传输也可以用于“流式数据”,例如由数据库动态生成的表单页面,这种情况下body数据的长度是未知的,无法在头字段“Content-Length”里给出确切的长度,所以也只能用chunked方式分块发送。
Transfer-Encoding: chunked
和Content-Length
这两个字段是互斥的,也就是说响应报文里这两个字段不能同时出现,一个响应报文的传输要么是长度已知,要么是长度未知(chunked)。
分块传输的编码规则:
1)每个分块包含两个部分,长度头和数据块;
2)长度头是以CRLF(回车换行,即\r\n)结尾的一行明文,用16进制数字表示长度;
3)数据块紧跟在长度头后,最后也用CRLF结尾,但数据不包含CRLF;
4)最后用一个长度为0的块表示结束,即“0\r\n\r\n”。
、
DELETE、HOST等方法Connection: keep-alive
来实现长连接头部压缩
HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。
这就是所谓的 HPACK
算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
二进制格式
HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧和数据帧。增加了数据传输的效率。
多路复用
HTTP/2 是可以在一个连接中并发多个请求或回应,而不用按照顺序一一对应。
移除了 HTTP/1.1 中的串行请求,不需要排队等待,也就不会再出现「队头阻塞」问题,降低了延迟,大幅度提高了连接的利用率。
举例来说,在一个 TCP 连接里,服务器收到了客户端 A 和 B 的两个请求,如果发现 A 处理过程非常耗时,于是就回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分。
服务器推送
HTTP/2 还在一定程度上改善了传统的「请求 - 应答」工作模式,服务不再是被动地响应,也可以主动向客户端发送消息。
举例来说,在浏览器刚请求 HTML 的时候,就提前把可能会用到的 JS、CSS 文件等静态资源主动发给客户端,减少延时的等待,也就是服务器推送(Server Push,也叫 Cache Push)。
HTTP/2 主要的问题在于,多个 HTTP 请求在复用一个 TCP 连接,下层的 TCP 协议是不知道有多少个 HTTP 请求的。所以一旦发生了丢包现象,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来。
HTTP/1.1 中的管道( pipeline)传输中如果有一个请求阻塞了,那么队列后请求也统统被阻塞住了
HTTP/2 多个请求复用一个TCP连接,一旦发生丢包,就会阻塞住所有的 HTTP 请求。
这都是基于 TCP 传输层的问题,所以 HTTP/3 把 HTTP 下层的 TCP 协议改成了 UDP!
UDP 发生是不管顺序,也不管丢包的,所以不会出现 HTTP/1.1 的队头阻塞 和 HTTP/2 的一个丢包全部重传问题。
大家都知道 UDP 是不可靠传输的,但基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输。
1.3
版本,头部压缩算法也升级成了 QPack
。TLS/1.3
的三次握手。QUIC 直接把以往的 TCP 和 TLS/1.3
的 6 次交互合并成了 3 次,减少了交互次数。所以, QUIC 是一个在 UDP 之上的伪 TCP + TLS + HTTP/2 的多路复用的协议。
QUIC 是新协议,对于很多网络设备,根本不知道什么是 QUIC,只会当做 UDP,这样会出现新的问题。所以 HTTP/3 现在普及的进度非常的缓慢,不知道未来 UDP 是否能够逆袭 TCP。
图中第一种请求方式,就是单次发送request请求,收到response后再进行下一次请求,显示是很低效的。
于是http1.1提出了管线化(pipelining)技术,就是如图中第二中请求方式,一次性发送多个request请求。
然而pipelining在接收response返回时,也必须依顺序接收,如果前一个请求遇到了阻塞,后面的请求即使已经处理完毕了,仍然需要等待阻塞的请求处理完毕。这种情况就如图中第三种,第一个请求阻塞后,后面的请求都需要等待,这也就是队头阻塞(Head of line blocking)。
为了解决上述阻塞问题,http2中提出了多路复用(Multiplexing)技术。http2中将多个请求复用同一个tcp链接中,将一个TCP连接分为若干个流(Stream),每个流中可以传输若干消息(Message),每个消息由若干最小的二进制帧(Frame)组成。也就是将每个request-response拆分为了细小的二进制帧Frame,这样即使一个请求被阻塞了,也不会影响其他请求,如图中第四种情况所示。
**不论是短连接还是长连接:**request 报文和 response在三次握手建立连接后的established状态发送
短连接:一般是web服务器发回response后主动关闭连接(如NGINX未开启keep-alive )
长连接:开启keep-alive ,配置keepalive_timeout 65;
如果客户端在这个时间内没有新的请求,那么到时间后由服务端主动断开。
另外:在浏览器tab关闭时,tcp连接会关闭。
浏览器对并发请求的数目限制是针对域名的,即针对同一域名(包括二级域名)在同一时间支持的并发请求数量的限制(Chrome允许对同一Host域名建立6个TCP连接)。如果请求数目超出限制,则会阻塞。因此,网站中对一些静态资源,使用不同的一级域名,可以提升浏览器并行请求的数目,加速界面资源的获取速度。
没用
转发是服务器行为,重定向是客户端行为。
转发(Forword) 通过RequestDispatcher对象的 forward
(HttpServletRequest request,HttpServletResponse response) 方法实现的。 RequestDispatcher 可以通过 HttpServletRequest的 getRequestDispatcher() 方法获得。例如下面的代码就是跳转到 login_success.jsp 页面。
重定向(Redirect) 是利用服务器返回的状态吗来实现的。客户端浏览器请求服务器的时候,服务器会返回一个态码。服务器通过HttpServletRequestResponse的setStatus(int status)方法设置状态码。如果服务器返回301或者302,则浏览器会到新的网址重新请求该资源。
通信内容使用明文,因此内容可能被窃听
无法验证数据的完整性,报文可能已经被修改
不验证通信方的身份,可能遭遇伪装
HTTPS主要解决的就是这三件事,首先为了保证内容不被窃听,HTTPS协议通信的内容都是加密的,并且加入了数字签名来保证数据的完整性,另外,为了确保最开始客户端与服务端建立安全连接,服务端需要去官方的正规的证书颁发机构申请证书,然后把自己的公钥放在证书里发给客户端,用证书来保证公钥的来源是真实可信的。
HTTPS就是在HTTP与TCP层中间添加了一个SSL层。因为HTTPS被HTTP多了这层加密的流程,所以HTTPS的速度要比HTTP慢的多。
SSL的加密过程是RSA与AES混合进行的。简单概括一下,就是通过RSA加密方式来交换AES加解密的密钥,然后使用AES加密的方式来传输报文。
基于散列函数验证信息的完整性。
常见的有 MD5、SHA1、SHA256,该类函数特点是函数单向不可逆、对输入非常敏感、输出长度固定,针对数据的任何修改都会改变散列函数的结果,用于防止信息篡改并验证数据的完整性;
需要权威的第三方机构CA(如沃通CA)去证明服务器身份,CA 负责核实公钥的拥有者的信息,并颁发认证"证书",同时能够为使用者提供证书验证服务,即PKI体系
上述两种技术的出现是为了解决HTTP中存在的安全性问题。例如,使用明文通信,内容被窃听;不验证身份,身份可伪装;无法验证报文完整性,容易被篡改。HTTPS=HTTP+TLS,并使用TSL作为安全保障,对传输内容加密并做身份验证。
证书:全称公钥证书(Public-Key Certificate, PKC),里面保存着归属者的基本信息,以及证书过期时间、归属者的公钥,并由认证机构(Certification Authority, CA)施加数字签名,表明,某个认证机构认定该公钥的确属于此人。数字证书认证机构(CA,Certificate Authority)是客户端与服务器双方都可信赖的第三方机构。
服务器的运营人员向CA提出公开密钥的申请,CA在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该开密钥放入公开密钥证书后绑定在一起。进行HTTPS通信时,服务器会把证书发送给客户端。客户端取得其中的公开密钥之后,先使用数字签名进行验证,如果验证通过,就可以开始通信了。
对称加密,指的就是加、解密使用的同是一串密钥(DES,AES)
非对称加密,指的是加、解密使用不同的密钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。反之,私钥加密的信息,只有公钥才能解密(RSA)
对称加密效率高,但没有非对称加密安全
虽然非对称加密很安全,但是和对称加密比起来,它非常的慢,所以我们还是要用对称加密来传送消息,但对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。
https://blog.csdn.net/jijianshuai/article/details/80582187
AES算法:对明文矩阵进行多轮的轮密相加、字节代换、行位移、列混合等…
中间人攻击原理
针对SSL的中间人攻击方式主要有两类,分别是SSL劫持攻击和SSL剥离攻击
SSL劫持攻击即SSL证书欺骗攻击,攻击者为了获得HTTPS传输的明文数据,需要先将自己接入到客户端和目标网站之间;在传输过程中伪造服务器的证书,将服务器的公钥替换成自己的公钥,这样,中间人就可以得到明文传输带Key1、Key2和Pre-Master-Key,从而窃取客户端和服务端的通信数据;
但是对于客户端来说,如果中间人伪造了证书,在校验证书过程中会提示证书错误,由用户选择继续操作还是返回,由于大多数用户的安全意识不强,会选择继续操作,此时,中间人就可以获取浏览器和服务器之间的通信数据
这种攻击方式也需要将攻击者设置为中间人,之后见HTTPS范文替换为HTTP返回给浏览器,而中间人和服务器之间仍然保持HTTPS服务器。由于HTTP是明文传输的,所以中间人可以获取客户端和服务器传输数据
https://www.jianshu.com/p/852f910d55e2
抓包工具伪造了自签名证书之后可以成功抓包,并且抓到的是明文。
加密层位于http层(应用层)和tcp层(传输层)之间, 所以抓到的http层的数据并没有加密。 同理, 在后台接收端, 经历解密后, 到达http层的数据也是明文。 要注意, https不是对http报文进行加密, 而是对业务数据进行加密, 然后用http传输。所以需要在客户端对密码进行MD5加密处理才行。
ssh 需要进行身份验证。一般都是用非对称的秘钥,公钥的作用是证明提供个密文是不是对应的私钥。当你用私钥登录的时候,服务器就可以用公钥验证你的身份,并且给你预设的权限。
ssh xxx@xxx.xxx -L 8023:RemoteIP:23
-L 将本地的某个端口映射到远程主机的某个端口上,上例中就是将本地的8023端口映射到远程主机的23号端口上,这样就可以直接telnet本机的8023端口来访问远程主机了。但是需要说明的是RemoteIP可以是127.0.0.1,此时127.0.0.1指的是远程计算机,而非本机地址。
-R 则正好与-L相反,它将远程主机的某个端口映射到本地的某个端口上,例如:
ssh xxx@xxx.xxx -R 8023:LocalIP:23
上例将远程主机的8023端口映射到本机的23号端口,这样远程主机就可以telnet 自己的8023端口来访问本地主机了。
1、DNS解析
建立TCP连接
2、http协议生成请求报文
3、TCP协议将请求报文分割成报文段,进行可靠连接传输
4、IP协议进行分组转发 (发送HTTP请求)
5、TCP协议重组请求报文,服务器处理请求
6、Http协议对请求进行处理,服务器返回HTTP报文
7、浏览器解析渲染页面
8、释放连接
Token授权机制、时间戳超时机制、签名机制、拒绝重复调用
跨站脚本攻击(XSS)、Dos攻击、SQL注入攻击、OS命令注入攻击、HTTP头部攻击、目录攻击、开放重定向攻击
答:HTTP1.x是半双工通信,客户端请求服务器响应,是无状态的,如果要实现实时通讯需要长轮询或者长连接的方式,这两种方式带来资源浪费。WebSocket是HTML5以后基于TCP协议应用层的一种全双工实时通讯协议。客户端和服务端可以进行信息的相互传递。它是借Http请求产生握手,在Http的头部会包含WebSocket协议的请求,所以握手之后,协议进行一个升级,转成TCP协议进行交流。
WebSocket可以应用于聊天和即时信息
WebSocket通信流程
对TCP而言在三次握手时的SYN标志会使用上一个ISN值,这个值是使用32位计数器,内由0-4294967295,每一次连接容都会分配到一个ISN值,连接双方对这个值会记录共识,假如这个值不一,就说明了这个连接已超时或无效甚至是被人恶意攻击冒充连接。
30位,子网掩码将某个IP地址划分成网络地址和主机地址两部分,在一个网段中,有2个地址是被固定占用的,一个是网段地址,一个是网段内广播地址,其他是主机可用的地址,至少一个,不然就没有意义了。也就是说,被掩码所分的网段至少要包含3个地址。
可以看到请求后,返回了状态码 302(重定向)与 location 值为长链的响应,然后浏览器会再请求这个长链以得到最终的响应。
**采用302——临时重定向的好处:**每次去请求短链都会去请求短网址服务器(除非响应中用 Cache-Control 或 Expired 暗示浏览器缓存),这样就便于 server 统计点击数,所以虽然用 302 会给 server 增加一点压力,但在数据异常重要的今天,这点代码是值得的,所以推荐使用 302!
MD5,SHA 等算法是加密就意味着性能上会有损失,我们其实不关心反向解密的难度,反而更关心的是哈希的运算速度和冲突概率。
Google 出品的 MurmurHash 算法,MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。与其它流行的哈希函数相比,对于规律性较强的 key,MurmurHash 的随机分布特征表现更良好。非加密意味着着相比 MD5,SHA 这些函数它的性能肯定更高(实际上性能是 MD5 等加密算法的十倍以上),也正是由于它的这些优点,所以虽然它出现于 2008,但目前已经广泛应用到 Redis、MemCache、Cassandra、HBase、Lucene 等众多著名的软件中。
如何解决哈希冲突的问题?
维护一个 ID 自增生成器,比如 1,2,3 这样的整数递增 ID,当收到一个长链转短链的请求时,ID 生成器为其分配一个 ID,再将其转化为 62 进制,拼接到短链域名后面就得到了最终的短网址。
生成ID的方法:1、redis(需要做持久化) 2、雪花算法 3、MySQL 自增主键
XSS攻击:跨站脚本攻击(Cross-Site Scripting),将恶意代码植入到提供给其它用户使用的页面中。目标是为了盗取存储在客户端的cookie或者其他网站用于识别客户端身份的敏感信息。一旦获取到合法用户的信息后,攻击者甚至可以假冒合法用户与网站进行交互。
**例子:**我写了一个网站,然后攻击者在上面发布了一个文章,内容是这样的 <script>alert(document.cookie)</script>
,如果我没有对他的内容进行处理,直接存储到数据库,那么下一次当其他用户访问他的这篇文章的时候,服务器从数据库读取后然后响应给客户端,浏览器执行了这段脚本,就会将cookie展现出来,这就是典型的存储型XSS。
坚决不要相信用户的任何输入,并过滤掉输入中的所有特殊字符。这样就能消灭绝大部分的XSS攻击。
script
标签)。w.Header().Set("Content-Type","text/javascript")
攻击者成功的向服务器提交恶意的SQL查询代码,程序在接收后错误的将攻击者的输入作为查询语句的一部分执行,导致原始的查询逻辑被改变,额外的执行了攻击者精心构造的恶意代码。
举例:' OR '1'='1
,当我们输如用户名 admin ,然后密码输如' OR '1'=1='1
的时候,我们在查询用户名和密码是否正确的时候,本来要执行的是SELECT * FROM user WHERE username='' and password=''
,经过参数拼接后,会执行 SQL语句 SELECT * FROM user WHERE username='' and password='' OR '1'='1'
,这个时候1=1是成立,自然就跳过验证了。
#{}可以防止sql注入 ${}
使用预编译语句(PreparedStatement),这样的话即使我们使用 SQL语句伪造成参数,到了服务端的时候,这个伪造 SQL语句的参数也只是简单的字符,并不能起到攻击的作用。
```java
DDOS:分布式拒绝服务攻击(Distributed Denial of Service),简单说就是发送大量请求是使服务器瘫痪。
在技术角度上,DDoS攻击可以针对网络通讯协议的各层,手段大致有:TCP类的SYN Flood、ACK Flood,UDP类的Fraggle、Trinoo,DNS Query Flood,ICMP Flood,Slowloris类等等。一般会根据攻击目标的情况,针对性的把技术手法混合,以达到最低的成本最难防御的目的,并且可以进行合理的节奏控制,以及隐藏保护攻击资源。
SYN
攻击指的是,攻击客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送SYN
包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN
包将长时间占用未连接队列,正常的SYN
请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。
FTP:21
Tomcat:8080
NGINX:80
dns:53
https:443
mysql:3306
neo4j:7687
将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。用户直接访问负载均衡器,再由负载均衡器将请求转发给后端服务器
负载均衡算法
负载均衡算法决定了后端的哪些健康服务器会被选中。几个常用的算法:
个人网络和Internet服务商之间的中间代理机构,它负责转发合法的网络信息,对转发进行控制和登记,作为连接Internet(广域网)与Intranet(局域网)的桥梁。
网关bai就是你要访问另一个网络时,首先需要访问的网络节点。比喻你有两个不同的内网,在A网中要访问B网,则首先需要访问网关,由它那里路由转发。所以,代理服务器可以说是一个网关,但网关并不一定是代理服务器。里写自定义目录标题)