---
# System prepended metadata

title: 使用Wireshark抓取quic-go產生的QUIC封包

---

# 使用Wireshark抓取quic-go產生的QUIC封包
這邊文章教大家如何使用Wireshark抓取並解析quic-go產生的QUIC封包。

Server code:
```
package main

import (
	"context"
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"math/big"
	"time"
	"os"

	"github.com/quic-go/quic-go"
)

func main() {
	fmt.Println("hello")
	err := Server()
	if err != nil {
		fmt.Println("server err")
		fmt.Println(err)
	}

}

func Server() error {
	const addr = "127.0.0.1:30000"
	ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
	defer cancel()

	listener, err := quic.ListenAddr(addr, generateTLSConfig(), &quic.Config{
		KeepAlivePeriod: time.Minute * 5,
		EnableDatagrams: true,
	})
	if err != nil {
		return err
	}

	conn, err := listener.Accept(ctx)
	if err != nil {
		return err
	}

	for {
		size := 256
		buf := make([]byte, size)
		buf, err = conn.ReceiveMessage()
		if err != nil {
			fmt.Println(err)
			break
		}
		fmt.Printf("Got: %s", buf)

	}
	return err

}

// Setup a bare-bones TLS config for the server
func generateTLSConfig() *tls.Config {
	key, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
		panic(err)
	}
	template := x509.Certificate{SerialNumber: big.NewInt(1)}
	certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
	if err != nil {
		panic(err)
	}
	keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
	certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
	
	kl, err := os.OpenFile("tls_key.log", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)

	tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
	if err != nil {
		panic(err)
	}
	return &tls.Config{
		Certificates: []tls.Certificate{tlsCert},
		NextProtos:   []string{"quic-echo-example"},
		KeyLogWriter: kl,
	}
}
```
主要是參考quic-go的example，然後再加上一些改動，quic.config裡的EnableDatagram我把它設成true使他能夠接受RFC 9221裡定義的datagram封包。
然後在tls.Config的地方，我增加了KeyLogWrite這個field，go本身的描述是
KeyLogWriter optionally specifies a destination for TLS master secrets in NSS key log format that can be used to allow external programs such as Wireshark to decrypt TLS connections. See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. Use of KeyLogWriter compromises security and should only be used for debugging.
使用上只要開一個os.File然後給他就行

client code:
```
package main

import (
	"bufio"
	"crypto/tls"
	"fmt"
	"os"
	"time"

	"github.com/quic-go/quic-go"
)

const addr = "127.0.0.1:30000"

func main() {
	fmt.Println("hello")
	err := Client()
	if err != nil {
		fmt.Println("client err")
		fmt.Println(err)
	}

}

func Client() error {
	tlsConf := &tls.Config{
		InsecureSkipVerify: true,
		NextProtos:         []string{"quic-echo-example"},
	}
	conn, err := quic.DialAddr(addr, tlsConf, &quic.Config{
		KeepAlivePeriod: time.Minute * 5,
		EnableDatagrams: true,
	})
	if err != nil {
		fmt.Println("conn err")
		fmt.Println(err)
		return err
	}
	reader := bufio.NewReader(os.Stdin)
	for {
		fmt.Println("What message do you want to send?")
		fmt.Print("message: ")
		text, _ := reader.ReadString('\n')
		sendData := []byte(text)
		err = conn.SendMessage(sendData)
		if err != nil {
			fmt.Println(err)
			return err
		}
		time.Sleep(1 * time.Second)
	}
}
```
接收使用者打的資訊並用datagram的形式傳給server

在執行server後，你會發現資料夾下多了tls_key.log，但是裡面什麼都沒有。

![](https://i.imgur.com/OJ1tVWv.png)

執行client後，key的資訊才會被寫進來，像這樣：

![](https://i.imgur.com/50ug2qr.png)

之後就可以使用Wireshark抓包了

開啟Wireshark
Edit->Preferences->Protocols
選擇QUIC，並設定使用的port

![](https://i.imgur.com/cL2UFpm.png)

現在Wireshark已經能偵測到QUIC封包，只是點開那些封包後會發現payload的資訊無法顯示，這是因為quic的封包都有用tls進行加密過，如果wireshark沒有鑰匙資訊，那也解不開這些封包。

![](https://i.imgur.com/Ao3atTr.png)

![](https://i.imgur.com/uGdepq0.png)

把之前設定的keylog傳給wireshark：
Edit->Preferences->Protocols
尋找TLS，設定(Pre)-Master-Secret log filename

![](https://i.imgur.com/gZ1SqLF.png)

選擇我們的keylog檔案

![](https://i.imgur.com/fM06MDD.png)

這樣就能解開payload了
再來用client隨便傳一些資訊

![](https://i.imgur.com/9nxdgJf.png)

然後在wireshark上過濾出quic.frame_type == 31的封包，這類型的封包是，QUIC datagram 封包。

![](https://i.imgur.com/yWhlhCT.png)

點開封包，可以發現剛剛傳送的資訊確實被解析出來了

![](https://i.imgur.com/lYhHFcK.png)

reference:
https://github.com/quic-go/quic-go






