找不到匹配的域名时自动记录日志、默认防cc攻击

This commit is contained in:
刘祥超
2022-06-22 20:04:33 +08:00
parent c5a635d796
commit f8e155887f
3 changed files with 95 additions and 45 deletions

View File

@@ -233,6 +233,12 @@ func (this *HTTPRequest) Do() {
// 开始调用
func (this *HTTPRequest) doBegin() {
// 是否找不到域名匹配
if this.ReqServer.Id == 0 {
this.doMismatch()
return
}
if !this.isLnRequest {
// 处理request limit
if this.web.RequestLimit != nil &&

View File

@@ -0,0 +1,68 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package nodes
import (
"github.com/TeaOSLab/EdgeCommon/pkg/nodeutils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/TeaOSLab/EdgeNode/internal/ttlcache"
"github.com/TeaOSLab/EdgeNode/internal/waf"
"net/http"
"time"
)
// 域名无匹配情况处理
func (this *HTTPRequest) doMismatch() {
// 是否为健康检查
var healthCheckKey = this.RawReq.Header.Get(serverconfigs.HealthCheckHeaderName)
if len(healthCheckKey) > 0 {
_, err := nodeutils.Base64DecodeMap(healthCheckKey)
if err == nil {
this.writer.WriteHeader(http.StatusOK)
return
}
}
// 是否已经在黑名单
var remoteIP = this.RemoteAddr()
if waf.SharedIPBlackList.Contains(waf.IPTypeAll, firewallconfigs.FirewallScopeGlobal, 0, remoteIP) {
this.Close()
return
}
// 根据配置进行相应的处理
if sharedNodeConfig.GlobalConfig != nil && sharedNodeConfig.GlobalConfig.HTTPAll.MatchDomainStrictly {
// 检查cc
// TODO 可以在管理端配置是否开启以及最多尝试次数
if len(remoteIP) > 0 {
const maxAttempts = 100
if ttlcache.SharedCache.IncreaseInt64("MISMATCH_DOMAIN:"+remoteIP, int64(1), time.Now().Unix()+60, false) > maxAttempts {
// 在加入之前再次检查黑名单
if !waf.SharedIPBlackList.Contains(waf.IPTypeAll, firewallconfigs.FirewallScopeGlobal, 0, remoteIP) {
waf.SharedIPBlackList.RecordIP(waf.IPTypeAll, firewallconfigs.FirewallScopeGlobal, 0, remoteIP, time.Now().Unix()+int64(3600), 0, true, 0, 0, "access mismatch domain '"+this.RawReq.Host+"' too frequently")
}
}
}
// 处理当前连接
var httpAllConfig = sharedNodeConfig.GlobalConfig.HTTPAll
var mismatchAction = httpAllConfig.DomainMismatchAction
if mismatchAction != nil && mismatchAction.Code == "page" {
if mismatchAction.Options != nil {
this.writer.Header().Set("Content-Type", "text/html; charset=utf-8")
this.writer.WriteHeader(mismatchAction.Options.GetInt("statusCode"))
_, _ = this.writer.Write([]byte(mismatchAction.Options.GetString("contentHTML")))
} else {
http.Error(this.writer, "404 page not found: '"+this.URL()+"'", http.StatusNotFound)
}
return
} else {
http.Error(this.writer, "404 page not found: '"+this.URL()+"'", http.StatusNotFound)
this.Close()
return
}
}
http.Error(this.writer, "404 page not found: '"+this.URL()+"'", http.StatusNotFound)
}

View File

@@ -3,7 +3,6 @@ package nodes
import (
"context"
"crypto/tls"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeutils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
"github.com/TeaOSLab/EdgeNode/internal/zero"
@@ -172,8 +171,8 @@ func (this *HTTPListener) ServeHTTP(rawWriter http.ResponseWriter, rawReq *http.
server, serverName := this.findNamedServer(domain)
if server == nil {
if server == nil {
this.handleMismatch(rawReq, rawWriter)
return
// 增加默认的一个服务
server = this.emptyServer()
} else {
serverName = domain
}
@@ -195,48 +194,7 @@ func (this *HTTPListener) ServeHTTP(rawWriter http.ResponseWriter, rawReq *http.
req.Do()
}
// 处理域名不匹配的情况
func (this *HTTPListener) handleMismatch(rawReq *http.Request, rawWriter http.ResponseWriter) {
// TODO 需要记录访问记录和防止CC
// 是否为健康检查
var healthCheckKey = rawReq.Header.Get(serverconfigs.HealthCheckHeaderName)
if len(healthCheckKey) > 0 {
_, err := nodeutils.Base64DecodeMap(healthCheckKey)
if err == nil {
rawWriter.WriteHeader(http.StatusOK)
return
}
}
// 严格匹配域名模式下,我们拒绝用户访问
if sharedNodeConfig.GlobalConfig != nil && sharedNodeConfig.GlobalConfig.HTTPAll.MatchDomainStrictly {
var httpAllConfig = sharedNodeConfig.GlobalConfig.HTTPAll
var mismatchAction = httpAllConfig.DomainMismatchAction
if mismatchAction != nil && mismatchAction.Code == "page" {
if mismatchAction.Options != nil {
rawWriter.Header().Set("Content-Type", "text/html; charset=utf-8")
rawWriter.WriteHeader(mismatchAction.Options.GetInt("statusCode"))
_, _ = rawWriter.Write([]byte(mismatchAction.Options.GetString("contentHTML")))
} else {
http.Error(rawWriter, "404 page not found: '"+rawReq.URL.String()+"'", http.StatusNotFound)
}
return
} else {
hijacker, ok := rawWriter.(http.Hijacker)
if ok {
conn, _, _ := hijacker.Hijack()
if conn != nil {
_ = conn.Close()
return
}
}
}
}
http.Error(rawWriter, "404 page not found: '"+rawReq.URL.String()+"'", http.StatusNotFound)
}
// 检查host是否为IP
func (this *HTTPListener) isIP(host string) bool {
// IPv6
if strings.Index(host, "[") > -1 {
@@ -251,3 +209,21 @@ func (this *HTTPListener) isIP(host string) bool {
return true
}
// 默认的访问日志
func (this *HTTPListener) emptyServer() *serverconfigs.ServerConfig {
var server = &serverconfigs.ServerConfig{
Type: serverconfigs.ServerTypeHTTPProxy,
}
var accessLogRef = serverconfigs.NewHTTPAccessLogRef()
// TODO 需要配置是否记录日志
accessLogRef.IsOn = true
accessLogRef.Fields = append([]int{}, serverconfigs.HTTPAccessLogDefaultFieldsCodes...)
server.Web = &serverconfigs.HTTPWebConfig{
IsOn: true,
AccessLogRef: accessLogRef,
}
return server
}