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