因WAF规则拦截而关闭连接时,不记录499

This commit is contained in:
刘祥超
2021-12-01 20:55:19 +08:00
parent 0f0776fc1a
commit ea84c41be3
8 changed files with 120 additions and 27 deletions

View File

@@ -0,0 +1,7 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package nodes
type ClientConnCloser interface {
IsClosed() bool
}

View File

@@ -11,12 +11,10 @@ func isClientConnClosed(conn net.Conn) bool {
if conn == nil { if conn == nil {
return true return true
} }
clientConn, ok := conn.(*ClientConn) clientConn, ok := conn.(ClientConnCloser)
if ok { if ok {
return clientConn.IsClosed() return clientConn.IsClosed()
} }
// TODO 解决tls.Conn无法获取底层连接对象的问题 return true
return false
} }

View File

@@ -0,0 +1,57 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package nodes
import (
"crypto/tls"
"net"
"time"
)
type ClientTLSConn struct {
rawConn *tls.Conn
isClosed bool
}
func NewClientTLSConn(conn *tls.Conn) net.Conn {
return &ClientTLSConn{rawConn: conn}
}
func (this *ClientTLSConn) Read(b []byte) (n int, err error) {
n, err = this.rawConn.Read(b)
return
}
func (this *ClientTLSConn) Write(b []byte) (n int, err error) {
n, err = this.rawConn.Write(b)
return
}
func (this *ClientTLSConn) Close() error {
this.isClosed = true
return this.rawConn.Close()
}
func (this *ClientTLSConn) LocalAddr() net.Addr {
return this.rawConn.LocalAddr()
}
func (this *ClientTLSConn) RemoteAddr() net.Addr {
return this.rawConn.RemoteAddr()
}
func (this *ClientTLSConn) SetDeadline(t time.Time) error {
return this.rawConn.SetDeadline(t)
}
func (this *ClientTLSConn) SetReadDeadline(t time.Time) error {
return this.rawConn.SetReadDeadline(t)
}
func (this *ClientTLSConn) SetWriteDeadline(t time.Time) error {
return this.rawConn.SetWriteDeadline(t)
}
func (this *ClientTLSConn) IsClosed() bool {
return this.isClosed
}

View File

@@ -1279,3 +1279,34 @@ func (this *HTTPRequest) canIgnore(err error) bool {
return false return false
} }
// 关闭当前连接
func (this *HTTPRequest) closeConn() {
requestConn := this.RawReq.Context().Value(HTTPConnContextKey)
if requestConn == nil {
return
}
conn, ok := requestConn.(net.Conn)
if ok {
_ = conn.Close()
return
}
return
}
// 检查连接是否已关闭
func (this *HTTPRequest) isConnClosed() bool {
requestConn := this.RawReq.Context().Value(HTTPConnContextKey)
if requestConn == nil {
return true
}
conn, ok := requestConn.(net.Conn)
if ok {
return isClientConnClosed(conn)
}
return true
}

View File

@@ -327,6 +327,8 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) {
return true, nil return true, nil
}) })
if err != nil { if err != nil {
this.varMapping["cache.status"] = "MISS"
if err == caches.ErrInvalidRange { if err == caches.ErrInvalidRange {
this.processResponseHeaders(http.StatusRequestedRangeNotSatisfiable) this.processResponseHeaders(http.StatusRequestedRangeNotSatisfiable)
this.writer.WriteHeader(http.StatusRequestedRangeNotSatisfiable) this.writer.WriteHeader(http.StatusRequestedRangeNotSatisfiable)
@@ -387,6 +389,8 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) {
_, err = this.writer.WriteString("\r\n--" + boundary + "--\r\n") _, err = this.writer.WriteString("\r\n--" + boundary + "--\r\n")
if err != nil { if err != nil {
this.varMapping["cache.status"] = "MISS"
// 不提示写入客户端错误 // 不提示写入客户端错误
return true return true
} }
@@ -402,6 +406,8 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) {
return true, nil return true, nil
}) })
if err != nil { if err != nil {
this.varMapping["cache.status"] = "MISS"
if !this.canIgnore(err) { if !this.canIgnore(err) {
remotelogs.Warn("HTTP_REQUEST_CACHE", "read from cache failed: "+err.Error()) remotelogs.Warn("HTTP_REQUEST_CACHE", "read from cache failed: "+err.Error())
} }

View File

@@ -186,6 +186,12 @@ func (this *HTTPRequest) doReverseProxy() {
isClientError := false isClientError := false
if ok { if ok {
if httpErr.Err == context.Canceled { if httpErr.Err == context.Canceled {
// 如果是服务器端主动关闭,则无需提示
if this.isConnClosed() {
this.disableLog = true
return
}
isClientError = true isClientError = true
this.addError(errors.New(httpErr.Op + " " + httpErr.URL + ": client closed the connection")) this.addError(errors.New(httpErr.Op + " " + httpErr.URL + ": client closed the connection"))
this.writer.WriteHeader(499) // 仿照nginx this.writer.WriteHeader(499) // 仿照nginx

View File

@@ -11,37 +11,29 @@ import (
"github.com/iwind/TeaGo/types" "github.com/iwind/TeaGo/types"
"io" "io"
"io/ioutil" "io/ioutil"
"net"
"net/http" "net/http"
) )
// 调用WAF // 调用WAF
func (this *HTTPRequest) doWAFRequest() (blocked bool) { func (this *HTTPRequest) doWAFRequest() (blocked bool) {
// 当前连接是否已关闭 // 当前连接是否已关闭
var conn = this.RawReq.Context().Value(HTTPConnContextKey) if this.isConnClosed() {
if conn != nil { this.disableLog = true
if isClientConnClosed(conn.(net.Conn)) { return true
this.disableLog = true
return true
}
} }
// 是否在全局名单中 // 是否在全局名单中
var remoteAddr = this.requestRemoteAddr(true) var remoteAddr = this.requestRemoteAddr(true)
if !iplibrary.AllowIP(remoteAddr, this.Server.Id) { if !iplibrary.AllowIP(remoteAddr, this.Server.Id) {
this.disableLog = true this.disableLog = true
if conn != nil { this.closeConn()
_ = conn.(net.Conn).Close()
}
return true return true
} }
// 检查是否在临时黑名单中 // 检查是否在临时黑名单中
if waf.SharedIPBlackList.Contains(waf.IPTypeAll, firewallconfigs.FirewallScopeService, this.Server.Id, remoteAddr) || waf.SharedIPBlackList.Contains(waf.IPTypeAll, firewallconfigs.FirewallScopeGlobal, 0, remoteAddr) { if waf.SharedIPBlackList.Contains(waf.IPTypeAll, firewallconfigs.FirewallScopeService, this.Server.Id, remoteAddr) || waf.SharedIPBlackList.Contains(waf.IPTypeAll, firewallconfigs.FirewallScopeGlobal, 0, remoteAddr) {
this.disableLog = true this.disableLog = true
if conn != nil { this.closeConn()
_ = conn.(net.Conn).Close()
}
return true return true
} }
@@ -317,16 +309,7 @@ func (this *HTTPRequest) WAFServerId() int64 {
// WAFClose 关闭连接 // WAFClose 关闭连接
func (this *HTTPRequest) WAFClose() { func (this *HTTPRequest) WAFClose() {
requestConn := this.RawReq.Context().Value(HTTPConnContextKey) this.closeConn()
if requestConn == nil {
return
}
conn, ok := requestConn.(net.Conn)
if ok {
_ = conn.Close()
return
}
return
} }
func (this *HTTPRequest) WAFOnAction(action interface{}) (goNext bool) { func (this *HTTPRequest) WAFOnAction(action interface{}) (goNext bool) {

View File

@@ -2,6 +2,7 @@ package nodes
import ( import (
"context" "context"
"crypto/tls"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeNode/internal/remotelogs" "github.com/TeaOSLab/EdgeNode/internal/remotelogs"
"golang.org/x/net/http2" "golang.org/x/net/http2"
@@ -68,6 +69,10 @@ func (this *HTTPListener) Serve() error {
} }
}, },
ConnContext: func(ctx context.Context, c net.Conn) context.Context { ConnContext: func(ctx context.Context, c net.Conn) context.Context {
tlsConn, ok := c.(*tls.Conn)
if ok {
c = NewClientTLSConn(tlsConn)
}
return context.WithValue(ctx, HTTPConnContextKey, c) return context.WithValue(ctx, HTTPConnContextKey, c)
}, },
} }