ipsec outbound

对于输出的报文,主要做如下操作:

1. 调用ip_route_output_flow路由查找

2. 在ip_route_output_flow里面会调用xfrm_lookup进行ipsec policy查找

3.
如果policy的action为XFRM_POLICY_ALLOW,则调用xfrm_find_bundle或者xfrm_bundle_create创建dst链表

4. 应用链表中的dst->output函数进行ipsec加密或发包

例如需要分别对报文进行IP COMP, ESP, AH变换的链表如图所示

下面主要分析bundle的创建过程,skb->dst在__xfrm4_bundle_create前后变化如下:

传输模式:

隧道模式:

图片中黄色的为原始报文的路由缓存,蓝色的为隧道外层的路由缓存


/* Allocate chain of dst_entry‘s, attach known xfrm‘s, calculate
* all the metrics... Shortly, bundle a bundle.
*/

static int
__xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
struct flowi *fl, struct dst_entry **dst_p)
{
struct dst_entry *dst, *dst_prev;
struct rtable *rt0 = (struct rtable*)(*dst_p);
struct rtable *rt = rt0;
struct flowi fl_tunnel = {
.nl_u = {
.ip4_u = {
.saddr = fl->fl4_src,
.daddr = fl->fl4_dst,
.tos = fl->fl4_tos
}
}
};
int i;
int err;
int header_len = 0;
int trailer_len = 0;

dst = dst_prev = NULL;
dst_hold(&rt->u.dst);

/* 每个xfrm生成一个dst_entry,child指向下一次变换或最外层报文的实际路由
* 一个报文最多只能有一次隧道变换,因此rt最多只有两个,一个是隧道内报文的路由,一个是隧道报文的路由
*/
for (i = 0; i < nx; i++) {
struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops);
struct xfrm_dst *xdst;

if (unlikely(dst1 == NULL)) {
err = -ENOBUFS;
dst_release(&rt->u.dst);
goto error;
}

if (!dst)
dst = dst1;
else {
dst_prev->child = dst1;
dst1->flags |= DST_NOHASH;
dst_clone(dst1);
}

xdst = (struct xfrm_dst *)dst1;
xdst->route = &rt->u.dst;
xdst->genid = xfrm[i]->genid;

dst1->next = dst_prev;
dst_prev = dst1;

header_len += xfrm[i]->props.header_len;
trailer_len += xfrm[i]->props.trailer_len;

/* 隧道模式则查找外层ip包的路由 */
if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) {
unsigned short encap_family = xfrm[i]->props.family;
switch(encap_family) {
case AF_INET:
fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4;
fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4;
break;
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
case AF_INET6:
ipv6_addr_copy(&fl_tunnel.fl6_dst, (struct in6_addr*)&xfrm[i]->id.daddr.a6);
ipv6_addr_copy(&fl_tunnel.fl6_src, (struct in6_addr*)&xfrm[i]->props.saddr.a6);
break;
#endif
default:
BUG_ON(1);
}
err = xfrm_dst_lookup((struct xfrm_dst **)&rt,
&fl_tunnel, encap_family);
if (err)
goto error;
} else
dst_hold(&rt->u.dst);
}

/* 最后一个child指向最外层报文的路由 */
dst_prev->child = &rt->u.dst;
dst->path = &rt->u.dst;

*dst_p = dst;
dst = dst_prev;

dst_prev = *dst_p;
i = 0;
for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
struct xfrm_state_afinfo *afinfo;
x->u.rt.fl = *fl;

dst_prev->xfrm = xfrm[i++];
dst_prev->dev = rt->u.dst.dev;
if (rt->u.dst.dev)
dev_hold(rt->u.dst.dev);
dst_prev->obsolete = -1;
dst_prev->flags |= DST_HOST;
dst_prev->lastuse = jiffies;
dst_prev->header_len = header_len;
dst_prev->nfheader_len = 0;
dst_prev->trailer_len = trailer_len;
memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));

/* Copy neighbout for reachability confirmation */
dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
dst_prev->input = rt->u.dst.input;
/* XXX: When IPv6 module can be unloaded, we should manage reference
* to xfrm6_output in afinfo->output. Miyazawa
* */
afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family);
if (!afinfo) {
dst = *dst_p;
err = -EAFNOSUPPORT;
goto error;
}
/* xfrm的dst_entry->output函数初始化为xfrm4_output */
dst_prev->output = afinfo->output;
xfrm_state_put_afinfo(afinfo);
if (dst_prev->xfrm->props.family == AF_INET && rt->peer)
atomic_inc(&rt->peer->refcnt);
x->u.rt.peer = rt->peer;
/* Sheit... I remember I did this right. Apparently,
* it was magically lost, so this code needs audit */
x->u.rt.rt_flags = rt0->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
x->u.rt.rt_type = rt->rt_type;
x->u.rt.rt_src = rt0->rt_src;
x->u.rt.rt_dst = rt0->rt_dst;
x->u.rt.rt_gateway = rt->rt_gateway;
x->u.rt.rt_spec_dst = rt0->rt_spec_dst;
x->u.rt.idev = rt0->idev;
in_dev_hold(rt0->idev);
header_len -= x->u.dst.xfrm->props.header_len;
trailer_len -= x->u.dst.xfrm->props.trailer_len;
}

xfrm_init_pmtu(dst);
return 0;

error:
if (dst)
dst_free(dst);
return err;
}

最后的xfrm4_output_finish2中沿着dst_entry->child每次调用xfrm4_output_one执行一次xfrm,直到最后一个真正的路由dst_entry,这时候调用dst_output进行路由输出;

时间: 2024-10-07 13:14:26

ipsec outbound的相关文章

Internet protocol security (ipsec) packet processing for multiple clients sharing a single network address

Embodiments of the present invention address deficiencies of the art in respect to secure communications for multiple hosts in an address translation environment and provide a method, system and computer program product for IPsec SA management for mu

IPSEC VPN

目录: 简介:... 2 分类:... 2 1.在路由上实现的VPN可分为:... 2 2.在ASA防火墙上实现的VPN:2 IPSec VPN:3 IPSec能实现的功能有:... 3 IPSec的特性(IPSec之所以安全是由它的特性决定的):... 3 IPSec的实施包含两个阶段... 4 IPSec协商过程:... 4 IPSec 范畴的VPN中各种形式的大体配置步骤:... 6 IPSEC VPN几种配置实例... 6 一.实验拓扑... 7 二.实验目的... 7 三.实验要求..

华为USG防火墙 IPsec VPN配置

实验拓扑 使用华为ensp 1.2.00.370模拟器 实验需求 USG-1和USG-2模拟企业边缘设备,分别在2台设备上配置NAT和IPsec VPN实现2边私网可以通过VPN互相通信 实验配置 R1 IP地址配置省略 USG-1配置 [USG-1]firewall zone trust          //配置trust区域 [USG-1-zone-trust]add interface g0/0/0    //将接口加入trust区域 [USG-1-zone-trust]quit [US

ISP IPSEC LAB

1-IPSEC理论 http://down.51cto.com/data/2112582 2-IPSEC LAN To LAN VPN 具体的我不介绍了,网上太多 R1(config)#crypto isakmp policy 100 R1(config-isakmp)#encryption 3des R1(config-isakmp)#hash sha R1(config-isakmp)#authentication pre-share R1(config-isakmp)#group ? 1

GRE OVER IPSEC过程解析

一,产生背景 IPsec是如今十分主流的分支机构互联VPN协议,其本身强大的加密与验证功能保障了在互联网传递时私网数据的安全,但是面对当前多元化的访问需求,Ipsec VPN并不能满足客户对私网网段之间复杂的互访要求:在实际环境中,分隔两地的机构要求通过VPN隧道建立私网之间的路由邻居关系,而Ipsec VPN本身并不具备传递路由的能力,所以GRE over IPSEC技术应运而生. 二,基本原理 我们知道,传统的IPsec VPN针对数据包的安全性要求,通常采用采用两种协议进行数据包封装:AH

基于预共享密钥认证的 IPSec VPN 配置

一.IKE第一阶段配置:建立加密隧道 这里会按照第1到第6个包的顺序来配置,而且要注意配置是双向的 crypto isakmp enable crypto isakmp policy 10   group 2authentication pre-shareencryption 3deshash sha   lifetime 86400crypto isakmp key 0 abc address 10.1.1.2 说明: 1. crypto isakmp enable:开启isakmp协议(默认

asa防火墙ipsec lan-lan vpn综合案例解析

我们来介绍Router与ASA之间配置LAN-to-LANVPN,即Router-to-ASA LAN-to-LANVPN 来加深对防火墙以及ipsec LAN-to-LANVPN的理解 实验环境拓扑如下: 说明:我们下面需要以上图的环境来演示LAN-to-LANVPN的效果,其中两个远程公司的网络上海和北京,如R5与R4之间需要直接使用私有地址来互访,比如R5通过直接访问地址192.168.1.4来访问R4,而R2则相当于Internet路由器,R2只负责让R1与ASA能够通信,R2不会配置任

Cisco IPSec VPN Gre over --- SVTI

SVTI实验简单配置 R2 配置: crypto isakmp policy 1 encr 3des hash md5 authentication pre-share group 2 ################################ 配置阶段1 policy 第 1 2个包交换的信息 ################################crypto isakmp key cisco123 address 200.1.1.4  // 配置预共享密钥    !!cryp

IPsec VPN原理与配置 【Route&ASA】

IPsec VPN原理与配置 简单的了解一些VPN的理论知识: 1.VPN的连接模式 VPN技术有两种传输模式:隧道模式和传输模式.这两种模式定义了两台实体设备之间传输数据时所采用的不同封装过程. (1)传输模式 传输模式一个最显著的特点就是:在传输过程中,包头并没有被封装进去,意思是从源端到目的端始终使用原有的IP地址进行通信.而传输的实际数据被封装在VPN报文中. (2)隧道模式 与传输模式的区别显而易见,VPN设备将整个三层数据报文封装在VPN数据内,再为封装过后的数据报文添加新的IP包头