IKEv2协议协商流程: (IKE-SA-INIT 交换)第二包
文章目录
1. IKEv2 协商总体框架
IKEv1协议建立一对IPSec SA,使用主动模式需要9个报文,使用野蛮模式需要使用6个报文方能协商成功。IKEv2对IKEv1协议进行了优化,IKEv2只需要进行两次交互,使用 4 条消息就可以完成一个 IKEv2 SA 和一对 IPsec SA 的协商建立。IKEv2 定义了三种交互:
-
初始交换、
-
创建子 SA 交换
-
通知交换。
下图简单介绍一下 IKEv2 协商过程中的初始交换过程,之后我们将对
ikev2_parent_inI1outR1()
接口相关的处理流程做一个简单说明。
初始化交换通过两次交换共4个报文便可以完成一对IKE SA和IPSec SA的协商。上图主要用来描述协商报文的内容和对应的处理函数入口。下图则是用来说明各接口对应的协商状态。协商过程中是根据该状态来确定当前的协商阶段。
RFC文档中的报文格式:
Initiator Responder
-------------------------------------------------------------------
HDR, SAi1, KEi, Ni -->
<-- HDR, SAr1, KEr, Nr, [CERTREQ]
HDR, SK {
IDi, [CERT,] [CERTREQ,]
[IDr,] AUTH, SAi2,
TSi, TSr} -->
<-- HDR, SK {
IDr, [CERT,] AUTH,
SAr2, TSi, TSr}
其中:
报文字段 | 说明 |
---|---|
HDR | 报文头部 |
SAi1、SAr1 | IKE SA建议 |
SAi2、SAr2 | IPSEC SA建议载荷 |
KEi、KEr | DH算法公共值 |
Ni、Nr | Nonce随机数 |
CERT、CERTREQ | 证书载荷、证书请求载荷 |
IDi、IDr | ID载荷 |
TSi、TSr | 流量选择器,使用此载荷完成保护子网的协商 |
AUTH | 认证数据载荷 |
这里面需要说明的是:报文中的SK并不是一个载荷。而是:SK {…}表示里面的内容被加密和认证保护。
下面对响应端对发起端第一包的处理流程做一个详细说明。入口函数为:ikev2_parent_inI1outR1()
。
2. 第二包流程图
3. openswan源码学习
3.1 ikev2parent_inI1outR1()
此函数是IKEv2协议 响应端开始协商的入口函数。主要功能包括:
- 根据收到报文四元组(IP和端口)查找连接:c
- 新建一个协商状态结构:state
- 根据发起端的地址等信息生成Cookie值
- 将连接上的参数信息、配置信息初始化state结构上参数
- 隧道本端IP和端口
- 隧道对端IP和端口
- 隧道的出接口
- 配置策略
- … …
- 抗重放检测(Cookie challenge)
- 根据发起端IP、SPI、Nonce计算用于抗重放的cookie
- 如果报文中包含KE和Cookie类型的通知载荷
- 比较两端的cookie是否一致
- 如果报文中不包含Cookie类型的通知载荷
- 发送携带cookie的通知报文,使发起端重新开始协商
- 解析报文中的KE载荷,获取到DH组信息
- DH组猜测成功,则计算DH算法的公共值,用于构建响应报文的KE载荷
static stf_status
ikev2_parent_inI1outR1_tail(struct pluto_crypto_req_cont *pcrc
, struct pluto_crypto_req *r);
stf_status ikev2parent_inI1outR1(struct msg_digest *md)
{
struct state *st = md->st;
lset_t policy = POLICY_IKEV2_ALLOW;
lset_t policy_hint = LEMPTY;
/*
* 根据隧道两端协商地址和端口来查找连接
*/
struct connection *c = find_host_connection(ANY_MATCH, &md->iface->ip_addr
, md->iface->port
, KH_IPADDR
, &md->sender
, md->sender_port
, POLICY_IKEV2_ALLOW, LEMPTY, &policy_hint);
if(c==NULL) {
/*连接查找失败则提示相应的错误信息*/
if(policy_hint & POLICY_IKEV2_ALLOW) {
/* connection not found, because IKEv2 was not allowed */
/* send back AUTHENTICATION_FAILED per WG mailing list discussion */
openswan_log("connection refused, IKEv2 not authorized");
return STF_FAIL + v2N_AUTHENTICATION_FAILED;
}
/*
* be careful about responding, or logging, since it may be that we
* are under DOS
*/
DBG_log("no connection with matching policy found\n");
return STF_FAIL + v2N_AUTHENTICATION_FAILED;
}
loglog(RC_COMMENT, "tentatively considering connection: %s\n", c ? c->name : "<none>");
if(!st) {
/*如果没有对应的状态,则新建一个state*/
st = new_state();
/* set up new state */
memcpy(st->st_icookie, md->hdr.isa_icookie, COOKIE_SIZE);
/* initialize_new_state expects valid icookie/rcookie values, so create it now */
/*相应方根据发起方的地址信息、当前时间生成一个cookie*/
get_cookie(FALSE, st->st_rcookie, COOKIE_SIZE, &md->sender);
initialize_new_state(st, c, policy, 0, NULL_FD, pcim_stranger_crypto);
st->st_ikev2 = TRUE;
st->st_localaddr = md->iface->ip_addr;
st->st_localport = md->iface->port;
st->st_remoteaddr = md->sender;
st->st_remoteport = md->sender_port;
st->st_ike_maj = md->maj;
st->st_ike_min = md->min;
change_state(st, STATE_PARENT_R1);
md->st = st;
md->from_state = STATE_IKEv2_BASE;
md->transition_state = st;
}
/* check,as a responder, are we under dos attack or not
* if yes go to 6 message exchange mode. it is a config option for now.
* TBD set force_busy dynamically
* Paul: Can we check for STF_TOOMUCHCRYPTO ?
*/
if(force_busy == TRUE)/*开启抗重放!!!!!!!!*/
{
u_char dcookie[SHA1_DIGEST_SIZE];
chunk_t dc;
/*计算用于cookie challenge的cookie值*/
ikev2_get_dcookie( dcookie, st->st_ni, &md->sender, st->st_icookie)