diff --git a/internal/nodes/client_conn_closer.go b/internal/nodes/client_conn_closer.go new file mode 100644 index 0000000..3eaec10 --- /dev/null +++ b/internal/nodes/client_conn_closer.go @@ -0,0 +1,7 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package nodes + +type ClientConnCloser interface { + IsClosed() bool +} diff --git a/internal/nodes/client_conn_utils.go b/internal/nodes/client_conn_utils.go index b00b0e7..6a5e782 100644 --- a/internal/nodes/client_conn_utils.go +++ b/internal/nodes/client_conn_utils.go @@ -11,12 +11,10 @@ func isClientConnClosed(conn net.Conn) bool { if conn == nil { return true } - clientConn, ok := conn.(*ClientConn) + clientConn, ok := conn.(ClientConnCloser) if ok { return clientConn.IsClosed() } - // TODO 解决tls.Conn无法获取底层连接对象的问题 - - return false + return true } diff --git a/internal/nodes/client_tls_conn.go b/internal/nodes/client_tls_conn.go new file mode 100644 index 0000000..1597ee5 --- /dev/null +++ b/internal/nodes/client_tls_conn.go @@ -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 +} diff --git a/internal/nodes/http_request.go b/internal/nodes/http_request.go index 29e876b..c251010 100644 --- a/internal/nodes/http_request.go +++ b/internal/nodes/http_request.go @@ -1279,3 +1279,34 @@ func (this *HTTPRequest) canIgnore(err error) bool { 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 +} diff --git a/internal/nodes/http_request_cache.go b/internal/nodes/http_request_cache.go index a8405cd..2388c3e 100644 --- a/internal/nodes/http_request_cache.go +++ b/internal/nodes/http_request_cache.go @@ -327,6 +327,8 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) { return true, nil }) if err != nil { + this.varMapping["cache.status"] = "MISS" + if err == caches.ErrInvalidRange { this.processResponseHeaders(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") if err != nil { + this.varMapping["cache.status"] = "MISS" + // 不提示写入客户端错误 return true } @@ -402,6 +406,8 @@ func (this *HTTPRequest) doCacheRead() (shouldStop bool) { return true, nil }) if err != nil { + this.varMapping["cache.status"] = "MISS" + if !this.canIgnore(err) { remotelogs.Warn("HTTP_REQUEST_CACHE", "read from cache failed: "+err.Error()) } diff --git a/internal/nodes/http_request_reverse_proxy.go b/internal/nodes/http_request_reverse_proxy.go index f050872..276b308 100644 --- a/internal/nodes/http_request_reverse_proxy.go +++ b/internal/nodes/http_request_reverse_proxy.go @@ -186,6 +186,12 @@ func (this *HTTPRequest) doReverseProxy() { isClientError := false if ok { if httpErr.Err == context.Canceled { + // 如果是服务器端主动关闭,则无需提示 + if this.isConnClosed() { + this.disableLog = true + return + } + isClientError = true this.addError(errors.New(httpErr.Op + " " + httpErr.URL + ": client closed the connection")) this.writer.WriteHeader(499) // 仿照nginx diff --git a/internal/nodes/http_request_waf.go b/internal/nodes/http_request_waf.go index 9204e2e..f93d02d 100644 --- a/internal/nodes/http_request_waf.go +++ b/internal/nodes/http_request_waf.go @@ -11,37 +11,29 @@ import ( "github.com/iwind/TeaGo/types" "io" "io/ioutil" - "net" "net/http" ) // 调用WAF func (this *HTTPRequest) doWAFRequest() (blocked bool) { // 当前连接是否已关闭 - var conn = this.RawReq.Context().Value(HTTPConnContextKey) - if conn != nil { - if isClientConnClosed(conn.(net.Conn)) { - this.disableLog = true - return true - } + if this.isConnClosed() { + this.disableLog = true + return true } // 是否在全局名单中 var remoteAddr = this.requestRemoteAddr(true) if !iplibrary.AllowIP(remoteAddr, this.Server.Id) { this.disableLog = true - if conn != nil { - _ = conn.(net.Conn).Close() - } + this.closeConn() return true } // 检查是否在临时黑名单中 if waf.SharedIPBlackList.Contains(waf.IPTypeAll, firewallconfigs.FirewallScopeService, this.Server.Id, remoteAddr) || waf.SharedIPBlackList.Contains(waf.IPTypeAll, firewallconfigs.FirewallScopeGlobal, 0, remoteAddr) { this.disableLog = true - if conn != nil { - _ = conn.(net.Conn).Close() - } + this.closeConn() return true } @@ -317,16 +309,7 @@ func (this *HTTPRequest) WAFServerId() int64 { // WAFClose 关闭连接 func (this *HTTPRequest) WAFClose() { - requestConn := this.RawReq.Context().Value(HTTPConnContextKey) - if requestConn == nil { - return - } - conn, ok := requestConn.(net.Conn) - if ok { - _ = conn.Close() - return - } - return + this.closeConn() } func (this *HTTPRequest) WAFOnAction(action interface{}) (goNext bool) { diff --git a/internal/nodes/listener_http.go b/internal/nodes/listener_http.go index 2b00e03..2791eb5 100644 --- a/internal/nodes/listener_http.go +++ b/internal/nodes/listener_http.go @@ -2,6 +2,7 @@ package nodes import ( "context" + "crypto/tls" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" "github.com/TeaOSLab/EdgeNode/internal/remotelogs" "golang.org/x/net/http2" @@ -68,6 +69,10 @@ func (this *HTTPListener) Serve() error { } }, 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) }, }