update
This commit is contained in:
parent
5ece8b96bb
commit
68f1eef7a6
@ -24,6 +24,8 @@ var dns, ipinfoaddr string
|
||||
var timeout int
|
||||
var maxHop int
|
||||
var disableIpInfo bool
|
||||
var bindAddr string
|
||||
var hideIncorrect bool
|
||||
|
||||
func init() {
|
||||
CmdNatClient.Flags().StringVarP(&natc.ServiceTarget, "target", "t", "", "forward server target address")
|
||||
@ -48,6 +50,8 @@ func init() {
|
||||
CmdNetTrace.Flags().IntVarP(&timeout, "timeout", "t", 800, "超时时间,单位毫秒")
|
||||
CmdNetTrace.Flags().IntVarP(&maxHop, "max-hop", "m", 32, "最大跳数")
|
||||
CmdNetTrace.Flags().BoolVarP(&disableIpInfo, "disable-ipinfo", "D", false, "禁用ip信息查询")
|
||||
CmdNetTrace.Flags().StringVarP(&bindAddr, "bind", "b", "0.0.0.0", "绑定地址")
|
||||
CmdNetTrace.Flags().BoolVarP(&hideIncorrect, "hide-incorrect", "H", false, "隐藏错误节点")
|
||||
Cmd.AddCommand(CmdNetTrace)
|
||||
|
||||
}
|
||||
@ -86,7 +90,7 @@ var CmdNetTrace = &cobra.Command{
|
||||
}
|
||||
for _, target := range args {
|
||||
starlog.Infoln("Traceroute to ", target)
|
||||
Traceroute(target, dns, maxHop, time.Millisecond*time.Duration(timeout), ipinfoaddr)
|
||||
Traceroute(target, bindAddr, dns, maxHop, time.Millisecond*time.Duration(timeout), ipinfoaddr, hideIncorrect)
|
||||
fmt.Println("-----------------------------")
|
||||
}
|
||||
},
|
||||
|
112
net/trace.go
112
net/trace.go
@ -32,7 +32,7 @@ func useCustomeDNS(dns []string) {
|
||||
net.DefaultResolver = &resolver
|
||||
}
|
||||
|
||||
func Traceroute(address string, dns string, maxHops int, timeout time.Duration, ipinfoAddr string) {
|
||||
func Traceroute(address string, bindaddr string, dns string, maxHops int, timeout time.Duration, ipinfoAddr string, hideIncorrect bool) {
|
||||
ipinfo := net.ParseIP(address)
|
||||
if ipinfo == nil {
|
||||
{
|
||||
@ -51,9 +51,9 @@ func Traceroute(address string, dns string, maxHops int, timeout time.Duration,
|
||||
address = addr.String()
|
||||
}
|
||||
}
|
||||
traceroute(address, maxHops, timeout, ipinfoAddr)
|
||||
traceroute(address, bindaddr, maxHops, timeout, ipinfoAddr, hideIncorrect)
|
||||
}
|
||||
func traceroute(address string, maxHops int, timeout time.Duration, ipinfoAddr string) {
|
||||
func traceroute(address string, bindaddr string, maxHops int, timeout time.Duration, ipinfoAddr string, hideIncorrect bool) {
|
||||
ipinfo := net.ParseIP(address)
|
||||
if ipinfo == nil {
|
||||
starlog.Errorln("IP地址解析失败:", address)
|
||||
@ -74,18 +74,16 @@ func traceroute(address string, maxHops int, timeout time.Duration, ipinfoAddr s
|
||||
replyType = ipv6.ICMPTypeEchoReply
|
||||
proto = 58
|
||||
}
|
||||
c, err := icmp.ListenPacket(network, "0.0.0.0")
|
||||
if bindaddr == "" {
|
||||
bindaddr = "0.0.0.0"
|
||||
}
|
||||
c, err := icmp.ListenPacket(network, bindaddr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
dst, err := net.ResolveIPAddr(resolveIP, address)
|
||||
if err != nil {
|
||||
starlog.Errorln("IP地址解析失败:", address, err)
|
||||
return
|
||||
}
|
||||
if maxHops == 0 {
|
||||
maxHops = 32
|
||||
}
|
||||
@ -95,6 +93,13 @@ func traceroute(address string, maxHops int, timeout time.Duration, ipinfoAddr s
|
||||
}
|
||||
exitfor:
|
||||
for i := 1; i <= maxHops; i++ {
|
||||
retry := 0
|
||||
doRetry:
|
||||
dst, err := net.ResolveIPAddr(resolveIP, address)
|
||||
if err != nil {
|
||||
starlog.Errorln("IP地址解析失败:", address, err)
|
||||
return
|
||||
}
|
||||
if atomic.LoadInt32(&firstTargetHop) <= int32(i) {
|
||||
return
|
||||
}
|
||||
@ -134,34 +139,73 @@ exitfor:
|
||||
continue
|
||||
}
|
||||
|
||||
reply := make([]byte, 1500)
|
||||
err = c.SetReadDeadline(time.Now().Add(timeout))
|
||||
if err != nil {
|
||||
fmt.Printf("%d\tSetReadDeadline error: %v\n", i, err)
|
||||
continue
|
||||
}
|
||||
n, peer, err := c.ReadFrom(reply)
|
||||
if err != nil {
|
||||
fmt.Printf("%d\tReadFrom error: %v\n", i, err)
|
||||
continue
|
||||
}
|
||||
duration := time.Since(start)
|
||||
now := time.Now()
|
||||
exitrecheck:
|
||||
for {
|
||||
reply := make([]byte, 1500)
|
||||
err = c.SetReadDeadline(time.Now().Add(timeout))
|
||||
if err != nil {
|
||||
fmt.Printf("%d\tSetReadDeadline error: %v\n", i, err)
|
||||
break
|
||||
}
|
||||
n, peer, err := c.ReadFrom(reply)
|
||||
if err != nil {
|
||||
fmt.Printf("%d\tReadFrom error: %v\n", i, err)
|
||||
break
|
||||
}
|
||||
duration := time.Since(start)
|
||||
|
||||
rm, err := icmp.ParseMessage(proto, reply[:n])
|
||||
if err != nil {
|
||||
fmt.Printf("%d\tParseMessage error: %v\n", i, err)
|
||||
return
|
||||
rm, err := icmp.ParseMessage(proto, reply[:n])
|
||||
if err != nil {
|
||||
fmt.Printf("%d\tParseMessage error: %v\n", i, err)
|
||||
break
|
||||
}
|
||||
|
||||
switch rm.Type {
|
||||
case exceededType:
|
||||
fmt.Printf("%d\thops away:\t%s\t(%s) %s\n", i, peer, duration, GetIPInfo(peer.String(), ipinfoAddr))
|
||||
break exitrecheck
|
||||
case replyType:
|
||||
fmt.Printf("%d\thops away:\t%s\t(%s) %s\n", i, peer, duration, GetIPInfo(peer.String(), ipinfoAddr))
|
||||
if peer.String() == dst.String() {
|
||||
break exitfor
|
||||
}
|
||||
case ipv4.ICMPTypeEcho, ipv6.ICMPTypeEchoRequest:
|
||||
if time.Now().Sub(now).Seconds() > timeout.Seconds() {
|
||||
if retry < 1 {
|
||||
retry++
|
||||
goto doRetry
|
||||
}
|
||||
if !hideIncorrect {
|
||||
fmt.Printf("%d\tInvalid Echo Request:%s (%s) %s\n", i, peer, duration, GetIPInfo(peer.String(), ipinfoAddr))
|
||||
}
|
||||
break exitrecheck
|
||||
}
|
||||
case ipv4.ICMPTypeDestinationUnreachable, ipv6.ICMPTypeDestinationUnreachable:
|
||||
if time.Now().Sub(now).Seconds() > timeout.Seconds() {
|
||||
if retry < 1 {
|
||||
retry++
|
||||
goto doRetry
|
||||
}
|
||||
if !hideIncorrect {
|
||||
fmt.Printf("%d\tInvalid DstInv Request:%s (%s) %s\n", i, peer, duration, GetIPInfo(peer.String(), ipinfoAddr))
|
||||
}
|
||||
break exitrecheck
|
||||
}
|
||||
default:
|
||||
if time.Now().Sub(now).Seconds() > timeout.Seconds() {
|
||||
if retry < 1 {
|
||||
retry++
|
||||
goto doRetry
|
||||
}
|
||||
if !hideIncorrect {
|
||||
fmt.Printf("%d\tgot %+v from %v (%s) %s\n", i, rm.Type, peer, duration, GetIPInfo(peer.String(), ipinfoAddr))
|
||||
}
|
||||
break exitrecheck
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch rm.Type {
|
||||
case exceededType:
|
||||
fmt.Printf("%d\thops away:\t%s\t(%s) %s\n", i, peer, duration, GetIPInfo(peer.String(), ipinfoAddr))
|
||||
case replyType:
|
||||
fmt.Printf("%d\thops away:\t%s\t(%s) %s\n", i, peer, duration, GetIPInfo(peer.String(), ipinfoAddr))
|
||||
break exitfor
|
||||
default:
|
||||
fmt.Printf("%d\tgot %+v from %v; want echo reply;%s\n", i, rm, peer, GetIPInfo(peer.String(), ipinfoAddr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user