ipsec: User can choose the UDP source port
Type: feature thus allowing NAT traversal, Signed-off-by: Neale Ranns <nranns@cisco.com> Change-Id: Ie8650ceeb5074f98c68d2d90f6adc2f18afeba08 Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
This commit is contained in:
committed by
Paul Vinciguerra
parent
6fdd7a5f77
commit
abc5660c61
@@ -1566,13 +1566,13 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
|
||||
IPSEC_PROTOCOL_ESP, a->encr_type,
|
||||
&a->loc_ckey, a->integ_type, &a->loc_ikey,
|
||||
a->flags, 0, a->salt_local, &a->local_ip,
|
||||
&a->remote_ip, NULL, a->dst_port);
|
||||
&a->remote_ip, NULL, a->dst_port, a->dst_port);
|
||||
rv |= ipsec_sa_add_and_lock (a->remote_sa_id, a->remote_spi,
|
||||
IPSEC_PROTOCOL_ESP, a->encr_type, &a->rem_ckey,
|
||||
a->integ_type, &a->rem_ikey,
|
||||
(a->flags | IPSEC_SA_FLAG_IS_INBOUND), 0,
|
||||
a->salt_remote, &a->remote_ip,
|
||||
&a->local_ip, NULL, a->dst_port);
|
||||
&a->local_ip, NULL, a->dst_port, a->dst_port);
|
||||
|
||||
rv |= ipsec_tun_protect_update (sw_if_index, NULL, a->local_sa_id, sas_in);
|
||||
}
|
||||
|
||||
@@ -124,6 +124,61 @@ ipsec_add_node (vlib_main_t * vm, const char *node_name,
|
||||
*out_next_index = vlib_node_add_next (vm, prev_node->index, node->index);
|
||||
}
|
||||
|
||||
void
|
||||
ipsec_add_feature (const char *arc_name,
|
||||
const char *node_name, u32 * out_feature_index)
|
||||
{
|
||||
u8 arc;
|
||||
|
||||
arc = vnet_get_feature_arc_index (arc_name);
|
||||
ASSERT (arc != (u8) ~ 0);
|
||||
*out_feature_index = vnet_get_feature_index (arc, node_name);
|
||||
}
|
||||
|
||||
void
|
||||
ipsec_unregister_udp_port (u16 port)
|
||||
{
|
||||
ipsec_main_t *im = &ipsec_main;
|
||||
u32 n_regs;
|
||||
uword *p;
|
||||
|
||||
p = hash_get (im->udp_port_registrations, port);
|
||||
|
||||
ASSERT (p);
|
||||
|
||||
n_regs = p[0];
|
||||
|
||||
if (0 == --n_regs)
|
||||
{
|
||||
udp_unregister_dst_port (vlib_get_main (), port, 1);
|
||||
hash_unset (im->udp_port_registrations, port);
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_unset (im->udp_port_registrations, port);
|
||||
hash_set (im->udp_port_registrations, port, n_regs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipsec_register_udp_port (u16 port)
|
||||
{
|
||||
ipsec_main_t *im = &ipsec_main;
|
||||
u32 n_regs;
|
||||
uword *p;
|
||||
|
||||
p = hash_get (im->udp_port_registrations, port);
|
||||
|
||||
n_regs = (p ? p[0] : 0);
|
||||
|
||||
if (0 == n_regs++)
|
||||
udp_register_dst_port (vlib_get_main (), port,
|
||||
ipsec4_tun_input_node.index, 1);
|
||||
|
||||
hash_unset (im->udp_port_registrations, port);
|
||||
hash_set (im->udp_port_registrations, port, n_regs);
|
||||
}
|
||||
|
||||
u32
|
||||
ipsec_register_ah_backend (vlib_main_t * vm, ipsec_main_t * im,
|
||||
const char *name,
|
||||
|
||||
+12
-2
@@ -108,6 +108,9 @@ typedef struct
|
||||
/* pool of policies */
|
||||
ipsec_policy_t *policies;
|
||||
|
||||
/* hash tables of UDP port registrations */
|
||||
uword *udp_port_registrations;
|
||||
|
||||
uword *tunnel_index_by_key;
|
||||
|
||||
/* convenience */
|
||||
@@ -225,8 +228,8 @@ extern vlib_node_registration_t esp4_encrypt_tun_node;
|
||||
extern vlib_node_registration_t esp6_encrypt_tun_node;
|
||||
extern vlib_node_registration_t esp4_decrypt_tun_node;
|
||||
extern vlib_node_registration_t esp6_decrypt_tun_node;
|
||||
extern vlib_node_registration_t ipsec4_if_input_node;
|
||||
extern vlib_node_registration_t ipsec6_if_input_node;
|
||||
extern vlib_node_registration_t ipsec4_tun_input_node;
|
||||
extern vlib_node_registration_t ipsec6_tun_input_node;
|
||||
|
||||
/*
|
||||
* functions
|
||||
@@ -284,6 +287,13 @@ ipsec_sa_get (u32 sa_index)
|
||||
return (pool_elt_at_index (ipsec_main.sad, sa_index));
|
||||
}
|
||||
|
||||
void ipsec_add_feature (const char *arc_name, const char *node_name,
|
||||
u32 * out_feature_index);
|
||||
|
||||
void ipsec_set_async_mode (u32 is_enabled);
|
||||
extern void ipsec_register_udp_port (u16 udp_port);
|
||||
extern void ipsec_unregister_udp_port (u16 udp_port);
|
||||
|
||||
#endif /* __IPSEC_H__ */
|
||||
|
||||
/*
|
||||
|
||||
@@ -374,7 +374,8 @@ static void vl_api_ipsec_sad_entry_add_del_t_handler
|
||||
crypto_alg, &crypto_key,
|
||||
integ_alg, &integ_key, flags,
|
||||
0, mp->entry.salt, &tun_src, &tun_dst,
|
||||
&sa_index, IPSEC_UDP_PORT_NONE);
|
||||
&sa_index, htons (mp->entry.udp_src_port),
|
||||
htons (mp->entry.udp_dst_port));
|
||||
else
|
||||
rv = ipsec_sa_unlock_id (id);
|
||||
|
||||
@@ -665,7 +666,7 @@ vl_api_ipsec_tunnel_if_add_del_t_handler (vl_api_ipsec_tunnel_if_add_del_t *
|
||||
(flags | IPSEC_SA_FLAG_IS_INBOUND),
|
||||
ntohl (mp->tx_table_id),
|
||||
mp->salt, &remote_ip, &local_ip, NULL,
|
||||
IPSEC_UDP_PORT_NONE);
|
||||
IPSEC_UDP_PORT_NONE, IPSEC_UDP_PORT_NONE);
|
||||
|
||||
if (rv)
|
||||
goto done;
|
||||
@@ -680,7 +681,7 @@ vl_api_ipsec_tunnel_if_add_del_t_handler (vl_api_ipsec_tunnel_if_add_del_t *
|
||||
flags,
|
||||
ntohl (mp->tx_table_id),
|
||||
mp->salt, &local_ip, &remote_ip, NULL,
|
||||
IPSEC_UDP_PORT_NONE);
|
||||
IPSEC_UDP_PORT_NONE, IPSEC_UDP_PORT_NONE);
|
||||
|
||||
if (rv)
|
||||
goto done;
|
||||
@@ -816,6 +817,11 @@ send_ipsec_sa_details (ipsec_sa_t * sa, void *arg)
|
||||
ip_address_encode (&sa->tunnel_dst_addr, IP46_TYPE_ANY,
|
||||
&mp->entry.tunnel_dst);
|
||||
}
|
||||
if (ipsec_sa_is_set_UDP_ENCAP (sa))
|
||||
{
|
||||
mp->entry.udp_src_port = sa->udp_hdr.src_port;
|
||||
mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
|
||||
}
|
||||
|
||||
mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
|
||||
mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
|
||||
|
||||
@@ -86,7 +86,8 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
|
||||
clib_error_t *error;
|
||||
ipsec_key_t ck = { 0 };
|
||||
ipsec_key_t ik = { 0 };
|
||||
u32 id, spi, salt;
|
||||
u32 id, spi, salt, sai;
|
||||
u16 udp_src, udp_dst;
|
||||
int is_add, rv;
|
||||
|
||||
salt = 0;
|
||||
@@ -96,6 +97,7 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
|
||||
proto = IPSEC_PROTOCOL_ESP;
|
||||
integ_alg = IPSEC_INTEG_ALG_NONE;
|
||||
crypto_alg = IPSEC_CRYPTO_ALG_NONE;
|
||||
udp_src = udp_dst = IPSEC_UDP_PORT_NONE;
|
||||
|
||||
if (!unformat_user (input, unformat_line_input, line_input))
|
||||
return 0;
|
||||
@@ -149,8 +151,7 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
|
||||
rv = ipsec_sa_add_and_lock (id, spi, proto, crypto_alg,
|
||||
&ck, integ_alg, &ik, flags,
|
||||
0, clib_host_to_net_u32 (salt),
|
||||
&tun_src, &tun_dst, NULL,
|
||||
IPSEC_UDP_PORT_NONE);
|
||||
&tun_src, &tun_dst, &sai, udp_src, udp_dst);
|
||||
else
|
||||
rv = ipsec_sa_unlock_id (id);
|
||||
|
||||
@@ -856,14 +857,16 @@ create_ipsec_tunnel_command_fn (vlib_main_t * vm,
|
||||
local_spi, IPSEC_PROTOCOL_ESP, crypto_alg,
|
||||
&lck, integ_alg, &lik, flags, table_id,
|
||||
clib_host_to_net_u32 (salt), &local_ip,
|
||||
&remote_ip, NULL, IPSEC_UDP_PORT_NONE);
|
||||
&remote_ip, NULL, IPSEC_UDP_PORT_NONE,
|
||||
IPSEC_UDP_PORT_NONE);
|
||||
rv |=
|
||||
ipsec_sa_add_and_lock (ipsec_tun_mk_remote_sa_id (sw_if_index),
|
||||
remote_spi, IPSEC_PROTOCOL_ESP, crypto_alg,
|
||||
&rck, integ_alg, &rik,
|
||||
(flags | IPSEC_SA_FLAG_IS_INBOUND), table_id,
|
||||
clib_host_to_net_u32 (salt), &remote_ip,
|
||||
&local_ip, NULL, IPSEC_UDP_PORT_NONE);
|
||||
&local_ip, NULL, IPSEC_UDP_PORT_NONE,
|
||||
IPSEC_UDP_PORT_NONE);
|
||||
rv |=
|
||||
ipsec_tun_protect_update_one (sw_if_index, &nh,
|
||||
ipsec_tun_mk_local_sa_id (sw_if_index),
|
||||
|
||||
@@ -310,6 +310,9 @@ format_ipsec_sa (u8 * s, va_list * args)
|
||||
s = format (s, " key %U", format_ipsec_key, &sa->integ_key);
|
||||
else
|
||||
s = format (s, " key [redacted]");
|
||||
s = format (s, "\n UDP:[src:%d dst:%d]",
|
||||
clib_host_to_net_u16 (sa->udp_hdr.src_port),
|
||||
clib_host_to_net_u16 (sa->udp_hdr.dst_port));
|
||||
|
||||
vlib_get_combined_counter (&ipsec_sa_counters, sai, &counts);
|
||||
s = format (s, "\n packets %u bytes %u", counts.packets, counts.bytes);
|
||||
|
||||
@@ -179,7 +179,7 @@ ipsec_sa_add_and_lock (u32 id,
|
||||
u32 salt,
|
||||
const ip46_address_t * tun_src,
|
||||
const ip46_address_t * tun_dst, u32 * sa_out_index,
|
||||
u16 dst_port)
|
||||
u16 src_port, u16 dst_port)
|
||||
{
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
ipsec_main_t *im = &ipsec_main;
|
||||
@@ -329,15 +329,17 @@ ipsec_sa_add_and_lock (u32 id,
|
||||
if (ipsec_sa_is_set_UDP_ENCAP (sa))
|
||||
{
|
||||
if (dst_port == IPSEC_UDP_PORT_NONE)
|
||||
{
|
||||
sa->udp_hdr.src_port = clib_host_to_net_u16 (UDP_DST_PORT_ipsec);
|
||||
sa->udp_hdr.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_ipsec);
|
||||
}
|
||||
sa->udp_hdr.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_ipsec);
|
||||
else
|
||||
{
|
||||
sa->udp_hdr.src_port = clib_host_to_net_u16 (dst_port);
|
||||
sa->udp_hdr.dst_port = clib_host_to_net_u16 (dst_port);
|
||||
}
|
||||
sa->udp_hdr.dst_port = clib_host_to_net_u16 (dst_port);
|
||||
|
||||
if (src_port == IPSEC_UDP_PORT_NONE)
|
||||
sa->udp_hdr.src_port = clib_host_to_net_u16 (UDP_DST_PORT_ipsec);
|
||||
else
|
||||
sa->udp_hdr.src_port = clib_host_to_net_u16 (src_port);
|
||||
|
||||
if (ipsec_sa_is_set_IS_INBOUND (sa))
|
||||
ipsec_register_udp_port (clib_host_to_net_u16 (sa->udp_hdr.dst_port));
|
||||
}
|
||||
|
||||
hash_set (im->sa_index_by_sa_id, sa->id, sa_index);
|
||||
@@ -361,6 +363,9 @@ ipsec_sa_del (ipsec_sa_t * sa)
|
||||
/* no recovery possible when deleting an SA */
|
||||
(void) ipsec_call_add_del_callbacks (im, sa, sa_index, 0);
|
||||
|
||||
if (ipsec_sa_is_set_UDP_ENCAP (sa) && ipsec_sa_is_set_IS_INBOUND (sa))
|
||||
ipsec_unregister_udp_port (clib_net_to_host_u16 (sa->udp_hdr.dst_port));
|
||||
|
||||
if (ipsec_sa_is_set_IS_TUNNEL (sa) && !ipsec_sa_is_set_IS_INBOUND (sa))
|
||||
{
|
||||
fib_entry_untrack (sa->fib_entry_index, sa->sibling);
|
||||
|
||||
@@ -250,7 +250,7 @@ extern int ipsec_sa_add_and_lock (u32 id,
|
||||
u32 salt,
|
||||
const ip46_address_t * tunnel_src_addr,
|
||||
const ip46_address_t * tunnel_dst_addr,
|
||||
u32 * sa_index, u16 dst_port);
|
||||
u32 * sa_index, u16 src_port, u16 dst_port);
|
||||
extern index_t ipsec_sa_find_and_lock (u32 id);
|
||||
extern int ipsec_sa_unlock_id (u32 id);
|
||||
extern void ipsec_sa_unlock (index_t sai);
|
||||
|
||||
@@ -91,9 +91,7 @@ ipsec_tun_register_nodes (ip_address_family_t af)
|
||||
{
|
||||
if (AF_IP4 == af)
|
||||
{
|
||||
udp_register_dst_port (vlib_get_main (),
|
||||
UDP_DST_PORT_ipsec,
|
||||
ipsec4_tun_input_node.index, 1);
|
||||
ipsec_register_udp_port (UDP_DST_PORT_ipsec);
|
||||
ip4_register_protocol (IP_PROTOCOL_IPSEC_ESP,
|
||||
ipsec4_tun_input_node.index);
|
||||
}
|
||||
@@ -111,7 +109,7 @@ ipsec_tun_unregister_nodes (ip_address_family_t af)
|
||||
{
|
||||
if (AF_IP4 == af)
|
||||
{
|
||||
udp_unregister_dst_port (vlib_get_main (), UDP_DST_PORT_ipsec, 1);
|
||||
ipsec_unregister_udp_port (UDP_DST_PORT_ipsec);
|
||||
ip4_unregister_protocol (IP_PROTOCOL_IPSEC_ESP);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -104,6 +104,10 @@ typedef key
|
||||
@param tunnel_dst_address - IPsec tunnel destination address IPv6 if is_tunnel_ipv6 is non-zero, else IPv4. Only valid if is_tunnel is non-zero
|
||||
@param tx_table_id - the FIB id used for encapsulated packets
|
||||
@param salt - for use with counter mode ciphers
|
||||
@param udp_src_port - If using UDP Encapsulation, use this source port for
|
||||
TX. It is ignored for RX.
|
||||
@param udp_dst_port - If using UDP Encapsulation, use this destination port
|
||||
for TX. Expect traffic on this port for RX.
|
||||
*/
|
||||
typedef ipsec_sad_entry
|
||||
{
|
||||
@@ -125,6 +129,8 @@ typedef ipsec_sad_entry
|
||||
vl_api_address_t tunnel_dst;
|
||||
u32 tx_table_id;
|
||||
u32 salt;
|
||||
u16 udp_src_port [default=4500];
|
||||
u16 udp_dst_port [default=4500];
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,6 +2,14 @@ diff --git a/scapy/layers/ipsec.py b/scapy/layers/ipsec.py
|
||||
index f8c601fa..f566d288 100644
|
||||
--- a/scapy/layers/ipsec.py
|
||||
+++ b/scapy/layers/ipsec.py
|
||||
@@ -138,6 +138,7 @@ bind_layers(IP, ESP, proto=socket.IPPROTO_ESP)
|
||||
bind_layers(IPv6, ESP, nh=socket.IPPROTO_ESP)
|
||||
bind_layers(UDP, ESP, dport=4500) # NAT-Traversal encapsulation
|
||||
bind_layers(UDP, ESP, sport=4500) # NAT-Traversal encapsulation
|
||||
+bind_layers(UDP, ESP, dport=4545) # NAT-Traversal encapsulation - random port
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -359,11 +359,8 @@ class CryptAlgo(object):
|
||||
encryptor = cipher.encryptor()
|
||||
|
||||
@@ -147,7 +155,7 @@ index f8c601fa..f566d288 100644
|
||||
|
||||
esp = self.crypt_algo.decrypt(self, encrypted, self.crypt_key,
|
||||
self.crypt_algo.icv_size or
|
||||
@@ -1050,9 +1069,10 @@ class SecurityAssociation(object):
|
||||
@@ -1050,11 +1069,12 @@ class SecurityAssociation(object):
|
||||
|
||||
def _decrypt_ah(self, pkt, verify=True):
|
||||
|
||||
@@ -160,3 +168,4 @@ index f8c601fa..f566d288 100644
|
||||
ah = pkt[AH]
|
||||
payload = ah.payload
|
||||
|
||||
|
||||
|
||||
+38
-13
@@ -70,23 +70,48 @@ class IpsecApiTestCase(VppTestCase):
|
||||
crypt_algo_vpp_id = params.crypt_algo_vpp_id
|
||||
crypt_key = params.crypt_key
|
||||
|
||||
self.vapi.ipsec_sad_entry_add_del(scapy_tun_sa_id, scapy_tun_spi,
|
||||
auth_algo_vpp_id, auth_key,
|
||||
crypt_algo_vpp_id, crypt_key,
|
||||
self.vpp_ah_protocol,
|
||||
self.pg0.local_addr[addr_type],
|
||||
self.pg0.remote_addr[addr_type])
|
||||
self.vapi.ipsec_sad_entry_add_del(
|
||||
is_add=1,
|
||||
entry={
|
||||
'sad_id': scapy_tun_sa_id,
|
||||
'spi': scapy_tun_spi,
|
||||
'integrity_algorithm': auth_algo_vpp_id,
|
||||
'integrity_key': {
|
||||
'data': auth_key,
|
||||
'length': len(auth_key),
|
||||
},
|
||||
'crypto_algorithm': crypt_algo_vpp_id,
|
||||
'crypto_key': {
|
||||
'data': crypt_key,
|
||||
'length': len(crypt_key),
|
||||
},
|
||||
'protocol': self.vpp_ah_protocol,
|
||||
'tunnel_src': self.pg0.local_addr[addr_type],
|
||||
'tunnel_dst': self.pg0.remote_addr[addr_type]
|
||||
})
|
||||
with self.vapi.assert_negative_api_retval():
|
||||
self.vapi.ipsec_select_backend(
|
||||
protocol=self.vpp_ah_protocol, index=0)
|
||||
|
||||
self.vapi.ipsec_sad_entry_add_del(scapy_tun_sa_id, scapy_tun_spi,
|
||||
auth_algo_vpp_id, auth_key,
|
||||
crypt_algo_vpp_id, crypt_key,
|
||||
self.vpp_ah_protocol,
|
||||
self.pg0.local_addr[addr_type],
|
||||
self.pg0.remote_addr[addr_type],
|
||||
is_add=0)
|
||||
self.vapi.ipsec_sad_entry_add_del(
|
||||
is_add=0,
|
||||
entry={
|
||||
'sad_id': scapy_tun_sa_id,
|
||||
'spi': scapy_tun_spi,
|
||||
'integrity_algorithm': auth_algo_vpp_id,
|
||||
'integrity_key': {
|
||||
'data': auth_key,
|
||||
'length': len(auth_key),
|
||||
},
|
||||
'crypto_algorithm': crypt_algo_vpp_id,
|
||||
'crypto_key': {
|
||||
'data': crypt_key,
|
||||
'length': len(crypt_key),
|
||||
},
|
||||
'protocol': self.vpp_ah_protocol,
|
||||
'tunnel_src': self.pg0.local_addr[addr_type],
|
||||
'tunnel_dst': self.pg0.remote_addr[addr_type]
|
||||
})
|
||||
self.vapi.ipsec_select_backend(
|
||||
protocol=self.vpp_ah_protocol, index=0)
|
||||
|
||||
|
||||
@@ -64,13 +64,15 @@ def config_tra_params(p, encryption_type, tun_if):
|
||||
crypt_algo=p.crypt_algo,
|
||||
crypt_key=crypt_key,
|
||||
auth_algo=p.auth_algo, auth_key=p.auth_key,
|
||||
esn_en=esn_en)
|
||||
esn_en=esn_en,
|
||||
nat_t_header=p.nat_header)
|
||||
p.vpp_tun_sa = SecurityAssociation(
|
||||
encryption_type, spi=p.scapy_tun_spi,
|
||||
crypt_algo=p.crypt_algo,
|
||||
crypt_key=crypt_key,
|
||||
auth_algo=p.auth_algo, auth_key=p.auth_key,
|
||||
esn_en=esn_en)
|
||||
esn_en=esn_en,
|
||||
nat_t_header=p.nat_header)
|
||||
|
||||
|
||||
class TemplateIpsec4TunIfEsp(TemplateIpsec):
|
||||
@@ -1060,6 +1062,127 @@ class TestIpsecGreTebIfEspTra(TemplateIpsec,
|
||||
super(TestIpsecGreTebIfEspTra, self).tearDown()
|
||||
|
||||
|
||||
class TestIpsecGreTebUdpIfEspTra(TemplateIpsec,
|
||||
IpsecTun4Tests):
|
||||
""" Ipsec GRE TEB UDP ESP - Tra tests """
|
||||
tun4_encrypt_node_name = "esp4-encrypt-tun"
|
||||
tun4_decrypt_node_name = "esp4-decrypt-tun"
|
||||
encryption_type = ESP
|
||||
omac = "00:11:22:33:44:55"
|
||||
|
||||
def gen_encrypt_pkts(self, p, sa, sw_intf, src, dst, count=1,
|
||||
payload_size=100):
|
||||
return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
|
||||
sa.encrypt(IP(src=self.pg0.remote_ip4,
|
||||
dst=self.pg0.local_ip4) /
|
||||
GRE() /
|
||||
Ether(dst=self.omac) /
|
||||
IP(src="1.1.1.1", dst="1.1.1.2") /
|
||||
UDP(sport=1144, dport=2233) /
|
||||
Raw(b'X' * payload_size))
|
||||
for i in range(count)]
|
||||
|
||||
def gen_pkts(self, sw_intf, src, dst, count=1,
|
||||
payload_size=100):
|
||||
return [Ether(dst=self.omac) /
|
||||
IP(src="1.1.1.1", dst="1.1.1.2") /
|
||||
UDP(sport=1144, dport=2233) /
|
||||
Raw(b'X' * payload_size)
|
||||
for i in range(count)]
|
||||
|
||||
def verify_decrypted(self, p, rxs):
|
||||
for rx in rxs:
|
||||
self.assert_equal(rx[Ether].dst, self.omac)
|
||||
self.assert_equal(rx[IP].dst, "1.1.1.2")
|
||||
|
||||
def verify_encrypted(self, p, sa, rxs):
|
||||
for rx in rxs:
|
||||
self.assertTrue(rx.haslayer(UDP))
|
||||
self.assertEqual(rx[UDP].dport, 4545)
|
||||
self.assertEqual(rx[UDP].sport, 5454)
|
||||
try:
|
||||
pkt = sa.decrypt(rx[IP])
|
||||
if not pkt.haslayer(IP):
|
||||
pkt = IP(pkt[Raw].load)
|
||||
self.assert_packet_checksums_valid(pkt)
|
||||
self.assert_equal(pkt[IP].dst, self.pg0.remote_ip4)
|
||||
self.assert_equal(pkt[IP].src, self.pg0.local_ip4)
|
||||
self.assertTrue(pkt.haslayer(GRE))
|
||||
e = pkt[Ether]
|
||||
self.assertEqual(e[Ether].dst, self.omac)
|
||||
self.assertEqual(e[IP].dst, "1.1.1.2")
|
||||
except (IndexError, AssertionError):
|
||||
self.logger.debug(ppp("Unexpected packet:", rx))
|
||||
try:
|
||||
self.logger.debug(ppp("Decrypted packet:", pkt))
|
||||
except:
|
||||
pass
|
||||
raise
|
||||
|
||||
def setUp(self):
|
||||
super(TestIpsecGreTebUdpIfEspTra, self).setUp()
|
||||
|
||||
self.tun_if = self.pg0
|
||||
|
||||
p = self.ipv4_params
|
||||
p = self.ipv4_params
|
||||
p.flags = (VppEnum.vl_api_ipsec_sad_flags_t.
|
||||
IPSEC_API_SAD_FLAG_UDP_ENCAP)
|
||||
p.nat_header = UDP(sport=5454, dport=4545)
|
||||
|
||||
bd1 = VppBridgeDomain(self, 1)
|
||||
bd1.add_vpp_config()
|
||||
|
||||
p.tun_sa_out = VppIpsecSA(self, p.scapy_tun_sa_id, p.scapy_tun_spi,
|
||||
p.auth_algo_vpp_id, p.auth_key,
|
||||
p.crypt_algo_vpp_id, p.crypt_key,
|
||||
self.vpp_esp_protocol,
|
||||
flags=p.flags,
|
||||
udp_src=5454,
|
||||
udp_dst=4545)
|
||||
p.tun_sa_out.add_vpp_config()
|
||||
|
||||
p.tun_sa_in = VppIpsecSA(self, p.vpp_tun_sa_id, p.vpp_tun_spi,
|
||||
p.auth_algo_vpp_id, p.auth_key,
|
||||
p.crypt_algo_vpp_id, p.crypt_key,
|
||||
self.vpp_esp_protocol,
|
||||
flags=(p.flags |
|
||||
VppEnum.vl_api_ipsec_sad_flags_t.
|
||||
IPSEC_API_SAD_FLAG_IS_INBOUND),
|
||||
udp_src=5454,
|
||||
udp_dst=4545)
|
||||
p.tun_sa_in.add_vpp_config()
|
||||
|
||||
p.tun_if = VppGreInterface(self,
|
||||
self.pg0.local_ip4,
|
||||
self.pg0.remote_ip4,
|
||||
type=(VppEnum.vl_api_gre_tunnel_type_t.
|
||||
GRE_API_TUNNEL_TYPE_TEB))
|
||||
p.tun_if.add_vpp_config()
|
||||
|
||||
p.tun_protect = VppIpsecTunProtect(self,
|
||||
p.tun_if,
|
||||
p.tun_sa_out,
|
||||
[p.tun_sa_in])
|
||||
|
||||
p.tun_protect.add_vpp_config()
|
||||
|
||||
p.tun_if.admin_up()
|
||||
p.tun_if.config_ip4()
|
||||
config_tra_params(p, self.encryption_type, p.tun_if)
|
||||
|
||||
VppBridgeDomainPort(self, bd1, p.tun_if).add_vpp_config()
|
||||
VppBridgeDomainPort(self, bd1, self.pg1).add_vpp_config()
|
||||
|
||||
self.vapi.cli("clear ipsec sa")
|
||||
self.logger.info(self.vapi.cli("sh ipsec sa 0"))
|
||||
|
||||
def tearDown(self):
|
||||
p = self.ipv4_params
|
||||
p.tun_if.unconfig_ip4()
|
||||
super(TestIpsecGreTebUdpIfEspTra, self).tearDown()
|
||||
|
||||
|
||||
class TestIpsecGreIfEsp(TemplateIpsec,
|
||||
IpsecTun4Tests):
|
||||
""" Ipsec GRE ESP - TUN tests """
|
||||
@@ -1799,7 +1922,7 @@ class TestIpsec4TunProtectUdp(TemplateIpsec,
|
||||
p = self.ipv4_params
|
||||
p.flags = (VppEnum.vl_api_ipsec_sad_flags_t.
|
||||
IPSEC_API_SAD_FLAG_UDP_ENCAP)
|
||||
p.nat_header = UDP(sport=5454, dport=4500)
|
||||
p.nat_header = UDP(sport=4500, dport=4500)
|
||||
self.config_network(p)
|
||||
self.config_sa_tra(p)
|
||||
self.config_protect(p)
|
||||
@@ -1811,6 +1934,13 @@ class TestIpsec4TunProtectUdp(TemplateIpsec,
|
||||
self.unconfig_network(p)
|
||||
super(TestIpsec4TunProtectUdp, self).tearDown()
|
||||
|
||||
def verify_encrypted(self, p, sa, rxs):
|
||||
# ensure encrypted packets are recieved with the default UDP ports
|
||||
for rx in rxs:
|
||||
self.assertEqual(rx[UDP].sport, 4500)
|
||||
self.assertEqual(rx[UDP].dport, 4500)
|
||||
super(TestIpsec4TunProtectUdp, self).verify_encrypted(p, sa, rxs)
|
||||
|
||||
def test_tun_44(self):
|
||||
"""IPSEC UDP tunnel protect"""
|
||||
|
||||
|
||||
+71
-25
@@ -184,12 +184,15 @@ class VppIpsecSA(VppObject):
|
||||
VPP SAD Entry
|
||||
"""
|
||||
|
||||
DEFAULT_UDP_PORT = 4500
|
||||
|
||||
def __init__(self, test, id, spi,
|
||||
integ_alg, integ_key,
|
||||
crypto_alg, crypto_key,
|
||||
proto,
|
||||
tun_src=None, tun_dst=None,
|
||||
flags=None, salt=0):
|
||||
flags=None, salt=0, udp_src=None,
|
||||
udp_dst=None):
|
||||
e = VppEnum.vl_api_ipsec_sad_flags_t
|
||||
self.test = test
|
||||
self.id = id
|
||||
@@ -214,44 +217,87 @@ class VppIpsecSA(VppObject):
|
||||
self.flags = self.flags | e.IPSEC_API_SAD_FLAG_IS_TUNNEL_V6
|
||||
if (tun_dst):
|
||||
self.tun_dst = ip_address(text_type(tun_dst))
|
||||
self.udp_src = udp_src
|
||||
self.udp_dst = udp_dst
|
||||
|
||||
def add_vpp_config(self):
|
||||
r = self.test.vapi.ipsec_sad_entry_add_del(
|
||||
self.id,
|
||||
self.spi,
|
||||
self.integ_alg,
|
||||
self.integ_key,
|
||||
self.crypto_alg,
|
||||
self.crypto_key,
|
||||
self.proto,
|
||||
(self.tun_src if self.tun_src else []),
|
||||
(self.tun_dst if self.tun_dst else []),
|
||||
flags=self.flags,
|
||||
salt=self.salt)
|
||||
entry = {
|
||||
'sad_id': self.id,
|
||||
'spi': self.spi,
|
||||
'integrity_algorithm': self.integ_alg,
|
||||
'integrity_key': {
|
||||
'length': len(self.integ_key),
|
||||
'data': self.integ_key,
|
||||
},
|
||||
'crypto_algorithm': self.crypto_alg,
|
||||
'crypto_key': {
|
||||
'data': self.crypto_key,
|
||||
'length': len(self.crypto_key),
|
||||
},
|
||||
'protocol': self.proto,
|
||||
'tunnel_src': (self.tun_src if self.tun_src else []),
|
||||
'tunnel_dst': (self.tun_dst if self.tun_dst else []),
|
||||
'flags': self.flags,
|
||||
'salt': self.salt
|
||||
}
|
||||
# don't explicitly send the defaults, let papi fill them in
|
||||
if self.udp_src:
|
||||
entry['udp_src_port'] = self.udp_src
|
||||
if self.udp_dst:
|
||||
entry['udp_dst_port'] = self.udp_dst
|
||||
r = self.test.vapi.ipsec_sad_entry_add_del(is_add=1, entry=entry)
|
||||
self.stat_index = r.stat_index
|
||||
self.test.registry.register(self, self.test.logger)
|
||||
|
||||
def remove_vpp_config(self):
|
||||
self.test.vapi.ipsec_sad_entry_add_del(
|
||||
self.id,
|
||||
self.spi,
|
||||
self.integ_alg,
|
||||
self.integ_key,
|
||||
self.crypto_alg,
|
||||
self.crypto_key,
|
||||
self.proto,
|
||||
(self.tun_src if self.tun_src else []),
|
||||
(self.tun_dst if self.tun_dst else []),
|
||||
flags=self.flags,
|
||||
is_add=0)
|
||||
r = self.test.vapi.ipsec_sad_entry_add_del(
|
||||
is_add=0,
|
||||
entry={
|
||||
'sad_id': self.id,
|
||||
'spi': self.spi,
|
||||
'integrity_algorithm': self.integ_alg,
|
||||
'integrity_key': {
|
||||
'length': len(self.integ_key),
|
||||
'data': self.integ_key,
|
||||
},
|
||||
'crypto_algorithm': self.crypto_alg,
|
||||
'crypto_key': {
|
||||
'data': self.crypto_key,
|
||||
'length': len(self.crypto_key),
|
||||
},
|
||||
'protocol': self.proto,
|
||||
'tunnel_src': (self.tun_src if self.tun_src else []),
|
||||
'tunnel_dst': (self.tun_dst if self.tun_dst else []),
|
||||
'flags': self.flags,
|
||||
'salt': self.salt
|
||||
})
|
||||
|
||||
def object_id(self):
|
||||
return "ipsec-sa-%d" % self.id
|
||||
|
||||
def query_vpp_config(self):
|
||||
e = VppEnum.vl_api_ipsec_sad_flags_t
|
||||
|
||||
bs = self.test.vapi.ipsec_sa_dump()
|
||||
for b in bs:
|
||||
if b.entry.sad_id == self.id:
|
||||
# if udp encap is configured then the ports should match
|
||||
# those configured or the default
|
||||
if (self.flags & e.IPSEC_API_SAD_FLAG_UDP_ENCAP):
|
||||
if not b.entry.flags & e.IPSEC_API_SAD_FLAG_UDP_ENCAP:
|
||||
return False
|
||||
if self.udp_src:
|
||||
if self.udp_src != b.entry.udp_src_port:
|
||||
return False
|
||||
else:
|
||||
if self.DEFAULT_UDP_PORT != b.entry.udp_src_port:
|
||||
return False
|
||||
if self.udp_dst:
|
||||
if self.udp_dst != b.entry.udp_dst_port:
|
||||
return False
|
||||
else:
|
||||
if self.DEFAULT_UDP_PORT != b.entry.udp_dst_port:
|
||||
return False
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ defaultmapping = {
|
||||
'ip_punt_redirect': {'is_add': 1, },
|
||||
'ip_route_add_del': {'is_add': 1, },
|
||||
'ipsec_interface_add_del_spd': {'is_add': 1, },
|
||||
'ipsec_sad_entry_add_del': {'is_add': 1, },
|
||||
'ipsec_spd_add_del': {'is_add': 1, },
|
||||
'ipsec_spd_dump': {'sa_id': 4294967295, },
|
||||
'ipsec_spd_entry_add_del': {'local_port_stop': 65535,
|
||||
@@ -947,60 +946,6 @@ class VppPapiProvider(object):
|
||||
{'spd_index': spd_index if spd_index else 0,
|
||||
'spd_index_valid': 1 if spd_index else 0})
|
||||
|
||||
def ipsec_sad_entry_add_del(self,
|
||||
sad_id,
|
||||
spi,
|
||||
integrity_algorithm,
|
||||
integrity_key,
|
||||
crypto_algorithm,
|
||||
crypto_key,
|
||||
protocol,
|
||||
tunnel_src_address='',
|
||||
tunnel_dst_address='',
|
||||
flags=0,
|
||||
salt=0,
|
||||
is_add=1):
|
||||
""" IPSEC SA add/del
|
||||
:param sad_id: security association ID
|
||||
:param spi: security param index of the SA in decimal
|
||||
:param integrity_algorithm:
|
||||
:param integrity_key:
|
||||
:param crypto_algorithm:
|
||||
:param crypto_key:
|
||||
:param protocol: AH(0) or ESP(1) protocol
|
||||
:param tunnel_src_address: tunnel mode outer src address
|
||||
:param tunnel_dst_address: tunnel mode outer dst address
|
||||
:param is_add:
|
||||
:param is_tunnel:
|
||||
:** reference /vpp/src/vnet/ipsec/ipsec.h file for enum values of
|
||||
crypto and ipsec algorithms
|
||||
"""
|
||||
return self.api(
|
||||
self.papi.ipsec_sad_entry_add_del,
|
||||
{
|
||||
'is_add': is_add,
|
||||
'entry':
|
||||
{
|
||||
'sad_id': sad_id,
|
||||
'spi': spi,
|
||||
'tunnel_src': tunnel_src_address,
|
||||
'tunnel_dst': tunnel_dst_address,
|
||||
'protocol': protocol,
|
||||
'integrity_algorithm': integrity_algorithm,
|
||||
'integrity_key': {
|
||||
'length': len(integrity_key),
|
||||
'data': integrity_key,
|
||||
},
|
||||
'crypto_algorithm': crypto_algorithm,
|
||||
'crypto_key': {
|
||||
'length': len(crypto_key),
|
||||
'data': crypto_key,
|
||||
},
|
||||
'flags': flags,
|
||||
'salt': salt,
|
||||
}
|
||||
})
|
||||
|
||||
def ipsec_sa_dump(self, sa_id=None):
|
||||
return self.api(self.papi.ipsec_sa_dump,
|
||||
{'sa_id': sa_id if sa_id else 0xffffffff})
|
||||
|
||||
Reference in New Issue
Block a user