# Copyright (c) 2010 Flowerfire, Inc. All Rights Reserved. cisco_vpnconcentrator = { plugin_version = "1.7" info.1.manfacturer = "Cisco" info.1.device = "VPN Concentrator" info.1.version.1 = "3000" # 2006-03-19: 1.1: added vpn_sessions field, to track sessions; added "decomposition" style parsing filter for disconnect lines, to handle more variants. # 2007-01-12 - 1.2 - GMF - Restored duration tracking when duration is on line by itself. # 2007-02-15 - 1.3 - GMF - added support for extracting source IP in formats where Group/User is on the second line. # 2007-02-22 - 1.4 - GMF - Reinstated Duration line filter, to support formats where Duration is alone on a line. # 2008-04-24 - 1.5 - GMF - Added support for ARP request and reply lines # 2008-04-25 - 1.6 - GMF - Added support for a slight variant # 2011-02-16 - 1.7 - MSG - Made a comma after User in connected lines optional # SEV=4 AUTH/22 RPT=4949 User [client-user1] Group [client-group] # Cisco VPN Concentrator # sessions, hits, bandwidth, pageviews, and visitors. # The name of the log format log.format.format_label = "Cisco VPN Concentrator" log.miscellaneous.log_data_type = "syslog_required" log.miscellaneous.log_format_type = "network_device" # The log is in this format if any of the first ten lines match this regular expression log.format.autodetect_regular_expression = "SEV=[0-9]+ [A-Z]+/[0-9]+ RPT=[0-9]+ [0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+" # All log field parsing will be done using the parsing filters log.format.parse_only_with_filters = "true" # There's no maximum duration or session timeout-- sessions just timeout # when the connection is terminated. statistics.miscellaneous.maximum_session_duration = "0" statistics.miscellaneous.session_timeout = "0" statistics.miscellaneous.session_logout_regexp = "(Connection terminated)" #ignore_newlines_after_log_line_regexp ' $' # An entry is an event statistics.miscellaneous.entry_name = "events" # Log fields log.fields = { severity = { label = "$lang_stats.field_labels.severity" type = "flat" index = 0 subindex = 0 } # severity operation = { label = "$lang_stats.field_labels.operation" type = "flat" index = 0 subindex = 0 } # operation user = { label = "$lang_stats.field_labels.user" type = "flat" index = 0 subindex = 0 } # user group = { label = "$lang_stats.field_labels.group" type = "flat" index = 0 subindex = 0 } # group cn = { label = "$lang_stats.field_labels.cn" type = "flat" index = 0 subindex = 0 } # cn sn = { label = "$lang_stats.field_labels.sn" type = "flat" index = 0 subindex = 0 } # sn sa = { label = "$lang_stats.field_labels.sa" type = "flat" index = 0 subindex = 0 } # sa status = { label = "$lang_stats.field_labels.status" type = "flat" index = 0 subindex = 0 } # status payload = { label = "$lang_stats.field_labels.payload" type = "flat" index = 0 subindex = 0 } # payload protocol = { label = "$lang_stats.field_labels.protocol" type = "flat" index = 0 subindex = 0 } # protocol port = { label = "$lang_stats.field_labels.port" type = "flat" index = 0 subindex = 0 } # port source_host = { label = "$lang_stats.field_labels.source_host" type = "host" index = 0 subindex = 0 hierarchy_dividers = "." left_to_right = false leading_divider = "false" } # source_host inbound_spi = { label = "$lang_stats.field_labels.inbound_spi" type = "flat" index = 0 subindex = 0 } # inbound_spi outbound_spi = { label = "$lang_stats.field_labels.outbound_spi" type = "flat" index = 0 subindex = 0 } # outbound_spi server_host = { label = "$lang_stats.field_labels.server_host" type = "flat" index = 0 subindex = 0 } # server_host local_proxy_host = { label = "$lang_stats.field_labels.local_proxy_host" type = "flat" index = 0 subindex = 0 } # local_proxy_host local_proxy_subnet = { label = "$lang_stats.field_labels.local_proxy_subnet" type = "flat" index = 0 subindex = 0 } # local_proxy_subnet local_proxy_mask = { label = "$lang_stats.field_labels.local_proxy_mask" type = "flat" index = 0 subindex = 0 } # local_proxy_mask remote_proxy_host = { label = "$lang_stats.field_labels.remote_proxy_host" type = "flat" index = 0 subindex = 0 } # remote_proxy_host remote_proxy_subnet = { label = "$lang_stats.field_labels.remote_proxy_subnet" type = "flat" index = 0 subindex = 0 } # remote_proxy_subnet remote_proxy_mask = { label = "$lang_stats.field_labels.remote_proxy_mask" type = "flat" index = 0 subindex = 0 } # remote_proxy_mask bytes_sent = { label = "$lang_stats.field_labels.bytes_sent" type = "flat" index = 0 subindex = 0 } # bytes_sent bytes_received = { label = "$lang_stats.field_labels.bytes_received" type = "flat" index = 0 subindex = 0 } # bytes_received duration = { label = "$lang_stats.field_labels.duration" type = "duration_hms" index = 0 subindex = 0 } # duration reason = { label = "$lang_stats.field_labels.reason" type = "flat" index = 0 subindex = 0 } # reason session_type = "" arp_ip = "" arp_mac = "" vpn_sessions = "" } # log.fields # # Log Parsing Filters log.parsing_filters = { # Accept on SEV= lines. This is necessary to support both types of VPN logs-- those # where everything is one one line, and those where entries are split across multiple # lines. This accepts the current entry (which may span multiple lines) on the first # (and possibly only) line of the next entry. # Multi line example: #54673 10/30/2006 19:49:03.970 SEV=5 IKE/75 RPT=5528 66.166.66.66 #Group [Sales] User [grouchy] #Overriding Initiator's IPSec rekeying duration from 2147483 to 28800 seconds # #54675 10/30/2006 19:49:03.980 SEV=5 IKE/25 RPT=5529 66.166.66.66 #Group [Sales] User [grouchy] #Received remote Proxy Host data in ID Payload: #Address 176.16.6.6, Protocol 0, Port 0 1 = { label = "1" comment = "" value = "accept_collected_entry_using_regexp('()SEV=', false)" } # 1 # Parse out the severity information 2 = { label = "2" comment = "" value = "collect_fields_using_regexp('()SEV=([0-9] [^ ]*) ', '*KEY*,severity')" } # 2 # Parse an extended Group/User line 3 = { label = "3" comment = "" value = "collect_fields_using_regexp('()RPT=[0-9]*:* ([0-9.]*):* +Group \\\\[([^]]*)\\\\] User \\\\[([^]]*)\\\\] (.*)$', '*KEY*,source_host,group,user,operation')" } # 3 # 2011-02-16 - 1.7 - MSG - Made a comma after User in connected lines optional # Parse a User, Group connected line 4 = { label = "4" comment = "" value = "collect_fields_using_regexp('()RPT=[0-9]*:* User \\\\[([^]]*)\\\\],? Group \\\\[([^]]*)\\\\] (connected)', '*KEY*,user,group,operation')" } # 4 # Parse a User, Group disconnected line 5 = { label = "5" comment = "" value = "collect_fields_using_regexp('()RPT=[0-9]* ([^ ]*) User \\\\[([^]]*)\\\\], Group \\\\[([^]]*)\\\\] (disconnected): Duration: ([0-9:]+) Bytes xmt: ([0-9]+) Bytes rcv: ([0-9]+) Reason: (.*)$', '*KEY*,source_host,user,group,operation,duration,bytes_sent,bytes_received,reason')" } # 5 # Parse disconnected line (short format) disconnected = { label = "disconnected" comment = "" value = "collect_fields_using_regexp('()User \\\\[([^]]*)\\\\] Group \\\\[([^]]*)\\\\] (disconnected):', '*KEY*,user,group,operation')" } # disconnected # Parse Duration. # 2007-01-12: this was commented out, but has to be here to extract Duration on its own line - GMF. #11703 12/10/2006 14:06:29.380 SEV=4 AUTH/28 RPT=7175 7.116.8.86 #User [rasmith] Group [MIS] disconnected: # Session Type: IPSec/UDP # Duration: 0:22:32 # Bytes xmt: 49728 # Bytes rcv: 55576 # Reason: User Requested duration = { label = "duration" comment = "" value = "collect_fields_using_regexp('() Duration: ([0-9:]+)', '*KEY*,duration')" } # duration # Parse bytes sent sent = { label = "sent" comment = "" value = "collect_fields_using_regexp('() Bytes xmt: ([0-9]+)', '*KEY*,bytes_sent')" } # sent # Parse bytes received received = { label = "received" comment = "" value = "collect_fields_using_regexp('() Bytes rcv: ([0-9]+)', '*KEY*,bytes_received')" } # Parse a general Group/User line 6 = { label = "6" comment = "" value = "collect_fields_using_regexp('()Group \\\\[([^]]*)\\\\] User \\\\[([^]]*)\\\\]', '*KEY*,group,user')" } # 6 # Parse a general User line 7 = { label = "7" comment = "" value = "collect_fields_using_regexp('()User \\\\[*([^ ]]*)\\\\]* (.*)$', '*KEY*,user,operation')" } # 7 # Parse a User/Protocol line 8 = { label = "8" comment = "" value = "collect_fields_using_regexp('()User \\\\[ ([^ ]+) \\\\] Protocol \\\\[ ([^ ]+) \\\\] (.*)', '*KEY*,user,protocol,operation')" } # 8 # Parse a Status line 9 = { label = "9" comment = "" value = "collect_fields_using_regexp('()Status: <([^>]+)>', '*KEY*,status')" } # 9 # Parse an 'authenticated' line 10 = { label = "10" comment = "" value = "collect_fields_using_regexp('()User \\\\[[^]]*\\\\] User \\\\(([^)]*)\\\\) (authenticated)', '*KEY*,user,operation')" } # 10 # Parse a 'Validation of certificate successful' line 11 = { label = "11" comment = "" value = "collect_fields_using_regexp('()Group .([0-9A-Z]*). (Validation of certificate successful) \\\\(CN=([^,]*), SN=([A-F0-9]*)\\\\)', '*KEY*,group,operation,cn,sn')" } # 11 # Parse a 'Received local Proxy Host' line 12 = { label = "12" comment = "" value = "collect_fields_using_regexp('()(Received local Proxy Host data in ID Payload): *Address ([0-9.]*), Protocol ([0-9]*), Port ([0-9]*)', '*KEY*,operation,local_proxy_host,protocol,port')" } # 12 # Parse a 'Received local Proxy Subnet data' line 13 = { label = "13" comment = "" value = "collect_fields_using_regexp('()(Received local IP Proxy Subnet data in ID Payload): *Address ([0-9.]*), Mask ([0-9.]*), Protocol ([0-9]*), Port ([0-9]*)', '*KEY*,operation,local_proxy_subnet,local_proxy_mask,protocol,port')" } # 13 # Parse a 'Received remote Proxy Host' line 14 = { label = "14" comment = "" value = "collect_fields_using_regexp('()(Received remote Proxy Host data in ID Payload): *Address ([0-9.]*), Protocol ([0-9]*), Port ([0-9]*)', '*KEY*,operation,remote_proxy_host,protocol,port')" } # 14 # Parse a 'Received remote Proxy Subnet data' line 15 = { label = "15" comment = "" value = "collect_fields_using_regexp('()(Received remote IP Proxy Subnet data in ID Payload): *Address ([0-9.]*), Mask ([0-9.]*), Protocol ([0-9]*), Port ([0-9]*)', '*KEY*,operation,remote_proxy_subnet,remote_proxy_mask,protocol,port')" } # 15 # Parse a 'Security negotiation complete' line 16 = { label = "16" comment = "" value = "collect_fields_using_regexp('()(Security negotiation complete) for User \\\\(([^]]*)\\\\) Responder, Inbound SPI = ([^,]*), Outbound SPI = ([^,]*)', '*KEY*,operation,user,inbound_spi,outbound_spi')" } # 16 # Parse a 'Connection terminated' line 17 = { label = "17" comment = "" value = "collect_fields_using_regexp('()(Connection terminated for peer) ([^ ]*) \\\\([^)]*\\\\) *Remote Proxy ([^,]*), Local Proxy ([^,])*', '*KEY*,operation,remote_proxy,local_proxy')" } # 17 # 2008-04-24 - GMF - Parse a 'ARP request' or ARP reply line arp_request = ` # e.g. Mar 28 09:34:58 12.34.56.78 47454 03/28/2008 09:32:49.750 SEV=7 IPDBG/14 RPT=7599 ARP request for 98.76.54.32 with 1 second timeout if (matches_regular_expression(current_log_line(), '(ARP request) for ([^ ]*)')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'arp_ip', $2); ); # e.g. Mar 28 11:54:38 12.34.56.78 47617 03/28/2008 11:52:29.390 SEV=7 IPDBG/15 RPT=6077 ARP reply for 98.76.54.32 from MAC 123456789ABC else if (matches_regular_expression(current_log_line(), '(ARP reply) for ([^ ]*) from MAC ([^ ]+)')) then ( set_collected_field('', 'operation', $1); set_collected_field('', 'arp_ip', $2); set_collected_field('', 'arp_mac', $3); ); ` # Parse a 'User disconnected' line user_disconnected = { label = "user disconnected" comment = "" value = ` v.message = v.syslog_message; # Chop off leading integer if (matches_regular_expression(v.message, '^[0-9]+ (.*)$')) then v.message = $1; # Extract date/time, if present if (matches_regular_expression(v.message, '^([0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9])\\\\.[0-9][0-9][0-9] (.*)$')) then ( set_collected_field('', 'date', $1); set_collected_field('', 'time', $2); v.message = $3; ); # Extract severity # 2008-04-25 - GMF - Required final expression to begin with non-space, to force all spaces before it to be consumed. if (matches_regular_expression(v.message, '^SEV=([0-9]+ [^ ]+) RPT=([0-9]+) ([^ ]+) +([^ ].*)$')) then ( set_collected_field('', 'severity', $1); set_collected_field('', 'source_host', $3); v.message = $4; if (matches_regular_expression(v.message, '^User \\\\[([^]]*)\\\\],* (.*)$')) then ( set_collected_field('', 'user', $1); v.message = $2; ); if (matches_regular_expression(v.message, '^Group \\\\[([^]]*)\\\\] (.*)$')) then ( set_collected_field('', 'group', $1); v.message = $2; ); if (matches_regular_expression(v.message, '^disconnected: (.*)$')) then ( set_collected_field('', 'operation', 'disconnected'); set_collected_field('', 'vpn_sessions', 1); v.message = $1; if (matches_regular_expression(v.message, '^Session Type: ([^ ]+) (.*)$')) then ( set_collected_field('', 'session_type', $1); v.message = $2; ); if (matches_regular_expression(v.message, '^Duration: ([0-9:]+) (.*)$')) then ( volatile.duration = $1; v.message = $2; # Convert duration to second if ( contains(volatile.duration, ':') ) then ( if (matches_regular_expression(volatile.duration, '^([0-9]+)d ([0-9]+):([0-9]+):([0-9]+)')) then set_collected_field('', 'duration', $4 + $3*60 + $2*3600 + $1*86400); else if (matches_regular_expression(volatile.duration, '^([0-9]+):([0-9]+):([0-9]+)')) then set_collected_field('', 'duration', $3 + $2*60 + $1*3600); ); ); # if duration if (matches_regular_expression(v.message, '^Bytes xmt: ([0-9]+) Bytes rcv: ([0-9]+) (.*)$')) then ( set_collected_field('', 'bytes_sent', $1); set_collected_field('', 'bytes_received', $2); v.message = $3; ); if (matches_regular_expression(v.message, '^Reason: (.*)$')) then ( set_collected_field('', 'reason', $1); v.message = $2; ); ); # if disconnected ); ## Start with volatile.duration at 0 #volatile.duration = 0; # ## Extract user/group disconnected lines #if (matches_regular_expression(v.syslog_message, 'RPT=[0-9]* ([^ ]*) User \\\\[([^]]*)\\\\], Group \\\\[([^]]*)\\\\] (disconnected): Duration: ([0-9:]+) Bytes xmt: ([0-9]+) Bytes rcv: ([0-9]+) Reason: (.*)$')) then ( # set_collected_field('', 'source_host', $1); # set_collected_field('', 'user', $2); # set_collected_field('', 'group', $3); # set_collected_field('', 'operation', $4); # volatile.duration = $5; # set_collected_field('', 'bytes_sent', $6); # set_collected_field('', 'bytes_received', $7); # set_collected_field('', 'vpn_sessions', 1); #); # ## Parse 'User disconnected' line #else if (matches_regular_expression(current_log_line(), 'User ([^ ]*) (disconnected): Duration: (.*) Bytes xmt: ([0-9]*) Bytes rcv: ([0-9]*)')) then ( # volatile.user = $1; # if (starts_with(volatile.user, '[')) then ( ## volatile.user = replace_first(volatile.user, '[', ''); # volatile.user = replace_first(volatile.user, ']', ''); # ); # set_collected_field('', 'user', volatile.user); # set_collected_field('', 'operation', $2); # volatile.duration = $3; # set_collected_field('', 'bytes_sent', $4); # set_collected_field('', 'bytes_received', $5); # set_collected_field('', 'vpn_sessions', 1); ##); # ## Handle other durations #else if (matches_regular_expression(current_log_line(), ' Duration: ([0-9:]+)')) then # volatile.duration = $1; # ## Convert duration to second #if ( contains(volatile.duration, ':') ) then ( # if (matches_regular_expression(volatile.duration, '^([0-9]+)d ([0-9]+):([0-9]+):([0-9]+)')) then # set_collected_field('', 'duration', $4 + $3*60 + $2*3600 + $1*86400); # else if (matches_regular_expression(volatile.duration, '^([0-9]+):([0-9]+):([0-9]+)')) then # set_collected_field('', 'duration', $3 + $2*60 + $1*3600); #); ` } # user_disconnected # Parse a 'PHASE 2 COMPLETE' line 19 = { label = "19" comment = "" value = "collect_fields_using_regexp('()(PHASE 2 COMPLETED)', '*KEY*,operation')" } # 19 # Accept on %IKE lines 20 = { label = "20" comment = "" value = "accept_collected_entry_using_regexp('()%IKE', false)" } # 20 # Accept on blank line # do_b # "" "" "" "" "" # accept_collected_entry_regexp "^()$" "" "" "" # goto_next_filter "" "" "" "" # "" } # log.parsing_filters # Database fields database.fields = { server_host = { label = "$lang_stats.field_labels.server_host" log_field = "server_host" type = "string" suppress_top = 0 suppress_bottom = 2 } # server_host severity = { label = "$lang_stats.field_labels.severity" log_field = "severity" type = "string" suppress_top = 0 suppress_bottom = 2 } # severity operation = { label = "$lang_stats.field_labels.operation" log_field = "operation" type = "string" suppress_top = 0 suppress_bottom = 2 } # operation user = { label = "$lang_stats.field_labels.user" log_field = "user" type = "string" suppress_top = 0 suppress_bottom = 2 } # user group = { label = "$lang_stats.field_labels.group" log_field = "group" type = "string" suppress_top = 0 suppress_bottom = 2 } # group cn = { label = "$lang_stats.field_labels.cn" log_field = "cn" type = "string" suppress_top = 0 suppress_bottom = 2 } # cn sn = { label = "$lang_stats.field_labels.sn" log_field = "sn" type = "string" suppress_top = 0 suppress_bottom = 2 } # sn sa = { label = "$lang_stats.field_labels.sa" log_field = "sa" type = "string" suppress_top = 0 suppress_bottom = 2 } # sa status = { label = "$lang_stats.field_labels.status" log_field = "status" type = "string" suppress_top = 0 suppress_bottom = 2 } # status payload = { label = "$lang_stats.field_labels.payload" log_field = "payload" type = "string" suppress_top = 0 suppress_bottom = 2 } # payload protocol = { label = "$lang_stats.field_labels.protocol" log_field = "protocol" type = "string" suppress_top = 0 suppress_bottom = 2 } # protocol port = { label = "$lang_stats.field_labels.port" log_field = "port" type = "string" suppress_top = 0 suppress_bottom = 2 } # port source_host = { label = "$lang_stats.field_labels.source_host" log_field = "source_host" type = "string" suppress_top = 0 suppress_bottom = 9 } # source_host arp_ip = "" arp_mac = "" local_proxy_host = { label = "$lang_stats.field_labels.local_proxy_host" log_field = "local_proxy_host" type = "string" suppress_top = 0 suppress_bottom = 2 } # local_proxy_host local_proxy_subnet = { label = "$lang_stats.field_labels.local_proxy_subnet" log_field = "local_proxy_subnet" type = "string" suppress_top = 0 suppress_bottom = 2 } # local_proxy_subnet local_proxy_mask = { label = "$lang_stats.field_labels.local_proxy_mask" log_field = "local_proxy_mask" type = "string" suppress_top = 0 suppress_bottom = 2 } # local_proxy_mask remote_proxy_host = { label = "$lang_stats.field_labels.remote_proxy_host" log_field = "remote_proxy_host" type = "string" suppress_top = 0 suppress_bottom = 2 } # remote_proxy_host remote_proxy_subnet = { label = "$lang_stats.field_labels.remote_proxy_subnet" log_field = "remote_proxy_subnet" type = "string" suppress_top = 0 suppress_bottom = 2 } # remote_proxy_subnet remote_proxy_mask = { label = "$lang_stats.field_labels.remote_proxy_mask" log_field = "remote_proxy_mask" type = "string" suppress_top = 0 suppress_bottom = 2 } # remote_proxy_mask reason = { label = "$lang_stats.field_labels.reason" log_field = "reason" type = "string" suppress_top = 0 suppress_bottom = 2 } # reason session_type = "" } # database.fields # Log Filters log.filters = { mark_entry = { label = '$lang_admin.log_filters.mark_entry_label' comment = '$lang_admin.log_filters.mark_entry_comment' value = 'events = 1;' } # mark_entry } # log.filters database.numerical_fields = { events = { label = "$lang_stats.field_labels.events" default = true requires_log_field = false type = "int" display_format_type = "integer" entries_field = true } # events visitors = { label = "$lang_stats.field_labels.visitors" default = false requires_log_field = true log_field = "user" type = "unique" display_format_type = "integer" } # visitors bytes_received = { label = "$lang_stats.field_labels.bytes_received" default = false requires_log_field = true log_field = "bytes_received" type = "float" display_format_type = "bandwidth" } # bytes_received bytes_sent = { label = "$lang_stats.field_labels.bytes_sent" default = false requires_log_field = true log_field = "bytes_sent" type = "float" display_format_type = "bandwidth" } # bytes_sent duration = { label = "$lang_stats.field_labels.duration" default = false requires_log_field = true log_field = "duration" type = "float" display_format_type = "duration_compact" } # duration vpn_sessions = "" } # database.numerical_fields create_profile_wizard_options = { host_tracking = true # How the reports should be grouped in the report menu report_groups = { date_time_group = "" server_host = true severity = true operation = true user = true group = true cn = true sn = true sa = true status = true payload = true protocol = true port = true source_host = true arp_ip = true arp_mac = true local_proxy_host = true local_proxy_subnet = true local_proxy_mask = true remote_proxy_host = true remote_proxy_subnet = true remote_proxy_mask = true reason = true } # report_groups } # create_profile_wizard_options not_supported = { pageviews = true sessionpages = true } # not_supported } # cisco_vpnconcentrator