服务器遭攻击致Node.js与MongoDB连接超时,求解决方案
Hey, sorry to hear about that attack and the frustrating MongoDB connection timeout issue—let’s walk through how to fix this and stop it from happening again.
First, let’s recap what’s happening here: Those malicious scans (looking for PHP vulnerabilities, .git files, etc.) are likely overwhelming your Node.js process or exhausting the MongoDB connection pool, leading to unhandled errors that freeze the connection logic. Since your app wasn’t handling these connection failures properly, it couldn’t recover on its own until you manually restarted it.
Here’s your action plan:
1. Block Malicious Requests at the Nginx Level
First line of defense—stop bad traffic before it hits your Node app. From your logs, there are tons of repeated scans for paths like /solr/, /.git/, /wp-login.php, and PHP exploit endpoints. Add these rules to your Nginx config to drop those requests immediately:
location ~* (/solr/|/.git/|/wp-login.php|/GponForm/|/vendor/phpunit/) { return 444; # Drops the connection without responding }
Also, set up fail2ban to auto-ban IPs that flood your server with invalid requests. Configure it to watch Nginx’s error log and block IPs that trigger multiple 404s in a short window (e.g., 10+ in 1 minute). This will shut down automated scanners fast.
2. Fix Node.js/Mongoose Connection Handling & Error Resilience
Your logs show unhandled Promise rejections and uncaught connection errors—these are what’s causing your process to freeze instead of recovering. Tweak your Mongoose setup with these critical fixes:
- Limit the connection pool size to match your Node server’s resources (1GB RAM =
poolSize: 5-10is reasonable) - Enable auto-reconnection with aggressive retry logic
- Add proper error listeners to avoid unhandled crashes
- Shorten connection timeouts so your app doesn’t hang waiting for a dead connection
Example code for your Mongoose connection:
const mongoose = require('mongoose'); const mongoOptions = { poolSize: 8, autoReconnect: true, reconnectTries: Number.MAX_VALUE, // Retry forever reconnectInterval: 1000, // Retry every 1s serverSelectionTimeoutMS: 5000, // Fail fast if no server found connectTimeoutMS: 3000, }; mongoose.connect('mongodb://your-mongo-node-ip:27017/your-db', mongoOptions); // Add connection event handlers mongoose.connection.on('error', (err) => { console.error(`MongoDB Error: ${err.message}`); }); mongoose.connection.on('disconnected', () => { console.log('MongoDB disconnected—retrying connection...'); }); mongoose.connection.on('reconnected', () => { console.log('MongoDB reconnected successfully!'); });
Also, wrap all database operations in try/catch blocks or use .catch() on Promises to handle individual query failures without taking down the whole app.
3. Upgrade to PM2 for Smarter Process Management
You’re using forever, but it’s not handling the recovery well (127 restarts and still stuck). Switch to PM2—it’s more robust for production Node apps, with features like:
- Auto-restart on crash or memory limit breach
- Process monitoring
- Log management
- Startup scripts for server reboots
Install and configure it like this:
# Install PM2 globally npm install -g pm2 # Start your app with a name pm2 start index.js --name "your-app-name" # Set PM2 to start on server boot pm2 startup # Save your PM2 config pm2 save
Create an ecosystem.config.js file to add memory-based restart rules (critical for preventing frozen processes):
module.exports = { apps: [{ name: 'your-app-name', script: 'index.js', autorestart: true, max_memory_restart: '800M', // Restart if process uses >800MB RAM env: { NODE_ENV: 'production' } }] };
Start with this config using pm2 start ecosystem.config.js.
4. Lock Down MongoDB Access
Don’t let anyone but your Node server talk to MongoDB:
- On your MongoDB droplet, use
ufwto whitelist only your Node server’s IP for port 27017:
sudo ufw allow from [your-node-droplet-ip] to any port 27017 sudo ufw enable
- Enable authentication in MongoDB: Edit
/etc/mongod.confto add:
security: authorization: enabled
Restart MongoDB, then create a dedicated app user with only the permissions it needs (never use the admin user for your app). This prevents any unauthorized access even if a scanner gets through.
5. Add Monitoring & Alerts
Set up basic monitoring to catch issues before they take down your app:
- Use
pm2 monitto keep an eye on your Node process’s CPU and memory usage. - For MongoDB, use
mongostatto track connection counts, query times, and server load. - For longer-term monitoring, set up tools like Prometheus + Grafana to visualize metrics and trigger alerts (e.g., alert you if MongoDB connection count spikes or Node process memory stays high).
With these steps, you’ll block most malicious traffic, make your app resilient to connection failures, and ensure it recovers automatically without manual intervention.
内容的提问来源于stack exchange,提问作者PennyWise

