BIT-867 - Support GRE tunnel decapsulation.

This includes enhanced GRE headers.  GRE tunnels are treated just like
IP-in-IP tunnels by parsing past the GRE header in between the delivery
and payload IP packets.
This commit is contained in:
Jon Siwek 2014-01-16 16:03:04 -06:00
parent 69ef268a44
commit 7717a3eb67
13 changed files with 207 additions and 1 deletions

View file

@ -3057,6 +3057,9 @@ export {
## Toggle whether to do GTPv1 decapsulation.
const enable_gtpv1 = T &redef;
## Toggle whether to do GRE decapsulation.
const enable_gre = T &redef;
## With this option set, the Teredo analysis will first check to see if
## other protocol analyzers have confirmed that they think they're
## parsing the right protocol and only continue with Teredo tunnel
@ -3082,7 +3085,8 @@ export {
## may work better.
const delay_gtp_confirmation = F &redef;
## How often to cleanup internal state for inactive IP tunnels.
## How often to cleanup internal state for inactive IP tunnels
## (includes GRE tunnels).
const ip_tunnel_timeout = 24hrs &redef;
} # end export
module GLOBAL;

View file

@ -376,6 +376,31 @@ int NetSessions::CheckConnectionTag(Connection* conn)
return 1;
}
static unsigned int gre_header_len(uint16 flags)
{
unsigned int len = 4; // Always has 2 byte flags and 2 byte protocol type.
if ( flags & 0x8000 )
// Checksum/Reserved1 present.
len += 4;
// Not considering routing presence bit since it's deprecated...
if ( flags & 0x2000 )
// Key present.
len += 4;
if ( flags & 0x1000 )
// Sequence present.
len += 4;
if ( flags & 0x0080 )
// Acknowledgement present.
len += 4;
return len;
}
void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
const IP_Hdr* ip_hdr, const u_char* const pkt,
int hdr_size, const EncapsulationStack* encapsulation)
@ -562,6 +587,101 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
break;
}
case IPPROTO_GRE:
{
if ( ! BifConst::Tunnel::enable_gre )
{
Weird("GRE_tunnel", ip_hdr, encapsulation);
Remove(f);
return;
}
uint16 flags_ver = ntohs(*((uint16*)(data + 0)));
uint16 proto_typ = ntohs(*((uint16*)(data + 2)));
int gre_version = flags_ver & 0x0007;
if ( gre_version != 0 && gre_version != 1 )
{
Weird(fmt("unknown_gre_version_%d", gre_version), ip_hdr,
encapsulation);
Remove(f);
return;
}
if ( gre_version == 0 )
{
if ( proto_typ != 0x0800 && proto_typ != 0x86dd )
{
// Not IPv4/IPv6 payload.
Weird(fmt("unknown_gre_protocol_%"PRIu16, proto_typ), ip_hdr,
encapsulation);
Remove(f);
return;
}
proto = (proto_typ == 0x0800) ? IPPROTO_IPV4 : IPPROTO_IPV6;
}
else // gre_version == 1
{
if ( proto_typ != 0x880b)
{
// Enhanced GRE payload must be PPP.
Weird("egre_protocol_type", ip_hdr, encapsulation);
Remove(f);
return;
}
}
if ( flags_ver & 0x4000 )
{
// RFC 2784 deprecates the variable length routing field
// specified by RFC 1701. It could be parsed here, but easiest
// to just skip for now.
Weird("gre_routing", ip_hdr, encapsulation);
Remove(f);
return;
}
if ( flags_ver & 0x0078 )
{
// Expect last 4 bits of flags are reserved, undefined.
Weird("unknown_gre_flags", ip_hdr, encapsulation);
Remove(f);
return;
}
unsigned int gre_len = gre_header_len(flags_ver);
unsigned int ppp_len = gre_version == 1 ? 1 : 0;
if ( len < gre_len + ppp_len || caplen < gre_len + ppp_len )
{
Weird("truncated_GRE", ip_hdr, encapsulation);
Remove(f);
return;
}
if ( gre_version == 1 )
{
int ppp_proto = *((uint8*)(data + gre_len));
if ( ppp_proto != 0x0021 && ppp_proto != 0x0057 )
{
Weird("non_ip_packet_in_egre", ip_hdr, encapsulation);
Remove(f);
return;
}
proto = (ppp_proto == 0x0021) ? IPPROTO_IPV4 : IPPROTO_IPV6;
}
data += gre_len + ppp_len;
len -= gre_len + ppp_len;
caplen -= gre_len + ppp_len;
// Treat GRE tunnel like IP tunnels, fallthrough to logic below now
// that GRE header is stripped and only payload packet remains.
}
case IPPROTO_IPV4:
case IPPROTO_IPV6:
{
@ -822,6 +942,9 @@ bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen,
case IPPROTO_NONE:
min_hdr_len = 0;
break;
case IPPROTO_GRE:
min_hdr_len = 4;
break;
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
default:

View file

@ -17,6 +17,7 @@ const Tunnel::enable_ip: bool;
const Tunnel::enable_ayiya: bool;
const Tunnel::enable_teredo: bool;
const Tunnel::enable_gtpv1: bool;
const Tunnel::enable_gre: bool;
const Tunnel::yielding_teredo_decapsulation: bool;
const Tunnel::delay_teredo_confirmation: bool;
const Tunnel::delay_gtp_confirmation: bool;

View file

@ -0,0 +1,12 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path conn
#open 2014-01-16-21-51-36
#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]
1341436440.002928 CRJuHdVW0XPVINV8a 3.3.3.2 520 224.0.0.9 520 udp - 26.148268 48 0 S0 - 0 D 2 104 0 0 CjhGID4nQcgTWjvg4c
1341436424.378840 CsRx2w45OKnoww6xl4 3.3.3.1 520 224.0.0.9 520 udp - 28.555457 168 0 S0 - 0 D 2 224 0 0 CjhGID4nQcgTWjvg4c
1341436424.204043 CCvvfg3TEfuqmmG4bh 10.10.25.1 8 192.168.1.2 0 icmp - 42.380221 22464 22464 OTH - 0 - 312 31200 312 31200 CjhGID4nQcgTWjvg4c
#close 2014-01-16-21-51-36

View file

@ -0,0 +1,11 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path tunnel
#open 2014-01-16-21-51-36
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action
#types time string addr port addr port enum enum
1341436424.204043 CXWv6p3arKYeMETxOg 72.205.54.70 0 86.106.164.150 0 Tunnel::IP Tunnel::DISCOVER
1341436424.204043 CjhGID4nQcgTWjvg4c 10.10.11.2 0 10.10.13.2 0 Tunnel::IP Tunnel::DISCOVER
#close 2014-01-16-21-51-36

View file

@ -0,0 +1,16 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path conn
#open 2014-01-16-21-51-12
#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]
1055289978.756932 CsRx2w45OKnoww6xl4 66.59.111.190 40264 172.28.2.3 22 tcp ssh 3.157831 952 1671 SF - 0 ShAdDaFf 12 1584 10 2199 CXWv6p3arKYeMETxOg
1055289987.055189 CRJuHdVW0XPVINV8a 66.59.111.190 37675 172.28.2.3 53 udp dns 5.001141 66 0 S0 - 0 D 2 122 0 0 CXWv6p3arKYeMETxOg
1055289996.849099 CIPOse170MGiRM1Qf4 66.59.111.190 123 129.170.17.4 123 udp - 0.072374 48 48 SF - 0 Dd 1 76 1 76 CXWv6p3arKYeMETxOg
1055289973.849878 CCvvfg3TEfuqmmG4bh 66.59.111.190 123 18.26.4.105 123 udp - 0.074086 48 48 SF - 0 Dd 1 76 1 76 CXWv6p3arKYeMETxOg
1055289992.849231 C6pKV8GSxOnSLghOa 66.59.111.190 123 66.59.111.182 123 udp - 0.056629 48 48 SF - 0 Dd 1 76 1 76 CXWv6p3arKYeMETxOg
1055289968.793044 CjhGID4nQcgTWjvg4c 66.59.111.190 8 172.28.2.3 0 icmp - 3.061298 224 224 OTH - 0 - 4 336 4 336 CXWv6p3arKYeMETxOg
1055289987.106744 CPbrpk1qSsw6ESzHV4 172.28.2.3 3 66.59.111.190 3 icmp - 4.994662 122 0 OTH - 0 - 2 178 0 0 CXWv6p3arKYeMETxOg
#close 2014-01-16-21-51-12

View file

@ -0,0 +1,11 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path dns
#open 2014-01-16-21-51-12
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected
#types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] bool
1055289987.055189 CRJuHdVW0XPVINV8a 66.59.111.190 37675 172.28.2.3 53 udp 48554 www.gleeble.org 1 C_INTERNET 255 * - - F F T F 0 - - F
1055289992.056330 CRJuHdVW0XPVINV8a 66.59.111.190 37675 172.28.2.3 53 udp 48554 www.gleeble.org 1 C_INTERNET 255 * - - F F T F 0 - - F
#close 2014-01-16-21-51-12

View file

@ -0,0 +1,10 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path ssh
#open 2014-01-16-21-51-12
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p status direction client server
#types time string addr port addr port string enum string string
1055289978.855137 CsRx2w45OKnoww6xl4 66.59.111.190 40264 172.28.2.3 22 failure INBOUND SSH-2.0-OpenSSH_3.6.1p1 SSH-1.99-OpenSSH_3.1p1
#close 2014-01-16-21-51-12

View file

@ -0,0 +1,10 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path tunnel
#open 2014-01-16-21-51-12
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action
#types time string addr port addr port enum enum
1055289968.793044 CXWv6p3arKYeMETxOg 172.27.1.66 0 66.59.109.137 0 Tunnel::IP Tunnel::DISCOVER
#close 2014-01-16-21-51-12

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,3 @@
# @TEST-EXEC: bro -r $TRACES/tunnels/gre-within-gre.pcap
# @TEST-EXEC: btest-diff conn.log
# @TEST-EXEC: btest-diff tunnel.log

View file

@ -0,0 +1,5 @@
# @TEST-EXEC: bro -r $TRACES/tunnels/gre-sample.pcap
# @TEST-EXEC: btest-diff conn.log
# @TEST-EXEC: btest-diff tunnel.log
# @TEST-EXEC: btest-diff dns.log
# @TEST-EXEC: btest-diff ssh.log