105 lines
2.6 KiB
Go
105 lines
2.6 KiB
Go
package protocol
|
|
|
|
import (
|
|
"golang.org/x/crypto/cryptobyte"
|
|
|
|
"git.maze.io/go/dpi"
|
|
)
|
|
|
|
func init() {
|
|
registerTLS()
|
|
}
|
|
|
|
func registerTLS() {
|
|
Register(Both, "\x16\x03\x00", detectTLS) // SSLv3
|
|
Register(Both, "\x16\x03\x01", detectTLS) // TLSv1.0
|
|
Register(Both, "\x16\x03\x02", detectTLS) // TLSv1.1
|
|
Register(Both, "\x16\x03\x03", detectTLS) // TLSv1.2
|
|
}
|
|
|
|
func detectTLS(dir Direction, data []byte, _, _ int) (proto *Protocol, confidence float64) {
|
|
stream := cryptobyte.String(data)
|
|
|
|
// A TLS packet always has a content type (1 byte), version (2 bytes) and length (2 bytes).
|
|
if len(stream) < 5 {
|
|
return nil, 0
|
|
}
|
|
|
|
// Check for TLS Handshake (type 22)
|
|
var header struct {
|
|
Type uint8
|
|
Version uint16
|
|
Length uint32
|
|
}
|
|
if !stream.ReadUint8(&header.Type) || header.Type != 0x16 {
|
|
return nil, 0
|
|
}
|
|
if !stream.ReadUint16(&header.Version) {
|
|
return nil, 0
|
|
}
|
|
if !stream.ReadUint24(&header.Length) {
|
|
return nil, 0
|
|
}
|
|
|
|
// Initial confidence
|
|
confidence = 0.5
|
|
|
|
// Detected SSL/TLS version
|
|
var version dpi.TLSVersion
|
|
|
|
// Attempt to decode the full TLS Client Hello handshake
|
|
if version == 0 {
|
|
if hello, err := dpi.DecodeTLSClientHelloHandshake(data); err == nil {
|
|
version = hello.Version
|
|
confidence += .45
|
|
}
|
|
}
|
|
|
|
// Attempt to decode the full TLS Server Hello handshake
|
|
if version == 0 {
|
|
if hello, err := dpi.DecodeTLSServerHello(data); err == nil {
|
|
version = hello.Version
|
|
confidence += .45
|
|
}
|
|
}
|
|
|
|
// Attempt to decode at least the handshake protocol and version.
|
|
if version == 0 && !Strict {
|
|
var handshakeType uint8
|
|
if stream.ReadUint8(&handshakeType) && (handshakeType == 1 || handshakeType == 2) {
|
|
var (
|
|
length uint32
|
|
versionWord uint16
|
|
)
|
|
if stream.ReadUint24(&length) && stream.ReadUint16(&versionWord) {
|
|
version = dpi.TLSVersion(versionWord)
|
|
confidence += .25
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fall back to the version in the TLS record header, this is less accurate
|
|
if version == 0 && !Strict {
|
|
version = dpi.TLSVersion(header.Version)
|
|
}
|
|
|
|
// We're "multi protocol", in that SSL is its own protocol
|
|
if version == dpi.VersionSSL30 {
|
|
return &Protocol{
|
|
Name: ProtocolSSL,
|
|
Version: Version{Major: 3, Minor: 0, Patch: -1},
|
|
}, confidence
|
|
} else if version >= dpi.VersionTLS10 && version <= dpi.VersionTLS13 {
|
|
return &Protocol{
|
|
Name: ProtocolTLS,
|
|
Version: Version{Major: 1, Minor: int(uint8(version) - 1), Patch: -1},
|
|
}, confidence
|
|
} else if version >= dpi.VersionTLS13Draft && version <= dpi.VersionTLS13Draft23 {
|
|
return &Protocol{
|
|
Name: ProtocolTLS,
|
|
Version: Version{Major: 1, Minor: 3, Patch: -1},
|
|
}, confidence
|
|
}
|
|
return nil, 0
|
|
}
|