Skip to content

Commit

Permalink
simple global rate limit by ip
Browse files Browse the repository at this point in the history
  • Loading branch information
tmkontra committed Oct 15, 2021
1 parent 4c345e9 commit 5862caa
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 4 deletions.
7 changes: 7 additions & 0 deletions bullion/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ config :logger, :console,
# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason

# Hammer rate limiting config
config :hammer,
backend: {
Hammer.Backend.ETS,
[expiry_ms: 60_000 * 60 * 4, cleanup_interval_ms: 60_000 * 10]
}

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"
42 changes: 42 additions & 0 deletions bullion/lib/bullion_web/controllers/rate_limit.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
defmodule BullionWeb.RateLimit do
import Phoenix.Controller
import Plug.Conn
require Logger

@global_bucket_name "any_request"
@bucket_duration 1_000 # 1 second
@request_limit 5

def init(_opts) do end

def call(conn, _opts) do
rate_limit(conn)
end

def rate_limit(conn, _options \\ []) do
case check_rate(conn) do
{:allow, _count} -> conn
{:deny, _limit} -> render_error(conn)
{:error, _reason} -> render_error(conn)
end
end

defp check_rate(conn) do
bucket_name(conn)
|> Hammer.check_rate(@bucket_duration, @request_limit)
end

defp bucket_name(conn) do
principal = case conn.remote_ip do
nil -> "unidentified"
addr -> addr |> Tuple.to_list |> Enum.join(".")
end
@global_bucket_name <> "_principal=" <> principal
end

defp render_error(conn) do
conn
|> put_status(429)
|> halt
end
end
2 changes: 2 additions & 0 deletions bullion/lib/bullion_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ defmodule BullionWeb.Router do
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug RemoteIp
plug BullionWeb.RateLimit
end

pipeline :api do
Expand Down
4 changes: 2 additions & 2 deletions bullion/lib/bullion_web/templates/page/index.html.eex
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<div class="btn white darken-4 col s10 m4">
<a href="/game/new" style="text-transform:none">
<a href="<%= Routes.game_path(@conn, :new_game) %>" style="text-transform:none">
<button>Start a Game</button>
</a>
<br><br><br>
<%= form_for @conn, Routes.game_path(@conn, :view_game), [method: :get], fn f -> %>
<%= text_input f, :shortcode %>
<%= submit "Find Game" %>
<% end %>
</div>
</div>
4 changes: 3 additions & 1 deletion bullion/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ defmodule Bullion.MixProject do
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.0"},
{:hashids, "~> 2.0"},
{:bullion_core, path: "../bullion-core"}
{:bullion_core, path: "../bullion-core"},
{:hammer, "~> 6.0"},
{:remote_ip, "~> 1.0"}
]
end

Expand Down
4 changes: 4 additions & 0 deletions bullion/mix.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%{
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"},
Expand All @@ -9,6 +10,7 @@
"ecto_sql": {:hex, :ecto_sql, "3.6.2", "9526b5f691701a5181427634c30655ac33d11e17e4069eff3ae1176c764e0ba3", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.6.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5ec9d7e6f742ea39b63aceaea9ac1d1773d574ea40df5a53ef8afbd9242fdb6b"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"},
"hammer": {:hex, :hammer, "6.0.0", "72ec6fff10e9d63856968988a22ee04c4d6d5248071ddccfbda50aa6c455c1d7", [:mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "d8e1ec2e534c4aae508b906759e077c3c1eb3e2b9425235d4b7bbab0b016210a"},
"hashids": {:hex, :hashids, "2.0.5", "d9839924c8221b954da8b110eda3e59c2c03df0389bac6e7d0e535f937033df1", [:mix], [], "hexpm", "ef47d8679f20d7bea59d0d49c202258c89f61b9b741bd3dceef2c1985cf95554"},
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
"mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"},
Expand All @@ -20,7 +22,9 @@
"plug": {:hex, :plug, "1.12.0", "39dc7f1ef8c46bb1bf6dd8f6a49f526c45b4b92ce553687fd885b559a46d0230", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5282c76e89efdf43f2e04bd268ca99d738039f9518137f02ff468cee3ba78096"},
"plug_cowboy": {:hex, :plug_cowboy, "2.5.1", "7cc96ff645158a94cf3ec9744464414f02287f832d6847079adfe0b58761cbd0", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "107d0a5865fa92bcb48e631cc0729ae9ccfa0a9f9a1bd8f01acb513abf1c2d64"},
"plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"},
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
"postgrex": {:hex, :postgrex, "0.15.9", "46f8fe6f25711aeb861c4d0ae09780facfdf3adbd2fb5594ead61504dd489bda", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "610719103e4cb2223d4ab78f9f0f3e720320eeca6011415ab4137ddef730adee"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"remote_ip": {:hex, :remote_ip, "1.0.0", "3d7fb45204a5704443f480cee9515e464997f52c35e0a60b6ece1f81484067ae", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9e9fcad4e50c43b5234bb6a9629ed6ab223f3ed07147bd35470e4ee5c8caf907"},
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
}
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ services:
image: "bullion:0.1.0.dev"
ports:
- "4000:4000"
environment:
environment:
- PORT=4001
- DATABASE_URL=postgresql://postgres:postgres@db/bullion
db:
Expand Down

0 comments on commit 5862caa

Please sign in to comment.