ike: Only consider number of half-open SAs as responder when deciding whether COOKIEs are sent
This commit is contained in:
parent
5de8703ee0
commit
735f929ca7
|
@ -381,7 +381,7 @@ METHOD(job_t, initiate_execute, job_requeue_t,
|
|||
u_int half_open, limit_half_open, limit_job_load;
|
||||
|
||||
half_open = charon->ike_sa_manager->get_half_open_count(
|
||||
charon->ike_sa_manager, NULL);
|
||||
charon->ike_sa_manager, NULL, FALSE);
|
||||
limit_half_open = lib->settings->get_int(lib->settings,
|
||||
"%s.init_limit_half_open", 0, lib->ns);
|
||||
limit_job_load = lib->settings->get_int(lib->settings,
|
||||
|
|
|
@ -322,16 +322,18 @@ static bool cookie_required(private_receiver_t *this,
|
|||
*/
|
||||
static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
|
||||
{
|
||||
u_int half_open;
|
||||
u_int half_open, half_open_r;
|
||||
u_int32_t now;
|
||||
|
||||
now = time_monotonic(NULL);
|
||||
half_open = charon->ike_sa_manager->get_half_open_count(
|
||||
charon->ike_sa_manager, NULL);
|
||||
charon->ike_sa_manager, NULL, FALSE);
|
||||
half_open_r = charon->ike_sa_manager->get_half_open_count(
|
||||
charon->ike_sa_manager, NULL, TRUE);
|
||||
|
||||
/* check for cookies in IKEv2 */
|
||||
if (message->get_major_version(message) == IKEV2_MAJOR_VERSION &&
|
||||
cookie_required(this, half_open, now) && !check_cookie(this, message))
|
||||
cookie_required(this, half_open_r, now) && !check_cookie(this, message))
|
||||
{
|
||||
chunk_t cookie;
|
||||
|
||||
|
@ -372,7 +374,7 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
|
|||
/* check if peer has too many IKE_SAs half open */
|
||||
if (this->block_threshold &&
|
||||
charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
|
||||
message->get_source(message)) >= this->block_threshold)
|
||||
message->get_source(message), TRUE) >= this->block_threshold)
|
||||
{
|
||||
DBG1(DBG_NET, "ignoring IKE_SA setup from %H, "
|
||||
"peer too aggressive", message->get_source(message));
|
||||
|
@ -381,7 +383,7 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
|
|||
|
||||
/* check if global half open IKE_SA limit reached */
|
||||
if (this->init_limit_half_open &&
|
||||
half_open >= this->init_limit_half_open)
|
||||
half_open >= this->init_limit_half_open)
|
||||
{
|
||||
DBG1(DBG_NET, "ignoring IKE_SA setup from %H, half open IKE_SA "
|
||||
"count of %d exceeds limit of %d", message->get_source(message),
|
||||
|
|
|
@ -647,7 +647,7 @@ METHOD(stroke_list_t, status, void,
|
|||
enumerator->destroy(enumerator);
|
||||
|
||||
half_open = charon->ike_sa_manager->get_half_open_count(
|
||||
charon->ike_sa_manager, NULL);
|
||||
charon->ike_sa_manager, NULL, FALSE);
|
||||
fprintf(out, "Security Associations (%u up, %u connecting):\n",
|
||||
charon->ike_sa_manager->get_count(charon->ike_sa_manager) - half_open,
|
||||
half_open);
|
||||
|
|
|
@ -929,7 +929,7 @@ CALLBACK(stats, vici_message_t*,
|
|||
charon->ike_sa_manager->get_count(charon->ike_sa_manager));
|
||||
b->add_kv(b, "half-open", "%u",
|
||||
charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
|
||||
NULL));
|
||||
NULL, FALSE));
|
||||
b->end_section(b);
|
||||
|
||||
b->begin_list(b, "plugins");
|
||||
|
|
|
@ -206,6 +206,9 @@ struct half_open_t {
|
|||
|
||||
/** the number of half-open IKE_SAs with that host */
|
||||
u_int count;
|
||||
|
||||
/** the number of half-open IKE_SAs we responded to with that host */
|
||||
u_int count_responder;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -360,6 +363,11 @@ struct private_ike_sa_manager_t {
|
|||
*/
|
||||
refcount_t half_open_count;
|
||||
|
||||
/**
|
||||
* Total number of half-open IKE_SAs as responder.
|
||||
*/
|
||||
refcount_t half_open_count_responder;
|
||||
|
||||
/**
|
||||
* Hash table with connected_peers_t objects.
|
||||
*/
|
||||
|
@ -737,9 +745,11 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
|
|||
table_item_t *item;
|
||||
u_int row, segment;
|
||||
rwlock_t *lock;
|
||||
ike_sa_id_t *ike_id;
|
||||
half_open_t *half_open;
|
||||
chunk_t addr;
|
||||
|
||||
ike_id = entry->ike_sa_id;
|
||||
addr = entry->other->get_address(entry->other);
|
||||
row = chunk_hash(addr) & this->table_mask;
|
||||
segment = row & this->segment_mask;
|
||||
|
@ -752,7 +762,6 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
|
|||
|
||||
if (chunk_equals(addr, half_open->other))
|
||||
{
|
||||
half_open->count++;
|
||||
break;
|
||||
}
|
||||
item = item->next;
|
||||
|
@ -762,7 +771,6 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
|
|||
{
|
||||
INIT(half_open,
|
||||
.other = chunk_clone(addr),
|
||||
.count = 1,
|
||||
);
|
||||
INIT(item,
|
||||
.value = half_open,
|
||||
|
@ -770,8 +778,14 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
|
|||
);
|
||||
this->half_open_table[row] = item;
|
||||
}
|
||||
this->half_open_segments[segment].count++;
|
||||
half_open->count++;
|
||||
ref_get(&this->half_open_count);
|
||||
if (!ike_id->is_initiator(ike_id))
|
||||
{
|
||||
half_open->count_responder++;
|
||||
ref_get(&this->half_open_count_responder);
|
||||
}
|
||||
this->half_open_segments[segment].count++;
|
||||
lock->unlock(lock);
|
||||
}
|
||||
|
||||
|
@ -783,8 +797,10 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
|
|||
table_item_t *item, *prev = NULL;
|
||||
u_int row, segment;
|
||||
rwlock_t *lock;
|
||||
ike_sa_id_t *ike_id;
|
||||
chunk_t addr;
|
||||
|
||||
ike_id = entry->ike_sa_id;
|
||||
addr = entry->other->get_address(entry->other);
|
||||
row = chunk_hash(addr) & this->table_mask;
|
||||
segment = row & this->segment_mask;
|
||||
|
@ -797,6 +813,12 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
|
|||
|
||||
if (chunk_equals(addr, half_open->other))
|
||||
{
|
||||
if (!ike_id->is_initiator(ike_id))
|
||||
{
|
||||
half_open->count_responder--;
|
||||
ignore_result(ref_put(&this->half_open_count_responder));
|
||||
}
|
||||
ignore_result(ref_put(&this->half_open_count));
|
||||
if (--half_open->count == 0)
|
||||
{
|
||||
if (prev)
|
||||
|
@ -811,7 +833,6 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
|
|||
free(item);
|
||||
}
|
||||
this->half_open_segments[segment].count--;
|
||||
ignore_result(ref_put(&this->half_open_count));
|
||||
break;
|
||||
}
|
||||
prev = item;
|
||||
|
@ -1945,7 +1966,7 @@ METHOD(ike_sa_manager_t, get_count, u_int,
|
|||
}
|
||||
|
||||
METHOD(ike_sa_manager_t, get_half_open_count, u_int,
|
||||
private_ike_sa_manager_t *this, host_t *ip)
|
||||
private_ike_sa_manager_t *this, host_t *ip, bool responder_only)
|
||||
{
|
||||
table_item_t *item;
|
||||
u_int row, segment;
|
||||
|
@ -1967,7 +1988,8 @@ METHOD(ike_sa_manager_t, get_half_open_count, u_int,
|
|||
|
||||
if (chunk_equals(addr, half_open->other))
|
||||
{
|
||||
count = half_open->count;
|
||||
count = responder_only ? half_open->count_responder
|
||||
: half_open->count;
|
||||
break;
|
||||
}
|
||||
item = item->next;
|
||||
|
@ -1976,7 +1998,8 @@ METHOD(ike_sa_manager_t, get_half_open_count, u_int,
|
|||
}
|
||||
else
|
||||
{
|
||||
count = (u_int)ref_cur(&this->half_open_count);
|
||||
count = responder_only ? (u_int)ref_cur(&this->half_open_count_responder)
|
||||
: (u_int)ref_cur(&this->half_open_count);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -216,14 +216,15 @@ struct ike_sa_manager_t {
|
|||
* To prevent the server from resource exhaustion, cookies and other
|
||||
* mechanisms are used. The number of half open IKE_SAs is a good
|
||||
* indicator to see if a peer is flooding the server.
|
||||
* If a host is supplied, only the number of half open IKE_SAs initiated
|
||||
* from this IP are counted.
|
||||
* Only SAs for which we are the responder are counted.
|
||||
* If a host is supplied, only the number of half open IKE_SAs with this IP
|
||||
* are counted.
|
||||
*
|
||||
* @param ip NULL for all, IP for half open IKE_SAs with IP
|
||||
* @param responder_only TRUE to return only the number of responding SAs
|
||||
* @return number of half open IKE_SAs
|
||||
*/
|
||||
u_int (*get_half_open_count) (ike_sa_manager_t *this, host_t *ip);
|
||||
u_int (*get_half_open_count)(ike_sa_manager_t *this, host_t *ip,
|
||||
bool responder_only);
|
||||
|
||||
/**
|
||||
* Delete all existing IKE_SAs and destroy them immediately.
|
||||
|
|
Loading…
Reference in New Issue