-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TLS module for packetbeat #5476
Conversation
Please review when you have time. It is a work in progress (working on the tests now) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are making good progress. Things look good so far to me. I'll take another look when you get closer to done.
packetbeat/_meta/fields.yml
Outdated
- name: tls | ||
type: group | ||
fields: | ||
- name: negotiated cypher |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This field name has a space in it. Probably you want an underscore here. But it looks like this file is progress because I don't see this field in the code so I'm sure you be updating all of this.
packetbeat/protos/tls/parse.go
Outdated
return m | ||
} | ||
|
||
func (parser *parser) parse(buf *streambuf.Buffer, conn *tlsConnectionData, plugin *tlsPlugin) (bool, bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try not to introduce circular dependencies in any way. At optimium the parser must be testable without requiring an instance of tlsPlugin
. This simplifies potential unit and/or fuzzy testing of the parser only.
The TCP code generate creates different types with different responsibilities on purpose. One type per task like: manage connections, parse, correlate messages, create events, publish events
packetbeat/protos/tls/parse.go
Outdated
|
||
func (parser *parser) parse(buf *streambuf.Buffer, conn *tlsConnectionData, plugin *tlsPlugin) (bool, bool) { | ||
|
||
if conn.handshakeCompleted { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
Abstraction leak. The parser should be about parsing messages from receive buffer only. The parser should not have to care about the connection state if possible.
-
if connection is 'completed' and there is nothing new to learn during the lifetime of the connect, clear the buffers more early and consider not appending to the buffer again. This will make the module much more lightweight.
packetbeat/protos/tls/parse.go
Outdated
switch header.recordType { | ||
case recordTypeChangeCipherSpec: // single message of size 1 (byte 1) | ||
conn.handshakeCompleted = true | ||
plugin.sendEvent(conn) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Abstraction leak. Parser should not directly trigger an event, depending on potential connection state. Instead parser should return/report messages only.
packetbeat/protos/tls/parse.go
Outdated
return true | ||
} | ||
|
||
func (parser *parser) processHandshake(conn *tlsConnectionData, handshakeType handshakeType, reader bufferView) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a task for the message 'correlator'. Note, depending on deployment (e.g. port forwarding), packetbeat might potentially see packets out of order.
Nice progress. Can't wait for finally having TLS envelope support 🎉 |
Will update with correct fields.yml |
93b394f
to
b3f8885
Compare
packetbeat/protos/tls/parse.go
Outdated
return nil | ||
} | ||
|
||
certs := make([]*x509.Certificate, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can probably use "var certs []*x509.Certificate" instead
packetbeat/protos/tls/parse.go
Outdated
return nil | ||
} | ||
|
||
certs := make([]*x509.Certificate, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can probably use "var certs []*x509.Certificate" instead
3e7e9cb
to
e46b850
Compare
packetbeat/_meta/fields.yml
Outdated
- name: timestamp | ||
type: long | ||
description: > | ||
The current time and date in standard UNIX 32-bit format |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this seconds since Unix epoch? Either way I suggest converting it to a date rather than a long so that’s easier to use in ES.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Will do
packetbeat/_meta/fields.yml
Outdated
fields: | ||
- name: server_name_indication | ||
type: string | ||
description: Comma-separated list of server names |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of comma separated, I think a list would be better for searching and aggregating.
packetbeat/_meta/fields.yml
Outdated
- name: session_ticket | ||
type: string | ||
description: > | ||
Length of the session ticket, if provided, or empty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“or empty” - does this mean the field is not sent when a value is not present?
packetbeat/_meta/fields.yml
Outdated
|
||
- name: session_ticket | ||
type: string | ||
description: Empty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please clarify here.
description: X509 format version. | ||
|
||
- name: serial_number | ||
type: keyword |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the some benefits to sending this as a keyword rather than a long? Will users be expecting to see hex? Maybe we should have a field formater in Kibana for hex (possibly there is one; I didn’t check).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The serial number can be up to 160 bits long so it doesn't fit on a numeric type.
I have changed the format to decimal. The most common way of representation seems to be decimal up to 64 bit in length and then hexadecimal number or hex dump of individual bytes. I will stick with decimal in a keyword field.
This patch adds TLS protocol support for packetbeat. It will parse the initial handshake and send to Elasticsearch an event for every TLS connection. This event contains: - ciphers supported by client - cipher selected by server - extensions - client and server certificate chain (if any) - whether the session is resumed using session IDs or tickets
This parses the Application Layer Protocol Negotiation extension in hello messages. This involves a list of protocols in the client hello: "application_layer_protocol_negotiation": "h2,http/1.1" And the selected protocol in the server hello. "application_layer_protocol_negotiation": "h2"
Both decimal and hexadecimal are used interchangeably. Unfortunately long datatype cannot be used for the serial number as it can have a length of up to 160 bits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This patch adds TLS protocol support to Packetbeat.
It will parse the initial handshake and send an event to Elasticsearch for every TLS connection.
Events contain:
There is support for Application Layer Protocol Negotiation (ALPN) extension to TLS. It parses extension data found in hello messages. This involves a list of protocols in the client hello:
And the selected protocol in the server hello.
References
ALPN: https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation