Rob--W / cors-anywhere

CORS Anywhere is a NodeJS reverse proxy which adds CORS headers to the proxied request.
MIT License
8.59k stars 6k forks source link

Restrict access of public CORS Anywhere demo #45

Open Rob--W opened 8 years ago

Rob--W commented 8 years ago

The CORS Anywhere demo is hosted at Heroku. I've been informed that the app is causing performance issues on the platform and that hosting an open proxy is against the Acceptable Use Policy:

  1. Use the Service to operate an "open proxy" or any other form of Internet proxy service that is capable of forwarding requests to any End User or third party-supplied Internet host;

I'll be monitoring the traffic in the coming period, and blacklist all origins/destinations that have excessive usage demands, and/or automatically block sites that have more than X requests per Y seconds, unless explicitly whitelisted.

These measures are needed to 1) resolve the performance issues on Heroku platform 2) prevent abuse of the open CORS Anywhere proxy 3) Ensure that the CORS Anywhere demo can continue to operate for (small) sites who want to try out CORS Anywhere before hosting it themselves.

Rob--W commented 8 years ago

I have now imposed some rate limits.

With some exceptions (e.g. localhost because it's used for development and blocking localhost altogether doesn't make sense), you can only make 600 requests per origin per hour. I came to this number by capturing Origin headers for a whole hour, 5 times (in the weekend and weekday, at different times on a given day) (resulting in 1741K requests from 2.9k unique origins, excluding previously blacklisted origins). The data shows that:

600 requests per hour is a royal limit. If you need more, host your own instance of CORS Anywhere (see https://github.com/Rob--W/cors-anywhere#demo-server for instructions). If this limit turns out to be too permissive, the limit may be tightened even more.

Here are some statistics based on the data.

Max requests per hour Origins not affected by the limit (% of all) Requests from sites affected by the limit (% of all)
4000 99% 66%
3600 98% 68%
3000 98% 71%
2000 98% 75%
1000 96% 83%
800 95% 85%
700 95% 86%
600 (current limit) 95% 88%
500 94% 89%
400 92% 92%
300 91% 93%
200 89% 95%
100 86% 96%
90 85% 96.6%
80 84% 96.9%
70 83% 97.2%
60 82% 97.5%
50 80% 97.8%
40 79% 98.1%
30 76% 98.4%
20 71% 98.8%
10 62% 99.3%
9 60% 99.4%
8 59% 99.4%
7 56% 99.5%
6 55% 99.5%
5 50% 99.6%
4 48% 99.7%
3 41% 99.8%
2 37% 99.8%
1 20% 99.9%
0 0% 100.0%

I captured another 1 hour of requests after setting the limit to 600 per hour, and got the following actual results (excluding blacklisted sites):

These actual findings are within the expectations from the original investigation, so I'll stick to these limits for now.

And here are some more healthy statistics from the past hour (similar to the analysis from https://github.com/Rob--W/cors-anywhere/issues/42#issuecomment-198744800):

Error codes:

     70 H12
      4 H15
   5528 H27

Status codes (including requests that were immediately blacklisted and not visible in the above stats):

 101253 200
    174 206
   1300 301
     87 304
   3925 400
 662592 403 <-- Most of them are blacklisted
   3607 404
 226238 429 <-- Rate-limited
   5528 499
     24 500
     74 503
(total # of requests in 1 hour: 1004802)
tstibbs commented 6 years ago

Are file:/// origins affected by the limits or are they excepted?

Rob--W commented 6 years ago

@tstibbs Excepted, at my discretion.

erikksuzuki commented 4 years ago

While developing on localhost, I accidentally wrote an infinitely-looping script that sent out multiple requests through your heroku demo... I noticed immediately in the console log, so I closed the browser tab that the site was running in and changed the lines that was causing this to happen.

Thought this took care of it, but a few minutes later my app stopped working altogether. May I know if reaching the rate limit results in a permanent ban or a temporary one that expires after a set amount of time? Honest mistake.

Rob--W commented 4 years ago

@erikksuzuki The ban is automatic and automatically expires. I do occasionally add extra restrictions when I spot persistent abuse patterns, but in your case, you probably have access again by now.

Note: When developing on localhost, I suggest that you don't use CORS Anywhere as a proxy, but self-host CORS Anywhere (see README) or use other methods (e.g. configuring CORS correctly or using browser extensions that automatically add CORS headers). That will result in faster response times, and also prevent you from being blocked by mistake.

loic-lescoat commented 4 years ago

@Rob--W I made the same mistake as erikksuzuki did. How much time must go by before the ban expires? Thank you.

Rob--W commented 4 years ago

The current rate limiting rules are documented in #164.

Note that you can easily self-host CORS Anywhere to not have the restrictions. To learn how to set it up, see https://github.com/Rob--W/cors-anywhere#demo-server

dmov42 commented 3 years ago

I totally understand your reasons for imposing the limits, but could this be conveyed in a bit friendlier manner? Below message GET http://127.0.0.1:3000/mytest.html 404 (Not Found) is the only thing I see in my Chrome console when my JS hangs out on a fetch against Heroku CORS proxy. It took me 2 hours of googling and reading possible reasons to understand that I seem to be making one too many requests per hour. Could an error message perhaps be returned as a custom HTTP error code or a message in a body since this public instance of CORS proxy is anyway not intended for production use?

Rob--W commented 3 years ago

GET http://127.0.0.1:3000/mytest.html 404 (Not Found) It took me 2 hours of googling and reading possible reasons to understand that I seem to be making one too many requests per hour.

Not true. If you're getting hit by the rate limit, the error is 429 Too Many Requests, which is indeed a good description of what happens.

404 either means: