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);
dc.ptr = dcookie;
dc.len = SHA1_DIGEST_SIZE;/*20bytes*/ /* check if I1 packet contian KE and a v2N payload with type COOKIE */
/*报文格式??? : HDR + NOTIF + KE*/
if ( md->chain[ISAKMP_NEXT_v2KE] && md->chain[ISAKMP_NEXT_v2N] &&
(md->chain[ISAKMP_NEXT_v2N]->payload.v2n.isan_type == v2N_COOKIE))
{/*对方的协商报文中包含了cookie*/
/*
* ISAKMP_NEXT_v2N : IKEv2 通知载荷
* ISAKMP_NEXT_v2Ni : 发起端Nonce载荷
* ISAKMP_NEXT_v2Nr : 接收端Nonce载荷
*/
u_int8_t spisize;
const pb_stream *dc_pbs;
chunk_t blob;
DBG(DBG_CONTROLMORE
, DBG_log("received a DOS cookie in I1 verify it")); /* we received dcookie we send earlier verify it */
spisize = md->chain[ISAKMP_NEXT_v2N]->payload.v2n.isan_spisize;
dc_pbs = &md->chain[ISAKMP_NEXT_v2N]->pbs;
blob.ptr = dc_pbs->cur + spisize;
blob.len = pbs_left(dc_pbs) - spisize;
DBG(DBG_CONTROLMORE
,DBG_dump_chunk("dcookie received in I1 Packet", blob);
DBG_dump("dcookie computed", dcookie, SHA1_DIGEST_SIZE)); /*检查收到的cookie和本端发送的cookie是否一致!!!*/
if(memcmp(blob.ptr, dcookie, SHA1_DIGEST_SIZE)!=0) {
openswan_log("mismatch in DOS v2N_COOKIE,send a new one");
SEND_V2_NOTIFICATION_DATA(md, st, v2N_COOKIE, &dc);
return STF_FAIL + v2N_INVALID_IKE_SPI;
}
DBG(DBG_CONTROLMORE
,DBG_log("dcookie received match with computed one"));
}
else/*收到的报文中并不包含COOKIE载荷,因此需要发起cookie challenge*/
{/*COOKIE challenge通知载荷发送*/
/* we are under DOS attack I1 contains no DOS COOKIE */
DBG(DBG_CONTROLMORE
,DBG_log("busy mode on. receieved I1 without a valid dcookie");
DBG_log("send a dcookie and forget this state"));
SEND_V2_NOTIFICATION_DATA(md, st, v2N_COOKIE, &dc);
return STF_FAIL;
}
}
else {
DBG(DBG_CONTROLMORE ,DBG_log("will not send/process a dcookie")); } /*
* If we did not get a KE payload, we cannot continue. There should be
* a Notify telling us why. We inform the user, but continue to try this
* connection via regular retransmit intervals.
*/
if(md->chain[ISAKMP_NEXT_v2N] && (md->chain[ISAKMP_NEXT_v2KE] == NULL))
{
const char *from_state_name = enum_name(&state_names, st->st_state);
const u_int16_t isan_type = md->chain[ISAKMP_NEXT_v2N]->payload.v2n.isan_type;
openswan_log("%s: received %s"
, from_state_name
, enum_name(&ikev2_notify_names, isan_type));
return STF_FAIL + isan_type;
} else if( md->chain[ISAKMP_NEXT_v2N]) {
/* XXX/SML: KE payload came with a notification-- is there a problem? */
DBG(DBG_CONTROL,DBG_log("received a notify.."));
} /*
* We have to agree to the DH group before we actually know who
* we are talking to. If we support the group, we use it.
*
* It is really too hard here to go through all the possible policies
* that might permit this group. If we think we are being DOS'ed
* then we should demand a cookie.
*/
{
struct ikev2_ke *ke;
if (md->chain[ISAKMP_NEXT_v2KE] == NULL)
return STF_FAIL; ke = &md->chain[ISAKMP_NEXT_v2KE]->payload.v2ke;
/*KE载荷中包含DH GROUP信息*/
st->st_oakley.group=lookup_group(ke->isak_group);/*查找DH GROUP,并存储在st->st_oakley上*/
if(st->st_oakley.group==NULL) {
char fromname[ADDRTOT_BUF]; addrtot(&md->sender, 0, fromname, ADDRTOT_BUF);
openswan_log("rejecting I1 from %s:%u, invalid DH group=%u"
,fromname, md->sender_port, ke->isak_group);
return v2N_INVALID_KE_PAYLOAD;
}
} /* now. we need to go calculate the nonce, and the KE */
{
struct ke_continuation *ke = alloc_thing(struct ke_continuation
, "ikev2_inI1outR1 KE");
stf_status e; ke->md = md;
set_suspended(st, ke->md); if (!st->st_sec_in_use) {
pcrc_init(&ke->ke_pcrc);
ke->ke_pcrc.pcrc_func = ikev2_parent_inI1outR1_continue;
e = build_ke(&ke->ke_pcrc, st, st->st_oakley.group, pcim_stranger_crypto);
if(e != STF_SUSPEND && e != STF_INLINE) {
loglog(RC_CRYPTOFAILED, "system too busy");
delete_state(st);
}
} else {
e = ikev2_parent_inI1outR1_tail((struct pluto_crypto_req_cont *)ke
, NULL);
} reset_globals(); return e;
}
}

3.2 ikev2parent_inI1outR1_tail()

此函数最主要的功能就是构建应答报文。具体的步骤包括如下几个方面:

  • 保存对端发送的协商报文,用于后续认证操作
  • 解析协商报文中的通知载荷
    • NAT-D
    • error information
    • … …
  • 构建IKEv2报文头部
  • 构建SA建议载荷
    • 将本地配置策略生成并转换为ikev2 SADB
    • 解析对端的SA载荷中所有的建议载荷
    • 使用排列组合匹配本地的SADB算法信息
  • 解析对端KE载荷
  • 解析对端Nonce载荷。
  • 构建KE载荷
  • 构建Nonce载荷
  • 构建NAT-D载荷
  • 保存当前报文供后续的认证等操作
  • 发送报文
static stf_status
ikev2_parent_inI1outR1_tail(struct pluto_crypto_req_cont *pcrc
, struct pluto_crypto_req *r)
{
struct ke_continuation *ke = (struct ke_continuation *)pcrc;
struct msg_digest *md = ke->md;
struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_v2SA];
struct state *const st = md->st;
stf_status notok;
int numvidtosend=0;
#ifdef PLUTO_SENDS_VENDORID
numvidtosend++; /* we send Openswan VID */
#endif if (sa_pd == NULL) {
return STF_FAIL;
} /* note that we don't update the state here yet */ /* record first packet for later checking of signature */
clonetochunk(st->st_firstpacket_him, md->message_pbs.start
, pbs_offset(&md->message_pbs), "saved first received packet"); /*
* verify the NAT DETECTION notify messages before answering.
* on the responder side, this allows us to detect when *we* are behind
* at NAPT (probably with a port-forward).
*
* If we are, then we set a bit saying so, which later on will make us pick the
* UDP encapsulation for packets. It is up to the initiator to switch ports
* from 500 to 4500. Could be they have already done so, we do not care here.
*/
if(md->chain[ISAKMP_NEXT_v2N]) {/*处理通知载荷,其中包括NAT-D探测*/
ikev2_process_notifies(st, md);
} /* make sure HDR is at start of a clean buffer */
zero(reply_buffer);
init_pbs(&reply_stream, reply_buffer, sizeof(reply_buffer), "reply packet"); /* HDR out */
{
struct isakmp_hdr r_hdr = md->hdr; memcpy(r_hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); r_hdr.isa_version = IKEv2_MAJOR_VERSION << ISA_MAJ_SHIFT | IKEv2_MINOR_VERSION;
r_hdr.isa_np = ISAKMP_NEXT_v2SA;
r_hdr.isa_flags = ISAKMP_FLAGS_R|IKEv2_ORIG_INITIATOR_FLAG(st);
r_hdr.isa_msgid = st->st_msgid;
if (!out_struct(&r_hdr, &isakmp_hdr_desc, &reply_stream, &md->rbody))
return STF_INTERNAL_ERROR;
} /* start of SA out */
{
struct ikev2_sa r_sa = sa_pd->payload.v2sa;/*收到的报文中的SA头部信息*/
v2_notification_t rn;
pb_stream r_sa_pbs; r_sa.isasa_np = ISAKMP_NEXT_v2KE; /* XXX */
if (!out_struct(&r_sa, &ikev2_sa_desc, &md->rbody, &r_sa_pbs))
return STF_INTERNAL_ERROR; /* SA body in and out *//*解析对方的SA建议载荷,并将选择的建议载荷填充到r_sa_pbs中*/
rn = ikev2_parse_parent_sa_body(&sa_pd->pbs, &sa_pd->payload.v2sa,
&r_sa_pbs, st, FALSE); if (rn != v2N_NOTHING_WRONG)
return STF_FAIL + rn;
}
/*解析对端的KE载荷,存储在st_gi中*/
if((notok = accept_v2_KE(md, st, &st->st_gi, "Gi"))!=STF_OK) {
return notok;
} /* Ni in *//*解析对端的Nonce载荷,存储在st_ni中*/
RETURN_STF_FAILURE(accept_v2_nonce(md, &st->st_ni, "Ni")); /* send KE *//*填充KE*/
if(!ship_v2KE(st, r, &st->st_gr, &md->rbody, ISAKMP_NEXT_v2Nr))
return STF_INTERNAL_ERROR; /* send NONCE *//*填充Nonce*/
unpack_nonce(&st->st_nr, r);
if(!justship_v2Nonce(st, &md->rbody, &st->st_nr, 0)) {
return STF_INTERNAL_ERROR;
} if(!justship_v2nat(st, &md->rbody)) {/*填充NAT-D*/
return STF_INTERNAL_ERROR;
} /* Send VendrID if needed VID */
{
pbs_set_np(&md->rbody, ISAKMP_NEXT_v2V);
if (!out_generic_raw(0, &isakmp_vendor_id_desc, &md->rbody
, pluto_vendorid, strlen(pluto_vendorid), "Vendor ID"))
return STF_INTERNAL_ERROR;
} close_message(&md->rbody);
close_output_pbs(&reply_stream); /* let TCL hack it before we mark the length. */
TCLCALLOUT("v2_avoidEmitting", st, st->st_connection, md); /* keep it for a retransmit if necessary */
freeanychunk(st->st_tpacket);
clonetochunk(st->st_tpacket, reply_stream.start, pbs_offset(&reply_stream)
, "reply packet for ikev2_parent_inI1outR1_tail") /* save packet for later signing */
freeanychunk(st->st_firstpacket_me);
clonetochunk(st->st_firstpacket_me, reply_stream.start
, pbs_offset(&reply_stream), "saved first packet"); /* while waiting for initiator to continue, arrange to die if nothing happens */
delete_event(st);
event_schedule(EVENT_SO_DISCARD, 300, st); return STF_OK; }

3.3 ikev2_parse_parent_sa_body()

该函数主要的作用是解析协商报文中的SA建议载荷,并从中选择本地支持的算法进行协商。

主要流程如下

  • 根据配置的SA建议载荷转换为SADB结构
  • 将SADB结构转换为IKEv2的SA结构
  • 解析报文中的SA载荷
  • 将报文SA中的算法进行排列组合, 并与本地SADB中的算法进行匹配
    • 加密算法
    • 完整性哈希算法
    • PRF哈希算法
    • DH算法
  • 根据算法标识获取算法详细参数,并将其存储在state上
  • 如果为响应端
    • 将选中的算法填充到报文SA载荷中
v2_notification_t
ikev2_parse_parent_sa_body(
pb_stream *sa_pbs, /* body of input SA Payload */
const struct ikev2_sa *sa_prop UNUSED, /* header of input SA Payload */
pb_stream *r_sa_pbs, /* if non-NULL, where to emit winning SA */
struct state *st, /* current state object */
bool selection UNUSED /* if this SA is a selection, only one
* tranform can appear. */
)
{
pb_stream proposal_pbs;
struct ikev2_prop proposal;
unsigned int np = ISAKMP_NEXT_P;
/* we need to parse proposal structures until there are none */
unsigned int lastpropnum=-1;
bool conjunction, gotmatch;
struct ikev2_prop winning_prop;
struct db_sa *sadb;
struct trans_attrs ta;
struct connection *c = st->st_connection; /*根据配置确定选用的SADB模板*/
int policy_index = POLICY_ISAKMP(c->policy
, c->spd.this.xauth_server
, c->spd.this.xauth_client); struct ikev2_transform_list itl0, *itl; memset(&itl0, 0, sizeof(struct ikev2_transform_list));
itl = &itl0; /* find the policy structures */
/*根据策略配置生成SADB信息*/
sadb = st->st_sadb;
if(!sadb) {
st->st_sadb = &oakley_sadb[policy_index];
sadb = oakley_alg_makedb(st->st_connection->alg_info_ike
, st->st_sadb, 0);
if(sadb != NULL) {
st->st_sadb = sadb;
}
sadb = st->st_sadb;
}
/*将SA结构由IKEv1转换为IKEv2*/
sadb = st->st_sadb = sa_v2_convert(sadb); gotmatch = FALSE;
conjunction = FALSE;
zero(&ta); while(np == ISAKMP_NEXT_P) {/*一般情况下只有一个建议载荷*/
/*
* note: we don't support ESN,
* so ignore any proposal that insists on it
*/ if(!in_struct(&proposal, &ikev2_prop_desc, sa_pbs, &proposal_pbs))
return PAYLOAD_MALFORMED; if(proposal.isap_protoid != PROTO_ISAKMP) {
loglog(RC_LOG_SERIOUS, "unexpected PARENT_SA, expected child");
return PAYLOAD_MALFORMED;
}
... ...
gotmatch = FALSE; {/*将报文中的建议载荷转换为struct ikev2_transform_list*/
stf_status ret = ikev2_process_transforms(&proposal
, &proposal_pbs, itl);
if(ret != STF_OK) return ret;
} np = proposal.isap_np;/*下一个建议载荷 或者为空*/ if(ikev2_match_transform_list_parent(sadb
, proposal.isap_propnum
, itl)) {/*匹配成功的算法组合存储在itl中*/ winning_prop = proposal;
gotmatch = TRUE;
/* gotmatch is true, so will never go inside if*/ }
} /*
* we are out of the loop. There are two situations in which we break
* out: gotmatch == FALSE, means nothing selected.
*/
if(!gotmatch) {
return NO_PROPOSAL_CHOSEN;
}
/*
* since we found something that matched, we might need to emit the
* winning value.
*
* 从对方的建议载荷中找到了合适的算法信息;
*/
/*加密算法*/
ta.encrypt = itl->encr_transforms[itl->encr_i];
ta.enckeylen = itl->encr_keylens[itl->encr_i] > 0 ?
itl->encr_keylens[itl->encr_i] : 0;
ta.encrypter = (struct encrypt_desc *)ike_alg_ikev2_find(IKE_ALG_ENCRYPT
, ta.encrypt
, ta.enckeylen);
passert(ta.encrypter != NULL);
if (ta.enckeylen <= 0)
ta.enckeylen = ta.encrypter->keydeflen; /*完整性哈希算法*/
ta.integ_hash = itl->integ_transforms[itl->integ_i];
ta.integ_hasher= (struct hash_desc *)ike_alg_ikev2_find(IKE_ALG_INTEG,ta.integ_hash, 0);
passert(ta.integ_hasher != NULL); /*PRF 哈希算法*/
ta.prf_hash = itl->prf_transforms[itl->prf_i];
ta.prf_hasher = (struct hash_desc *)ike_alg_ikev2_find(IKE_ALG_HASH, ta.prf_hash, 0);
passert(ta.prf_hasher != NULL); /*DH 算法*/
ta.groupnum = itl->dh_transforms[itl->dh_i];
ta.group = lookup_group(ta.groupnum); st->st_oakley = ta;/*将算法信息存储到state上*/ if (r_sa_pbs != NULL)/*将选中的算法填充到应答报文的SA载荷上*/
{
return ikev2_emit_winning_sa(st, r_sa_pbs
, ta
, /*parentSA*/TRUE
, winning_prop);
}
return NOTHING_WRONG;
}

4. 小结

4.1 SA载荷中加密套件算法选择

  • IKEv2加密套件的转换详细说明见下表
用途 名称 编号
IKE转换类型Ⅰ(加密) ENCR_3DES 3
ENCR_NULL 11
ENCR_AES_CBC 12
ENCR_AES_CTR 13
IKE转换类型Ⅱ(PRF) PRF_HMAC_MD5 1
PEF_HMAC_SHA1 2
PRF_AES128_CBC 4
IKE转换类型Ⅲ(完整性) AUTH_HMAC_MD5_96 1
AUTH_HMAC_SHA1_96 2
AUTH_AES_XCBC_96 5
IKE转换类型Ⅳ(DH组) 1024 MODP (Group 2) 2
2048 MODP (Group 14) 14

安全关联(SA)负载包含了一个SPI数值和一套建议(通常是一个)。这些建议是通过一些复杂的建议结构关联起来的。每一个建议结构都会被编号(参见上表)并且包含一个IPsec协议标识符,此标识符用来支持采用的协议,如IKE, ESP, AH。

每一个建议载荷包含一个或者多个变换载荷用来描述指定协议的算法。通常情况下,AH协议仅有一个变换载荷(与完整性检验算法有关),ESP协议有两个变换载荷(与完整性检验算法和加密算法相对应),DH算法有四个转换结构(DH组编号、PRF算法、完整性检验算法、加密算法)。而第二个报文中的SA加密套件中的建议载荷便属于DH转换结构。

4.2 密钥交换KE和随机负载Nonce

IKE_SA_INIT交换报文中处理SA载荷外,还包括KE载荷和Nonce载荷。

  • KE载荷包括DH组编号和密钥交换数据(DH算法公共值)
  • Nonce载荷则是随机生成的随机数,用于生成密钥材料。

DH一旦交换完成,双方便可以计算出自己的SKEYSEED,该值用来生成所有与IKE_SA相关的子密钥,包括:SK_d, SK_ai, SK_ar, SK_ei, SK_er, SK_pi, SK_pr

SKEYSEED的计算方式如下:

S

K

E

Y

S

E

E

D

=

p

r

f

(

N

i

N

r

,

g

i

r

)

SKEYSEED = prf(Ni | Nr, g^{ir} )

SKEYSEED=prf(Ni∣Nr,gir)

密钥 用途
SK_ai, SK_ar 用于认证
SK_ei, SK_er 用于加密
SK_d 用于派生CHILD_SA密钥
SK_p 用于在IKE_AUTH交换中生成AUTH载荷

版本所有,谢绝转载!!!

IKEv2协议协商流程: (IKE-SA-INIT 交换)第二包的更多相关文章

  1. IKEv2协议协商流程: (IKE-SA-INIT 交换)第一包

    文章目录 1. IKEv2 协商总体框架 2. 第一包流程图 3. openswan源码学习 3.1 ikev2parent_outI1() 3.2 ikev2parent_outI1_withsta ...

  2. IKEv2协议关键知识点总结整理

    文章目录 @[toc] 1. IKEv2基本原理 2. IKEv2协议重点注意事项 2.1 情景一:==IKEv2协商密钥逻辑== ①密钥协商流程 ②函数调用关系 ③流程简述 2.2 情景二:==使用 ...

  3. [ipsec][crypto] IKEv2的协商交互分析

    一: 无论协商了什么样的加密算法.DH都交换一块长度为32byte的内存,作为key. IKE和esp的key,分别基于这块内存生成. 二: 当esp的算法协商没有指定dh group时,rekey将 ...

  4. openswan协商流程之(二):main_inI1_outR1()

    主模式第二包:main_inI1_outR1() 文章目录 主模式第二包:main_inI1_outR1() 1. 序言 2. `main_inI1_outR1()`处理流程图 3. `main_in ...

  5. openswan协商流程之(一):main_outI1()

    主模式第一包:main_outI1() 1. 序言 main_outI1()作为主模式主动发起连接请求的核心处理函数,我们可以通过学习该函数的处理流程来探究openswan中报文封装的基本思想.如果之 ...

  6. PPTP协议握手流程分析

    一  PPTP概述 PPTP(Point to Point Tunneling Protocol),即点对点隧道协议.该协议是在PPP协议的基础上开发的一种新的增强型安全协议,支持多协议虚拟专用网,可 ...

  7. PPTP协议握手流程分析--转载

    一  PPTP概述   PPTP(Point to Point Tunneling Protocol),即点对点隧道协议.该协议是在PPP协议的基础上开发的一种新的增强型安全协议,支持多协议虚拟专用网 ...

  8. openswan协商流程之(七):main_inR3

    主模式第六包(收包):main_inR3 1. 序言 main_inR3()函数是ISAKMP协商过程中第一阶段的最后一个报文的接收处理函数,它的作用同main_inI3_outR3()部分功能相同: ...

  9. 数据包接收系列 — IP协议处理流程(二)

    本文主要内容:在接收数据包时,IP协议的处理流程. 内核版本:2.6.37 Author:zhangskd @ csdn blog 我们接着来看数据包如何发往本地的四层协议. ip_local_del ...

随机推荐

  1. Docker介绍及安装详解

    1:Docker简介 Docker 是一种运行于 Linux 和 Windows 上的软件,用于创建.管理和编排容器.Docker 是在 GitHub 上开发的 Moby 开源项目的一部分.Docke ...

  2. 为什么有些容器在docker run的时候需要接 -it ,有些不需要?

    这是我们的Dockerfile文件 FROM busybox ENV sg WANG CMD ["/bin/sh", "-c", "echo wang ...

  3. 单片机学习(八)点阵LED的使用

    目录 一.点阵LED的理论知识 1. 点阵屏的打开方式 2. LED点阵简介 3. 点阵LED的结构和操作方式 4. 74HC595模块 PPT上的简介 串行转并行的工作原理 二.编码实现 1. C5 ...

  4. SQL 练习14

    查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩 SELECT Student.SId,Student.Sname,t.不及格课程数,t.平均成绩 from Student, (SELECT ...

  5. Vmware下安装Ubuntu18.04详情

    转载地址:https://blog.csdn.net/qq_35623773/article/details/89893853

  6. Sadmin:打造私有Django公共库实现代码复用

    我们借助于Django开发了许多的内部管理系统,例如之前介绍过的Probius.Kerrigan.Proxy等等,这些系统看起来长的都一样,但实际实现的功能确是千差万别,这些不同的系统为什么会长的一样 ...

  7. 如何在WPF中定义窗体模板

    参考网址:https://www.cnblogs.com/chenxizhang/archive/2010/01/10/1643676.html可以在app.xaml中定义一个ControlTempl ...

  8. UWP App Data存储和获取

    这篇博客介绍如何在UWP开发时,如何存储App Data和获取. App Data是指用户的一些设定,偏好等.例如,App的主题,是否接收推送,离线接收消息等.需要区分下App Data和User D ...

  9. SpringBoot整合mybatis快速入门

    一.创建一个SpringBoot项目                 二.引入相关依赖 <!--web核心依赖--> <dependency> <groupId>o ...

  10. beeline: 新版连接Hive server的工具

    HiveServer2 支持一个新的命令行Shell,称为Beeline,它是基于SQLLine CLI的JDBC客户端.它是从 Hive 0.11版本引入的,是Hive新的命令行客户端工具.Hive ...