使用 Go 進行 HTTP 流量重放測試

在 Web 安全測試、API 調試、流量回歸測試中,HTTP 流量重放(HTTP Traffic Replay)是一項重要的技術。它可以幫助我們復現問題、測試系統兼容性、進行安全研究等。在這篇文章中,我們將簡單探討 HTTP 流量重放的原理,並通過 Go 語言實現不同的流量重放方案,同時介紹常見的開源工具。(身爲一個在小公司裏的網安牛馬,總得幹些雜活🐂🐎)

HTTP 流量重放的原理

HTTP 流量重放的基本流程如下:

  1. 捕獲 HTTP 請求:記錄 HTTP 請求的方法、URL、頭部、請求體等信息。

  2. 存儲 HTTP 請求數據:可以存儲爲 JSON、文本、數據庫或 PCAP 文件等格式。

  3. 重放 HTTP 請求:按照捕獲的請求信息,重新發送 HTTP 請求,並接收服務器響應。

  4. 比對響應結果(可選):檢查重放的響應是否與原始請求一致,驗證系統的穩定性。

HTTP 流量重放廣泛應用於:

使用 Go 語言實現 HTTP 流量重放

直接使用 httputil.DumpRequest 進行重放

Go 標準庫 net/http 提供了 httputil.DumpRequestOut,可以用來捕獲和重放 HTTP 請求。

示例代碼

package main
import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
)
func main() {
	url := "https://httpbin.org/post"
	// 構造原始請求
	originalReq, _ := http.NewRequest("POST", url, bytes.NewBuffer([]byte(`{"key": "value"}`)))
	originalReq.Header.Set("Content-Type""application/json")
	// 記錄請求數據
	dump, _ := httputil.DumpRequestOut(originalReq, true)
	fmt.Println("Captured Request:\n", string(dump))
	// 重新發送請求
	client := &http.Client{}
	resp, err := client.Do(originalReq)
	if err != nil {
		fmt.Println("Request failed:", err)
		return
	}
	defer resp.Body.Close()
	// 讀取響應
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println("Response:\n", string(body))
}

代碼解析

📌 適用場景:適用於簡單的 HTTP 請求重放,但無法攔截 HTTPS 流量。

使用 httptrace 監聽 HTTP 交互過程

如果你想更深入地分析 HTTP 交互過程,比如 DNS 解析、連接建立、TLS 握手,可以使用 httptrace。

示例代碼

package main
import (
	"bytes"
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptrace"
)
func main() {
	url := "https://httpbin.org/post"
	req, _ := http.NewRequest("POST", url, bytes.NewBuffer([]byte(`{"key": "value"}`)))
	req.Header.Set("Content-Type""application/json")
	trace := &httptrace.ClientTrace{
		GotConn: func(info httptrace.GotConnInfo) {
			fmt.Println("Connected to:", info.Conn.RemoteAddr())
		},
	}
	req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace))
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Request failed:", err)
		return
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println("Response:\n", string(body))
}

代碼解析

使用 go-mitmproxy 進行流量攔截和重放

對於 HTTPS 站點,直接抓取請求數據進行重放是不行的,因爲 TLS 保護了傳輸數據。要攔截 HTTPS 流量,可以使用 go-mitmproxy 作爲中間人代理。

安裝 go-mitmproxy,命令如下所示:

go install github.com/lqqyt2423/go-mitmproxy/cmd/go-mitmproxy@latest

啓動 go-mitmproxy,直接使用 go-mitmproxy 命令就可以了,運行如下所示:

go-mitmproxy 也提供了可視化的 web 界面

設置瀏覽器或系統代理爲 http://127.0.0.1:9080,然後抓取 HTTPS 流量。當然啦,我們還可以爲其編寫擴展插件實現一些符合我們實際操作的功能。

📌 適用場景

使用 gor 進行生產環境流量回放

Gor 是一個強大的 HTTP 流量回放工具,適用於大規模生產流量回放

步驟

  1. 捕獲 8080 端口的 HTTP 流量
sudo ./gor --input-raw :8080 --output-file requests.gor
  1. 重放請求到測試環境
sudo ./gor --input-file requests.gor --output-http "http://localhost:8080"

📌 適用場景

我認爲的最佳實踐

結語

HTTP 流量重放在 API 調試、安全測試、流量回歸等領域非常有價值。Go 語言提供了豐富的庫來實現流量捕獲與重放,同時 go-mitmproxy 和 gor 這樣的工具可以幫助我們更高效地進行 HTTPS 攔截和生產流量回放。當然啦,以上所提及到的還不是全部,實際上還有更好的。今天的內容到此就結束了,感謝您的收看🌹🌹🌹。如果本文對你有所幫,歡迎關注➕,點贊👍,收藏⭐️和轉發🚀🚀🚀🦀🦀🦀

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/HWCmYOxWM80ZxSuMnua41Q