There’s no way around this simply because of how CloudFlare is designed. I mean, there is, but you’re effectively disabling CloudFlare’s DDoS protection, caching, etc.
CloudFlare is at its heart an nginx reverse proxy. Traffic from your users go to their servers which are extremely beafy. These servers take the HTTP request from your user, and it forwards it to your origin server (a.k.a Discourse). The way this works is the reason why IP banning a user bans everyone. This is the same for phpBB, MyBB, WordPress, or anything else. In fact, if you had a setup like mine where you hide Discourse behind a local nginx reverse proxy so you can run other sites on your server, even without CloudFlare this issue would occur.
The way to get around this is to first:
- Make sure you’re not running a setup like me where you have Discourse running alongside another website, both hidden behind an nginx or haproxy reverse proxy. Because then, you won’t be IP-banning
localhost. The caveat for this is, if you do want to run another website on your domain, you’ll need another VPS entirely for that site.
- Disable CloudFlare routing in your DNS section for your domain and all subdomains that point to the same server. This will stop Discourse from IP-banning CloudFlare’s servers. As mentioned above, the caveat for doing this is you’ll lose their DDoS protection, caching, etc. And if you’re having a spam problem like you’re describing, that might be a big concern as many bots trying to spam your community can be enough to cause minor DDoS issues especially on VPSes with low amounts of CPU resources, RAM, or network speeds.
HOWEVER. If you’re sure you’re being attacked by bots, make sure that:
- Email confirmations are enabled and working - not sure if they can even be disabled, but, if they aren’t enabled, it makes it a lot easier to perform mass-spam attacks as accounts can be created extremely quickly and possibly even in bulk.
- Disable any form of anonymous posting/editing/etc. This makes it so users are required to login in order to post things.
- Make use of the Trust Levels system. Trust Levels are designed for exactly this reason. Limit the amount of replies and topic creations that a Trust Level 0 user can make per day, or even per hour. Make them wait a day if they hit their limit. If they’re a genuine user, the Trust Level system will automatically grant them Trust Level 1 and give them less harsh restrictions.
- Blacklist known spam email providers - mail.ru, 10minutemail (or whatever it is), etc. Discourse blacklists a few of them by default, but you may want to add more. Check the user details of your spammers and see what email addresses they’re using. If they’re not familiar (a.k.a they’re not using genuine providers like Gmail, Outlook, Yahoo, etc), blacklist 'em.
If you’re getting spam from a domain name of a company website and you know that’s a legit company, and that they don’t usually spam communities, let them know that their email system has potentially been compromised and used for spam. Like, if for some reason you start getting spam accounts from my site (watercolorgames.net), let me know just so I can deal with the headache and not you.
- Completely shut off local account sign-ups/sign-ins and rely on OAuth2 (a.k.a “Sign in with Google”, “Sign in with Twitter”, etc) completely. You may screw over existing genuine users by doing this, so only use it as a last resort if all else fails and the spam is just too chaotic and IP-banning isn’t working. It’s very hard for a robot to get through an OAuth2 signin flow, compared to local sign-ins at least, so it’ll definitely help.
- Not sure if Discourse has reCAPTCHA built in, but definitely consider enabling it if it is - or installing a plugin that enables that functionality. That’ll make it CONSIDERABLY harder for bots to sign up for your site and spam it. ReCAPTCHA is so strict at times that I’ve had to complete a picture puzzle even when I was signed into Google and verified as human - simply because I was doing things over a Remote Desktop connection and the mouse movement didn’t look exactly human. (Yes, reCAPTCHA tracks the user’s mouse movement for quirks only recreatable by a human hand, and uses that as verification of the fact that you are a carbon-based life form and not a silicon-based artificial life form.)
Also, if your spammer problem is in fact caused by humans, there’s a good chance you may have angered some people on the Internet. Happens to the best of us. [cough]SpamSyndicate and ShiftOS[/cough]. You may be dealing with dedicated trolls. Don’t feed the troll - a.k.a, don’t personally react to their messages even if they threaten you. Ignore it, as hard as it may be to do so, and just keep banning and blacklisting. Like a school bully, if you don’t give a personal reaction that’s entertaining to them, they will eventually give up on you. The only difference between an Internet troll and a school bully is that you won’t ever walk away with a physical injury (unless they SWAT you, but that’s only possible if you’ve been doxxed or you made your home address public. I don’t think there’s ever been a case of a Discourse forum admin being SWATted or doxxed though so you’re probably good unless you seriously screwed some jerk over.)
Hope those tips help you out with your spam problem. Probably not the answer you were looking for, but, hopefully it helps someone.
Edit: Someone replied with another possible solution for getting around CloudFlare - if that works then, awesome but do keep that stuff I said in mind for the future if spam is still a problem!
Edit 2: Seems as though you can actually get the client’s IP address in nginx and pump it through to Discourse using
proxy_set_header X-Real-IP $remoteaddress; or whatever variable the client IP address is in, that should help with setups like mine when Cloudflare is disabled.