计算机网络面试问题总结
TCP三次握手四次挥手
握手
一.服务器监听:
int main(int argc, char const *argv[])
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
bind(fd, ...);//绑定端口
listen(fd, 128);
accept(fd, ...);
...
}
在服务器 listen 的时候,主要是进行了全/半连接队列的长度限制计算,以及相关的内存申请和初始化
二.客户端发起SYN包:
int main()
{
fd = socket(AF_INET, SOCK_STREAM, 0);
connect(fd, ...);
...
}
客户端在 connect 的时候,把本地 socket 状态设置成了 TCP_SYN_SENT,选了一个可用的端口,接着发出 SYN 握手请求并启动失败重传定时器
3.服务端响应SYN
服务器响应 ack 是主要工作是判断下接收队列是否满了,满的话可能会丢弃该请求,否则发出 synack。申请 request_sock 添加到半连接队列中,同时启动失败重传定时器
4.客户端相应SYNACK
客户端响应来自服务端的synack时,清除了connect时设置的重传定时器,把当前的socket状态设置为ESTABLISHED,开启保活计时器后发出第三次握手的ack确认
5.服务器响应ACK
服务器把当前半连接队列元素删除,创建新的sock后加入到全连接队列中,socket状态设置为ESTABLISHED
6.服务器accept
accept的重点工作就是从全连接的队列中取出一个返回给用户进程
挥手
1.客户端发送fin服务端,客户端状态:fin_wait_1,服务端状态:close_wait
2.服务端发送ack客户端,客户端状态:fin_wait_2,服务端状态:close_wait
3.服务端发送fin客户端,客户端状态:time_wait,服务端:last_ack
4.客户端发送ack服务端,客户端状态:time_wait,服务端close
5.60秒后(可配置),客户端状态:close
TCP粘包/拆包
TCP建立连接之后,发送和接受数据都有一个可配置的缓冲区
发送端:要发送的数据小于TCP缓冲区的大小时会等凑多几个数据包够缓冲区大小一次性发送出去,这里会发生粘包
接受端:没有及时处理接受缓冲区的数据时,这里会发生粘包
发送端:要发送的数据大于TCP缓冲区的大小时,将会发生拆包
发送端:待发送数据大于最大报文长度(MSS),将会发生拆包
解决方案:
将数据分为两部分,一部分是头部,一部分是内容体;其中头部结构大小固定,且有一个字段声明内容体的大小。
HTTP1.0/1.1/2.0/HTTPS
HTTP1.0 短连接,浏览器每次请求都要和服务器建立一个TCP链接,请求完成立即断开TCP链接,每个图片,js,css文件都要建立一次TCP链接,影响性能和带宽
HTTP1.1 默认支持长连接,一个网页内所有html,js,css,image...请求共享一个TCP连接,还允许不用等上一次请求返回就发出下一次请求
connection 默认 keep-alive,如果不希望使用长连接则HEADER 设置 connection:close,无论是request header还是 response header中包含了connection:close,tcp连接都会马上中断
提供了了身份认证,状态管理,cache缓存机制的请求头和响应头
支持断点续传
HTTP2.0
多路复用
二进制分帧
首部压缩
服务端推送
HTTPS
颁发证书
找可靠的CA机构购买证书,放到自己服务器站点上,或者用let's encrypt自己操作生成免费证书,不过一般浏览器不承认可靠性
证书原理
自己生成一对公私钥,把公钥上传到CA机构,CA机构用自己的私钥对你的公钥进行数字签名并颁发证书,可靠的CA机构的公钥则维护在浏览器或者操作系统,用户客户端验证证书的真伪
HTTPS握手过程
1.先建立TCP连接,客户端发送SYN包到服务器443端口(默认)
2.服务器发送SYN+ACK到客户端
3.客户端发送ACK到服务器 完成TCP三次握手
4.客户端发送Hello消息,包含了随机数1和客户端能支持的加密算法集合,SSL版本等信息
5.服务端发送Hello消息,包含了随机数2和确定了加密算法,自此客户端和服务端都有两个随机数1,2
6.服务器下发证书
7.客户端从浏览器或操作系统获取CA机构的公钥对证书验证真伪,验证通过后,解密得到服务器的公钥,再生成一个随机数3,使用服务器的公钥对随机数3进行非对称加密生成PreMaster Key发送给服务器
8.服务器用自己的私钥解密PreMaster Key得到随机数3,至此客户端和服务器都有三个随机数1,2,3
9.两边根据服务器确认的算法,对这三个随机数连接起来的字符串进行加密生成一份秘钥,用于报文的对称加密
10.客户端用客户端这边生成的秘钥加密报文发送Client Finish消息给服务器,服务器用服务器这边生成的秘钥解密报文,能解出来说明秘钥协商一致
11.服务器用服务器这边生成的秘钥加密报文发送Server Finish消息给客户端,客户端用客户端这边生成的秘钥解密报文,能解出来说明秘钥协商一致
12.到这里,双方已安全协商出了相同的对称加密秘钥,接下来所有报文都会有这个秘钥进行对称加密
13.想知道这个秘钥在客户端和服务器分别存储在哪里,有知道的大神请留言,在fd文件里面?系统内核维护?
网络攻击
中间人攻击
建立HTTPS连接的时候,在服务器把证书发给客户端时,被中间人拦截下来,伪造了一个中间人的证书发给客户端,客户端用伪造的公钥加密随机KEY发给中间人,中间人用伪造的私钥解密得到随机KEY,再用拦截下来的真正的公钥加密随机KEY发给服务器,实现中间人赚差价,闷声发大财
所以客户端要校验证书的可靠性,所以才需要可靠的证书颁发机构,可靠的证书颁发机构的根证书都是操作系统维护的,浏览器拿到服务器的证书去找操作系统判断证书的真假
CSRF (Cross-site request forgery) 跨站请求伪造
攻击原理:
用户登录A网站后,浏览器获得A网站的cookie,然后B网站有个按钮跳转A网站删除所有博客的链接,用户就会在不知情的情况下清空所有博客
攻击实例:
1.登录www.a.com,删除博客链接:www.a.com/blog/delete/1
2.www.b.com 有一张图片<img src="www.a.com/blog/delete/1"/>
3.用户一打开www.b.com,浏览器就会向www.a.com发起删除博客的请求,实现攻击
不止img标签可以实现攻击,frame,script标签也可以, flash也可以
如果网站被XSS攻破,就可以模拟表单进行提交,那么CSRF加Token也不管用
解决方案:
1.验证码,不是万能,只能作为辅助手段,且很影响体验
2.检车http头referer,不是万能,有时浏览器不会发送referer,referer也可以伪造
3.Anti CSRF Token
增删改敏感操作的请求带上一个随机数Token,存储在服务器端的SESSION里面,这样伪造请求就没办法猜到请求的全部参数
读操作不在CSRF攻击范围
GET方式:
http://host/path/delete?uid=1&blog=2&token=DD3A4D42A6E57D6F9F22DFB3D1BD2851
POST方式:
<form action="path" method="POST">
<input type="hidden" name="__token__" value="DD3A4D42A6E57D6F9F22DFB3D1BD2851">
</form>
GET方式有可能会被XSS攻击,,通过Referer方式泄露,尽量还是使用POST
XSS (Cross-Site Scripting)
通过注入HTML+JS篡改网页,用户浏览网页的时候,控制用户浏览器进行攻击,留言板,评论区,站内信是XSS攻击的高发地,攻击者在留言板输入
<script>alert("法海你不懂爱")</script>
如果服务器直接输出攻击者的留言,那么访问留言板的其他用户都会收到,这只是简单的alert,复杂点就用js获取你的cookie,帮你调用转账接口,改密码接口,然后通过同样的方式蠕虫式传播等等
解决方案:
1.HttpOnly
服务器设置Cookie的时候添加HttpOnly,禁止js访问带有HttpOnly属性的Cookie,解决Cookie劫持攻击
2.表单验证码,脚本可以把验证码图片URL发送到远程服务器来识别验证码
3.输出检查
除了富文本的输出外,在变量渲染的时候,可以使用编码或转义的方式防御XSS攻击,PHP的函数是htmlentities() 和 htmlspecialchars()
htmlentities 转化所有html标签和中文
htmlspecialchars只转义 & ' " < > 这五个字符,有中文的时候最好用这个,实在要使用 htmlentities 时,要注意为第三个参数传递正确的编码
DDOS
GET POST 区别
GET:
1.可收藏书签
2.保存在浏览器历史记录中
3.能被缓存
4.url长度字符限制(IE:2083字符,Firefox:65536字符,Chrome:8182字符,Opera:190000字符)
POST:
1.不可收藏书签
2.退回重新提交表单
3.不能保存历史记录
4.不能被缓存
5.数据长度无限制
WEBSOCKET
Websocket是浏览器与服务器进行全双工通讯的应用层协议,基于TCP传输协议,复用HTTP的握手通道
优点:
1.实时性更强,更好的二进制支持
2.建立连接后,协议控制的数据包头部较HTTP协议小很多
建立连接:
HTTP 状态码
301:永久重定向,浏览器再次请求该链接的时候,直接请求浏览器缓存的Location跳转就可以,无需访问服务器
302:临时重定向,浏览器再次请求该链接的时候,除非设置了Cache-Control 或 Expired 暗示浏览器缓存,否则都会直接访问服务器重新获取Location跳转
本作品采用《CC 协议》,转载必须注明作者和本文链接