From 58b514cd317adfa11f4efab6ccd749df98e6a280 Mon Sep 17 00:00:00 2001 From: ale <ale@incal.net> Date: Fri, 16 Apr 2021 23:52:27 +0100 Subject: [PATCH] Add a --test option to the tail command --- cmd/iprep/tail.go | 49 +++++++++++++++++++++++++++++++++-------------- example.patterns | 29 ++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 example.patterns diff --git a/cmd/iprep/tail.go b/cmd/iprep/tail.go index 27d615a..845ef93 100644 --- a/cmd/iprep/tail.go +++ b/cmd/iprep/tail.go @@ -9,6 +9,7 @@ import ( "log" "os" "regexp" + "strings" ippb "git.autistici.org/ai3/tools/iprep/proto" "git.autistici.org/ai3/tools/iprep/submission" @@ -16,6 +17,7 @@ import ( ) type tailCommand struct { + testOnly bool serverAddr string patternFile string } @@ -33,11 +35,21 @@ func parsePatterns(r io.Reader, filename string) ([]pattern, error) { var lineno int for scanner.Scan() { lineno++ - m := patternRx.FindSubmatch(scanner.Bytes()) - if len(m) < 1 { + line := scanner.Text() + if n := strings.Index(line, "#"); n >= 0 { + line = line[:n] + } + line = strings.TrimSpace(line) + if line == "" { continue } - rx, err := regexp.Compile(string(m[1])) + + m := patternRx.FindStringSubmatch(line) + if len(m) < 1 { + return nil, fmt.Errorf("syntax error, %s line %d: no pattern found", filename, lineno) + } + p := strings.Replace(string(m[1]), "\\/", "/", -1) + rx, err := regexp.Compile(p) if err != nil { return nil, fmt.Errorf("syntax error, %s line %d: %v", filename, lineno, err) } @@ -77,6 +89,7 @@ func (c *tailCommand) Usage() string { func (c *tailCommand) SetFlags(f *flag.FlagSet) { f.StringVar(&c.serverAddr, "server", "", "`address` (https://host:port) of the iprep server") f.StringVar(&c.patternFile, "patterns", "", "`file` with patterns to load") + f.BoolVar(&c.testOnly, "test", false, "only print matches, do not submit them") } func (c *tailCommand) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { @@ -112,24 +125,32 @@ func (c *tailCommand) run(ctx context.Context) error { return err } - sub, err := submission.New(c.serverAddr, nil) - if err != nil { - return err + var sub submission.Submitter + if !c.testOnly { + sub, err = submission.New(c.serverAddr, nil) + if err != nil { + return err + } + defer sub.Close() } - defer sub.Close() scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { + b := scanner.Bytes() for _, p := range patterns { - m := p.rx.FindSubmatch(scanner.Bytes()) - if len(m) < 1 { + m := p.rx.FindSubmatch(b) + if len(m) < 2 { continue } - sub.AddEvent(&ippb.Event{ - Ip: string(m[1]), - Type: p.eventType, - Count: 1, - }) + if c.testOnly { + fmt.Printf("ip=%s type=%s\n", string(m[1]), p.eventType) + } else { + sub.AddEvent(&ippb.Event{ + Ip: string(m[1]), + Type: p.eventType, + Count: 1, + }) + } } } diff --git a/example.patterns b/example.patterns new file mode 100644 index 0000000..f7ebffd --- /dev/null +++ b/example.patterns @@ -0,0 +1,29 @@ +# Example patterns. To be used with "journalctl --output=cat" (which +# only prints the log message, with no additional metadata). + +### SSH authentication failures + +# Silly brute-forcers that do not support our kex: +/^Unable to negotiate with ([.0-9]+) port \d+: no matching host key type found./ ssh + +### Email-related rules + +# Postscreen failures - protocol errors are (in high volume) characteristic of spammers +/^NOQUEUE: reject: RCPT from \[([.0-9]+)\]:\d+: 550 5.5.1 Protocol error;/ spammer + +# Spammers trying to send email via disabled accounts +/^NOQUEUE: reject: RCPT from [^[]+\[(.[0-9]+)\]: 553 5.7.1 <[^>]+>: Sender address rejected: not owned by user/ spammer + +# Spammers triggering SPF failures +/^550 5.7.23 Message rejected due to: SPF fail - not authorized. Please see http:\/\/www.openspf.net\/Why?s=mfrom;id=[^;]*;ip=([.0-9]+);/ spammer + +### Authentication + +# General auth-server errors +/^auth-server\[\d+\]: auth: user=.* service=smtp status=error ip=([.0-9]+) error=/ auth + +### Wordpress-specific rules + +/^.*nginx_access: .+ .+ (?:::ffff:)?([.:0-9a-f]+) .*"POST \/wp-login\.php HTTP/ wordpress +/^.*nginx_access: .+ .+ (?:::ffff:)?([.:0-9a-f]+) .*"POST \/wp-comments-post\.php HTTP/ wordpress + -- GitLab