Skip to content

Commit

Permalink
Merge pull request #715 from wafuwafu13/dns-response
Browse files Browse the repository at this point in the history
check-dns: add `expected-string` option
  • Loading branch information
lufia authored Feb 22, 2023
2 parents 912e648 + c42f506 commit 7ce2ccb
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 46 deletions.
62 changes: 41 additions & 21 deletions check-dns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,45 @@

Monitor DNS response.

## Synopsis
## Usage

### Options

```
check-dns -H example.com -s 8.8.8.8
-H, --host= The name or address you want to query
-s, --server= DNS server you want to use for the lookup
-p, --port= Port number you want to use (default: 53)
-q, --querytype= DNS record query type (default: A)
--norec Set not recursive mode
-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
```

- query class is always IN.
- Punycode is not supported.

### Check DNS server status

If DNS server returns `NOERROR` in status of HEADER, then the checker result becomes `OK`, if not `NOERROR`, then `CRITICAL`

```
check-dns -H a.root-servers.net -s 8.8.8.8
```

### Check string DNS server returns

- The currently supported query types are A, AAAA.

If DNS server returns 1.1.1.1 and 2.2.2.2
```
-e 1.1.1.1 -e 2.2.2.2 -> OK
-e 1.1.1.1 -e 2.2.2.2 -e 3.3.3.3 -> WARNING
-e 1.1.1.1 -> WARNING
-e 1.1.1.1 -e 3.3.3.3 -> WARNING
-e 3.3.3.3 -> CRITICAL
-e 3.3.3.3 -e 4.4.4.4 -e 5.5.5.5 -> CRITICAL
```
```
check-dns -H a.root-servers.net -s 8.8.8.8 -e 198.41.0.4
```

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

```
check-dns -H example.com -s 8.8.8.8
check-dns -H a.root-servers.net -s 8.8.8.8
```


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

```
[plugin.checks.fileage-sample]
command = ["check-dns", "-H", "example.com", "-s", "8.8.8.8"]
```

## Usage
### Options

```
-H, --host= The name or address you want to query
-s, --server= DNS server you want to use for the lookup
-p, --port= Port number you want to use (default: 53)
-q, --querytype= DNS record query type where TYPE =(A, AAAA, SRV, TXT, MX, ANY) (default: A)
-c, --queryclass= DNS record class type where TYPE =(IN, CS, CH, HS, NONE, ANY) (default: IN)
--norec Set not recursive mode
[plugin.checks.dns-sample]
command = ["check-dns", "-H", "a.root-servers.net", "-s", "8.8.8.8"]
```

## For more information

Please execute `check-dns -h` and you can get command line options.
69 changes: 57 additions & 12 deletions check-dns/lib/check_dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import (
)

type dnsOpts struct {
Host string `short:"H" long:"host" required:"true" description:"The name or address you want to query"`
Server string `short:"s" long:"server" description:"DNS server you want to use for the lookup"`
Port int `short:"p" long:"port" default:"53" description:"Port number you want to use"`
QueryType string `short:"q" long:"querytype" default:"A" description:"DNS record query type where TYPE =(A, AAAA, SRV, TXT, MX, ANY)"`
QueryClass string `short:"c" long:"queryclass" default:"IN" description:"DNS record class type where TYPE =(IN, CS, CH, HS, NONE, ANY)"`
Norec bool `long:"norec" description:"Set not recursive mode"`
Host string `short:"H" long:"host" required:"true" description:"The name or address you want to query"`
Server string `short:"s" long:"server" description:"DNS server you want to use for the lookup"`
Port int `short:"p" long:"port" default:"53" description:"Port number you want to use"`
QueryType string `short:"q" long:"querytype" default:"A" description:"DNS record query type"`
Norec bool `long:"norec" description:"Set not recursive mode"`
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"`
}

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

queryType, ok := dns.StringToType[strings.ToUpper(opts.QueryType)]
if !ok {
return checkers.Critical(fmt.Sprintf("%s is invalid queryType", opts.QueryType))
}
queryClass, ok := dns.StringToClass[strings.ToUpper(opts.QueryClass)]
if !ok {
return checkers.Critical(fmt.Sprintf("%s is invalid queryClass", opts.QueryClass))
return checkers.Critical(fmt.Sprintf("%s is invalid query type", opts.QueryType))
}

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

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

checkSt := checkers.OK
/**
if DNS server return 1.1.1.1, 2.2.2.2
1: -e 1.1.1.1 -e 2.2.2.2 -> OK
2: -e 1.1.1.1 -e 2.2.2.2 -e 3.3.3.3 -> WARNING
3: -e 1.1.1.1 -> WARNING
4: -e 1.1.1.1 -e 3.3.3.3 -> WARNING
5: -e 3.3.3.3 -> CRITICAL
6: -e 3.3.3.3 -e 4.4.4.4 -e 5.5.5.5 -> CRITICAL
**/
if len(opts.ExpectedString) != 0 {
supportedQueryType := map[string]int{"A": 1, "AAAA": 1}
_, ok := supportedQueryType[strings.ToUpper(opts.QueryType)]
if !ok {
return checkers.Critical(fmt.Sprintf("%s is not supported query type. Only A, AAAA is supported for expectation.", opts.QueryType))
}
match := 0
for _, expectedString := range opts.ExpectedString {
for _, answer := range r.Answer {
var anserWithoutHeader string
expectMatch := expectedString
switch t := answer.(type) {
case *dns.A:
anserWithoutHeader = t.A.String()
case *dns.AAAA:
anserWithoutHeader = t.AAAA.String()
default:
return checkers.Critical(fmt.Sprintf("%s is not supported query type. Only A, AAAA is supported for expectation.", opts.QueryType))
}
if anserWithoutHeader == expectMatch {
match += 1
}
}
}
if match == len(r.Answer) {
if len(opts.ExpectedString) == len(r.Answer) { // case 1
checkSt = checkers.OK
} else { // case 2
checkSt = checkers.WARNING
}
} else {
if match > 0 { // case 3,4
checkSt = checkers.WARNING
} else { // case 5,6
checkSt = checkers.CRITICAL
}
}
}

if r.MsgHdr.Rcode != dns.RcodeSuccess {
checkSt = checkers.CRITICAL
}

msg := fmt.Sprintf("HEADER-> %s\n", r.MsgHdr.String())
for _, answer := range r.Answer {
msg += fmt.Sprintf("ANSWER-> %s\n", answer)
Expand Down
51 changes: 38 additions & 13 deletions check-dns/lib/check_dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,54 +29,79 @@ func TestCheckDns(t *testing.T) {
want_msg []string
}{
{
[]string{"-H", "example.com"},
[]string{"-H", "a.root-servers.net"},
checkers.OK,
[]string{"status: NOERROR"},
},
{
[]string{"-H", "example.com", "--norec"},
[]string{"-H", "a.root-servers.net", "--norec"},
checkers.OK,
[]string{"status: NOERROR"},
},
{
[]string{"-H", "exampleeeee.com"},
[]string{"-H", "a.root-servers.invalid"},
checkers.CRITICAL,
[]string{"status: NXDOMAIN"},
},
{
[]string{"-H", "example.com", "-s", "8.8.8.8"},
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8"},
checkers.OK,
[]string{"status: NOERROR"},
},
{
[]string{"-H", "exampleeeee.com", "-s", "8.8.8.8"},
[]string{"-H", "a.root-servers.invalid", "-s", "8.8.8.8"},
checkers.CRITICAL,
[]string{"status: NXDOMAIN"},
},
{
[]string{"-H", "example.com", "-s", "8.8.8"},
[]string{"-H", "a.root-servers.net", "-s", "8.8.8"},
checkers.CRITICAL,
[]string{""},
},
{
[]string{"-H", "example.com", "-s", "8.8.8.8", "-q", "AAAA"},
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-q", "AAAA"},
checkers.OK,
[]string{"status: NOERROR", "AAAA"},
},
{
[]string{"-H", "example.com", "-s", "8.8.8.8", "-q", "AAA"},
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-q", "AAA"},
checkers.CRITICAL,
[]string{"AAA is invalid queryType"},
[]string{"AAA is invalid query type"},
},
{
[]string{"-H", "example.com", "-s", "8.8.8.8", "-c", "IN"},
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-e", "198.41.0.4"},
checkers.OK,
[]string{"status: NOERROR"},
[]string{"status: NOERROR", "198.41.0.4"},
},
{
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-q", "AAAA", "--expected-string", "2001:503:ba3e::2:30"},
checkers.OK,
[]string{"status: NOERROR", "2001:503:ba3e::2:30"},
},
{
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-q", "TXT", "-e", ""},
checkers.CRITICAL,
[]string{"is not supported query type. Only A, AAAA is supported for expectation."},
},
{
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-e", "198.41.0.3"},
checkers.CRITICAL,
[]string{"status: NOERROR", "198.41.0.4"},
},
{
[]string{"-H", "a.root-servers.invalid", "-s", "8.8.8.8", "-e", "198.41.0.4"},
checkers.CRITICAL,
[]string{"status: NXDOMAIN"},
},
{
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-e", "198.41.0.3", "-e", "198.41.0.4"},
checkers.WARNING,
[]string{"status: NOERROR", "198.41.0.4"},
},
{
[]string{"-H", "example.com", "-s", "8.8.8.8", "-c", "INN"},
[]string{"-H", "a.root-servers.net", "-s", "8.8.8.8", "-e", "198.41.0.3", "-e", " 198.41.0.4 "},
checkers.CRITICAL,
[]string{"INN is invalid queryClass"},
[]string{"status: NOERROR", "198.41.0.4"},
},
}

Expand Down

0 comments on commit 7ce2ccb

Please sign in to comment.