Open kolbma opened 3 years ago
Nuance of running locally with actix. remote_addr() is returning the local peer socket so it sees "127.0.0.1:xxxx" where the xxxx will be changing on each connection. Try adjusting your code to add an identifier for comparison:
.wrap(
RateLimiter::new(MemoryStoreActor::from(store.clone()).start())
.with_interval(Duration::from_secs(60))
.with_max_requests(10)
.with_identifier(|req| {
let c = req.connection_info().clone();
let ip_parts: Vec<&str> = c.remote_addr().unwrap().split(":").collect();
Ok(ip_parts[0].to_string()) // should now be "127.0.0.1"
}),
)
Then there should be used realip_remote_addr. Or the rate limiter sees any reverse proxy as the client and there is the opposite effect that you'll block the service simply by a concurrent number of requests.
I've switched to a different crate, which seems to handle this for me.
realip_remote_addr
and remote_addr
yield the same results, no matter if its deployed locally or remote(I deployed the example in cloud and cross checked for myself). The security drawback listed on docs.rs for realip_remote_addr
is something that I didn't fully understand, hence I went with remote_addr
as a safe option. The port definitely seems an issue. I'm thinking of stripping the port part for the default behavior in the next release as demonstrated by @Svjard . In any case, users still have access to the full req
object.
Thanks for pointing this out.
I'd like to explain the difference in a few words.
It is not uncommon that you don't put your webservice/application in the first row to clients.
It is often the case that there is a reverse proxy or an api gateway. In these situations the remote ip is the local net ip address of these gates and not the real client ip. In the proxy protocol there is an http header extension where the proxy puts in the origin source ip of the client. Also cascades of proxying is possible. This header is the place which is used by real-remote-addr if available. But if there is no proxy in between which sets this header trustworthy for the application, an evil client can set the x-forwarded-for header by itself to any address and fools the application.
So I understand, the support of proxying might be a feature and it is ok to "workaround" only the actix "bug". I'm pretty sure it is not intended that actix returns a port on remote-addr in some situations. There is a peer-addr-method documented to get ports.
I use JMeter for a lot of local threaded requests and the ratelimiter detects only a single connection although there are 100 hundred requests in a second.
I've also used a loop to get requests for some more seconds. No change.
I've checked this with wireshark and there are really 100 hundred new TCP connections.
Every response looks the same:
My code looks like this
Looks like there is always executed the else-condition here: https://docs.rs/actix-ratelimit/0.3.1/src/actix_ratelimit/middleware.rs.html#220