我在很多场合讲过,现在业务服务器我会定义成 API 服务器,他们只提供 API 接口的服务,不提供任何静态资源的服务,静态资源全部交给 CDN 来处理,这样可以有效的减少业务服务器的压力,也可以有效的减少业务服务器的带宽消耗。
在服务器的前置加上雷池后,恶意的请求会被拦截,但是拦截后的响应内容是一个 HTML 页面,目前大小是有 17 KB 的,在恶意请求较多的场景下会给我们的业务服务器带来很大的压力,所以我们需要对这个响应内容进行优化。
这个痛点很早就有了,我找到了响应的 HTML 文件位于 /root/safeline/resources/nginx/forbidden_pages
下面,进行修改后是可以生效的,但过一会又被重新写入了,一直没找到合适的处理方法。
通过公众号文章发现了 fsnotify 这个开源项目,可以监听文件的变化,然后我们再根据变化来进行处理,这样就可以实现我们的需求了。因为实现起来非常简单,就直接贴代码了。
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| package main
import ( "github.com/fsnotify/fsnotify" "log" "os" "strings" "time" )
var SAFELINE_DIR = os.Getenv("SAFELINE_DIR")
var Content = map[string]string{ "/data/forbidden_pages/default_forbidden_page.html": `{"code": 0, "msg": "风控拦截"}`, }
func init() { if strings.HasSuffix(SAFELINE_DIR, "/") { SAFELINE_DIR = SAFELINE_DIR[:len(SAFELINE_DIR)-1] }
go func() { time.Sleep(time.Second * 30)
for path := range Content { _ = forceContent(path) } }() }
func main() { err := handle()
if err != nil { log.Fatal(err) } }
func handle() error { watcher, err := fsnotify.NewWatcher()
if err != nil { return err }
defer watcher.Close()
go func() { for { select { case event, ok := <-watcher.Events: if !ok { return }
if !event.Has(fsnotify.Write) { continue }
err = forceContent(event.Name)
if err != nil { watcher.Errors <- err } case err, ok := <-watcher.Errors: if !ok { return }
log.Println("error:", err) } } }()
err = watcher.Add(SAFELINE_DIR)
if err != nil { return err }
<-make(chan struct{})
return nil }
func forceContent(path string) error { log.Printf("强制修改文件: %s", path)
content, ok := Content[path]
if !ok { return nil }
body, err := os.ReadFile(path)
if err != nil { return err }
if string(body) == content { return nil }
return os.WriteFile(path, []byte(content), 0644) }
|
你可以自行编译后进行部署使用,记得要挂载卷和设置监听地址。
通过打印的日志,可以发现雷池每30秒会重新修改一次文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 2023/08/28 12:39:00 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:39:00 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:39:30 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:39:30 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:39:30 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:40:00 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:40:00 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:40:00 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:40:30 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:40:30 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:40:30 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:41:00 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:41:00 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:41:00 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:41:30 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:41:30 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:41:30 强制修改文件: /data/forbidden_pages/default_forbidden_page.html 2023/08/28 12:42:00 强制修改文件: /data/forbidden_pages/default_forbidden_page.html
|
另外响应内容不是正常的 JSON 内容,雷池还会赋值一个事件 ID 进去,这块还需要前端进行兼容处理,暂时是没办法在服务器层面来调整的。
1 2
| {"code": 0, "msg": "风控拦截"}
|