Compare commits

...

7 Commits

Author SHA1 Message Date
刘祥超
d82c03db23 修复在HTTPS下无法连接Websocket的问题 2023-01-10 21:20:27 +08:00
刘祥超
230c5c3766 版本号修改为0.6.2 2023-01-10 21:18:53 +08:00
刘祥超
927425149e 优化代码 2023-01-10 09:47:56 +08:00
刘祥超
5ce1aab92c 修复域名跳转时没有携带参数的Bug 2023-01-09 20:06:09 +08:00
刘祥超
195742bb26 修复读超时时间(ReadDeadline)导致WAFGET302、POST307延时关闭连接的问题 2023-01-09 15:56:59 +08:00
刘祥超
006cc2912d 版本修改为0.6.1 2023-01-09 15:49:16 +08:00
刘祥超
2d4ba90c3b 改进在自动读超时模式下的Websocket连接 2023-01-09 12:36:33 +08:00
10 changed files with 73 additions and 33 deletions

View File

@@ -1,7 +1,7 @@
package teaconst package teaconst
const ( const (
Version = "0.6.0" Version = "0.6.2"
ProductName = "Edge Node" ProductName = "Edge Node"
ProcessName = "edge-node" ProcessName = "edge-node"

View File

@@ -42,7 +42,11 @@ type ClientConn struct {
lastErr error lastErr error
readDeadlineTime int64 readDeadlineTime int64
isShortReading bool // header or handshake isShortReading bool // reading header or tls handshake
isDebugging bool
autoReadTimeout bool
autoWriteTimeout bool
} }
func NewClientConn(rawConn net.Conn, isHTTP bool, isTLS bool, isInAllowList bool) net.Conn { func NewClientConn(rawConn net.Conn, isHTTP bool, isTLS bool, isInAllowList bool) net.Conn {
@@ -59,6 +63,14 @@ func NewClientConn(rawConn net.Conn, isHTTP bool, isTLS bool, isInAllowList bool
createdAt: time.Now().Unix(), createdAt: time.Now().Unix(),
} }
var globalServerConfig = sharedNodeConfig.GlobalServerConfig
if globalServerConfig != nil {
var performanceConfig = globalServerConfig.Performance
conn.isDebugging = performanceConfig.Debug
conn.autoReadTimeout = performanceConfig.AutoReadTimeout
conn.autoWriteTimeout = performanceConfig.AutoWriteTimeout
}
if isHTTP { if isHTTP {
// TODO 可以在配置中设置此值 // TODO 可以在配置中设置此值
_ = conn.SetLinger(nodeconfigs.DefaultTCPLinger) _ = conn.SetLinger(nodeconfigs.DefaultTCPLinger)
@@ -71,9 +83,7 @@ func NewClientConn(rawConn net.Conn, isHTTP bool, isTLS bool, isInAllowList bool
} }
func (this *ClientConn) Read(b []byte) (n int, err error) { func (this *ClientConn) Read(b []byte) (n int, err error) {
var globalServerConfig = sharedNodeConfig.GlobalServerConfig if this.isDebugging {
if globalServerConfig != nil && globalServerConfig.Performance.Debug {
this.lastReadAt = time.Now().Unix() this.lastReadAt = time.Now().Unix()
defer func() { defer func() {
@@ -93,8 +103,7 @@ func (this *ClientConn) Read(b []byte) (n int, err error) {
} }
// 设置读超时时间 // 设置读超时时间
var autoReadTimeout = globalServerConfig != nil && globalServerConfig.Performance.AutoReadTimeout if this.isHTTP && !this.isWebsocket && !this.isShortReading && this.autoReadTimeout {
if this.isHTTP && !this.isShortReading && autoReadTimeout {
this.setHTTPReadTimeout() this.setHTTPReadTimeout()
} }
@@ -134,9 +143,7 @@ func (this *ClientConn) Read(b []byte) (n int, err error) {
} }
func (this *ClientConn) Write(b []byte) (n int, err error) { func (this *ClientConn) Write(b []byte) (n int, err error) {
var globalServerConfig = sharedNodeConfig.GlobalServerConfig if this.isDebugging {
if globalServerConfig != nil && globalServerConfig.Performance.Debug {
this.lastWriteAt = time.Now().Unix() this.lastWriteAt = time.Now().Unix()
defer func() { defer func() {
@@ -147,7 +154,7 @@ func (this *ClientConn) Write(b []byte) (n int, err error) {
} }
// 设置写超时时间 // 设置写超时时间
if globalServerConfig != nil && globalServerConfig.Performance.AutoWriteTimeout { if this.autoWriteTimeout {
// TODO L2 -> L1 写入时不限制时间 // TODO L2 -> L1 写入时不限制时间
var timeoutSeconds = len(b) / 1024 var timeoutSeconds = len(b) / 1024
if timeoutSeconds < 3 { if timeoutSeconds < 3 {
@@ -157,7 +164,7 @@ func (this *ClientConn) Write(b []byte) (n int, err error) {
} }
// 延长读超时时间 // 延长读超时时间
if this.isHTTP { if this.isHTTP && !this.isWebsocket && this.autoReadTimeout {
this.setHTTPReadTimeout() this.setHTTPReadTimeout()
} }
@@ -216,8 +223,7 @@ func (this *ClientConn) SetDeadline(t time.Time) error {
func (this *ClientConn) SetReadDeadline(t time.Time) error { func (this *ClientConn) SetReadDeadline(t time.Time) error {
// 如果开启了HTTP自动读超时选项则自动控制超时时间 // 如果开启了HTTP自动读超时选项则自动控制超时时间
var globalServerConfig = sharedNodeConfig.GlobalServerConfig if this.isHTTP && !this.isWebsocket && this.autoReadTimeout {
if this.isHTTP && globalServerConfig != nil && globalServerConfig.Performance.AutoReadTimeout {
this.isShortReading = false this.isShortReading = false
var unixTime = t.Unix() var unixTime = t.Unix()

View File

@@ -16,6 +16,8 @@ type BaseClientConn struct {
remoteAddr string remoteAddr string
hasLimit bool hasLimit bool
isWebsocket bool
isClosed bool isClosed bool
rawIP string rawIP string
@@ -122,3 +124,7 @@ func (this *BaseClientConn) SetLinger(seconds int) error {
} }
return nil return nil
} }
func (this *BaseClientConn) SetIsWebsocket(isWebsocket bool) {
this.isWebsocket = isWebsocket
}

View File

@@ -23,4 +23,7 @@ type ClientConnInterface interface {
// UserId 获取当前连接所属服务的用户ID // UserId 获取当前连接所属服务的用户ID
UserId() int64 UserId() int64
// SetIsWebsocket 设置是否为Websocket
SetIsWebsocket(isWebsocket bool)
} }

View File

@@ -55,3 +55,16 @@ func (this *ClientTLSConn) SetReadDeadline(t time.Time) error {
func (this *ClientTLSConn) SetWriteDeadline(t time.Time) error { func (this *ClientTLSConn) SetWriteDeadline(t time.Time) error {
return this.rawConn.SetWriteDeadline(t) return this.rawConn.SetWriteDeadline(t)
} }
func (this *ClientTLSConn) SetIsWebsocket(isWebsocket bool) {
tlsConn, ok := this.rawConn.(*tls.Conn)
if ok {
var rawConn = tlsConn.NetConn()
if rawConn != nil {
clientConn, ok := rawConn.(*ClientConn)
if ok {
clientConn.SetIsWebsocket(isWebsocket)
}
}
}
}

View File

@@ -146,6 +146,13 @@ func (this *HTTPRequest) doHostRedirect() (blocked bool) {
u.Status = http.StatusTemporaryRedirect u.Status = http.StatusTemporaryRedirect
} }
this.processResponseHeaders(this.writer.Header(), u.Status) this.processResponseHeaders(this.writer.Header(), u.Status)
// 参数
var qIndex = strings.Index(this.uri, "?")
if qIndex >= 0 {
afterURL += this.uri[qIndex:]
}
http.Redirect(this.RawWriter, this.RawReq, afterURL, u.Status) http.Redirect(this.RawWriter, this.RawReq, afterURL, u.Status)
return true return true
} }

View File

@@ -70,6 +70,13 @@ func (this *HTTPRequest) doWebsocket(requestHost string, isLastRetry bool) (shou
this.RawReq.Header.Set("Origin", newRequestOrigin) this.RawReq.Header.Set("Origin", newRequestOrigin)
} }
// 获取当前连接
var requestConn = this.RawReq.Context().Value(HTTPConnContextKey)
if requestConn == nil {
return
}
// 连接源站
// TODO 增加N次错误重试重试的时候需要尝试不同的源站 // TODO 增加N次错误重试重试的时候需要尝试不同的源站
originConn, _, err := OriginConnect(this.origin, this.requestServerPort(), this.RawReq.RemoteAddr, requestHost) originConn, _, err := OriginConnect(this.origin, this.requestServerPort(), this.RawReq.RemoteAddr, requestHost)
if err != nil { if err != nil {
@@ -102,6 +109,11 @@ func (this *HTTPRequest) doWebsocket(requestHost string, isLastRetry bool) (shou
return return
} }
requestClientConn, ok := requestConn.(ClientConnInterface)
if ok {
requestClientConn.SetIsWebsocket(true)
}
clientConn, _, err := this.writer.Hijack() clientConn, _, err := this.writer.Hijack()
if err != nil || clientConn == nil { if err != nil || clientConn == nil {
this.write50x(err, http.StatusInternalServerError, "Failed to get origin site connection", "获取源站连接失败", false) this.write50x(err, http.StatusInternalServerError, "Failed to get origin site connection", "获取源站连接失败", false)

View File

@@ -2,10 +2,6 @@
package waf package waf
import (
"net/http"
)
type BaseAction struct { type BaseAction struct {
currentActionId int64 currentActionId int64
} }
@@ -19,16 +15,3 @@ func (this *BaseAction) ActionId() int64 {
func (this *BaseAction) SetActionId(actionId int64) { func (this *BaseAction) SetActionId(actionId int64) {
this.currentActionId = actionId this.currentActionId = actionId
} }
// CloseConn 关闭连接
func (this *BaseAction) CloseConn(writer http.ResponseWriter) error {
// 断开连接
hijack, ok := writer.(http.Hijacker)
if ok {
conn, _, err := hijack.Hijack()
if err == nil && conn != nil {
return conn.Close()
}
}
return nil
}

View File

@@ -70,7 +70,12 @@ func (this *Get302Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, requ
http.Redirect(writer, request.WAFRaw(), Get302Path+"?info="+url.QueryEscape(info), http.StatusFound) http.Redirect(writer, request.WAFRaw(), Get302Path+"?info="+url.QueryEscape(info), http.StatusFound)
if request.WAFRaw().ProtoMajor == 1 { if request.WAFRaw().ProtoMajor == 1 {
_ = this.CloseConn(writer) flusher, ok := writer.(http.Flusher)
if ok {
flusher.Flush()
}
request.WAFClose()
} }
return false, false return false, false

View File

@@ -87,7 +87,12 @@ func (this *Post307Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req
http.Redirect(writer, request.WAFRaw(), request.WAFRaw().URL.String(), http.StatusTemporaryRedirect) http.Redirect(writer, request.WAFRaw(), request.WAFRaw().URL.String(), http.StatusTemporaryRedirect)
if request.WAFRaw().ProtoMajor == 1 { if request.WAFRaw().ProtoMajor == 1 {
_ = this.CloseConn(writer) flusher, ok := writer.(http.Flusher)
if ok {
flusher.Flush()
}
request.WAFClose()
} }
return false, false return false, false