Initial commit
This commit is contained in:
commit
e90ff542b0
8 changed files with 250 additions and 0 deletions
7
README
Normal file
7
README
Normal 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
69
background.js
Normal 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
40
blocked.html
Normal 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
21
blocked.js
Normal 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
BIN
icons/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
28
manifest.json
Normal file
28
manifest.json
Normal 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
53
popup.html
Normal 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
32
popup.js
Normal 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
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue