How to Identify a CC Attack? These Signs Are Immediate Tells
CC attack volume is not large, yet it can take a site down. Hardest part is separating it from a legitimate traffic spike. FAQ covering CC identification: six typical signs, three Nginx log stats commands, per-IP request thresholds, server-side symptoms, and a copy-paste limit_req emergency config after confirmation.
Introduction
CC is the attack mid-size sites see most, and the one hardest to tell apart: it does not need large bandwidth. Dozens of bots — or one well-specced box — can take a site down. This FAQ answers the high-frequency questions on CC identification: how to separate CC from a legitimate traffic spike, typical signs, how to verify fast with Nginx logs and commands, and what to do first after you confirm it.
Q: What is a CC attack? How do you separate it from a legitimate traffic spike?
CC (Challenge Collapsar) is an HTTP-layer attack. The attacker simulates a large volume of requests that look legitimate and continuously hits the most expensive pages (dynamic pages, search, DB query APIs), exhausting CPU, connection slots, or the database pool. Core difference from a real spike: traffic rose; real visitors did not. A real spike is spread out, hits diverse pages, request/response both exist. CC is highly concentrated, mechanical, and hammers a handful of URLs.
Q: Typical CC signs?
Any of the following is enough to call CC, not a traffic spike:
- Requests concentrated on a few IPs: TOP 10 IPs account for more than half of total requests;
- URLs highly concentrated: the same dynamic page, search API, or parameterized page, over and over;
- Abnormal Referer and UA: large numbers of empty or repeated UAs, or missing Referer;
- Abnormal hours: request volume far above baseline at 03:00–04:00;
- Bandwidth is fine, resources are not: ingress bandwidth normal, but CPU, php-fpm, and MySQL are saturated. This is the key separator from volumetric DDoS;
- Requests without clicks: no CSS/JS/image static fetches. The client never rendered the page.
Q: How do you confirm CC from Nginx logs fast?
Three command groups. First, top talker IPs:
`awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20`
Second, most-requested URLs:
`awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20`
Third, requests per second, looking for instantaneous spikes:
`awk '{print $4}' /var/log/nginx/access.log | cut -d: -f2-4 | uniq -c | sort -rn | head -20`
If a few IPs are hitting a few URLs at tens to hundreds of requests per second continuously, call it CC. Pull logs before and after the suspected window. Do not look only at now.
Q: How many requests per IP is abnormal? False positives?
No absolute number. Depends on the business. For a typical corporate site, a single IP sustaining hundreds of requests per minute, concentrated on one URL, is highly suspicious. Two false-positive cases:
- NAT egress: offices, schools, and ISP CGNAT share one IP; volume is naturally high. Check URL diversity for that IP — real NAT egress hits many pages; attacks are highly uniform;
- Search-engine spiders: Baidu and Google crawlers also fetch at high frequency. Verification in the next section.
Q: What server symptoms should make you suspect CC?
Read host symptoms together with connection counts. Typical: php-fpm saturates CPU, intermittent 502/504, MySQL connection count explodes with too many connections. Source distribution on 80/443:
`netstat -an | grep -E ':80|:443' | grep ESTABLISHED | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20`
If a single IP holds tens to hundreds of ESTABLISHED connections while load spikes in lockstep, that is the textbook CC picture. Pair with `top` and `mysqladmin processlist` to confirm the burn is in the dynamic tier, not the bandwidth tier.
Q: Confirmed CC. First action?
Rate-limit to cut loss. Do not ban IPs one by one — attack IPs rotate; manual bans always lag. Nginx's built-in limiter is enough for emergency use:
`http {
limit_req_zone $binary_remote_addr zone=cc_zone:10m rate=10r/s;
server {
location / {
limit_req zone=cc_zone burst=20 nodelay;
limit_req_status 429;
}
}
}`
rate=10r/s means 10 requests per second average per IP; burst=20 allows a short burst. Then `nginx -t && nginx -s reload`. For IPs you have actually confirmed as malicious, add a precise deny:
`deny 203.0.113.45;`
Do not ban large CIDRs. Easy to collateral-damage real users behind ISP NAT egress.
Q: Can CDN or WAF identify CC automatically?
Yes. This is the lowest-effort path. Self-built rate limits are a blunt per-IP knife. A real WAF's CC stack is frequency stats + behavior analysis + human challenge: suspicious hits get a JS challenge or CAPTCHA; real users pass with no friction; scripts fail. WAF sits at the edge, so attack traffic never reaches origin. Origin bandwidth and connection resources stay untouched. For mid-size sites with no dedicated ops, onboarding a WAF with CC protection such as Baidu Cloud WAF is more stable than repeatedly tuning iptables on the box.
Q: Additional notes?
- Copy logs before rotate: logrotate may wipe the attack window before you analyze. `cp` first;
- Separate CC from hostile scraping: similar symptoms. Scraping walks the whole site; CC burns resources. Different response;
- Cache dynamic pages: turn hot dynamic requests into static output or add page cache. Raises attack cost sharply;
- Keep attack evidence: log screenshots and connection records help later police reports or datacenter tickets;
- Rehearse in peacetime: pre-stage and test rate-limit rules and ban procedures so you are not improvising under fire.