Skip to content

Commit 7ce2ccb

Browse files
authored
Merge pull request mackerelio#715 from wafuwafu13/dns-response
check-dns: add `expected-string` option
2 parents 912e648 + c42f506 commit 7ce2ccb

File tree

3 files changed

+136
-46
lines changed

3 files changed

+136
-46
lines changed

check-dns/README.md

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,45 @@
44

55
Monitor DNS response.
66

7-
## Synopsis
7+
## Usage
8+
9+
### Options
10+
811
```
9-
check-dns -H example.com -s 8.8.8.8
12+
-H, --host= The name or address you want to query
13+
-s, --server= DNS server you want to use for the lookup
14+
-p, --port= Port number you want to use (default: 53)
15+
-q, --querytype= DNS record query type (default: A)
16+
--norec Set not recursive mode
17+
-e, --expected-string= IP-ADDRESS string you expect the DNS server to return. If multiple IP-ADDRESS are returned at once, you have to specify whole string
18+
```
19+
20+
- query class is always IN.
21+
- Punycode is not supported.
22+
23+
### Check DNS server status
24+
25+
If DNS server returns `NOERROR` in status of HEADER, then the checker result becomes `OK`, if not `NOERROR`, then `CRITICAL`
26+
27+
```
28+
check-dns -H a.root-servers.net -s 8.8.8.8
29+
```
30+
31+
### Check string DNS server returns
32+
33+
- The currently supported query types are A, AAAA.
34+
35+
If DNS server returns 1.1.1.1 and 2.2.2.2
36+
```
37+
-e 1.1.1.1 -e 2.2.2.2 -> OK
38+
-e 1.1.1.1 -e 2.2.2.2 -e 3.3.3.3 -> WARNING
39+
-e 1.1.1.1 -> WARNING
40+
-e 1.1.1.1 -e 3.3.3.3 -> WARNING
41+
-e 3.3.3.3 -> CRITICAL
42+
-e 3.3.3.3 -e 4.4.4.4 -e 5.5.5.5 -> CRITICAL
43+
```
44+
```
45+
check-dns -H a.root-servers.net -s 8.8.8.8 -e 198.41.0.4
1046
```
1147

1248
## Installation
@@ -25,7 +61,7 @@ Or you can use this program by installing the official Mackerel package. See [Us
2561
Next, you can execute this program :-)
2662

2763
```
28-
check-dns -H example.com -s 8.8.8.8
64+
check-dns -H a.root-servers.net -s 8.8.8.8
2965
```
3066

3167

@@ -34,22 +70,6 @@ check-dns -H example.com -s 8.8.8.8
3470
If there are no problems in the execution result, add a setting in mackerel-agent.conf .
3571

3672
```
37-
[plugin.checks.fileage-sample]
38-
command = ["check-dns", "-H", "example.com", "-s", "8.8.8.8"]
39-
```
40-
41-
## Usage
42-
### Options
43-
44-
```
45-
-H, --host= The name or address you want to query
46-
-s, --server= DNS server you want to use for the lookup
47-
-p, --port= Port number you want to use (default: 53)
48-
-q, --querytype= DNS record query type where TYPE =(A, AAAA, SRV, TXT, MX, ANY) (default: A)
49-
-c, --queryclass= DNS record class type where TYPE =(IN, CS, CH, HS, NONE, ANY) (default: IN)
50-
--norec Set not recursive mode
73+
[plugin.checks.dns-sample]
74+
command = ["check-dns", "-H", "a.root-servers.net", "-s", "8.8.8.8"]
5175
```
52-
53-
## For more information
54-
55-
Please execute `check-dns -h` and you can get command line options.

check-dns/lib/check_dns.go

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ import (
1313
)
1414

1515
type dnsOpts struct {
16-
Host string `short:"H" long:"host" required:"true" description:"The name or address you want to query"`
17-
Server string `short:"s" long:"server" description:"DNS server you want to use for the lookup"`
18-
Port int `short:"p" long:"port" default:"53" description:"Port number you want to use"`
19-
QueryType string `short:"q" long:"querytype" default:"A" description:"DNS record query type where TYPE =(A, AAAA, SRV, TXT, MX, ANY)"`
20-
QueryClass string `short:"c" long:"queryclass" default:"IN" description:"DNS record class type where TYPE =(IN, CS, CH, HS, NONE, ANY)"`
21-
Norec bool `long:"norec" description:"Set not recursive mode"`
16+
Host string `short:"H" long:"host" required:"true" description:"The name or address you want to query"`
17+
Server string `short:"s" long:"server" description:"DNS server you want to use for the lookup"`
18+
Port int `short:"p" long:"port" default:"53" description:"Port number you want to use"`
19+
QueryType string `short:"q" long:"querytype" default:"A" description:"DNS record query type"`
20+
Norec bool `long:"norec" description:"Set not recursive mode"`
21+
ExpectedString []string `short:"e" long:"expected-string" description:"IP-ADDRESS string you expect the DNS server to return. If multiple IP-ADDRESS are returned at once, you have to specify whole string"`
2222
}
2323

2424
// Do the plugin
@@ -53,11 +53,7 @@ func (opts *dnsOpts) run() *checkers.Checker {
5353

5454
queryType, ok := dns.StringToType[strings.ToUpper(opts.QueryType)]
5555
if !ok {
56-
return checkers.Critical(fmt.Sprintf("%s is invalid queryType", opts.QueryType))
57-
}
58-
queryClass, ok := dns.StringToClass[strings.ToUpper(opts.QueryClass)]
59-
if !ok {
60-
return checkers.Critical(fmt.Sprintf("%s is invalid queryClass", opts.QueryClass))
56+
return checkers.Critical(fmt.Sprintf("%s is invalid query type", opts.QueryType))
6157
}
6258

6359
c := new(dns.Client)
@@ -66,7 +62,7 @@ func (opts *dnsOpts) run() *checkers.Checker {
6662
RecursionDesired: !opts.Norec,
6763
Opcode: dns.OpcodeQuery,
6864
},
69-
Question: []dns.Question{{Name: dns.Fqdn(opts.Host), Qtype: queryType, Qclass: uint16(queryClass)}},
65+
Question: []dns.Question{{Name: dns.Fqdn(opts.Host), Qtype: queryType, Qclass: dns.StringToClass["IN"]}},
7066
}
7167
m.Id = dns.Id()
7268

@@ -76,9 +72,58 @@ func (opts *dnsOpts) run() *checkers.Checker {
7672
}
7773

7874
checkSt := checkers.OK
75+
/**
76+
if DNS server return 1.1.1.1, 2.2.2.2
77+
1: -e 1.1.1.1 -e 2.2.2.2 -> OK
78+
2: -e 1.1.1.1 -e 2.2.2.2 -e 3.3.3.3 -> WARNING
79+
3: -e 1.1.1.1 -> WARNING
80+
4: -e 1.1.1.1 -e 3.3.3.3 -> WARNING
81+
5: -e 3.3.3.3 -> CRITICAL
82+
6: -e 3.3.3.3 -e 4.4.4.4 -e 5.5.5.5 -> CRITICAL
83+
**/
84+
if len(opts.ExpectedString) != 0 {
85+
supportedQueryType := map[string]int{"A": 1, "AAAA": 1}
86+
_, ok := supportedQueryType[strings.ToUpper(opts.QueryType)]
87+
if !ok {
88+
return checkers.Critical(fmt.Sprintf("%s is not supported query type. Only A, AAAA is supported for expectation.", opts.QueryType))
89+
}
90+
match := 0
91+
for _, expectedString := range opts.ExpectedString {
92+
for _, answer := range r.Answer {
93+
var anserWithoutHeader string
94+
expectMatch := expectedString
95+
switch t := answer.(type) {
96+
case *dns.A:
97+
anserWithoutHeader = t.A.String()
98+
case *dns.AAAA:
99+
anserWithoutHeader = t.AAAA.String()
100+
default:
101+
return checkers.Critical(fmt.Sprintf("%s is not supported query type. Only A, AAAA is supported for expectation.", opts.QueryType))
102+
}
103+
if anserWithoutHeader == expectMatch {
104+
match += 1
105+
}
106+
}
107+
}
108+
if match == len(r.Answer) {
109+
if len(opts.ExpectedString) == len(r.Answer) { // case 1
110+
checkSt = checkers.OK
111+
} else { // case 2
112+
checkSt = checkers.WARNING
113+
}
114+
} else {
115+
if match > 0 { // case 3,4
116+
checkSt = checkers.WARNING
117+
} else { // case 5,6
118+
checkSt = checkers.CRITICAL
119+
}
120+
}
121+
}
122+
79123
if r.MsgHdr.Rcode != dns.RcodeSuccess {
80124
checkSt = checkers.CRITICAL
81125
}
126+
82127
msg := fmt.Sprintf("HEADER-> %s\n", r.MsgHdr.String())
83128
for _, answer := range r.Answer {
84129
msg += fmt.Sprintf("ANSWER-> %s\n", answer)

check-dns/lib/check_dns_test.go

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,54 +29,79 @@ func TestCheckDns(t *testing.T) {
2929
want_msg []string
3030
}{
3131
{
32-
[]string{"-H", "example.com"},
32+
[]string{"-H", "a.root-servers.net"},
3333
checkers.OK,
3434
[]string{"status: NOERROR"},
3535
},
3636
{
37-
[]string{"-H", "example.com", "--norec"},
37+
[]string{"-H", "a.root-servers.net", "--norec"},
3838
checkers.OK,
3939
[]string{"status: NOERROR"},
4040
},
4141
{
42-
[]string{"-H", "exampleeeee.com"},
42+
[]string{"-H", "a.root-servers.invalid"},
4343
checkers.CRITICAL,
4444
[]string{"status: NXDOMAIN"},
4545
},
4646
{
47-
[]string{"-H", "example.com", "-s", "8.8.8.8"},
47+
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8"},
4848
checkers.OK,
4949
[]string{"status: NOERROR"},
5050
},
5151
{
52-
[]string{"-H", "exampleeeee.com", "-s", "8.8.8.8"},
52+
[]string{"-H", "a.root-servers.invalid", "-s", "8.8.8.8"},
5353
checkers.CRITICAL,
5454
[]string{"status: NXDOMAIN"},
5555
},
5656
{
57-
[]string{"-H", "example.com", "-s", "8.8.8"},
57+
[]string{"-H", "a.root-servers.net", "-s", "8.8.8"},
5858
checkers.CRITICAL,
5959
[]string{""},
6060
},
6161
{
62-
[]string{"-H", "example.com", "-s", "8.8.8.8", "-q", "AAAA"},
62+
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-q", "AAAA"},
6363
checkers.OK,
6464
[]string{"status: NOERROR", "AAAA"},
6565
},
6666
{
67-
[]string{"-H", "example.com", "-s", "8.8.8.8", "-q", "AAA"},
67+
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-q", "AAA"},
6868
checkers.CRITICAL,
69-
[]string{"AAA is invalid queryType"},
69+
[]string{"AAA is invalid query type"},
7070
},
7171
{
72-
[]string{"-H", "example.com", "-s", "8.8.8.8", "-c", "IN"},
72+
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-e", "198.41.0.4"},
7373
checkers.OK,
74-
[]string{"status: NOERROR"},
74+
[]string{"status: NOERROR", "198.41.0.4"},
75+
},
76+
{
77+
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-q", "AAAA", "--expected-string", "2001:503:ba3e::2:30"},
78+
checkers.OK,
79+
[]string{"status: NOERROR", "2001:503:ba3e::2:30"},
80+
},
81+
{
82+
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-q", "TXT", "-e", ""},
83+
checkers.CRITICAL,
84+
[]string{"is not supported query type. Only A, AAAA is supported for expectation."},
85+
},
86+
{
87+
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-e", "198.41.0.3"},
88+
checkers.CRITICAL,
89+
[]string{"status: NOERROR", "198.41.0.4"},
90+
},
91+
{
92+
[]string{"-H", "a.root-servers.invalid", "-s", "8.8.8.8", "-e", "198.41.0.4"},
93+
checkers.CRITICAL,
94+
[]string{"status: NXDOMAIN"},
95+
},
96+
{
97+
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-e", "198.41.0.3", "-e", "198.41.0.4"},
98+
checkers.WARNING,
99+
[]string{"status: NOERROR", "198.41.0.4"},
75100
},
76101
{
77-
[]string{"-H", "example.com", "-s", "8.8.8.8", "-c", "INN"},
102+
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-e", "198.41.0.3", "-e", " 198.41.0.4 "},
78103
checkers.CRITICAL,
79-
[]string{"INN is invalid queryClass"},
104+
[]string{"status: NOERROR", "198.41.0.4"},
80105
},
81106
}
82107

0 commit comments

Comments
 (0)