• Stars
    star
    164
  • Rank 230,032 (Top 5 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 10 years ago
  • Updated 7 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Configurable HTTP rate limiter

Sphinx: HTTP Rate Limiting

Sphinx is a rate limiting HTTP proxy, implemented in Go, using leaky buckets.

The name for this project ("Sphinx") comes from the ancient Greek word sphingien, which means "to squeeze" or "to strangle." The Sphinx would stand by the road and stop travelers to ask them a riddle. If they could not answer, she would strangle them. She was often thought of as a guardian and flanked the entrances to temples.

Sphinx

Why?

Rate limiting an API is often required to ensure that clients do not abuse the available resources and that the API is reliably available when multiple clients are requesting data concurrently. Buckets can be created based on various parameters of an incoming request (eg. Authorization, IP address) to configure how requests are grouped for limiting.

Rate limiting functionality is already available in some proxies (eg. Nginx, HAProxy). However, they often use in-memory stores that make rate-limiting when running multiple proxies (e.g. for load balancing) unpredictable. Configuration for these limits also gets complex since it includes many actions such as routing, request/response re-writing, and rate-limiting.

Sphinx is not...

  • Sphinx is not focused on preventing Denial of Service (DoS) attacks or requests from malicious clients. The goal is to expose rate limiting information to clients and enforce balanced use by API clients.

  • Sphinx is not a request forwarding service. Sphinx only allows for very simplistic forwarding to a single host per instance of the rate limiter. Any advanced routing or request handling should be handled by a real proxy (eg. Nginx, HAProxy).

  • Sphinx is not an HTTPS terminator. This keeps the burden of configuring SSL certificates and security outside of Sphinx. Ideally, there is real load balancing and HTTPS termination before a request hits Sphinx.

Rate limit headers and errors

Sphinx will update HTTP response headers for requests that match limits to include details about the rate limit status. Headers are canonicalized, but clients should assume header names are case insensitive.

  • X-RateLimit-Reset: Unix timestamp when the rate limit counter will be reset.
  • X-RateLimit-Limit: The total number of requests allowed in a time period.
  • X-RateLimit-Remaining: Number of requests that can be made until the reset time.
  • X-RateLimit-Bucket: Name of the rate-limit bucket this request belongs to in the configuration.

Limit names can be configured via a configuration file.

Request:

HOST example.com
GET /resource/123
AUTHORIZATION Basic ABCD

Response headers:

Status: 200 OK
X-RateLimit-Limit: 200
X-RateLimit-Remaining: 199
X-RateLimit-Reset: 1394506274
X-RateLimit-Bucket: authorized-users

In case the client hits a rate limit, an empty response with a 429 Too Many Requests status code will be returned.

Request:

HOST example.com
GET /resource/123
AUTHORIZATION Basic ABC

Response headers:

Status: 429 Too Many Requests
X-RateLimit-Limit: 200
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1394506274
X-RateLimit-Bucket: authorized-users

Configuring Sphinx

Rate limiting in Sphinx is managed by setting up limits in a yaml configuration file. Details about the configuration format can be found in the annotated example.

It is important to understand the concept of buckets and limits to effectively configure a rate limiter.

Limit: A limit defines a rate limiting policy that Sphinx enforces by counting requests in named buckets. Bucket: A bucket is simply a named value. Each request that matches a limit increments the value of one bucket.

Below is an example of a limit and three requests that increment two bucket values.

Test Limit

match if request path begins with /limited bucket names are defined as name-{ip-address} Allow TWO requests per minute

Setting this limit using the config would look like:

proxy:
  handler: http             # can be {http,httplogger}
  host: http://httpbin.org  # URI for the http(s) backend we are proxying to
  listen: :6634             # bind to host:port. default: height of the Great Sphinx of Giza

storage:
  type: redis       # must be one of {redis, dynamodb, memory}
  host: localhost   # redis hostname. required for redis
  port: 6379        # redis port.     required for redis
  table: table      # table name.     required for dynamodb
  region: us-west-1 # table region.   required for dynamodb

limits:
  test-limit:
    interval: 60  # in seconds
    max: 2        # number of requests allowed in interval
    keys:
      ip: ""      # ip keys require no configuration
    matches:
      paths:
        match_any:
          - "/limited*"

Request One

path: /limited/resource/1 Headers: Host: example.com Authorization: Basic User:Password IP: 10.0.0.1

State: test-limit-10.0.0.1: 1

Request Two

path: /limited/resource/2 Headers: Host: example.com Authorization: Basic Admin:Secure IP: 10.0.0.2

State test-limit-10.0.0.1: 1 test-limit-10.0.0.2: 1

Request Three

path: /limited/resource/3 Headers: Host: example.com Authorization: Basic Admin:Secure IP: 10.0.0.1

State test-limit-10.0.0.1: 2 test-limit-10.0.0.2: 1

The following snippet explains how to define limits in Sphinx:

limit-name:
  interval: 15
  max: 200
  keys:
    headers:
      names:
        - "Authorization"
  matches:
    paths:
      match_any:
        - "/special/resources/.*"

limit_name: Used to identify and added to the X-RateLimit-Bucket header.

interval: A limit may create many buckets. This key provides the expire time in secs for all buckets created for this limit.

max: Maximum number of requests that will be allowed for a bucket in one interval.

keys: This section defines the dynamic bucket name generated for each request. Currently supported matchers include headers and ip. All keys defined are concatenated to create the full bucket name.

headers: Use concatenated header values from requests in the bucket name.

headers:
  encrypt: "SALT_TO_ENCRYPT_VALUE"  # optional
  names:
    - HEADER_NAME_1
    - HEADER_NAME_2

ip: Use the incoming IP Address from the incoming request in the bucket name.

matches: This section defines which requests this limit should be applied to. The request MUST match all of the matchers defined in this block. Currently supported matchers are headers and paths.

headers: This matcher currently supports the match_any key which returns true if any of the list items evaluate to true. eg:

headers:
  match_any:
    - name: "HEADER_NAME"
      match: "REGEX_FOR_MATCHING_HEADER_VALUE"
    - name: "OTHER_HEADER_NAME"  # no match key means just check for existence

paths: This matcher also supports the match_any key.

paths:
  match_any:
    - "/limited/resource/*"
    - "/objects/limited/.*"

Documentation

  • LeakyBucket: LeakyBucket documentation
  • Sphinx: Sphinx documentation

Tests

Sphinx is built and tested against Go 1.15. Ensure this is the version of Go you're running with go version.

Now you can run our test and linting suites via Make:

cd sphinx
make test

Credits

  • Sphinx logo by EricP from The Noun Project
  • Drone inspiration for building a deb

More Repositories

1

microplane

A CLI tool to make git changes across many repos, especially useful with Microservices.
Go
367
star
2

saml2

Node module to abstract away the complexities of the SAML protocol behind an easy to use interface.
CoffeeScript
352
star
3

csvlint

library and command line tool that validates a CSV file
Makefile
186
star
4

leakybucket

Leaky bucket implementation in Go with support for different backends (redis, in-memory)
Go
85
star
5

wag

sWAGger - Web API Generator
Go
77
star
6

gitbot

programmatically make changes to many git repositories
Makefile
74
star
7

dev-handbook

A guide to the processes, conventions, and philosophies of the Clever dev team.
Makefile
63
star
8

moredis

sync data from mongo into redis
Go
53
star
9

ARCHIVED-mongo-graph

visualize mongo data
CoffeeScript
40
star
10

optimus

Concurrently extract, transform, and load tables of data in Go
Go
34
star
11

quest

node http requests made easy
CoffeeScript
29
star
12

underscore.deep

Underscore utilities for operating on nested objects
CoffeeScript
27
star
13

http-science

Forward http requests to two places, report any differences in the response.
Go
27
star
14

clever-ruby

Clever Ruby library
Ruby
27
star
15

clever-python

Clever Python bindings
Python
27
star
16

resolve-ip

service that takes in an IP address and converts it to a latitude and longitude
Go
25
star
17

components

Frontend components
TypeScript
24
star
18

clever-js

Node.js library for the Clever API
CoffeeScript
24
star
19

workflow-manager

Minimal Workflow orchestrator for AWS Step Functions
Go
24
star
20

reposync

Syncs repos for a GitHub user or organization into a folder on your computer
Makefile
23
star
21

clever-php

Clever PHP library
PHP
22
star
22

thrift-pool

A module that wraps thrift interfaces in connection pooling logic to make them more resilient.
CoffeeScript
22
star
23

gitsem

a command line utility for managing semantically versioned (semver) git tags
Makefile
18
star
24

terrafam

IAM modules and YML-based terraform configuration generator
HCL
18
star
25

log-replay

Replays log files at a given speed
Makefile
16
star
26

amazon-kinesis-client-go

Amazon Kinesis Client for Go
Go
16
star
27

ARCHIVED-mongoose-repl

A Mongo REPL with the full power of Mongoose
CoffeeScript
16
star
28

sfncli

Utility to create AWS Step Function activities out of command line programs
Go
15
star
29

ARCHIVED-json-schema-converter

Utilities to translate your schema into anything, as long as 'anything' is JSON Schema.
CoffeeScript
15
star
30

policies

Clever Terms and Policies
14
star
31

pathio

go library for transparently writing to and reading from different types of paths (supports stdout, s3, and fs)
Go
14
star
32

ios-sdk

Clever iOS SDK
Objective-C
13
star
33

discovery-go

Programmatically find services
Go
13
star
34

clever-go

Go library for the Clever API
Go
13
star
35

writable-stream-parallel

Parallelize your _write()s
JavaScript
12
star
36

go-bench

HTTP benchmarking with customizable log replays written in go
Go
12
star
37

node-google-admin-sdk

node.js library for Google's Admin SDK
CoffeeScript
12
star
38

unix-sort

Sort large streams of JSON objects using the unix sort command.
CoffeeScript
12
star
39

ARCHIVED-ebs-snapshots

Service to automate creation and cleanup of Amazon EBS snapshots
Python
11
star
40

graphviz-service

A REST interface to the graphviz command line tool.
Makefile
9
star
41

clever-oauth-examples

DEPRECATED - this repository is no longer maintained
PHP
8
star
42

marathon-stats

ARCHIVED: A simple container which queries marathon and mesos for stats about their current state, and logs these stats to stderr
Go
7
star
43

tracing-middleware

Moved to opentracing-contrib org
JavaScript
7
star
44

mesos-visualizer

Visualizations showing mesos resource utilization
Go
7
star
45

stealth

Go wrapper for credstash secret store
Go
7
star
46

sentry-node

simple node wrapper around the Sentry API
CoffeeScript
6
star
47

understream

stream all the things
CoffeeScript
6
star
48

kayvee-go

Logs for human and machine readability
Go
6
star
49

unix-join

Join large streams of JSON objects using the unix join command.
CoffeeScript
6
star
50

loofah

Data scrubber
CoffeeScript
5
star
51

swagger-api

A Swagger Definition for the Clever API
Go
5
star
52

analytics-monitor

watch over our db to ensure up-to-date data
Go
5
star
53

flarebot

A bot for controlling Flares
Go
5
star
54

csvutil

A [un]marshaling utility for translating between CSV data and Go structs
Go
5
star
55

node-redis-reservation

Distributed locking mechanism built on redis.
CoffeeScript
5
star
56

omniauth-clever

Ruby
5
star
57

clever-cli

DEPRECATED - this repository is no longer maintained
Go
4
star
58

ARCHIVED-baseworker-go

A simple Gearman worker library
Go
4
star
59

frontend-boilerplate

Want to create a React app? Start here!
JavaScript
4
star
60

ecs-rollover

DEPRECATED: script to safely rollover ECS nodes without service interruption
Python
4
star
61

clever-csharp

C# client library for Clever APIs
C#
3
star
62

ARCHIVED-oplog-replay

Replay mongodb oplogs at variable speed
Go
3
star
63

discovery-node

Programmatically find services (like discovery-go, but for node)
TypeScript
3
star
64

ci-scripts

Re-usable continuous integration (CI) scripts
Shell
3
star
65

kayvee

Kayvee translates an object into a human and machine parseable string
3
star
66

ddb-to-es

Process DynamoDB streams and INDEX, MODIFY, DELETE Elasticsearch document
Go
3
star
67

go-utils

collection of small packages with useful, common behavior
Go
3
star
68

clever-java

Java library for the Clever API
Java
2
star
69

prune-images

a worker that prunes old images from ECR and Docker Hub
Makefile
2
star
70

ecs-task-metadata-exporter

A Prometheus exporter for monitoring ECS containers using the ECS task metadata endpoint.
Go
2
star
71

mongo-lock-go

Distributed lock client backed by mongo
Go
2
star
72

ARCHIVED-go-validation

Go validation library
Go
2
star
73

kayvee-python

Kayvee translates an dictionary into a human and machine parseable string
Python
2
star
74

dynamodb-lock-go

Go client library for distributed locking using a DynamoDB backend
Go
1
star
75

mongo-lock-node

Implements a distributed lock client backed by mongo
TypeScript
1
star
76

atlas-api-client

Go client for MongoDB Atlas
Go
1
star
77

whackanop

periodically kill long-running mongo operations
Makefile
1
star
78

ARCHIVED-redirector

simple redirection app to redirect from one domain to another, preserving protocol, subdomain, path, and querystring
CoffeeScript
1
star
79

elasticsearch-toolbox

Maintenance tooling for Elasticsearch
TypeScript
1
star
80

async-ext

Extensions to the Node.js async library
CoffeeScript
1
star
81

connect-session-compress

connect session store that compresses the session data. compatible with any backing store (redis, dynamo, etc.)
JavaScript
1
star
82

consul-service-pulse

Externally confirms if consul services are alive. Used to cleanup stale consul nodes, and better understand networking errors.
Go
1
star
83

ARCHIVED-mongoose-any-index

Extra index functionality for mongoose
CoffeeScript
1
star
84

talks

slides!
Go
1
star
85

kayvee-js

Package kayvee provides methods to output human and machine parseable strings
TypeScript
1
star
86

python-redis-reservation

Python library for resource reservation using Redis
Python
1
star
87

json-predicate-transformer

A simple utility for modifying JSON objects using a predicate-transformer paradigm
TypeScript
1
star
88

discovery-python

Programmatically find service endpoints (i.e. discovery-go for python)
Python
1
star
89

go-process-metrics

A library for tracking golang process metrics
Makefile
1
star