環境網絡
都開啓了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); }