init
This commit is contained in:
commit
ceefc45622
27
license
Normal file
27
license
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2015, stephen mcquay
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of authpixious nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
129
main.go
Normal file
129
main.go
Normal file
@ -0,0 +1,129 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var max = flag.Int64("max", 5, "limit output, if negative print all")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
// Failed password for root from 43.229.53.57 port 62954 ssh2
|
||||
// message repeated 2 times: [ Failed password for root from 43.229.53.57 port 32871 ssh2]
|
||||
p, err := regexp.Compile(`(message repeated (\d+) times: \[)? Failed password for (invalid user )?(.*?) from (.*) port`)
|
||||
if err != nil {
|
||||
fail("failed to compile regex", err)
|
||||
}
|
||||
|
||||
unames := counter{}
|
||||
ips := counter{}
|
||||
|
||||
s := bufio.NewScanner(os.Stdin)
|
||||
for s.Scan() {
|
||||
if m := p.FindSubmatch(s.Bytes()); m == nil {
|
||||
continue
|
||||
} else {
|
||||
if len(m) != 6 {
|
||||
fail("failure to capture correct number of tokens", nil)
|
||||
}
|
||||
|
||||
multstr := string(m[2])
|
||||
uname, ip := m[4], m[5]
|
||||
|
||||
multiplier := 1
|
||||
if multstr != "" {
|
||||
i, err := strconv.Atoi(multstr)
|
||||
if err != nil {
|
||||
fail("problem parsing int", err)
|
||||
}
|
||||
multiplier = i
|
||||
}
|
||||
|
||||
unames[string(uname)] += multiplier
|
||||
ips[string(ip)] += multiplier
|
||||
}
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fail("failure reading from stdin", err)
|
||||
}
|
||||
|
||||
display(unames, ips)
|
||||
}
|
||||
|
||||
// fail constructs an error message, sends to stderr, and exists 1
|
||||
func fail(msg string, err error) {
|
||||
fmt.Fprintf(os.Stderr, "%s; %v\n", msg, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
type counter map[string]int
|
||||
|
||||
// top sorts the map by value and returns max pairs, unless max is negative in
|
||||
// which case it returns all pairs
|
||||
func top(m counter, max int64) pairList {
|
||||
p := make(pairList, len(m))
|
||||
i := 0
|
||||
for k, v := range m {
|
||||
p[i] = pair{k, v}
|
||||
i++
|
||||
}
|
||||
sort.Sort(p)
|
||||
|
||||
if max < 0 {
|
||||
return p
|
||||
}
|
||||
if int64(len(p)) > max {
|
||||
p = p[:max]
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// How I sort a counter by value
|
||||
type pair struct {
|
||||
key string
|
||||
value int
|
||||
}
|
||||
|
||||
type pairList []pair
|
||||
|
||||
func (p pairList) Swap(i, j int) {
|
||||
p[i], p[j] = p[j], p[i]
|
||||
}
|
||||
|
||||
func (p pairList) Len() int {
|
||||
return len(p)
|
||||
}
|
||||
|
||||
// Less sorts in descending order
|
||||
func (p pairList) Less(i, j int) bool {
|
||||
return p[i].value > p[j].value
|
||||
}
|
||||
|
||||
func display(unames, ips map[string]int) {
|
||||
var title string
|
||||
title = fmt.Sprintf("%-20s %s", "unames", "count")
|
||||
fmt.Printf("%s\n", title)
|
||||
for _ = range title {
|
||||
fmt.Print("-")
|
||||
}
|
||||
fmt.Println()
|
||||
for _, v := range top(unames, *max) {
|
||||
fmt.Printf("%-20s %d\n", v.key, v.value)
|
||||
}
|
||||
title = fmt.Sprintf("%-20s %s", "ips", "count")
|
||||
fmt.Printf("\n%s\n", title)
|
||||
for _ = range title {
|
||||
fmt.Print("-")
|
||||
}
|
||||
fmt.Println()
|
||||
for _, v := range top(ips, *max) {
|
||||
fmt.Printf("%-20s %d\n", v.key, v.value)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user