/
tracert.go
132 lines (116 loc) · 2.65 KB
/
tracert.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package gatherer
import (
"fmt"
"net"
"time"
"../logger"
"../utils"
"github.com/aeden/traceroute"
"github.com/gorilla/websocket"
geoip2 "github.com/oschwald/geoip2-golang"
)
type node struct {
addr string
ttl int
elapsedTime time.Duration
country string
lat float64
long float64
}
// Tracer trace route to the target.
// WebSocket API.
type Tracer struct {
mconn *utils.MuxConn
host string
route []node
}
// NewTracer returns a new route tracer.
func NewTracer() *Tracer {
return &Tracer{
mconn: &utils.MuxConn{},
route: make([]node, 0),
}
}
// Set implements Gatherer interface.
// Params should be {conn *websocket.Conn, target string}
func (t *Tracer) Set(v ...interface{}) {
t.mconn.Conn = v[0].(*websocket.Conn)
t.host = v[1].(string)
}
// Report implements Gatherer interface.
func (t *Tracer) Report() map[string]interface{} {
return nil
}
// Run implements Gatherer interface.
func (t *Tracer) Run() {
logger.Green.Println("Trace Route and GeoIP")
t.route = []node{}
ch := make(chan traceroute.TracerouteHop, 0)
go func() {
hop, ok := <-ch
if !ok {
return
}
t.printHop(hop)
}()
_, err := traceroute.Traceroute(t.host, &traceroute.TracerouteOptions{}, ch)
if err != nil {
logger.Red.Println(err)
return
}
time.Sleep(1 * time.Second)
}
func (t *Tracer) printHop(hop traceroute.TracerouteHop) {
addr := fmt.Sprintf("%v.%v.%v.%v", hop.Address[0], hop.Address[1], hop.Address[2], hop.Address[3])
if hop.Success {
n := node{
addr: addr,
ttl: hop.TTL,
elapsedTime: hop.ElapsedTime,
}
n.geoip()
t.route = append(t.route, n)
logger.Blue.Printf("TTL: %d; addr: %s; ElapsedTime: %s; Country: %s; Position: (%f, %f)",
n.ttl, n.addr, n.elapsedTime, n.country, n.lat, n.long)
ret := map[string]interface{}{
"ttl": n.ttl,
"addr": n.addr,
"elapsed_time": n.elapsedTime,
"country": n.country,
"lat": n.lat,
"long": n.long,
}
t.mconn.Send(ret)
return
}
n := node{
addr: addr,
ttl: hop.TTL,
}
logger.Blue.Println(n.ttl, "no reply")
ret := map[string]interface{}{
"ttl": n.ttl,
"addr": n.addr,
"elapsed_time": n.elapsedTime,
"country": n.country,
"lat": n.lat,
"long": n.long,
}
t.mconn.Send(ret)
}
func (n *node) geoip() {
db, err := geoip2.Open("/dict/GeoLite2-City.mmdb")
defer db.Close()
if err != nil {
logger.Red.Println(err)
return
}
record, err := db.City(net.ParseIP(n.addr))
if err != nil {
logger.Red.Println(err)
return
}
n.country = record.Country.Names["en"]
n.lat = record.Location.Latitude
n.long = record.Location.Longitude
}