Securely rate limit an API, prevent IP address spoofing
I'm developing an API using PHP, MySQL, and Redis and would like to rate limit particular calls. The API is sitting behind CloudFlare. To implement this, I'll be incrementing the count per hour each IP address makes for a particular call in Redis, and will present an error if it exceeds the limit.
However, I believe I've run into an issue with IP address spoofing. I know the real client will never receive a response back if they spoof their IP address, but that may not be necessary for a call such as a create account call. A client could effectively create a DoS attack by registering for many accounts, all with different IPs, all the while avoiding the rate limit. This would cause my system to send out a high volume of welcome emails (leading to my servers being marked as spam), and could prevent users from signing up if their email account was maliciously registered. How can this be avoided?
- Does SSL prevent this form of IP spoofing?
- Is there a way to make sure the client receives the server's response, thereby ensuring that it's not a spoofed IP address?
- Does cloudflare somehow verify the IP address is not spoofed when passing along the HTTP_CF_CONNECTING_IP header?
Thanks for your help and suggestions.
Usually you would use a secret token (API key, login credentials or whatever) that identifies a user and count requests per user account.
Since you are attempting to limit the requests by IP I assume that you are about to create an "open" API where anybody may send requests too, without authentication.
The term *IP spoofing is not a problem in this case. This is because - unless he controls the routing between your server and the internet - the spoofing attacker will not get an answer (as you said). But HTTP(S) is transported over TCP and establishing a TCP connection requires the attacker to perform a successful handshake which requires to receive the connection ID from the server - meaning it requires to receive answers.
The Wikipedia Page of the TCP protocol might me a good external resource to start: https://en.wikipedia.org/wiki/Transmission_Control_Protocol
You see IP spoofing isn't a problem. But you need to understand that rate limiting by IP isn't a good solution at all. That's because:
- an abuser could request a new IP after the limit has been reached
- your API might be used by a large organization where internal IPs get NATed by the core router and you see only that core routers IP.
I would strongly encourage you to use authentication (together with SSL!) and limit requests on a per user base.
Answers to the listed questions in short (Can explain more if you want)
Does SSL prevent this form of IP spoofing?
Is there a way to make sure the client receives the server's response, thereby ensuring that it's not a spoofed IP address?
Yes, it is implemented in TCP -> see ACK in the wikipedia link above
Does cloudflare somehow verify the IP address is not spoofed when passing along the HTTP_CF_CONNECTING_IP header?
As explained above. HTTP traffic requires an established TCP connection. Therefore this makes no sense.