Skip to content
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

question: TLS example #687

Open
detailyang opened this issue Jul 28, 2019 · 8 comments
Open

question: TLS example #687

detailyang opened this issue Jul 28, 2019 · 8 comments

Comments

@detailyang
Copy link

Hello. I see the TLS layer has merged to master but there is no example to reference.

It would be good if gopacket provides the TLS example.

Many thanks:)

@xhdix
Copy link

xhdix commented Sep 2, 2019

I used the method available at https://github.com/google/gopacket/blob/master/layers/tls_test.go.
But it didn't work.

	if tls, ok := p.Layer(layers.LayerTypeTLS).(*layers.TLS); ok {
		fmt.Printf("work: ", tls)
	} else {
		t.Error("doesn't work -- No TLS layer type found in packet")
	}

Returns nil for all packets (TLS).

@xhdix
Copy link

xhdix commented Sep 2, 2019

@jselvi & @gconnell Have you tried it with a real packet before?

@spitfire55
Copy link

spitfire55 commented Sep 5, 2019

UPDATE: See comment below for automatically decoding TLS from a PacketSource

Can confirm that live packet capture doesn't automatically decode TLS layers. Right now, I have to manually decode it w/ the following code:

if packet.ApplicationLayer() != nil {
            var tls layers.TLS
            var decoded []gopacket.LayerType
            parser := gopacket.NewDecodingLayerParser(layers.LayerTypeTLS, &tls)
            err := parser.DecodeLayers(packet.ApplicationLayer().LayerContents(), &decoded); if err != nil {
                return
            }
            for _, layerType := range decoded {
                switch layerType {
                case layers.LayerTypeTLS:
                    // do things with tls variable
                }
            }
        }

@jselvi
Copy link
Contributor

jselvi commented Sep 5, 2019

I contributed with this layer because I needed it for my tool. You can see a basic example on in: https://github.com/jselvi/fiesta/blob/master/pkg/tlsrelay/tls.go#L28
In this tool, it has been working perfectly.

I implemented this some time ago and I can't remember the details, but I tried to mimic the decisions that were taken in other layers, so you shouldn't see a different behaviour.

@xhdix
Copy link

xhdix commented Sep 5, 2019

@jselvi Thanks
But It only works when you use NewPacket().
It doesn't work even when you use OpenOffline()

@spitfire55
Copy link

spitfire55 commented Sep 18, 2019

So I identified why this behavior is occuring. If you want to automatically decode TLS layers from a packet source (pcap or handle), you need to set DecodeStreamsAsDatagrams to true. Otherwise, if this is false, tcp.go simply sets all TCP payloads as LayerTypePayload.

As explained by the documentation for DecodeStreamsAsDatagrams:

// DecodeStreamsAsDatagrams enables routing of application-level layers in the TCP
// decoder. If true, we should try to decode layers after TCP in single packets.
// This is disabled by default because the reassembly package drives the decoding
// of TCP payload data after reassembly.

And the relevant lines of code from tcp.go:

func decodeTCP(data []byte, p gopacket.PacketBuilder) error {
	tcp := &TCP{}
	err := tcp.DecodeFromBytes(data, p)
	p.AddLayer(tcp)
	p.SetTransportLayer(tcp)
	if err != nil {
		return err
	}
	if p.DecodeOptions().DecodeStreamsAsDatagrams {
		return p.NextDecoder(tcp.NextLayerType())
	} else {
		return p.NextDecoder(gopacket.LayerTypePayload)
	}
}

@jselvi
Copy link
Contributor

jselvi commented Sep 18, 2019

Oh, I see. But this is something that should happen with every application layer, not only TLS. I understood that this was a problem not happening when decoding packet containing an application layer other than TLS.

Btw, that flag is set to true in the tests:

DecodeStreamsAsDatagrams: true,

Thanks @spitfire55 !

@notti
Copy link
Collaborator

notti commented Sep 18, 2019

So I identified why this behavior is occuring. If you want to automatically decode TLS layers from a packet source (pcap or handle), you need to set DecodeStreamsAsDatagrams to true. Otherwise, if this is false, tcp.go simply sets all TCP payloads as LayerTypePayload.

Oh, I see. But this is something that should happen with every application layer, not only TLS. I understood that this was a problem not happening when decoding packet containing an application layer other than TLS.

The reason for this is that TCP carries a stream of data and not datagrams. This means that single TCP packets do not generally carry single payloads. E.g., for TLS, if you're lucky one TCP packet will contain a single TLS record - but in many cases one TCP packet will contain:

  • part of a TLS record (either cut at the beginning, end, or both)
  • multiple TLS records
  • multiple TLS records where the first or the last one is only a part
  • one of the above (or a single record) but a second, third, ... time (TCP does automatic retransmissions)
  • one of the above but in the wrong order (TCP does reordering)

So the correct way to go about this would be to use reassembly, and then pull the tls records out of the reassembled stream. This problem also exists for the other TCP payloads and is the reason why #587 and #584 are not yet implemented (we don't have some kind of mechanism to somehow mix reassembly and packets, and a mechanism for implementing stream based protocols that can consume a reassembled stream).
TLS and modbus shouldn't have been merged this way - sorry for the confusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants