Initial commit

This commit is contained in:
libroot 2025-09-28 06:09:19 +00:00
commit e90ff542b0
8 changed files with 250 additions and 0 deletions

7
README Normal file
View file

@ -0,0 +1,7 @@
# Cloudflare Blocker extension
* Detects Cloudflare-related headers in outgoing requests.
* Blocks the request if Cloudflare is present.
* Toggle the blocker on/off via the extension popup.
Available from Mozilla Add-ons: [https://addons.mozilla.org/en-US/firefox/addon/cloudflare-blocker/](https://addons.mozilla.org/en-US/firefox/addon/cloudflare-blocker/)

69
background.js Normal file
View file

@ -0,0 +1,69 @@
let blockingEnabled = true;
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'toggleBlocking') {
blockingEnabled = message.enabled;
}
if (message.action === 'getBlockingState') {
sendResponse({ action: 'setBlockingState', enabled: blockingEnabled });
}
});
chrome.webRequest.onHeadersReceived.addListener(
function(details) {
if (!blockingEnabled) {
return { cancel: false };
}
// These are Cloudflare's headers, taken from here:
// https://developers.cloudflare.com/fundamentals/reference/http-headers/
const cloudflare_headers = [
'cf-connecting-ip',
'cf-connecting-ipv6',
'cf-ew-via',
'cf-Pseudo-ipv4',
'cf-ray',
'cf-ipcountry',
'cf-visitor',
'cf-worker'
];
// You might want capture all headers prefixed with "cf-":
// const cf_header = details.responseHeaders.find(header =>
// header.name.toLowerCase().startsWith('cf-')
// );
const cf_header = details.responseHeaders.find(header =>
cloudflare_headers.includes(header.name.toLowerCase())
);
if (cf_header) {
console.log('Cloudflare header found:', cf_header);
const query_params = new URLSearchParams({
name: cf_header.name,
value: cf_header.value,
url: details.url
}).toString();
/*
* It would be cool to pass the tab URL in the query params, but how?
* When accessing chrome.tabs here, the active tab URL is "about:newtab".
* Because we block the request immediately and the tab URL state doesn't
* never update to the URL we tried to access. I'd like to pass the URL
* to the web.archive.org/tab_url_here in blocked.html.
* Email contact@libroot.org if you know a solution!
*/
// Redirect to our custom blocked.html page
const url = chrome.runtime.getURL('blocked.html') + '?' + query_params;
console.log('Redirecting to blocked page:', url);
chrome.tabs.update(details.tabId, { url: url });
// Block the request, reject Cloudflare!
return { cancel: true };
}
},
{ urls: ['<all_urls>'] },
['blocking', 'responseHeaders']
);

40
blocked.html Normal file
View file

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cloudflare page blocked</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
text-align: center;
}
h1 {
color: red;
}
a {
color: blue;
text-decoration: none;
}
</style>
</head>
<body>
<h1>This page has been blocked by the Cloudflare Blocker extension due to a Cloudflare header.</h1>
<p>
<strong>Blocked Header:</strong>
<pre id="header_info">Loading...</pre>
</p>
<p>
<strong>Blocked response URL:</strong>
<pre id="url">Loading...</pre>
</p>
<br>
<p>You can probably view the page on the <a href="https://web.archive.org" target="_blank">Wayback Machine</a>.</p>
<script src="blocked.js"></script>
</body>
</html>

21
blocked.js Normal file
View file

@ -0,0 +1,21 @@
function getUrlParams() {
const urlParams = new URLSearchParams(window.location.search);
return {
name: urlParams.get('name'),
value: urlParams.get('value'),
url: urlParams.get('url')
};
}
document.addEventListener('DOMContentLoaded', function() {
const params = getUrlParams();
if (params.name && params.value) {
const header_info = `Name: ${params.name}\nValue: ${params.value}`;
document.getElementById('header_info').textContent = header_info;
}
if (params.url) {
document.getElementById('url').textContent = params.url;
}
});

BIN
icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

28
manifest.json Normal file
View file

@ -0,0 +1,28 @@
{
"name": "Cloudflare Blocker",
"version": "1.0.0",
"author": "libroot.org",
"developer": {
"name": "libroot",
"url": "https://libroot.org/posts/Cloudflare-Blocker-Firefox-extension"
},
"description": "Blocks requests if they have Cloudflare's headers, and shows a blocked page.",
"manifest_version": 2,
"permissions": [
"webRequest",
"webRequestBlocking",
"tabs",
"<all_urls>"
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_popup": "popup.html",
"default_icon": "icons/icon.png"
},
"web_accessible_resources": [
"blocked.html"
]
}

53
popup.html Normal file
View file

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cloudflare Blocker</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 10px;
width: 200px;
}
#toggle {
width: 50px;
height: 25px;
position: relative;
border-radius: 15px;
background-color: #ccc;
cursor: pointer;
}
#toggle .slider {
width: 25px;
height: 25px;
border-radius: 50%;
background-color: white;
position: absolute;
top: 0;
transition: 0.3s;
}
#toggle.active {
background-color: #4CAF50;
}
#toggle.active .slider {
left: 25px;
}
#status {
margin-top: 10px;
font-size: 14px;
color: #333;
}
</style>
</head>
<body>
<h3>Cloudflare Blocker</h3>
<div id="toggle" class="active">
<div class="slider"></div>
</div>
<p id="status">Blocking is ON</p>
<script src="popup.js"></script>
</body>
</html>

32
popup.js Normal file
View file

@ -0,0 +1,32 @@
const toggle = document.getElementById('toggle');
const status = document.getElementById('status');
chrome.runtime.sendMessage({ action: 'getBlockingState' }, (response) => {
if (response && response.enabled !== undefined) {
const blockingEnabled = response.enabled;
if (blockingEnabled) {
toggle.classList.add('active');
status.textContent = 'Blocking is ON';
} else {
toggle.classList.remove('active');
status.textContent = 'Blocking is OFF';
}
}
});
toggle.addEventListener('click', function () {
const isActive = toggle.classList.toggle('active');
if (isActive) {
status.textContent = 'Blocking is ON';
} else {
status.textContent = 'Blocking is OFF';
}
chrome.runtime.sendMessage({
action: 'toggleBlocking',
enabled: isActive
});
});