child-sa: Allow requesting different unique marks for in/out
When requiring unique flags for CHILD_SAs, allow the configuration to request different marks for each direction by using the %unique-dir keyword. This is useful when different marks are desired for each direction but the number of peers is not predefined. An example use case is when implementing a site-to-site route-based VPN without VTI devices. A use of 0.0.0.0/0 - 0.0.0.0/0 traffic selectors with identical in/out marks results in outbound traffic being wrongfully matched against the 'fwd' policy - for which the underlay 'template' does not match - and dropped. Using different marks for each direction avoids this issue as the 'fwd' policy uses the 'in' mark will not match outbound traffic. Closes strongswan/strongswan#78.
This commit is contained in:
committed by
Tobias Brunner
parent
00498d78a8
commit
32e5c49234
+4
-1
@@ -1037,7 +1037,10 @@ mask of
|
|||||||
.B 0xffffffff
|
.B 0xffffffff
|
||||||
is assumed. The special value
|
is assumed. The special value
|
||||||
.B %unique
|
.B %unique
|
||||||
assigns a unique value to each newly created IPsec SA.
|
assigns a unique value to each newly created IPsec SA. To additionally
|
||||||
|
make the mark unique for each IPsec SA direction (in/out) the special value
|
||||||
|
.B %unique-dir
|
||||||
|
may be used.
|
||||||
.TP
|
.TP
|
||||||
.BR mark_in " = <value>[/<mask>]"
|
.BR mark_in " = <value>[/<mask>]"
|
||||||
sets an XFRM mark in the inbound IPsec SA and
|
sets an XFRM mark in the inbound IPsec SA and
|
||||||
|
|||||||
@@ -1745,7 +1745,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
|
|||||||
{
|
{
|
||||||
private_child_sa_t *this;
|
private_child_sa_t *this;
|
||||||
static refcount_t unique_id = 0, unique_mark = 0;
|
static refcount_t unique_id = 0, unique_mark = 0;
|
||||||
refcount_t mark;
|
refcount_t mark = 0;
|
||||||
|
|
||||||
INIT(this,
|
INIT(this,
|
||||||
.public = {
|
.public = {
|
||||||
@@ -1818,16 +1818,33 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
|
|||||||
{
|
{
|
||||||
this->mark_out.value = mark_out;
|
this->mark_out.value = mark_out;
|
||||||
}
|
}
|
||||||
if (this->mark_in.value == MARK_UNIQUE ||
|
|
||||||
this->mark_out.value == MARK_UNIQUE)
|
if (MARK_IS_UNIQUE(this->mark_in.value) ||
|
||||||
|
MARK_IS_UNIQUE(this->mark_out.value))
|
||||||
{
|
{
|
||||||
mark = ref_get(&unique_mark);
|
bool unique_dir;
|
||||||
if (this->mark_in.value == MARK_UNIQUE)
|
|
||||||
|
unique_dir = this->mark_in.value == MARK_UNIQUE_DIR ||
|
||||||
|
this->mark_out.value == MARK_UNIQUE_DIR;
|
||||||
|
|
||||||
|
if (!unique_dir)
|
||||||
{
|
{
|
||||||
|
mark = ref_get(&unique_mark);
|
||||||
|
}
|
||||||
|
if (MARK_IS_UNIQUE(this->mark_in.value))
|
||||||
|
{
|
||||||
|
if (unique_dir)
|
||||||
|
{
|
||||||
|
mark = ref_get(&unique_mark);
|
||||||
|
}
|
||||||
this->mark_in.value = mark;
|
this->mark_in.value = mark;
|
||||||
}
|
}
|
||||||
if (this->mark_out.value == MARK_UNIQUE)
|
if (MARK_IS_UNIQUE(this->mark_out.value))
|
||||||
{
|
{
|
||||||
|
if (unique_dir)
|
||||||
|
{
|
||||||
|
mark = ref_get(&unique_mark);
|
||||||
|
}
|
||||||
this->mark_out.value = mark;
|
this->mark_out.value = mark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,8 +66,21 @@ bool mark_from_string(const char *value, mark_t *mark)
|
|||||||
}
|
}
|
||||||
if (strcasepfx(value, "%unique"))
|
if (strcasepfx(value, "%unique"))
|
||||||
{
|
{
|
||||||
mark->value = MARK_UNIQUE;
|
|
||||||
endptr = (char*)value + strlen("%unique");
|
endptr = (char*)value + strlen("%unique");
|
||||||
|
if (strcasepfx(endptr, "-dir"))
|
||||||
|
{
|
||||||
|
mark->value = MARK_UNIQUE_DIR;
|
||||||
|
endptr += strlen("-dir");
|
||||||
|
}
|
||||||
|
else if (!*endptr || *endptr == '/')
|
||||||
|
{
|
||||||
|
mark->value = MARK_UNIQUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG1(DBG_APP, "invalid mark value: %s", value);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -178,9 +178,11 @@ struct mark_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special mark value that uses a unique mark for each CHILD_SA
|
* Special mark value that uses a unique mark for each CHILD_SA (and direction)
|
||||||
*/
|
*/
|
||||||
#define MARK_UNIQUE (0xFFFFFFFF)
|
#define MARK_UNIQUE (0xFFFFFFFF)
|
||||||
|
#define MARK_UNIQUE_DIR (0xFFFFFFFE)
|
||||||
|
#define MARK_IS_UNIQUE(m) ((m) == MARK_UNIQUE || (m) == MARK_UNIQUE_DIR)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to parse a mark_t from the given string of the form mark[/mask].
|
* Try to parse a mark_t from the given string of the form mark[/mask].
|
||||||
|
|||||||
@@ -870,7 +870,9 @@ connections.<conn>.children.<child>.mark_in = 0/0x00000000
|
|||||||
Netfilter mark and mask for input traffic. On Linux Netfilter may require
|
Netfilter mark and mask for input traffic. On Linux Netfilter may require
|
||||||
marks on each packet to match an SA having that option set. This allows
|
marks on each packet to match an SA having that option set. This allows
|
||||||
Netfilter rules to select specific tunnels for incoming traffic. The
|
Netfilter rules to select specific tunnels for incoming traffic. The
|
||||||
special value _%unique_ sets a unique mark on each CHILD_SA instance.
|
special value _%unique_ sets a unique mark on each CHILD_SA instance,
|
||||||
|
beyond that the value _%unique-dir_ assigns a different unique mark for each
|
||||||
|
CHILD_SA direction (in/out).
|
||||||
|
|
||||||
An additional mask may be appended to the mark, separated by _/_. The
|
An additional mask may be appended to the mark, separated by _/_. The
|
||||||
default mask if omitted is 0xffffffff.
|
default mask if omitted is 0xffffffff.
|
||||||
@@ -881,7 +883,9 @@ connections.<conn>.children.<child>.mark_out = 0/0x00000000
|
|||||||
Netfilter mark and mask for output traffic. On Linux Netfilter may require
|
Netfilter mark and mask for output traffic. On Linux Netfilter may require
|
||||||
marks on each packet to match a policy having that option set. This allows
|
marks on each packet to match a policy having that option set. This allows
|
||||||
Netfilter rules to select specific tunnels for outgoing traffic. The
|
Netfilter rules to select specific tunnels for outgoing traffic. The
|
||||||
special value _%unique_ sets a unique mark on each CHILD_SA instance.
|
special value _%unique_ sets a unique mark on each CHILD_SA instance,
|
||||||
|
beyond that the value _%unique-dir_ assigns a different unique mark for each
|
||||||
|
CHILD_SA direction (in/out).
|
||||||
|
|
||||||
An additional mask may be appended to the mark, separated by _/_. The
|
An additional mask may be appended to the mark, separated by _/_. The
|
||||||
default mask if omitted is 0xffffffff.
|
default mask if omitted is 0xffffffff.
|
||||||
|
|||||||
Reference in New Issue
Block a user