我试图拦截和修改在端口 2106 上发送和接收的数据包,但连接是使用随机端口建立的。因此,我不知道使用哪个本地主机端口来创建代理来完成此任务。
通过以下代码,我可以拦截并读取数据包:
package main
import (
"fmt"
"log"
"sync"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
)
func capturePackets(device string, wg *sync.WaitGroup) {
defer wg.Done()
handle, err := pcap.OpenLive(device, 65536, true, pcap.BlockForever)
if err != nil {
log.Printf("Error opening interface %s: %v", device, err)
return
}
defer handle.Close()
var filter = "tcp and (dst port 2106 or src port 2106)"
err = handle.SetBPFFilter(filter)
if err != nil {
log.Printf("Error setting filter for %s: %v", device, err)
return
}
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
fmt.Printf("Captured packet on interface %s: %v\n", device, packet)
}
}
func main() {
devices, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}
var wg sync.WaitGroup
for _, device := range devices {
wg.Add(1)
go capturePackets(device.Name, &wg) // Capture packets in a goroutine
}
// Wait for all goroutines to finish
wg.Wait()
}
但是,我还需要根据拦截的数据包发送一个新数据包,这意味着我需要根据收到的数据包拦截并向服务器发送另一个数据包。有人可以帮我弄清楚如何做到这一点吗?
我知道使用 iptables,我可以将服务器的所有流量重定向到我的代理服务器,但我想在单个 Go 二进制文件中实现所有内容。这可能吗?
这是一个草图,未经测试,但我希望它能给出总体思路。
它使用
packetSource.Packages()
-> package.Data()
的原始数据作为 io.Reader
,然后可以使用 io.MultiWriter
将其复制到多个编写器(一个 io.TeeWriter
仅够两个编写器,但这更多可扩展)。
通过编写器传入的数据必须进行相应的检查和转发,而不是使用
io.Discard
。
请注意,
gopacket
模块中还有多个“层”,这可能会使分析变得更容易,因此转发字节可能不是进行更广泛检查的最佳解决方案。
package main
import (
"bytes"
"fmt"
"io"
"log"
"sync"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
)
func capturePackets(device string, wg *sync.WaitGroup) {
defer wg.Done()
handle, err := pcap.OpenLive(device, 65536, true, pcap.BlockForever)
if err != nil {
log.Printf("Error opening interface %s: %v", device, err)
return
}
defer handle.Close()
var filter = "tcp and (dst port 2106 or src port 2106)"
err = handle.SetBPFFilter(filter)
if err != nil {
log.Printf("Error setting filter for %s: %v", device, err)
return
}
// the ioutil.Discard must be replaced by an io.Writer to do the actual work
analyticsWriter := io.Discard
forwardingWriter := io.Discard
// this will copy to both at the sane time, reducing memory usage
multiWriter := io.MultiWriter(analyticsWriter, forwardingWriter)
// here the logic should wire both writers, so the results of the analyticsWriter
// can also be sent to forwardingWriter (if that is the desired architecture...)
startAnalytics(analyticsWriter, forwardingWriter)
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
bytesWritten, err := io.Copy(multiWriter, bytes.NewReader(packet.Data()))
if err != nil {
fmt.Printf("warn: could not copy: %s", err)
}
fmt.Printf("Captured packet on interface %s, %d bytes written: %v\n", device, bytesWritten, packet)
}
}
func startAnalytics(_, _ io.Writer) {
// analyse and use forwarding writer
}
func main() {
devices, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}
var wg sync.WaitGroup
for _, device := range devices {
wg.Add(1)
go capturePackets(device.Name, &wg) // Capture packets in a goroutine
}
// Wait for all goroutines to finish
wg.Wait()
}