PhoenixDDoS
High performance application-layer DDoS protection for Elixir Phoenix.
Table of contents
- Features
- Setup
- Monitoring
- Local tooling
- Benchmark
- Community
- Next in roadmap
- Later in roadmap
- Contributing
Features
- protection: ip safelist_ips - List of ip that bypass all checks
- protection: ip blocklist_ips - List of ip that are always rejected
- protection:
PhoenixDDoS.IpRateLimit- rate limit per ip - protection:
PhoenixDDoS.IpRateLimitPerRequestPath- rate limit per ip per path - protection: log flooding - in case of an attack, prevent application log to explode
- engine: jail system - auto-blocklist ips that triggered a protection for a limited amount of time
- monitoring: telemetry - provide events to your application from phoenix_ddos decisions
- monitoring: sentry - if you use sentry, you can be notified when an ip has been put in jail
- local tools: ddos youself - because it is fun !
Usage
phoenix_ddos is a high performance application-layer DDoS protection for Elixir Phoenix.
Installation
- Add
:phoenix_ddosto your list of dependencies inmix.exs:
def deps do
[
{:phoenix_ddos, "~> 1.1"},
# Highly recommended, this will makes sure we get the correct remote_ip
{:remote_ip, "~> 1.1"}
]
end
- Add the
PhoenixDDoSplug to your app's Endpoint, after the excellent RemoteIp plug (optional but highly recommended !).
defmodule MyApp.Endpoint do
use Phoenix.Endpoint, otp_app: :my_app
# put as high in the order as possible
plug RemoteIp
plug PhoenixDDoS
# ...
end
Configuration
config :phoenix_ddos,
safelist_ips: ["1.2.3.4", "5.6.7.0"],
blocklist_ips: ["11.12.13.0"],
protections: [
# ip rate limit
{PhoenixDDoS.IpRateLimit, allowed: 500, period: {2, :minutes}},
{PhoenixDDoS.IpRateLimit, allowed: 10_000, period: {1, :hour}},
# ip rate limit on specific request_path
{PhoenixDDoS.IpRateLimitPerRequestPath,
request_paths: ["/graphql"], allowed: 20, period: {1, :minute}}
]
| Type | Option | Default | Description |
|---|---|---|---|
| bool | enabled | true | set false to disable |
| int | jail_time (minutes) | 15 | time an ip is fully blocked if caught by a protection. set nil to disable thus blocking instead |
| bool | raise_on_reject | false | raise when we reject a connexion instead of returning an http code error |
| int | http_code_on_reject | 429 | http code returned when we reject a connexion |
| list | protections | @see Protections examples | |
| list | safelist_ips | bypass all protections ips | |
| list | blocklist_ips | always blocked ips | |
| bool | on_jail_alert_to_sentry | false | notify slack when an ip get jailed |
The configuration is per node you run, rate_limits are not shared (yet), but it gives you the best performance in case of an attack.
Examples with protection PhoenixDDoS.IpRateLimit
- 500 per minute max, if triggered ip will be in jail for 15 minutes
[{PhoenixDDoS.IpRateLimit, allowed: 500, period: {1, :minute}}]
- disable jail, ip will be throttle to 500 per minute
[{PhoenixDDoS.IpRateLimit, allowed: 500, period: {1, :minute}, jail_time: nil}]
Examples with protection PhoenixDDoS.IpRateLimitPerRequestPath
- single route /graphql with a 20 per minute max, if triggered ip will be in jail for 15 minutes
[{PhoenixDDoS.IpRateLimitPerRequestPath,
request_paths: ["/graphql"], allowed: 20, period: {1, :minute}}]
- you can also give a phoenix-like path
[{PhoenixDDoS.IpRateLimitPerRequestPath,
request_paths: ["/admin/:id/dashboard"], allowed: 20, period: {1, :minute}}]
- multiple route consuming same quota
[{PhoenixDDoS.IpRateLimitPerRequestPath,
request_paths: ["/graphql", "/graphiql"], allowed: 20, shared: true, period: {1, :minute}}]
- multiple route consuming independent quota
[{PhoenixDDoS.IpRateLimitPerRequestPath,
request_paths: ["/graphql", "/graphiql"], allowed: 20, period: {1, :minute}}]
is equivalent to:
[
{PhoenixDDoS.IpRateLimitPerRequestPath,
request_paths: ["/graphql"], allowed: 20, period: {1, :minute}},
{PhoenixDDoS.IpRateLimitPerRequestPath,
request_paths: ["/graphiql"], allowed: 20, period: {1, :minute}}
]
Community
Slack: join elixir-lang and join channel #phoenix_ddos
Next in roadmap
- [perf] generate blocklist/allow pre-compute list module instead of make an
ip in blocklisttest - [monitoring/config] observe tooling, to be able to observe what volume is normal traffic and craft a configuration accordingly
- [feat] ip blocklist/safelist with mask/subnet
- [feat] log central genserver to avoid log spam and create possibility provide aggregated report
- [feat] out of jail system: an attacker ip would go out of jail and will make some damage again before being put in jail, prevent that
Later in roadmap
- [chore] go away from cachex
- [feat] multi-node
- [path] make a phoenix_ddos_pro with powerful features for companies ? The oban model might be a good path to take !
Contributing
Create issues on github for any bug or issue.
To contribute on the code, please clone and use following tools:
run tests
mix test
run release code validation
mix ci