Merge branch 'iptfs'
This adds basic support for IP-TFS/AGGFRAG (RFC 9347). The Linux kernel, since 6.14, only supports aggregation/fragmentation so far. The actual TFS features will get added later.
This commit is contained in:
@@ -16,6 +16,7 @@ options = \
|
|||||||
options/charon-systemd.opt \
|
options/charon-systemd.opt \
|
||||||
options/imcv.opt \
|
options/imcv.opt \
|
||||||
options/imv_policy_manager.opt \
|
options/imv_policy_manager.opt \
|
||||||
|
options/iptfs.opt \
|
||||||
options/manager.opt \
|
options/manager.opt \
|
||||||
options/medsrv.opt \
|
options/medsrv.opt \
|
||||||
options/pki.opt \
|
options/pki.opt \
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
charon.iptfs {}
|
||||||
|
Global settings for IP-TFS (RFC 9347). The Linux kernel supports this mode
|
||||||
|
since 6.14. However, it currently only supports aggregation/fragmentation of
|
||||||
|
tunneled IP packets in ESP/AGGFRAG packets. It doesn't yet support other
|
||||||
|
IP-TFS features like sending packets at a constant rate or congestion control.
|
||||||
|
|
||||||
|
charon.iptfs.drop_time = 1000000
|
||||||
|
Time in microseconds to wait for out-of-order packets when processing
|
||||||
|
inbound traffic.
|
||||||
|
|
||||||
|
charon.iptfs.reorder_window = 3
|
||||||
|
Number of packets that may arrive out of order when processing inbound
|
||||||
|
traffic.
|
||||||
|
|
||||||
|
charon.iptfs.init_delay = 0
|
||||||
|
Time in microseconds to wait for subsequent packets to aggregate together
|
||||||
|
when sending outbound traffic. Only relevant if no packets are already
|
||||||
|
queued to be sent.
|
||||||
|
|
||||||
|
charon.iptfs.max_queue_size = 1048576
|
||||||
|
Maximum number of bytes allowed to be queued for sending on the tunnel
|
||||||
|
(default 1 MiB). If the queue is full, packets are dropped.
|
||||||
|
|
||||||
|
charon.iptfs.packet_size = 0
|
||||||
|
Maximum outer packet size (layer 3) when sending packets. The default of 0
|
||||||
|
will use the PMTU as packet size. Note that the kernel currently doesn't
|
||||||
|
pad smaller packets.
|
||||||
|
|
||||||
|
charon.iptfs.accept_fragments = yes
|
||||||
|
Whether fragments of inner packets across multiple AGGFRAG payloads are
|
||||||
|
accepted. This is an IKEv2 option, so if the peer doesn't adhere to this
|
||||||
|
request and still sends such fragments, they will be processed by the
|
||||||
|
kernel.
|
||||||
|
|
||||||
|
charon.iptfs.dont_frag = no
|
||||||
|
Force disabling fragmenting inner packets across multiple AGGFRAG payloads
|
||||||
|
when sending outbound traffic (fragmentation is automatically disabled if
|
||||||
|
the peer indicates that it doesn't support handling such packets).
|
||||||
+1
-1
@@ -1949,7 +1949,7 @@ strongswan_options=
|
|||||||
|
|
||||||
AM_COND_IF([USE_AIKGEN], [strongswan_options=${strongswan_options}" aikgen"])
|
AM_COND_IF([USE_AIKGEN], [strongswan_options=${strongswan_options}" aikgen"])
|
||||||
AM_COND_IF([USE_ATTR_SQL], [strongswan_options=${strongswan_options}" pool"])
|
AM_COND_IF([USE_ATTR_SQL], [strongswan_options=${strongswan_options}" pool"])
|
||||||
AM_COND_IF([USE_CHARON], [strongswan_options=${strongswan_options}" charon charon-logging"])
|
AM_COND_IF([USE_CHARON], [strongswan_options=${strongswan_options}" charon charon-logging iptfs"])
|
||||||
AM_COND_IF([USE_FILE_CONFIG], [strongswan_options=${strongswan_options}" starter"])
|
AM_COND_IF([USE_FILE_CONFIG], [strongswan_options=${strongswan_options}" starter"])
|
||||||
AM_COND_IF([USE_IMV_ATTESTATION], [strongswan_options=${strongswan_options}" attest"])
|
AM_COND_IF([USE_IMV_ATTESTATION], [strongswan_options=${strongswan_options}" attest"])
|
||||||
AM_COND_IF([USE_IMCV], [strongswan_options=${strongswan_options}" imcv imv_policy_manager"])
|
AM_COND_IF([USE_IMCV], [strongswan_options=${strongswan_options}" imcv imv_policy_manager"])
|
||||||
|
|||||||
@@ -154,7 +154,8 @@ enum {
|
|||||||
#define XFRM_MODE_ROUTEOPTIMIZATION 2
|
#define XFRM_MODE_ROUTEOPTIMIZATION 2
|
||||||
#define XFRM_MODE_IN_TRIGGER 3
|
#define XFRM_MODE_IN_TRIGGER 3
|
||||||
#define XFRM_MODE_BEET 4
|
#define XFRM_MODE_BEET 4
|
||||||
#define XFRM_MODE_MAX 5
|
#define XFRM_MODE_IPTFS 5
|
||||||
|
#define XFRM_MODE_MAX 6
|
||||||
|
|
||||||
/* Netlink configuration messages. */
|
/* Netlink configuration messages. */
|
||||||
enum {
|
enum {
|
||||||
@@ -319,6 +320,12 @@ enum xfrm_attr_type_t {
|
|||||||
XFRMA_SA_DIR, /* __u8 */
|
XFRMA_SA_DIR, /* __u8 */
|
||||||
XFRMA_NAT_KEEPALIVE_INTERVAL, /* __u32 in seconds for NAT keepalive */
|
XFRMA_NAT_KEEPALIVE_INTERVAL, /* __u32 in seconds for NAT keepalive */
|
||||||
XFRMA_SA_PCPU, /* __u32 */
|
XFRMA_SA_PCPU, /* __u32 */
|
||||||
|
XFRMA_IPTFS_DROP_TIME, /* __u32 in: usec to wait for next seq */
|
||||||
|
XFRMA_IPTFS_REORDER_WINDOW, /* __u16 in: reorder window size (pkts) */
|
||||||
|
XFRMA_IPTFS_DONT_FRAG, /* out: don't use fragmentation */
|
||||||
|
XFRMA_IPTFS_INIT_DELAY, /* __u32 out: initial packet wait delay (usec) */
|
||||||
|
XFRMA_IPTFS_MAX_QSIZE, /* __u32 out: max ingress queue size (octets) */
|
||||||
|
XFRMA_IPTFS_PKT_SIZE, /* __u32 out: size of outer packet, 0 for PMTU */
|
||||||
__XFRMA_MAX
|
__XFRMA_MAX
|
||||||
|
|
||||||
#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */
|
#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */
|
||||||
|
|||||||
@@ -122,9 +122,10 @@ ENUM_NEXT(notify_type_names, USE_PPK, INTERMEDIATE_EXCHANGE_SUPPORTED, SIGNATURE
|
|||||||
"PPK_IDENTITY",
|
"PPK_IDENTITY",
|
||||||
"NO_PPK_AUTH",
|
"NO_PPK_AUTH",
|
||||||
"INTERMEDIATE_EXCHANGE_SUPPORTED");
|
"INTERMEDIATE_EXCHANGE_SUPPORTED");
|
||||||
ENUM_NEXT(notify_type_names, ADDITIONAL_KEY_EXCHANGE, ADDITIONAL_KEY_EXCHANGE, INTERMEDIATE_EXCHANGE_SUPPORTED,
|
ENUM_NEXT(notify_type_names, ADDITIONAL_KEY_EXCHANGE, USE_AGGFRAG, INTERMEDIATE_EXCHANGE_SUPPORTED,
|
||||||
"ADDITIONAL_KEY_EXCHANGE");
|
"ADDITIONAL_KEY_EXCHANGE",
|
||||||
ENUM_NEXT(notify_type_names, SA_RESOURCE_INFO, SA_RESOURCE_INFO, ADDITIONAL_KEY_EXCHANGE,
|
"USE_AGGFRAG");
|
||||||
|
ENUM_NEXT(notify_type_names, SA_RESOURCE_INFO, SA_RESOURCE_INFO, USE_AGGFRAG,
|
||||||
"SA_RESOURCE_INFO");
|
"SA_RESOURCE_INFO");
|
||||||
ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, SA_RESOURCE_INFO,
|
ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, SA_RESOURCE_INFO,
|
||||||
"INITIAL_CONTACT");
|
"INITIAL_CONTACT");
|
||||||
@@ -244,9 +245,10 @@ ENUM_NEXT(notify_type_short_names, USE_PPK, INTERMEDIATE_EXCHANGE_SUPPORTED, SIG
|
|||||||
"PPK_ID",
|
"PPK_ID",
|
||||||
"NO_PPK",
|
"NO_PPK",
|
||||||
"IKE_INT_SUP");
|
"IKE_INT_SUP");
|
||||||
ENUM_NEXT(notify_type_short_names, ADDITIONAL_KEY_EXCHANGE, ADDITIONAL_KEY_EXCHANGE, INTERMEDIATE_EXCHANGE_SUPPORTED,
|
ENUM_NEXT(notify_type_short_names, ADDITIONAL_KEY_EXCHANGE, USE_AGGFRAG, INTERMEDIATE_EXCHANGE_SUPPORTED,
|
||||||
"ADD_KE");
|
"ADD_KE",
|
||||||
ENUM_NEXT(notify_type_short_names, SA_RESOURCE_INFO, SA_RESOURCE_INFO, ADDITIONAL_KEY_EXCHANGE,
|
"AGGFRAG");
|
||||||
|
ENUM_NEXT(notify_type_short_names, SA_RESOURCE_INFO, SA_RESOURCE_INFO, USE_AGGFRAG,
|
||||||
"RES_INFO");
|
"RES_INFO");
|
||||||
ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, SA_RESOURCE_INFO,
|
ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, SA_RESOURCE_INFO,
|
||||||
"INITIAL_CONTACT");
|
"INITIAL_CONTACT");
|
||||||
@@ -560,6 +562,12 @@ METHOD(payload_t, verify, status_t,
|
|||||||
bad_length = TRUE;
|
bad_length = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case USE_AGGFRAG:
|
||||||
|
if (this->notify_data.len != 1)
|
||||||
|
{
|
||||||
|
bad_length = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* TODO: verify */
|
/* TODO: verify */
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -171,6 +171,8 @@ enum notify_type_t {
|
|||||||
|
|
||||||
/* multiple key exchanges, RFC 9370 */
|
/* multiple key exchanges, RFC 9370 */
|
||||||
ADDITIONAL_KEY_EXCHANGE = 16441,
|
ADDITIONAL_KEY_EXCHANGE = 16441,
|
||||||
|
/* IP-TFS/AGGFRAG, RFC 9347 */
|
||||||
|
USE_AGGFRAG = 16442,
|
||||||
|
|
||||||
/* Resource info for CHILD_SAs, RFC 9611 */
|
/* Resource info for CHILD_SAs, RFC 9611 */
|
||||||
SA_RESOURCE_INFO = 16444,
|
SA_RESOURCE_INFO = 16444,
|
||||||
|
|||||||
@@ -113,6 +113,8 @@ struct kernel_ipsec_add_sa_t {
|
|||||||
bool copy_ecn;
|
bool copy_ecn;
|
||||||
/** Whether to copy the DSCP header field to/from the outer header */
|
/** Whether to copy the DSCP header field to/from the outer header */
|
||||||
dscp_copy_t copy_dscp;
|
dscp_copy_t copy_dscp;
|
||||||
|
/** TRUE if the peer doesn't support receiving fragments in AGGFRAG pkts */
|
||||||
|
bool iptfs_dont_frag;
|
||||||
/** TRUE if initiator of the exchange creating the SA */
|
/** TRUE if initiator of the exchange creating the SA */
|
||||||
bool initiator;
|
bool initiator;
|
||||||
/** TRUE if this is an inbound SA */
|
/** TRUE if this is an inbound SA */
|
||||||
|
|||||||
@@ -205,6 +205,12 @@ ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, __XFRMA_MAX,
|
|||||||
"XFRMA_SA_DIR",
|
"XFRMA_SA_DIR",
|
||||||
"XFRMA_NAT_KEEPALIVE_INTERVAL",
|
"XFRMA_NAT_KEEPALIVE_INTERVAL",
|
||||||
"XFRMA_SA_PCPU",
|
"XFRMA_SA_PCPU",
|
||||||
|
"XFRMA_IPTFS_DROP_TIME",
|
||||||
|
"XFRMA_IPTFS_REORDER_WINDOW",
|
||||||
|
"XFRMA_IPTFS_DONT_FRAG",
|
||||||
|
"XFRMA_IPTFS_INIT_DELAY",
|
||||||
|
"XFRMA_IPTFS_MAX_QSIZE",
|
||||||
|
"XFRMA_IPTFS_PKT_SIZE",
|
||||||
"XFRMA_MAX",
|
"XFRMA_MAX",
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -787,6 +793,8 @@ static uint8_t mode2kernel(ipsec_mode_t mode)
|
|||||||
return XFRM_MODE_TUNNEL;
|
return XFRM_MODE_TUNNEL;
|
||||||
case MODE_BEET:
|
case MODE_BEET:
|
||||||
return XFRM_MODE_BEET;
|
return XFRM_MODE_BEET;
|
||||||
|
case MODE_IPTFS:
|
||||||
|
return XFRM_MODE_IPTFS;
|
||||||
default:
|
default:
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
@@ -1304,6 +1312,23 @@ static bool add_uint32(struct nlmsghdr *hdr, int buflen,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a uint16 attribute to message
|
||||||
|
*/
|
||||||
|
static bool add_uint16(struct nlmsghdr *hdr, int buflen,
|
||||||
|
enum xfrm_attr_type_t type, uint16_t value)
|
||||||
|
{
|
||||||
|
uint16_t *xvalue;
|
||||||
|
|
||||||
|
xvalue = netlink_reserve(hdr, buflen, type, sizeof(*xvalue));
|
||||||
|
if (!xvalue)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*xvalue = value;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a uint8 attribute to message
|
* Add a uint8 attribute to message
|
||||||
*/
|
*/
|
||||||
@@ -1821,6 +1846,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
|||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case MODE_TUNNEL:
|
case MODE_TUNNEL:
|
||||||
|
case MODE_IPTFS:
|
||||||
sa->flags |= XFRM_STATE_AF_UNSPEC;
|
sa->flags |= XFRM_STATE_AF_UNSPEC;
|
||||||
break;
|
break;
|
||||||
case MODE_BEET:
|
case MODE_BEET:
|
||||||
@@ -2124,6 +2150,53 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
|||||||
DBG2(DBG_KNL, " using CPU ID: %u", data->cpu);
|
DBG2(DBG_KNL, " using CPU ID: %u", data->cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mode == MODE_IPTFS)
|
||||||
|
{
|
||||||
|
if (data->inbound)
|
||||||
|
{
|
||||||
|
if (!add_uint32(hdr, sizeof(request), XFRMA_IPTFS_DROP_TIME,
|
||||||
|
lib->settings->get_int(lib->settings,
|
||||||
|
"%s.iptfs.drop_time", 1000000, lib->ns)))
|
||||||
|
{
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if (!add_uint16(hdr, sizeof(request), XFRMA_IPTFS_REORDER_WINDOW,
|
||||||
|
lib->settings->get_int(lib->settings,
|
||||||
|
"%s.iptfs.reorder_window", 3, lib->ns)))
|
||||||
|
{
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!add_uint32(hdr, sizeof(request), XFRMA_IPTFS_INIT_DELAY,
|
||||||
|
lib->settings->get_int(lib->settings,
|
||||||
|
"%s.iptfs.init_delay", 0, lib->ns)))
|
||||||
|
{
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if (!add_uint32(hdr, sizeof(request), XFRMA_IPTFS_MAX_QSIZE,
|
||||||
|
lib->settings->get_int(lib->settings,
|
||||||
|
"%s.iptfs.max_queue_size", 1024 * 1024, lib->ns)))
|
||||||
|
{
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if (!add_uint32(hdr, sizeof(request), XFRMA_IPTFS_PKT_SIZE,
|
||||||
|
lib->settings->get_int(lib->settings,
|
||||||
|
"%s.iptfs.packet_size", 0, lib->ns)))
|
||||||
|
{
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if ((data->iptfs_dont_frag ||
|
||||||
|
lib->settings->get_bool(lib->settings,
|
||||||
|
"%s.iptfs.dont_fragment", FALSE, lib->ns)) &&
|
||||||
|
!netlink_reserve(hdr, sizeof(request), XFRMA_IPTFS_DONT_FRAG, 0))
|
||||||
|
{
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (id->proto != IPPROTO_COMP)
|
if (id->proto != IPPROTO_COMP)
|
||||||
{
|
{
|
||||||
/* we don't need a replay window for outbound SAs, however, older
|
/* we don't need a replay window for outbound SAs, however, older
|
||||||
@@ -3054,7 +3127,8 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
|
|||||||
policy->direction != POLICY_OUT;
|
policy->direction != POLICY_OUT;
|
||||||
tmpl->family = ipsec->src->get_family(ipsec->src);
|
tmpl->family = ipsec->src->get_family(ipsec->src);
|
||||||
|
|
||||||
if (proto_mode == MODE_TUNNEL || proto_mode == MODE_BEET)
|
if (proto_mode == MODE_TUNNEL || proto_mode == MODE_BEET ||
|
||||||
|
proto_mode == MODE_IPTFS)
|
||||||
{ /* only for tunnel mode */
|
{ /* only for tunnel mode */
|
||||||
host2xfrm(ipsec->src, &tmpl->saddr);
|
host2xfrm(ipsec->src, &tmpl->saddr);
|
||||||
host2xfrm(ipsec->dst, &tmpl->id.daddr);
|
host2xfrm(ipsec->dst, &tmpl->id.daddr);
|
||||||
|
|||||||
@@ -904,6 +904,7 @@ CALLBACK(parse_mode, bool,
|
|||||||
{ "tunnel", MODE_TUNNEL },
|
{ "tunnel", MODE_TUNNEL },
|
||||||
{ "transport", MODE_TRANSPORT },
|
{ "transport", MODE_TRANSPORT },
|
||||||
{ "transport_proxy", MODE_TRANSPORT },
|
{ "transport_proxy", MODE_TRANSPORT },
|
||||||
|
{ "iptfs", MODE_IPTFS },
|
||||||
{ "beet", MODE_BEET },
|
{ "beet", MODE_BEET },
|
||||||
{ "drop", MODE_DROP },
|
{ "drop", MODE_DROP },
|
||||||
{ "pass", MODE_PASS },
|
{ "pass", MODE_PASS },
|
||||||
|
|||||||
@@ -246,6 +246,11 @@ struct private_child_sa_t {
|
|||||||
*/
|
*/
|
||||||
ipsec_mode_t mode;
|
ipsec_mode_t mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable fragmenting packets across IP-TFS packets
|
||||||
|
*/
|
||||||
|
bool iptfs_dont_frag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action to enforce if peer closes the CHILD_SA
|
* Action to enforce if peer closes the CHILD_SA
|
||||||
*/
|
*/
|
||||||
@@ -462,6 +467,12 @@ METHOD(child_sa_t, set_mode, void,
|
|||||||
this->mode = mode;
|
this->mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(child_sa_t, set_iptfs_dont_fragment, void,
|
||||||
|
private_child_sa_t *this)
|
||||||
|
{
|
||||||
|
this->iptfs_dont_frag = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(child_sa_t, has_encap, bool,
|
METHOD(child_sa_t, has_encap, bool,
|
||||||
private_child_sa_t *this)
|
private_child_sa_t *this)
|
||||||
{
|
{
|
||||||
@@ -1109,6 +1120,7 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
|
|||||||
.copy_df = !this->config->has_option(this->config, OPT_NO_COPY_DF),
|
.copy_df = !this->config->has_option(this->config, OPT_NO_COPY_DF),
|
||||||
.copy_ecn = !this->config->has_option(this->config, OPT_NO_COPY_ECN),
|
.copy_ecn = !this->config->has_option(this->config, OPT_NO_COPY_ECN),
|
||||||
.copy_dscp = this->config->get_copy_dscp(this->config),
|
.copy_dscp = this->config->get_copy_dscp(this->config),
|
||||||
|
.iptfs_dont_frag = this->iptfs_dont_frag,
|
||||||
.label = label_for(this, LABEL_USE_SA),
|
.label = label_for(this, LABEL_USE_SA),
|
||||||
.initiator = initiator,
|
.initiator = initiator,
|
||||||
.inbound = inbound,
|
.inbound = inbound,
|
||||||
@@ -2168,6 +2180,7 @@ child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
|
|||||||
.has_encap = _has_encap,
|
.has_encap = _has_encap,
|
||||||
.get_ipcomp = _get_ipcomp,
|
.get_ipcomp = _get_ipcomp,
|
||||||
.set_ipcomp = _set_ipcomp,
|
.set_ipcomp = _set_ipcomp,
|
||||||
|
.set_iptfs_dont_fragment = _set_iptfs_dont_fragment,
|
||||||
.get_close_action = _get_close_action,
|
.get_close_action = _get_close_action,
|
||||||
.set_close_action = _set_close_action,
|
.set_close_action = _set_close_action,
|
||||||
.get_dpd_action = _get_dpd_action,
|
.get_dpd_action = _get_dpd_action,
|
||||||
|
|||||||
@@ -290,6 +290,12 @@ struct child_sa_t {
|
|||||||
*/
|
*/
|
||||||
void (*set_ipcomp)(child_sa_t *this, ipcomp_transform_t ipcomp);
|
void (*set_ipcomp)(child_sa_t *this, ipcomp_transform_t ipcomp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable fragmenting messages across multiple IP-TFS packets. Only
|
||||||
|
* relevant with MODE_IPTFS.
|
||||||
|
*/
|
||||||
|
void (*set_iptfs_dont_fragment)(child_sa_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the action to enforce if the remote peer closes the CHILD_SA.
|
* Get the action to enforce if the remote peer closes the CHILD_SA.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -43,6 +43,16 @@ typedef struct private_child_create_t private_child_create_t;
|
|||||||
/** Assumed minimum CPU ID, used when searching for a CPU without SA */
|
/** Assumed minimum CPU ID, used when searching for a CPU without SA */
|
||||||
#define CPU_ID_MIN 0
|
#define CPU_ID_MIN 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags for IP-TFS
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/** Indicates that fragmentation across packets is not supported */
|
||||||
|
IPTFS_DONT_FRAGMENT = (1 << 0),
|
||||||
|
/** Requests periodic congestion control information from the peer */
|
||||||
|
IPTFS_CONGESTION_CONTROL = (1 << 1),
|
||||||
|
} iptfs_flags_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private members of a child_create_t task.
|
* Private members of a child_create_t task.
|
||||||
*/
|
*/
|
||||||
@@ -207,6 +217,11 @@ struct private_child_create_t {
|
|||||||
*/
|
*/
|
||||||
ipcomp_transform_t ipcomp_received;
|
ipcomp_transform_t ipcomp_received;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP-TFS flags received from the peer
|
||||||
|
*/
|
||||||
|
uint8_t iptfs_flags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IPsec protocol
|
* IPsec protocol
|
||||||
*/
|
*/
|
||||||
@@ -571,6 +586,22 @@ static bool check_mode(private_child_create_t *this, host_t *i, host_t *r)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MODE_IPTFS:
|
||||||
|
if (this->config->get_mode(this->config) != MODE_IPTFS)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if ((this->iptfs_flags & IPTFS_CONGESTION_CONTROL) ||
|
||||||
|
(this->iptfs_flags & 0xfc))
|
||||||
|
{
|
||||||
|
/* congestion control is not supported, neither are any of
|
||||||
|
* the 6 reserved flags, so we disable IP-TFS if they are set */
|
||||||
|
DBG1(DBG_IKE, "not using IP-TFS mode, peer sent unsupported "
|
||||||
|
"flags (0x%.2x) in %N notify", this->iptfs_flags,
|
||||||
|
notify_type_names, USE_AGGFRAG);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -706,6 +737,10 @@ static status_t install_child_sa(private_child_create_t *this)
|
|||||||
|
|
||||||
this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
|
this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
|
||||||
this->child_sa->set_mode(this->child_sa, this->mode);
|
this->child_sa->set_mode(this->child_sa, this->mode);
|
||||||
|
if (this->mode == MODE_IPTFS && this->iptfs_flags & IPTFS_DONT_FRAGMENT)
|
||||||
|
{
|
||||||
|
this->child_sa->set_iptfs_dont_fragment(this->child_sa);
|
||||||
|
}
|
||||||
this->child_sa->set_protocol(this->child_sa,
|
this->child_sa->set_protocol(this->child_sa,
|
||||||
this->proposal->get_protocol(this->proposal));
|
this->proposal->get_protocol(this->proposal));
|
||||||
|
|
||||||
@@ -1073,6 +1108,19 @@ static bool build_payloads(private_child_create_t *this, message_t *message)
|
|||||||
case MODE_BEET:
|
case MODE_BEET:
|
||||||
message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
|
message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
|
||||||
break;
|
break;
|
||||||
|
case MODE_IPTFS:
|
||||||
|
{
|
||||||
|
uint8_t iptfs_flags = 0;
|
||||||
|
|
||||||
|
if (!lib->settings->get_bool(lib->settings,
|
||||||
|
"%s.iptfs.accept_fragments", TRUE, lib->ns))
|
||||||
|
{
|
||||||
|
iptfs_flags |= IPTFS_DONT_FRAGMENT;
|
||||||
|
}
|
||||||
|
message->add_notify(message, FALSE, USE_AGGFRAG,
|
||||||
|
chunk_from_thing(iptfs_flags));
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1126,6 +1174,8 @@ static void add_ipcomp_notify(private_child_create_t *this,
|
|||||||
*/
|
*/
|
||||||
static void handle_notify(private_child_create_t *this, notify_payload_t *notify)
|
static void handle_notify(private_child_create_t *this, notify_payload_t *notify)
|
||||||
{
|
{
|
||||||
|
chunk_t data;
|
||||||
|
|
||||||
switch (notify->get_notify_type(notify))
|
switch (notify->get_notify_type(notify))
|
||||||
{
|
{
|
||||||
case USE_TRANSPORT_MODE:
|
case USE_TRANSPORT_MODE:
|
||||||
@@ -1142,11 +1192,15 @@ static void handle_notify(private_child_create_t *this, notify_payload_t *notify
|
|||||||
"mode, but peer implementation unknown, skipped");
|
"mode, but peer implementation unknown, skipped");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case USE_AGGFRAG:
|
||||||
|
this->mode = MODE_IPTFS;
|
||||||
|
data = notify->get_notification_data(notify);
|
||||||
|
this->iptfs_flags = *data.ptr;
|
||||||
|
break;
|
||||||
case IPCOMP_SUPPORTED:
|
case IPCOMP_SUPPORTED:
|
||||||
{
|
{
|
||||||
ipcomp_transform_t ipcomp;
|
ipcomp_transform_t ipcomp;
|
||||||
uint16_t cpi;
|
uint16_t cpi;
|
||||||
chunk_t data;
|
|
||||||
|
|
||||||
data = notify->get_notification_data(notify);
|
data = notify->get_notification_data(notify);
|
||||||
cpi = *(uint16_t*)data.ptr;
|
cpi = *(uint16_t*)data.ptr;
|
||||||
|
|||||||
@@ -16,12 +16,13 @@
|
|||||||
|
|
||||||
#include "ipsec_types.h"
|
#include "ipsec_types.h"
|
||||||
|
|
||||||
ENUM(ipsec_mode_names, MODE_TRANSPORT, MODE_DROP,
|
ENUM(ipsec_mode_names, MODE_TRANSPORT, MODE_IPTFS,
|
||||||
"TRANSPORT",
|
"TRANSPORT",
|
||||||
"TUNNEL",
|
"TUNNEL",
|
||||||
"BEET",
|
"BEET",
|
||||||
"PASS",
|
"PASS",
|
||||||
"DROP"
|
"DROP",
|
||||||
|
"IPTFS",
|
||||||
);
|
);
|
||||||
|
|
||||||
ENUM(policy_dir_names, POLICY_IN, POLICY_FWD,
|
ENUM(policy_dir_names, POLICY_IN, POLICY_FWD,
|
||||||
|
|||||||
@@ -51,7 +51,9 @@ enum ipsec_mode_t {
|
|||||||
/** passthrough policy for traffic without an IPsec SA */
|
/** passthrough policy for traffic without an IPsec SA */
|
||||||
MODE_PASS,
|
MODE_PASS,
|
||||||
/** drop policy discarding traffic */
|
/** drop policy discarding traffic */
|
||||||
MODE_DROP
|
MODE_DROP,
|
||||||
|
/** IP-TFS mode, tunnel mode with aggregation/fragmentation */
|
||||||
|
MODE_IPTFS,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -920,12 +920,13 @@ connections.<conn>.children.<child>.hostaccess = no
|
|||||||
Hostaccess variable to pass to **updown** script.
|
Hostaccess variable to pass to **updown** script.
|
||||||
|
|
||||||
connections.<conn>.children.<child>.mode = tunnel
|
connections.<conn>.children.<child>.mode = tunnel
|
||||||
IPsec Mode to establish (_tunnel_, _transport_, _transport_proxy_, _beet_,
|
IPsec Mode to establish (_tunnel_, _transport_, _transport_proxy_, _iptfs_,
|
||||||
_pass_ or _drop_).
|
_beet_, _pass_ or _drop_).
|
||||||
|
|
||||||
IPsec Mode to establish CHILD_SA with. _tunnel_ negotiates the CHILD_SA
|
IPsec Mode to establish CHILD_SA with. _tunnel_ negotiates the CHILD_SA
|
||||||
in IPsec Tunnel Mode, whereas _transport_ uses IPsec Transport Mode.
|
in IPsec Tunnel Mode, whereas _transport_ uses IPsec Transport Mode.
|
||||||
_transport_proxy_ signifying the special Mobile IPv6 Transport Proxy Mode.
|
_transport_proxy_ signifying the special Mobile IPv6 Transport Proxy Mode.
|
||||||
|
_iptfs_ is IP-TFS tunnel mode with aggregation and fragmentation,
|
||||||
_beet_ is the Bound End to End Tunnel mixture mode, working with fixed inner
|
_beet_ is the Bound End to End Tunnel mixture mode, working with fixed inner
|
||||||
addresses without the need to include them in each packet.
|
addresses without the need to include them in each packet.
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+9
@@ -0,0 +1,9 @@
|
|||||||
|
A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up
|
||||||
|
enabling IP-TFS (RFC 9347) to aggregate small packets into a single ESP packets and
|
||||||
|
fragment large packets across multiple ESP packets.
|
||||||
|
The authentication is based on <b>X.509 certificates</b>.
|
||||||
|
<p/>
|
||||||
|
Upon the successful establishment of the IPsec tunnel, the updown script automatically
|
||||||
|
inserts iptables-based firewall rules that let pass the tunneled traffic.
|
||||||
|
In order to test both tunnel and firewall, client <b>alice</b> behind gateway <b>moon</b>
|
||||||
|
sends several pings to client <b>bob</b> located behind gateway <b>sun</b>.
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
moon::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=4500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net-net.*state=INSTALLED mode=IPTFS.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
|
||||||
|
sun:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=4500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net-net.*state=INSTALLED mode=IPTFS.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
|
||||||
|
alice::ping -c 4 -i 0.1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=.::4
|
||||||
|
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::1
|
||||||
|
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::1
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
swanctl {
|
||||||
|
load = pem pkcs1 revocation constraints pubkey openssl random
|
||||||
|
}
|
||||||
|
|
||||||
|
charon-systemd {
|
||||||
|
load = random nonce openssl pem pkcs1 revocation curl kernel-netlink socket-default updown vici
|
||||||
|
iptfs {
|
||||||
|
# set to 0.5 seconds for test purposes
|
||||||
|
init_delay = 500000
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
connections {
|
||||||
|
|
||||||
|
gw-gw {
|
||||||
|
local_addrs = 192.168.0.1
|
||||||
|
remote_addrs = 192.168.0.2
|
||||||
|
|
||||||
|
local {
|
||||||
|
auth = pubkey
|
||||||
|
certs = moonCert.pem
|
||||||
|
id = moon.strongswan.org
|
||||||
|
}
|
||||||
|
remote {
|
||||||
|
auth = pubkey
|
||||||
|
id = sun.strongswan.org
|
||||||
|
}
|
||||||
|
children {
|
||||||
|
net-net {
|
||||||
|
local_ts = 10.1.0.0/16
|
||||||
|
remote_ts = 10.2.0.0/16
|
||||||
|
|
||||||
|
mode = iptfs
|
||||||
|
|
||||||
|
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||||
|
hostaccess = yes
|
||||||
|
esp_proposals = aes128gcm128-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version = 2
|
||||||
|
proposals = aes128-sha256-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
swanctl {
|
||||||
|
load = pem pkcs1 revocation constraints pubkey openssl random
|
||||||
|
}
|
||||||
|
|
||||||
|
charon-systemd {
|
||||||
|
load = random nonce openssl pem pkcs1 revocation curl kernel-netlink socket-default updown vici
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
connections {
|
||||||
|
|
||||||
|
gw-gw {
|
||||||
|
local_addrs = 192.168.0.2
|
||||||
|
remote_addrs = 192.168.0.1
|
||||||
|
|
||||||
|
local {
|
||||||
|
auth = pubkey
|
||||||
|
certs = sunCert.pem
|
||||||
|
id = sun.strongswan.org
|
||||||
|
}
|
||||||
|
remote {
|
||||||
|
auth = pubkey
|
||||||
|
id = moon.strongswan.org
|
||||||
|
}
|
||||||
|
children {
|
||||||
|
net-net {
|
||||||
|
local_ts = 10.2.0.0/16
|
||||||
|
remote_ts = 10.1.0.0/16
|
||||||
|
|
||||||
|
mode = iptfs
|
||||||
|
|
||||||
|
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||||
|
esp_proposals = aes128gcm128-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version = 2
|
||||||
|
proposals = aes128-sha256-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
moon::systemctl stop strongswan
|
||||||
|
sun::systemctl stop strongswan
|
||||||
|
moon::iptables-restore < /etc/iptables.flush
|
||||||
|
sun::iptables-restore < /etc/iptables.flush
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
moon::iptables-restore < /etc/iptables.rules
|
||||||
|
sun::iptables-restore < /etc/iptables.rules
|
||||||
|
moon::systemctl start strongswan
|
||||||
|
sun::systemctl start strongswan
|
||||||
|
moon::expect-connection gw-gw
|
||||||
|
sun::expect-connection gw-gw
|
||||||
|
moon::swanctl --initiate --child net-net 2> /dev/null
|
||||||
Executable
+25
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# This configuration file provides information on the
|
||||||
|
# guest instances used for this test
|
||||||
|
|
||||||
|
# All guest instances that are required for this test
|
||||||
|
#
|
||||||
|
VIRTHOSTS="alice moon winnetou sun bob"
|
||||||
|
|
||||||
|
# Corresponding block diagram
|
||||||
|
#
|
||||||
|
DIAGRAM="a-m-w-s-b.png"
|
||||||
|
|
||||||
|
# Guest instances on which tcpdump is to be started
|
||||||
|
#
|
||||||
|
TCPDUMPHOSTS="sun"
|
||||||
|
|
||||||
|
# Guest instances on which IPsec is started
|
||||||
|
# Used for IPsec logging purposes
|
||||||
|
#
|
||||||
|
IPSECHOSTS="moon sun"
|
||||||
|
|
||||||
|
# charon controlled by swanctl
|
||||||
|
#
|
||||||
|
SWANCTL=1
|
||||||
Reference in New Issue
Block a user