Отправка пакетов UDP с помощью gopacket
Я пытаюсь отправить UDP-пакеты на удаленный хост, как это
conn, err := net.ListenPacket("ip4:udp", "0.0.0.0")
if err != nil {
panic(err)
}
ip := &layers.IPv4{
SrcIP: saddr,
DstIP: dip,
Protocol: layers.IPProtocolUDP,
}
udp := &layers.UDP{
SrcPort: layers.UDPPort(sport),
DstPort: layers.UDPPort(us.Port),
}
udp.SetNetworkLayerForChecksum(ip)
buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{
ComputeChecksums: true,
FixLengths: true,
}
if err := gopacket.SerializeLayers(buf, opts, udp); err != nil {
fmt.Printf("%v", err)
}
if _, err := us.Conn.WriteTo(buf.Bytes(), &net.IPAddr{IP: dip}); err != nil {
panic(err)
}
// reading
for {
buf2 := make([]byte, 4096)
n, addr, err := us.Conn.ReadFrom(buf2)
if err != nil {
fmt.Printf("%v", err)
}
if addr.String() == dip.String() {
fmt.Printf("Got a reply")
}
}
Но это продолжает приводить к ошибкам при чтении пакетов с read ip4 0.0.0.0: i/o timeout
, Когда я запускаю tcpdump, я вижу, что пакеты отправляются, и один ответ UDP возвращается на порт 53, все остальные - ICMP. Почему мой код не может прочитать эти пакеты?
2 ответа
Я не специалист по Go, но, похоже, вам нужно использовать функцию net.ListenUDP и указать порт для привязки сокета UDP. Затем вы используете это соединение (полученное из ListeUDP) для чтения оттуда. Я предполагаю, что вы указываете порт 53 в "спорт".
Вот простой пример клиента и сервера: https://varshneyabhi.wordpress.com/2014/12/23/simple-udp-clientserver-in-golang/
В примере вы смешиваете два разных подхода к созданию пакетов UDP. Вы должны использовать только один.
Первый подход с использованием модуля net приложения Go для подготовки и отправки пакета UDP. Это обычный способ, и в большинстве случаев вы будете использовать этот.
Secand подход, используя специальный модуль Google "gopacket" для подготовки пакета RAW сети. Это хакерский способ проверить оборудование или реализовать специальный протокол и эмулировать определенный стек протоколов. Это единственный экспертный способ создания специальных утилит и тестовых приложений.
Если вы создаете новое оборудование и пытаетесь взаимодействовать с этими устройствами, вы можете использовать gopakcet или, если вы просто создаете программное приложение, вам следует использовать сетевой пакет.