PhoenixDDoS

High performance application-layer DDoS protection for Elixir Phoenix.

Hex DocsCI StatusHex VersionApache 2 License

Table of contents

Usage Installation Configuration

How it works (you defined rules and list, it can put in jail or just block if it reach any threshold)

Features

Monitoring Telemetry events (@see module PhoenixDDoS.Telemetry) Notification to sentry

Local tests DDoS youself using siege (mix phoenix_ddos.attack_myself)

Benchmarks

Community Next in roadmap

Features

protection: ip safelist_ips protection: ip blocklist_ips protection: PhoenixDDoS.IpRateLimit protection: PhoenixDDoS.IpRateLimitPerRequestPath protection: log flooding

engine: jail system

monitoring: telemetry monitoring: sentry

local tools: ddos youself testing

Usage

phoenix_ddos is a high perContact / Supportformance application-layer DDoS protection for Elixir Phoenix.

Installation

  1. Add :phoenix_ddos to your list of dependencies in mix.exs:
def deps do
  [
    {:phoenix_ddos, "~> 0.7"},
    # Highly recommended, this will makes sure we get the correct remote_ip
    {:remote_ip, "~> 1.1"}
  ]
end
  1. Add the PhoenixDDoS plug 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
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

Examples with PhoenixDDoS.IpRateLimit

  1. 500 per minute max, if triggered ip will be in jail for 15 minutes

    [{PhoenixDDoS.IpRateLimit, allowed: 500, period: {1, :minute}}]
  2. disable jail, ip will only be throttle to 500 per minute

    [{PhoenixDDoS.IpRateLimit, allowed: 500, period: {1, :minute}, jail_time: nil}]

Examples with PhoenixDDoS.IpRateLimitPerRequestPath

  1. single route

     [{PhoenixDDoS.IpRateLimitPerRequestPath,
      request_paths: ["/graphql"], allowed: 20, period: {1, :minute}}]
  2. you can also give a phoenix-like path

     [{PhoenixDDoS.IpRateLimitPerRequestPath,
      request_paths: ["/admin/:id/dashboard"], allowed: 20, period: {1, :minute}}]
  3. multiple route consumming same quota

     [{PhoenixDDoS.IpRateLimitPerRequestPath,
      request_paths: ["/graphql", "/graphiql"], allowed: 20, shared: true, period: {1, :minute}}]
  4. multiple route consumming independant quota

     [{PhoenixDDoS.IpRateLimitPerRequestPath,
      request_paths: ["/graphql", "/graphiql"], allowed: 20, period: {1, :minute}}]

is equivalant 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