@@ -2,7 +2,11 @@ package main
22
33import (
44 "encoding/hex"
5+ "encoding/json"
6+ "flag"
57 "fmt"
8+ "io/ioutil"
9+ "log"
610 "math/rand"
711 "net"
812 "os"
@@ -11,39 +15,86 @@ import (
1115)
1216
1317const (
14- banner = `
18+ Banner = `
1519
16- .´/
17- / ( .----------------.
18- [ ]░░░░░░░░░░░|// RESPOUNDER //|
19- ) ( '----------------'` + "\n " +
20- " '-' \n "
20+ .´/
21+ / ( .----------------.
22+ [ ]░░░░░░░░░░░|// RESPOUNDER //|
23+ ) ( '----------------'
24+ '-'
25+ `
2126
22- timeoutSec = 3
27+ Version = 1.0
28+ TimeoutSec = 3
29+ )
30+
31+ var (
32+ // stdout is default output
33+ outFile = os .Stdout
34+
35+ // default logger is set to abyss
36+ logger = log .New (ioutil .Discard , "" , 0 )
37+
38+ // argument flags
39+ jsonPtr = flag .Bool ("json" , false ,
40+ `Prints a JSON to STDOUT if a responder is detected on
41+ network. Other text is sent to STDERR` )
42+
43+ debugPtr = flag .Bool ("debug" , false ,
44+ `Creates a debug.log file with a trace of the program` )
2345)
2446
2547func main () {
26- fmt .Fprintln (os .Stderr , banner )
48+ initFlags ()
49+
50+ fmt .Fprintln (os .Stderr , Banner )
2751
2852 interfaces , _ := net .Interfaces ()
53+ logger .Println ("======== Starting RESPOUNDER ========" )
54+ logger .Printf ("List of all interfaces: \n %+v\n " , interfaces )
55+
56+ var resultMap []map [string ]string
57+
2958 for _ , inf := range interfaces {
30- checkResponderOnInterface (inf )
59+ detailsMap := checkResponderOnInterface (inf )
60+ if len (detailsMap ) > 0 {
61+ resultMap = append (resultMap , detailsMap )
62+ }
63+ }
64+
65+ if * debugPtr {
66+ fmt .Fprintln (os .Stderr , "Debug file 'debug.log' created." )
67+ }
68+
69+ if * jsonPtr {
70+ resultJSON , _ := json .Marshal (resultMap )
71+ fmt .Println (string (resultJSON ))
3172 }
73+ logger .Println ("======== Ending RESPOUNDER Session ========" )
3274}
3375
34- func checkResponderOnInterface (inf net.Interface ) string {
35- json := ""
76+ func checkResponderOnInterface (inf net.Interface ) map [ string ] string {
77+ var json map [ string ] string
3678 addrs , _ := inf .Addrs ()
37- if len (addrs ) > 0 {
38- ip := addrs [0 ].(* net.IPNet ).IP
39- if ip .String () != "127.0.0.1" {
40- fmt .Printf ("%-10s Sending probe from %s...\t " , "[" + inf .Name + "]" , ip )
41- responderAddr := sendLLMNRProbe (ip )
42- if responderAddr != "" {
43- fmt .Printf ("responder detected at %s\n " , responderAddr )
44- } else {
45- fmt .Println ("responder not detected" )
79+ logger .Printf ("List of all addresses on interface [%s]: %+v\n " ,
80+ inf .Name , addrs )
81+ ip := getValidIPv4Addr (addrs )
82+ logger .Printf ("Bind IP address for interface %+v is %+v\n " ,
83+ inf .Name , ip )
84+
85+ if ip != nil {
86+ fmt .Fprintf (outFile , "%-10s Sending probe from %s...\t " ,
87+ "[" + inf .Name + "]" , ip )
88+ responderIP := sendLLMNRProbe (ip )
89+ if responderIP != "" {
90+ fmt .Fprintf (outFile , "responder detected at %s\n " , responderIP )
91+ json = map [string ]string {
92+ "interface" : inf .Name ,
93+ "sourceIP" : ip .String (),
94+ "responderIP" : responderIP ,
4695 }
96+ } else {
97+ fmt .Fprintln (outFile , "responder not detected" )
4798 }
4899 }
49100 return json
@@ -68,16 +119,59 @@ func sendLLMNRProbe(ip net.IP) string {
68119 conn , err := net .ListenUDP ("udp" , & net.UDPAddr {IP : ip })
69120 if err != nil {
70121 fmt .Println ("Couldn't bind to a UDP interface. Bailing out!" )
122+ logger .Printf ("Bind error: %+v\n Source IP: %v\n " , err , ip )
123+ fmt .Println (err )
71124 }
72125
73126 defer conn .Close ()
74127 _ , _ = conn .WriteToUDP (n , & remoteAddr )
75128
76- conn .SetReadDeadline (time .Now ().Add (timeoutSec * time .Second ))
129+ conn .SetReadDeadline (time .Now ().Add (TimeoutSec * time .Second ))
77130 buffer := make ([]byte , 1024 )
78- _ , clientIP , err := conn .ReadFromUDP (buffer )
131+ bytes , clientIP , err := conn .ReadFromUDP (buffer )
79132 if err == nil { // no timeout (or any other) error
80133 responderIP = strings .Split (clientIP .String (), ":" )[0 ]
134+ logger .Printf ("Data received on %s from responder IP %s: %x\n " ,
135+ ip , clientIP , buffer [:bytes ])
136+ } else {
137+ logger .Printf ("Error getting response: %s\n " , err )
81138 }
82139 return responderIP
83140}
141+
142+ // From all the IP addresses of this interface,
143+ // extract the IPv4 address where we'll bind to
144+ func getValidIPv4Addr (addrs []net.Addr ) net.IP {
145+ var ip net.IP
146+ for _ , addr := range addrs { // amongst all addrs,
147+ ip = addr .(* net.IPNet ).IP .To4 () // pick the IPv4 addr
148+ if ip != nil && ip .String () != "127.0.0.1" {
149+ break
150+ }
151+ }
152+ return ip
153+ }
154+
155+ // parses cmd line flag and set appropriate variables
156+ func initFlags () {
157+ flag .Usage = func () {
158+ fmt .Fprintf (os .Stderr , "Respounder version %1.1f\n " , Version )
159+ fmt .Fprintf (os .Stderr , "Usage: $ respounder [-json] [-debug]" )
160+ fmt .Fprintf (os .Stderr , "\n \n Flags:\n " )
161+ flag .PrintDefaults ()
162+ }
163+
164+ flag .Parse ()
165+ if * jsonPtr {
166+ outFile = os .Stderr
167+ }
168+ if * debugPtr {
169+ f , err := os .OpenFile ("debug.log" ,
170+ os .O_CREATE | os .O_WRONLY | os .O_APPEND , 0644 )
171+ if err != nil {
172+ panic (err )
173+ }
174+ logger = log .New (f , "" , 0 )
175+ logger .SetPrefix ("[" + time .Now ().Format ("02-Jan-2006 15:04:05 MST" ) + "]: " )
176+ }
177+ }
0 commit comments