Apart from usual security precautions (Cookies etc), the following I found to be the must:
- Good limits on number of concurrent requests to Tomcat (or whatever you use, it's normally in web connector directive) - you can load-test it so server is not overloading on full load, so that makes servers not crash under full load but also they got well utilized, for example with
ab -c <number of connections>. And then, in front of these Tomcats put load balance to distribute traffic and shield from other attacks like packet floods. Load Balancer should have tuned TCP/IP stack for such scenarios (see below).
- Geographically dispersed servers in Cloud, so with GSLB load balancing and autoscaling
- Try to use in-RAM cache as much as you can
- Use scalable databases, like DynamoDB in AWS, but good MySQL instance will also do, so they can scale-up with your load
- Make sure any single API function is not slow, this can be done in unit tests (so with every test run you can see whatever there's no potential target for DDoS), making all API calls very fast you basically make DDoS problems very small and your website very nice.
The above things in bold are what usually I do after developers do their stuff basically to make it faster and more resilient and that's my 4 golden points :-)
From my experience it takes 20GBps network and 4-6 32 core servers to mitigate any spike like that to Tomcats anyway. It just doesn't happen more than that and the resources today are cheap to deal with it, and even on demand. The problem is when something is slow or not scalable like Databases, then the resources go too high and that's the problem.
For developers doing the API the main point is to use in-RAM cache. The rest is infrastructure / server with Tomcat build. I've seen some developers actually doing things like that and that's good and simple approach. So instead of every time checking Cookie with database, keep it in RAM, use sticky sessions etc. Same for other things. Like one poller to database which loads data into RAM every minute and other threads are using it without ever touching DB. I've seen this approach as well.
Infrastructure-wise, it's good to have Load Balancer in front of Tomcats and if it's not Cloud one, then you can do following.
Setup normal load balancer like HAProxy and put limits for each server, so in case of large number of real HTTP requests you can process them and forward to Tomcats, other software might be able to drop or filter bad requests base on configured rules - you could try Varnish Cache which is Cache, but for Load Balancer with filter it's also excellent and you can program your own logic.
Tune the TCP/IP stack of load balancer so it's resilient to large number of requests or SYN packets. So following tuning is effective:
- No IPTABLES on it (just filter things on switch)
- Disable SynCookies
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
The last two can help achieving a lot's of incoming new connections per second.