implemented IKEv2 force_encap connection parameter

enforces UDP encapsulation by faking NAT detection payloads
  to hurdle restrictive firewalls
This commit is contained in:
Martin Willi
2007-10-01 12:19:39 +00:00
parent 92232dab33
commit 9dae1bed00
16 changed files with 101 additions and 12 deletions
@@ -192,6 +192,7 @@ static peer_cfg_t *process_peer_cfg_row(private_sqlite_backend_t *this,
sqlite3_column_int(stmt, 10), /* jitter */
sqlite3_column_int(stmt, 13), /* reauth */
sqlite3_column_int(stmt, 14), /* mobike */
FALSE, /* force_encap */
sqlite3_column_int(stmt, 11), /* dpd_delay */
sqlite3_column_int(stmt, 12), /* dpd_action */
local_vip, remote_vip);
+16 -1
View File
@@ -140,6 +140,11 @@ struct private_peer_cfg_t {
*/
bool use_mobike;
/**
* enforce UDP encapsulation
*/
bool force_encap;
/**
* Time before an SA gets invalid
*/
@@ -364,6 +369,14 @@ static bool use_mobike(private_peer_cfg_t *this)
{
return this->use_mobike;
}
/**
* Implementation of peer_cfg_t.force_encap.
*/
static bool force_encap_meth(private_peer_cfg_t *this)
{
return this->force_encap;
}
/**
* Implements peer_cfg_t.get_dpd_delay
@@ -452,7 +465,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
auth_method_t auth_method, eap_type_t eap_type,
u_int32_t keyingtries, u_int32_t lifetime,
u_int32_t rekeytime, u_int32_t jitter,
bool reauth, bool mobike,
bool reauth, bool mobike, bool force_encap,
u_int32_t dpd_delay, dpd_action_t dpd_action,
host_t *my_virtual_ip, host_t *other_virtual_ip)
{
@@ -477,6 +490,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->public.get_lifetime = (u_int32_t (*) (peer_cfg_t *, bool rekey))get_lifetime;
this->public.use_reauth = (bool (*) (peer_cfg_t *))use_reauth;
this->public.use_mobike = (bool (*) (peer_cfg_t *))use_mobike;
this->public.force_encap = (bool (*) (peer_cfg_t *))force_encap_meth;
this->public.get_dpd_delay = (u_int32_t (*) (peer_cfg_t *))get_dpd_delay;
this->public.get_dpd_action = (dpd_action_t (*) (peer_cfg_t *))get_dpd_action;
this->public.get_my_virtual_ip = (host_t* (*) (peer_cfg_t *))get_my_virtual_ip;
@@ -504,6 +518,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->jitter = jitter;
this->use_reauth = reauth;
this->use_mobike = mobike;
this->force_encap = force_encap;
this->dpd_delay = dpd_delay;
this->dpd_action = dpd_action;
this->my_virtual_ip = my_virtual_ip;
+12 -3
View File
@@ -273,6 +273,14 @@ struct peer_cfg_t {
*/
bool (*use_mobike) (peer_cfg_t *this);
/**
* @brief Enforce UDP encapsulation by faking NATD notifies?
*
* @param this calling object
* @return TRUE to enfoce UDP encapsulation
*/
bool (*force_encap) (peer_cfg_t *this);
/**
* @brief Get the DPD check interval.
*
@@ -364,8 +372,9 @@ struct peer_cfg_t {
* @param lifetime lifetime before deleting an SA
* @param rekeytime lifetime before rekeying an SA
* @param jitter range of random to substract from rekeytime
* @param use_reauth sould be done reauthentication instead of rekeying?
* @param use_mobike use MOBIKE (RFC4555) if peer supports it
* @param reauth sould be done reauthentication instead of rekeying?
* @param mobike use MOBIKE (RFC4555) if peer supports it
* @param force_encap enforce UDP encapsulation by faking NATD notify
* @param dpd_delay after how many seconds of inactivity to check DPD
* @param dpd_action what to do with CHILD_SAs when detected a dead peer
* @param my_virtual_ip virtual IP for local host, or NULL
@@ -381,7 +390,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg,
auth_method_t auth_method, eap_type_t eap_type,
u_int32_t keyingtries, u_int32_t lifetime,
u_int32_t rekeytime, u_int32_t jitter,
bool reauth, bool mobike,
bool reauth, bool mobike, bool force_encap,
u_int32_t dpd_delay, dpd_action_t dpd_action,
host_t *my_virtual_ip, host_t *other_virtual_ip);
@@ -571,8 +571,9 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
msg->add_conn.rekey.tries, msg->add_conn.rekey.ike_lifetime,
msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
msg->add_conn.rekey.reauth, msg->add_conn.mobike,
msg->add_conn.dpd.delay, msg->add_conn.dpd.action, my_vip, other_vip);
msg->add_conn.rekey.reauth, msg->add_conn.mobike,
msg->add_conn.force_encap, msg->add_conn.dpd.delay,
msg->add_conn.dpd.action, my_vip, other_vip);
}
child_cfg = child_cfg_create(
+4
View File
@@ -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 */
+7 -1
View File
@@ -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;
+7 -2
View File
@@ -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),
};
/**
+37 -3
View File
@@ -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);
}
}
}
+1
View File
@@ -876,6 +876,7 @@ extern const char *prettypolicy(lset_t policy);
#define POLICY_DONT_REAUTH LELEM(21) /* don't reauthenticate on rekeying, IKEv2 only */
#define POLICY_BEET LELEM(22) /* bound end2end tunnel, IKEv2 */
#define POLICY_MOBIKE LELEM(23) /* enable MOBIKE for IKEv2 */
#define POLICY_FORCE_ENCAP LELEM(24) /* force UDP encapsulation (IKEv2) */
/* Any IPsec policy? If not, a connection description
* is only for ISAKMP SA, not IPSEC SA. (A pun, I admit.)
+1
View File
@@ -194,6 +194,7 @@ static const token_info_t token_info[] =
{ ARG_MISC, 0, NULL /* KW_AUTHBY */ },
{ ARG_MISC, 0, NULL /* KW_EAP */ },
{ ARG_MISC, 0, NULL /* KW_MOBIKE */ },
{ ARG_MISC, 0, NULL /* KW_FORCE_ENCAP */ },
{ ARG_TIME, offsetof(starter_conn_t, sa_ike_life_seconds), NULL },
{ ARG_TIME, offsetof(starter_conn_t, sa_ipsec_life_seconds), NULL },
{ ARG_TIME, offsetof(starter_conn_t, sa_rekey_margin), NULL },
+3
View File
@@ -554,6 +554,9 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
case KW_MOBIKE:
KW_POLICY_FLAG("yes", "no", POLICY_MOBIKE)
break;
case KW_FORCE_ENCAP:
KW_POLICY_FLAG("yes", "no", POLICY_FORCE_ENCAP)
break;
case KW_MODECONFIG:
KW_POLICY_FLAG("push", "pull", POLICY_MODECFG_PUSH)
break;
+5
View File
@@ -365,6 +365,11 @@ for the connection, e.g.
(encryption-integrity-[dh-group]). If dh-group is specified, CHILD_SA setup
and rekeying include a separate diffe hellman exchange (IKEv2 only).
.TP
.B force_encap
Force UDP encapsulation for ESP packets even if no NAT situation is detected.
This may help to hurdle restrictive firewalls. To enforce the peer to
encapsulate packets, NAT detection payloads are faked (IKEv2 only).
.TP
.B ike
IKE/ISAKMP SA encryption/authentication algorithm to be used, e.g.
.B aes128-sha1-modp2048
+1
View File
@@ -71,6 +71,7 @@ typedef enum {
KW_AUTHBY,
KW_EAP,
KW_MOBIKE,
KW_FORCE_ENCAP,
KW_IKELIFETIME,
KW_KEYLIFE,
KW_REKEYMARGIN,
+1
View File
@@ -50,6 +50,7 @@ virtual_private, KW_VIRTUAL_PRIVATE
eap, KW_EAP
eapdir, KW_EAPDIR
mobike, KW_MOBIKE
force_encap, KW_FORCE_ENCAP
pkcs11module, KW_PKCS11MODULE
pkcs11initargs, KW_PKCS11INITARGS
pkcs11keepstate, KW_PKCS11KEEPSTATE
+1
View File
@@ -110,6 +110,7 @@ static int add_connection(char *name,
msg.add_conn.eap_type = 0;
msg.add_conn.mode = 1;
msg.add_conn.mobike = 1;
msg.add_conn.force_encap = 0;
msg.add_conn.rekey.reauth = 0;
msg.add_conn.rekey.ipsec_lifetime = 0;
+1
View File
@@ -183,6 +183,7 @@ struct stroke_msg_t {
int eap_type;
int mode;
int mobike;
int force_encap;
struct {
char *ike;
char *esp;