Merge branch 'fwd-out-policies-optional'

This makes the FWD policies in the out direction  optional (disabled by
default).  They may be enabled (e.g. if conflicting drop policies are
used) via the policies_fwd_out swanctl.conf option.
This commit is contained in:
Tobias Brunner
2016-09-28 17:59:21 +02:00
6 changed files with 93 additions and 44 deletions
+14
View File
@@ -153,6 +153,11 @@ struct private_child_cfg_t {
*/ */
bool install_policy; bool install_policy;
/**
* Install outbound FWD policies
*/
bool fwd_out_policy;
/** /**
* anti-replay window size * anti-replay window size
*/ */
@@ -564,6 +569,12 @@ METHOD(child_cfg_t, install_policy, bool,
return this->install_policy; return this->install_policy;
} }
METHOD(child_cfg_t, install_fwd_out_policy, bool,
private_child_cfg_t *this)
{
return this->fwd_out_policy;
}
#define LT_PART_EQUALS(a, b) ({ a.life == b.life && a.rekey == b.rekey && a.jitter == b.jitter; }) #define LT_PART_EQUALS(a, b) ({ a.life == b.life && a.rekey == b.rekey && a.jitter == b.jitter; })
#define LIFETIME_EQUALS(a, b) ({ LT_PART_EQUALS(a.time, b.time) && LT_PART_EQUALS(a.bytes, b.bytes) && LT_PART_EQUALS(a.packets, b.packets); }) #define LIFETIME_EQUALS(a, b) ({ LT_PART_EQUALS(a.time, b.time) && LT_PART_EQUALS(a.bytes, b.bytes) && LT_PART_EQUALS(a.packets, b.packets); })
@@ -613,6 +624,7 @@ METHOD(child_cfg_t, equals, bool,
this->replay_window == other->replay_window && this->replay_window == other->replay_window &&
this->proxy_mode == other->proxy_mode && this->proxy_mode == other->proxy_mode &&
this->install_policy == other->install_policy && this->install_policy == other->install_policy &&
this->fwd_out_policy == other->fwd_out_policy &&
streq(this->updown, other->updown) && streq(this->updown, other->updown) &&
streq(this->interface, other->interface); streq(this->interface, other->interface);
} }
@@ -673,6 +685,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.set_replay_window = _set_replay_window, .set_replay_window = _set_replay_window,
.use_proxy_mode = _use_proxy_mode, .use_proxy_mode = _use_proxy_mode,
.install_policy = _install_policy, .install_policy = _install_policy,
.install_fwd_out_policy = _install_fwd_out_policy,
.equals = _equals, .equals = _equals,
.get_ref = _get_ref, .get_ref = _get_ref,
.destroy = _destroy, .destroy = _destroy,
@@ -695,6 +708,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.manual_prio = data->priority, .manual_prio = data->priority,
.interface = strdupnull(data->interface), .interface = strdupnull(data->interface),
.install_policy = !data->suppress_policies, .install_policy = !data->suppress_policies,
.fwd_out_policy = data->fwd_out_policies,
.refcount = 1, .refcount = 1,
.proposals = linked_list_create(), .proposals = linked_list_create(),
.my_ts = linked_list_create(), .my_ts = linked_list_create(),
+10
View File
@@ -283,6 +283,14 @@ struct child_cfg_t {
*/ */
bool (*install_policy)(child_cfg_t *this); bool (*install_policy)(child_cfg_t *this);
/**
* Check whether outbound FWD IPsec policies should be installed.
*
* @return TRUE, if outbound FWD policies should be installed
* FALSE, otherwise
*/
bool (*install_fwd_out_policy)(child_cfg_t *this);
/** /**
* Check if two child_cfg objects are equal. * Check if two child_cfg objects are equal.
* *
@@ -346,6 +354,8 @@ struct child_cfg_create_t {
bool hostaccess; bool hostaccess;
/** Don't install IPsec policies */ /** Don't install IPsec policies */
bool suppress_policies; bool suppress_policies;
/** Install outbound FWD IPsec policies to bypass drop policies */
bool fwd_out_policies;
}; };
/** /**
+29 -25
View File
@@ -437,6 +437,7 @@ typedef struct {
linked_list_t *remote_ts; linked_list_t *remote_ts;
uint32_t replay_window; uint32_t replay_window;
bool policies; bool policies;
bool policies_fwd_out;
child_cfg_create_t cfg; child_cfg_create_t cfg;
} child_data_t; } child_data_t;
@@ -462,6 +463,7 @@ static void log_child_data(child_data_t *data, char *name)
DBG2(DBG_CFG, " ipcomp = %u", cfg->ipcomp); DBG2(DBG_CFG, " ipcomp = %u", cfg->ipcomp);
DBG2(DBG_CFG, " mode = %N", ipsec_mode_names, cfg->mode); DBG2(DBG_CFG, " mode = %N", ipsec_mode_names, cfg->mode);
DBG2(DBG_CFG, " policies = %u", data->policies); DBG2(DBG_CFG, " policies = %u", data->policies);
DBG2(DBG_CFG, " policies_fwd_out = %u", data->policies_fwd_out);
if (data->replay_window != REPLAY_UNDEFINED) if (data->replay_window != REPLAY_UNDEFINED)
{ {
DBG2(DBG_CFG, " replay_window = %u", data->replay_window); DBG2(DBG_CFG, " replay_window = %u", data->replay_window);
@@ -1330,31 +1332,32 @@ CALLBACK(child_kv, bool,
child_data_t *child, vici_message_t *message, char *name, chunk_t value) child_data_t *child, vici_message_t *message, char *name, chunk_t value)
{ {
parse_rule_t rules[] = { parse_rule_t rules[] = {
{ "updown", parse_string, &child->cfg.updown }, { "updown", parse_string, &child->cfg.updown },
{ "hostaccess", parse_bool, &child->cfg.hostaccess }, { "hostaccess", parse_bool, &child->cfg.hostaccess },
{ "mode", parse_mode, &child->cfg.mode }, { "mode", parse_mode, &child->cfg.mode },
{ "policies", parse_bool, &child->policies }, { "policies", parse_bool, &child->policies },
{ "replay_window", parse_uint32, &child->replay_window }, { "policies_fwd_out", parse_bool, &child->policies_fwd_out },
{ "rekey_time", parse_time, &child->cfg.lifetime.time.rekey }, { "replay_window", parse_uint32, &child->replay_window },
{ "life_time", parse_time, &child->cfg.lifetime.time.life }, { "rekey_time", parse_time, &child->cfg.lifetime.time.rekey },
{ "rand_time", parse_time, &child->cfg.lifetime.time.jitter }, { "life_time", parse_time, &child->cfg.lifetime.time.life },
{ "rekey_bytes", parse_bytes, &child->cfg.lifetime.bytes.rekey }, { "rand_time", parse_time, &child->cfg.lifetime.time.jitter },
{ "life_bytes", parse_bytes, &child->cfg.lifetime.bytes.life }, { "rekey_bytes", parse_bytes, &child->cfg.lifetime.bytes.rekey },
{ "rand_bytes", parse_bytes, &child->cfg.lifetime.bytes.jitter }, { "life_bytes", parse_bytes, &child->cfg.lifetime.bytes.life },
{ "rekey_packets", parse_uint64, &child->cfg.lifetime.packets.rekey }, { "rand_bytes", parse_bytes, &child->cfg.lifetime.bytes.jitter },
{ "life_packets", parse_uint64, &child->cfg.lifetime.packets.life }, { "rekey_packets", parse_uint64, &child->cfg.lifetime.packets.rekey },
{ "rand_packets", parse_uint64, &child->cfg.lifetime.packets.jitter }, { "life_packets", parse_uint64, &child->cfg.lifetime.packets.life },
{ "dpd_action", parse_action, &child->cfg.dpd_action }, { "rand_packets", parse_uint64, &child->cfg.lifetime.packets.jitter },
{ "start_action", parse_action, &child->cfg.start_action }, { "dpd_action", parse_action, &child->cfg.dpd_action },
{ "close_action", parse_action, &child->cfg.close_action }, { "start_action", parse_action, &child->cfg.start_action },
{ "ipcomp", parse_bool, &child->cfg.ipcomp }, { "close_action", parse_action, &child->cfg.close_action },
{ "inactivity", parse_time, &child->cfg.inactivity }, { "ipcomp", parse_bool, &child->cfg.ipcomp },
{ "reqid", parse_uint32, &child->cfg.reqid }, { "inactivity", parse_time, &child->cfg.inactivity },
{ "mark_in", parse_mark, &child->cfg.mark_in }, { "reqid", parse_uint32, &child->cfg.reqid },
{ "mark_out", parse_mark, &child->cfg.mark_out }, { "mark_in", parse_mark, &child->cfg.mark_in },
{ "tfc_padding", parse_tfc, &child->cfg.tfc }, { "mark_out", parse_mark, &child->cfg.mark_out },
{ "priority", parse_uint32, &child->cfg.priority }, { "tfc_padding", parse_tfc, &child->cfg.tfc },
{ "interface", parse_string, &child->cfg.interface }, { "priority", parse_uint32, &child->cfg.priority },
{ "interface", parse_string, &child->cfg.interface },
}; };
return parse_rules(rules, countof(rules), name, value, return parse_rules(rules, countof(rules), name, value,
@@ -1537,6 +1540,7 @@ CALLBACK(children_sn, bool,
} }
} }
child.cfg.suppress_policies = !child.policies; child.cfg.suppress_policies = !child.policies;
child.cfg.fwd_out_policies = child.policies_fwd_out;
check_lifetimes(&child.cfg.lifetime); check_lifetimes(&child.cfg.lifetime);
+27 -14
View File
@@ -111,11 +111,16 @@ struct private_child_sa_t {
*/ */
bool static_reqid; bool static_reqid;
/* /**
* Unique CHILD_SA identifier * Unique CHILD_SA identifier
*/ */
uint32_t unique_id; uint32_t unique_id;
/**
* Whether FWD policieis in the outbound direction should be installed
*/
bool policies_fwd_out;
/** /**
* inbound mark used for this child_sa * inbound mark used for this child_sa
*/ */
@@ -931,15 +936,19 @@ static status_t install_policies_internal(private_child_sa_t *this,
* policies of two SAs we install them with reduced priority. As they * policies of two SAs we install them with reduced priority. As they
* basically act as bypass policies for drop policies we use a higher * basically act as bypass policies for drop policies we use a higher
* priority than is used for them. */ * priority than is used for them. */
out_id.dir = POLICY_FWD; if (this->policies_fwd_out)
other_sa->reqid = 0;
if (priority == POLICY_PRIORITY_DEFAULT)
{ {
out_policy.prio = POLICY_PRIORITY_ROUTED; out_id.dir = POLICY_FWD;
other_sa->reqid = 0;
if (priority == POLICY_PRIORITY_DEFAULT)
{
out_policy.prio = POLICY_PRIORITY_ROUTED;
}
status |= charon->kernel->add_policy(charon->kernel, &out_id,
&out_policy);
/* reset the reqid for any other further policies */
other_sa->reqid = this->reqid;
} }
status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
/* reset the reqid for any other further policies */
other_sa->reqid = this->reqid;
} }
return status; return status;
} }
@@ -988,14 +997,17 @@ static void del_policies_internal(private_child_sa_t *this,
in_id.dir = POLICY_FWD; in_id.dir = POLICY_FWD;
charon->kernel->del_policy(charon->kernel, &in_id, &in_policy); charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
out_id.dir = POLICY_FWD; if (this->policies_fwd_out)
other_sa->reqid = 0;
if (priority == POLICY_PRIORITY_DEFAULT)
{ {
out_policy.prio = POLICY_PRIORITY_ROUTED; out_id.dir = POLICY_FWD;
other_sa->reqid = 0;
if (priority == POLICY_PRIORITY_DEFAULT)
{
out_policy.prio = POLICY_PRIORITY_ROUTED;
}
charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
other_sa->reqid = this->reqid;
} }
charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
other_sa->reqid = this->reqid;
} }
} }
@@ -1443,6 +1455,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
.mark_in = config->get_mark(config, TRUE), .mark_in = config->get_mark(config, TRUE),
.mark_out = config->get_mark(config, FALSE), .mark_out = config->get_mark(config, FALSE),
.install_time = time_monotonic(NULL), .install_time = time_monotonic(NULL),
.policies_fwd_out = config->install_fwd_out_policy(config),
); );
this->config = config; this->config = config;
+7
View File
@@ -659,6 +659,13 @@ connections.<conn>.children.<child>.policies = yes
Whether to install IPsec policies or not. Disabling this can be useful in Whether to install IPsec policies or not. Disabling this can be useful in
some scenarios e.g. MIPv6, where policies are not managed by the IKE daemon. some scenarios e.g. MIPv6, where policies are not managed by the IKE daemon.
connections.<conn>.children.<child>.policies_fwd_out = no
Whether to install outbound FWD IPsec policies or not.
Whether to install outbound FWD IPsec policies or not. Enabling this is
required in case there is a drop policy that would match and block forwarded
traffic for this CHILD_SA.
connections.<conn>.children.<child>.dpd_action = clear connections.<conn>.children.<child>.dpd_action = clear
Action to perform on DPD timeout (_clear_, _trap_ or _restart_). Action to perform on DPD timeout (_clear_, _trap_ or _restart_).
@@ -16,7 +16,8 @@ connections {
local_ts = 10.1.0.0/16 local_ts = 10.1.0.0/16
priority = 2 priority = 2
interface = eth0 interface = eth0
policies_fwd_out = yes
esp_proposals = aes128gcm128-modp3072 esp_proposals = aes128gcm128-modp3072
} }
} }
@@ -32,15 +33,15 @@ connections {
local_ts = 0.0.0.0/0 local_ts = 0.0.0.0/0
remote_ts = 0.0.0.0/0 remote_ts = 0.0.0.0/0
interface = eth0 interface = eth0
priority = 4 priority = 4
mode = drop mode = drop
start_action = trap start_action = trap
} }
pass-ssh-in { pass-ssh-in {
local_ts = 0.0.0.0/0[tcp/ssh] local_ts = 0.0.0.0/0[tcp/ssh]
remote_ts = 0.0.0.0/0[tcp] remote_ts = 0.0.0.0/0[tcp]
priority = 1 priority = 1
mode = pass mode = pass
start_action = trap start_action = trap
@@ -61,6 +62,6 @@ connections {
mode = pass mode = pass
start_action = trap start_action = trap
} }
} }
} }
} }