Upgrade to Pro — share decks privately, control downloads, hide ads and more …

«Сниффинг RPC-трафика for fun and profit» — Мар...

Badoo Tech
March 09, 2018
8.8k

«Сниффинг RPC-трафика for fun and profit» — Марко Кевац (Badoo)

Выступление на Go 1.10 Release Party @ Badoo 24.02.2018.

Использование бинарного сетевого протокола имеет свои преимущества и недостатки. В качестве одного из недостатков часто упоминают сложность при дебаггинге, т.к. человек не может сходу увидеть содержание запроса или ответа.

Марко расскажет, как мы до сих пор «сниффали» наш бинарный протокол с помощью wireshark и самописного «диссектора», а теперь планируем использовать модный «диссектор» на Go.

В докладе посмотрим, как сниффать сетевой трафик в Go, познакомимся с кишками protocol buffers, проникнемся магией генерации, парсинга Go-кода и пакета reflect.

Badoo Tech

March 09, 2018
Tweet

More Decks by Badoo Tech

Transcript

  1. Marko Kevac Software Engineer in Platform team at Badoo. I

    love low level stuff, learning new things, watching Coub weekly, yogurt and of course Go language. Hello, my name is [email protected] blog.kevac.org
  2. • Internal/builtin • Dump (simple) • Distributed tracing (advanced) •

    External • Debugger (medium, slow) • SystemTap/eBPF (expert) • Traffic sniffing & parsing (could be simple) Approaches
  3. Client Client Service Client Another Service Observability And one more

    ? ? ? ? ? Text • Memcached • JSON Binary • HTTP/2 • Protobuf
  4. Dissectors Wireshark Wireshark dissectors know how to parse and present

    various protocols. There a many builtin ones, but you can write your own. github.com/mkevac/gpbs-dissector
  5. Pitfails Wireshark • Clunky • Needs *.so files with proto

    descriptors • It is difficult to remember how to use it
  6. 1 2 3 Dissector in Go Sniffing and parsing traffic.

    Same as with Wireshark. Single binary that is easy to use and deploy. Wide possibilities for improvement and custom features.
  7. Milestones Sniffing network Just use libpcap… Unfortunately we are using

    TCP/IP. Parsing and presenting GPBRPC protobuf Should be straightforward, right? It is not when you remember our requirement about “single binary” and ease of deployment. • A lot of services • New services, changing services • Various service versions at the same time
  8. • Sniffing using libpcap • Reading from the network and

    from files • TCP Reassembly Examples: • github.com/google/gopacket/examples/ bidirectional github.com/google/ gopacket
  9. • type, id, length, content • bytes and sub message

    look the same • We need schema • *.proto is a schema and protobuf descriptor is a computer friendly *.proto file representation Binary format
  10. • Some are very dynamic (python), some are very static

    (c). • Go has two main generators: default and gogo. Protoc compiler
  11. Possible solutions Create struct on the fly Go is no

    Python, but we have very powerful reflect package, right?.. Custom unmarshaller/ marshaller I am too lazy and I don’t want to support this thing forever… C-like dynamic libraries This should be possible in theory, but Go modules are very immature and I don’t want to deal with module preparing stuff.
  12. DOES NOT FIT reflect.StructOf() It accepts reflect.Type, not types.Type… types.Type

    -> reflect.Type There is no library or code that does this. There is a similar code deep in Go compiler, but not the same.
  13. DOES NOT FIT reflect.StructOf() It accepts reflect.Type, not types.Type… types.Type

    -> reflect.Type There is no library or code that does this. There is a similar code deep in Go compiler, but not the same. Muse Jason. E. Aten https://github.com/glycerine/muse golang-nuts
  14. … is not proto.Message: missing method ProtoMessage goroutine 1 [running]:

    main.test() /home/marko/src/github.com/mkevac/generatestruct_old/main.go:231 +0x456 main.main() /home/marko/src/github.com/mkevac/generatestruct_old/main.go:247 +0x25
  15. type Wrapper struct{} func (w Wrapper) Reset() {} func (w

    Wrapper) String() string { return "" } func (w Wrapper) ProtoMessage() {} sf, _ := m.ConvertStruct(u.Underlying()) wsf := reflect.StructField{ Name: "Wrapper", Type: reflect.TypeOf(Wrapper{}), Anonymous: true, Index: []int{0}, } sf = append([]reflect.StructField{wsf}, sf[0]) rt := reflect.StructOf(sf)
  16. … is not proto.Message: missing method ProtoMessage goroutine 1 [running]:

    main.test() /home/marko/src/github.com/mkevac/generatestruct_old/main.go:231 +0x456 main.main() /home/marko/src/github.com/mkevac/generatestruct_old/main.go:247 +0x25
  17. Fuck that shit Only for first anon field Ok, my

    type is first and anonymous… But doesn’t work anyway https://github.com/golang/go/issues/20824 https://github.com/golang/go/issues/16522 https://github.com/golang/go/issues/15924
  18. Possible solutions Create struct on the fly Custom unmarshaller/ marshaller

    C-like dynamic libraries Create struct on the fly + proto fork