From ad1f3e148224bced41afd47b0ab1ed158c07f399 Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Wed, 28 Nov 2018 21:26:34 -0800 Subject: [PATCH] NAT: syslog - sessions logging (VPP-1139) Change-Id: I6e0b7cf37c1a9ac66f8ac011db29504e57844ee9 Signed-off-by: Matus Fabian --- src/plugins/nat/CMakeLists.txt | 1 + src/plugins/nat/dslite_in2out.c | 14 +- src/plugins/nat/in2out.c | 11 ++ src/plugins/nat/in2out_ed.c | 16 +++ src/plugins/nat/nat.c | 15 +++ src/plugins/nat/nat.h | 3 + src/plugins/nat/nat64_db.c | 8 +- src/plugins/nat/nat_syslog.c | 290 ++++++++++++++++++++++++++++++++++++++++ src/plugins/nat/nat_syslog.h | 75 +++++++++++ src/plugins/nat/out2in.c | 11 ++ src/plugins/nat/out2in_ed.c | 21 +++ test/test_nat.py | 174 +++++++++++++++++++++++- 12 files changed, 636 insertions(+), 3 deletions(-) create mode 100644 src/plugins/nat/nat_syslog.c create mode 100644 src/plugins/nat/nat_syslog.h diff --git a/src/plugins/nat/CMakeLists.txt b/src/plugins/nat/CMakeLists.txt index 76662f96cf3..134aafed509 100644 --- a/src/plugins/nat/CMakeLists.txt +++ b/src/plugins/nat/CMakeLists.txt @@ -47,6 +47,7 @@ add_vpp_plugin(nat nat66_out2in.c nat_affinity.c nat_format.c + nat_syslog.c API_FILES nat.api diff --git a/src/plugins/nat/dslite_in2out.c b/src/plugins/nat/dslite_in2out.c index e7a3028f28a..5c1de19b8b2 100644 --- a/src/plugins/nat/dslite_in2out.c +++ b/src/plugins/nat/dslite_in2out.c @@ -14,6 +14,7 @@ */ #include #include +#include vlib_node_registration_t dslite_in2out_node; vlib_node_registration_t dslite_in2out_slowpath_node; @@ -45,6 +46,7 @@ slow_path (dslite_main_t * dm, dslite_session_key_t * in2out_key, u32 oldest_index; dslite_session_t *s; snat_session_key_t out2in_key; + u32 b4_index; out2in_key.protocol = in2out_key->proto; out2in_key.fib_index = 0; @@ -66,12 +68,13 @@ slow_path (dslite_main_t * dm, dslite_session_key_t * in2out_key, clib_dlist_init (dm->per_thread_data[thread_index].list_pool, b4->sessions_per_b4_list_head_index); - b4_kv.value = b4 - dm->per_thread_data[thread_index].b4s; + b4_index = b4_kv.value = b4 - dm->per_thread_data[thread_index].b4s; clib_bihash_add_del_16_8 (&dm->per_thread_data[thread_index].b4_hash, &b4_kv, 1); } else { + b4_index = b4_value.value; b4 = pool_elt_at_index (dm->per_thread_data[thread_index].b4s, b4_value.value); @@ -104,6 +107,11 @@ slow_path (dslite_main_t * dm, dslite_session_key_t * in2out_key, snat_free_outside_address_and_port (dm->addr_pool, thread_index, &s->out2in); + nat_syslog_dslite_apmdel (b4_index, &s->in2out.softwire_id, + &s->in2out.addr, s->in2out.port, + &s->out2in.addr, s->out2in.port, + s->in2out.proto); + if (snat_alloc_outside_address_and_port (dm->addr_pool, 0, thread_index, &out2in_key, dm->port_per_thread, thread_index)) @@ -147,6 +155,10 @@ slow_path (dslite_main_t * dm, dslite_session_key_t * in2out_key, clib_bihash_add_del_8_8 (&dm->per_thread_data[thread_index].out2in, &out2in_kv, 1); + nat_syslog_dslite_apmadd (b4_index, &s->in2out.softwire_id, &s->in2out.addr, + s->in2out.port, &s->out2in.addr, s->out2in.port, + s->in2out.proto); + return next; } diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c index d4432d98016..786d82147a7 100755 --- a/src/plugins/nat/in2out.c +++ b/src/plugins/nat/in2out.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -216,6 +217,11 @@ nat44_i2o_is_idle_session_cb (clib_bihash_kv_8_8_t * kv, void *arg) s->out2in.port, s->in2out.fib_index); + nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index, + &s->in2out.addr, s->in2out.port, + &s->out2in.addr, s->out2in.port, + s->in2out.protocol); + if (!snat_is_session_static (s)) snat_free_outside_address_and_port (sm->addresses, ctx->thread_index, &s->out2in); @@ -365,6 +371,11 @@ slow_path (snat_main_t * sm, vlib_buffer_t * b0, s->in2out.protocol, s->in2out.port, s->out2in.port, s->in2out.fib_index); + + nat_syslog_nat44_apmadd (s->user_index, s->in2out.fib_index, + &s->in2out.addr, s->in2out.port, &s->out2in.addr, + s->out2in.port, s->in2out.protocol); + return next0; } diff --git a/src/plugins/nat/in2out_ed.c b/src/plugins/nat/in2out_ed.c index c42d4e79f9e..ab253e8206b 100644 --- a/src/plugins/nat/in2out_ed.c +++ b/src/plugins/nat/in2out_ed.c @@ -28,6 +28,7 @@ #include #include #include +#include #define foreach_nat_in2out_ed_error \ _(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \ @@ -197,6 +198,13 @@ nat44_i2o_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg) s->out2in.port, s->in2out.fib_index); + nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index, + &s->in2out.addr, s->in2out.port, + &s->ext_host_nat_addr, s->ext_host_nat_port, + &s->out2in.addr, s->out2in.port, + &s->ext_host_addr, s->ext_host_port, + s->in2out.protocol, is_twice_nat_session (s)); + if (is_twice_nat_session (s)) { for (i = 0; i < vec_len (sm->twice_nat_addresses); i++) @@ -409,6 +417,14 @@ slow_path_ed (snat_main_t * sm, s->in2out.protocol, s->in2out.port, s->out2in.port, s->in2out.fib_index); + + nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index, + &s->in2out.addr, s->in2out.port, + &s->ext_host_nat_addr, s->ext_host_nat_port, + &s->out2in.addr, s->out2in.port, + &s->ext_host_addr, s->ext_host_port, + s->in2out.protocol, 0); + return next; } diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index b7ade881c3f..6bfea3c4162 100755 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -236,6 +237,13 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index) ed_kv.key[1] = ed_key.as_u64[1]; if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)) nat_log_warn ("in2out_ed key del failed"); + + nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index, + &s->in2out.addr, s->in2out.port, + &s->ext_host_nat_addr, s->ext_host_nat_port, + &s->out2in.addr, s->out2in.port, + &s->ext_host_addr, s->ext_host_port, + s->in2out.protocol, is_twice_nat_session (s)); } else { @@ -245,6 +253,11 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index) kv.key = s->out2in.as_u64; if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0)) nat_log_warn ("out2in key del failed"); + + nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index, + &s->in2out.addr, s->in2out.port, + &s->out2in.addr, s->out2in.port, + s->in2out.protocol); } if (snat_is_unk_proto_session (s)) @@ -382,6 +395,8 @@ nat_session_alloc_or_recycle (snat_main_t * sm, snat_user_t * u, clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index, per_user_translation_list_elt - tsm->list_pool); + + s->user_index = u - tsm->users; } return s; diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index 3162e41b696..3ce83ea2602 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -222,6 +222,9 @@ typedef CLIB_PACKED(struct u8 state; u32 i2o_fin_seq; u32 o2i_fin_seq; + + /* user index */ + u32 user_index; }) snat_session_t; /* *INDENT-ON* */ diff --git a/src/plugins/nat/nat64_db.c b/src/plugins/nat/nat64_db.c index bb327a57152..ca8358ef8a2 100644 --- a/src/plugins/nat/nat64_db.c +++ b/src/plugins/nat/nat64_db.c @@ -19,6 +19,7 @@ #include #include #include +#include #include int @@ -456,7 +457,9 @@ nat64_db_st_entry_create (nat64_db_t * db, nat64_db_bib_entry_t * bibe, &ste->in_r_addr, &ste->out_r_addr, ste->r_port, ste->r_port, fib->ft_table_id, 1); - + nat_syslog_nat64_sadd (bibe->fib_index, &bibe->in_addr, bibe->in_port, + &bibe->out_addr, bibe->out_port, &ste->out_r_addr, + ste->r_port, bibe->proto); return ste; } @@ -528,6 +531,9 @@ nat64_db_st_entry_free (nat64_db_t * db, nat64_db_st_entry_t * ste) &ste->in_r_addr, &ste->out_r_addr, ste->r_port, ste->r_port, fib->ft_table_id, 0); + nat_syslog_nat64_sdel (bibe->fib_index, &bibe->in_addr, bibe->in_port, + &bibe->out_addr, bibe->out_port, &ste->out_r_addr, + ste->r_port, bibe->proto); /* delete from pool */ pool_put (st, ste); diff --git a/src/plugins/nat/nat_syslog.c b/src/plugins/nat/nat_syslog.c new file mode 100644 index 00000000000..07fe2ea5808 --- /dev/null +++ b/src/plugins/nat/nat_syslog.c @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file + * @brief NAT syslog logging + */ + +#include +#include +#include + +#include +#include + + +#define NAT_FACILITY SYSLOG_FACILITY_LOCAL0 + +#define NAT_APPNAME "NAT" + +#define SADD_SDEL_SEVERITY SYSLOG_SEVERITY_INFORMATIONAL +#define APMADD_APMDEL_SEVERITY SYSLOG_SEVERITY_INFORMATIONAL + +#define SADD_MSGID "SADD" +#define SDEL_MSGID "SDEL" +#define APMADD_MSGID "APMADD" +#define APMDEL_MSGID "APMDEL" + +#define NSESS_SDID "nsess" +#define NAPMAP_SDID "napmap" + +#define SSUBIX_SDPARAM_NAME "SSUBIX" +#define SVLAN_SDPARAM_NAME "SVLAN" +#define IATYP_SDPARAM_NAME "IATYP" +#define ISADDR_SDPARAM_NAME "ISADDR" +#define ISPORT_SDPARAM_NAME "ISPORT" +#define IDADDR_SDPARAM_NAME "IDADDR" +#define IDPORT_SDPARAM_NAME "IDPORT" +#define XATYP_SDPARAM_NAME "XATYP" +#define XSADDR_SDPARAM_NAME "XSADDR" +#define XSPORT_SDPARAM_NAME "XSPORT" +#define XDADDR_SDPARAM_NAME "XDADDR" +#define XDPORT_SDPARAM_NAME "XDPORT" +#define PROTO_SDPARAM_NAME "PROTO" +#define SV6ENC_SDPARAM_NAME "SV6ENC" + +#define IATYP_IPV4 "IPv4" +#define IATYP_IPV6 "IPv6" + +static inline void +nat_syslog_nat44_apmap (u32 ssubix, u32 sfibix, ip4_address_t * isaddr, + u16 isport, ip4_address_t * xsaddr, u16 xsport, + snat_protocol_t proto, u8 is_add, + ip6_address_t * sv6enc) +{ + syslog_msg_t syslog_msg; + fib_table_t *fib; + + if (!syslog_is_enabled ()) + return; + + if (syslog_severity_filter_block (APMADD_APMDEL_SEVERITY)) + return; + + syslog_msg_init (&syslog_msg, NAT_FACILITY, APMADD_APMDEL_SEVERITY, + NAT_APPNAME, is_add ? APMADD_MSGID : APMDEL_MSGID); + + syslog_msg_sd_init (&syslog_msg, NAPMAP_SDID); + syslog_msg_add_sd_param (&syslog_msg, SSUBIX_SDPARAM_NAME, "%d", ssubix); + if (sv6enc) + { + syslog_msg_add_sd_param (&syslog_msg, SV6ENC_SDPARAM_NAME, "%U", + format_ip6_address, sv6enc); + } + else + { + fib = fib_table_get (sfibix, FIB_PROTOCOL_IP4); + syslog_msg_add_sd_param (&syslog_msg, SVLAN_SDPARAM_NAME, "%d", + fib->ft_table_id); + } + syslog_msg_add_sd_param (&syslog_msg, IATYP_SDPARAM_NAME, IATYP_IPV4); + syslog_msg_add_sd_param (&syslog_msg, ISADDR_SDPARAM_NAME, "%U", + format_ip4_address, isaddr); + syslog_msg_add_sd_param (&syslog_msg, ISPORT_SDPARAM_NAME, "%d", + clib_net_to_host_u16 (isport)); + syslog_msg_add_sd_param (&syslog_msg, XATYP_SDPARAM_NAME, IATYP_IPV4); + syslog_msg_add_sd_param (&syslog_msg, XSADDR_SDPARAM_NAME, "%U", + format_ip4_address, xsaddr); + syslog_msg_add_sd_param (&syslog_msg, XSPORT_SDPARAM_NAME, "%d", + clib_net_to_host_u16 (xsport)); + syslog_msg_add_sd_param (&syslog_msg, PROTO_SDPARAM_NAME, "%d", + snat_proto_to_ip_proto (proto)); + + syslog_msg_send (&syslog_msg); +} + +void +nat_syslog_nat44_apmadd (u32 ssubix, u32 sfibix, ip4_address_t * isaddr, + u16 isport, ip4_address_t * xsaddr, u16 xsport, + snat_protocol_t proto) +{ + nat_syslog_nat44_apmap (ssubix, sfibix, isaddr, isport, xsaddr, xsport, + proto, 1, 0); +} + +void +nat_syslog_nat44_apmdel (u32 ssubix, u32 sfibix, ip4_address_t * isaddr, + u16 isport, ip4_address_t * xsaddr, u16 xsport, + snat_protocol_t proto) +{ + nat_syslog_nat44_apmap (ssubix, sfibix, isaddr, isport, xsaddr, xsport, + proto, 0, 0); +} + +void +nat_syslog_dslite_apmadd (u32 ssubix, ip6_address_t * sv6enc, + ip4_address_t * isaddr, u16 isport, + ip4_address_t * xsaddr, u16 xsport, + snat_protocol_t proto) +{ + nat_syslog_nat44_apmap (ssubix, 0, isaddr, isport, xsaddr, xsport, + proto, 1, sv6enc); +} + +void +nat_syslog_dslite_apmdel (u32 ssubix, ip6_address_t * sv6enc, + ip4_address_t * isaddr, u16 isport, + ip4_address_t * xsaddr, u16 xsport, + snat_protocol_t proto) +{ + nat_syslog_nat44_apmap (ssubix, 0, isaddr, isport, xsaddr, xsport, + proto, 0, sv6enc); +} + +static inline void +nat_syslog_nat44_sess (u32 ssubix, u32 sfibix, ip4_address_t * isaddr, + u16 isport, ip4_address_t * xsaddr, u16 xsport, + ip4_address_t * idaddr, u16 idport, + ip4_address_t * xdaddr, u16 xdport, + snat_protocol_t proto, u8 is_add, u8 is_twicenat) +{ + syslog_msg_t syslog_msg; + fib_table_t *fib; + + if (!syslog_is_enabled ()) + return; + + if (syslog_severity_filter_block (SADD_SDEL_SEVERITY)) + return; + + fib = fib_table_get (sfibix, FIB_PROTOCOL_IP4); + + syslog_msg_init (&syslog_msg, NAT_FACILITY, SADD_SDEL_SEVERITY, NAT_APPNAME, + is_add ? SADD_MSGID : SDEL_MSGID); + + syslog_msg_sd_init (&syslog_msg, NSESS_SDID); + syslog_msg_add_sd_param (&syslog_msg, SSUBIX_SDPARAM_NAME, "%d", ssubix); + syslog_msg_add_sd_param (&syslog_msg, SVLAN_SDPARAM_NAME, "%d", + fib->ft_table_id); + syslog_msg_add_sd_param (&syslog_msg, IATYP_SDPARAM_NAME, IATYP_IPV4); + syslog_msg_add_sd_param (&syslog_msg, ISADDR_SDPARAM_NAME, "%U", + format_ip4_address, isaddr); + syslog_msg_add_sd_param (&syslog_msg, ISPORT_SDPARAM_NAME, "%d", + clib_net_to_host_u16 (isport)); + syslog_msg_add_sd_param (&syslog_msg, XATYP_SDPARAM_NAME, IATYP_IPV4); + syslog_msg_add_sd_param (&syslog_msg, XSADDR_SDPARAM_NAME, "%U", + format_ip4_address, xsaddr); + syslog_msg_add_sd_param (&syslog_msg, XSPORT_SDPARAM_NAME, "%d", + clib_net_to_host_u16 (xsport)); + syslog_msg_add_sd_param (&syslog_msg, PROTO_SDPARAM_NAME, "%d", + snat_proto_to_ip_proto (proto)); + syslog_msg_add_sd_param (&syslog_msg, XDADDR_SDPARAM_NAME, "%U", + format_ip4_address, xdaddr); + syslog_msg_add_sd_param (&syslog_msg, XDPORT_SDPARAM_NAME, "%d", + clib_net_to_host_u16 (xdport)); + if (is_twicenat) + { + syslog_msg_add_sd_param (&syslog_msg, IDADDR_SDPARAM_NAME, "%U", + format_ip4_address, idaddr); + syslog_msg_add_sd_param (&syslog_msg, IDPORT_SDPARAM_NAME, "%d", + clib_net_to_host_u16 (idport)); + } + + syslog_msg_send (&syslog_msg); +} + +void +nat_syslog_nat44_sadd (u32 ssubix, u32 sfibix, ip4_address_t * isaddr, + u16 isport, ip4_address_t * idaddr, u16 idport, + ip4_address_t * xsaddr, u16 xsport, + ip4_address_t * xdaddr, u16 xdport, + snat_protocol_t proto, u8 is_twicenat) +{ + nat_syslog_nat44_sess (ssubix, sfibix, isaddr, isport, xsaddr, xsport, + idaddr, idport, xdaddr, xdport, proto, 1, + is_twicenat); +} + +void +nat_syslog_nat44_sdel (u32 ssubix, u32 sfibix, ip4_address_t * isaddr, + u16 isport, ip4_address_t * idaddr, u16 idport, + ip4_address_t * xsaddr, u16 xsport, + ip4_address_t * xdaddr, u16 xdport, + snat_protocol_t proto, u8 is_twicenat) +{ + nat_syslog_nat44_sess (ssubix, sfibix, isaddr, isport, xsaddr, xsport, + idaddr, idport, xdaddr, xdport, proto, 0, + is_twicenat); +} + +static inline void +nat_syslog_nat64_sess (u32 sfibix, ip6_address_t * isaddr, u16 isport, + ip4_address_t * xsaddr, u16 xsport, + ip4_address_t * xdaddr, u16 xdport, + snat_protocol_t proto, u8 is_add) +{ + syslog_msg_t syslog_msg; + fib_table_t *fib; + + if (!syslog_is_enabled ()) + return; + + if (syslog_severity_filter_block (SADD_SDEL_SEVERITY)) + return; + + fib = fib_table_get (sfibix, FIB_PROTOCOL_IP6); + + syslog_msg_init (&syslog_msg, NAT_FACILITY, SADD_SDEL_SEVERITY, NAT_APPNAME, + is_add ? SADD_MSGID : SDEL_MSGID); + + syslog_msg_sd_init (&syslog_msg, NSESS_SDID); + syslog_msg_add_sd_param (&syslog_msg, SVLAN_SDPARAM_NAME, "%d", + fib->ft_table_id); + syslog_msg_add_sd_param (&syslog_msg, IATYP_SDPARAM_NAME, IATYP_IPV6); + syslog_msg_add_sd_param (&syslog_msg, ISADDR_SDPARAM_NAME, "%U", + format_ip6_address, isaddr); + syslog_msg_add_sd_param (&syslog_msg, ISPORT_SDPARAM_NAME, "%d", + clib_net_to_host_u16 (isport)); + syslog_msg_add_sd_param (&syslog_msg, XATYP_SDPARAM_NAME, IATYP_IPV4); + syslog_msg_add_sd_param (&syslog_msg, XSADDR_SDPARAM_NAME, "%U", + format_ip4_address, xsaddr); + syslog_msg_add_sd_param (&syslog_msg, XSPORT_SDPARAM_NAME, "%d", + clib_net_to_host_u16 (xsport)); + syslog_msg_add_sd_param (&syslog_msg, PROTO_SDPARAM_NAME, "%d", proto); + syslog_msg_add_sd_param (&syslog_msg, XDADDR_SDPARAM_NAME, "%U", + format_ip4_address, xdaddr); + syslog_msg_add_sd_param (&syslog_msg, XDPORT_SDPARAM_NAME, "%d", + clib_net_to_host_u16 (xdport)); + + syslog_msg_send (&syslog_msg); +} + +void +nat_syslog_nat64_sadd (u32 sfibix, ip6_address_t * isaddr, u16 isport, + ip4_address_t * xsaddr, u16 xsport, + ip4_address_t * xdaddr, u16 xdport, + snat_protocol_t proto) +{ + nat_syslog_nat64_sess (sfibix, isaddr, isport, xsaddr, xsport, xdaddr, + xdport, proto, 1); +} + +void +nat_syslog_nat64_sdel (u32 sfibix, ip6_address_t * isaddr, u16 isport, + ip4_address_t * xsaddr, u16 xsport, + ip4_address_t * xdaddr, u16 xdport, + snat_protocol_t proto) +{ + nat_syslog_nat64_sess (sfibix, isaddr, isport, xsaddr, xsport, xdaddr, + xdport, proto, 0); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/nat/nat_syslog.h b/src/plugins/nat/nat_syslog.h new file mode 100644 index 00000000000..15a891fd0c0 --- /dev/null +++ b/src/plugins/nat/nat_syslog.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file + * @brief NAT syslog logging + */ + +#ifndef __included_nat_syslog_h__ +#define __included_nat_syslog_h__ + +#include + +void nat_syslog_nat44_apmadd (u32 ssubix, u32 sfibix, ip4_address_t * isaddr, + u16 isport, ip4_address_t * xsaddr, u16 xsport, + snat_protocol_t proto); + +void nat_syslog_nat44_apmdel (u32 ssubix, u32 sfibix, ip4_address_t * isaddr, + u16 isport, ip4_address_t * xsaddr, u16 xsport, + snat_protocol_t proto); + +void +nat_syslog_dslite_apmadd (u32 ssubix, ip6_address_t * sv6enc, + ip4_address_t * isaddr, u16 isport, + ip4_address_t * xsaddr, u16 xsport, + snat_protocol_t proto); + +void +nat_syslog_dslite_apmdel (u32 ssubix, ip6_address_t * sv6enc, + ip4_address_t * isaddr, u16 isport, + ip4_address_t * xsaddr, u16 xsport, + snat_protocol_t proto); + +void nat_syslog_nat44_sadd (u32 ssubix, u32 sfibix, ip4_address_t * isaddr, + u16 isport, ip4_address_t * idaddr, u16 idport, + ip4_address_t * xsaddr, u16 xsport, + ip4_address_t * xdaddr, u16 xdport, + snat_protocol_t proto, u8 is_twicenat); + +void nat_syslog_nat44_sdel (u32 ssubix, u32 sfibix, ip4_address_t * isaddr, + u16 isport, ip4_address_t * idaddr, u16 idport, + ip4_address_t * xsaddr, u16 xsport, + ip4_address_t * xdaddr, u16 xdport, + snat_protocol_t proto, u8 is_twicenat); + +void nat_syslog_nat64_sadd (u32 sfibix, ip6_address_t * isaddr, u16 isport, + ip4_address_t * xsaddr, u16 xsport, + ip4_address_t * xdaddr, u16 xdport, + snat_protocol_t proto); + +void nat_syslog_nat64_sdel (u32 sfibix, ip6_address_t * isaddr, u16 isport, + ip4_address_t * xsaddr, u16 xsport, + ip4_address_t * xdaddr, u16 xdport, + snat_protocol_t proto); + +#endif /* __included_nat_syslog_h__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/nat/out2in.c b/src/plugins/nat/out2in.c index 52f2023efe1..74d20888f57 100755 --- a/src/plugins/nat/out2in.c +++ b/src/plugins/nat/out2in.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -132,6 +133,11 @@ nat44_o2i_is_idle_session_cb (clib_bihash_kv_8_8_t * kv, void *arg) s->out2in.port, s->in2out.fib_index); + nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index, + &s->in2out.addr, s->in2out.port, + &s->out2in.addr, s->out2in.port, + s->in2out.protocol); + if (!snat_is_session_static (s)) snat_free_outside_address_and_port (sm->addresses, ctx->thread_index, &s->out2in); @@ -229,6 +235,11 @@ create_session_for_static_mapping (snat_main_t * sm, s->in2out.protocol, s->in2out.port, s->out2in.port, s->in2out.fib_index); + + nat_syslog_nat44_apmadd (s->user_index, s->in2out.fib_index, + &s->in2out.addr, s->in2out.port, &s->out2in.addr, + s->out2in.port, s->in2out.protocol); + return s; } diff --git a/src/plugins/nat/out2in_ed.c b/src/plugins/nat/out2in_ed.c index aa7f7e40117..f76fc60bda0 100644 --- a/src/plugins/nat/out2in_ed.c +++ b/src/plugins/nat/out2in_ed.c @@ -29,6 +29,7 @@ #include #include #include +#include #define foreach_nat_out2in_ed_error \ _(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \ @@ -173,6 +174,13 @@ nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg) s->out2in.port, s->in2out.fib_index); + nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index, + &s->in2out.addr, s->in2out.port, + &s->ext_host_nat_addr, s->ext_host_nat_port, + &s->out2in.addr, s->out2in.port, + &s->ext_host_addr, s->ext_host_port, + s->in2out.protocol, is_twice_nat_session (s)); + if (is_twice_nat_session (s)) { for (i = 0; i < vec_len (sm->twice_nat_addresses); i++) @@ -303,6 +311,19 @@ create_session_for_static_mapping_ed (snat_main_t * sm, &ctx)) nat_log_notice ("in2out-ed key add failed"); + snat_ipfix_logging_nat44_ses_create (s->in2out.addr.as_u32, + s->out2in.addr.as_u32, + s->in2out.protocol, + s->in2out.port, + s->out2in.port, s->in2out.fib_index); + + nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index, + &s->in2out.addr, s->in2out.port, + &s->ext_host_nat_addr, s->ext_host_nat_port, + &s->out2in.addr, s->out2in.port, + &s->ext_host_addr, s->ext_host_port, + s->in2out.protocol, is_twice_nat_session (s)); + return s; } diff --git a/test/test_nat.py b/test/test_nat.py index 59d98d94569..b7b80c95c2a 100644 --- a/test/test_nat.py +++ b/test/test_nat.py @@ -21,6 +21,9 @@ from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder from time import sleep from util import ip4_range from util import mactobinary +from syslog_rfc5424_parser import SyslogMessage, ParseError +from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity +from vpp_papi_provider import SYSLOG_SEVERITY class MethodHolder(VppTestCase): @@ -69,6 +72,8 @@ class MethodHolder(VppTestCase): self.ipfix_src_port = 4739 self.ipfix_domain_id = 1 + self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG) + interfaces = self.vapi.nat44_interface_dump() for intf in interfaces: if intf.is_inside > 1: @@ -1031,6 +1036,55 @@ class MethodHolder(VppTestCase): # sourceIPv4Address self.assertEqual(src_addr, record[8]) + def verify_syslog_apmap(self, data, is_add=True): + message = data.decode('utf-8') + try: + message = SyslogMessage.parse(message) + self.assertEqual(message.severity, SyslogSeverity.info) + self.assertEqual(message.appname, 'NAT') + self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL') + sd_params = message.sd.get('napmap') + self.assertTrue(sd_params is not None) + self.assertEqual(sd_params.get('IATYP'), 'IPv4') + self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4) + self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in) + self.assertEqual(sd_params.get('XATYP'), 'IPv4') + self.assertEqual(sd_params.get('XSADDR'), self.nat_addr) + self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out) + self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp) + self.assertTrue(sd_params.get('SSUBIX') is not None) + self.assertEqual(sd_params.get('SVLAN'), '0') + except ParseError as e: + self.logger.error(e) + + def verify_syslog_sess(self, data, is_add=True, is_ip6=False): + message = data.decode('utf-8') + try: + message = SyslogMessage.parse(message) + self.assertEqual(message.severity, SyslogSeverity.info) + self.assertEqual(message.appname, 'NAT') + self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL') + sd_params = message.sd.get('nsess') + self.assertTrue(sd_params is not None) + if is_ip6: + self.assertEqual(sd_params.get('IATYP'), 'IPv6') + self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6) + else: + self.assertEqual(sd_params.get('IATYP'), 'IPv4') + self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4) + self.assertTrue(sd_params.get('SSUBIX') is not None) + self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in) + self.assertEqual(sd_params.get('XATYP'), 'IPv4') + self.assertEqual(sd_params.get('XSADDR'), self.nat_addr) + self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out) + self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp) + self.assertEqual(sd_params.get('SVLAN'), '0') + self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4) + self.assertEqual(sd_params.get('XDPORT'), + "%d" % self.tcp_external_port) + except ParseError as e: + self.logger.error(e) + def verify_mss_value(self, pkt, mss): """ Verify TCP MSS value @@ -2687,6 +2741,32 @@ class TestNAT44(MethodHolder): data = ipfix.decode_data_set(p.getlayer(Set)) self.verify_ipfix_max_sessions(data, max_sessions) + def test_syslog_apmap(self): + """ Test syslog address and port mapping creation and deletion """ + self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO) + self.vapi.syslog_set_sender(self.pg3.remote_ip4n, self.pg3.local_ip4n) + self.nat44_add_address(self.nat_addr) + self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index) + self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index, + is_inside=0) + + p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / + IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) / + TCP(sport=self.tcp_port_in, dport=20)) + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(1) + self.tcp_port_out = capture[0][TCP].sport + capture = self.pg3.get_capture(1) + self.verify_syslog_apmap(capture[0][Raw].load) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + self.nat44_add_address(self.nat_addr, is_add=0) + capture = self.pg3.get_capture(1) + self.verify_syslog_apmap(capture[0][Raw].load, False) + def test_pool_addr_fib(self): """ NAT44 add pool addresses to FIB """ static_addr = '10.0.0.10' @@ -5777,6 +5857,32 @@ class TestNAT44EndpointDependent(MethodHolder): self.pg_start() self.pg1.get_capture(1) + def test_syslog_sess(self): + """ Test syslog session creation and deletion """ + self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO) + self.vapi.syslog_set_sender(self.pg2.remote_ip4n, self.pg2.local_ip4n) + self.nat44_add_address(self.nat_addr) + self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index) + self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index, + is_inside=0) + + p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / + IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) / + TCP(sport=self.tcp_port_in, dport=self.tcp_external_port)) + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(1) + self.tcp_port_out = capture[0][TCP].sport + capture = self.pg2.get_capture(1) + self.verify_syslog_sess(capture[0][Raw].load) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + self.nat44_add_address(self.nat_addr, is_add=0) + capture = self.pg2.get_capture(1) + self.verify_syslog_sess(capture[0][Raw].load, False) + def tearDown(self): super(TestNAT44EndpointDependent, self).tearDown() if not self.vpp_dead: @@ -6524,6 +6630,7 @@ class TestNAT64(MethodHolder): cls.udp_port_out = 6304 cls.icmp_id_in = 6305 cls.icmp_id_out = 6305 + cls.tcp_external_port = 80 cls.nat_addr = '10.0.0.3' cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr) cls.vrf1_id = 10 @@ -7726,6 +7833,39 @@ class TestNAT64(MethodHolder): else: self.logger.error(ppp("Unexpected or invalid packet: ", p)) + def test_syslog_sess(self): + """ Test syslog session creation and deletion """ + self.tcp_port_in = random.randint(1025, 65535) + remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4, + '64:ff9b::', + 96) + + self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n, + self.nat_addr_n) + self.vapi.nat64_add_del_interface(self.pg0.sw_if_index) + self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0) + self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO) + self.vapi.syslog_set_sender(self.pg3.remote_ip4n, self.pg3.local_ip4n) + + p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / + IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) / + TCP(sport=self.tcp_port_in, dport=self.tcp_external_port)) + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + p = self.pg1.get_capture(1) + self.tcp_port_out = p[0][TCP].sport + capture = self.pg3.get_capture(1) + self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n, + self.nat_addr_n, + is_add=0) + capture = self.pg3.get_capture(1) + self.verify_syslog_sess(capture[0][Raw].load, False, True) + def nat64_get_ses_num(self): """ Return number of active NAT64 sessions. @@ -7742,6 +7882,8 @@ class TestNAT64(MethodHolder): self.ipfix_src_port = 4739 self.ipfix_domain_id = 1 + self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG) + self.vapi.nat_set_timeouts() interfaces = self.vapi.nat64_interface_dump() @@ -7802,7 +7944,7 @@ class TestDSlite(MethodHolder): cls.nat_addr = '10.0.0.3' cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr) - cls.create_pg_interfaces(range(2)) + cls.create_pg_interfaces(range(3)) cls.pg0.admin_up() cls.pg0.config_ip4() cls.pg0.resolve_arp() @@ -7810,11 +7952,36 @@ class TestDSlite(MethodHolder): cls.pg1.config_ip6() cls.pg1.generate_remote_hosts(2) cls.pg1.configure_ipv6_neighbors() + cls.pg2.admin_up() + cls.pg2.config_ip4() + cls.pg2.resolve_arp() except Exception: super(TestDSlite, cls).tearDownClass() raise + def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport, + sv6enc, proto): + message = data.decode('utf-8') + try: + message = SyslogMessage.parse(message) + self.assertEqual(message.severity, SyslogSeverity.info) + self.assertEqual(message.appname, 'NAT') + self.assertEqual(message.msgid, 'APMADD') + sd_params = message.sd.get('napmap') + self.assertTrue(sd_params is not None) + self.assertEqual(sd_params.get('IATYP'), 'IPv4') + self.assertEqual(sd_params.get('ISADDR'), isaddr) + self.assertEqual(sd_params.get('ISPORT'), "%d" % isport) + self.assertEqual(sd_params.get('XATYP'), 'IPv4') + self.assertEqual(sd_params.get('XSADDR'), xsaddr) + self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport) + self.assertEqual(sd_params.get('PROTO'), "%d" % proto) + self.assertTrue(sd_params.get('SSUBIX') is not None) + self.assertEqual(sd_params.get('SV6ENC'), sv6enc) + except ParseError as e: + self.logger.error(e) + def test_dslite(self): """ Test DS-Lite """ nat_config = self.vapi.nat_show_config() @@ -7827,6 +7994,7 @@ class TestDSlite(MethodHolder): aftr_ip6 = '2001:db8:85a3::8a2e:370:1' aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6) self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n) + self.vapi.syslog_set_sender(self.pg2.remote_ip4n, self.pg2.local_ip4n) # UDP p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / @@ -7845,6 +8013,10 @@ class TestDSlite(MethodHolder): self.assertEqual(capture[UDP].dport, 10000) self.assert_packet_checksums_valid(capture) out_port = capture[UDP].sport + capture = self.pg2.get_capture(1) + self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1', + 20000, self.nat_addr, out_port, + self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp) p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(dst=self.nat_addr, src=self.pg0.remote_ip4) / -- 2.16.6