first version

This commit is contained in:
2021-08-01 00:03:25 +03:00
parent 231ca061ac
commit 5e38debcfd
13 changed files with 854 additions and 0 deletions

67
cmd/kf2-antiddos/args.go Normal file
View File

@ -0,0 +1,67 @@
package main
import (
"github.com/juju/gnuflag"
"kf2-antiddos/internal/config"
"kf2-antiddos/internal/output"
)
func printHelp() {
output.Println("Anti DDoS tool for kf2 servers")
output.Println("")
output.Printf("Usage: <kf2_logs_output> | %s [option]... <shell> <deny_script> <allow_script>", AppName)
output.Println("kf2_logs_output KF2 logs to redirect to stdin")
output.Println("shell shell to run deny_script and allow_script")
output.Println("deny_script firewall deny script (takes IP as argument)")
output.Println("allow_script firewall allow script (takes IPs as arguments)")
output.Println("")
output.Println("Options:")
output.Println(" -j, --jobs N allow N jobs at once")
output.Println(" -o, --output MODE self|proxy|all|quiet")
output.Println(" -dt, --deny-time TIME minimum ip deny TIME (seconds)")
output.Println(" -mc, --max-connections N Skip N connections before run deny script")
output.Println(" -v, --version Show version")
output.Println(" -h, --help Show help")
}
func printVersion() {
output.Printf("%s %s", AppName, AppVersion)
}
func parseArgs() config.Config {
rawCfg := config.Config{}
gnuflag.UintVar(&rawCfg.Jobs, "j", 0, "")
gnuflag.UintVar(&rawCfg.Jobs, "jobs", 0, "")
gnuflag.StringVar(&rawCfg.OutputMode, "o", "", "")
gnuflag.StringVar(&rawCfg.OutputMode, "output", "", "")
gnuflag.UintVar(&rawCfg.DenyTime, "dt", 0, "")
gnuflag.UintVar(&rawCfg.DenyTime, "deny-time", 0, "")
gnuflag.UintVar(&rawCfg.MaxConn, "mc", 0, "")
gnuflag.UintVar(&rawCfg.MaxConn, "max-connections", 0, "")
gnuflag.BoolVar(&rawCfg.ShowVersion, "v", false, "")
gnuflag.BoolVar(&rawCfg.ShowVersion, "version", false, "")
gnuflag.BoolVar(&rawCfg.ShowHelp, "h", false, "")
gnuflag.BoolVar(&rawCfg.ShowHelp, "help", false, "")
gnuflag.Parse(true)
for i := 0; i < 3 && i < gnuflag.NArg(); i++ {
switch i {
case 0:
rawCfg.Shell = gnuflag.Arg(i)
case 1:
rawCfg.DenyAction = gnuflag.Arg(i)
case 2:
rawCfg.AllowAction = gnuflag.Arg(i)
}
}
return rawCfg
}

140
cmd/kf2-antiddos/main.go Normal file
View File

@ -0,0 +1,140 @@
package main
import (
"kf2-antiddos/internal/action"
"kf2-antiddos/internal/common"
"kf2-antiddos/internal/config"
"kf2-antiddos/internal/history"
"kf2-antiddos/internal/output"
"kf2-antiddos/internal/parser"
"kf2-antiddos/internal/reader"
"os"
"os/signal"
"runtime"
"sync"
"syscall"
)
const (
ExitSuccess int = 0
ExitArgError int = 1
)
const (
AppName = "kf2-antiddos"
)
var (
AppVersion string = "dev"
)
func main() {
cfg := parseArgs()
switch {
case cfg.ShowHelp:
printHelp()
os.Exit(ExitSuccess)
case cfg.ShowVersion:
printVersion()
os.Exit(ExitSuccess)
}
if cfg.IsValid() {
cfg.SetEmptyArgs()
} else {
os.Exit(ExitArgError)
}
switch cfg.OutputMode {
case config.OT_All:
output.AllMode()
case config.OT_Proxy:
output.ProxyMode()
case config.OT_Quiet:
output.QuietMode()
case config.OT_Self:
output.SelfMode()
}
runtime.GOMAXPROCS(int(cfg.Jobs))
Workers := make([]common.Worker, 0, cfg.Jobs+3)
wg := sync.WaitGroup{}
// Data flow:
banChan := make(chan string, cfg.Jobs)
inputChan := make(chan common.RawEvent, cfg.Jobs)
eventChan := make(chan common.Event, cfg.Jobs)
resetChan := make(chan string, cfg.Jobs)
// Reader worker
Workers = append(Workers,
reader.New(
uint(len(Workers)),
&inputChan,
))
// parser workers
for i := uint(0); i < cfg.Jobs; i++ {
Workers = append(Workers,
parser.New(
uint(len(Workers)),
&inputChan,
&eventChan,
))
}
// History worker
Workers = append(Workers,
history.New(
uint(len(Workers)),
&eventChan,
&banChan,
&resetChan,
cfg.MaxConn,
))
// Action worker
Workers = append(Workers,
action.New(
uint(len(Workers)),
cfg.DenyTime,
cfg.Shell,
cfg.AllowAction,
cfg.DenyAction,
&banChan,
&resetChan,
))
wg.Add(len(Workers))
closeHandler(Workers, &wg)
for i := range Workers {
Workers[i].Do()
}
output.Println("started")
wg.Wait()
output.Println("exit")
os.Exit(ExitSuccess)
}
func closeHandler(Workers []common.Worker, wg *sync.WaitGroup) {
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
go func() {
<-interrupt
output.Println("interrupt")
for _, worker := range Workers {
worker.Stop()
wg.Done()
}
}()
}