你的WordPress网站正在遭到DDoS和CC攻击?这应该是最划算的DDoS攻击防御方案

DDoS攻击防御是每个网站运维人员的必修课,因为DDoS和CC攻击是门槛非常低的网络攻击方式,以至于成为脚本小子的最爱,这种攻击方式通常被用于恶性商业竞争、炫耀式的恶作剧,或用于敲诈勒索等,其危害性是不容小觑的。如果你是一个小博客网站,却遭到不明缘由的DDoS或CC攻击的话,那么这对你好不容易积累起来的网站权重的打击是毁灭性的。一般情况下,如果你在使用国内的VPS,会被直接打进黑洞清洗状态,一般持续2小时-12小时不等;如果你使用国外的VPS,一般会被打进黑洞半小时以上,期间你的网站主机商是不允许你重新上线的,除非你另外再开一台VPS。

网站防御DDoS和CC攻击不仅是大型网站的重要工作,也是小网站不可忽视的一项内容,但是这需要一定的技术门槛,我结合自己的理解和实践进行了总结,特此记录。

1、隐藏并保护源站IP

(1)泄漏源站IP的方式有哪些?

1)扫描全网IP数据库

它7×24小时扫描全网IP,可能你正好在添加DNS解析,而且还没有套上CDN而被扫描到了,于是它就会把你的域名和源站IP的对应关系添加到数据库保存。

原理:当我们在浏览器输入域名,浏览器通过HTTP(S)协议访问具体网站的通讯过程是通过查询DNS域名解析获得目标网站的IP地址,就相当于http(s)://IP:端口的形式(HTTP默认端口:80、HTTPS默认端口:443)向源站获取网站内容。如果你在浏览器直接输入形如“http(s)://IP:端口”的地址,如果得到回应,会显示你的SSL证书绑定的域名信息。如下图所示:

2)Wordpress评论邮件泄漏源站IP

因为Wordpress系统自动发送的提醒邮件会包含你源站IP信息,如下图所示:

 

3)站长工具IP查询

有些站长喜欢用站长工具查询网站域名,殊不知,你一旦查询之后,你的域名和IP的绑定关系就被记录了,而且会被搜索引擎收录。常用的站长工具如 站长之家“http://ping.chinaz.com/”、爱站网“http://ping.aizhan.com/”等。

(2)如何隐藏你的源站IP地址?

1)在启用CDN防护之前,我们使用http协议,而暂时不配置SSL证书,同时修改你远程VPS的SSH连接端口为不常用端口,然后设置防火墙规则为仅允许你的CDN服务商的节点IP访问源站,其它的请求全部阻断。防火墙规则设置脚本内容如下:

nano firewall.sh ##创建一个防火墙脚本
# 输入以下内容
#!/bin/bash
# Name : Anti IP Leakage
# Author: Zhys
# Date : 2019

# 禁止来自IPv4的所有HTTP/S访问请求
iptables -I INPUT -p tcp --dport 80 -j DROP
iptables -I INPUT -p tcp --dport 443 -j DROP

# 对Cloudflare CDN IPv4地址开放HTTP/S入站访问
for i in `curl https://www.cloudflare.com/ips-v4`; do iptables -I INPUT -s $i -p tcp --dport 80 -j ACCEPT; done
for i in `curl https://www.cloudflare.com/ips-v4`; do iptables -I INPUT -s $i -p tcp --dport 443 -j ACCEPT; done

# 禁止来自IPv6的所有HTTP/S访问请求
ip6tables -I INPUT -p tcp --dport 80 -j DROP
ip6tables -I INPUT -p tcp --dport 443 -j DROP

# 对Cloudflare CDN IPv6地址开放HTTP/S入站访问
for i in `curl https://www.cloudflare.com/ips-v6`; do ip6tables -I INPUT -s $i -p tcp --dport 80 -j ACCEPT; done
for i in `curl https://www.cloudflare.com/ips-v6`; do ip6tables -I INPUT -s $i -p tcp --dport 443 -j ACCEPT; done

# 保存iptables配置
iptables-save
ip6tables-save

# 注意:80/443为默认HTTP/S协议通讯使用端口,若实际应用有使用非80/443端口进行,请依葫芦画瓢自行修改脚本
# Ubuntu系统可以使用UFW则类似:for i in `curl https://www.cloudflare.com/ips-v4`; do ufw allow proto tcp from $i to any port 80; done
# 基于Linux系统兼容性考虑脚本使用iptables配置系统防火墙,请自行根据各自系统、防火墙不同做相应配置调整实施

# 按CTRL+X 保存即可

bash firewall.sh ##使防火墙生效

注意事项:这个需要你有CDN服务商的IP段,否则容易造成误伤,这样可以有效防止IP地址被类似于 censys 这样的网站扫描到。

2)临时使用无关域名和源站IP的SSL证书

如果你是在无法得到CDN提供商的IP段,而且仍然想要不被自动扫描程序监控到IP跟域名的关系,那么你先可以使用临时无关域名的SSL证书。当加上CDN之后,再重新更新SSL证书。这种操作你可以借助宝塔面板添加自定义的假SSL证书,总之都是为了隐藏域名跟IP地址的绑定关系。其实,对于一般小博客不用这么麻烦,被扫描到的概率非常低,而且你只是短暂的暴露,大约5分钟左右就够了。

如果以上方法都没有成功隐藏源站IP,那么很可能你的IP早已经泄漏过了。

2、隐藏网站程序特征

如果你在使用 WordPress,那么推荐你使用插件“Hide My WP Ghost Lite”,土豪用户可以购买专业高级版,这可以有效防止针对 WordPress 程序的漏洞攻击,以及针对特定页面的CC攻击。

3、最大程度使网站静态化

如果你把网站的每一个页面全部静态化,然后开启 Cloudflare 缓存的“永久在线(Always Online)”,全站静态化缓存是最理想状态,这时候即使你源站关机也不影响用户访问。由于 Cloudflare 拥有超过35TB流量的防御能力,所以这时候你的网站约等于打不死。

4、开启 Cloudflare Workers 缓存

Cloudflare Workers 的缓存比一般的 CF 缓存加页面规则更有效,所以我们启用它。

(1)创建 Cloudflare Worker,代码如下:

// IMPORTANT: Either A Key/Value Namespace must be bound to this worker script
// using the variable name EDGE_CACHE. or the API parameters below should be
// configured. KV is recommended if possible since it can purge just the HTML
// instead of the full cache.
// API settings if KV isn't being used
const CLOUDFLARE_API = {
email: "你的邮箱", // From https://dash.cloudflare.com/profile
key: "全局 API Token", // Global API Key from https://dash.cloudflare.com/profile
zone: "对应域名的Zone ID" // "Zone ID" from the API section of the dashboard overview page https://dash.cloudflare.com/
};
// Default cookie prefixes for bypass
// 注意!!!!这里填写你的对应路径,若你没有修改过就保持这样,修改过了WP的评论等路径的在此更改对应的路径成为你的路径
const DEFAULT_BYPASS_COOKIES = [
"wp-",
"wordpress",
"comment_",
"woocommerce_",
"comments_"
];
//后面的不动就行了。
/**
* Main worker entry point. 
*/
addEventListener("fetch", event => {
const request = event.request;
let upstreamCache = request.headers.get('x-HTML-Edge-Cache');
// Only process requests if KV store is set up and there is no
// HTML edge cache in front of this worker (only the outermost cache
// should handle HTML caching in case there are varying levels of support).
let configured = false;
if (typeof EDGE_CACHE !== 'undefined') {
configured = true;
} else if (CLOUDFLARE_API.email.length && CLOUDFLARE_API.key.length && CLOUDFLARE_API.zone.length) {
configured = true;
}
// Bypass processing of image requests (for everything except Firefox which doesn't use image/*)
const accept = request.headers.get('Accept');
let isImage = false;
if (accept && (accept.indexOf('image/*') !== -1)) {
isImage = true;
}
if (configured && !isImage && upstreamCache === null) {
event.passThroughOnException();
event.respondWith(processRequest(request, event));
}
});
/**
* Process every request coming through to add the edge-cache header,
* watch for purge responses and possibly cache HTML GET requests.
* 
* @param {Request} originalRequest - Original request
* @param {Event} event - Original event (for additional async waiting)
*/
async function processRequest(originalRequest, event) {
let cfCacheStatus = null;
const accept = originalRequest.headers.get('Accept');
const isHTML = (accept && accept.indexOf('text/html') >= 0);
let {response, cacheVer, status, bypassCache} = await getCachedResponse(originalRequest);
if (response === null) {
// Clone the request, add the edge-cache header and send it through.
let request = new Request(originalRequest);
request.headers.set('x-HTML-Edge-Cache', 'supports=cache|purgeall|bypass-cookies');
response = await fetch(request);
if (response) {
const options = getResponseOptions(response);
if (options && options.purge) {
await purgeCache(cacheVer, event);
status += ', Purged';
}
bypassCache = bypassCache || shouldBypassEdgeCache(request, response);
if ((!options || options.cache) && isHTML &&
originalRequest.method === 'GET' && response.status === 200 &&
!bypassCache) {
status += await cacheResponse(cacheVer, originalRequest, response, event);
}
}
} else {
// If the origin didn't send the control header we will send the cached response but update
// the cached copy asynchronously (stale-while-revalidate). This commonly happens with
// a server-side disk cache that serves the HTML directly from disk.
cfCacheStatus = 'HIT';
if (originalRequest.method === 'GET' && response.status === 200 && isHTML) {
bypassCache = bypassCache || shouldBypassEdgeCache(originalRequest, response);
if (!bypassCache) {
const options = getResponseOptions(response);
if (!options) {
status += ', Refreshed';
event.waitUntil(updateCache(originalRequest, cacheVer, event));
}
}
}
}
if (response && status !== null && originalRequest.method === 'GET' && response.status === 200 && isHTML) {
response = new Response(response.body, response);
response.headers.set('x-HTML-Edge-Cache-Status', status);
if (cacheVer !== null) {
response.headers.set('x-HTML-Edge-Cache-Version', cacheVer.toString());
}
if (cfCacheStatus) {
response.headers.set('CF-Cache-Status', cfCacheStatus);
}
}
return response;
}
/**
* Determine if the cache should be bypassed for the given request/response pair.
* Specifically, if the request includes a cookie that the response flags for bypass.
* Can be used on cache lookups to determine if the request needs to go to the origin and
* origin responses to determine if they should be written to cache.
* @param {Request} request - Request
* @param {Response} response - Response
* @returns {bool} true if the cache should be bypassed
*/
function shouldBypassEdgeCache(request, response) {
let bypassCache = false;
if (request && response) {
const options = getResponseOptions(response);
const cookieHeader = request.headers.get('cookie');
let bypassCookies = DEFAULT_BYPASS_COOKIES;
if (options) {
bypassCookies = options.bypassCookies;
}
if (cookieHeader && cookieHeader.length && bypassCookies.length) {
const cookies = cookieHeader.split(';');
for (let cookie of cookies) {
// See if the cookie starts with any of the logged-in user prefixes
for (let prefix of bypassCookies) {
if (cookie.trim().startsWith(prefix)) {
bypassCache = true;
break;
}
}
if (bypassCache) {
break;
}
}
}
}
return bypassCache;
}
const CACHE_HEADERS = ['Cache-Control', 'Expires', 'Pragma'];
/**
* Check for cached HTML GET requests.
* 
* @param {Request} request - Original request
*/
async function getCachedResponse(request) {
let response = null;
let cacheVer = null;
let bypassCache = false;
let status = 'Miss';
// Only check for HTML GET requests (saves on reading from KV unnecessarily)
// and not when there are cache-control headers on the request (refresh)
const accept = request.headers.get('Accept');
const cacheControl = request.headers.get('Cache-Control');
let noCache = false;
if (cacheControl && cacheControl.indexOf('no-cache') !== -1) {
noCache = true;
status = 'Bypass for Reload';
}
if (!noCache && request.method === 'GET' && accept && accept.indexOf('text/html') >= 0) {
// Build the versioned URL for checking the cache
cacheVer = await GetCurrentCacheVersion(cacheVer);
const cacheKeyRequest = GenerateCacheRequest(request, cacheVer);
// See if there is a request match in the cache
try {
let cache = caches.default;
let cachedResponse = await cache.match(cacheKeyRequest);
if (cachedResponse) {
// Copy Response object so that we can edit headers.
cachedResponse = new Response(cachedResponse.body, cachedResponse);
// Check to see if the response needs to be bypassed because of a cookie
bypassCache = shouldBypassEdgeCache(request, cachedResponse);
// Copy the original cache headers back and clean up any control headers
if (bypassCache) {
status = 'Bypass Cookie';
} else {
status = 'Hit';
cachedResponse.headers.delete('Cache-Control');
cachedResponse.headers.delete('x-HTML-Edge-Cache-Status');
for (header of CACHE_HEADERS) {
let value = cachedResponse.headers.get('x-HTML-Edge-Cache-Header-' + header);
if (value) {
cachedResponse.headers.delete('x-HTML-Edge-Cache-Header-' + header);
cachedResponse.headers.set(header, value);
}
}
response = cachedResponse;
}
} else {
status = 'Miss';
}
} catch (err) {
// Send the exception back in the response header for debugging
status = "Cache Read Exception: " + err.message;
}
}
return {response, cacheVer, status, bypassCache};
}
/**
* Asynchronously purge the HTML cache.
* @param {Int} cacheVer - Current cache version (if retrieved)
* @param {Event} event - Original event
*/
async function purgeCache(cacheVer, event) {
if (typeof EDGE_CACHE !== 'undefined') {
// Purge the KV cache by bumping the version number
cacheVer = await GetCurrentCacheVersion(cacheVer);
cacheVer++;
event.waitUntil(EDGE_CACHE.put('html_cache_version', cacheVer.toString()));
} else {
// Purge everything using the API
const url = "https://api.cloudflare.com/client/v4/zones/" + CLOUDFLARE_API.zone + "/purge_cache";
event.waitUntil(fetch(url,{
method: 'POST',
headers: {'X-Auth-Email': CLOUDFLARE_API.email,
'X-Auth-Key': CLOUDFLARE_API.key,
'Content-Type': 'application/json'},
body: JSON.stringify({purge_everything: true})
}));
}
}
/**
* Update the cached copy of the given page
* @param {Request} originalRequest - Original Request
* @param {String} cacheVer - Cache Version
* @param {EVent} event - Original event
*/
async function updateCache(originalRequest, cacheVer, event) {
// Clone the request, add the edge-cache header and send it through.
let request = new Request(originalRequest);
request.headers.set('x-HTML-Edge-Cache', 'supports=cache|purgeall|bypass-cookies');
response = await fetch(request);
if (response) {
status = ': Fetched';
const options = getResponseOptions(response);
if (options && options.purge) {
await purgeCache(cacheVer, event);
}
let bypassCache = shouldBypassEdgeCache(request, response);
if ((!options || options.cache) && !bypassCache) {
await cacheResponse(cacheVer, originalRequest, response, event);
}
}
}
/**
* Cache the returned content (but only if it was a successful GET request)
* 
* @param {Int} cacheVer - Current cache version (if already retrieved)
* @param {Request} request - Original Request
* @param {Response} originalResponse - Response to (maybe) cache
* @param {Event} event - Original event
* @returns {bool} true if the response was cached
*/
async function cacheResponse(cacheVer, request, originalResponse, event) {
let status = "";
const accept = request.headers.get('Accept');
if (request.method === 'GET' && originalResponse.status === 200 && accept && accept.indexOf('text/html') >= 0) {
cacheVer = await GetCurrentCacheVersion(cacheVer);
const cacheKeyRequest = GenerateCacheRequest(request, cacheVer);
try {
// Move the cache headers out of the way so the response can actually be cached.
// First clone the response so there is a parallel body stream and then
// create a new response object based on the clone that we can edit.
let cache = caches.default;
let clonedResponse = originalResponse.clone();
let response = new Response(clonedResponse.body, clonedResponse);
for (header of CACHE_HEADERS) {
let value = response.headers.get(header);
if (value) {
response.headers.delete(header);
response.headers.set('x-HTML-Edge-Cache-Header-' + header, value);
}
}
response.headers.delete('Set-Cookie');
response.headers.set('Cache-Control', 'public; max-age=315360000');
event.waitUntil(cache.put(cacheKeyRequest, response));
status = ", Cached";
} catch (err) {
// status = ", Cache Write Exception: " + err.message;
}
}
return status;
}
/******************************************************************************
* Utility Functions
*****************************************************************************/
/**
* Parse the commands from the x-HTML-Edge-Cache response header.
* @param {Response} response - HTTP response from the origin.
* @returns {*} Parsed commands
*/
function getResponseOptions(response) {
let options = null;
let header = response.headers.get('x-HTML-Edge-Cache');
if (header) {
options = {
purge: false,
cache: false,
bypassCookies: []
};
let commands = header.split(',');
for (let command of commands) {
if (command.trim() === 'purgeall') {
options.purge = true;
} else if (command.trim() === 'cache') {
options.cache = true;
} else if (command.trim().startsWith('bypass-cookies')) {
let separator = command.indexOf('=');
if (separator >= 0) {
let cookies = command.substr(separator + 1).split('|');
for (let cookie of cookies) {
cookie = cookie.trim();
if (cookie.length) {
options.bypassCookies.push(cookie);
}
}
}
}
}
}
return options;
}
/**
* Retrieve the current cache version from KV
* @param {Int} cacheVer - Current cache version value if set.
* @returns {Int} The current cache version.
*/
async function GetCurrentCacheVersion(cacheVer) {
if (cacheVer === null) {
if (typeof EDGE_CACHE !== 'undefined') {
cacheVer = await EDGE_CACHE.get('html_cache_version');
if (cacheVer === null) {
// Uninitialized - first time through, initialize KV with a value
// Blocking but should only happen immediately after worker activation.
cacheVer = 0;
await EDGE_CACHE.put('html_cache_version', cacheVer.toString());
} else {
cacheVer = parseInt(cacheVer);
}
} else {
cacheVer = -1;
}
}
return cacheVer;
}
/**
* Generate the versioned Request object to use for cache operations.
* @param {Request} request - Base request
* @param {Int} cacheVer - Current Cache version (must be set)
* @returns {Request} Versioned request object
*/
function GenerateCacheRequest(request, cacheVer) {
let cacheUrl = request.url;
if (cacheUrl.indexOf('?') >= 0) {
cacheUrl += '&';
} else {
cacheUrl += '?';
}
cacheUrl += 'cf_edge_cache_ver=' + cacheVer;
return new Request(cacheUrl);
}

(2)为选择域名的 Worker 规则添加路由

我们点击要添加规则的域名,然后点击“Workers”菜单,点击右侧的“添加路由”按钮,弹出添加 Cloudflare Worker 规则的窗口。具体设置如下图所示:

以上添加的 Cloudflare Worker 规则代码需要填写注册 Cloudflare 账户的电子邮件地址(email)、“区域 ID (key)”和“全局 API (zone)”。如下图所示:

Cloudflare Worker 规则代码内容如下:

#!/bin/sh
#
#cdn.bnxb.com自动开盾对接脚本,后续功能实时完善更新,请详见网站通知,其他不需要改,仅需要改下面三行参数
#
token="您的TOPKEN" #本站生成的TOKEN内容【需要改成分配给您的实际KEY】
mode="load" #判断服务器负载方式 load负载法 cpu CPU百分比法 只能选一个
keeptime=1800 #开盾负载下降后持续多少秒,进行尝试关盾
if [ "$mode" = "cpu" ];
then
check=90 #5秒内CPU连续超过80 则开盾【可以根据您的服务器负荷情况调整】
#系统空闲时间
TIME_INTERVAL=5
time=$(date "+%Y-%m-%d %H:%M:%S")
LAST_CPU_INFO=$(cat /proc/stat | grep -w cpu | awk '{print $2,$3,$4,$5,$6,$7,$8}')
LAST_SYS_IDLE=$(echo $LAST_CPU_INFO | awk '{print $4}')
LAST_TOTAL_CPU_T=$(echo $LAST_CPU_INFO | awk '{print $1+$2+$3+$4+$5+$6+$7}')
sleep ${TIME_INTERVAL}
NEXT_CPU_INFO=$(cat /proc/stat | grep -w cpu | awk '{print $2,$3,$4,$5,$6,$7,$8}')
NEXT_SYS_IDLE=$(echo $NEXT_CPU_INFO | awk '{print $4}')
NEXT_TOTAL_CPU_T=$(echo $NEXT_CPU_INFO | awk '{print $1+$2+$3+$4+$5+$6+$7}')
#系统空闲时间
SYSTEM_IDLE=`echo ${NEXT_SYS_IDLE} ${LAST_SYS_IDLE} | awk '{print $1-$2}'`
#CPU总时间
TOTAL_TIME=`echo ${NEXT_TOTAL_CPU_T} ${LAST_TOTAL_CPU_T} | awk '{print $1-$2}'`
load=`echo ${SYSTEM_IDLE} ${TOTAL_TIME} | awk '{printf "%.2f", 100-$1/$2*100}'`
else
load=$(cat /proc/loadavg | colrm 5)
check=$(cat /proc/cpuinfo | grep "processor" | wc -l)
fi
if [ ! -f "status.txt" ];then
echo "" > status.txt
else
status=$(cat status.txt)
fi
now=$(date +%s)
time=$(date +%s -r status.txt)
echo "当前$mode负载:$load"
if [[ $status -eq 1 ]]
then
echo "当前开盾中"
else
echo "当前未开盾"
fi
newtime=`expr $now - $time`
closetime=`expr $keeptime - $newtime`
if [[ $load <$check ]]&&[[ $status -eq 1 ]]&&[[ $newtime -gt $keeptime ]] 
then
echo -e "\n$mode负载低于$check,当前已开盾超过半小时($newtime秒),尝试关盾"
url="https://cdn.bnxb.com/api/?token=$token&status=off" 
cResult=$(curl --insecure -X GET $url )
echo $cResult
if [[ $cResult -eq 1 ]]
then
echo 0 > status.txt
echo -e "\n关盾成功"
fi 
elif [[ $load <$check ]]
then
echo -e "\n$mode负载低于$check,不做任何改变,$newtime秒"
if [[ $status -eq 1 ]]
then
echo -e "将于$closetime秒后关盾"
fi 
exit
elif [[ $load >$check ]] && [[ $status -eq 1 ]] && [[ $newtime -gt $keeptime ]] 
then
echo -e "\n$mode负载高于$check,当前已开盾超过$newtime秒,盾无效,请联系管理员定制其他方案"
exit
elif [[ $load >$check ]] && [[ $status -eq 1 ]]
then
echo -e "\n$mode负载高于$check,当前已开盾($newtime秒),请再观察"
exit 
elif [[ $load >$check ]]
then
echo -e "\n$mode负载高于$check,开启防御规则" 
url="https://cdn.bnxb.com/api/?token=$token&status=on" 
cResult=$(curl --insecure -X GET $url )
echo $cResult
if [[ $cResult -eq 1 ]]
then
echo 1 > status.txt
echo -e "\n开盾成功"
fi 
else
echo 0 > status.txt 
fi

此规则需要配合Wordpress的 Cloudflare、Cloudflare Page Cache 或 WP Rocket 等具备自动管理 Cloudflare 边缘缓存页面功能的插件。

5、自动开启 Cloudflare 的5秒盾

对于防御 DDoS 和 CC 攻击,我这里推荐您使用通过 CloudFlare Partner 接入的 Cloudflare CDN,当然普通用户接触到的都是免费版,个别用户可以接触到特殊渠道的专业版。

最简单的做法就是开启Cloudflare的5秒盾,但是期间会非常影响用户体验,而且攻击者会在开启期间暂停攻击,一旦你撤掉5秒盾会再次攻击你的网站。这样搞你,是不是很烦?你不可能一直看着网站吧!没关系,你只需要通过调用 CloudFlare API 来实现自动判断攻击并开启5秒盾就行了,这样可以让你的网站时刻都处于防御状态。

具体操作方法如下:

登录笨牛网,然后打开“自动开盾[ON]”,使其处于绿色状态,然后下载自动开盾的脚本文件。如下图所示:

使用说明:请将SH文件下载打开,将$token=””;改成上面TOKEN内容,然后将文件放在您服务器上的任意地方,使用命令“chmod+x tz.sh”赋权,设置定时任务1分钟执行一次此SH文件代码。SH文件代码修改,如下图所示:

如果你正在使用宝塔面板,那么把以上代码添加到计划任务。如下图所示:

至此,设置完成。是不是很简单?您的网站已经可以防御绝大多数的DDoS和CC攻击了。

6、配置 Cloudflare 防火墙规则

(1)添加防火墙规则(Anti-DDoS)

添加防火墙规则主要用来防御DDoS攻击,具体操作步骤:我们选择要操作的域名,然后依次点击“防火墙”-“防火墙规则”-“创建防火墙规则”,进入规则详细设置页面。如下图所示:

以上规则设置确认无误后,点击“部署”完成添加防火墙规则。

(2)添加 Rate Limit 规则(Anti-CC)

添加 Rate Limit 规则主要用来防御CC攻击,具体操作步骤:我们选择要操作的域名,然后依次点击“防火墙”-“工具”-“启用速率限制”,进入规则详细设置页面。这个需要开通 Cloudflare Pro 套餐或单独用信用卡购买规则(0.05美元/10000次合法请求),已阻止的请求无需再付费。

信用卡购买规则有些不受控制,说不定一夜之间一套房就没了,所以还是开通 Cloudflare Pro 套餐比较可靠。

(3)添加 Cloudflare 托管规则(WAF)

Cloudflare 托管规则默认可以防御网络层和应用程序层的DDoS攻击,而且开通 Cloudflare Pro 套餐还可以防御针对特定 Web 应用程序的漏洞攻击,即WAF防御规则。

只有 Cloudflare Pro 套餐才可以使用全功能的防火墙规则配置,免费版无法使用 Rate Limit 和 Web应用程序防火墙等。

7、DDoS攻击防御/CC攻击防御结语

通过以上配置,你的Wordpress网站已经可以防御绝大多数的DDoS或CC攻击了,但是没有高级版的话,CC攻击防御功能主要依靠 Cloudflare 的自动5秒盾,也许这是最低成本的网站安全防御策略。如果你的网站不是那么值钱的话,我相信没有傻B愿意花更多的流量和时间来DDoS和CC攻击你了,因为这一点都不划算。

本篇博客内容主要是针对Wordpress网站安全方面的配置,用于网站被DDoS攻击防御和CC攻击防御;如果你想要对服务器性能和网站速度进行优化的话,我建议你参考文章 【VPS加速+WordPress网站优化】记一次网站数据迁移后的服务器加速优化过程通过 Cloudflare Partner 的CName方式接入并利用智能DNS解析为不同网络线路分配优选Cloudflare自定义IP节点实现全球CDN加速

本文由一灯不是和尚于2020年7月12日更新;如果您有什么意见或建议,请在文章下面评论区留言反馈。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注