Giter Site home page Giter Site logo

play-guard's People

Contributors

arturalkaim avatar enalmada avatar jtjeferreira avatar sief avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

play-guard's Issues

X-Forwarded-For parsing does not support more than one proxy, is a dangerous default

Currently, the last IP address in the X-Forwarded-For header is used by default as the originating IP address for the request:

} yield ip) getOrElse {
// Consider X-Forwarded-For as most accurate if it exists
// Since it is easy to forge an X-Forwarded-For, only consider the last ip added by our proxy as the most accurate
// https://en.wikipedia.org/wiki/X-Forwarded-For
request.headers.get("X-Forwarded-For").map(_.split(",").last.trim).getOrElse {
request.remoteAddress
}

There's quite a few problems with this approach:

  • If no IP is appended to the X-Forwarded-For header at all, the user can spoof their IP address to the rate limiter just by creating an X-Forwarded-For header of their own (effectively bypassing the limiter, or DoSing any IP address they like)
    • This will become more common as load-balancers move to RFC 7239 (Forwarded) headers, which aren't supported at all
  • It doesn't support configuration of trusted proxies (those that the determination of IP address should "look through")
  • etc.

I'd suggest that the default case in the getOrElse (L12) block should just be request.remoteAddress:

  • It can't be spoofed by the user, providing a much safer default
  • It provides compatibility with the built-in way of determining the actual IP address in situations where there's more than one proxy: Play's play.http.forwarded.trustedProxies setting
    • Which means it gives us RFC 7239 support "for free" too

I'm guessing play.http.forwarded.trustedProxies might not have existed when this code was conceived, but either way, request.remoteAddress is definitely all that needs to be considered now.

Using Play Guard in HttpErrorHandler

Hi Simon,

My apologies for posting this here; this is not an issue but more of an implementation question. I am trying to implement the "HttpErrorRateLimitAction" on my auth controller, however if there is a body parsing error, the entire action is caught by the default http error handler and rate limiting will not work in this instance.

I have been trying to implement it in my custom "HttpErrorHandler" but I'm not quite sure as to where (or rather how) I should place the code.

def onClientError(request: RequestHeader, statusCode: Int, message: String) = {
    
    HttpErrorRateLimitAction(new RateLimiter(2, 1f / 10, "test failure rate limit")) {
      request => BadRequest("failure rate exceeded")
    }

    Logger.error("Client Error (" + statusCode + "):" + message)
    Future.successful(
      //Status(statusCode)("A client error occurred: " + message)
      BadRequest(Json.obj("status" -> Messages("unknown.error")))
    )
  } 

Make TokenBucketGroup a trait to allow easier customization

If you create a trait:

trait TokenBucketGroup {
  def consume(key: Any, required: Int): Long
}

and rename the current class to DefaultTokenBucketGroup, then it would be easier to customize the TokenBucketGroup implementation - there are tradeoffs between exactness and computational complexity, the current implementation is exact but at the cost of doing up to rate bucket rebuilds per second, which is totally fine at 10/s, but less so at 10k/s.

I would also consider changing the return type from Long to Boolean since it's only (intended to be?) used in a boolean way - that would also hide more of the TokenBucketGroup internals.

(Yes, it's of course possible to just subclass and ignore the private members of the current TokenBucketGroup)

(Happy to provide a pull request, wanted to check for interest first)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.