bedrocktool/subcommands/capture.go

104 lines
2.4 KiB
Go
Raw Normal View History

2022-09-04 14:53:21 +00:00
package subcommands
2022-04-03 20:12:21 +00:00
import (
"bytes"
"context"
"flag"
"net"
"os"
"time"
2022-09-04 14:53:21 +00:00
"github.com/bedrock-tool/bedrocktool/utils"
2022-09-04 14:26:32 +00:00
2022-04-03 20:12:21 +00:00
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcapgo"
"github.com/google/subcommands"
2022-04-03 20:12:21 +00:00
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
2022-09-03 17:32:30 +00:00
"github.com/sirupsen/logrus"
2022-04-03 20:12:21 +00:00
)
func init() {
2022-09-04 14:26:32 +00:00
utils.RegisterCommand(&CaptureCMD{})
2022-04-03 20:12:21 +00:00
}
2022-09-04 13:24:55 +00:00
func dump_packet(w *pcapgo.Writer, from_client bool, pk packet.Header, payload []byte) {
2022-04-03 20:12:21 +00:00
var err error
2022-09-04 13:24:55 +00:00
var prefix []byte
2022-04-03 20:12:21 +00:00
if from_client {
2022-09-04 13:24:55 +00:00
prefix = []byte("client")
2022-04-03 20:12:21 +00:00
} else {
2022-09-04 13:24:55 +00:00
prefix = []byte("server")
2022-04-03 20:12:21 +00:00
}
2022-09-03 22:56:40 +00:00
packet_data := bytes.NewBuffer(nil)
2022-09-04 13:24:55 +00:00
pk.Write(packet_data)
packet_data.Write(payload)
2022-04-03 20:12:21 +00:00
serialize_buf := gopacket.NewSerializeBuffer()
err = gopacket.SerializeLayers(
serialize_buf,
gopacket.SerializeOptions{},
2022-09-04 13:24:55 +00:00
gopacket.Payload(prefix),
2022-09-03 22:56:40 +00:00
gopacket.Payload(packet_data.Bytes()),
2022-04-03 20:12:21 +00:00
)
if err != nil {
2022-09-07 12:07:33 +00:00
logrus.Fatal(err)
2022-04-03 20:12:21 +00:00
}
err = w.WritePacket(gopacket.CaptureInfo{
Timestamp: time.Now(),
Length: len(serialize_buf.Bytes()),
CaptureLength: len(serialize_buf.Bytes()),
2022-09-04 13:24:55 +00:00
InterfaceIndex: 1,
2022-04-03 20:12:21 +00:00
}, serialize_buf.Bytes())
if err != nil {
2022-09-07 12:07:33 +00:00
logrus.Fatal(err)
2022-04-03 20:12:21 +00:00
}
}
type CaptureCMD struct {
server_address string
}
func (*CaptureCMD) Name() string { return "capture" }
func (*CaptureCMD) Synopsis() string { return "capture packets in a pcap file" }
func (p *CaptureCMD) SetFlags(f *flag.FlagSet) {
f.StringVar(&p.server_address, "address", "", "remote server address")
}
2022-09-03 17:32:30 +00:00
func (c *CaptureCMD) Usage() string {
2022-09-04 14:26:32 +00:00
return c.Name() + ": " + c.Synopsis() + "\n" + utils.SERVER_ADDRESS_HELP
}
2022-04-03 20:12:21 +00:00
func (c *CaptureCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
2022-09-04 14:26:32 +00:00
address, hostname, err := utils.ServerInput(c.server_address)
2022-04-03 20:12:21 +00:00
if err != nil {
2022-09-07 12:07:33 +00:00
logrus.Fatal(err)
return 1
2022-04-03 20:12:21 +00:00
}
fio, err := os.Create(hostname + "-" + time.Now().Format("2006-01-02_15-04-05") + ".pcap")
2022-04-03 20:12:21 +00:00
if err != nil {
2022-09-07 12:07:33 +00:00
logrus.Fatal(err)
return 1
2022-04-03 20:12:21 +00:00
}
defer fio.Close()
w := pcapgo.NewWriter(fio)
2022-04-03 20:12:21 +00:00
w.WriteFileHeader(65536, layers.LinkTypeEthernet)
2022-09-04 14:26:32 +00:00
proxy := utils.NewProxy(logrus.StandardLogger())
proxy.PacketFunc = func(header packet.Header, payload []byte, src, dst net.Addr) {
from_client := src.String() == proxy.Client.LocalAddr().String()
2022-09-04 13:24:55 +00:00
dump_packet(w, from_client, header, payload)
}
2022-08-13 14:30:46 +00:00
2022-09-04 13:24:55 +00:00
err = proxy.Run(ctx, address)
2022-09-03 17:32:30 +00:00
if err != nil {
2022-09-07 12:07:33 +00:00
logrus.Fatal(err)
2022-09-03 17:32:30 +00:00
return 1
2022-04-03 20:12:21 +00:00
}
2022-09-03 17:32:30 +00:00
return 0
2022-04-03 20:12:21 +00:00
}