前言:
最近受某学长刺激,授权爆破他的网站,短时间内就被他的网站防住了~
好滴~ 最近又开始捣鼓服务器了,我也想搞~ 所以我就简单说一下我的实现。
以下我简单说下我的思路来实现防爆破与CC等攻击:👇
- 通过Cloudfare获取到原始IP
- Fail2ban读取日志
- 回调通知Cloudfare进行防御
要用到的有:Gin框架
与nginx服务器
与cloudfare免费版
与Fail2ban
工具
获取到原始IP
其实有个思路是已经有模块与nginx进行二进制编译后
access日志
就已经是原始IP了,但是刚好我是后端接口怼的CF
那么我为什么不写个中间件然后模拟Nginx日志结构,同样实现日志。
说干就干,下面直接贴代码: (实现了高并发下的读写)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| package middleware
import ( "GoBackEnd/common" "fmt" "github.com/gin-gonic/gin" "io" "io/ioutil" "os" "sync" "time" )
func NginxLogMiddleware() gin.HandlerFunc { return func(c *gin.Context) { var bodySize int nginxPath := common.Path("access.log") ip := c.ClientIP() utcTimeStr := time.Now().Format("02/Jan/2006:15:04:05") url := c.Request.URL method := c.Request.Method status := c.Writer.Status() body, err := ioutil.ReadAll(c.Request.Body) http := c.Request.Proto if err != nil { bodySize = -1 } bodySize = len(body) header := c.Request.UserAgent() res := fmt.Sprintf("%v - - [%v +8000] \"%v %v %v\" %v %v \"-\" \"%v\"", ip, utcTimeStr, method, url, http, status, bodySize, header) file, _ := os.OpenFile(nginxPath, os.O_WRONLY|os.O_APPEND, 0666) defer file.Close() wr := &SyncWriter{sync.Mutex{}, file} wg := sync.WaitGroup{} wg.Add(1) go func(content string) { fmt.Fprintln(wr, content) wg.Done() }(res) wg.Wait() c.Next() } }
type SyncWriter struct { m sync.Mutex Writer io.Writer }
func (w *SyncWriter) Write(b []byte) (n int, err error) { w.m.Lock() defer w.m.Unlock() return w.Writer.Write(b) }
|

然后直接放到默认路由里面,所有流量都要走~

Fail2ban的安装与设置
1 2 3
| $ sudo apt install fail2ban $ systemctl stop fail2ban $ cd /etc/fail2ban
|
这里说下Fail2ban的加载文件规则:依次进行
/etc/fail2ban/jail.conf
/etc/fail2ban/jail.d/*.conf
/etc/fail2ban/jail.local
/etc/fail2ban/jail.d/*.local
我们需要做的就是: 分别写入匹配规则与拉黑设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| $ cd /etc/fail2ban/jail.d $ vim nginxcc.conf
[nginxcc] enabled = true port = http,https filter = nginxcc logpath = /home/ubuntu/HengY1Service/access.log bantime = 1200 findtime = 30 maxretry = 10 action = %(action_mwl)s custom-cloudflare :wq
$ cd /etc/fail2ban/filter.d $ vim nginxcc.conf
[Definition] failregex =(?i)^<HOST> .* "(GET|POST|HEAD).*HTTP.*" (404|503) .*$ ignoreregex =.*(robots.txt|favicon.ico|jpg|png|webp|js|css)
:wq
|
然后验证下自己写对没:access.log最好有点东西
1 2 3 4 5
| $ fail2ban-regex /home/ubuntu/HengY1Service/access.log /etc/fail2ban/filter.d/nginxcc.conf $ systemctl restart fail2ban $ fail2ban-client status $ fail2ban-client status nginxcc $ fail2ban-client set nginxcc unbanip 1.1.1.1
|

通知Cloudfare进行防御
到这里的话还是不行的,因为你虽然拿到了源IP,但是是过CDN过来的IP你没有封
但是Fail2ban已经考虑到了,提供了脚本。这就是为什么要设置action
1 2 3 4 5
| $ cd /etc/fail2ban/action.d $ cp cloudflare.conf custom-cloudflare.conf $ vim custom-cloudflare.conf
$ systemctl restart fail2ban
|

然后可以自己试试效果了~ (我的是:api.hengy1.top) 可以来试试效果

总结:
逼逼两句:
- 构造日志参数与高并发读写要注意
- 正则匹配必须有<HOST>,正则测试https://regex101.com/
- 一定要CF来防御,思路得先串通
- Fail2ban有点反应延迟