implemented IKEv2 force_encap connection parameter
enforces UDP encapsulation by faking NAT detection payloads to hurdle restrictive firewalls
This commit is contained in:
@@ -822,6 +822,8 @@ static status_t update_hosts(private_child_sa_t *this,
|
||||
policy->other_ts, policy->my_ts, POLICY_FWD);
|
||||
|
||||
/* check wether we have to update a "dynamic" traffic selector */
|
||||
DBG1(DBG_IKE, "--- my: %H, %H, %R", me, this->me.addr, policy->my_ts);
|
||||
DBG1(DBG_IKE, "--- ot: %H, %H, %R", other, this->other.addr, policy->other_ts);
|
||||
if (!me->ip_equals(me, this->me.addr) &&
|
||||
policy->my_ts->is_host(policy->my_ts, this->me.addr))
|
||||
{
|
||||
@@ -832,6 +834,8 @@ static status_t update_hosts(private_child_sa_t *this,
|
||||
{
|
||||
policy->other_ts->set_address(policy->other_ts, other);
|
||||
}
|
||||
DBG1(DBG_IKE, "--- my: %H, %H, %R", me, this->me.addr, policy->my_ts);
|
||||
DBG1(DBG_IKE, "--- ot: %H, %H, %R", other, this->other.addr, policy->other_ts);
|
||||
|
||||
/* we reinstall the virtual IP to handle interface romaing
|
||||
* correctly */
|
||||
|
||||
@@ -495,6 +495,10 @@ static void set_condition(private_ike_sa_t *this, ike_condition_t condition,
|
||||
DBG1(DBG_IKE, "remote host is behind NAT");
|
||||
this->conditions |= COND_NAT_ANY;
|
||||
break;
|
||||
case COND_NAT_FAKE:
|
||||
DBG1(DBG_IKE, "faked NAT situation to enforce UDP encapsulation");
|
||||
this->conditions |= COND_NAT_ANY;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -508,10 +512,12 @@ static void set_condition(private_ike_sa_t *this, ike_condition_t condition,
|
||||
DBG1(DBG_IKE, "new route to %H found", this->other_host);
|
||||
break;
|
||||
case COND_NAT_HERE:
|
||||
case COND_NAT_FAKE:
|
||||
case COND_NAT_THERE:
|
||||
set_condition(this, COND_NAT_ANY,
|
||||
has_condition(this, COND_NAT_HERE) ||
|
||||
has_condition(this, COND_NAT_THERE));
|
||||
has_condition(this, COND_NAT_THERE) ||
|
||||
has_condition(this, COND_NAT_FAKE));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -94,7 +94,7 @@ enum ike_extension_t {
|
||||
enum ike_condition_t {
|
||||
|
||||
/**
|
||||
* Connection is natted somewhere
|
||||
* Connection is natted (or faked) somewhere
|
||||
*/
|
||||
COND_NAT_ANY = (1<<0),
|
||||
|
||||
@@ -107,11 +107,16 @@ enum ike_condition_t {
|
||||
* other is behind NAT
|
||||
*/
|
||||
COND_NAT_THERE = (1<<2),
|
||||
|
||||
/**
|
||||
* Faking NAT to enforce UDP encapsulation
|
||||
*/
|
||||
COND_NAT_FAKE = (1<<3),
|
||||
|
||||
/**
|
||||
* peer is currently not reachable (due missing route, ...)
|
||||
*/
|
||||
COND_STALE = (1<<3),
|
||||
COND_STALE = (1<<4),
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -113,6 +113,25 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this,
|
||||
return natd_hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* build a faked NATD payload to enforce UDP encap
|
||||
*/
|
||||
static chunk_t generate_natd_hash_faked(private_ike_natd_t *this)
|
||||
{
|
||||
randomizer_t *randomizer;
|
||||
chunk_t chunk;
|
||||
|
||||
randomizer = randomizer_create();
|
||||
if (randomizer->allocate_pseudo_random_bytes(randomizer, HASH_SIZE_SHA1,
|
||||
&chunk) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "unable to get random bytes for NATD fake");
|
||||
chunk = chunk_empty;
|
||||
}
|
||||
randomizer->destroy(randomizer);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a NAT detection notify payload.
|
||||
*/
|
||||
@@ -121,12 +140,21 @@ static notify_payload_t *build_natd_payload(private_ike_natd_t *this,
|
||||
{
|
||||
chunk_t hash;
|
||||
notify_payload_t *notify;
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
peer_cfg_t *config;
|
||||
|
||||
ike_sa_id = this->ike_sa->get_id(this->ike_sa);
|
||||
config = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||
notify = notify_payload_create();
|
||||
notify->set_notify_type(notify, type);
|
||||
hash = generate_natd_hash(this, ike_sa_id, host);
|
||||
if (config->force_encap(config) && type == NAT_DETECTION_SOURCE_IP)
|
||||
{
|
||||
hash = generate_natd_hash_faked(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
hash = generate_natd_hash(this, ike_sa_id, host);
|
||||
}
|
||||
notify->set_notification_data(notify, hash);
|
||||
chunk_free(&hash);
|
||||
|
||||
@@ -144,6 +172,7 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
|
||||
chunk_t hash, src_hash, dst_hash;
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
host_t *me, *other;
|
||||
peer_cfg_t *config;
|
||||
|
||||
/* Precompute NAT-D hashes for incoming NAT notify comparison */
|
||||
ike_sa_id = message->get_ike_sa_id(message);
|
||||
@@ -209,7 +238,12 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
|
||||
this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE,
|
||||
!this->dst_matched);
|
||||
this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE,
|
||||
!this->src_matched);
|
||||
!this->src_matched);
|
||||
config = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||
if (config->force_encap(config))
|
||||
{
|
||||
this->ike_sa->set_condition(this->ike_sa, COND_NAT_FAKE, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user