js/abuse.js (309 lines of code) (raw):

const blocklist_url = 'https://blocky.apache.org/all'; let blocks = []; const block_rules = { "BL001": { "title": "More than 100,000 builds.apache.org visits per 12 hours", "description": "" }, "BL002": { "title": "More than 2,500 rate-limited (code 429) responses not honored", "description": "Many of our services make use of rate-limiting for compute or data intensive tasks, and will respond with a 429 HTTP response code (Too Many Requests).\nUsers of our services are expected to detect rate-limiting responses and act accordingly, slowing down their request rate." }, "BL003": { "title": "More than 25,000 JIRA pageviews per hour", "description": "" }, "BL004": { "title": "More than 200,000 pageviews on any box in a day (except svn)", "description": "" }, "BL005": { "title": "More than 100,000 Confluence pageviews per day", "description": "" }, "BL006": { "title": "More than 100,000 repository.a.o visits per day", "description": "Neither repository.apache.org nor people.apache.org are general-purpose Maven repositories,\n" + "and should only be used for the testing of pre-production ASF code artifacts.\n" + "\n" + "Maven Central is the correct public Java artifact service - https://mvnrepository.com/repos/central If you have been blocked due to excessive use of repository.apache.org, please evaluate your\n" + "systems and update your configuration to use Maven Central, not repository.apache.org or\n" + "people.apache.org, and let us know the results of your investigation.\n" + "\n" + "We will then review the ban on your IP address." }, "BL007": { "title": "More than 1,000 viewvc visits in a day", "description": "" }, "BL008": { "title": "More than 5,000 BugZilla visits per day", "description": "" }, "BL009": { "title": "More than 500 s.apache.org visits per day", "description": "" }, "BL010": { "title": "More than 50GB traffic in a day", "description": "" }, "BL011": { "title": "More than 25,000 visits to archive.apache.org within 24h", "description": "The ASF software archive at archive.apache.org is designed to make older versions of ASF software available for occasional download.\n" + "\n" + "It is not meant to be used as a CI target for specific versions of our software.\n" + "\n" + "Please cache such artifacts locally if you expect to use them in a CI context, either on disk or through a caching proxy." }, "BL012": { "title": "Excessive use of archive.a.o (>40GB per week)", "description": "The ASF software archive at archive.apache.org is designed to make older versions of ASF software available for occasional download.\n" + "\n" + "It is not meant to be used as a CI target for specific versions of our software.\n" + "\n" + "Please cache such artifacts locally if you expect to use them in a CI context, either on disk or through a caching proxy." }, "BL013": { "title": "BugZilla scraping (more than 800 requests in a single hour)", "description": "" }, "BL014": { "title": "Openoffice Wiki scraping (more than 1000 requests in a single hour)", "description": "" }, "BL015": { "title": "Suspicious Confluence traffic (more than 10 bad requests in 15min)", "description": "" }, "BL016": { "title": "Abusive Confluence wiki scans, Apache Struts security bulletin", "description": "" }, "BL017": { "title": "BugZilla scraping (more than 800 requests in a single hour)", "description": "" }, "BL018": { "title": "Too many 404s on repository.a.o (bad CI configs looking for maven repos)", "description": "Neither repository.apache.org nor people.apache.org are general-purpose Maven repositories, " + "and should only be used for the testing of pre-production ASF code artifacts.\n" + "\n" + "Maven Central is the correct public Java artifact service - https://mvnrepository.com/repos/central\n" + "\n" + "If you have been blocked due to excessive use of repository.apache.org, please evaluate your " + "systems and update your configuration to use Maven Central, not repository.apache.org or " + "people.apache.org, and let us know the results of your investigation. \n\n" + "We will then review the ban on your IP address." }, "BL019": { "title": "Too many 404s on people.a.o (bad CI configs looking for maven repos)", "description": "Neither repository.apache.org nor people.apache.org are general-purpose Maven repositories, " + "and should only be used for the testing of pre-production ASF code artifacts.\n" + "\n" + "Maven Central is the correct public Java artifact service - https://mvnrepository.com/repos/central\n" + "\n" + "If you have been blocked due to excessive use of repository.apache.org, please evaluate your " + "systems and update your configuration to use Maven Central, not repository.apache.org or " + "people.apache.org, and let us know the results of your investigation. \n\n" + "We will then review the ban on your IP address." }, "BL020": { "title": "Too many 404s on Apache NetBeans BugZilla (buglist.cgi scraper)", "description": "" }, "BL021": { "title": "Too many downloads via downloads.apache.org (more than 30,000 per day)", "description": "" }, "BL022": { "title": "Poorly configured Scrapy instance that does not respect robots.txt", "description": "" } } async function fetch_blocklist() { const rv = await fetch(blocklist_url); const json = await rv.json(); blocks = json.block; make_rule_accordion(document.getElementById('block_rules')); } function to_cidr(ip_or_range) { ip_or_range = ip_or_range.trim(); // remove any excess whitespace let cidr; if (ip_or_range.search("/") === -1) { // If not in CIDR notation, convert to it if (ip_or_range.search(":") !== -1) ip_or_range += "/128" // IPv6 else ip_or_range += "/32" // IPv4 } if (ip_or_range.search(":") === -1) { // IPv4 range try { cidr = ipnum.IPv4CidrRange.fromCidr(ip_or_range); } catch { } } else { // IPv6 ?? try { cidr = ipnum.IPv6CidrRange.fromCidr(ip_or_range); } catch { } } return cidr; } // Borrowed from Apache Pony Mail (incubating): const blockrule_re = new RegExp(/\b(BL\d\d\d)\b/, "m"); function fixup_urls(splicer) { if (typeof splicer == 'object') { return splicer; //splicer = splicer.innerText; } /* Array holding text and links */ let i, m, t, textbits, url, urls; textbits = []; /* Find the first link, if any */ i = splicer.search(blockrule_re); urls = 0; /* While we have more links, ... */ while (i !== -1) { urls++; /* Only parse the first 250 URLs... srsly */ if (urls > 250) { break; } /* Text preceding the link? add it to textbits frst */ if (i > 0) { t = splicer.substring(0, i); textbits.push(t); splicer = splicer.substring(i); } /* Find the URL and cut it out as a link */ m = splicer.match(blockrule_re); if (m) { url = `#${m[1]}`; i = m[1].length; t = splicer.substring(0, i); const linkel = document.createElement('a'); linkel.href = url; linkel.innerText = m[1]; linkel.className = 'blockrule'; // show the accordion item linkel.addEventListener('click', () => { document.getElementById(`collapse_${m[1]}`).className="accordion-collapse collapse show"; document.getElementById(`cb_${m[1]}`).className="accordion-button"; }) textbits.push(linkel); splicer = splicer.substring(i); } /* Find the next link */ i = splicer.search(blockrule_re); } /* push the remaining text into textbits */ textbits.push(splicer); return textbits; } function isArray(value) { return value && typeof value === 'object' && value instanceof Array && typeof value.length === 'number' && typeof value.splice === 'function' && !(value.propertyIsEnumerable('length')); } HTMLElement.prototype.inject = function (child) { let item, j, len; if (isArray(child)) { for (j = 0, len = child.length; j < len; j++) { item = child[j]; if (typeof item === 'string') { item = document.createTextNode(item); } this.appendChild(item); } } else { if (typeof child === 'string') { child = document.createTextNode(child); } this.appendChild(child); } return child; }; function is_blocked(e) { if (e) { if (e.key !== 'Enter') { console.log("moo") return } else { e.preventDefault(); } } const ip = document.getElementById('ip_address').value; const cidr = to_cidr(ip); if (!cidr) { alert("Please input a valid IPv4 or IPv6 address or range."); return } console.log(`Checking block list for occurrences of ${ip}...`); document.getElementById('block_results_table').style.visibility = "visible"; const bdiv = document.getElementById('block_results'); bdiv.innerText = ""; let c = 0; for (let block_entry of blocks) { let bcidr = to_cidr(block_entry.ip); if (bcidr.contains(cidr) || cidr.contains(bcidr)) { if (++c > 100) break const rdiv = document.createElement('tr'); // block match const cidrdiv = document.createElement('th'); cidrdiv.className = "cidrblock"; cidrdiv.scope = "row"; cidrdiv.innerText = block_entry.ip; rdiv.appendChild(cidrdiv); // timestamp const tdiv = document.createElement('td'); tdiv.className = "timeblock"; tdiv.innerText = new Date(block_entry.timestamp * 1000.0).toUTCString(); rdiv.appendChild(tdiv); // reason const reasondiv = document.createElement('td'); reasondiv.className = 'reasonblock'; reasondiv.inject(fixup_urls(block_entry.reason)); rdiv.appendChild(reasondiv); bdiv.appendChild(rdiv); } } if (bdiv.innerText === "") { document.getElementById('blockheads').style.visibility = "hidden"; bdiv.innerText = "We could not find any entries matching your IP address or range. If you are certain you are blocked from our resources, please see the paragraph below about "; const dlink = document.createElement('a'); dlink.innerText = "debugging connectivity issues"; dlink.href = "#debug"; bdiv.appendChild(dlink); } else { document.getElementById('blockheads').style.visibility = "visible"; } return false } async function fill_ip() { const response = await fetch('https://api.ipify.org/?format=json'); const data = await response.json(); document.getElementById('ip_address').value = data.ip; } function make_rule_accordion(adiv, rules) { adiv.innerText = ''; for (const [k, item] of Object.entries(block_rules)) { const idiv = document.createElement('div'); idiv.className = "accordion-item"; const hdiv = document.createElement('h2'); hdiv.className = "accordion-header"; hdiv.id = k; const bdiv = document.createElement('button'); bdiv.className = "accordion-button collapsed"; bdiv.id = `cb_${k}`; bdiv.type = "button"; bdiv.dataset.bsToggle = "collapse"; bdiv.dataset.bsTarget = `#collapse_${k}`; bdiv.style.fontWeight = "bold"; const kbd = document.createElement('code'); kbd.innerText = k; kbd.style.marginRight = '8px'; const title = document.createTextNode(" " + item.title); bdiv.appendChild(kbd); bdiv.appendChild(title); const cdiv = document.createElement('div'); cdiv.className = "accordion-collapse collapse"; cdiv.dataset.bsParent = 'block_rules'; bdiv.ariaExpanded = false; bdiv.ariaControls = `#collapse_${k}`; cdiv.id = `collapse_${k}`; idiv.appendChild(hdiv); hdiv.appendChild(bdiv); idiv.appendChild(cdiv); const tdiv = document.createElement('div'); tdiv.className = "accordion-body"; tdiv.innerText = item.description.length ? item.description : "No specific description is available for this rule at this time."; cdiv.appendChild(tdiv); adiv.appendChild(idiv); const advice = document.getElementById('general_block_advice').cloneNode(true); advice.style.display = "block"; tdiv.appendChild(advice); } } document.getElementById('ip_address').addEventListener(`keypress`, is_blocked);