From dd95ae2fe7d73f24f321c10ff9c3f3796000feec Mon Sep 17 00:00:00 2001 From: Anedroid Date: Sat, 15 Oct 2022 22:10:33 +0200 Subject: [PATCH] Initial commit --- .gitignore | 1 + background-script.js | 64 ++++++++++++++++++++++++ content-script.js | 115 +++++++++++++++++++++++++++++++++++++++++++ images/pure-evil.png | Bin 0 -> 2940 bytes manifest.json | 29 +++++++++++ 5 files changed, 209 insertions(+) create mode 100644 .gitignore create mode 100644 background-script.js create mode 100644 content-script.js create mode 100644 images/pure-evil.png create mode 100644 manifest.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..44ce34d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +web-ext-artifacts diff --git a/background-script.js b/background-script.js new file mode 100644 index 0000000..c0972e6 --- /dev/null +++ b/background-script.js @@ -0,0 +1,64 @@ +const cfRange = [ + '173.245.48.0/20', + '103.21.244.0/22', + '103.22.200.0/22', + '103.31.4.0/22', + '141.101.64.0/18', + '108.162.192.0/18', + '190.93.240.0/20', + '188.114.96.0/20', + '197.234.240.0/22', + '198.41.128.0/17', + '162.158.0.0/15', + '104.16.0.0/13', + '104.24.0.0/14', + '172.64.0.0/13', + '131.0.72.0/22' +]; +const cfRange6 = [ + '2400:cb00::/32', + '2606:4700::/32', + '2803:f800::/32', + '2405:b500::/32', + '2405:8100::/32', + '2a06:98c0::/29', + '2c0f:f248::/32' +]; +// TODO: implement IPv6 check +function ip42int(address) { + let _4 = address.split('.'); + let rtn = 0; + rtn += Number(_4[0]) * 0x100**3; + rtn += Number(_4[1]) * 0x100**2; + rtn += Number(_4[2]) * 0x100; + rtn += Number(_4[3]); + return rtn; +} +function calc4range(range) { + let base = range.split('/')[0]; + let prefix = Number(range.split('/')[1]); + let hostN = 2 ** (32-prefix); + let hostMin = ip42int(base); + hostMin -= hostMin % hostN--; + let hostMax = hostMin + hostN; + return [hostMin, hostMax]; +} +function in_4range(range, address) { + range = calc4range(range); + address = ip42int(address); + return address >= range[0] && address <= range[1]; +} +function is_cloudfucked(address) { + return cfRange.some(range => in_4range(range, address)); +} +browser.runtime.onConnect.addListener(function(port) { + port.onMessage.addListener(async function(data) { + console.log(`testing ${data.hostname}`); + let result = await browser.dns.resolve(data.hostname, ['disable_ipv6']); + let cloudfucked = result.addresses.some(ip => is_cloudfucked(ip)); + port.postMessage({ + "hostname": data.hostname, + "cloudfucked": cloudfucked + }); + }); +}); diff --git a/content-script.js b/content-script.js new file mode 100644 index 0000000..32212ac --- /dev/null +++ b/content-script.js @@ -0,0 +1,115 @@ +const gatekeepers = { + // "here-goes-hostname-of-your-local-searx-instance": "searx", + "html.duckduckgo.com": "duckduckgo" +}; +function prepare_searx(hosts, port) { + port.onMessage.addListener(function(data) { + hosts[data.hostname].cloudfucked = data.cloudfucked; + hosts[data.hostname].links.forEach(link => { + if (!link.querySelector('.cloudfuck_market')) { + let market = document.createElement('img'); + market.classList.add('cloudfuck_market'); + market.setAttribute('data-test', data.cloudfucked); + if (data.cloudfucked) { + market.alt = 'cloudflare'; + market.src = browser.runtime.getURL('images/pure-evil.png'); + market.style.height = '1em'; + market.style.marginRight = '0.5em'; + } + link.prepend(market); + } + }); + }); + function getPages() { + return document.querySelectorAll('#main_results hr').length + 1; + } + let pages = getPages(); + parse_searx(hosts, port); + addEventListener('scroll', function() { + if (getPages() > pages) { + parse_searx(hosts, port); + pages = getPages(); + } + }); +} +function parse_searx(hosts, port) { + Array.from(document.querySelectorAll('.result-default')) + .forEach(function(el) { + let link = el.querySelector('a'); + let hostname = new URL(link.href).hostname; + if (!(hostname in hosts)) { + hosts[hostname] = { + "links": [link], + "cloudfucked": null + }; + } else { + hosts[hostname].links.push(link); + } + }); + for (hostname in hosts) { + let host = hosts[hostname]; + if (host.cloudfucked === null) { + port.postMessage({ + "hostname": hostname + }); + } + } +} +// TODO: optimize code for search engines modules +function prepare_duckduckgo(hosts, port) { + port.onMessage.addListener(function(data) { + hosts[data.hostname].cloudfucked = data.cloudfucked; + hosts[data.hostname].links.forEach(link => { + if (!link.querySelector('.cloudfuck_market')) { + let market = document.createElement('img'); + market.classList.add('cloudfuck_market'); + market.setAttribute('data-test', data.cloudfucked); + if (data.cloudfucked) { + market.alt = 'cloudflare'; + market.src = browser.runtime.getURL('images/pure-evil.png'); + market.style.height = '1em'; + market.style.marginRight = '0.5em'; + } + link.prepend(market); + } + }); + }); + parse_duckduckgo(hosts, port); +} +function parse_duckduckgo(hosts, port) { + Array.from(document.querySelectorAll('.result__a')) + .forEach(function(link) { + let hostname = new URL(link.href).hostname; + if (!(hostname in hosts)) { + hosts[hostname] = { + "links": [link], + "cloudfucked": null + }; + } else { + hosts[hostname].links.push(link); + } + }); + for (hostname in hosts) { + let host = hosts[hostname]; + if (host.cloudfucked === null) { + port.postMessage({ + "hostname": hostname + }); + } + } +} + +let hosts = []; +let port = browser.runtime.connect(); +switch (gatekeepers[location.hostname]) { +case 'duckduckgo': + if (document.body.classList.contains('body--html')) { + prepare_duckduckgo(hosts, port); + } + break; +case 'searx': + if (document.body.classList.contains('results_endpoint')) { + prepare_searx(hosts, port); + } + break; +} diff --git a/images/pure-evil.png b/images/pure-evil.png new file mode 100644 index 0000000000000000000000000000000000000000..b062c2237dc6d5b6c718dc14513c350a5860371f GIT binary patch literal 2940 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 A_y7O^ literal 0 HcmV?d00001 diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..354ceb2 --- /dev/null +++ b/manifest.json @@ -0,0 +1,29 @@ +{ + "manifest_version": 2, + "name": "Cloudfuck", + "version": "1.0", + "description": "Adds an icons next to the search results to indicate pages that uses Cloudflare. Detection is performed by checking a DNS record.", + "browser_specific_settings": { + "gecko": { + "id": "{66abaf41-20a3-48da-bafb-1eef7f75ec57}" + } + }, + "icons": { + "64": "images/pure-evil.png" + }, + "permissions": [ + "dns" + ], + "background": { + "scripts": ["background-script.js"] + }, + "content_scripts": [ + { + "matches": [""], + "js": ["content-script.js"] + } + ], + "web_accessible_resources": [ + "images/check.png" + ] +}