Реализация ICMP ping в Go

возможно ли реализовать ICMP ping в Go? Альтернативой является развилка процесса "ping", но я бы предпочел записать его в Go.

2 ответов


В настоящее время функция ICMP Echo (Ping) не поддерживается в пакете Go net.

нет поддержки для отправки ICMP эхо-запрос. Вы должны добавить поддержка пакета net. пинг


следующий код показывает, как выполнить пинг по IPv4 с помощью сырых сокетов (требует прав root):

package main

import (
    "log"
    "net"
    "os"

    "golang.org/x/net/icmp"
    "golang.org/x/net/internal/iana"
    "golang.org/x/net/ipv4"
)

const targetIP = "8.8.8.8"

func main() {
    c, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
    if err != nil {
        log.Fatalf("listen err, %s", err)
    }
    defer c.Close()

    wm := icmp.Message{
        Type: ipv4.ICMPTypeEcho, Code: 0,
        Body: &icmp.Echo{
            ID: os.Getpid() & 0xffff, Seq: 1,
            Data: []byte("HELLO-R-U-THERE"),
        },
    }
    wb, err := wm.Marshal(nil)
    if err != nil {
        log.Fatal(err)
    }
    if _, err := c.WriteTo(wb, &net.IPAddr{IP: net.ParseIP(targetIP)}); err != nil {
        log.Fatalf("WriteTo err, %s", err)
    }

    rb := make([]byte, 1500)
    n, peer, err := c.ReadFrom(rb)
    if err != nil {
        log.Fatal(err)
    }
    rm, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
    if err != nil {
        log.Fatal(err)
    }
    switch rm.Type {
    case ipv4.ICMPTypeEchoReply:
        log.Printf("got reflection from %v", peer)
    default:
        log.Printf("got %+v; want echo reply", rm)
    }
}

на примере кода найти здесь: https://godoc.org/golang.org/x/net/icmp#PacketConn

чтобы выполнить ping из Linux как непривилегированный пользователь, см. этот пост