环境网络
都开启了DPDcode
server端DPD探测到client不在线,删除本身的ISAKMP SA
和IPsec SA
,发送删除ISAKMP SA
和IPsec SA
两个通知报文给client端,此时若是client端只收到删除ISAKMP SA
的报文,client端把ISAKMP SA
删除了,但IPsec SA
还存在,这就出如今状态不一致问题,server端状态为断开,client端状态为链接,实际上隧道已不能互通。同时DPD没法工做(由于ISAKMP SA
不存在)server
理论上这种状况很难出现,由于两端DPD都开启,当server探测到client不在线时,client也应该探测到server不在线了。在真实网络中,特别是中国的ISP环境下,client收到server DPD报文后已作出回应,但server就是收不到,这样client是不可能探测到server不在线的ci
这种状况我以为也跟DPD探测机制有关,由于DPD定义只要本端收到对端发送的R_U_THERE报文或R_U_ACK报文都认为对端是在线的io
修改dpd.c加入BEGIN MODIFY
到END MODIFY
之间的代码,当DPD发现ISAKMP SA
不存时进行重协商,从而保证隧道连续可用event
void p2_dpd_outI1(struct state *p2st) { struct state *st; time_t delay = p2st->st_connection->dpd_delay; time_t timeout = p2st->st_connection->dpd_timeout; /* find the related Phase 1 state */ st = find_phase1_state(p2st->st_connection, ISAKMP_SA_ESTABLISHED_STATES); if (st == NULL) { /** BEGIN MODIFY **/ /*loglog(RC_LOG_SERIOUS, "DPD: could not find newest phase 1 state");*/ #define DELETE_SA_DELAY EVENT_RETRANSMIT_DELAY_0 if (p2st->st_event != NULL && p2st->st_event->ev_type == EVENT_SA_REPLACE && p2st->st_event->ev_time <= DELETE_SA_DELAY + now()) { loglog(RC_LOG_SERIOUS, "DPD: could not find newest phase 1 state: " "already replacing IPSEC State #%lu in %d seconds" , p2st->st_serialno, (int)(p2st->st_event->ev_time - now())); } else { loglog(RC_LOG_SERIOUS, "DPD: could not find newest phase 1 state: " "replace IPSEC State #%lu in %d seconds" , p2st->st_serialno, DELETE_SA_DELAY); p2st->st_margin = DELETE_SA_DELAY; delete_event(p2st); event_schedule(EVENT_SA_REPLACE, DELETE_SA_DELAY, p2st); } /** END MODIFY **/ return; } dpd_outI(st, p2st, TRUE, delay, timeout); }