require('dotenv').config(); const axios = require('axios').default; const fs = require('fs'); const Discord = require('discord.js'); const API_BASE_URL = 'https://api.cloudflare.com/client/v4'; const { CF_TOKEN, CF_ZONES_BLACKLIST, WEBHOOK_ID, WEBHOOK_SECRET } = process.env; if (!CF_TOKEN) return console.log("Error: Env var 'CF_TOKEN' is not set"); if (!WEBHOOK_ID) return console.log("Error: Env var 'WEBHOOK_ID' is not set"); if (!WEBHOOK_SECRET) return console.log("Error: Env var 'WEBHOOK_SECRET' is not set"); if (CF_ZONES_BLACKLIST) console.log("Info: 'CF_ZONES_BLACKLIST' is set"); const client = new Discord.WebhookClient(WEBHOOK_ID, WEBHOOK_SECRET); const ZONES_BLACKLIST = CF_ZONES_BLACKLIST?.split(',') || []; async function refresh(zone) { if (!fs.existsSync('./last_request')) await fs.promises.writeFile('./last_request', '' + (Date.now() - (1000 * 60 * 60 * 24) + 10000)); let lowerDate = new Date(); let upperDate = new Date(); lowerDate.setTime(await fs.promises.readFile('./last_request')); if (upperDate.getTime() - lowerDate.getTime() > 1000 * 60 * 60 * 24) lowerDate.setTime((Date.now() - (1000 * 60 * 60 * 24) + 10000)); let payload = `{ "query": "query ListFirewallEvents($zoneTag: string, $filter: FirewallEventsAdaptiveFilter_InputObject) { viewer { zones(filter: { zoneTag: $zoneTag }) { firewallEventsAdaptive( filter: $filter limit: 10 orderBy: [datetime_DESC] ) { action clientCountryName clientIP clientIPClass clientRequestHTTPHost clientRequestHTTPMethodName clientRequestScheme clientRequestPath clientRequestQuery datetime source userAgent clientRefererHost clientRefererPath ruleId } } } }", "variables": { "zoneTag": "${zone.id}", "filter": { "datetime_geq": "${lowerDate.toISOString()}", "datetime_leq": "${upperDate.toISOString()}" } } }`.replace(/\n/g, ''); let res = await axios.post( `${API_BASE_URL}/graphql/`, payload, { headers: { 'Authorization': `Bearer ${CF_TOKEN}` } } ); let eventsPerZone = res.data.data?.viewer?.zones; if (!(eventsPerZone instanceof Array)) return console.log(res.data); await fs.promises.writeFile('./last_request', '' + upperDate.getTime()); eventsPerZone.forEach(events => { events.firewallEventsAdaptive.forEach(event => { console.log(`[${zone.name}] Info: New firewall event`); client.send( new Discord.MessageEmbed() .setTitle('Retard deflected') .setColor('#f6821f') .setAuthor(`Cloudflare - ${event.clientRequestHTTPHost || zone.name}`, 'https://pbs.twimg.com/profile_images/1313131647315910666/opulcRqc.jpg') .setDescription(`${event.source} - ${event.ruleId}`) .addField('Firewall Action', event.action, true) .addField('IP Address', `${event.clientIP} (${event.clientCountryName}` + `${event.clientIPClass != 'unknown' ? ` - ${event.clientIPClass}` : ''})`, true) .addField('\u200b', '\u200b') .addField('Request', `${event.clientRequestHTTPMethodName} ${event.clientRequestPath}${event.clientRequestQuery}` + `${event.clientRefererHost ? `\nReferer: ${event.clientRefererHost}${event.clientRefererPath}` : ''}`, true) .addField('User Agent', `${event.userAgent}`, true) .setTimestamp(event.datetime) ) }); }); } (async () => { let { data: zones } = await axios.get(`${API_BASE_URL}/zones`, { headers: { 'Authorization': 'Bearer ' + CF_TOKEN } }); if (!zones.result) return console.log(zones); let total = 0; zones.result.forEach(async zone => { if (ZONES_BLACKLIST.indexOf(zone.id) == -1) { total++; refresh(zone); setInterval(() => refresh(zone), 1000 * 15); } }); console.log(`Info: Monitoring ${total} zone${total != 1 ? 's' : ''}`); })();