linux路由协议网络协议栈Word文件下载.docx
《linux路由协议网络协议栈Word文件下载.docx》由会员分享,可在线阅读,更多相关《linux路由协议网络协议栈Word文件下载.docx(21页珍藏版)》请在冰豆网上搜索。
当建立好GRE隧道后,内网1就可以和内网2通信了。
实现:
GRE脚本主要通过iproute2这个工具实现。
使用的主要脚本命令:
Iprouteadd$namemodegreremote$remoteiplocal$localipttl255
Iprouteset$nameup
Iprouteaddnet$net/$maskdev$name
脚本流程:
脚本从lua保存的配置文件中获取到上面的变量值,然后通过以上指令,将变量值设置到相应的隧道中。
责任:
主要担任gre模块的测试(与linux)。
DDNS模块:
原理:
DDNS又叫动态域名解析。
实用环境是在用户动态获取IP地址的情况下。
因为传统的DNS只能与固定IP地址绑定,一旦IP地址发生变化,相应的域名将不能解析到变换后的IP地址上。
然后DDNS改变了这一点。
它以动态域名绑定的方式来完成这一点。
什么叫动态域名呢?
就是指在用户的IP地址发生改变时,相应的DDNS客户端会把自己现在的变化后的IP地址传给DDNS服务器,告诉它自己的IP地址已经发生变化,需要服务器将以前绑定域名的IP换成现在变化后的IP地址。
如果内部在加上端口映射,那么久可以实现路由器内部的主机间接与DNS绑定,即其他人通过域名就能访问的内网的某台计算上的服务器。
DDNS的测试。
静态路由模块:
举个例子,当一个路由器刚接入到一个网络中时,在这个陌生的环境中,它根本不知道去某个地址该怎么走,静态路由就相当于一个指路人,它告诉路由器某个IP地址该怎么走。
配置的时候,只需要告诉路由器到达某个网络需要从哪张网卡和相应网卡出去的网关地址就可以了。
这样凡是到那个网络的IP数据包,路由器都会将它从相应网卡转发出去(ttl-1)。
它并不关心数据包能否真正的到达。
具体命令:
routeadd–net$netmask$netmaskgw$gatewaydev$device
静态路由的脚本的基本框架。
Ipsec模块:
在内核2.6版本中已经存在ipsec模块,该模块的主要作用是让数据包经过加密/认证从安全的隧道中到达指定的目标地址。
它的有几种数据包格式,一种是esp,一种是ah,另一种是esp+ah。
他们的报文格式如下:
Ah是一种用于认证报文,它主要是给数据包提供认证,防重放;
ESP是一种用于加密报文,当然它也有认证的功能,并且也具有抗重放的机制。
它是一种更优越于AH的报文结构。
另外,esp+ah则是一种集esp和ah于一身的格式,当然它的安全性就更不可否认了。
整个模块分为两大类:
第一类,kernelipsec的实现,第二类上层应用程序ike即为ipsec模块协商认证算法和加密算法的协议。
下面谈谈ike协议。
Ike协议分为两个阶段,第一阶段协商对对方的身份进行认证,并且为第二阶段的协商提供一条安全可靠的通道。
第一个阶段又分为3种模式,我们常用的有两种模式,一个是主模式,一个是积极模式。
第二阶段主要对IPSEC的安全性能进行协商,产生真正可以用来加密数据流的密钥。
主模式(IKESA阶段):
安全提议,转换载荷,一些详情
接收端
发起端
DH算法产生公共密钥,密钥交换
加密ID,进行身份认证
以上过程中包含验证信息,我就没特别指出了。
具体参见如下:
发送cockie包,用来标识唯一的一个IPSEC会话。
IKE阶段一(主模式):
发送消息1
initiator====>
responsor
isakmpheader
sapayload
proposalpayload
transformpayload
定义一组策略:
加密方法:
DES
认证身份方法:
预共享密钥
认证散列:
MD5
存活时间:
86400秒
Diffie-Hellmangroup:
1
IKE阶段二(主模式):
发送消息2
initiator<
====responsor
同上
IKE阶段三(主模式):
发送消息3
通过DH算法产生共享密钥
KE(KeyExchang)Payload
nonce(暂时)Payload
DH算法:
A:
P(较大的质数)
B:
P(较大的质数)
G
G
PriA(随机产生)
PriB(随机产生)
PubA=G^PriAmodP
PubB=G^PriBmodP
交换PubA和PubB
Z=PubB^PriAmodP
Z=PubA^PriBmodP
Z就是共享密钥,两个自我产生的Z应相同,它是用来产生3个SKEYID的素材。
IKE阶段四(主模式):
发送消息4
主模式第3、4条消息其实就是DH算法中需要交换的几个参数,然后路由器再通过DH算法计算出的公共密钥计算出以下3个参数(这是在发送第5、6个消息前完成的):
SKEYID_d:
留在在第二阶段用,用来计算后续的IKE密钥资源;
SKEYID_a:
散列预共享密钥,提供IKE数据完整性和认证;
SKEYID_e:
用来加密下一阶段的message,data,presharedkey,包括第二阶段。
IKE阶段五(主模式):
发送消息5
IdentityPayload:
用于身份标识
HashPayload:
用来认证
以上2个负载都用SKEYID_e加密
IKE阶段六(主模式):
发送消息6
消息5、6是用来验证对等体身份的。
至此IKE协商第一阶段完成。
主要会发送6个报文,由于最后一组报文发送的是身份,此时身份已经加密,因此,只能采用地址进行认证,但其安全性高于积极模式。
缺点是耗时比积极模式长。
积极模式:
所有转换载荷,加密材料,提议,DH,ID等
所有转换载荷,加密材料,提议,DH,ID等
验证成功
主要发送3个报文,安全性没有主模式好,由于其ID不加密,因此可用于移动客户端模式。
即不用地址作为ID。
优点:
速度快,缺点安全性不高。
第二阶段快速模式(IPSecSA阶段):
所有二阶段参数,提议,算法等
以上过程中包含验证信息(最开始如果支持PFS算法,那么还要协商DH算法),我就没特别指出了。
首先判断是否启用了PFS(完美转发安全),若启用了则重新进行DH算法产生密钥,若没有启用则是用第一阶段的密钥。
IPSec阶段一(快速模式):
同样定义一组策略,继续用SKEYID_e加密:
Encapsulation—ESP
Integritychecking—SHA-HMAC
DHgroup—2
Mode—Tunnel
IPSec阶段二(快速模式):
发送消息2
同上,主要是对消息1策略的一个确认。
在发送消息3前,用SKEYID_d,DH共享密钥,SPI等产生真正用来加密数据的密钥。
IPSec阶段三(快速模式):
用来核实responsor的liveness。
至此,整个IPSec协商的两个过程已经完成,两端可以进行安全的数据传输。
ike协议我们主要是通过利用开源软件ipsec-tools来实现的。
负责ipsec的代码BUG解决(BUG数量多,就不列出了),ipsec的证书申请脚本编写(研究了openssl)。
Ipsec-tools流程:
eay_init();
//opensll初始化
initlcconf();
//本地配置文件初始化
initrmconf();
//远端配置文件初始化
oakley_dhinit();
//dh算法初始化
compute_vendorids();
//dpd
parse(ac,av);
//传进来的参数分析
ploginit();
//本地日志初始化
pfkey_init()//内核接口af_key初始化,主要是向内核注册
isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))//isakmp配置初始化
cfparse();
//配置文件分析,别且赋值给相应结构体
session();
//主要会话
下面是session函数里面的实现:
sched_init();
//调度初始化
init_signal();
//信号初始化
admin_init()//和setkey,racoonctl的连接口初始化
initmyaddr();
//初始化本地地址
isakmp_init()//isakmp初始化
initfds();
//初始化select的套接字
natt_keepalive_init();
//初始化nat协商的相关内容
for(i=0;
i<
=NSIG;
i++)//信号的相应保存变量初始化
sigreq[i]=0;
check_sigreq();
//检测是否收到有信号
error=select(nfds,&
rfds,(fd_set*)0,(fd_set*)0,timeout);
//多路监听
admin_handler();
//监听到setkey和racoonctl的fd触发,调用该函数处理
isakmp_handler(p->
sock);
//监听到ike连接信息和ike协商信息处理函数
pfkey_handler();
//监听的内核af_key发上来的信息处理函数(包含发起ike协商等)
函数里最重要的函数是isakmp_main()
()这个函数里面除了数据包有效性检查外,ph1_main()第一阶段函数,quick_main()第二阶段处理函数,这两个函数最重要。
这两个函数内分别用了一个重要的结构体:
如下
ph1exchange[][]整个racoon就靠这个结构体来进行协商。
(可以说是贯穿整个racoon)
staticint(*ph1exchange[][2][PHASE1ST_MAX])
__P((structph1handle*,vchar_t*))={
/*error*/
{{},{},},
/*IdentityProtectionexchange*/
{
{nostate1,ident_i1send,nostate1,ident_i2recv,ident_i2send,
ident_i3recv,ident_i3send,ident_i4recv,ident_i4send,nostate1,},
{nostate1,ident_r1recv,ident_r1send,ident_r2recv,ident_r2send,
ident_r3recv,ident_r3send,nostate1,nostate1,nostate1,},
},
/*Aggressiveexchange*/
{nostate1,agg_i1send,nostate1,agg_i2recv,agg_i2send,
nostate1,nostate1,nostate1,nostate1,nostate1,},
{nostate1,agg_r1recv,agg_r1send,agg_r2recv,agg_r2send,
/*Baseexchange*/
{nostate1,base_i1send,nostate1,base_i2recv,base_i2send,
base_i3recv,base_i3send,nostate1,nostate1,nostate1,},
{nostate1,base_r1recv,base_r1send,base_r2recv,base_r2send,
};
可以看的到上面有第一阶段有三个模式的发送和接受函数(main,Aggressive,base);
其中有每一个模式下的交互消息一个函数。
同时也有验证函数。
如果熟悉几种模式的发包流程,
相信通过函数定义的名字就可以轻松知道函数是干嘛用的了。
(注意存在状态判断函数,发送
和接收函数,每个阶段都不同)以上函数会在ph1_main()调用,在pfkey_handler()调用的则是
协商发起方。
staticint(*ph2exchange[][2][PHASE2ST_MAX])
__P((structph2handle*,vchar_t*))={
/*QuickmodeforIKE*/
{nostate2,nostate2,quick_i1prep,nostate2,quick_i1send,
quick_i2recv,quick_i2send,quick_i3recv,nostate2,nostate2,},
{nostate2,quick_r1recv,quick_r1prep,nostate2,quick_r2send,
quick_r3recv,quick_r3prep,quick_r3send,nostate2,nostate2,}
可以看到上面的第二阶段即快速模式下的发送和接受函数,这些函数就是ike第二阶段协商使用的。
其中有二阶段的每个包的发送和接受,状态函数。
具体是怎么实现的请参看相应的源代码。
以上的
ph2handle会在,quick_main()中调用。
各个处理方法和流程参考代码就可以了。
这就是大概流程,其中可能会涉及到openssl编码问题(第一
阶段的算法为二阶段的传递信息编码)。
日志分析:
编写选出特定信息的脚本。
通过awk的传参和让AWK进行处理。
Linuxkernel网络协议栈流程:
LINK
Ip_recv()
IP包头有效性检查
IPheadercheck
主要改变Mark,tos,ttl
Managle(PREROUTING)
整个路由抉择可以过滤多播或组播
通过找到的策略调用相关SA封装IPSEC数据包
NAT(PREROUTEING)
DNAT
De_fragment
Routedecision
Output_route
Input_route
Ouput_route
接受包过滤
Managle(INPUT)
安全路由检查,查找路由表(包括查找IPSEC策略)
Filter(INPUT)
Some_check
包括本机IPSEC数据包处理,或tcp,udp,icmp等
Transfer(tcp,udphandle)
Recvmsg()(socket)
Managle(FORWARD)
ESP,AH(使用netif_rx())等
Localprocess
Filter
F
O
R
W
A
D
sendmsg()(socket)
转发包过滤
安全路有检查,查找路由表(包括查找IPSEC策略)
Routedecision
Managle(OUTPUT)
Nat(OUTPUT)
发送包过滤
Filter(OUTPUT)
Managle(POSTROUTING)
SNAT
Ip_Send_out()
NAT(POSTROUTING)
IP_fragment
QOS
图1,tcp/ip协议栈AF_INET运行结构图(包含IPSEC,netfilter,af_key)
Netfilter维护链表:
netfilter定义了一个二维的链表头数组struct
list_head
nf_hooks[NPROTO][NF_MAX_HOOKS]来表示所有协议族的各个挂接点,NPROTO值为32,可表示linux所支持所有32个协议族(include/linux/socket.h文件中定义),也就是使用socket
(2)函数的第一个参数的值,如互联网的TCP/IP协议族PF_INET
(2)。
每个协议族有NF_MAX_HOOKS(8)个挂接点,但实际只用了如上所述的5个,数组中每个元素表示一个协议族在一个挂接点的处理链表头。
AF_IPX
AF_AX25
AF_LOCAL
AF_INET
……
PREROUTINGFORWARDINPUTOUTPUTPOSTROUTING
…….
managle
nat
filter
图2,netfilter维护的链表结构图
例如:
在IPv4(PF_INET协议族)下,各挂接点定义在:
NF_IP_PRE_ROUTING中,在IP栈成功接收sk_buff包后处理,挂接点在在net/ipv4/ip_input.c的函数
int
ip_rcv(struct
sk_buff
*skb,
struct
net_device
*dev,
packet_type
*pt)
中使用:
return
NF_HOOK(PF_INET,
NF_IP_PRE_ROUTING,
skb,
dev,
NULL,
ip_rcv_finish);
挂接点的操作由结构struct
nf_hook_ops定义:
include/linux/netfilter.h
nf_hook_ops
{
list;
//链表头,用于将此结构接入操作链表
/*
User
fills
in
from
here
down.
*/
nf_hookfn
*hook;
//钩子函数
pf;
//协议族
hooknum;
//挂接点如:
PREROUTING
Hooks
are
ordered
ascending
priority.
priority;
//优先级
优先级列表:
NF_IP_PRI_FIRST
=
INT_MIN,
NF_IP_PRI_CONNTRACK
-200,
NF_IP_PRI_MANGLE
-150,
NF_IP_PRI_NAT_DST
-100,
NF_IP_PRI_FILTER
0,