# Author: Justin Henderson
#         SANS Instructor and author of SANS SEC555: SIEM and Tactical Analytics
# Email: justin@hasecuritysolution.com
# Last Update: 12/9/2016

filter {
  if [type] == "dns" and "bro" not in [tags] {
    json {
      source => "message"
    }
    # strip whitespace from message field
    mutate {
      strip => "message"
    }
    # If the message is blank, drop the log
    if [Message] =~ /^$/ {
      drop {  }
    } else {
      if [type] == "dns" {
  	  # This section is lookup for a match against the log and parsing out the fields
        grok {
          match => { "Message" => "(?<timestamp>%{DATE_US} %{TIME} (?:AM|PM))\s+%{DATA:thread_id}\s+%{WORD:dns_type}\s+ %{BASE16NUM:packet_id}\s+%{WORD:dns_protocol}\s+%{WORD:dns_direction}\s+%{IP:dns_ip}\s+ %{BASE16NUM:xid}\s+%{DATA:response}\s+%{WORD:dns_query_type}\s+\[%{BASE16NUM:hex_flags}\s+%{WORD:flags}\s+ %{WORD:rcode_name}\]\s+%{WORD:query_type_name}\s+%{GREEDYDATA:dns_domain}"}
          match => { "Message" => "(?<timestamp>%{DATE_US} %{TIME} (?:AM|PM))\s+%{DATA:thread_id}\s+%{WORD:dns_type}\s+ %{BASE16NUM:packet_id}\s+%{WORD:dns_protocol}\s+%{WORD:dns_direction}\s+%{IP:dns_ip}\s+ %{BASE16NUM:xid}\s+%{DATA:response}\s+%{WORD:dns_query_type}\s+\[%{BASE16NUM:hex_flags}\s+%{WORD:flags}\s+%{WORD:recursion}\s+%{WORD:rcode_name}\]\s+%{WORD:query_type_name}\s+%{GREEDYDATA:dns_domain}"}
          match => { "Message" => "(?<timestamp>%{DATE_US} %{TIME} (?:AM|PM))\s+%{DATA:thread_id}\s+%{WORD:dns_type}\s+ %{BASE16NUM:packet_id}\s+%{WORD:dns_protocol}\s+%{WORD:dns_direction}\s+%{IP:dns_ip}\s+ %{BASE16NUM:xid}\s+%{DATA:response}\s+%{WORD:dns_query_type}\s+\[%{BASE16NUM:hex_flags}\s+%{WORD:recursion}\s+%{WORD:rcode_name}\]\s+%{WORD:query_type_name}\s+%{GREEDYDATA:dns_domain}"}
          match => { "Message" => "(?<timestamp>%{DATE_US} %{TIME} (?:AM|PM))\s+%{DATA:thread_id}\s+%{WORD:dns_type}\s+ %{BASE16NUM:packet_id}\s+%{WORD:dns_protocol}\s+%{WORD:dns_direction}\s+%{IP:dns_ip}\s+ %{BASE16NUM:xid}\s+%{DATA:response}\s+%{WORD:dns_query_type}\s+\[%{BASE16NUM:hex_flags}\s+%{WORD:rcode_name}\]\s+%{WORD:query_type_name}\s+%{GREEDYDATA:dns_domain}"}
          match => { "Message" => "(?<timestamp>%{DATE_US} %{TIME} (?:AM|PM))\s+%{DATA:thread_id}\s+%{WORD:dns_type}\s+ %{BASE16NUM:packet_id}\s+%{WORD:dns_protocol}\s+%{WORD:dns_direction}\s+%{IP:dns_ip}\s+ %{BASE16NUM:xid}\s+%{WORD:dns_query_type}\s+\[%{BASE16NUM:hex_flags}\s+%{WORD:flags}\s+ %{WORD:rcode_name}\]\s+%{WORD:query_type_name}\s+%{GREEDYDATA:dns_domain}"}
          # Server 2003 DNS logs do not include slashes or AM/PM in timestamp
          match => { "Message" => "(?<timestamp>%{YEAR}%{MONTHNUM}%{MONTHDAY} %{TIME})\s+%{DATA:thread_id}\s+%{WORD:dns_type}\s+ %{BASE16NUM:packet_id}\s+%{WORD:dns_protocol}\s+%{WORD:dns_direction}\s+%{IP:dns_ip}\s+ %{BASE16NUM:xid}\s+%{DATA:response}\s+%{WORD:dns_query_type}\s+\[%{BASE16NUM:hex_flags}\s+%{WORD:flags}\s+ %{WORD:rcode_name}\]\s+%{WORD:query_type_name}\s+%{GREEDYDATA:dns_domain}"}
          match => { "Message" => "(?<timestamp>%{YEAR}%{MONTHNUM}%{MONTHDAY} %{TIME})\s+%{DATA:thread_id}\s+%{WORD:dns_type}\s+ %{BASE16NUM:packet_id}\s+%{WORD:dns_protocol}\s+%{WORD:dns_direction}\s+%{IP:dns_ip}\s+ %{BASE16NUM:xid}\s+%{DATA:response}\s+%{WORD:dns_query_type}\s+\[%{BASE16NUM:hex_flags}\s+%{WORD:flags}\s+%{WORD:recursion}\s+%{WORD:rcode_name}\]\s+%{WORD:query_type_name}\s+%{GREEDYDATA:dns_domain}"}
          match => { "Message" => "(?<timestamp>%{YEAR}%{MONTHNUM}%{MONTHDAY} %{TIME})\s+%{DATA:thread_id}\s+%{WORD:dns_type}\s+ %{BASE16NUM:packet_id}\s+%{WORD:dns_protocol}\s+%{WORD:dns_direction}\s+%{IP:dns_ip}\s+ %{BASE16NUM:xid}\s+%{DATA:response}\s+%{WORD:dns_query_type}\s+\[%{BASE16NUM:hex_flags}\s+%{WORD:recursion}\s+%{WORD:rcode_name}\]\s+%{WORD:query_type_name}\s+%{GREEDYDATA:dns_domain}"}
          match => { "Message" => "(?<timestamp>%{YEAR}%{MONTHNUM}%{MONTHDAY} %{TIME})\s+%{DATA:thread_id}\s+%{WORD:dns_type}\s+ %{BASE16NUM:packet_id}\s+%{WORD:dns_protocol}\s+%{WORD:dns_direction}\s+%{IP:dns_ip}\s+ %{BASE16NUM:xid}\s+%{DATA:response}\s+%{WORD:dns_query_type}\s+\[%{BASE16NUM:hex_flags}\s+%{WORD:rcode_name}\]\s+%{WORD:query_type_name}\s+%{GREEDYDATA:dns_domain}"}
          match => { "Message" => "(?<timestamp>%{YEAR}%{MONTHNUM}%{MONTHDAY} %{TIME})\s+%{DATA:thread_id}\s+%{WORD:dns_type}\s+ %{BASE16NUM:packet_id}\s+%{WORD:dns_protocol}\s+%{WORD:dns_direction}\s+%{IP:dns_ip}\s+ %{BASE16NUM:xid}\s+%{WORD:dns_query_type}\s+\[%{BASE16NUM:hex_flags}\s+%{WORD:flags}\s+ %{WORD:rcode_name}\]\s+%{WORD:query_type_name}\s+%{GREEDYDATA:dns_domain}"}
          remove_field => [ "Message" ]
        }
  	  # This section attempts to convert the dns_domain into the traditional domain.com format
        mutate {
          gsub => [ "dns_domain", "(\(\d+\))", "." ]
        }
        grok {
          match => { "dns_domain" => "\.%{DATA:query}\.$" }
          remove_field => [ "dns_domain" ]
        }
      }
    }
	mutate {
		#add_tag => [ "conf_file_6301"]
	}
  }
}
