Fukuoka.go#12 で GoでTCPパケットを読むための最初の一歩の話 をした #fukuokago

Fukuoka.go に参加してきました!

fukuokago.connpass.com

主催者、発表者のみなさん、ありがとうございました!

ちょっとトラブルがあって楽しみにしていた「Road to your goroutines」をまともに聞けなかったので残念がっていたら、素晴らしいまとめエントリが上がっていて本当に感謝です!!

GoでTCPパケットを読む

最近、tcpdpというTCPパケットを読むツールを作っているのですが、その開発をするにあたって「Goもやっぱりライブラリが揃っているな」と感じたので、そういった意味での発表をしました。

tcpdpの話をすると、プロトコルの解析苦労話になりそうだったのでやめときました(Goっぽくない)

google/gopacket

スライドを見てもらったらわかるとおり、ほとんど google/gopacket の紹介みたいになっています。

それでも、あまりにも簡単にtcpdumpぽいものが作れてしまうので、最初、個人的には本当にびっくりしました。

発表で作った簡易tcpdumpはわずか32行です。

package main

import (
  "encoding/hex"
  "fmt"
  "log"

  "github.com/google/gopacket"
  "github.com/google/gopacket/pcap"
)

func main() {
  device := "en0"
  filter := "tcp and port 80"

  handle, err := pcap.OpenLive(
    device, int32(0xFFFF), true, pcap.BlockForever,
  )
  if err != nil {
    log.Fatal(err)
  }
  defer handle.Close()
  if err := handle.SetBPFFilter(filter); err != nil {
    log.Fatal(err)
  }

  packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
  for packet := range packetSource.Packets() {
    fmt.Printf("%s\n", packet)
    fmt.Printf("%s", hex.Dump(packet.Data()))
  }
}

たったこれだけで動くtcpdumpっぽいコマンドが出来上がりです。

そうするとあとは、拡張したいと思ったところをいじればいいし、気になるところはコードから定義ジャンプをしていけば理解が深まります。

書いて動くと理解が進む

発表資料をみたらわかるように、自分はネットワーク周辺は雰囲気で触っていることが多いです(注意: 上記ツイートはわざと面白おかしくしてもらった結果です)

しかし、実際にコードに落とし込んで動くようになると、次の試行錯誤をすることができます。

試行錯誤ができるところまでできたら、次の「使えるツールが作れるかも」というモチベーションを持った開発ができます。

モチベーションを持てるとちょっとばかり面倒な部分についても調べたり検証したりする気になります。

そして、結果として周辺の理解が進むと感じています。

というわけで

今回の発表で、自分と同じように「ネットワーク周り得意じゃないな」と思っている人がちょっとでも「Goで書けるならやってみようかな」と思ってくれたら幸いです。

そういえば、今週末もずっと []byte{} を眺めてたな。。。