ipsec: Fix decap of IPSEC/GRE in transport mode

Type: fix

in transport mode the header sequence is:
  MAC - IP (tun) - ESP - GRE - L2
so popping the GRE header is done in the ESP decrypt node.

Change-Id: Ia125eb65b9300368617d2bffca09683851e43be0
Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
Neale Ranns
2019-12-18 05:54:40 +00:00
parent 6461b7a319
commit 568acbb7c9
2 changed files with 169 additions and 7 deletions

View File

@ -24,10 +24,13 @@
#include <vnet/ipsec/ipsec_io.h>
#include <vnet/ipsec/ipsec_tun.h>
#include <vnet/gre/gre.h>
#define foreach_esp_decrypt_next \
_(DROP, "error-drop") \
_(IP4_INPUT, "ip4-input-no-checksum") \
_(IP6_INPUT, "ip6-input") \
_(L2_INPUT, "l2-input") \
_(HANDOFF, "handoff")
#define _(v, s) ESP_DECRYPT_NEXT_##v,
@ -487,9 +490,40 @@ esp_decrypt_inline (vlib_main_t * vm,
}
else
{
next[0] = ESP_DECRYPT_NEXT_DROP;
b[0]->error = node->errors[ESP_DECRYPT_ERROR_DECRYPTION_FAILED];
goto trace;
if (is_tun && f->next_header == IP_PROTOCOL_GRE)
{
gre_header_t *gre;
b[0]->current_data = pd->current_data + adv;
b[0]->current_length = pd->current_length - adv - tail;
gre = vlib_buffer_get_current (b[0]);
vlib_buffer_advance (b[0], sizeof (*gre));
switch (clib_net_to_host_u16 (gre->protocol))
{
case GRE_PROTOCOL_teb:
next[0] = ESP_DECRYPT_NEXT_L2_INPUT;
break;
case GRE_PROTOCOL_ip4:
next[0] = ESP_DECRYPT_NEXT_IP4_INPUT;
break;
case GRE_PROTOCOL_ip6:
next[0] = ESP_DECRYPT_NEXT_IP6_INPUT;
break;
default:
next[0] = ESP_DECRYPT_NEXT_DROP;
break;
}
}
else
{
next[0] = ESP_DECRYPT_NEXT_DROP;
b[0]->error =
node->errors[ESP_DECRYPT_ERROR_DECRYPTION_FAILED];
goto trace;
}
}
if (is_tun)
{
@ -501,9 +535,9 @@ esp_decrypt_inline (vlib_main_t * vm,
*/
const ipsec_tun_protect_t *itp;
itp =
ipsec_tun_protect_get (vnet_buffer (b[0])->
ipsec.protect_index);
itp = ipsec_tun_protect_get
(vnet_buffer (b[0])->ipsec.protect_index);
if (PREDICT_TRUE (f->next_header == IP_PROTOCOL_IP_IN_IP))
{
const ip4_header_t *ip4;
@ -614,6 +648,7 @@ VLIB_REGISTER_NODE (esp4_decrypt_node) = {
[ESP_DECRYPT_NEXT_DROP] = "ip4-drop",
[ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
[ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
[ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
[ESP_DECRYPT_NEXT_HANDOFF] = "esp4-decrypt-handoff",
},
};
@ -632,6 +667,7 @@ VLIB_REGISTER_NODE (esp6_decrypt_node) = {
[ESP_DECRYPT_NEXT_DROP] = "ip6-drop",
[ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
[ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
[ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
[ESP_DECRYPT_NEXT_HANDOFF]= "esp6-decrypt-handoff",
},
};
@ -648,6 +684,7 @@ VLIB_REGISTER_NODE (esp4_decrypt_tun_node) = {
[ESP_DECRYPT_NEXT_DROP] = "ip4-drop",
[ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
[ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
[ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
[ESP_DECRYPT_NEXT_HANDOFF] = "esp4-decrypt-handoff",
},
};
@ -664,6 +701,7 @@ VLIB_REGISTER_NODE (esp6_decrypt_tun_node) = {
[ESP_DECRYPT_NEXT_DROP] = "ip6-drop",
[ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
[ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
[ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
[ESP_DECRYPT_NEXT_HANDOFF]= "esp6-decrypt-handoff",
},
};

View File

@ -47,6 +47,25 @@ def config_tun_params(p, encryption_type, tun_if):
esn_en=esn_en)
def config_tra_params(p, encryption_type, tun_if):
ip_class_by_addr_type = {socket.AF_INET: IP, socket.AF_INET6: IPv6}
esn_en = bool(p.flags & (VppEnum.vl_api_ipsec_sad_flags_t.
IPSEC_API_SAD_FLAG_USE_ESN))
crypt_key = mk_scapy_crypt_key(p)
p.scapy_tun_sa = SecurityAssociation(
encryption_type, spi=p.vpp_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)
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)
class TemplateIpsec4TunIfEsp(TemplateIpsec):
""" IPsec tunnel interface tests """
@ -657,6 +676,111 @@ class TestIpsecGreTebIfEsp(TemplateIpsec,
super(TestIpsecGreTebIfEsp, self).tearDown()
class TestIpsecGreTebIfEspTra(TemplateIpsec,
IpsecTun4Tests):
""" Ipsec GRE TEB 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, 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:
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(TestIpsecGreTebIfEspTra, self).setUp()
self.tun_if = self.pg0
p = self.ipv4_params
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)
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)
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")
def tearDown(self):
p = self.ipv4_params
p.tun_if.unconfig_ip4()
super(TestIpsecGreTebIfEspTra, self).tearDown()
class TestIpsecGreIfEsp(TemplateIpsec,
IpsecTun4Tests):
""" Ipsec GRE ESP - TUN tests """
@ -845,7 +969,7 @@ class TestIpsecGreIfEspTra(TemplateIpsec,
p.tun_if.admin_up()
p.tun_if.config_ip4()
config_tun_params(p, self.encryption_type, p.tun_if)
config_tra_params(p, self.encryption_type, p.tun_if)
VppIpRoute(self, "1.1.1.2", 32,
[VppRoutePath(p.tun_if.remote_ip4,