-
Notifications
You must be signed in to change notification settings - Fork 2
Deep Packet Inspection
Deep Packet Inspection is the science (and art) of examining a network packet's header and/or payload to identify its contents and determine whether a packet should be filtered. However, the payload is stored as raw byte data and must be transformed back into more human readable objects before it can be analyzed.
This transformation process (known as marshalling and unmarshalling) is very complex and we won't go into the details of it here, but it involves using tools like Wireshark to manually analyze byte data then developing functions that transform individual bytes into analyzable objects. gopacket provides libraries for unmarshalling the more common pieces of information in a packet.
Once the raw byte data has been unmarshalled the resulting objects can be analyzed to help determine the actual contents and appropriate action can be taken as needed. The unique characteristics or patterns of a packet that help identify it are known as a "signature".
The following is an abbreviated example that demonstrates how the Marconi Protocol provides robust access to network packets for deep packet inspection and signature creation. For brevity, it assumes a working knowledge of network programming and that the reader can unmarshall packets as needed.
TLS is a network protocol used for securing web traffic and while the latest version (1.3) is very secure, the prior version (1.2) is far more common. The rest of this wiki will use Marconi to determine what version of TLS is being used. This can be a jumping off point for further action like alerting network admins of less secure network activity or more aggressive dropping of network packets.
To inspect TLS packets the filter should check for TCP packets, in addition we are looking for a packet with payload
func (t tlsFilter) Execute(p gopacket.Packet, response *m_packet_filter.FilterResponse) {
// Check the packet for TCP information
if tcpLayer := p.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
// Check TCP payload size, only check if there is data
if len(tcp.LayerPayload()) > 0 {
...
}t
}
The payload is a byte slice that contains the data that may help us determine the version of the TLS packet received. For this example, we are interested in detecting the handshake of 1.2 and 1.3. Another good resource is this visual guide.
isTlsPacket, packet := tls_filter.IsTLSPacket(tcp.LayerPayload())
tls_filter.IsTLSPacket is a function that returns a boolean indicating a TLS packet was found and packet is a struct representing the packet data.
The basic TLS information used to initialize TLSInfo struct is retreived by reading the byte data into different variables. This process of interpretting byte array into a data object is what we described as unmarshalling.
func IsTLSPacket(payload []byte) (bool, interface{}) {
...
sslRecord := uint8(payload[0])
if sslRecord != CHANGE_CIPHER_SPEC && sslRecord != ALERT && sslRecord != HANDSHAKE && sslRecord != APPLICATION_DATA {
return false, nil
}
tlsVersion := uint16(payload[1])<<8 | uint16(payload[2])
if tlsVersion != SSL3_VERSION && tlsVersion != TLS1_VERSION && tlsVersion != TLS2_VERSION && tlsVersion != TLS3_VERSION {
return false, nil
}
messageLen := uint16(payload[3])<<8 | uint16(payload[4])
if messageLen > MAX_LENGTH {
return false, nil
}
tlsInfo := TLSInfo{ sslRecord, tlsVersion, messageLen }
...
// more unmarshalling code below
}
This is the payload highlighted in wireshark.
TLS packet inspected
The first byte is 0x16 signifying that the TLS packet is a handshake packet.
The second and third bytes are 0x0303, which represents either TLS 1.2 OR TLS 1.3.
The fourth and fifth bytes are 0x0080, which tells us the length of the remainder of the payload is 128 bytes long.
There are different strategies to differentiate between TLS 1.2 and 1.3.
TLS 1.3 ServerHello packets include a supported_versions extension that can identify that packet as belonging to a TLS 1.3 session. The cipher suite used by the server can also provide information about the version.
To submit feedback or report technical issues, please email support@marconi.org
