前言 最近逛论坛的时候发现大家的网站都是被打过的,我就没被打
但为了保证网站的在线率,提前假定自己被ddos的情况。未雨绸缪总是好的
方法 js css资源cdn替换 针对我自己的网站来说,我是静态hexo,没有数据库,没必要去保护自己的接口
但还是有优化的空间,比如js,css 等资源可以使用国内的公共cdn
以我的主题Butterfly为例子
注意这里如果需要修改mainjs和maincss的话需要选择和主题对应版本号的js和css,或者你自己传到自己的对象存储中填写对应的链接
把需要用到的包通过国内cdn加速
就不要用什么jsdelivr.net什么的了,访问速度很慢,反向加速
可以看到优化后的速度很快,基本都是200ms以下的加载
具体请看别人写的目前可用 cdnjs, unpkg/npm, jsdelivr 国内镜像(前端文件镜像)
网站吞吐量 静态页面的吞吐量跟网络 , 4k硬盘io 息息相关,如果用的是和中国互联很差的如github page , cloudflare page (cloudflare其实还好点), vercel (有些地区被阻断了有的时候很卡),就优先换线路,或者直接备案域名找个国内存储桶托管(具体可以看3. 迁移halo到hexo,并部署到七牛云作静态资源博客
但我已经放弃了国内备案,这种做法就不适合我了
于是只能转而提升硬盘io,我测了一下我的serverless的硬盘4k只有惨淡的4MB/s
想要改善只能换服务器了,但转念一想得益于静态页面的资源很小,其实可以把静态资源全放到内存里永久缓存就行了
目前我找到的支持内存缓存的页面服务器是带插件的caddy ,即cache-handler ,但是需要手动编译,这里给出Dockerfile
FROM golang:1.23 -alpine AS builderRUN go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest RUN xcaddy build \ --with github.com/caddyserver/cache-handler \ --with github.com/darkweak/storages/badger/caddy FROM alpine:3.18 RUN apk add --no-cache ca-certificates COPY --from=builder /go/caddy /usr/bin/caddy RUN addgroup -S caddy && adduser -S caddy -G caddy WORKDIR /srv EXPOSE 8090 USER caddyCMD ["caddy" , "run" , "--config" , "/etc/caddy/Caddyfile" , "--adapter" , "caddyfile" ]
docker build . -t twoonefour/caddy
打包镜像即可开箱即用了
接下来是配置文件,根据cache-handler文档
{ cache { ttl 999999999s mode bypass_request badger { configuration { InMemory true # 这里很坑,根据文档是要填写ValueDir或path其中一个的。不要填ValueDir和path, 不然无法启用 } } } } :8090 { cache header -Vary header -Server header -Alt-Svc header -cache-control handle /css/* { reverse_proxy http://hexo.zeabur.internal:8080 { header_up Host {host} header_up X-Real-IP {remote} } } handle /js/* { reverse_proxy http://hexo.zeabur.internal:8080 { header_up Host {host} header_up X-Real-IP {remote} } } # 默认路由 handle { reverse_proxy http://hexo.zeabur.internal:8080 { header_up Host {host} header_up X-Real-IP {remote} } } }
请求一下显示hit和badger即可
为了排除延迟干扰,直接使用香港服务器请求网页,如下图,延迟只有1.19ms 并排除dns解析干扰
cat “43.199.8.212 www.voidval.com “ >> /etc/hosts
使用命令
curl -o /dev/null -s -w %{time_total}”\n” “https://www.voidval.com/css/index.css “
虽然只提升了20ms , 但如果面对磁盘性能瓶颈时候会有很大的提升(理论上
这样即便遇到ddos攻击,磁盘io也不会爆满导致网站无法访问(多半会先网络瓶颈就是了)
图片优化 hexo使用懒加载即可,还可以让图片在上传时自动压缩为webp
nginx配置单个链接 接下来nginx开启限制单个ip并发限制5个链接
# http块添加(/etc/nginx/nginx.conf内) limit_conn_zone $binary_remote_addr zone=addr:10m; # server块添加, 单个ip限制5个最大连接数 limit_conn addr 5; limit_conn_log_level error;
fail2ban 注意,如果你使用cdn,就不要使用这个,用iptables过滤cdn ip就行了
安装
配置 cat << EOF >> /etc/nginx/conf.d/fallback.conf [nginx-conn-limit] enabled = true filter = nginx-conn-limit port = http,https logpath = /var/log/nginx/error.log maxretry = 1 bantime = 3600 EOF
cat << EOF >> /etc/fail2ban/filter.d/nginx-conn-limit.conf [Definition] failregex = limiting connections by zone "addr", client: <HOST> ignoreregex = EOF
这里要对应nginx上面的addr zone和error logpath
Cloudflare WAF 使用cloudflare waf过滤一部分风险流量 在博客访问来源不属于cn时触发验证码(Managed Challenge)
爬虫跳过验证
可以看到能挡掉大部分来自外面的恶意攻击
iptables拒绝除了来自cf的ip 若你使用cdn,直接将cf cdn的来源加入白名单,其他流量拒绝即可
wget https://www.cloudflare.com/ips-v4 -O cf.zone apt install ipset ipset -N cf hash :net for i in $(cat cf.zone); do ipset -A cf $i ; done iptables -A INPUT -p tcp -m set --dport=443 --match-set cf src -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport=443 -j DROP
但我暂时不用cdn,因为线路比较好不舍得用
保护重要的端口只允许特定地址访问(如中国) 同上类似
wget https://github.com/Hackl0us/GeoIP2-CN/raw/release/CN-ip-cidr.txt apt install ipset ipset -N cn hash :net for i in $(cat CN-ip-cidr.txt); do ipset -A cn $i ; done iptables -A INPUT -p tcp -m set --dport=1688 --match-set cn src -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport=1688 -j DROP
dns切换(最终方法) 被打了直接解析切到gov可以爆杀ddos
没办法的办法,切解析
这里还是教切解析吧
准备一个备用服务器 -> cron定时curl 检测网站是否在规定时间内返回200 -> 若不是则切换解析到备用服务器
curl -Ls --max-time 5 https://www.voidval.com > /dev/null && exit 0
切换解析的命令可以参考这里
加钱上ip防护的服务器 没钱,我直接跳过
linux内核调参 SYN Cookies sysctl -w net.ipv4.tcp_syncookies=1 sysctl -p
其他的自行探索
压测网站 使用go-stress-test
压测
这里先关掉了fail2ban和nginx链接限制测试ddos(因为这里只有一个ip只能算dos)
48线程并发测试结果如下
root@localhost:~/go-stress-testing# go run main.go -c $(nproc) -n 60 -u https://www.voidval.com 开始启动 并发数:48 请求数:60 请求参数: request: form:http url:https://www.voidval.com method:GET headers:map[Content-Type:application/x-www-form-urlencoded; charset=utf-8] data: verify:statusCode timeout:30s debug:false http2.0:false keepalive:false maxCon:1 ─────┬───────┬───────┬───────┬────────┬────────┬────────┬────────┬────────┬────────┬──────── 耗时│ 并发数│ 成功数│ 失败数│ qps │最长耗时│最短耗时│平均耗时│下载字节│字节每秒│ 状态码 ─────┼───────┼───────┼───────┼────────┼────────┼────────┼────────┼────────┼────────┼──────── 114s│ 48│ 2854│ 26│ 34.49│30001.36│ 246.37│ 1391.76│74,255,372│ 649,126│200:2854;509:26 ************************* 结果 stat **************************** 处理协程数量: 48 请求总数(并发数*请求数 -c * -n): 2880 总请求时间: 114.393 秒 successNum: 2854 failureNum: 26 tp90: 1403.000 tp95: 4372.000 tp99: 16871.000 ************************* 结果 end ****************************
cpu很容易就占满了
tp99为1200ms,qps为34 ,还是cpu瓶颈了,但此时网站还是能访问的,最终结果还能接受吧QAQ,毕竟服务器就一个单核洋垃圾E5-2696,不卡死宕机就算成功
syn flood测试 主机cpu甚至没有波动直接被ban了
ending 到这里优化就差不多了,其实静态页面没什么好d的_(:з)∠)_,毕竟d也要花钱