Cloudflare Tips and Tricks – 51 Security
Cloudflare is designed for easy setup. Anyone with a website and their own domain can use Cloudflare regardless of their platform choice. Cloudflare doesn’t require additional hardware, software, or changes to your code. Cloudflare stops malicious traffic before it reaches your origin web server. Cloudflare analyzes potential threats in visitor requests based on a number of characteristics:
- visitor’s IP address,
- resources requested,
- request payload and frequency, and
- customer-defined firewall rules.
By default, Cloudflare allows you to create five active firewall rules. In this post, I lists some useful firewall rules for different use cases.
Diagrams
Cloudflare security diagram:
Troubleshooting
https://51sec.org/cdn-cgi/trace
fl=684f51 h=51sec.org ip=16.3.19.10 ts=1723310073.493 visit_scheme=https uag=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 colo=YYZ sliver=none http=http/3 loc=CA tls=TLSv1.3 sni=plaintext warp=off gateway=off rbi=off kex=X25519K1be76811Drat00
Access Cloudflare Dashboard – Firewall Page
Steps:
- Login your Cloudflare dashboard
- Select the domain name you want to configure Firewall Rules
- Click Firewall from the tools at the top
- Click Firewall Rules
Firewall Page at Cloudflare dashboard:
Firewall Settings – Security Level Explaination
Threat Score based on Cloudflare Doc as configured by Security Level is based on:
Security Level | Threat Scores | Description |
---|---|---|
Essentially off | greater than 49 | Only challenges IP addresses with the worst reputation. |
Low | greater than 24 | Challenges only the most threatening visitors. |
Medium | greater than 14 | Challenges both moderate threat visitors and the most threatening visitors. |
High | greater than 0 | Challenges all visitors that exhibit threatening behavior within the last 14 days. |
I’m Under Attack! | N/A | Only for use if your website is currently under a DDoS attack. |
Cloudflare sets Security Level to Medium by default. Change the Security Level settings via the Cloudflare Firewall app under the Settings tab.
Challenge Low Risk and Higher IP but Allow Known Bots
Bad IP:
A request that came from an IP address that is not trusted by Cloudflare based on the Threat Score.
Based on default settings (Medium security level):
Challenges both moderate threat visitors and the most threatening visitors which threat score is higher than 14.
Here are some common agreed in Cloudflare community when using Threat score to create firewall rule
0 indicates low risk as determined by Cloudflare. Values above 10 may represent spammers or bots, and values above 40 point to bad actors on the Internet. It is rare to see values above 60, so tune your firewall rules to challenge those above 10, and to block those above 50.
My rule setting:
If access request is having Threat Score greater than or equal to 10, and it is not from Known bots, the access request will be challenged by Captcha.
Bypass CloudFlare Cache From Your Browser For Testing
Verify CloudFlare Cache Status
From Google Chrome Browser – F12 or Ctrl+Shift+I (Developer Tools) – Network tab – Filter by Doc
Check File Name’s Response Header – > cf-cache-status
It should show either bypass, hit, or DYNAMIC.
Dsiable Cache
Security – WAF – Rate Limiting Rules
Received huge amount of access requests to my workers. Daily requets limitation 100k was reached in less than an hour.
One way to defend that is to enable rate limiting rule.
Cloudflare Proxy Another Website
Method 1: Proxy Site
// 替换成你想镜像的站点
const upstream = 'netsec.alwaysdata.net'
// Custom pathname for the upstream website.
const upstream_path = '/'
// 如果那个站点有专门的移动适配站点,否则保持和上面一致
const upstream_mobile = 'netsec.alwaysdata.net'
// 你希望禁止哪些国家访问
const blocked_region = ['RU']
// 禁止自访问
const blocked_ip_address = ['0.0.0.0', '127.0.0.1']
// 替换成你想镜像的站点
const replace_dict = {
'$upstream': '$custom_domain',
'//netsec.alwaysdata.net': ''
}
//以下内容都不用动
addEventListener('fetch', event => {
event.respondWith(fetchAndApply(event.request));
})
async function fetchAndApply(request) {
const region = request.headers.get('cf-ipcountry').toUpperCase();
const ip_address = request.headers.get('cf-connecting-ip');
const user_agent = request.headers.get('user-agent');
let response = null;
let url = new URL(request.url);
let url_host = url.host;
if (url.protocol == 'http:') {
url.protocol = 'https:'
response = Response.redirect(url.href);
return response;
}
if (await device_status(user_agent)) {
upstream_domain = upstream
} else {
upstream_domain = upstream_mobile
}
url.host = upstream_domain;
if (blocked_region.includes(region)) {
response = new Response('Access denied: WorkersProxy is not available in your region yet.', {
status: 403
});
} else if(blocked_ip_address.includes(ip_address)){
response = new Response('Access denied: Your IP address is blocked by WorkersProxy.', {
status: 403
});
} else{
let method = request.method;
let request_headers = request.headers;
let new_request_headers = new Headers(request_headers);
new_request_headers.set('Host', upstream_domain);
new_request_headers.set('Referer', url.href);
let original_response = await fetch(url.href, {
method: method,
headers: new_request_headers
})
let original_response_clone = original_response.clone();
let original_text = null;
let response_headers = original_response.headers;
let new_response_headers = new Headers(response_headers);
let status = original_response.status;
new_response_headers.set('access-control-allow-origin', '*');
new_response_headers.set('access-control-allow-credentials', true);
new_response_headers.delete('content-security-policy');
new_response_headers.delete('content-security-policy-report-only');
new_response_headers.delete('clear-site-data');
const content_type = new_response_headers.get('content-type');
if (content_type.includes('text/html') && content_type.includes('UTF-8')) {
original_text = await replace_response_text(original_response_clone, upstream_domain, url_host);
} else {
original_text = original_response_clone.body
}
response = new Response(original_text, {
status,
headers: new_response_headers
})
}
return response;
}
async function replace_response_text(response, upstream_domain, host_name) {
let text = await response.text()
var i, j;
for (i in replace_dict) {
j = replace_dict[i]
if (i == '$upstream') {
i = upstream_domain
} else if (i == '$custom_domain') {
i = host_name
}
if (j == '$upstream') {
j = upstream_domain
} else if (j == '$custom_domain') {
j = host_name
}
let re = new RegExp(i, 'g')
text = text.replace(re, j);
}
return text;
}
async function device_status (user_agent_info) {
var agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
var flag = true;
for (var v = 0; v < agents.length; v++) { if (user_agent_info.indexOf(agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}
Method 2: Redirect
export default {
async fetch(request, env) {
try {
const { pathname } = new URL(request.url);
if (pathname.startsWith("/status")) {
const httpStatusCode = Number(pathname.split("/")[2]);
return Number.isInteger(httpStatusCode)
? fetch("https://http.cat/" + httpStatusCode)
: new Response("That's not a valid HTTP status code.");
}
return fetch("https://blog.51sec.org");
} catch(e) {
return new Response(err.stack, { status: 500 })
}
}
}
Cloudflare Workers Received Attacks
Received attacks to workers.
Post Comment