{"id":37785335,"url":"https://github.com/markdingo/rrl","last_synced_at":"2026-01-16T15:11:47.201Z","repository":{"id":66369290,"uuid":"601443904","full_name":"markdingo/rrl","owner":"markdingo","description":"Response Rate Limiting (RRL) package for DNS servers","archived":false,"fork":false,"pushed_at":"2023-07-15T06:11:16.000Z","size":53,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-06-20T05:02:24.304Z","etag":null,"topics":["dns","go","golang","golang-package"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/markdingo.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-14T04:23:19.000Z","updated_at":"2023-10-18T04:58:40.000Z","dependencies_parsed_at":"2024-06-20T04:17:09.496Z","dependency_job_id":"34e69ff9-c5cc-4e2e-960e-0d39e342a449","html_url":"https://github.com/markdingo/rrl","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/markdingo/rrl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markdingo%2Frrl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markdingo%2Frrl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markdingo%2Frrl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markdingo%2Frrl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/markdingo","download_url":"https://codeload.github.com/markdingo/rrl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markdingo%2Frrl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28479406,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["dns","go","golang","golang-package"],"created_at":"2026-01-16T15:11:46.553Z","updated_at":"2026-01-16T15:11:47.192Z","avatar_url":"https://github.com/markdingo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- Always newline after period so diffs are easier to read. --\u003e\n# rrl - Response Rate Limiting for DNS Servers\n\n## Introduction\n\n`rrl` is a standalone `go` package which implements the [ISC](https://www.isc.org) [Response\nRate Limiting](https://kb.isc.org/docs/aa-01148) algorithms as originally implemented in\n[Bind 9](https://www.isc.org/bind/).\nThe goal of \"Response Rate Limiting\" is to help authoritative DNS servers mitigate against\nbeing used as part of an amplification attack.\nSuch attacks are very easy to orchestrate since most authoritative DNS servers respond to\nUDP queries from any putative source address.\n\nIf you are the developer of an authoritative DNS server then in the interest of Internet\nhygiene you really should incorporate a \"Response Rate Limiting\" capability - whether with\nthis package or some other.\nIf you don't, your server is more vulnerable to being used as part of an amplification\nattack which will not be regarded highly by other DNS operators.\n\nThis package is designed to be very easy to use.\nIt consists of a configuration mechanism and a single public function to check limits.\nThat's it; that's the interface.\n\nIf you use [miekg/dns](https://github.com/miekg/dns) you might\nfind it convenient to use [markdingo/miekgrrl](https://github.com/markdingo/miekgrrl) which\nprovides an adaptor function for passing `miekg.dns.Msg` attributes to this package.\n\n## Genesis\n\nThis package is derived from [coredns/rrl](https://github.com/coredns/rrl) which mimics\nthe ISC algorithms.\n\nThe main differences between this package and coredns/rrl is that all coredns dependencies\nand external interfaces have been removed so that this package can be used by programs\nunrelated to coredns.\nFor example the external logging and statistics functions have been removed and are now\nthe responsibility of the caller.\nIn short, all external interactions and dependencies have been eliminated, but otherwise the underlying\nimplementation is largely unchanged.\n\n(Needless to say, this package only exists because of the efforts of the coredns/rrl developers.\nA big \"thank you\" to them.)\n\n### Project Status\n\n[![Build Status](https://github.com/markdingo/rrl/actions/workflows/go.yml/badge.svg)](https://github.com/markdingo/rrl/actions/workflows/go.yml)\n[![codecov](https://codecov.io/gh/markdingo/rrl/branch/main/graph/badge.svg)](https://codecov.io/gh/markdingo/rrl)\n[![CodeQL](https://github.com/markdingo/rrl/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/markdingo/rrl/actions/workflows/codeql-analysis.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/markdingo/rrl)](https://goreportcard.com/report/github.com/markdingo/rrl)\n[![Go Reference](https://pkg.go.dev/badge/github.com/markdingo/rrl.svg)](https://pkg.go.dev/github.com/markdingo/rrl)\n\n## Description\n\n`rrl` is called by an authoritative DNS server prior to sending each response to a query.\n`rrl` tracks the query-per-second rate in a unique \"account\" assigned to each \"Response\nTuple\" destined for a particular Client Network.\n\n\"Accounts\" are credited each second with a configured amount and debited once for\neach call to [Debit].\nAt most an \"account\" can gain up to one second of credits or up to a configurable 15\nseconds of debits.\nWhile the \"account\" is in credit `rrl` indicates that the caller should send their planned response.\nOtherwise `rrl` indicates that the caller should `Drop` or `'Slip'` their response.\n\nThe \"Response Tuple\" is formulated from the most salient features of the response message.\nThis formulation is somewhat convoluted because DNS responses are somewhat convoluted.\n\n`'Slip'` is ISC terminology which means to respond with a BADCOOKIE response or a\ntruncated response depending on whether the query contained a valid client cookie or not.\nThe goal of a `'Slip'` response is to give genuine clients a small chance of getting a\nresponse even when their source addresses are in a range being used as part of an\namplification attack.\n\n`rrl` plays no part in processing DNS messages or modifying them for output - it solely\ntracks rate-limiting \"accounts\" and returns a recommended course of action.\nAll DNS actions, statistics gathering and logging are the responsibility of the caller.\n\n### \"Response Tuple\" and Client Network\n\n\"Response Tuple\" and Client Network are used to uniquely identity rate-limiting\n\"accounts\".\nIn effect they form keys to an internal `rrl` \"accounts\" cache.\n\nA \"Response Tuple\" is formulated from various features of the response message - the exact\ndetails depend on the nature of the response (NXDomain, Error, referral, etc).\nTo paraphrase ISC, the formulation of the \"Response Tuple\" is not simplistic.\nThe intent is for responses indicative of potential abuse to be assigned to a small set of\ntuples whereas responses indicative of genuine requests are assigned to a large set of\ntuples.\nThe goal being to cause \"accounts\" of suspect queries to run out of credits far sooner\nthan the \"accounts\" of genuine queries.\n\nThe package documentation describes how to formulate a \"Response Tuple\".\n\nA Client Network is the putative source address of the request masked by the configured\nsize of the \"network\".\nThe default configured sizes being 24 for ipv4 and 56 for ipv6.\n\n### ISC Terminology\n\nAs a general rule, this documentation uses ISC terminology, such as \"accounts\" and\n\"debits\" and so on.\nThe one exception being \"Response Tuple\" which is used in preference to \"Identical\nResponse\", or \"Token\" in coredns/rrl parlance.\nWhile there is obvious merit in common terminology, \"Response Tuple\" seem to better\nconvey intent and outcome.\n\n## Sample Code\n\n    package main\n\n    import \"github.com/markdingo/rrl\"\n\n    func main() {\n\n      server:= dnsListenSocket()\n      db := myDatabase()\n\n      cfg := rrl.NewConfig()\n      cfg.SetValue(...)             // Configure limits relevant to our deployment\n      R := NewRRL(cfg)              // Create our `rrl` instance\n\n      for {\n          srcIP, request := server.GetRequest()      // Accept a query\n          response := db.lookupResponse(request)     // Create the response\n\n          tuple := makeTuple(response)               // Formulate the \"Response Tuple\"...\n          action, _, _ := R.Debit(srcIP, tuple)      // ... and debit the corresponding accounts\n\n          switch action {                            // Dispatch on the recommended action\n\n          case rrl.Drop:                             // Drop is easy, do nothing\n\n          case rrl.Send:                             // No rate limit applies, ship it!\n              server.Send(response)\n\n          case rrl.Slip:\n              if request.ValidClientCookie() {       // Slip response varies depending on\n                  server.SendBadCookie(response)     // whether the client sent a cooke or not\n              } else {\n                  response.makeTruncatedIfAble()     // No valid client cookie means\n                  server.Send(response)              // send a truncated response\n              }\n          }\n      }\n    }\n\nNote that some error responses such as REFUSED and SERVFAIL cannot be replaced with\ntruncated responses thus the `makeTruncatedIfAble` function needs some intelligence.\n\n## Installation\n\n`rrl` requires [go](https://golang.org) version 1.19 or later.\n\nOnce your application imports `\"github.com/markdingo/rrl\"`, then `\"go build\"` or `\"go mod\ntidy\"` in your application directory should download and compile `rrl` automatically.\n\n## Further Reading\n\nThe `rrl` API is described in the package documentation which is mirrored online at\n[pkg.go.dev](https://pkg.go.dev/github.com/markdingo/rrl).\nOther background material can be found at the [coredns rrl\nplugin](https://github.com/coredns/rrl) home page.\n\n## Community\n\nIf you have any problems using `rrl` or suggestions on how it can do a better job,\ndon't hesitate to create an [issue](https://github.com/markdingo/rrl/issues) on\nthe project home page.\nThis package can only improve with your feedback.\n\n## Motivation\n\n`rrl` was originally created for [autoreverse](https://github.com/markdingo/autoreverse),\nthe no muss, no fuss reverse DNS server; check\n[it](https://github.com/markdingo/autoreverse) out if you want an example of how `rrl` is\nused in the wild.\n\n## Copyright and License\n\n`rrl` is Copyright :copyright: 2023 Mark Delany and is licensed under the BSD\n2-Clause \"Simplified\" License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkdingo%2Frrl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarkdingo%2Frrl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkdingo%2Frrl/lists"}