Fix: tls handshake with timeout
This commit is contained in:
parent
da92601902
commit
7e85d5a954
@ -3,14 +3,15 @@ package mitm
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -68,6 +69,11 @@ readLoop:
|
|||||||
|
|
||||||
if trusted {
|
if trusted {
|
||||||
if session.request.Method == http.MethodConnect {
|
if session.request.Method == http.MethodConnect {
|
||||||
|
if session.request.ProtoMajor > 1 {
|
||||||
|
session.request.ProtoMajor = 1
|
||||||
|
session.request.ProtoMinor = 1
|
||||||
|
}
|
||||||
|
|
||||||
// Manual writing to support CONNECT for http 1.0 (workaround for uplay client)
|
// Manual writing to support CONNECT for http 1.0 (workaround for uplay client)
|
||||||
if _, err = fmt.Fprintf(session.conn, "HTTP/%d.%d %03d %s\r\n\r\n", session.request.ProtoMajor, session.request.ProtoMinor, http.StatusOK, "Connection established"); err != nil {
|
if _, err = fmt.Fprintf(session.conn, "HTTP/%d.%d %03d %s\r\n\r\n", session.request.ProtoMajor, session.request.ProtoMinor, http.StatusOK, "Connection established"); err != nil {
|
||||||
handleError(opt, session, err)
|
handleError(opt, session, err)
|
||||||
@ -88,12 +94,15 @@ readLoop:
|
|||||||
if b[0] == 0x16 {
|
if b[0] == 0x16 {
|
||||||
tlsConn := tls.Server(conn, opt.CertConfig.NewTLSConfigForHost(session.request.URL.Hostname()))
|
tlsConn := tls.Server(conn, opt.CertConfig.NewTLSConfigForHost(session.request.URL.Hostname()))
|
||||||
|
|
||||||
// Handshake with the local client
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||||
if err = tlsConn.Handshake(); err != nil {
|
// handshake with the local client
|
||||||
|
if err = tlsConn.HandshakeContext(ctx); err != nil {
|
||||||
|
cancel()
|
||||||
session.response = session.NewErrorResponse(fmt.Errorf("handshake failed: %w", err))
|
session.response = session.NewErrorResponse(fmt.Errorf("handshake failed: %w", err))
|
||||||
_ = writeResponse(session, false)
|
_ = writeResponse(session, false)
|
||||||
break // close connection
|
break // close connection
|
||||||
}
|
}
|
||||||
|
cancel()
|
||||||
|
|
||||||
cs := tlsConn.ConnectionState()
|
cs := tlsConn.ConnectionState()
|
||||||
connState = &cs
|
connState = &cs
|
||||||
@ -105,20 +114,20 @@ readLoop:
|
|||||||
goto readLoop
|
goto readLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
var noErr bool
|
if conn.SetReadDeadline(time.Now().Add(time.Second)) != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
buf, err2 := conn.Peek(7)
|
buf, err2 := conn.Peek(7)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
if err2 == bufio.ErrBufferFull || errors.Is(err2, io.EOF) {
|
if err2 != bufio.ErrBufferFull && !os.IsTimeout(err2) {
|
||||||
noErr = true
|
|
||||||
} else {
|
|
||||||
handleError(opt, session, err2)
|
handleError(opt, session, err2)
|
||||||
break // close connection
|
break // close connection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// others protocol over tcp
|
// others protocol over tcp
|
||||||
if noErr || !isHTTPTraffic(buf) {
|
if !isHTTPTraffic(buf) {
|
||||||
if connState != nil {
|
if connState != nil {
|
||||||
session.request.TLS = connState
|
session.request.TLS = connState
|
||||||
}
|
}
|
||||||
@ -128,7 +137,9 @@ readLoop:
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = conn.SetReadDeadline(time.Time{})
|
if conn.SetReadDeadline(time.Time{}) != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
N.Relay(serverConn, conn)
|
N.Relay(serverConn, conn)
|
||||||
return // hijack connection
|
return // hijack connection
|
||||||
|
Reference in New Issue
Block a user