-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchecks.go
122 lines (108 loc) · 2.81 KB
/
checks.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
package main
import (
"bytes"
"errors"
"fmt"
"net"
"net/url"
"strings"
)
func tcpChecks(ports map[string]*url.URL) map[string]string {
results := make(map[string]string, len(ports))
for _, uri := range ports {
results[uri.String()] = checkConn(uri)
}
return results
}
func checkConn(uri *url.URL) string {
protocol := "tcp"
address := uri.Host
service := uri.Scheme
if strings.HasSuffix(service, "-udp") {
service = service[:len(service)-4]
protocol = "udp"
} else if strings.HasSuffix(address, "-tcp") {
service = service[:len(service)-4]
protocol = "tcp"
}
conn, err := net.DialTimeout(protocol, uri.Host, timeout)
if err != nil {
var opErr *net.OpError
if errors.As(err, &opErr) {
return opErr.Err.Error()
}
return fmt.Sprintf("%#v", err)
}
if conn == nil {
return "nil"
}
defer func() {
_ = conn.Close()
}()
ret := "verified"
// depending on the service we may want to do some health / ping checking
switch {
case service == "mysql":
case service == "mariadb":
// this is very crude and incorrect for now (but kinda works)
resp, respErr := readResponseBytes(conn, 4)
if respErr != nil {
return respErr.Error()
}
if bytes.Compare(resp[1:4], []byte("\x00\x00\x00")) != 0 {
return fmt.Sprintf("not MySQL/MariaDB (%q)", resp)
}
case service == "mssql":
// this is very crude and incorrect for now (but kinda works)
return IsMSSQLServer(uri)
case service == "http":
case service == "ssh":
// reading the info data from the server
resp, respErr := readResponseString(conn)
if respErr != nil {
return respErr.Error()
}
if !strings.HasPrefix(resp, "SSH-") {
return fmt.Sprintf("not a SSH server response (%q)", resp[:min(len(resp), 32)])
}
case service == "dns":
// reading the info data from the server
if protocol == "udp" {
if !isRealDNSServerUDP(conn) {
return "not dns"
}
} else if !isRealDNSServerTCP(conn) {
return "not dns"
}
case service == "nats":
// reading the info data from the server
resp, respErr := readResponseString(conn)
if respErr != nil {
return respErr.Error()
}
if !strings.HasPrefix(resp, "INFO {") {
return fmt.Sprintf("not a NATS server response (%q)", resp[:min(len(resp), 32)])
}
case service == "smtp":
// reading the info data from the server
resp, respErr := readResponseString(conn)
if respErr != nil {
return respErr.Error()
}
if !strings.HasPrefix(resp, "220 ") {
return fmt.Sprintf("not a SMTP (%q)", resp[:min(len(resp), 32)])
}
case uri.RawQuery != "":
// reading the info data from the server
resp, respErr := readResponseString(conn)
if respErr != nil {
return respErr.Error()
}
if !strings.HasPrefix(resp, uri.RawQuery) {
return fmt.Sprintf("expected %q but got %q", uri.RawQuery, resp[:min(len(resp), 32)])
}
default:
ret = "found"
}
return ret
}