尝试一下 Go 语言的 gopacket 库初体验
最编程
2024-02-29 19:11:59
...
package main
import (
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"golang.org/x/sys/unix"
"log"
"net"
"syscall"
)
func getLocalIP(destIP net.IP) (net.IP, int) {
// 向目标地址使用udp发送
serverAddr, err := net.ResolveUDPAddr("udp", destIP.String()+":23456")
if err != nil {
log.Fatalln(err)
}
if con, err := net.DialUDP("udp", nil, serverAddr); err == nil {
if udpAddr, ok := con.LocalAddr().(*net.UDPAddr); ok {
return udpAddr.IP, udpAddr.Port
}
} else {
log.Fatalln("Can not get local ip: " + err.Error())
}
return nil, -1
}
func main() {
// 构建destination ip
const (
IPv4 = "ip4"
Addr = "192.168.0.3"
Port = 8081
)
dstIP, _ := net.ResolveIPAddr(IPv4, Addr)
dstPort := layers.TCPPort(Port)
sIP, sPort := getLocalIP(dstIP.IP)
srcPort := layers.TCPPort(sPort)
fmt.Printf("Local IP:PORT - %s:%d \n", sIP, srcPort)
// 构建IP包
ipPack := &layers.IPv4{
SrcIP: sIP,
DstIP: dstIP.IP,
Protocol: layers.IPProtocolTCP,
}
// 构建tcp报文段
tcpPack := &layers.TCP{
SrcPort: srcPort,
DstPort: dstPort,
Seq: 1205014776,
SYN: true,
}
if err := tcpPack.SetNetworkLayerForChecksum(ipPack); err != nil {
log.Fatalln(err)
}
serialBuf := gopacket.NewSerializeBuffer()
serialOpts := gopacket.SerializeOptions{
ComputeChecksums: true,
FixLengths: true,
}
if err := gopacket.SerializeLayers(serialBuf, serialOpts, ipPack, tcpPack); err != nil {
log.Fatalln(err)
}
// 创建套接字
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
if err != nil {
log.Fatalln(err)
}
defer unix.Close(fd)
//defer syscall.Close(fd)
// 构建目标地址对象
destAddr := syscall.SockaddrInet4{
Port: 0,
Addr: [4]byte{
dstIP.IP.To4()[0],
dstIP.IP.To4()[1],
dstIP.IP.To4()[2],
dstIP.IP.To4()[3],
},
}
err = syscall.Sendto(fd, serialBuf.Bytes(), 0, &destAddr)
if err != nil {
log.Fatalln("Send error: ", err)
}
log.Println("Send succeed.")
}