Bra*_*Man 5 sockets ip udp go packet
我正在寻找一种使用 go 语言发送数据包的方法,它使我能够查看和设置数据包的 TTL 和其他低级字段(我不需要修改以太网标头,只需修改 IP 和 UDP 标头)。我尝试在下面的代码中制作并发送我自己的数据包。
运行以下代码时,接收者不会收到任何消息。任何人都可以 a.) 提醒我在此代码中犯的任何错误,或者 b.) 建议使用 golang 发送 UDP 数据的另一种方法,同时保留对 IP 和 UDP 标头的访问权限?
我已经删除了 MAC 地址,需要替换它们才能运行此代码。
package main
import (
"syscall"
"log"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"fmt"
"encoding/hex"
"encoding/json"
"net"
)
type NameTag struct {
Name string `json:"name"`
}
func main() {
var err error
fd, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_UDP)
if e != nil {
fmt.Println("Problem @ location 1")
}
addr := syscall.SockaddrInet4{
Port: 27289,
Addr: [4]byte{127, 0, 0, 1},
}
p := pkt()
err = syscall.Sendto(fd, p, 0, &addr)
if err != nil {
log.Fatal("Sendto:", err)
}
}
func pkt() []byte {
sb := gopacket.NewSerializeBuffer()
nt := NameTag{"Paul"}
b, _ := json.Marshal(nt)
pld := gopacket.Payload(b)
l := uint16(len(pld))
udp := layers.UDP{
SrcPort: 27289,
DstPort: 27288,
Length: l + 8,
Checksum: 0,
}
l = l + 8
ip := layers.IPv4{
Version: 0x4,
IHL: 5,
Length: 20 + l,
TTL: 255,
Flags: 0x40,
FragOffset: 0,
Checksum: 0,
Protocol: syscall.IPPROTO_UDP,
DstIP: net.IPv4(127, 0, 0, 1),
SrcIP: net.IPv4(127, 0, 0, 1),
}
l = l + 20
eth := layers.Ethernet{
EthernetType: layers.EthernetTypeIPv4,
SrcMAC: net.HardwareAddr{
0x--, 0x--, 0x--, 0x--, 0x--, 0x--,
},
DstMAC: net.HardwareAddr{
0x--, 0x--, 0x--, 0x--, 0x--, 0x--,
},
}
fmt.Println(pld.SerializeTo(sb, gopacket.SerializeOptions{}))
fmt.Println(udp.SerializeTo(sb, gopacket.SerializeOptions{}))
fmt.Println(ip.SerializeTo(sb, gopacket.SerializeOptions{}))
fmt.Println(eth.SerializeTo(sb, gopacket.SerializeOptions{}))
//Debug prints here (first line is for dump to packet validator)
fmt.Println(hex.EncodeToString(sb.Bytes()))
fmt.Println(sb.Bytes())
return sb.Bytes()
}
Run Code Online (Sandbox Code Playgroud)
package main
import (
"syscall"
"os"
"fmt"
)
func main() {
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_UDP)
if err != nil {
fmt.Println(err)
return
}
sa:= &syscall.SockaddrInet4{
Addr: [4]byte{127,0,0,1},
Port:27288,
}
e := syscall.Bind(fd, sa)
if e != nil {
fmt.Println("problems @ location 1")
}
f := os.NewFile(uintptr(fd), fmt.Sprintf("fd%d", fd))
fmt.Println("Entering main loop")
for {
fmt.Println("In loop")
buf := make([]byte, 1024)
numRead, err := f.Read(buf)
if err != nil {
fmt.Println("problems @ location 2")
}
fmt.Printf("Loop done %v\n", buf[:numRead])
}
}
Run Code Online (Sandbox Code Playgroud)