{"id":13413767,"url":"https://github.com/jaredfolkins/badactor","last_synced_at":"2026-04-09T04:03:18.410Z","repository":{"id":24529846,"uuid":"27936107","full_name":"jaredfolkins/badactor","owner":"jaredfolkins","description":"BadActor.org An in-memory application driven jailer written in Go","archived":false,"fork":false,"pushed_at":"2020-05-28T22:21:02.000Z","size":92,"stargazers_count":322,"open_issues_count":1,"forks_count":17,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-07-31T20:52:50.628Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://badactor.org","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jaredfolkins.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-12T20:05:20.000Z","updated_at":"2024-07-17T15:52:10.000Z","dependencies_parsed_at":"2022-08-28T11:51:11.585Z","dependency_job_id":null,"html_url":"https://github.com/jaredfolkins/badactor","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredfolkins%2Fbadactor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredfolkins%2Fbadactor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredfolkins%2Fbadactor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredfolkins%2Fbadactor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jaredfolkins","download_url":"https://codeload.github.com/jaredfolkins/badactor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243635898,"owners_count":20323014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T20:01:48.671Z","updated_at":"2025-12-17T06:23:29.476Z","avatar_url":"https://github.com/jaredfolkins.png","language":"Go","readme":"![badactor logo](https://raw.githubusercontent.com/jaredfolkins/badactor_logo/master/badactor_logo_300x300.png) [![Coverage Status](https://img.shields.io/coveralls/jaredfolkins/badactor.svg)](https://coveralls.io/r/jaredfolkins/badactor?branch=master) [![Documentation](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://godoc.org/github.com/jaredfolkins/badactor)\n\n# BadActor \n\nBadActor is an in-memory, application driven jailer built in the spirit of fail2ban. A middleware with the primary goal to increase the expense for \"bad actors\" who engage in system probing or attacks.\n\n\u003csup\u003e\u003csup\u003eThe BadActor logo is based on [Renee French's](http://reneefrench.blogspot.com) wonderful gopher. Thanks Renee!\u003c/sup\u003e\u003c/sup\u003e\n# Install\n\n```bash\n$ go get github.com/jaredfolkins/badactor\n```\n\n# Use Case\n\nA common use case for BadActor is jailing an offender who fails to login to your website (N) times as this can signal a bruteforce attempt.\n\n# Tutorial\n\nCheckout [badactor.org](http://badactor.org) for a tutorial.\n\n\n# Design\n\n- speed (subsecond response underload and submillisecond with standard operations)\n- no external dependencies \n- solid code coverage and thorough tests\n\n# Does It Scale? \n\nBadActor can be included in your go application and ran concurrently. This allows you an easy way to scale up as BadActor's memory footprint is tiny. Because it leverages a light-weight cache with sharding and reaping, it allows most organizations to be confident that BadActor will not be a bottleneck. \n\n# Benchmarks \n\n| Type    |  Value   |\n| --- | --- |\n| **Model Name** | MacBook Pro |\n| **Model Identifier** | MacBookPro11,3 |\n| **Processor Name** | Intel Core i7 | \n| **Processor Speed** | 2.3 GHz | \n| **Number of Processors** | 1 |\n| **Total Number of Cores** | 4 |\n| **L2 Cache (per Core)** | 256 KB | \n| **L3 Cache** | 6 MB | \n| **Memory** | 16 GB |\n\n###### 1.8.2015\n\n```bash\n➜  badactor git:(master) ✗ go test -bench=. -cpu=4 -benchmem -benchtime=5s | column -t\nPASS\nBenchmarkIsJailed-4                50000000                          121       ns/op  0    B/op  0  allocs/op\nBenchmarkIsJailedFor-4             50000000                          134       ns/op  0    B/op  0  allocs/op\nBenchmarkInfraction-4              5000000                           1390      ns/op  528  B/op  7  allocs/op\nBenchmarkInfractionlIsJailed-4     3000000                           2755      ns/op  800  B/op  9  allocs/op\nBenchmarkInfractionlIsJailedFor-4  3000000                           2733      ns/op  800  B/op  9  allocs/op\nBenchmarkStudioInfraction512-4     3000000                           2215      ns/op  591  B/op  9  allocs/op\nBenchmarkStudioInfraction1024-4    3000000                           2357      ns/op  612  B/op  9  allocs/op\nBenchmarkStudioInfraction2048-4    5000000                           2617      ns/op  621  B/op  9  allocs/op\nBenchmarkStudioInfraction4096-4    5000000                           2566      ns/op  671  B/op  9  allocs/op\nBenchmarkStudioInfraction65536-4   3000000                           3309      ns/op  667  B/op  9  allocs/op\nBenchmarkStudioInfraction262144-4  2000000                           3644      ns/op  674  B/op  9  allocs/op\nok                                 github.com/jaredfolkins/badactor  178.239s\n➜  badactor git:(master) ✗\n```\n\n###### 12.30.2014\n\n```bash\n➜  badactor git:(master) ✗ go test -benchtime=5s -bench=. -benchmem -cpu=4 | column -t\nPASS\nBenchmarkIsJailed-4                  50000000                          133        ns/op  0          B/op  0        allocs/op\nBenchmarkIsJailedFor-4               50000000                          136        ns/op  0          B/op  0        allocs/op\nBenchmarkInfraction-4                10000000                          824        ns/op  116        B/op  5        allocs/op\nBenchmarkInfractionMostCostly-4      10000000                          891        ns/op  116        B/op  5        allocs/op\nBenchmarkInfractionIsJailed-4        3000000                           2569       ns/op  340        B/op  13       allocs/op\nBenchmarkInfractionIsJailedFor-4     3000000                           2611       ns/op  340        B/op  13       allocs/op\nBenchmark10000Actors1Infraction-4    1000                              8571335    ns/op  1162931    B/op  50023    allocs/op\nBenchmark100000Actors1Infraction-4   100                               87687224   ns/op  11630938   B/op  500248   allocs/op\nBenchmark1000000Actors1Infraction-4  10                                841989544  ns/op  116292788  B/op  5002740  allocs/op\nBenchmark10000Actors4Infractions-4   200                               30728688   ns/op  4522659    B/op  170013   allocs/op\nok                                   github.com/jaredfolkins/badactor  93.868s\n➜  badactor git:(master) ✗\n\n```\n\n###### 12.24.2014\n\n```bash\n➜  badactor git:(master) ✗ go test -bench=. -benchtime=5s -benchmem | column -t\nPASS\nBenchmarkIsJailed                 50000000                          138        ns/op  0         B/op  0       allocs/op\nBenchmarkIsJailedFor              50000000                          140        ns/op  0         B/op  0       allocs/op\nBenchmarkInfraction               10000000                          943        ns/op  128       B/op  4       allocs/op\nBenchmarkInfractionMostCostly     10000000                          1008       ns/op  128       B/op  4       allocs/op\nBenchmark10000Actors              100                               140566388  ns/op  13150354  B/op  150598  allocs/op\nBenchmark10000Actors4Infractions  50                                241030802  ns/op  17278074  B/op  210614  allocs/op\nok                                github.com/jaredfolkins/badactor  73.592s\n➜  badactor git:(master) ✗\n\n```\n\n###### 12.16.2014\n\nThis was **before** a serious refactoring. I am keeping it here because **(a)** I'd like to encourage others to *benchmark* their code and **(b)** I learned many valuable lessons while doing it. \n \n```bash\n➜  badactor git:(master) go test -bench=. -benchtime=5s -benchmem | column -t\nPASS\nBenchmarkInfraction1                  2000                              2679694   ns/op  518  B/op  10  allocs/op\nBenchmarkInfraction10                 2000                              3050845   ns/op  516  B/op  10  allocs/op\nBenchmarkInfraction100                2000                              3430051   ns/op  516  B/op  10  allocs/op\nBenchmarkInfraction1000               2000                              3738125   ns/op  516  B/op  10  allocs/op\nBenchmarkInfraction10000              2000                              4004534   ns/op  516  B/op  10  allocs/op\nBenchmarkInfractionWithIsJailed1      3000                              1832770   ns/op  193  B/op  3   allocs/op\nBenchmarkInfractionWithIsJailed10     3000                              1968030   ns/op  193  B/op  3   allocs/op\nBenchmarkInfractionWithIsJailed100    3000                              2120179   ns/op  193  B/op  3   allocs/op\nBenchmarkInfractionWithIsJailed1000   3000                              1955656   ns/op  193  B/op  3   allocs/op\nBenchmarkInfractionWithIsJailed10000  3000                              1943728   ns/op  193  B/op  3   allocs/op\nok                                    github.com/jaredfolkins/badactor  109.879s\n➜  badactor git:(master)\n```\n\n# Action Interface\n\nThe Action Interface has two primary methods, **WhenJailed** and **WhenTimeServed**. An excerpt of an implementation is below. They are called when the actor is jailed for the rule or when the actor has served its time for a particular rule.\n\n\n```go\ntype MyAction struct{}\n\nfunc (ma *MyAction) WhenJailed(a *badactor.Actor, r *badactor.Rule) error {\n  // Do something here. Log, email, etc...\n\treturn nil\n}\n\nfunc (ma *MyAction) WhenTimeServed(a *badactor.Actor, r *badactor.Rule) error {\n  // Do something here. Log, email, etc...\n\treturn nil\n}\n```\n\nAnd assigned to the rule like so.\n\n```go\n// define and add the rule to the stack\nru := \u0026badactor.Rule{\n  Name:        \"Login\",\n  Message:     \"You have failed to login too many times\",\n  StrikeLimit: 10,\n  ExpireBase:  time.Second * 1,\n  Sentence:    time.Second * 10,\n  Action:      \u0026MyAction{},\n}\nst.AddRule(ru)\n```\n\n# Httprouter \u0026 Negroni Example\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/urfave/negroni\"\n\t\"github.com/jaredfolkins/badactor\"\n\t\"github.com/julienschmidt/httprouter\"\n)\n\nvar st *badactor.Studio\n\ntype MyAction struct{}\n\nfunc (ma *MyAction) WhenJailed(a *badactor.Actor, r *badactor.Rule) error {\n\treturn nil\n}\n\nfunc (ma *MyAction) WhenTimeServed(a *badactor.Actor, r *badactor.Rule) error {\n\treturn nil\n}\n\nfunc main() {\n\n\t//runtime.GOMAXPROCS(4)\n\n\t// studio capacity\n\tvar sc int32\n\t// director capacity\n\tvar dc int32\n\n\tsc = 1024\n\tdc = 1024\n\n\t// init new Studio\n\tst = badactor.NewStudio(sc)\n\n\t// define and add the rule to the stack\n\tru := \u0026badactor.Rule{\n\t\tName:        \"Login\",\n\t\tMessage:     \"You have failed to login too many times\",\n\t\tStrikeLimit: 10,\n\t\tExpireBase:  time.Second * 1,\n\t\tSentence:    time.Second * 10,\n\t\tAction:      \u0026MyAction{},\n\t}\n\tst.AddRule(ru)\n\n\terr := st.CreateDirectors(dc)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t//poll duration\n\tdur := time.Minute * time.Duration(60)\n\t// Start the reaper\n\tst.StartReaper(dur)\n\n\t// router\n\trouter := httprouter.New()\n\trouter.POST(\"/login\", LoginHandler)\n\n\t// middleware\n\tn := negroni.Classic()\n\tn.Use(NewBadActorMiddleware())\n\tn.UseHandler(router)\n\tn.Run(\":9999\")\n\n}\n\n//\n// HANDLER\n//\n\n// this is a niave login function for example purposes\nfunc LoginHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {\n\n\tvar err error\n\n\tun := r.FormValue(\"username\")\n\tpw := r.FormValue(\"password\")\n\n\t// snag the IP for use as the actor's name\n\tan, _, err := net.SplitHostPort(r.RemoteAddr)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// mock authentication\n\tif un == \"example_user\" \u0026\u0026 pw == \"example_pass\" {\n\t\thttp.Redirect(w, r, \"\", http.StatusOK)\n\t\treturn\n\t}\n\n\t// auth fails, increment infraction\n\terr = st.Infraction(an, \"Login\")\n\tif err != nil {\n\t\tlog.Printf(\"[%v] has err %v\", an, err)\n\t}\n\n\t// auth fails, increment infraction\n\ti, err := st.Strikes(an, \"Login\")\n\tlog.Printf(\"[%v] has %v Strikes %v\", an, i, err)\n\n\thttp.Redirect(w, r, \"\", http.StatusUnauthorized)\n\treturn\n}\n\n//\n// MIDDLEWARE\n//\ntype BadActorMiddleware struct {\n\tnegroni.Handler\n}\n\nfunc NewBadActorMiddleware() *BadActorMiddleware {\n\treturn \u0026BadActorMiddleware{}\n}\n\nfunc (bam *BadActorMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\n\n\t// snag the IP for use as the actor's name\n\tan, _, err := net.SplitHostPort(r.RemoteAddr)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// if the Actor is jailed, send them StatusUnauthorized\n\tif st.IsJailed(an) {\n\t\thttp.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)\n\t\treturn\n\t}\n\n\t// call the next middleware in the chain\n\tnext(w, r)\n}\n```\n\n\n\n\n","funding_links":[],"categories":["Security","Go","Relational Databases","安全性","\u003cspan id=\"安全-security\"\u003e安全 Security\u003c/span\u003e","安全领域相关库","安全","Web Framework Hardening"],"sub_categories":["HTTP Clients","Advanced Console UIs","交流","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","查询语","HTTP客户端","高級控制台界面","高级控制台界面"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaredfolkins%2Fbadactor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaredfolkins%2Fbadactor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaredfolkins%2Fbadactor/lists"}