Enhance failtoban plugin with log-only mode and SIGHUP cache reset (#519)
This commit is contained in:
parent
74ea60e0b0
commit
e95d30fdc8
1 changed files with 29 additions and 3 deletions
|
|
@ -5,6 +5,9 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
gocache "github.com/patrickmn/go-cache"
|
gocache "github.com/patrickmn/go-cache"
|
||||||
|
|
@ -17,7 +20,7 @@ func main() {
|
||||||
|
|
||||||
libplugin.CreateAndRunPluginTemplate(&libplugin.PluginTemplate{
|
libplugin.CreateAndRunPluginTemplate(&libplugin.PluginTemplate{
|
||||||
Name: "failtoban",
|
Name: "failtoban",
|
||||||
Usage: "sshpiperd fixed plugin, only password auth is supported",
|
Usage: "failtoban plugin, block ip after too many auth failures",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "max-failures",
|
Name: "max-failures",
|
||||||
|
|
@ -31,14 +34,33 @@ func main() {
|
||||||
EnvVars: []string{"SSHPIPERD_FAILTOBAN_BAN_DURATION"},
|
EnvVars: []string{"SSHPIPERD_FAILTOBAN_BAN_DURATION"},
|
||||||
Value: 60 * time.Minute,
|
Value: 60 * time.Minute,
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "log-only",
|
||||||
|
Usage: "log only mode, no ban, useful for working with other tools like fail2ban",
|
||||||
|
EnvVars: []string{"SSHPIPERD_FAILTOBAN_LOG_ONLY"},
|
||||||
|
Value: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
CreateConfig: func(c *cli.Context) (*libplugin.SshPiperPluginConfig, error) {
|
CreateConfig: func(c *cli.Context) (*libplugin.SshPiperPluginConfig, error) {
|
||||||
|
|
||||||
maxFailures := c.Int("max-failures")
|
maxFailures := c.Int("max-failures")
|
||||||
banDuration := c.Duration("ban-duration")
|
banDuration := c.Duration("ban-duration")
|
||||||
|
logOnly := c.Bool("log-only")
|
||||||
|
|
||||||
cache := gocache.New(banDuration, banDuration/2*3)
|
cache := gocache.New(banDuration, banDuration/2*3)
|
||||||
|
|
||||||
|
// register signal handler
|
||||||
|
go func() {
|
||||||
|
sigChan := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigChan, syscall.SIGHUP)
|
||||||
|
|
||||||
|
for {
|
||||||
|
<-sigChan
|
||||||
|
cache.Flush()
|
||||||
|
log.Info("failtoban: cache reset due to SIGHUP")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
return &libplugin.SshPiperPluginConfig{
|
return &libplugin.SshPiperPluginConfig{
|
||||||
NoClientAuthCallback: func(conn libplugin.ConnMetadata) (*libplugin.Upstream, error) {
|
NoClientAuthCallback: func(conn libplugin.ConnMetadata) (*libplugin.Upstream, error) {
|
||||||
// in case someone put the failtoban plugin before other plugins
|
// in case someone put the failtoban plugin before other plugins
|
||||||
|
|
@ -47,6 +69,10 @@ func main() {
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
NewConnectionCallback: func(conn libplugin.ConnMetadata) error {
|
NewConnectionCallback: func(conn libplugin.ConnMetadata) error {
|
||||||
|
if logOnly {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
ip, _, _ := net.SplitHostPort(conn.RemoteAddr())
|
ip, _, _ := net.SplitHostPort(conn.RemoteAddr())
|
||||||
|
|
||||||
failed, found := cache.Get(ip)
|
failed, found := cache.Get(ip)
|
||||||
|
|
@ -64,12 +90,12 @@ func main() {
|
||||||
UpstreamAuthFailureCallback: func(conn libplugin.ConnMetadata, method string, err error, allowmethods []string) {
|
UpstreamAuthFailureCallback: func(conn libplugin.ConnMetadata, method string, err error, allowmethods []string) {
|
||||||
ip, _, _ := net.SplitHostPort(conn.RemoteAddr())
|
ip, _, _ := net.SplitHostPort(conn.RemoteAddr())
|
||||||
failed, _ := cache.IncrementInt(ip, 1)
|
failed, _ := cache.IncrementInt(ip, 1)
|
||||||
log.Debugf("failtoban: %v auth failed. current status: fail %v times, max allowed %v", ip, failed, maxFailures)
|
log.Warnf("failtoban: %v auth failed. current status: fail %v times, max allowed %v", ip, failed, maxFailures)
|
||||||
},
|
},
|
||||||
PipeCreateErrorCallback: func(remoteAddr string, err error) {
|
PipeCreateErrorCallback: func(remoteAddr string, err error) {
|
||||||
ip, _, _ := net.SplitHostPort(remoteAddr)
|
ip, _, _ := net.SplitHostPort(remoteAddr)
|
||||||
failed, _ := cache.IncrementInt(ip, 1)
|
failed, _ := cache.IncrementInt(ip, 1)
|
||||||
log.Debugf("failtoban: %v pipe create failed, reason %v. current status: fail %v times, max allowed %v", ip, err, failed, maxFailures)
|
log.Warnf("failtoban: %v pipe create failed, reason %v. current status: fail %v times, max allowed %v", ip, err, failed, maxFailures)
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue