mirror of
https://github.com/zeek/zeek.git
synced 2025-10-12 03:28:19 +00:00
Improve handling of IPv6 Routing Type 0 headers.
- For RH0 headers with non-zero segments left, a "routing0_segleft" flow_weird event is raised (with a destination indicating the last address in the routing header), and an "rh0_segleft" event can also be handled if the other contents of the packet header are of interest. No further analysis is done as the complexity required to correctly identify destination endpoints of connections doesn't seem worth it as RH0 has been deprecated by RFC 5095. - For RH0 headers without any segments left, a "routing0_header" flow_weird event is raised, but further analysis still occurs as normal.
This commit is contained in:
parent
d889f14638
commit
256cd592a7
12 changed files with 93 additions and 4 deletions
18
src/IP.cc
18
src/IP.cc
|
@ -305,6 +305,24 @@ void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next)
|
||||||
|
|
||||||
chain.push_back(p);
|
chain.push_back(p);
|
||||||
|
|
||||||
|
// RFC 5095 deprecates routing type 0 headers, so raise weirds for that
|
||||||
|
if ( current_type == IPPROTO_ROUTING &&
|
||||||
|
((const struct ip6_rthdr*)hdrs)->ip6r_type == 0 )
|
||||||
|
{
|
||||||
|
IPAddr src(((const struct ip6_hdr*)(chain[0]->Data()))->ip6_src);
|
||||||
|
|
||||||
|
if ( ((const struct ip6_rthdr*)hdrs)->ip6r_segleft > 0 )
|
||||||
|
{
|
||||||
|
const in6_addr* a = (const in6_addr*)(hdrs+len-16);
|
||||||
|
reporter->Weird(src, *a, "routing0_segleft");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IPAddr dst(((const struct ip6_hdr*)(chain[0]->Data()))->ip6_dst);
|
||||||
|
reporter->Weird(src, dst, "routing0_header");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hdrs += len;
|
hdrs += len;
|
||||||
length += len;
|
length += len;
|
||||||
} while ( current_type != IPPROTO_FRAGMENT &&
|
} while ( current_type != IPPROTO_FRAGMENT &&
|
||||||
|
|
21
src/IP.h
21
src/IP.h
|
@ -171,6 +171,20 @@ public:
|
||||||
{ return IsFragment() ?
|
{ return IsFragment() ?
|
||||||
(ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; }
|
(ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the chain contains a routing type 0 extension header
|
||||||
|
* with nonzero segments left.
|
||||||
|
*/
|
||||||
|
bool RH0SegLeft() const
|
||||||
|
{
|
||||||
|
for ( size_t i = 0; i < chain.size(); ++i )
|
||||||
|
if ( chain[i]->Type() == IPPROTO_ROUTING &&
|
||||||
|
((const struct ip6_rthdr*)chain[i]->Data())->ip6r_type == 0 &&
|
||||||
|
((const struct ip6_rthdr*)chain[i]->Data())->ip6r_segleft > 0 )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a vector of ip6_ext_hdr RecordVals that includes script-layer
|
* Returns a vector of ip6_ext_hdr RecordVals that includes script-layer
|
||||||
* representation of all extension headers in the chain.
|
* representation of all extension headers in the chain.
|
||||||
|
@ -343,6 +357,13 @@ public:
|
||||||
size_t NumHeaders() const
|
size_t NumHeaders() const
|
||||||
{ return ip4 ? 1 : ip6_hdrs->Size(); }
|
{ return ip4 ? 1 : ip6_hdrs->Size(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this is an IPv6 header containing a routing type 0
|
||||||
|
* extension with nonzero segments left, else returns false.
|
||||||
|
*/
|
||||||
|
bool RH0SegLeft() const
|
||||||
|
{ return ip4 ? false : ip6_hdrs->RH0SegLeft(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an ip_hdr or ip6_hdr_chain RecordVal.
|
* Returns an ip_hdr or ip6_hdr_chain RecordVal.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -481,6 +481,22 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop analyzing IPv6 packets that use routing type 0 headers with segments
|
||||||
|
// left since RH0 headers are deprecated by RFC 5095 and we'd have to make
|
||||||
|
// extra effort to get the destination in the connection/flow endpoint right
|
||||||
|
if ( ip_hdr->RH0SegLeft() )
|
||||||
|
{
|
||||||
|
dump_this_packet = 1;
|
||||||
|
if ( rh0_segleft )
|
||||||
|
{
|
||||||
|
val_list* vl = new val_list();
|
||||||
|
vl->append(ip_hdr->BuildPktHdrVal());
|
||||||
|
mgr.QueueEvent(rh0_segleft, vl);
|
||||||
|
}
|
||||||
|
Remove(f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int proto = ip_hdr->NextProto();
|
int proto = ip_hdr->NextProto();
|
||||||
|
|
||||||
if ( CheckHeaderTrunc(proto, len, caplen, hdr, pkt) )
|
if ( CheckHeaderTrunc(proto, len, caplen, hdr, pkt) )
|
||||||
|
|
|
@ -478,6 +478,14 @@ event ipv6_ext_headers%(c: connection, p: pkt_hdr%);
|
||||||
## .. bro:see:: new_packet tcp_packet ipv6_ext_headers
|
## .. bro:see:: new_packet tcp_packet ipv6_ext_headers
|
||||||
event esp_packet%(p: pkt_hdr%);
|
event esp_packet%(p: pkt_hdr%);
|
||||||
|
|
||||||
|
## Generated for any packets using an IPv6 Routing Type 0 extension header
|
||||||
|
## with non-zero segments left.
|
||||||
|
##
|
||||||
|
## p: Information from the header of the packet that triggered the event.
|
||||||
|
##
|
||||||
|
## .. bro:see:: new_packet tcp_packet ipv6_ext_headers
|
||||||
|
event rh0_segleft%(p: pkt_hdr%);
|
||||||
|
|
||||||
## Generated for every packet that has non-empty transport-layer payload. This is a
|
## Generated for every packet that has non-empty transport-layer payload. This is a
|
||||||
## very low-level and expensive event that should be avoided when at all possible.
|
## very low-level and expensive event that should be avoided when at all possible.
|
||||||
## It's usually infeasible to handle when processing even medium volumes of
|
## It's usually infeasible to handle when processing even medium volumes of
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
[ip=<uninitialized>, ip6=[class=0, flow=0, len=59, nxt=0, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=0, hopopts=[nxt=43, len=0, options=[[otype=1, len=4, data=\0\0\0\0]]], dstopts=<uninitialized>, routing=<uninitialized>, fragment=<uninitialized>, ah=<uninitialized>, esp=<uninitialized>], [id=43, hopopts=<uninitialized>, dstopts=<uninitialized>, routing=[nxt=17, len=4, rtype=0, segleft=2, data=\0\0\0\0 ^A\0x\0^A\02\0\0\0\0\0\0\0^A ^A\0x\0^A\02\0\0\0\0\0\0\0^B], fragment=<uninitialized>, ah=<uninitialized>, esp=<uninitialized>]]], tcp=<uninitialized>, udp=[sport=53/udp, dport=53/udp, ulen=11], icmp=<uninitialized>]
|
[ip=<uninitialized>, ip6=[class=0, flow=0, len=68, nxt=0, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=0, hopopts=[nxt=43, len=0, options=[[otype=1, len=4, data=\0\0\0\0]]], dstopts=<uninitialized>, routing=<uninitialized>, fragment=<uninitialized>, ah=<uninitialized>, esp=<uninitialized>], [id=43, hopopts=<uninitialized>, dstopts=<uninitialized>, routing=[nxt=6, len=4, rtype=0, segleft=0, data=\0\0\0\0 ^A\0x\0^A\02\0\0\0\0\0\0\0^A ^A\0x\0^A\02\0\0\0\0\0\0\0^B], fragment=<uninitialized>, ah=<uninitialized>, esp=<uninitialized>]]], tcp=[sport=30000/tcp, dport=80/tcp, seq=0, ack=0, hl=20, dl=0, flags=2, win=8192], udp=<uninitialized>, icmp=<uninitialized>]
|
||||||
|
|
2
testing/btest/Baseline/core.ipv6_rh0/segleft.out
Normal file
2
testing/btest/Baseline/core.ipv6_rh0/segleft.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
flow_weird routing0_segleft from 2001:4f8:4:7:2e0:81ff:fe52:ffff to 2001:78:1:32::2
|
||||||
|
rh0 w/ segments left from 2001:4f8:4:7:2e0:81ff:fe52:ffff to 2001:4f8:4:7:2e0:81ff:fe52:9a6b
|
2
testing/btest/Baseline/core.ipv6_rh0/segleft0.out
Normal file
2
testing/btest/Baseline/core.ipv6_rh0/segleft0.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
flow_weird routing0_header from 2001:4f8:4:7:2e0:81ff:fe52:ffff to 2001:4f8:4:7:2e0:81ff:fe52:9a6b
|
||||||
|
new_connection: [orig_h=2001:4f8:4:7:2e0:81ff:fe52:ffff, orig_p=30000/tcp, resp_h=2001:4f8:4:7:2e0:81ff:fe52:9a6b, resp_p=80/tcp]
|
BIN
testing/btest/Traces/ipv6-hbh-rh0-segleft0.trace
Normal file
BIN
testing/btest/Traces/ipv6-hbh-rh0-segleft0.trace
Normal file
Binary file not shown.
|
@ -1,7 +1,7 @@
|
||||||
# @TEST-EXEC: bro -C -b -r $TRACES/ext_hdr_hbh_routing.trace %INPUT >output
|
# @TEST-EXEC: bro -b -r $TRACES/ipv6-hbh-rh0-segleft.trace %INPUT >output
|
||||||
# @TEST-EXEC: btest-diff output
|
# @TEST-EXEC: btest-diff output
|
||||||
|
|
||||||
event ipv6_ext_headers(c: connection, p: pkt_hdr)
|
event rh0_segleft(p: pkt_hdr)
|
||||||
{
|
{
|
||||||
for ( h in p$ip6$exts )
|
for ( h in p$ip6$exts )
|
||||||
if ( p$ip6$exts[h]$id == IPPROTO_ROUTING )
|
if ( p$ip6$exts[h]$id == IPPROTO_ROUTING )
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# @TEST-EXEC: bro -C -b -r $TRACES/ext_hdr_hbh_routing.trace %INPUT >output
|
# @TEST-EXEC: bro -b -r $TRACES/ipv6-hbh-rh0-segleft0.trace %INPUT >output
|
||||||
# @TEST-EXEC: btest-diff output
|
# @TEST-EXEC: btest-diff output
|
||||||
|
|
||||||
# Just check that the event is raised correctly for a packet containing
|
# Just check that the event is raised correctly for a packet containing
|
||||||
|
|
22
testing/btest/core/ipv6_rh0.test
Normal file
22
testing/btest/core/ipv6_rh0.test
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# @TEST-EXEC: bro -b -r $TRACES/ipv6-hbh-rh0-segleft0.trace %INPUT >segleft0.out
|
||||||
|
# @TEST-EXEC: btest-diff segleft0.out
|
||||||
|
# @TEST-EXEC: bro -b -r $TRACES/ipv6-hbh-rh0-segleft.trace %INPUT >segleft.out
|
||||||
|
# @TEST-EXEC: btest-diff segleft.out
|
||||||
|
|
||||||
|
# This will be raised only by the packet with RH0 and segments left.
|
||||||
|
event rh0_segleft(p: pkt_hdr)
|
||||||
|
{
|
||||||
|
print fmt("rh0 w/ segments left from %s to %s", p$ip6$src, p$ip6$dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
# This will be raised only by the packet with RH0 and no segments left.
|
||||||
|
event new_connection(c: connection)
|
||||||
|
{
|
||||||
|
print fmt("new_connection: %s", c$id);
|
||||||
|
}
|
||||||
|
|
||||||
|
# This will be raised by any packet with RH0 regardless of segments left.
|
||||||
|
event flow_weird(name: string, src: addr, dst: addr)
|
||||||
|
{
|
||||||
|
print fmt("flow_weird %s from %s to %s", name, src, dst);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue