i’m facing a big problem i have a lot of ASA firewalls which are sending around 500 GB /day to the graylog box,
and because i have 14 grok extractors for that input sometimes the CPU goes through the roof, and sometimes i’m facing issues with loosing logs… which is not good at all.
now the question is can i write some kind of input plugin dedicated only for CISCO ASA firewalls to parse those messages without forcing the CPU to work hard?
if the answer is probably yes, can you offer me some guidance, considering the fact that i have 0 programming experience? i know something about python but not a lot…
Are you using pipelines at all, or just running the 14 extractors on every message? It might be useful to consider moving to pipelines, if only to reduce the amount of regex work needed to get those messages parsed. We still use extractors on our ASA logs, and haven’t moved those logs to pipelines yet. If you don’t get any immediate answers, I will take a look converting our ASA logs to pipelines and see it it makes a difference for cpu load.
As long as you have enough disk journal available and cpu to get through the day, you shouldn’t be loosing logs. If you are taking in more than you can process and get continually further and further behind, something will need to change.
many thanks for the help, the problem is that i have arround 20k msg/s and in the next months i’m expecting for something like 35k or 40k…
i’m not loosing too much but a considerable amount…
i did the rule(down bellow), however i get a an error at the line with let asa7, it says: “invalid expression line 14 column 110”
at column 110 i have “from” as a word i don’t think this should be any problem… right?
rule “ASA firewall grok”
when
has_field(“message”)
then
let message_field = to_string($message.message);
let asa1 = grok(pattern: "%{CISCO_APP:application} client %{DATA:src_interface}:%{IPV4:src_ip}(/%{INT:src_port})", value: message_field, only_named_captures: true);
let asa2 = grok(pattern: "%{CISCO_ACTION:action} %{WORD:protocol} src %{DATA:src_interface}:%{IPV4:src_ip}(/%{INT:src_port})?(\(%{DATA:src_fwuser}\))? dst %{DATA:dst_interface}:%{IPV4:dst_ip}(/%{INT:dst_port})?(\(%{DATA:dst_fwuser}\))?( \(type %{INT:icmp_type}, code %{INT:icmp_code}\))? by access-group %{DATA:access_group} \[%{DATA:hashcode1}, %{DATA:hashcode2}\]", value: message_field, only_named_captures: true);
let asa3 = grok(pattern: "%{CISCO_ACTION:action} local-host %{DATA:dst_interface}:%{IPV4:dst_ip}", value: message_field, only_named_captures: true);
let asa4 = grok(pattern: "%{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} from %{IPV4:src_ip}/%{INT:src_port} to %{IPV4:dst_ip}/%{INT:dst_port} due to %{CISCO_REASON:reason}", value: message_field, only_named_captures: true);
let asa5 = grok(pattern: "%{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} from %{IPV4:src_ip}/%{INT:src_port} to %{IPV4:dst_ip}/%{INT:dst_port} on interface %{DST_ACCT:dst_interface}", value: message_field, only_named_captures: true);
let asa6 = grok(pattern: "%{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} from %{IPV4:src_ip}/%{INT:src_port} to %{IPV4:dst_ip}/%{INT:dst_port} on interface %{DST_ACCT:dst_interface}", value: message_field, only_named_captures: true);
let asa7 = grok(pattern: "%{CISCO_ACTION:action} %{CISCO_XLATE_TYPE:xlate_type} %{WORD:protocol} translation from %{DATA:src_interface}:%{IPV4:src_ip}(/%{INT:src_port})?(\(%{DATA:src_fwuser}\))? to %{DATA:src_xlated_interface}:%{IPV4:src_xlated_ip}/%{INT:src_xlated_port}", value: message_field, only_named_captures: true);
let asa8 = grok(pattern: "%{CISCO_REASON:reason} for %{CISCO_XLATE_TYPE:xlate_type} %{WORD:protocol} translation from %{DATA:src_interface}:%{IPV4:src_ip}/%{INT:src_port}( \(%{IPV4:src_mapped_ip}/%{INT:src_mapped_port}\))?(\(%{DATA:src_fwuser}\))? to %{DATA:dst_interface}:%{IPV4:dst_ip}/%{INT:dst_port}( \(%{IPV4:dst_mapped_ip}/%{INT:dst_mapped_port}\))?", value: message_field, only_named_captures: true);
let asa9 = grok(pattern: "%{CISCO_REASON:reason} from %{DATA:src_interface}:%{IPV4:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IPV4:dst_ip}/%{INT:dst_port} with different initial sequence number", value: message_field, only_named_captures: true);
let asa10 = grok(pattern: "%{CISCO_IPS:Detected_by_IPS} requested to %{CISCO_ACTION:action} %{WORD:protocol} packet from %{DATA:src_interface}:%{IPV4:src_ip}(/%{INT:src_port}) to %{DATA:dst_interface}:%{IPV4:dst_ip}(/%{INT:dst_port})", value: message_field, only_named_captures: true);
let asa11 = grok(pattern: "access-list %{DATA:acl_name} %{CISCO_ACTION:action} %{WORD:protocol} for user %{DATA:src_fwuser} %{DATA:src_interface}/%{IPV4:src_ip}\(%{INT:src_port}\)(\(%{DATA:src_fwuser}\))? -> %{DATA:dst_interface}/%{IPV4:dst_ip}\(%{INT:dst_port}\)(\(%{DATA:src_fwuser}\))? hit-cnt %{INT:hit_count} %{CISCO_INTERVAL:interval} \[%{DATA:hashcode1}, %{DATA:hashcode2}\]", value: message_field, only_named_captures: true);
let asa12 = grok(pattern: "%{WORD:protocol} (?:request|access) %{CISCO_ACTION:action} from %{IPV4:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IPV4:dst_ip}/%{INT:dst_port}", value: message_field, only_named_captures: true);
let asa13 = grok(pattern: "%{CISCO_APP:application} client %{DATA:src_interface}:%{IPV4:src_ip}(/%{INT:src_port})", value: message_field, only_named_captures: true);
set_fields(asa1);
set_fields(asa2);
set_fields(asa3);
set_fields(asa4);
set_fields(asa5);
set_fields(asa6);
set_fields(asa7);
set_fields(asa8);
set_fields(asa9);
set_fields(asa10);
set_fields(asa11);
set_fields(asa12);
set_fields(asa13);
how would you parse this message?
Aug 15 2018 10:46:33: %ASA-6-302014: Teardown TCP connection 1576899401 for outside:10.3.128.40/55258(LOCAL\james.smith) to inside:10.10.1.10/80 duration 0:03:15 bytes 916787 TCP Reset-I (james.smith)
because i have to brake everything into small thing. with grok extractors it’s easy, but with rule for pipelines doesn’t work…
for this one here is what i have as a grok extractor:
%{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} connection %{INT:connection_id} for %{DATA:src_interface}:%{IPV4:src_ip}/%{INT:src_port}( (%{IPV4:src_mapped_ip}/%{INT:src_mapped_port}))?((%{DATA:src_fwuser}))? to %{DATA:dst_interface}:%{IPV4:dst_ip}/%{INT:dst_port}( (%{IPV4:dst_mapped_ip}/%{INT:dst_mapped_port}))?((%{DATA:dst_fwuser}))?( duration %{TIME:duration} bytes %{INT:bytes})?(?: %{CISCO_REASON:reason})?( (%{DATA:user}))?
can you figure out how can i have the same result with a rule for a pipeline?
that seems to work, but i will have quite a number of rules. once i will have everything finished, can you post the rule somewhere? maybe others will find it helpful
@do you know when version 3 will be released? for example in 2 months time?
i have finishted the rule for the pipeline, i’ll continue working on it
this is what i have so far
rule “ASA firewall grok”
when
has_field(“message”)
then
let message_field = to_string($message.message);
let asa1 = grok(pattern: "%{CISCO_APP:application} client %{DATA:src_interface}:%{IPV4:src_ip}(/%{INT:src_port})", value: message_field, only_named_captures: true);
let asa2 = grok(pattern: "%{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} from %{IPV4:src_ip}/%{INT:src_port} to %{IPV4:dst_ip}/%{INT:dst_port} due to %{CISCO_REASON:reason}", value: message_field, only_named_captures: true);
let asa3 = grok(pattern: "%{CISCO_ACTION:action} local-host %{DATA:dst_interface}:%{IPV4:dst_ip}", value: message_field, only_named_captures: true);
let asa4 = grok(pattern: "%{WORD:protocol} (?:request|access) %{CISCO_ACTION:action} from %{IPV4:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IPV4:dst_ip}/%{INT:dst_port}", value: message_field, only_named_captures: true);
let asa5 = grok(pattern: "%{CISCO_IPS:Detected_by_IPS} requested to %{CISCO_ACTION:action} %{WORD:protocol} packet from %{DATA:src_interface}:%{IPV4:src_ip}(/%{INT:src_port}) to %{DATA:dst_interface}:%{IPV4:dst_ip}(/%{INT:dst_port})", value: message_field, only_named_captures: true);
let asa6 = grok(pattern: "%{CISCO_REASON:reason} from %{DATA:src_interface}:%{IPV4:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IPV4:dst_ip}/%{INT:dst_port} with different initial sequence number", value: message_field, only_named_captures: true);
let asa7 = grok(pattern: "%{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} from %{IPV4:src_ip}/%{INT:src_port} to %{IPV4:dst_ip}/%{INT:dst_port} on interface %{DST_ACCT:dst_interface}", value: message_field, only_named_captures: true);
let asa8 = grok(pattern: "%{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} connection %{INT:connection_id} for %{DATA:src_interface}:%{IPV4:src_ip}/%{INT:src_port} to %{DATA:dst_interface}:%{IPV4:dst_ip}/%{INT:dst_port} duration %{TIME:duration} bytes %{INT:bytes}", value: message_field, only_named_captures: true);
let asa9 = grok(pattern: "%{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} connection %{INT:connection_id} for %{DATA:src_interface}:%{IPV4:src_ip}/%{INT:src_port}( %{DATA:UNWANTED}) to %{DATA:dst_interface}:%{IPV4:dst_ip}/%{INT:dst_port}( %{DATA:UNWANTED})", value: message_field, only_named_captures: true);
let asa10 = grok(pattern: "%{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} connection for faddr %{IPV4:dst_ip}/%{INT:icmp_seq_num}(?:(%{DATA:user}))? gaddr %{IPV4:src_xlated_ip}/%{INT:icmp_code_xlated} laddr %{IPV4:src_ip}/%{INT:icmp_code}( (%{DATA:user}))?", value: message_field, only_named_captures: true);
let asa11 = grok(pattern: "%{CISCO_ACTION:action}(?: %{CISCO_DIRECTION:direction})? %{WORD:protocol} connection %{INT:connection_id} for %{DATA:src_interface}:%{IPV4:src_ip}/%{INT:src_port}(?:(%{DATA:user}))? to %{DATA:dst_interface}:%{IPV4:dst_ip}/%{INT:dst_port} duration %{TIME:duration} bytes %{INT:bytes}( (%{DATA:user}))?", value: message_field, only_named_captures: true);
let asa12 = grok(pattern: "%{CISCO_ACTION:action} %{WORD:protocol} src %{DATA:src_interface}:%{IPV4:src_ip}(/%{INT:src_port})?((%{DATA:user}))?dst %{DATA:dst_interface}:%{IPV4:dst_ip}(/%{INT:dst_port})?((%{DATA:user})) by access-group %{DATA:access_group}", value: message_field, only_named_captures: true);
let asa13 = grok(pattern: "%{CISCO_ACTION:action} %{CISCO_XLATE_TYPE:xlate_type} %{WORD:protocol} translation from %{DATA:src_interface}:%{IPV4:src_ip}(/%{INT:src_port})?((%{DATA:user}))? to %{DATA:src_xlated_interface}:%{IPV4:src_xlated_ip}/%{INT:src_xlated_port}", value: message_field, only_named_captures: true);
let asa14 = grok(pattern: "%{CISCO_ACTION:action} %{WORD:protocol} %{CISCO_REASON:reason} from %{IPV4:src_ip}/%{INT:src_port} to %{IPV4:dst_ip}/%{INT:dst_port} flags %{CISCO_FLAGS:tcp_flags} on interface %{GREEDYDATA:interface}", value: message_field, only_named_captures: true);
let asa15 = grok(pattern: "%{IP:dst_ip} Accessed URL %{GREEDYDATA:url}?", value: message_field, only_named_captures: true);
let asa16 = grok(pattern: "Starting %{CISCO_SSL:ssl} with client %{DATA:dst_interface}:%{IPV4:dst_ip}(/%{INT:dst_port})", value: message_field, only_named_captures: true);
let asa17 = grok(pattern: "%{CISCO_SSL:ssl} %{DATA:dst_interface}:%{IPV4:dst_ip}(/%{INT:dst_port})", value: message_field, only_named_captures: true);
let asa18 = grok(pattern: "%{CISCO_SSL:ssl} with client %{DATA:dst_interface}:%{IPV4:dst_ip}(/%{INT:dst_port})", value: message_field, only_named_captures: true);
set_fields(asa1);
set_fields(asa2);
set_fields(asa3);
set_fields(asa4);
set_fields(asa5);
set_fields(asa6);
set_fields(asa7);
set_fields(asa8);
set_fields(asa9);
set_fields(asa10);
set_fields(asa11);
set_fields(asa12);
set_fields(asa13);
set_fields(asa14);
set_fields(asa15);
set_fields(asa16);
set_fields(asa17);
set_fields(asa18);
when i receive logs from ASA with a source of 10.16.10.6, i want to create another field using pipelines called ASA_host which has the firewall name of Jerry-01
and the same for firewall Tom
i have created the following pipeline:
rule “ASA lookup names”
when
has_field(“source”)
then
let ASA_host = lookup_value(to_string("source", $message.source), "source");
set_field("ASA_host");
end
but it’s not working, can you guys help me out with this one?