无法接收超时消息

时间:2017-02-08 14:36:16

标签: go icmp

我根据pwnat的想法做了一些测试,它引入了一种没有第三方的NAT遍历方法:服务器将ICMP echo请求包发送到固定地址(例如,{{ 1}})其中没有回复的回应回复,客户端假装是Internet上的跳,向服务器发送ICMP超时报文,期望服务器前面的NAT转发ICMP超时消息到服务器。
在我向3.3.3.3发送信息后,我在3.3.3.3中运行以下代码,以便在Go中收听ICMP消息:

192.168.1.100

并且在package main import ( "fmt" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" ) func main() { c, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { fmt.Println("listen error", err) } rb := make([]byte, 1500) for { n, _, err := c.ReadFrom(rb) if err != nil { fmt.Printf("read err: %s\n", err) } reply, err := icmp.ParseMessage(1, rb[:n]) if err != nil { fmt.Println("parse icmp err:", err) return } switch reply.Type { case ipv4.ICMPTypeTimeExceeded: if _, ok := reply.Body.(*icmp.TimeExceeded); ok { // internet header(20 bytes) plus the first 64 bits of the original datagram's data //fmt.Println("recv id ", binary.BigEndian.Uint16(timeExceed.Data[22:24])) fmt.Printf("ttl exceeded\n") } default: } } } 中运行以发送伪造时间的程序超出了192.168.2.100的消息:

192.168.1.100

问题是package main import ( "errors" "fmt" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" "net" "os" ) func sendTtle(host string) error { conn, err := net.Dial("ip4:icmp", host) if err != nil { return err } // original IP header h := ipv4.Header{ Version: 4, Len: 20, TotalLen: 20 + 8, TTL: 64, Protocol: 1, } h.Src = net.ParseIP(host) h.Dst = net.ParseIP("3.3.3.3") iph, err := h.Marshal() if err != nil { fmt.Println("ip header error", err) return err } // 8 bytes of original datagram's data echo := icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: 3456, Seq: 1, }} oriReq, err := echo.Marshal(nil) if err != nil { return errors.New("Marshal error") } data := append(iph, oriReq...) te := icmp.Message{ Type: ipv4.ICMPTypeTimeExceeded, Code: 0, Body: &icmp.TimeExceeded{ Data: data, }} if buf, err := te.Marshal(nil); err == nil { fmt.Println("sent") if _, err := conn.Write(buf); err != nil { return errors.New("write error") } } else { return errors.New("Marshal error") } return nil } func main() { argc := len(os.Args) if argc < 2 { fmt.Println("usage: prpgram + host") return } if err := sendTtle(os.Args[1]); err != nil { fmt.Println("failed to send TTL exceeded message: ", err) } } 无法接收消息。可能的原因是什么?

1 个答案:

答案 0 :(得分:2)

您的代码没有问题。如果您在同一网络中运行代码(我的意思是没有NAT /路由器参与),程序将按预期接收超出时间的消息。原因是pwnat使用的理论现在不起作用。

  • 首先,您没有获得发送的echo请求的标识符 192.168.2.1003.3.3.3,标识符将是唯一的 通过NAPT(如果有)映射到外部查询ID,以便它可以路由 future ICMP Echo使用相同的查询ID回复发件人。根据{{​​3}},

      

    在NAPT设置中,如果ICMP中嵌入的IP消息恰好是   一个TCP,UDP或ICMP查询包,你还需要修改   TCP / UDP标头或查询中的适当TU端口号   ICMP查询标头中的标识符字段。

  • 其次,根据rfc 5508:

      

    如果NAT设备从私有领域收到ICMP错误数据包,   并且NAT没有嵌入式有效负载的活动映射,   NAT应该静默地丢弃ICMP错误数据包。

因此伪造的时间超过了消息无法通过。 rfc 3022 ICMP error packet modifications section是关于此的更多细节。