diff --git a/lib/dough.ex b/lib/dough.ex index 5ed7edb..0d6c2f3 100644 --- a/lib/dough.ex +++ b/lib/dough.ex @@ -6,26 +6,32 @@ defmodule Dough do import Supervisor.Spec import Cachex.Spec - def start(_type, _args) do # List all child processes to be supervised children = [ # Starts a worker by calling: Dough.Worker.start_link(arg) # {Dough.Worker, arg}, # Plug.Adapters.Cowboy.child_spec(:https, Dough.Router, [], port: 8331, keyfile: "priv/ssl/localhost.key", certfile: "priv/ssl/localhost.crt", otp_app: :dough) - worker(Cachex, [:dough, [ - expiration: expiration( - default: :timer.seconds(6000), - interval: :timer.seconds(300), - lazy: true) - ]]), - - {Plug.Adapters.Cowboy2, scheme: :https, plug: Dough.Router, options: [ - port: 8331, - otp_app: :dough, - keyfile: "priv/ssl/localhost.key", - certfile: "priv/ssl/localhost.crt" - ]} + worker(Cachex, [ + :dough, + [ + expiration: + expiration( + default: :timer.seconds(6000), + interval: :timer.seconds(300), + lazy: true + ) + ] + ]), + {Plug.Adapters.Cowboy2, + scheme: :https, + plug: Dough.Router, + options: [ + port: 8331, + otp_app: :dough, + keyfile: "priv/ssl/localhost.key", + certfile: "priv/ssl/localhost.crt" + ]} ] # See https://hexdocs.pm/elixir/Supervisor.html diff --git a/lib/dough/context.ex b/lib/dough/context.ex index 042c58e..ec46ebd 100644 --- a/lib/dough/context.ex +++ b/lib/dough/context.ex @@ -1,26 +1,33 @@ defmodule Dough.RequestContext do require Logger - defstruct [:start, :close, :lookup, :cache, :ttl] - - def ctx_start(ctx) do + + def ctx_start(ctx) do Map.put(ctx, :start, System.monotonic_time(:milliseconds)) end + def ctx_close(ctx) do Map.put(ctx, :close, System.monotonic_time(:milliseconds)) end + def ctx_lookup(ctx, dns_record) do Map.put(ctx, :lookup, dns_record.qdlist |> List.first()) end + def ctx_cachehit(ctx, v) do Map.put(ctx, :cache, v) end + def ctx_ttl(ctx, ttl) do Map.put(ctx, :ttl, ttl) end def ctx_log_out(ctx) do - Logger.info "#{ctx.lookup.type} - #{ctx.lookup.domain} - TTL #{ctx.ttl} | #{ctx.cache} - #{ctx.close - ctx.start}ms" + Logger.info( + "#{ctx.lookup.type} - #{ctx.lookup.domain} - TTL #{ctx.ttl} | #{ctx.cache} - #{ + ctx.close - ctx.start + }ms" + ) end end diff --git a/lib/dough/dohplug.ex b/lib/dough/dohplug.ex index 1287b9a..262b565 100644 --- a/lib/dough/dohplug.ex +++ b/lib/dough/dohplug.ex @@ -10,30 +10,36 @@ defmodule Dough.DoHPlug do def init(options), do: options def call(conn, _opts) do - ctx = %Dough.RequestContext{} |> ctx_start() - dns_message = case parse_doh(conn) do - {:ok, msg} -> msg - {:error, _} -> - Logger.error conn.method - raise Dough.NotAllowed, "" - end + dns_message = + case parse_doh(conn) do + {:ok, msg} -> + msg + + {:error, _} -> + Logger.error(conn.method) + raise Dough.NotAllowed, "" + end {cache_hit, ttl, dns_resp} = fetch_dns(dns_message) decoded = DNS.Record.decode(dns_message) - ctx = ctx_lookup(ctx, decoded) - |> ctx_cachehit(cache_hit) - |> ctx_ttl(ttl) - |> ctx_close() + ctx = + ctx_lookup(ctx, decoded) + |> ctx_cachehit(cache_hit) + |> ctx_ttl(ttl) + |> ctx_close() Dough.RequestContext.ctx_log_out(ctx) conn # support for [RFC5861] / cache control extensions - |> put_resp_header("cache-control", "max-age=#{ttl}, stale-while-revalidate=#{ttl * 2}, stale-if-error=#{ttl * 10}") + |> put_resp_header( + "cache-control", + "max-age=#{ttl}, stale-while-revalidate=#{ttl * 2}, stale-if-error=#{ttl * 10}" + ) |> put_resp_header("content-type", content_type(conn)) |> send_resp(200, dns_resp) end @@ -53,30 +59,33 @@ defmodule Dough.DoHPlug do ttlcache_set(dns_message, resp, ttl) {:miss, ttl, resp} + result -> ttl = ttl_extract(result) {:hit, ttl, result} end - end def parse_doh(conn) do - conn = fetch_query_params conn + conn = fetch_query_params(conn) + case conn.method do - "GET" -> {:ok, Base.url_decode64!(conn.query_params["dns"], padding: false, ignore: :whitespace)} + "GET" -> + {:ok, Base.url_decode64!(conn.query_params["dns"], padding: false, ignore: :whitespace)} + "POST" -> {:ok, body, _conn} = read_body(conn) {:ok, body} - _ -> {:error, nil} + + _ -> + {:error, nil} end end def handoff_dns(dns_message) do - client = Socket.UDP.open! + client = Socket.UDP.open!() send!(client, dns_message, {"8.8.8.8", 53}) {data, _server} = recv!(client) data end - end - diff --git a/lib/dough/exceptions.ex b/lib/dough/exceptions.ex index 7704bd9..57f914b 100644 --- a/lib/dough/exceptions.ex +++ b/lib/dough/exceptions.ex @@ -1,13 +1,13 @@ defmodule Dough.NotAllowed do - defexception [plug_status: 405, message: "Method Not Allowed"] + defexception plug_status: 405, message: "Method Not Allowed" end defmodule Dough.ServerError do - defexception [plug_status: 500, message: "Server Error"] + defexception plug_status: 500, message: "Server Error" end defimpl Plug.Exception, for: [Dough.NotAllowed, Dough.ServerError] do - def status(exc) do - exc.plug_status + def status(exc) do + exc.plug_status end end diff --git a/lib/dough/router.ex b/lib/dough/router.ex index 3177dfc..9f344c2 100644 --- a/lib/dough/router.ex +++ b/lib/dough/router.ex @@ -2,17 +2,16 @@ defmodule Dough.Router do use Plug.Router use Plug.ErrorHandler - if Mix.env == :dev do + if Mix.env() == :dev do use Plug.Debugger end require Logger - plug :match - plug :dispatch - - get "/", do: send_resp(conn, 200, "") - match "/dns-query", to: Dough.DoHPlug - match _, do: send_resp(conn, 404, "oopsie") + plug(:match) + plug(:dispatch) + get("/", do: send_resp(conn, 200, "")) + match("/dns-query", to: Dough.DoHPlug) + match(_, do: send_resp(conn, 404, "oopsie")) end diff --git a/lib/dough/ttlcache.ex b/lib/dough/ttlcache.ex index e5a1a39..3760836 100644 --- a/lib/dough/ttlcache.ex +++ b/lib/dough/ttlcache.ex @@ -1,5 +1,4 @@ defmodule Dough.TTL do - require Logger def ttlcache_lookup(dns_message) do @@ -29,6 +28,7 @@ defmodule Dough.TTL do {ans, nil} -> ans.ttl + {ans, _} -> ans.ttl end @@ -36,7 +36,6 @@ defmodule Dough.TTL do def _hashify_dns(dns_message) do :crypto.hash(:sha256, dns_message) - |> Base.encode16 + |> Base.encode16() end - end