diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/charon/config/backends/sqlite_backend.c | 1 | ||||
-rw-r--r-- | src/charon/config/peer_cfg.c | 17 | ||||
-rw-r--r-- | src/charon/config/peer_cfg.h | 15 | ||||
-rwxr-xr-x | src/charon/control/interfaces/stroke_interface.c | 5 | ||||
-rw-r--r-- | src/charon/sa/child_sa.c | 4 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 8 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.h | 9 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_natd.c | 40 | ||||
-rw-r--r-- | src/pluto/constants.h | 1 | ||||
-rw-r--r-- | src/starter/args.c | 1 | ||||
-rw-r--r-- | src/starter/confread.c | 3 | ||||
-rw-r--r-- | src/starter/ipsec.conf.5 | 5 | ||||
-rw-r--r-- | src/starter/keywords.h | 1 | ||||
-rw-r--r-- | src/starter/keywords.txt | 1 | ||||
-rw-r--r-- | src/stroke/stroke.c | 1 | ||||
-rw-r--r-- | src/stroke/stroke.h | 1 |
16 files changed, 101 insertions, 12 deletions
diff --git a/src/charon/config/backends/sqlite_backend.c b/src/charon/config/backends/sqlite_backend.c index 2db90f909..be94f9b5f 100644 --- a/src/charon/config/backends/sqlite_backend.c +++ b/src/charon/config/backends/sqlite_backend.c @@ -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); diff --git a/src/charon/config/peer_cfg.c b/src/charon/config/peer_cfg.c index 6733df08c..7935b9703 100644 --- a/src/charon/config/peer_cfg.c +++ b/src/charon/config/peer_cfg.c @@ -141,6 +141,11 @@ struct private_peer_cfg_t { bool use_mobike; /** + * enforce UDP encapsulation + */ + bool force_encap; + + /** * Time before an SA gets invalid */ u_int32_t lifetime; @@ -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; diff --git a/src/charon/config/peer_cfg.h b/src/charon/config/peer_cfg.h index 1c6051f16..ecd6bcf83 100644 --- a/src/charon/config/peer_cfg.h +++ b/src/charon/config/peer_cfg.h @@ -274,6 +274,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. * * @param this calling object @@ -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); diff --git a/src/charon/control/interfaces/stroke_interface.c b/src/charon/control/interfaces/stroke_interface.c index 3ab6b5700..13d4b9662 100755 --- a/src/charon/control/interfaces/stroke_interface.c +++ b/src/charon/control/interfaces/stroke_interface.c @@ -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( diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c index 44f0298d5..9ccf297c9 100644 --- a/src/charon/sa/child_sa.c +++ b/src/charon/sa/child_sa.c @@ -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 */ diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 0c0e1792c..27ba1263a 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -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; diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index ba189577c..67d6a8853 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -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), }; /** diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c index eea769138..ff3fbb77c 100644 --- a/src/charon/sa/tasks/ike_natd.c +++ b/src/charon/sa/tasks/ike_natd.c @@ -114,6 +114,25 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this, } /** + * 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. */ static notify_payload_t *build_natd_payload(private_ike_natd_t *this, @@ -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); + } } } diff --git a/src/pluto/constants.h b/src/pluto/constants.h index b869992e1..a4f5ba1eb 100644 --- a/src/pluto/constants.h +++ b/src/pluto/constants.h @@ -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.) diff --git a/src/starter/args.c b/src/starter/args.c index bfb71470d..6ddc7217b 100644 --- a/src/starter/args.c +++ b/src/starter/args.c @@ -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 }, diff --git a/src/starter/confread.c b/src/starter/confread.c index 8ef115f52..cd1e21317 100644 --- a/src/starter/confread.c +++ b/src/starter/confread.c @@ -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; diff --git a/src/starter/ipsec.conf.5 b/src/starter/ipsec.conf.5 index a1f6cb8cc..a54a6cc11 100644 --- a/src/starter/ipsec.conf.5 +++ b/src/starter/ipsec.conf.5 @@ -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 diff --git a/src/starter/keywords.h b/src/starter/keywords.h index 69a4b6d86..d25e08b47 100644 --- a/src/starter/keywords.h +++ b/src/starter/keywords.h @@ -71,6 +71,7 @@ typedef enum { KW_AUTHBY, KW_EAP, KW_MOBIKE, + KW_FORCE_ENCAP, KW_IKELIFETIME, KW_KEYLIFE, KW_REKEYMARGIN, diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt index 5deecff90..c0990c588 100644 --- a/src/starter/keywords.txt +++ b/src/starter/keywords.txt @@ -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 diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c index 14f2e548f..d984f66ab 100644 --- a/src/stroke/stroke.c +++ b/src/stroke/stroke.c @@ -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; diff --git a/src/stroke/stroke.h b/src/stroke/stroke.h index f903379cd..46bd12965 100644 --- a/src/stroke/stroke.h +++ b/src/stroke/stroke.h @@ -183,6 +183,7 @@ struct stroke_msg_t { int eap_type; int mode; int mobike; + int force_encap; struct { char *ike; char *esp; |