Skip to content

Commit

Permalink
add JSON output
Browse files Browse the repository at this point in the history
  • Loading branch information
Jozef Reisinger committed Oct 31, 2021
1 parent fd6160b commit 608d075
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 74 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
install:
go install cmd/checkip.go

demo: install
run: install
checkip 140.82.114.4
checkip 218.92.0.158
checkip 92.118.160.17
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ or [SecChecker](https://pkg.go.dev/github.com/jreisinger/checkip#SecChecker)
interface and add it to `cmd/checkip.go`. Then:

```
make demo # see the picture above
make run # see the picture above
```

## Releasing
Expand Down
5 changes: 2 additions & 3 deletions abuseipdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ func (a *AbuseIPDB) Check(ipaddr net.IP) error {
return nil
}

// IsOK returns true if the IP address is not considered suspicious.
func (a *AbuseIPDB) IsOK() bool {
return a.Data.TotalReports == 0 || a.Data.IsWhitelisted || a.Data.AbuseConfidenceScore <= 25
func (a *AbuseIPDB) IsMalicious() bool {
return a.Data.TotalReports > 0 && !a.Data.IsWhitelisted && a.Data.AbuseConfidenceScore > 25
}
82 changes: 80 additions & 2 deletions checkip.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
package checkip

import (
"encoding/json"
"fmt"
"net"
"os"
"regexp"
"sync"

"github.com/logrusorgru/aurora"
)

// Checker runs a check of an IP address.
Expand All @@ -16,8 +23,79 @@ type InfoChecker interface {
Checker
}

// SecChecker checks an IP address is ok from the security point of view.
// SecChecker checks an IP address from the security point of view.
type SecChecker interface {
IsOK() bool
IsMalicious() bool
Checker
}

// Run runs checkers concurrently checking the ipaddr.
func Run(checkers []Checker, ipaddr net.IP) Result {
var res Result

var wg sync.WaitGroup
for _, c := range checkers {
wg.Add(1)
go func(c Checker) {
defer wg.Done()
if err := c.Check(ipaddr); err != nil {
res.Errors = append(res.Errors, redactSecrets(err.Error()))
}
}(c)
}
wg.Wait()

var total, malicious int
for _, c := range checkers {
switch ip := c.(type) {
case InfoChecker:
res.Infos = append(res.Infos, ip.Info())
case SecChecker:
total++
if ip.IsMalicious() {
malicious++
}
}

}
res.ProbabilityMalicious = float64(malicious) / float64(total)

return res
}

func redactSecrets(s string) string {
key := regexp.MustCompile(`(key|pass|password)=\w+`)
return key.ReplaceAllString(s, "${1}=REDACTED")
}

// Result holds the result of running a check.
type Result struct {
Infos []string
ProbabilityMalicious float64
Errors []string
}

func (res Result) Print() error {
for _, i := range res.Infos {
fmt.Println(i)
}

var msg string

switch {
case res.ProbabilityMalicious < 0.15:
msg = fmt.Sprint(aurora.Green("Malicious"))
case res.ProbabilityMalicious < 0.50:
msg = fmt.Sprint(aurora.Yellow("Malicious"))
default:
msg = fmt.Sprint(aurora.Red("Malicious"))
}

_, err := fmt.Printf("%s\t%.0f%%\n", msg, res.ProbabilityMalicious*100)
return err
}

func (res Result) PrintJSON() error {
enc := json.NewEncoder(os.Stdout)
return enc.Encode(&res)
}
Binary file modified checkip.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 2 additions & 3 deletions cins.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ func (c *CINSArmy) Check(ipaddr net.IP) error {
return nil
}

// IsOK returns true if the IP address is not considered suspicious.
func (c *CINSArmy) IsOK() bool {
return !c.BadGuyIP
func (c *CINSArmy) IsMalicious() bool {
return c.BadGuyIP
}

// search searches the ippadrr in filename fills in ET data.
Expand Down
64 changes: 15 additions & 49 deletions cmd/checkip.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,30 @@ package main

import (
"flag"
"fmt"
"log"
"net"
"os"
"regexp"
"sync"

"github.com/jreisinger/checkip"
"github.com/logrusorgru/aurora"
)

func init() {
log.SetFlags(0)
log.SetPrefix(os.Args[0] + ": ")
}

var j = flag.Bool("j", false, "output JSON")

func main() {
if len(os.Args[1:]) != 1 {
fmt.Printf("Usage: %s <ipaddr>\n", os.Args[0])
os.Exit(1)
flag.Parse()

if len(flag.Args()) != 1 {
log.Fatal("missing IP address")
}

ipaddr := net.ParseIP(os.Args[1])
ipaddr := net.ParseIP(flag.Arg(0))
if ipaddr == nil {
fmt.Fprintf(os.Stderr, "%s: wrong IP address: %s\n", os.Args[0], flag.Arg(0))
os.Exit(1)
log.Fatalf("wrong IP address: %s\n", flag.Arg(0))
}

checkers := []checkip.Checker{
Expand All @@ -46,45 +44,13 @@ func main() {
&checkip.VirusTotal{},
}

var wg sync.WaitGroup
for _, c := range checkers {
wg.Add(1)
go func(c checkip.Checker) {
defer wg.Done()
if err := c.Check(ipaddr); err != nil {
log.Print(redactSecrets(err.Error()))
}
}(c)
}
wg.Wait()

var total, malicious int
for _, c := range checkers {
switch ip := c.(type) {
case checkip.InfoChecker:
fmt.Println(ip.Info())
case checkip.SecChecker:
total++
if !ip.IsOK() {
malicious++
}
results := checkip.Run(checkers, ipaddr)
if *j {
results.PrintJSON()
} else {
for _, e := range results.Errors {
log.Println(e)
}

}
perc := float64(malicious) / float64(total) * 100
var msg string
switch {
case perc < 15:
msg = fmt.Sprint(aurora.Green("Malicious"))
case perc < 50:
msg = fmt.Sprint(aurora.Yellow("Malicious"))
default:
msg = fmt.Sprint(aurora.Red("Malicious"))
results.Print()
}
fmt.Printf("%s\t%.0f%% (%d out of %d checkers)\n", msg, perc, malicious, total)
}

func redactSecrets(s string) string {
key := regexp.MustCompile(`(key|pass|password)=\w+`)
return key.ReplaceAllString(s, "${1}=REDACTED")
}
5 changes: 2 additions & 3 deletions et.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ func (e *ET) Check(ipaddr net.IP) error {
return nil
}

// IsOK returns true if the IP address is not considered suspicious.
func (e *ET) IsOK() bool {
return !e.CompromisedIP
func (e *ET) IsMalicious() bool {
return e.CompromisedIP
}

// search searches the ippadrr in filename fills in ET data.
Expand Down
5 changes: 2 additions & 3 deletions ipsum.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ func (ip *IPsum) Check(ipaddr net.IP) error {
return nil
}

// IsOK returns true if the IP address is not considered suspicious.
func (ip *IPsum) IsOK() bool {
return ip.NumOfBlacklists == 0
func (ip *IPsum) IsMalicious() bool {
return ip.NumOfBlacklists > 0
}

// search searches the ippadrr in tsvFile and if found fills in IPsum data.
Expand Down
5 changes: 2 additions & 3 deletions otx.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ func (otx *OTX) Check(ipaddr net.IP) error {
return nil
}

// IsOK returns true if the IP address is not considered suspicious.
func (otx *OTX) IsOK() bool {
return otx.PulseInfo.Count <= 10
func (otx *OTX) IsMalicious() bool {
return otx.PulseInfo.Count > 10
}
5 changes: 2 additions & 3 deletions threatcrowd.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ func (t *ThreatCrowd) Check(ipaddr net.IP) error {
return nil
}

// IsOK returns true if the IP address is not considered suspicious.
func (t *ThreatCrowd) IsOK() bool {
func (t *ThreatCrowd) IsMalicious() bool {
// https://github.com/AlienVault-OTX/ApiV2#votes
// -1 voted malicious by most users
// 0 voted malicious/harmless by equal number of users
// 1: voted harmless by most users
return t.Votes >= 0
return t.Votes < 0
}
5 changes: 2 additions & 3 deletions virustotal.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ func (vt *VirusTotal) Check(ipaddr net.IP) error {
return nil
}

// IsOK returns true if the IP address is not considered suspicious.
func (vt *VirusTotal) IsOK() bool {
func (vt *VirusTotal) IsMalicious() bool {
// https://developers.virustotal.com/reference#ip-object
return vt.Data.Attributes.Reputation >= 0
return vt.Data.Attributes.Reputation < 0
}

0 comments on commit 608d075

Please sign in to comment.