As it happens we have the same dhcpd
logs in our lab, so I took a closer look. Unsurprisingly there is a bit of variation in the logs that you will have to construct your pipeline to handle.
I am showing only the "log message" portion of the syslog event. To make it easier to compare, I have normalized all of the values as follows:
- Client IP: 10.10.1.111
- Client MAC: 01:02:03:04:05:06
- Client hostame: clihost
- DHCP Server Interface: eth1
- DHCP Server Interface IP: 10.10.1.1
These are the different variations I see in our environment:
DHCPDISCOVER: Client broadcast to find available DHCP servers.
DHCPDISCOVER from 01:02:03:04:05:06 via eth1
DHCPDISCOVER from 01:02:03:04:05:06 (clihost) via eth1
DHCPOFFER: Server response to client’s DHCPDISCOVER, offering configuration parameters.
DHCPOFFER on 10.10.1.111 to 01:02:03:04:05:06 via eth1
DHCPOFFER on 10.10.1.111 to 01:02:03:04:05:06 (clihost) via eth1
DHCPREQUEST: Client message to one or more servers to do any of the following:
- Request parameters from one server and implicitly decline offers from other servers.
- Confirm that a previously allocated address is correct after, for example, a system reboot.
- Extend the lease of a network address.
DHCPREQUEST for 10.10.1.111 from 01:02:03:04:05:06 via eth1
DHCPREQUEST for 10.10.1.111 (10.10.1.1) from 01:02:03:04:05:06 via eth1
DHCPREQUEST for 10.10.1.111 from 01:02:03:04:05:06 (clihost) via eth1
DHCPREQUEST for 10.10.1.111 (10.10.1.1) from 01:02:03:04:05:06 (clihost) via eth1
DHCPREQUEST for 10.10.1.111 from 01:02:03:04:05:06 via eth1: ignored (not authoritative).
DHCPREQUEST for 10.10.1.111 from 01:02:03:04:05:06 (clihost) via eth1: ignored (not authoritative).
DHCPREQUEST for 10.10.1.111 (10.10.1.1) from 01:02:03:04:05:06 (clihost) via eth1: ignored (not authoritative).
DHCPACK: Server to client acknowledgment message containing configuration parameters, including a confirmed network address.
DHCPACK on 10.10.1.111 to 00:0e:c4:d0:69:39 via eth1
DHCPACK on 10.10.1.111 to d4:a3:3d:d7:5c:d3 (clihost) via eth1
DHCPINFORM: Client to server message requesting only local configuration parameters; client has an externally configured network address.
DHCPINFORM from 10.10.1.111 via eth1: not authoritative for subnet 10.10.1.0
DHCPNAK: Server to client negative acknowledgment indicating the client’s understanding of the network address is incorrect (for example, if the client has moved to a new subnet), or a client’s lease has expired.
DHCPNAK on 10.10.1.111 to 01:02:03:04:05:06 via eth1
DHCPRELEASE: Client to server message giving up the user of the network address and canceling the remaining time on the lease.
DHCPRELEASE of 10.10.1.111 from 01:02:03:04:05:06 via eth1 (not found)
DHCPRELEASE of 10.10.1.111 from 01:02:03:04:05:06 via eth1 (found)
DHCPRELEASE of 10.10.1.111 from 01:02:03:04:05:06 (clihost) via eth1 (found)
DHCPDECLINE: Client to server message indicating the network address is already being used.
# I didn't have any examples of this message type. I may try to force the generation of such a message when I get more time.
A few things should jump out here...
- Your sample data only includes 4 types of messages, but you need to be able to handle 8.
- We don't even have an example of one of the types, so we don't know what it looks like. There is also some variation within a type, which begs the question whether we have identified all variations?
- Sometimes MAC addresses are by themselves
01:02:03:04:05:06
and sometimes they are followed by the name reported by the client 01:02:03:04:05:06 (clihost)
.
- Sometimes the client IP is by itself
10.10.1.111
and sometimes it is followed by the IP of the interface of the DHCP server 10.10.1.111 (10.10.1.1)
.
-
DHCPREQUEST
messages will sometimes include additional information after the DHCP server's interface name eth1: ignored (not authoritative).
(also note the trailing period which can sometimes be troublesome). Where you are using %{NOTSPACE:Interface}
you will pickup the colon after the interface name if you don't account for it.
If I was to start developing this pipeline, I would probably handle each message type individually. You may be able to come up with a series of grok patterns that will handle them all in one filter, but there is a lot more we do with the data as we normalize to our data model/schema. So I would start with something like this...
(NOTE: after initial processing we have examples above in a field called log.message
)
if [log][message] =~ /^DHCPACK .*/ {
grok {
# Grok focused only on DHCPACK here.
}
# Here is any additional logic to handle DCHPACK.
} else if [log][message] =~ /^DHCPREQUEST .*/ {
grok {
# Grok focused only on DHCPREQUEST here.
}
# Here is any additional logic to handle DHCPREQUEST.
} else if [log][message] =~ /^DHCPDISCOVER .*/ {
grok {
# Grok focused only on DHCPDISCOVER here.
}
# Here is any additional logic to handle DHCPDISCOVER.
} else if [log][message] =~ /^DHCPOFFER .*/ {
grok {
# Grok focused only on DHCPOFFER here.
}
# Here is any additional logic to handle DHCPOFFER.
} else if [log][message] =~ /^DHCPRELEASE .*/ {
grok {
# Grok focused only on DHCPRELEASE here.
}
# Here is any additional logic to handle DHCPRELEASE.
} else if [log][message] =~ /^DHCPINFORM .*/ {
grok {
# Grok focused only on DHCPINFORM here.
}
# Here is any additional logic to handle DHCPINFORM.
} else if [log][message] =~ /^DHCPNAK .*/ {
grok {
# Grok focused only on DHCPNAK here.
}
# Here is any additional logic to handle DHCPNAK.
} else if [log][message] =~ /^DHCPDECLINE .*/ {
grok {
# Grok focused only on DHCPDECLINE here.
}
# Here is any additional logic to handle DHCPDECLINE.
} else {
# nothing matched above so put some generic logic and maybe add a tag indicating that it didn't match.
}
I hope you find this helpful. We will probably complete this and add it to our own library of integrations in the near future.