mirror of
https://github.com/zeek/zeek.git
synced 2025-10-03 15:18:20 +00:00
281 lines
6.4 KiB
Text
281 lines
6.4 KiB
Text
@load http
|
|
@load app-summary
|
|
|
|
redef capture_filters = {
|
|
["http"] = "tcp port 80 or tcp port 8080 or tcp port 8000 or tcp port 8888 or tcp port 3128",
|
|
["ipp"] = "tcp port 631",
|
|
};
|
|
|
|
module HTTP_summary;
|
|
|
|
global log = open_log_file("http-summary") &redef;
|
|
|
|
type http_transaction: record {
|
|
# standard stuff
|
|
connection_id: conn_id;
|
|
conn_start: time;
|
|
func: string;
|
|
start: time;
|
|
num_req: count;
|
|
req_size: count;
|
|
num_resp: count;
|
|
resp_size: count;
|
|
|
|
# for tracking the state
|
|
req_done: bool;
|
|
resp_done: bool;
|
|
done: bool;
|
|
|
|
# http-specific stuff
|
|
code: count;
|
|
req_content_type: string;
|
|
resp_content_type: string;
|
|
conditional_get: string;
|
|
user_agent: string;
|
|
cache_control: string;
|
|
last_modified: string;
|
|
etag: string;
|
|
};
|
|
|
|
type http_trans_group: record {
|
|
trans: table[count] of http_transaction;
|
|
first_req: count;
|
|
last_req: count;
|
|
};
|
|
|
|
global http_trans_table: table[conn_id] of http_trans_group;
|
|
|
|
function lookup_http_trans_group(id: conn_id, create: bool): http_trans_group
|
|
{
|
|
if ( id !in http_trans_table )
|
|
{
|
|
if ( create )
|
|
{
|
|
local trans: table[count] of http_transaction;
|
|
http_trans_table[id] = [
|
|
$trans = trans, $first_req = 1, $last_req = 0];
|
|
}
|
|
else
|
|
print fmt("HTTP trans_group not found: %s", conn_id_string(id));
|
|
}
|
|
|
|
return http_trans_table[id];
|
|
}
|
|
|
|
function new_http_transaction(c: connection, func: string): http_transaction
|
|
{
|
|
# print fmt("new http trans: %.6f %s", network_time(), func);
|
|
local g = lookup_http_trans_group(c$id, T);
|
|
|
|
local t = [
|
|
$connection_id = c$id,
|
|
$conn_start = c$start_time,
|
|
$func = func,
|
|
$start = network_time(),
|
|
$num_req = 0, $req_size = 0,
|
|
$num_resp = 0, $resp_size = 0,
|
|
$req_done = F, $resp_done = F, $done = F,
|
|
$code = 0,
|
|
$req_content_type = "none",
|
|
$resp_content_type = "none",
|
|
$conditional_get = "no",
|
|
$user_agent = "none",
|
|
$cache_control = "none",
|
|
$last_modified = "none",
|
|
$etag = "none"];
|
|
|
|
++g$last_req;
|
|
g$trans[g$last_req] = t;
|
|
|
|
return t;
|
|
}
|
|
|
|
function lookup_http_transaction(id: conn_id, is_orig: bool): http_transaction
|
|
{
|
|
local g = lookup_http_trans_group(id, F);
|
|
local index = is_orig ? g$last_req : g$first_req;
|
|
|
|
if ( index !in g$trans )
|
|
{
|
|
print fmt("HTTP transaction not found: %s : %d-%d",
|
|
conn_id_string(id), g$first_req, g$last_req);
|
|
}
|
|
|
|
return g$trans[index];
|
|
}
|
|
|
|
function end_http_transaction(t: http_transaction)
|
|
{
|
|
if ( t$req_done && t$resp_done )
|
|
{
|
|
if ( t$done )
|
|
return;
|
|
t$done = T;
|
|
print_app_summary(log, t$connection_id, t$conn_start, t$func, t$start,
|
|
t$num_req, t$req_size,
|
|
t$num_resp, t$resp_size,
|
|
fmt("code %d content_type_^ %s content_type_v %s conditional_get %s user_agent %s cache_control %s last_modified %s etag %s",
|
|
t$code,
|
|
t$req_content_type, t$resp_content_type,
|
|
t$conditional_get,
|
|
subst_string(t$user_agent, " ", "_"),
|
|
subst_string(t$cache_control, " ", ""),
|
|
t$last_modified == "none" ? "none" : "present",
|
|
t$etag == "none" ? "none" : "present"
|
|
));
|
|
}
|
|
}
|
|
|
|
event http_request(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string)
|
|
{
|
|
# print fmt("http request");
|
|
local t = new_http_transaction(c, method);
|
|
++t$num_req;
|
|
t$req_done = F;
|
|
}
|
|
|
|
event http_reply(c: connection, version: string, code: count, reason: string)
|
|
{
|
|
# print fmt("http reply");
|
|
local id = c$id;
|
|
local g = lookup_http_trans_group(id, T);
|
|
local t: http_transaction;
|
|
if ( g$first_req in g$trans )
|
|
t = g$trans[g$first_req];
|
|
else
|
|
t = new_http_transaction(c, "none");
|
|
|
|
++t$num_resp;
|
|
t$code = code;
|
|
t$resp_done = F;
|
|
}
|
|
|
|
function http_request_done(c: connection, stat: http_message_stat)
|
|
{
|
|
# print fmt("http request done");
|
|
local t = lookup_http_transaction(c$id, T);
|
|
t$req_size = t$req_size + stat$body_length;
|
|
t$req_done = T;
|
|
end_http_transaction(t);
|
|
}
|
|
|
|
function http_reply_done(c: connection, stat: http_message_stat)
|
|
{
|
|
# print fmt("http reply done");
|
|
local t = lookup_http_transaction(c$id, F);
|
|
t$resp_size = t$resp_size + stat$body_length;
|
|
if ( t$code >= 200 )
|
|
{
|
|
t$resp_done = T;
|
|
end_http_transaction(t);
|
|
local g = lookup_http_trans_group(t$connection_id, F);
|
|
++g$first_req;
|
|
}
|
|
}
|
|
|
|
event http_message_done(c: connection, is_orig: bool, stat: http_message_stat)
|
|
{
|
|
if ( is_orig )
|
|
http_request_done(c, stat);
|
|
else
|
|
http_reply_done(c, stat);
|
|
}
|
|
|
|
event http_content_type(c: connection, is_orig: bool, ty: string, subty: string)
|
|
{
|
|
local t = lookup_http_transaction(c$id, is_orig);
|
|
local type_str = fmt("%s/%s", ty, subty);
|
|
if ( is_orig )
|
|
t$req_content_type = type_str;
|
|
else
|
|
t$resp_content_type = type_str;
|
|
}
|
|
|
|
function http_conditional_get(c: connection, is_orig: bool, h: mime_header_rec)
|
|
{
|
|
local t = lookup_http_transaction(c$id, is_orig);
|
|
t$conditional_get = h$name;
|
|
}
|
|
|
|
function http_user_agent(c: connection, is_orig: bool, h: mime_header_rec)
|
|
{
|
|
local t = lookup_http_transaction(c$id, is_orig);
|
|
t$user_agent = h$value;
|
|
}
|
|
|
|
function http_cache_control(c: connection, is_orig: bool, h: mime_header_rec)
|
|
{
|
|
local t = lookup_http_transaction(c$id, is_orig);
|
|
t$cache_control = h$value;
|
|
}
|
|
|
|
function http_last_modified(c: connection, is_orig: bool, h: mime_header_rec)
|
|
{
|
|
local t = lookup_http_transaction(c$id, is_orig);
|
|
t$last_modified = h$value;
|
|
}
|
|
|
|
function http_etag(c: connection, is_orig: bool, h: mime_header_rec)
|
|
{
|
|
local t = lookup_http_transaction(c$id, is_orig);
|
|
t$etag = h$value;
|
|
}
|
|
|
|
# type mime_header_rec: record {
|
|
# name: string;
|
|
# value: string;
|
|
# };
|
|
# type mime_header_list: table[count] of mime_header_rec;
|
|
|
|
const conditional_get_headers = {
|
|
"IF-MODIFIED-SINCE",
|
|
"IF-UNMODIFIED-SINCE",
|
|
"IF-MATCH",
|
|
"IF-NONE-MATCH",
|
|
"IF-RANGE",
|
|
};
|
|
|
|
event http_all_headers(c: connection, is_orig: bool, hlist: mime_header_list)
|
|
{
|
|
if ( ! is_orig )
|
|
return;
|
|
|
|
for ( i in hlist )
|
|
{
|
|
local h = hlist[i];
|
|
if ( h$name in conditional_get_headers )
|
|
http_conditional_get(c, is_orig, h);
|
|
if ( h$name == "USER-AGENT" )
|
|
http_user_agent(c, is_orig, h);
|
|
if ( h$name == "CACHE-CONTROL" )
|
|
http_cache_control(c, is_orig, h);
|
|
if ( h$name == "LAST-MODIFIED" )
|
|
http_last_modified(c, is_orig, h);
|
|
if ( h$name == "ETAG" )
|
|
http_etag(c, is_orig, h);
|
|
}
|
|
}
|
|
|
|
function end_http_trans_group(g: http_trans_group, index: count)
|
|
{
|
|
if ( index !in g$trans )
|
|
return;
|
|
local t = g$trans[index];
|
|
|
|
t$req_done = T;
|
|
t$resp_done = T;
|
|
end_http_transaction(t);
|
|
|
|
delete g$trans[index];
|
|
end_http_trans_group(g, index + 1);
|
|
}
|
|
|
|
event connection_state_remove(c: connection)
|
|
{
|
|
local id = c$id;
|
|
if ( id in http_trans_table )
|
|
{
|
|
end_http_trans_group(http_trans_table[id], 1);
|
|
delete http_trans_table[id];
|
|
}
|
|
}
|