From f3b3e73eba1dba81aa35f477d6a20ebdd54cf7a8 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 18 Jun 2012 12:29:49 -0500 Subject: [PATCH 1/5] Script-layer tunnel interface cleanup. - Clarify "tunnel_changed" event documentation. - Make expiration of "Tunnel::active" elements configuration via "Tunnel::expiration_interval". - Remove redundant registration of a connection's tunnels in tunnel/main.bro's "tunnel_changed" handler. - Rename "parents" field of "Conn::Info" to "tunnel_parents" to give more context. --- scripts/base/frameworks/tunnels/main.bro | 15 +++++++++------ scripts/base/protocols/conn/main.bro | 6 +++--- src/event.bif | 8 +++++--- .../Baseline/core.print-bpf-filters/conn.log | 2 +- .../btest/Baseline/core.print-bpf-filters/output | 8 ++++---- .../btest/Baseline/core.tunnels.ayiya/conn.log | 2 +- .../btest/Baseline/core.tunnels.socks/conn.log | 2 +- .../btest/Baseline/core.tunnels.teredo/conn.log | 2 +- testing/btest/Baseline/core.vlan-mpls/conn.log | 2 +- .../scripts.base.protocols.ftp.ftp-ipv4/conn.log | 2 +- .../scripts.base.protocols.ftp.ftp-ipv6/conn.log | 2 +- 11 files changed, 28 insertions(+), 23 deletions(-) diff --git a/scripts/base/frameworks/tunnels/main.bro b/scripts/base/frameworks/tunnels/main.bro index 1f0258e0a3..2f5625f8b2 100644 --- a/scripts/base/frameworks/tunnels/main.bro +++ b/scripts/base/frameworks/tunnels/main.bro @@ -17,7 +17,8 @@ export { DISCOVER, ## A tunnel connection has closed. CLOSE, - ## No new connections over a tunnel happened in the past day. + ## No new connections over a tunnel happened in the amount of + ## time indicated by :bro:see:`Tunnel::expiration_interval`. EXPIRE, }; @@ -68,9 +69,14 @@ export { ## action: The specific reason for the tunnel ending. global close: function(tunnel: Info, action: Action); + ## The amount of time a tunnel is not used in establishment of new + ## connections before it is considered inactive/expired. + const expiration_interval = 24hrs &redef; + ## Currently active tunnels. That is, tunnels for which new, encapsulated - ## connections have been seen in the last day. - global active: table[conn_id] of Info = table() &synchronized &read_expire=24hrs &expire_func=expire; + ## connections have been seen in the interval indicated by + ## :bro:see:`Tunnel::expiration_interval`. + global active: table[conn_id] of Info = table() &synchronized &read_expire=expiration_interval &expire_func=expire; } const ayiya_ports = { 5072/udp }; @@ -129,9 +135,6 @@ event new_connection(c: connection) &priority=5 event tunnel_changed(c: connection, e: EncapsulatingConnVector) &priority=5 { - if ( c?$tunnel ) - register_all(c$tunnel); - register_all(e); } diff --git a/scripts/base/protocols/conn/main.bro b/scripts/base/protocols/conn/main.bro index 432bb12e84..5796c3c6b1 100644 --- a/scripts/base/protocols/conn/main.bro +++ b/scripts/base/protocols/conn/main.bro @@ -104,7 +104,7 @@ export { ## If this connection was over a tunnel, indicate the ## *uid* values for any encapsulating parent connections ## used over the lifetime of this inner connection. - parents: set[string] &log; + tunnel_parents: set[string] &log; }; ## Event that can be handled to access the :bro:type:`Conn::Info` @@ -195,7 +195,7 @@ function set_conn(c: connection, eoc: bool) c$conn$uid=c$uid; c$conn$id=c$id; if ( c?$tunnel && |c$tunnel| > 0 ) - add c$conn$parents[c$tunnel[|c$tunnel|-1]$uid]; + add c$conn$tunnel_parents[c$tunnel[|c$tunnel|-1]$uid]; c$conn$proto=get_port_transport_proto(c$id$resp_p); if( |Site::local_nets| > 0 ) c$conn$local_orig=Site::is_local_addr(c$id$orig_h); @@ -238,7 +238,7 @@ event tunnel_changed(c: connection, e: EncapsulatingConnVector) &priority=5 { set_conn(c, F); if ( |e| > 0 ) - add c$conn$parents[e[|e|-1]$uid]; + add c$conn$tunnel_parents[e[|e|-1]$uid]; c$tunnel = e; } diff --git a/src/event.bif b/src/event.bif index 0531bb8a18..72c033cd75 100644 --- a/src/event.bif +++ b/src/event.bif @@ -143,9 +143,11 @@ event new_connection%(c: connection%); ## Generated for a connection whose tunneling has changed. This could ## be from a previously seen connection now being encapsulated in a tunnel, -## or from the outer encapsulation changing. Note that the connection's -## *tunnel* field is NOT automatically assigned to the new encapsulation value -## internally after this event is raised. +## or from the outer encapsulation changing. Note that connection *c*'s +## *tunnel* field is NOT automatically/internally assigned to the new +## encapsulation value of *e* after this event is raised. If the desired +## behavior is to track the latest tunnel encapsulation per-connection, +## then a handler of this event should assign *e* to ``c$tunnel``. ## ## c: The connection whose tunnel/encapsulation changed. ## diff --git a/testing/btest/Baseline/core.print-bpf-filters/conn.log b/testing/btest/Baseline/core.print-bpf-filters/conn.log index ca81844a4a..b563c4a3ed 100644 --- a/testing/btest/Baseline/core.print-bpf-filters/conn.log +++ b/testing/btest/Baseline/core.print-bpf-filters/conn.log @@ -3,6 +3,6 @@ #empty_field (empty) #unset_field - #path conn -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes parents +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] 1128727435.450898 UWkUyAuUGXf 141.42.64.125 56730 125.190.109.199 80 tcp http 1.733303 98 9417 SF - 0 ShADdFaf 12 730 10 9945 (empty) diff --git a/testing/btest/Baseline/core.print-bpf-filters/output b/testing/btest/Baseline/core.print-bpf-filters/output index b4a52965cb..0560b34769 100644 --- a/testing/btest/Baseline/core.print-bpf-filters/output +++ b/testing/btest/Baseline/core.print-bpf-filters/output @@ -5,7 +5,7 @@ #path packet_filter #fields ts node filter init success #types time string string bool bool -1335456050.312960 - ip or not ip T T +1340040469.440535 - ip or not ip T T #separator \x09 #set_separator , #empty_field (empty) @@ -13,7 +13,7 @@ #path packet_filter #fields ts node filter init success #types time string string bool bool -1335456050.557822 - ((((((((((((((((((((((((port 53) or (tcp port 989)) or (tcp port 443)) or (port 6669)) or (udp and port 5353)) or (port 6668)) or (udp and port 5355)) or (tcp port 22)) or (tcp port 995)) or (port 21)) or (tcp port 25 or tcp port 587)) or (port 6667)) or (tcp port 614)) or (tcp port 990)) or (udp port 137)) or (tcp port 993)) or (tcp port 5223)) or (port 514)) or (tcp port 585)) or (tcp port 992)) or (tcp port 563)) or (tcp port 994)) or (tcp port 636)) or (tcp and port (80 or 81 or 631 or 1080 or 3138 or 8000 or 8080 or 8888))) or (port 6666) T T +1340040469.681428 - ((((((((((((((((((((((((port 53) or (tcp port 989)) or (tcp port 443)) or (port 6669)) or (udp and port 5353)) or (port 6668)) or (udp and port 5355)) or (tcp port 22)) or (tcp port 995)) or (port 21)) or (tcp port 25 or tcp port 587)) or (port 6667)) or (tcp port 614)) or (tcp port 990)) or (udp port 137)) or (tcp port 993)) or (tcp port 5223)) or (port 514)) or (tcp port 585)) or (tcp port 992)) or (tcp port 563)) or (tcp port 994)) or (tcp port 636)) or (tcp and port (80 or 81 or 631 or 1080 or 3138 or 8000 or 8080 or 8888))) or (port 6666) T T #separator \x09 #set_separator , #empty_field (empty) @@ -21,7 +21,7 @@ #path packet_filter #fields ts node filter init success #types time string string bool bool -1335456050.805695 - port 42 T T +1340040469.925663 - port 42 T T #separator \x09 #set_separator , #empty_field (empty) @@ -29,4 +29,4 @@ #path packet_filter #fields ts node filter init success #types time string string bool bool -1335456051.042953 - port 56730 T T +1340040470.169001 - port 56730 T T diff --git a/testing/btest/Baseline/core.tunnels.ayiya/conn.log b/testing/btest/Baseline/core.tunnels.ayiya/conn.log index 5c23b4c404..db54a8a475 100644 --- a/testing/btest/Baseline/core.tunnels.ayiya/conn.log +++ b/testing/btest/Baseline/core.tunnels.ayiya/conn.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path conn -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes parents +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] 1257655301.595604 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 tcp http 2.101052 2981 4665 S1 - 0 ShADad 10 3605 11 5329 k6kgXLOoSKl 1257655296.585034 k6kgXLOoSKl 192.168.3.101 53859 216.14.98.22 5072 udp ayiya 20.879001 5129 6109 SF - 0 Dd 21 5717 13 6473 (empty) diff --git a/testing/btest/Baseline/core.tunnels.socks/conn.log b/testing/btest/Baseline/core.tunnels.socks/conn.log index 9d5ae8efb1..f8a684d4c6 100644 --- a/testing/btest/Baseline/core.tunnels.socks/conn.log +++ b/testing/btest/Baseline/core.tunnels.socks/conn.log @@ -3,6 +3,6 @@ #empty_field (empty) #unset_field - #path conn -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes parents +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] 1208299429.265243 UWkUyAuUGXf 127.0.0.1 62270 127.0.0.1 1080 tcp http,socks 0.008138 152 3950 SF - 0 ShAaDdfF 9 632 9 4430 (empty) diff --git a/testing/btest/Baseline/core.tunnels.teredo/conn.log b/testing/btest/Baseline/core.tunnels.teredo/conn.log index 151230886b..cefc8f3e84 100644 --- a/testing/btest/Baseline/core.tunnels.teredo/conn.log +++ b/testing/btest/Baseline/core.tunnels.teredo/conn.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path conn -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes parents +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] 1210953047.736921 arKYeMETxOg 192.168.2.16 1576 75.126.130.163 80 tcp - 0.000357 0 0 SHR - 0 fA 1 40 1 40 (empty) 1210953050.867067 k6kgXLOoSKl 192.168.2.16 1577 75.126.203.78 80 tcp - 0.000387 0 0 SHR - 0 fA 1 40 1 40 (empty) diff --git a/testing/btest/Baseline/core.vlan-mpls/conn.log b/testing/btest/Baseline/core.vlan-mpls/conn.log index 20903d1db8..e165df621a 100644 --- a/testing/btest/Baseline/core.vlan-mpls/conn.log +++ b/testing/btest/Baseline/core.vlan-mpls/conn.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path conn -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes parents +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] 952109346.874907 UWkUyAuUGXf 10.1.2.1 11001 10.34.0.1 23 tcp - 2.102560 26 0 SH - 0 SADF 11 470 0 0 (empty) 1128727435.450898 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 tcp http 1.733303 98 9417 SF - 0 ShADdFaf 12 730 10 9945 (empty) diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log index 5704153b07..4a20ec39b4 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path conn -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes parents +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] 1329843175.736107 arKYeMETxOg 141.142.220.235 37604 199.233.217.249 56666 tcp ftp-data 0.112432 0 342 SF - 0 ShAdfFa 4 216 4 562 (empty) 1329843179.871641 k6kgXLOoSKl 141.142.220.235 59378 199.233.217.249 56667 tcp ftp-data 0.111218 0 77 SF - 0 ShAdfFa 4 216 4 297 (empty) diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log index e3d458bae7..9d19ffaf85 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path conn -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes parents +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] 1329327783.316897 arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49186 2001:470:4867:99::21 57086 tcp ftp-data 0.219721 0 342 SF - 0 ShAdfFa 5 372 4 642 (empty) 1329327786.524332 k6kgXLOoSKl 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49187 2001:470:4867:99::21 57087 tcp ftp-data 0.217501 0 43 SF - 0 ShAdfFa 5 372 4 343 (empty) From 2ba3f5420b13ddc0f2cb173a2ccb41a716972f98 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 18 Jun 2012 12:48:03 -0500 Subject: [PATCH 2/5] Add "encap_hdr_size" option back in. The "tunnel_port" and "parse_udp_tunnels" options are still gone as those did not work entirely (e.g. IPv6 support and misnaming of tunnel_port/udp_tunnel_port). --- scripts/base/init-bare.bro | 4 ++++ src/NetVar.cc | 4 ++++ src/NetVar.h | 2 ++ src/Sessions.cc | 4 ++++ 4 files changed, 14 insertions(+) diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 879a4f5995..503bf2547c 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -915,6 +915,10 @@ const frag_timeout = 0.0 sec &redef; ## to be potentially copied and buffered. const packet_sort_window = 0 usecs &redef; +## If positive, indicates the encapsulation header size that should +## be skipped. This applies to all packets. +const encap_hdr_size = 0 &redef; + ## Whether to use the ``ConnSize`` analyzer to count the number of packets and ## IP-level bytes transfered by each endpoint. If true, these values are returned ## in the connection's :bro:see:`endpoint` record value. diff --git a/src/NetVar.cc b/src/NetVar.cc index 70aa60c886..b057efad11 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -30,6 +30,8 @@ int partial_connection_ok; int tcp_SYN_ack_ok; int tcp_match_undelivered; +int encap_hdr_size; + double frag_timeout; double tcp_SYN_timeout; @@ -323,6 +325,8 @@ void init_net_var() tcp_SYN_ack_ok = opt_internal_int("tcp_SYN_ack_ok"); tcp_match_undelivered = opt_internal_int("tcp_match_undelivered"); + encap_hdr_size = opt_internal_int("encap_hdr_size"); + frag_timeout = opt_internal_double("frag_timeout"); tcp_SYN_timeout = opt_internal_double("tcp_SYN_timeout"); diff --git a/src/NetVar.h b/src/NetVar.h index 7aff9b84e6..e6f6e0cfc4 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -33,6 +33,8 @@ extern int partial_connection_ok; extern int tcp_SYN_ack_ok; extern int tcp_match_undelivered; +extern int encap_hdr_size; + extern double frag_timeout; extern double tcp_SYN_timeout; diff --git a/src/Sessions.cc b/src/Sessions.cc index c754a14698..b5d82f147f 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -158,6 +158,10 @@ void NetSessions::DispatchPacket(double t, const struct pcap_pkthdr* hdr, ip_data = pkt + hdr_size + (ip_hdr->ip_hl << 2); } + if ( encap_hdr_size > 0 && ip_data ) + // Blanket encapsulation + hdr_size += encap_hdr_size; + if ( src_ps->FilterType() == TYPE_FILTER_NORMAL ) NextPacket(t, hdr, pkt, hdr_size, pkt_elem); else From e04d6297330f4872c97588131f31abacce780acb Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 18 Jun 2012 15:44:34 -0500 Subject: [PATCH 3/5] Add state management of NetSessions's IP tunnel map. Entries are checked for inactivity at an interval controlled by "Tunnel::ip_tunnel_timeout" and discarded if needed. --- scripts/base/init-bare.bro | 3 +++ src/Sessions.cc | 28 +++++++++++++++++++++++++--- src/Sessions.h | 20 +++++++++++++++++++- src/Timer.cc | 1 + src/Timer.h | 1 + src/const.bif | 1 + 6 files changed, 50 insertions(+), 4 deletions(-) diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 503bf2547c..3a57a65b20 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -2717,6 +2717,9 @@ export { ## reduce false positives of UDP traffic (e.g. DNS) that also happens ## to have a valid Teredo encapsulation. const yielding_teredo_decapsulation = T &redef; + + ## How often to cleanup internal state for inactive IP tunnels. + const ip_tunnel_timeout = 24hrs &redef; } # end export module GLOBAL; diff --git a/src/Sessions.cc b/src/Sessions.cc index b5d82f147f..84c881b0ef 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -68,6 +68,24 @@ void TimerMgrExpireTimer::Dispatch(double t, int is_expire) } } +void IPTunnelTimer::Dispatch(double t, int is_expire) + { + NetSessions::IPTunnelMap::const_iterator it = + sessions->ip_tunnels.find(tunnel_idx); + + if ( it == sessions->ip_tunnels.end() ) return; + + double last_active = it->second.second; + double inactive_time = t > last_active ? t - last_active : 0; + + if ( inactive_time >= BifConst::Tunnel::ip_tunnel_timeout ) + // tunnel activity timed out, delete it from map + sessions->ip_tunnels.erase(tunnel_idx); + else if ( ! is_expire ) + // tunnel activity didn't timeout, schedule another timer + timer_mgr->Add(new IPTunnelTimer(t, tunnel_idx)); + } + NetSessions::NetSessions() { TypeList* t = new TypeList(); @@ -569,16 +587,20 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, else tunnel_idx = IPPair(ip_hdr->DstAddr(), ip_hdr->SrcAddr()); - IPTunnelMap::const_iterator it = ip_tunnels.find(tunnel_idx); + IPTunnelMap::iterator it = ip_tunnels.find(tunnel_idx); if ( it == ip_tunnels.end() ) { EncapsulatingConn ec(ip_hdr->SrcAddr(), ip_hdr->DstAddr()); - ip_tunnels[tunnel_idx] = ec; + ip_tunnels[tunnel_idx] = TunnelActivity(ec, network_time); + timer_mgr->Add(new IPTunnelTimer(network_time, tunnel_idx)); outer->Add(ec); } else - outer->Add(it->second); + { + it->second.second = network_time; + outer->Add(it->second.first); + } DoNextInnerPacket(t, hdr, inner, outer); diff --git a/src/Sessions.h b/src/Sessions.h index ed7f56c878..548c0903be 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -181,6 +181,7 @@ protected: friend class RemoteSerializer; friend class ConnCompressor; friend class TimerMgrExpireTimer; + friend class IPTunnelTimer; Connection* NewConn(HashKey* k, double t, const ConnID* id, const u_char* data, int proto, uint32 flow_lable, @@ -240,8 +241,10 @@ protected: PDict(Connection) udp_conns; PDict(Connection) icmp_conns; PDict(FragReassembler) fragments; + typedef pair IPPair; - typedef std::map IPTunnelMap; + typedef pair TunnelActivity; + typedef std::map IPTunnelMap; IPTunnelMap ip_tunnels; ARP_Analyzer* arp_analyzer; @@ -261,6 +264,21 @@ protected: TimerMgrMap timer_mgrs; }; + +class IPTunnelTimer : public Timer { +public: + IPTunnelTimer(double t, NetSessions::IPPair p) + : Timer(t + BifConst::Tunnel::ip_tunnel_timeout, + TIMER_IP_TUNNEL_INACTIVITY), tunnel_idx(p) {} + + ~IPTunnelTimer() {} + + void Dispatch(double t, int is_expire); + +protected: + NetSessions::IPPair tunnel_idx; +}; + // Manager for the currently active sessions. extern NetSessions* sessions; diff --git a/src/Timer.cc b/src/Timer.cc index 2e2fb09c6b..c2a8bb3421 100644 --- a/src/Timer.cc +++ b/src/Timer.cc @@ -20,6 +20,7 @@ const char* TimerNames[] = { "IncrementalSendTimer", "IncrementalWriteTimer", "InterconnTimer", + "IPTunnelInactivityTimer", "NetbiosExpireTimer", "NetworkTimer", "NTPExpireTimer", diff --git a/src/Timer.h b/src/Timer.h index bb6b8d56ae..310e72bdc9 100644 --- a/src/Timer.h +++ b/src/Timer.h @@ -26,6 +26,7 @@ enum TimerType { TIMER_INCREMENTAL_SEND, TIMER_INCREMENTAL_WRITE, TIMER_INTERCONN, + TIMER_IP_TUNNEL_INACTIVITY, TIMER_NB_EXPIRE, TIMER_NETWORK, TIMER_NTP_EXPIRE, diff --git a/src/const.bif b/src/const.bif index 368ee34396..499dc63314 100644 --- a/src/const.bif +++ b/src/const.bif @@ -16,5 +16,6 @@ const Tunnel::enable_ip: bool; const Tunnel::enable_ayiya: bool; const Tunnel::enable_teredo: bool; const Tunnel::yielding_teredo_decapsulation: bool; +const Tunnel::ip_tunnel_timeout: interval; const Threading::heartbeat_interval: interval; From ce58a3e90864a00027ec5ecabdf71e4f0eaa93f4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 18 Jun 2012 16:56:19 -0500 Subject: [PATCH 4/5] Refactor of interal tunnel analysis code. - Pulled more common code into NetSessions::DoNextInnerPacket() and made the pcap header it makes internally use network_time - Remove Encapsulation class ctor from pointer - Rename Encapsulation class to EncapsulationStack --- src/Conn.cc | 14 +++++++------- src/Conn.h | 8 ++++---- src/Sessions.cc | 37 +++++++++++++++++++++---------------- src/Sessions.h | 21 +++++++++++++-------- src/Teredo.cc | 9 ++------- src/TunnelEncapsulation.cc | 2 +- src/TunnelEncapsulation.h | 26 ++++++++++---------------- src/ayiya-analyzer.pac | 8 ++------ 8 files changed, 60 insertions(+), 65 deletions(-) diff --git a/src/Conn.cc b/src/Conn.cc index f3ebaca0c9..bc2e7fb5cf 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -113,7 +113,7 @@ unsigned int Connection::external_connections = 0; IMPLEMENT_SERIAL(Connection, SER_CONNECTION); Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id, - uint32 flow, const Encapsulation* arg_encap) + uint32 flow, const EncapsulationStack* arg_encap) { sessions = s; key = k; @@ -162,7 +162,7 @@ Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id, uid = 0; // Will set later. if ( arg_encap ) - encapsulation = new Encapsulation(arg_encap); + encapsulation = new EncapsulationStack(*arg_encap); else encapsulation = 0; @@ -200,7 +200,7 @@ Connection::~Connection() --external_connections; } -void Connection::CheckEncapsulation(const Encapsulation* arg_encap) +void Connection::CheckEncapsulation(const EncapsulationStack* arg_encap) { if ( encapsulation && arg_encap ) { @@ -208,22 +208,22 @@ void Connection::CheckEncapsulation(const Encapsulation* arg_encap) { Event(tunnel_changed, 0, arg_encap->GetVectorVal()); delete encapsulation; - encapsulation = new Encapsulation(arg_encap); + encapsulation = new EncapsulationStack(*arg_encap); } } else if ( encapsulation ) { - Encapsulation empty; + EncapsulationStack empty; Event(tunnel_changed, 0, empty.GetVectorVal()); delete encapsulation; - encapsulation = new Encapsulation(arg_encap); + encapsulation = 0; } else if ( arg_encap ) { Event(tunnel_changed, 0, arg_encap->GetVectorVal()); - encapsulation = new Encapsulation(arg_encap); + encapsulation = new EncapsulationStack(*arg_encap); } } diff --git a/src/Conn.h b/src/Conn.h index b3798cfb36..782d41a801 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -52,7 +52,7 @@ class Analyzer; class Connection : public BroObj { public: Connection(NetSessions* s, HashKey* k, double t, const ConnID* id, - uint32 flow, const Encapsulation* arg_encap); + uint32 flow, const EncapsulationStack* arg_encap); virtual ~Connection(); // Invoked when an encapsulation is discovered. It records the @@ -60,7 +60,7 @@ public: // event if it's different from the previous encapsulation (or the // first encountered). encap can be null to indicate no // encapsulation. - void CheckEncapsulation(const Encapsulation* encap); + void CheckEncapsulation(const EncapsulationStack* encap); // Invoked when connection is about to be removed. Use Ref(this) // inside Done to keep the connection object around (though it'll @@ -252,7 +252,7 @@ public: uint64 GetUID() const { return uid; } - const Encapsulation* GetEncapsulation() const + const EncapsulationStack* GetEncapsulation() const { return encapsulation; } void CheckFlowLabel(bool is_orig, uint32 flow_label); @@ -292,7 +292,7 @@ protected: double inactivity_timeout; RecordVal* conn_val; LoginConn* login_conn; // either nil, or this - const Encapsulation* encapsulation; // tunnels + const EncapsulationStack* encapsulation; // tunnels int suppress_event; // suppress certain events to once per conn. unsigned int installed_status_timer:1; diff --git a/src/Sessions.cc b/src/Sessions.cc index 84c881b0ef..10126f45b1 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -367,7 +367,7 @@ int NetSessions::CheckConnectionTag(Connection* conn) void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, const IP_Hdr* ip_hdr, const u_char* const pkt, - int hdr_size, const Encapsulation* encapsulation) + int hdr_size, const EncapsulationStack* encapsulation) { uint32 caplen = hdr->caplen - hdr_size; const struct ip* ip4 = ip_hdr->IP4_Hdr(); @@ -576,8 +576,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, return; } - Encapsulation* outer = new Encapsulation(encapsulation); - // Look up to see if we've already seen this IP tunnel, identified // by the pair of IP addresses, so that we can always associate the // same UID with it. @@ -594,18 +592,13 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, EncapsulatingConn ec(ip_hdr->SrcAddr(), ip_hdr->DstAddr()); ip_tunnels[tunnel_idx] = TunnelActivity(ec, network_time); timer_mgr->Add(new IPTunnelTimer(network_time, tunnel_idx)); - outer->Add(ec); } else - { it->second.second = network_time; - outer->Add(it->second.first); - } - DoNextInnerPacket(t, hdr, inner, outer); + DoNextInnerPacket(t, hdr, inner, encapsulation, + ip_tunnels[tunnel_idx].first); - delete inner; - delete outer; Remove(f); return; } @@ -724,7 +717,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, } void NetSessions::DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr, - const IP_Hdr* inner, const Encapsulation* outer) + const IP_Hdr* inner, const EncapsulationStack* prev, + const EncapsulatingConn& ec) { struct pcap_pkthdr fake_hdr; fake_hdr.caplen = fake_hdr.len = inner->TotalLen(); @@ -732,7 +726,11 @@ void NetSessions::DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr, if ( hdr ) fake_hdr.ts = hdr->ts; else - fake_hdr.ts.tv_sec = fake_hdr.ts.tv_usec = 0; + { + fake_hdr.ts.tv_sec = (time_t) network_time; + fake_hdr.ts.tv_usec = (suseconds_t) + ((network_time - (double)fake_hdr.ts.tv_sec) * 1000000); + } const u_char* pkt = 0; @@ -741,7 +739,14 @@ void NetSessions::DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr, else pkt = (const u_char*) inner->IP6_Hdr(); + EncapsulationStack* outer = prev ? + new EncapsulationStack(*prev) : new EncapsulationStack(); + outer->Add(ec); + DoNextPacket(t, &fake_hdr, inner, pkt, 0, outer); + + delete inner; + delete outer; } int NetSessions::ParseIPPacket(int caplen, const u_char* const pkt, int proto, @@ -778,7 +783,7 @@ int NetSessions::ParseIPPacket(int caplen, const u_char* const pkt, int proto, bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, const struct pcap_pkthdr* h, - const u_char* p, const Encapsulation* encap) + const u_char* p, const EncapsulationStack* encap) { uint32 min_hdr_len = 0; switch ( proto ) { @@ -1110,7 +1115,7 @@ void NetSessions::GetStats(SessionStats& s) const Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id, const u_char* data, int proto, uint32 flow_label, - const Encapsulation* encapsulation) + const EncapsulationStack* encapsulation) { // FIXME: This should be cleaned up a bit, it's too protocol-specific. // But I'm not yet sure what the right abstraction for these things is. @@ -1331,7 +1336,7 @@ void NetSessions::Internal(const char* msg, const struct pcap_pkthdr* hdr, } void NetSessions::Weird(const char* name, const struct pcap_pkthdr* hdr, - const u_char* pkt, const Encapsulation* encap) + const u_char* pkt, const EncapsulationStack* encap) { if ( hdr ) dump_this_packet = 1; @@ -1343,7 +1348,7 @@ void NetSessions::Weird(const char* name, const struct pcap_pkthdr* hdr, } void NetSessions::Weird(const char* name, const IP_Hdr* ip, - const Encapsulation* encap) + const EncapsulationStack* encap) { if ( encap && encap->LastType() != BifEnum::Tunnel::NONE ) reporter->Weird(ip->SrcAddr(), ip->DstAddr(), diff --git a/src/Sessions.h b/src/Sessions.h index 548c0903be..613eebe5ca 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -16,7 +16,7 @@ struct pcap_pkthdr; -class Encapsulation; +class EncapsulationStack; class Connection; class ConnID; class OSFingerprint; @@ -109,9 +109,9 @@ public: void GetStats(SessionStats& s) const; void Weird(const char* name, const struct pcap_pkthdr* hdr, - const u_char* pkt, const Encapsulation* encap = 0); + const u_char* pkt, const EncapsulationStack* encap = 0); void Weird(const char* name, const IP_Hdr* ip, - const Encapsulation* encap = 0); + const EncapsulationStack* encap = 0); PacketFilter* GetPacketFilter() { @@ -137,7 +137,7 @@ public: void DoNextPacket(double t, const struct pcap_pkthdr* hdr, const IP_Hdr* ip_hdr, const u_char* const pkt, - int hdr_size, const Encapsulation* encapsulation); + int hdr_size, const EncapsulationStack* encapsulation); /** * Wrapper that recurses on DoNextPacket for encapsulated IP packets. @@ -147,10 +147,15 @@ public: * so that the fake pcap header passed to DoNextPacket will use * the same timeval. The caplen and len fields of the fake pcap * header are always set to the TotalLength() of \a inner. - * @param outer The encapsulation information for the inner IP packet. + * @param inner Pointer to IP header wrapper of the inner packet, ownership + * of the pointer's memory is assumed by this function. + * @param prev Any previous encapsulation stack of the caller, not including + * the most-recently found depth of encapsulation. + * @param ec The most-recently found depth of encapsulation. */ void DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr, - const IP_Hdr* inner, const Encapsulation* outer); + const IP_Hdr* inner, const EncapsulationStack* prev, + const EncapsulatingConn& ec); /** * Returns a wrapper IP_Hdr object if \a pkt appears to be a valid IPv4 @@ -185,7 +190,7 @@ protected: Connection* NewConn(HashKey* k, double t, const ConnID* id, const u_char* data, int proto, uint32 flow_lable, - const Encapsulation* encapsulation); + const EncapsulationStack* encapsulation); // Check whether the tag of the current packet is consistent with // the given connection. Returns: @@ -234,7 +239,7 @@ protected: // than that protocol's minimum header size. bool CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, const struct pcap_pkthdr* hdr, const u_char* pkt, - const Encapsulation* encap); + const EncapsulationStack* encap); CompositeHash* ch; PDict(Connection) tcp_conns; diff --git a/src/Teredo.cc b/src/Teredo.cc index e537edb916..ac68bdbed1 100644 --- a/src/Teredo.cc +++ b/src/Teredo.cc @@ -149,7 +149,7 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, return; } - const Encapsulation* e = Conn()->GetEncapsulation(); + const EncapsulationStack* e = Conn()->GetEncapsulation(); if ( e && e->Depth() >= BifConst::Tunnel::max_depth ) { @@ -222,12 +222,7 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, Conn()->Event(teredo_bubble, 0, teredo_hdr); } - Encapsulation* outer = new Encapsulation(e); EncapsulatingConn ec(Conn(), BifEnum::Tunnel::TEREDO); - outer->Add(ec); - sessions->DoNextInnerPacket(network_time, 0, inner, outer); - - delete inner; - delete outer; + sessions->DoNextInnerPacket(network_time, 0, inner, e, ec); } diff --git a/src/TunnelEncapsulation.cc b/src/TunnelEncapsulation.cc index f023a40b6a..edbabef81f 100644 --- a/src/TunnelEncapsulation.cc +++ b/src/TunnelEncapsulation.cc @@ -34,7 +34,7 @@ RecordVal* EncapsulatingConn::GetRecordVal() const return rv; } -bool operator==(const Encapsulation& e1, const Encapsulation& e2) +bool operator==(const EncapsulationStack& e1, const EncapsulationStack& e2) { if ( ! e1.conns ) return e2.conns; diff --git a/src/TunnelEncapsulation.h b/src/TunnelEncapsulation.h index 9dcf134536..e8ca7a48b6 100644 --- a/src/TunnelEncapsulation.h +++ b/src/TunnelEncapsulation.h @@ -114,12 +114,12 @@ protected: /** * Abstracts an arbitrary amount of nested tunneling. */ -class Encapsulation { +class EncapsulationStack { public: - Encapsulation() : conns(0) + EncapsulationStack() : conns(0) {} - Encapsulation(const Encapsulation& other) + EncapsulationStack(const EncapsulationStack& other) { if ( other.conns ) conns = new vector(*(other.conns)); @@ -127,15 +127,7 @@ public: conns = 0; } - Encapsulation(const Encapsulation* other) - { - if ( other && other->conns ) - conns = new vector(*(other->conns)); - else - conns = 0; - } - - Encapsulation& operator=(const Encapsulation& other) + EncapsulationStack& operator=(const EncapsulationStack& other) { if ( this == &other ) return *this; @@ -150,10 +142,10 @@ public: return *this; } - ~Encapsulation() { delete conns; } + ~EncapsulationStack() { delete conns; } /** - * Add a new inner-most tunnel to the Encapsulation. + * Add a new inner-most tunnel to the EncapsulationStack. * * @param c The new inner-most tunnel to append to the tunnel chain. */ @@ -200,9 +192,11 @@ public: return vv; } - friend bool operator==(const Encapsulation& e1, const Encapsulation& e2); + friend bool operator==(const EncapsulationStack& e1, + const EncapsulationStack& e2); - friend bool operator!=(const Encapsulation& e1, const Encapsulation& e2) + friend bool operator!=(const EncapsulationStack& e1, + const EncapsulationStack& e2) { return ! ( e1 == e2 ); } diff --git a/src/ayiya-analyzer.pac b/src/ayiya-analyzer.pac index f1b144ff44..89d1143ad7 100644 --- a/src/ayiya-analyzer.pac +++ b/src/ayiya-analyzer.pac @@ -12,7 +12,7 @@ flow AYIYA_Flow function process_ayiya(pdu: PDU): bool %{ Connection *c = connection()->bro_analyzer()->Conn(); - const Encapsulation* e = c->GetEncapsulation(); + const EncapsulationStack* e = c->GetEncapsulation(); if ( e && e->Depth() >= BifConst::Tunnel::max_depth ) { @@ -72,14 +72,10 @@ flow AYIYA_Flow if ( result != 0 ) return false; - Encapsulation* outer = new Encapsulation(e); EncapsulatingConn ec(c, BifEnum::Tunnel::AYIYA); - outer->Add(ec); - sessions->DoNextInnerPacket(network_time(), 0, inner, outer); + sessions->DoNextInnerPacket(network_time(), 0, inner, e, ec); - delete inner; - delete outer; return (result == 0) ? true : false; %} From d6286d953d0d0c34096ebbe9bec4b25ed2d72565 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 18 Jun 2012 17:04:46 -0500 Subject: [PATCH 5/5] Remove &synchronized from Tunnel::active table. --- scripts/base/frameworks/tunnels/main.bro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/base/frameworks/tunnels/main.bro b/scripts/base/frameworks/tunnels/main.bro index 2f5625f8b2..869c501fe6 100644 --- a/scripts/base/frameworks/tunnels/main.bro +++ b/scripts/base/frameworks/tunnels/main.bro @@ -76,7 +76,7 @@ export { ## Currently active tunnels. That is, tunnels for which new, encapsulated ## connections have been seen in the interval indicated by ## :bro:see:`Tunnel::expiration_interval`. - global active: table[conn_id] of Info = table() &synchronized &read_expire=expiration_interval &expire_func=expire; + global active: table[conn_id] of Info = table() &read_expire=expiration_interval &expire_func=expire; } const ayiya_ports = { 5072/udp };