add route for recorder
This commit is contained in:
+8
-7
@@ -108,14 +108,15 @@ func (r *Router) dial(ctx context.Context, network, address string, log logger.L
|
||||
route = r.options.Chain.Route(ctx, network, ipAddr, chain.WithHostRouteOption(address))
|
||||
}
|
||||
|
||||
if log.IsLevelEnabled(logger.DebugLevel) {
|
||||
buf := bytes.Buffer{}
|
||||
for _, node := range routePath(route) {
|
||||
fmt.Fprintf(&buf, "%s@%s > ", node.Name, node.Addr)
|
||||
}
|
||||
fmt.Fprintf(&buf, "%s", ipAddr)
|
||||
log.Debugf("route(retry=%d) %s", i, buf.String())
|
||||
buf := ctxvalue.BufferFromContext(ctx)
|
||||
if buf == nil {
|
||||
buf = &bytes.Buffer{}
|
||||
}
|
||||
for _, node := range routePath(route) {
|
||||
fmt.Fprintf(buf, "%s@%s > ", node.Name, node.Addr)
|
||||
}
|
||||
fmt.Fprintf(buf, "%s", ipAddr)
|
||||
log.Debugf("route(retry=%d) %s", i, buf.String())
|
||||
|
||||
if route == nil {
|
||||
route = DefaultRoute
|
||||
|
||||
@@ -121,6 +121,7 @@ type TLSOptions struct {
|
||||
MinVersion string `yaml:"minVersion,omitempty" json:"minVersion,omitempty"`
|
||||
MaxVersion string `yaml:"maxVersion,omitempty" json:"maxVersion,omitempty"`
|
||||
CipherSuites []string `yaml:"cipherSuites,omitempty" json:"cipherSuites,omitempty"`
|
||||
ALPN []string `yaml:"alpn,omitempty" json:"alpn,omitempty"`
|
||||
}
|
||||
|
||||
type PluginConfig struct {
|
||||
|
||||
@@ -220,6 +220,7 @@ func ParseNode(hop string, cfg *config.NodeConfig, log logger.Logger) (*chain.No
|
||||
tlsCfg.Options.MinVersion = o.MinVersion
|
||||
tlsCfg.Options.MaxVersion = o.MaxVersion
|
||||
tlsCfg.Options.CipherSuites = o.CipherSuites
|
||||
tlsCfg.Options.ALPN = o.ALPN
|
||||
}
|
||||
opts = append(opts, chain.TLSNodeOption(tlsCfg))
|
||||
}
|
||||
|
||||
+19
-1
@@ -1,6 +1,9 @@
|
||||
package ctx
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
)
|
||||
|
||||
// clientAddrKey saves the client address.
|
||||
type clientAddrKey struct{}
|
||||
@@ -74,3 +77,18 @@ func ClientIDFromContext(ctx context.Context) ClientID {
|
||||
v, _ := ctx.Value(keyClientID).(ClientID)
|
||||
return v
|
||||
}
|
||||
|
||||
type bufferKey struct{}
|
||||
|
||||
var (
|
||||
keyBuffer = &bufferKey{}
|
||||
)
|
||||
|
||||
func ContextWithBuffer(ctx context.Context, buffer *bytes.Buffer) context.Context {
|
||||
return context.WithValue(ctx, keyBuffer, buffer)
|
||||
}
|
||||
|
||||
func BufferFromContext(ctx context.Context) *bytes.Buffer {
|
||||
v, _ := ctx.Value(keyBuffer).(*bytes.Buffer)
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -9,12 +9,12 @@ require (
|
||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
||||
github.com/gin-contrib/cors v1.6.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/go-gost/core v0.1.4
|
||||
github.com/go-gost/core v0.1.5
|
||||
github.com/go-gost/gosocks4 v0.0.1
|
||||
github.com/go-gost/gosocks5 v0.4.2
|
||||
github.com/go-gost/plugin v0.1.1
|
||||
github.com/go-gost/relay v0.5.0
|
||||
github.com/go-gost/tls-dissector v0.1.0
|
||||
github.com/go-gost/tls-dissector v0.1.1
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/golang/snappy v0.0.4
|
||||
|
||||
@@ -53,8 +53,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-gost/core v0.1.4 h1:uP1r6kpi39NaFtKo6guCjMSvgJl8eTWW3Lb/8+4YDdo=
|
||||
github.com/go-gost/core v0.1.4/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A=
|
||||
github.com/go-gost/core v0.1.5 h1:Rbj+xq+q2RkxviUErjwyT8wbqCa5WeV+UelyIs99dFI=
|
||||
github.com/go-gost/core v0.1.5/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A=
|
||||
github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s=
|
||||
github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc=
|
||||
github.com/go-gost/gosocks5 v0.4.2 h1:IianxHTkACPqCwiOAT3MHoMdSUl+SEPSRu1ikawC1Pc=
|
||||
@@ -63,8 +63,8 @@ github.com/go-gost/plugin v0.1.1 h1:LNoc/Rqwb3ceGhhxwhpjf1SeeYBGe80MJ9E4lpM3qak=
|
||||
github.com/go-gost/plugin v0.1.1/go.mod h1:oN23l+yGDCIP9G3KnDl/I/0zVGOobZUDCB2Z5yYYXts=
|
||||
github.com/go-gost/relay v0.5.0 h1:JG1tgy/KWiVXS0ukuVXvbM0kbYuJTWxYpJ5JwzsCf/c=
|
||||
github.com/go-gost/relay v0.5.0/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8=
|
||||
github.com/go-gost/tls-dissector v0.1.0 h1:hpgzC/Qt9MMGGie+hLeBAZ379OG72sSc1TRiG7+rahI=
|
||||
github.com/go-gost/tls-dissector v0.1.0/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs=
|
||||
github.com/go-gost/tls-dissector v0.1.1 h1:2zUOTPzCQAUQ54Rpy0UEi3JPMQSYsIFSeFeKrzmkCoU=
|
||||
github.com/go-gost/tls-dissector v0.1.1/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -290,7 +291,10 @@ func (h *dnsHandler) request(ctx context.Context, msg []byte, ro *xrecorder.Hand
|
||||
}
|
||||
|
||||
log.Debugf("exchange message %d: %s", mq.Id, mq.Question[0].String())
|
||||
mr, err := h.exchange(ctx, ex, &mq)
|
||||
|
||||
var buf bytes.Buffer
|
||||
mr, err := h.exchange(ctxvalue.ContextWithBuffer(ctx, &buf), ex, &mq)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -196,7 +196,9 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
|
||||
|
||||
log.Debugf("%s >> %s", conn.RemoteAddr(), addr)
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, network, addr)
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), network, addr)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
// TODO: the router itself may be failed due to the failed node in the router,
|
||||
@@ -351,7 +353,9 @@ func (h *forwardHandler) handleHTTP(ctx context.Context, rw io.ReadWriteCloser,
|
||||
bodyRewrites = httpSettings.RewriteBody
|
||||
}
|
||||
|
||||
cc, err = h.options.Router.Dial(ctx, "tcp", target.Addr)
|
||||
var buf bytes.Buffer
|
||||
cc, err = h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", target.Addr)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
// TODO: the router itself may be failed due to the failed node in the router,
|
||||
// the dead marker may be a wrong operation.
|
||||
@@ -376,6 +380,7 @@ func (h *forwardHandler) handleHTTP(ctx context.Context, rw io.ReadWriteCloser,
|
||||
MinVersion: tlsSettings.Options.MinVersion,
|
||||
MaxVersion: tlsSettings.Options.MaxVersion,
|
||||
CipherSuites: tlsSettings.Options.CipherSuites,
|
||||
ALPN: tlsSettings.Options.ALPN,
|
||||
})
|
||||
cc = tls.Client(cc, cfg)
|
||||
}
|
||||
|
||||
@@ -195,7 +195,9 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
|
||||
|
||||
log.Debugf("%s >> %s", conn.RemoteAddr(), target.Addr)
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, network, target.Addr)
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), network, target.Addr)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
// TODO: the router itself may be failed due to the failed node in the router,
|
||||
@@ -278,7 +280,8 @@ func (h *forwardHandler) handleHTTP(ctx context.Context, rw io.ReadWriteCloser,
|
||||
if _, _, err := net.SplitHostPort(host); err != nil {
|
||||
host = net.JoinHostPort(strings.Trim(host, "[]"), "80")
|
||||
}
|
||||
if bp := h.options.Bypass; bp != nil && bp.Contains(ctx, "tcp", host, bypass.WithPathOption(req.RequestURI)) {
|
||||
if bp := h.options.Bypass; bp != nil &&
|
||||
bp.Contains(ctx, "tcp", host, bypass.WithPathOption(req.RequestURI)) {
|
||||
log.Debugf("bypass: %s %s", host, req.RequestURI)
|
||||
resp.StatusCode = http.StatusForbidden
|
||||
resp.Write(rw)
|
||||
@@ -350,7 +353,9 @@ func (h *forwardHandler) handleHTTP(ctx context.Context, rw io.ReadWriteCloser,
|
||||
bodyRewrites = httpSettings.RewriteBody
|
||||
}
|
||||
|
||||
cc, err = h.options.Router.Dial(ctx, "tcp", target.Addr)
|
||||
var buf bytes.Buffer
|
||||
cc, err = h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", target.Addr)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
// TODO: the router itself may be failed due to the failed node in the router,
|
||||
// the dead marker may be a wrong operation.
|
||||
@@ -375,6 +380,7 @@ func (h *forwardHandler) handleHTTP(ctx context.Context, rw io.ReadWriteCloser,
|
||||
MinVersion: tlsSettings.Options.MinVersion,
|
||||
MaxVersion: tlsSettings.Options.MaxVersion,
|
||||
CipherSuites: tlsSettings.Options.CipherSuites,
|
||||
ALPN: tlsSettings.Options.ALPN,
|
||||
})
|
||||
cc = tls.Client(cc, cfg)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package http
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
@@ -267,7 +268,9 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
|
||||
ctx = ctxvalue.ContextWithHash(ctx, &ctxvalue.Hash{Source: addr})
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, network, addr)
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), network, addr)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
resp.StatusCode = http.StatusServiceUnavailable
|
||||
|
||||
|
||||
@@ -243,7 +243,9 @@ func (h *http2Handler) roundTrip(ctx context.Context, w http.ResponseWriter, req
|
||||
ctx = ctxvalue.ContextWithHash(ctx, &ctxvalue.Hash{Source: addr})
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, "tcp", addr)
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", addr)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
resp.StatusCode = http.StatusServiceUnavailable
|
||||
|
||||
+227
-69
@@ -6,6 +6,8 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -133,7 +135,7 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han
|
||||
"dst": fmt.Sprintf("%s/%s", dstAddr, dstAddr.Network()),
|
||||
})
|
||||
|
||||
var rw io.ReadWriter = conn
|
||||
var rw io.ReadWriteCloser = conn
|
||||
if h.md.sniffing {
|
||||
if h.md.sniffingTimeout > 0 {
|
||||
conn.SetReadDeadline(time.Now().Add(h.md.sniffingTimeout))
|
||||
@@ -144,7 +146,7 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han
|
||||
if h.md.sniffingTimeout > 0 {
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
}
|
||||
rw = xio.NewReadWriter(io.MultiReader(bytes.NewReader(hdr[:n]), rw), rw)
|
||||
rw = xio.NewReadWriteCloser(io.MultiReader(bytes.NewReader(hdr[:n]), rw), rw, rw)
|
||||
tlsVersion := binary.BigEndian.Uint16(hdr[1:3])
|
||||
if err == nil &&
|
||||
hdr[0] == dissector.Handshake &&
|
||||
@@ -154,18 +156,24 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han
|
||||
|
||||
// try to sniff HTTP traffic
|
||||
if isHTTP(string(hdr[:])) {
|
||||
return h.handleHTTP(ctx, rw, conn.RemoteAddr(), dstAddr, ro, log)
|
||||
ro2 := &xrecorder.HandlerRecorderObject{}
|
||||
*ro2 = *ro
|
||||
ro.Time = time.Time{}
|
||||
return h.handleHTTP(ctx, rw, conn.RemoteAddr(), dstAddr, ro2, log)
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("%s >> %s", conn.RemoteAddr(), dstAddr)
|
||||
|
||||
if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, dstAddr.Network(), dstAddr.String()) {
|
||||
if h.options.Bypass != nil &&
|
||||
h.options.Bypass.Contains(ctx, dstAddr.Network(), dstAddr.String()) {
|
||||
log.Debug("bypass: ", dstAddr)
|
||||
return xbypass.ErrBypass
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, dstAddr.Network(), dstAddr.String())
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), dstAddr.Network(), dstAddr.String())
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
@@ -182,27 +190,13 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *redirectHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, raddr, dstAddr net.Addr, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||
req, err := http.ReadRequest(bufio.NewReader(rw))
|
||||
func (h *redirectHandler) handleHTTP(ctx context.Context, rw io.ReadWriteCloser, raddr, dstAddr net.Addr, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||
br := bufio.NewReader(rw)
|
||||
req, err := http.ReadRequest(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ro.HTTP = &xrecorder.HTTPRecorderObject{
|
||||
Host: req.Host,
|
||||
Proto: req.Proto,
|
||||
Scheme: req.URL.Scheme,
|
||||
Method: req.Method,
|
||||
URI: req.RequestURI,
|
||||
Request: xrecorder.HTTPRequestRecorderObject{
|
||||
ContentLength: req.ContentLength,
|
||||
Header: req.Header,
|
||||
},
|
||||
}
|
||||
if clientIP := xhttp.GetClientIP(req); clientIP != nil {
|
||||
ro.ClientIP = clientIP.String()
|
||||
}
|
||||
|
||||
if log.IsLevelEnabled(logger.TraceLevel) {
|
||||
dump, _ := httputil.DumpRequest(req, false)
|
||||
log.Trace(string(dump))
|
||||
@@ -217,12 +211,15 @@ func (h *redirectHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, radd
|
||||
"host": host,
|
||||
})
|
||||
|
||||
if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, "tcp", host, bypass.WithPathOption(req.RequestURI)) {
|
||||
if h.options.Bypass != nil &&
|
||||
h.options.Bypass.Contains(ctx, "tcp", host, bypass.WithPathOption(req.RequestURI)) {
|
||||
log.Debugf("bypass: %s %s", host, req.RequestURI)
|
||||
return xbypass.ErrBypass
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, "tcp", host)
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", host)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
if !h.md.sniffingFallback {
|
||||
@@ -231,7 +228,9 @@ func (h *redirectHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, radd
|
||||
}
|
||||
|
||||
if cc == nil {
|
||||
cc, err = h.options.Router.Dial(ctx, "tcp", dstAddr.String())
|
||||
var buf bytes.Buffer
|
||||
cc, err = h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", dstAddr.String())
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
@@ -239,14 +238,138 @@ func (h *redirectHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, radd
|
||||
}
|
||||
defer cc.Close()
|
||||
|
||||
t := time.Now()
|
||||
log.Infof("%s <-> %s", raddr, host)
|
||||
if req.Header.Get("Upgrade") == "websocket" {
|
||||
return h.handleWebsocket(ctx, raddr, rw, cc, req, ro, log)
|
||||
}
|
||||
|
||||
if err := h.httpRoundTrip(ctx, raddr, rw, cc, req, ro, log); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
req, err := http.ReadRequest(br)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if log.IsLevelEnabled(logger.TraceLevel) {
|
||||
dump, _ := httputil.DumpRequest(req, false)
|
||||
log.Trace(string(dump))
|
||||
}
|
||||
|
||||
if err = h.httpRoundTrip(ctx, raddr, rw, cc, req, ro, log); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *redirectHandler) handleWebsocket(ctx context.Context, raddr net.Addr, rw io.ReadWriteCloser, cc io.ReadWriter, req *http.Request, ro *xrecorder.HandlerRecorderObject, log logger.Logger) (err error) {
|
||||
start := time.Now()
|
||||
ro.Time = start
|
||||
|
||||
log.Infof("%s <-> %s", raddr, req.Host)
|
||||
|
||||
defer func() {
|
||||
ro.Duration = time.Since(start)
|
||||
if err != nil {
|
||||
ro.Err = err.Error()
|
||||
}
|
||||
if err := ro.Record(ctx, h.recorder.Recorder); err != nil {
|
||||
log.Errorf("record: %v", err)
|
||||
}
|
||||
|
||||
log.WithFields(map[string]any{
|
||||
"duration": time.Since(t),
|
||||
}).Infof("%s >-< %s", raddr, host)
|
||||
"duration": time.Since(start),
|
||||
}).Infof("%s >-< %s", raddr, req.Host)
|
||||
}()
|
||||
|
||||
ro.HTTP = &xrecorder.HTTPRecorderObject{
|
||||
Host: req.Host,
|
||||
Proto: req.Proto,
|
||||
Scheme: req.URL.Scheme,
|
||||
Method: req.Method,
|
||||
URI: req.RequestURI,
|
||||
Request: xrecorder.HTTPRequestRecorderObject{
|
||||
ContentLength: req.ContentLength,
|
||||
Header: req.Header.Clone(),
|
||||
},
|
||||
}
|
||||
|
||||
if err = req.Write(cc); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
res, err := http.ReadResponse(bufio.NewReader(cc), req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
ro.HTTP.StatusCode = res.StatusCode
|
||||
ro.HTTP.Response.Header = res.Header
|
||||
ro.HTTP.Response.ContentLength = res.ContentLength
|
||||
|
||||
if log.IsLevelEnabled(logger.TraceLevel) {
|
||||
dump, _ := httputil.DumpResponse(res, false)
|
||||
log.Trace(string(dump))
|
||||
}
|
||||
|
||||
if err = res.Write(rw); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
netpkg.Transport(rw, cc)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (h *redirectHandler) httpRoundTrip(ctx context.Context, raddr net.Addr, rw io.ReadWriteCloser, cc io.ReadWriter, req *http.Request, ro *xrecorder.HandlerRecorderObject, log logger.Logger) (err error) {
|
||||
if req == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
ro.Time = start
|
||||
|
||||
log.Infof("%s <-> %s", raddr, req.Host)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
ro.Duration = time.Since(start)
|
||||
ro.Err = err.Error()
|
||||
if err := ro.Record(ctx, h.recorder.Recorder); err != nil {
|
||||
log.Errorf("record: %v", err)
|
||||
}
|
||||
|
||||
log.WithFields(map[string]any{
|
||||
"duration": time.Since(start),
|
||||
}).Infof("%s >-< %s", raddr, req.Host)
|
||||
}
|
||||
}()
|
||||
|
||||
ro.HTTP = &xrecorder.HTTPRecorderObject{
|
||||
Host: req.Host,
|
||||
Proto: req.Proto,
|
||||
Scheme: req.URL.Scheme,
|
||||
Method: req.Method,
|
||||
URI: req.RequestURI,
|
||||
Request: xrecorder.HTTPRequestRecorderObject{
|
||||
ContentLength: req.ContentLength,
|
||||
Header: req.Header.Clone(),
|
||||
},
|
||||
}
|
||||
|
||||
// HTTP/1.0
|
||||
if req.ProtoMajor == 1 && req.ProtoMinor == 0 {
|
||||
if strings.ToLower(req.Header.Get("Connection")) == "keep-alive" {
|
||||
req.Header.Del("Connection")
|
||||
} else {
|
||||
req.Header.Set("Connection", "close")
|
||||
}
|
||||
}
|
||||
|
||||
var reqBody *xhttp.Body
|
||||
if opts := h.recorder.Options; opts != nil && opts.HTTPBody {
|
||||
if req.Body != nil {
|
||||
@@ -258,8 +381,8 @@ func (h *redirectHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, radd
|
||||
req.Body = reqBody
|
||||
}
|
||||
}
|
||||
if err := req.Write(cc); err != nil {
|
||||
log.Error(err)
|
||||
|
||||
if err = req.Write(cc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -268,44 +391,68 @@ func (h *redirectHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, radd
|
||||
ro.HTTP.Request.ContentLength = reqBody.Length()
|
||||
}
|
||||
|
||||
br := bufio.NewReader(cc)
|
||||
resp, err := http.ReadResponse(br, req)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
go func() {
|
||||
var err error
|
||||
var res *http.Response
|
||||
var respBody *xhttp.Body
|
||||
|
||||
ro.HTTP.Response.Header = resp.Header
|
||||
ro.HTTP.StatusCode = resp.StatusCode
|
||||
ro.HTTP.Response.ContentLength = resp.ContentLength
|
||||
defer func() {
|
||||
ro.Duration = time.Since(start)
|
||||
if err != nil {
|
||||
ro.Err = err.Error()
|
||||
}
|
||||
if res != nil {
|
||||
ro.HTTP.StatusCode = res.StatusCode
|
||||
ro.HTTP.Response.Header = res.Header
|
||||
ro.HTTP.Response.ContentLength = res.ContentLength
|
||||
if respBody != nil {
|
||||
ro.HTTP.Response.Body = respBody.Content()
|
||||
ro.HTTP.Response.ContentLength = respBody.Length()
|
||||
}
|
||||
}
|
||||
ro.Record(ctx, h.recorder.Recorder)
|
||||
}()
|
||||
|
||||
if log.IsLevelEnabled(logger.TraceLevel) {
|
||||
dump, _ := httputil.DumpResponse(resp, false)
|
||||
log.Trace(string(dump))
|
||||
}
|
||||
|
||||
var respBody *xhttp.Body
|
||||
if opts := h.recorder.Options; opts != nil && opts.HTTPBody {
|
||||
maxSize := opts.MaxBodySize
|
||||
if maxSize <= 0 {
|
||||
maxSize = defaultBodySize
|
||||
res, err = http.ReadResponse(bufio.NewReader(cc), req)
|
||||
if err != nil {
|
||||
rw.Close()
|
||||
log.Errorf("read response: %v", err)
|
||||
return
|
||||
}
|
||||
respBody = xhttp.NewBody(resp.Body, maxSize)
|
||||
resp.Body = respBody
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if err := resp.Write(rw); err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
if log.IsLevelEnabled(logger.TraceLevel) {
|
||||
dump, _ := httputil.DumpResponse(res, false)
|
||||
log.Trace(string(dump))
|
||||
}
|
||||
|
||||
if respBody != nil {
|
||||
ro.HTTP.Response.Body = respBody.Content()
|
||||
ro.HTTP.Response.ContentLength = resp.ContentLength
|
||||
}
|
||||
if res.Close {
|
||||
defer rw.Close()
|
||||
}
|
||||
|
||||
netpkg.Transport(rw, xio.NewReadWriter(br, cc))
|
||||
// HTTP/1.0
|
||||
if req.ProtoMajor == 1 && req.ProtoMinor == 0 {
|
||||
if !res.Close {
|
||||
res.Header.Set("Connection", "keep-alive")
|
||||
}
|
||||
res.ProtoMajor = req.ProtoMajor
|
||||
res.ProtoMinor = req.ProtoMinor
|
||||
}
|
||||
|
||||
if opts := h.recorder.Options; opts != nil && opts.HTTPBody {
|
||||
maxSize := opts.MaxBodySize
|
||||
if maxSize <= 0 {
|
||||
maxSize = defaultBodySize
|
||||
}
|
||||
respBody = xhttp.NewBody(res.Body, maxSize)
|
||||
res.Body = respBody
|
||||
}
|
||||
|
||||
if err = res.Write(rw); err != nil {
|
||||
rw.Close()
|
||||
log.Errorf("write response: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -318,7 +465,8 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad
|
||||
return err
|
||||
}
|
||||
ro.TLS = &xrecorder.TLSRecorderObject{
|
||||
ServerName: clientHello.ServerName,
|
||||
ServerName: clientHello.ServerName,
|
||||
ClientHello: hex.EncodeToString(buf.Bytes()),
|
||||
}
|
||||
if len(clientHello.SupportedProtos) > 0 {
|
||||
ro.TLS.Proto = clientHello.SupportedProtos[0]
|
||||
@@ -340,12 +488,15 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad
|
||||
})
|
||||
ro.Host = host
|
||||
|
||||
if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, "tcp", host) {
|
||||
if h.options.Bypass != nil &&
|
||||
h.options.Bypass.Contains(ctx, "tcp", host) {
|
||||
log.Debug("bypass: ", host)
|
||||
return xbypass.ErrBypass
|
||||
}
|
||||
|
||||
cc, err = h.options.Router.Dial(ctx, "tcp", host)
|
||||
var routeBuf bytes.Buffer
|
||||
cc, err = h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &routeBuf), "tcp", host)
|
||||
ro.Route = routeBuf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
|
||||
@@ -356,7 +507,9 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad
|
||||
}
|
||||
|
||||
if cc == nil {
|
||||
cc, err = h.options.Router.Dial(ctx, "tcp", dstAddr.String())
|
||||
var routeBuf bytes.Buffer
|
||||
cc, err = h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &routeBuf), "tcp", dstAddr.String())
|
||||
ro.Route = routeBuf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
@@ -368,7 +521,8 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad
|
||||
return err
|
||||
}
|
||||
|
||||
if serverHello, _ := dissector.ParseServerHello(io.TeeReader(cc, buf)); serverHello != nil {
|
||||
serverHello, err := dissector.ParseServerHello(io.TeeReader(cc, buf))
|
||||
if serverHello != nil {
|
||||
ro.TLS.CipherSuite = tls_util.CipherSuite(serverHello.CipherSuite).String()
|
||||
ro.TLS.CompressionMethod = serverHello.CompressionMethod
|
||||
if serverHello.Proto != "" {
|
||||
@@ -379,6 +533,10 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad
|
||||
}
|
||||
}
|
||||
|
||||
if buf.Len() > 0 {
|
||||
ro.TLS.ServerHello = hex.EncodeToString(buf.Bytes())
|
||||
}
|
||||
|
||||
if _, err := buf.WriteTo(rw); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -390,7 +548,7 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad
|
||||
"duration": time.Since(t),
|
||||
}).Infof("%s >-< %s", raddr, host)
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *redirectHandler) checkRateLimit(addr net.Addr) bool {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package redirect
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
@@ -100,12 +101,15 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han
|
||||
|
||||
log.Debugf("%s >> %s", conn.RemoteAddr(), dstAddr)
|
||||
|
||||
if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, dstAddr.Network(), dstAddr.String()) {
|
||||
if h.options.Bypass != nil &&
|
||||
h.options.Bypass.Contains(ctx, dstAddr.Network(), dstAddr.String()) {
|
||||
log.Debug("bypass: ", dstAddr)
|
||||
return xbypass.ErrBypass
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, dstAddr.Network(), dstAddr.String())
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), dstAddr.Network(), dstAddr.String())
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package relay
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -18,9 +19,10 @@ import (
|
||||
serial "github.com/go-gost/x/internal/util/serial"
|
||||
traffic_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||
xrecorder "github.com/go-gost/x/recorder"
|
||||
)
|
||||
|
||||
func (h *relayHandler) handleConnect(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) (err error) {
|
||||
func (h *relayHandler) handleConnect(ctx context.Context, conn net.Conn, network, address string, ro *xrecorder.HandlerRecorderObject, log logger.Logger) (err error) {
|
||||
if network == "unix" || network == "serial" {
|
||||
if host, _, _ := net.SplitHostPort(address); host != "" {
|
||||
address = host
|
||||
@@ -67,7 +69,9 @@ func (h *relayHandler) handleConnect(ctx context.Context, conn net.Conn, network
|
||||
case "serial":
|
||||
cc, err = serial.OpenPort(serial.ParseConfigFromAddr(address))
|
||||
default:
|
||||
cc, err = h.options.Router.Dial(ctx, network, address)
|
||||
var buf bytes.Buffer
|
||||
cc, err = h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), network, address)
|
||||
ro.Route = buf.String()
|
||||
}
|
||||
if err != nil {
|
||||
resp.Status = relay.StatusNetworkUnreachable
|
||||
|
||||
@@ -193,7 +193,7 @@ func (h *relayHandler) Handle(ctx context.Context, conn net.Conn, opts ...handle
|
||||
|
||||
switch req.Cmd & relay.CmdMask {
|
||||
case 0, relay.CmdConnect:
|
||||
return h.handleConnect(ctx, conn, network, address, log)
|
||||
return h.handleConnect(ctx, conn, network, address, ro, log)
|
||||
case relay.CmdBind:
|
||||
return h.handleBind(ctx, conn, network, address, log)
|
||||
default:
|
||||
|
||||
+17
-6
@@ -7,6 +7,7 @@ import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
@@ -176,7 +177,9 @@ func (h *sniHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, raddr net
|
||||
ctx = ctxvalue.ContextWithHash(ctx, &ctxvalue.Hash{Source: host})
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, "tcp", host)
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", host)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
@@ -247,7 +250,7 @@ func (h *sniHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, raddr net
|
||||
|
||||
if respBody != nil {
|
||||
ro.HTTP.Response.Body = respBody.Content()
|
||||
ro.HTTP.Response.ContentLength = resp.ContentLength
|
||||
ro.HTTP.Response.ContentLength = respBody.Length()
|
||||
}
|
||||
|
||||
netpkg.Transport(rw, xio.NewReadWriter(br, cc))
|
||||
@@ -268,7 +271,8 @@ func (h *sniHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, raddr ne
|
||||
return err
|
||||
}
|
||||
ro.TLS = &xrecorder.TLSRecorderObject{
|
||||
ServerName: clientHello.ServerName,
|
||||
ServerName: clientHello.ServerName,
|
||||
ClientHello: hex.EncodeToString(buf.Bytes()),
|
||||
}
|
||||
if len(clientHello.SupportedProtos) > 0 {
|
||||
ro.TLS.Proto = clientHello.SupportedProtos[0]
|
||||
@@ -295,7 +299,9 @@ func (h *sniHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, raddr ne
|
||||
ctx = ctxvalue.ContextWithHash(ctx, &ctxvalue.Hash{Source: host})
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, "tcp", host)
|
||||
var routeBuf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &routeBuf), "tcp", host)
|
||||
ro.Route = routeBuf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
@@ -306,7 +312,8 @@ func (h *sniHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, raddr ne
|
||||
return err
|
||||
}
|
||||
|
||||
if serverHello, _ := dissector.ParseServerHello(io.TeeReader(cc, buf)); serverHello != nil {
|
||||
serverHello, err := dissector.ParseServerHello(io.TeeReader(cc, buf))
|
||||
if serverHello != nil {
|
||||
ro.TLS.CipherSuite = tls_util.CipherSuite(serverHello.CipherSuite).String()
|
||||
ro.TLS.CompressionMethod = serverHello.CompressionMethod
|
||||
if serverHello.Proto != "" {
|
||||
@@ -317,6 +324,10 @@ func (h *sniHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, raddr ne
|
||||
}
|
||||
}
|
||||
|
||||
if buf.Len() > 0 {
|
||||
ro.TLS.ServerHello = hex.EncodeToString(buf.Bytes())
|
||||
}
|
||||
|
||||
if _, err := buf.WriteTo(rw); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -328,7 +339,7 @@ func (h *sniHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, raddr ne
|
||||
"duration": time.Since(t),
|
||||
}).Infof("%s >-< %s", raddr, host)
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *sniHandler) decodeHost(r io.Reader) (host string, err error) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
@@ -148,7 +149,7 @@ func (h *socks4Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl
|
||||
|
||||
switch req.Cmd {
|
||||
case gosocks4.CmdConnect:
|
||||
return h.handleConnect(ctx, conn, req, log)
|
||||
return h.handleConnect(ctx, conn, req, ro, log)
|
||||
case gosocks4.CmdBind:
|
||||
return h.handleBind(ctx, conn, req)
|
||||
default:
|
||||
@@ -165,7 +166,7 @@ func (h *socks4Handler) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *socks4Handler) handleConnect(ctx context.Context, conn net.Conn, req *gosocks4.Request, log logger.Logger) error {
|
||||
func (h *socks4Handler) handleConnect(ctx context.Context, conn net.Conn, req *gosocks4.Request, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||
addr := req.Addr.String()
|
||||
|
||||
log = log.WithFields(map[string]any{
|
||||
@@ -185,7 +186,9 @@ func (h *socks4Handler) handleConnect(ctx context.Context, conn net.Conn, req *g
|
||||
ctx = ctxvalue.ContextWithHash(ctx, &ctxvalue.Hash{Source: addr})
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, "tcp", addr)
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", addr)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
resp := gosocks4.NewReply(gosocks4.Failed, nil)
|
||||
log.Trace(resp)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package v5
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
@@ -14,9 +15,10 @@ import (
|
||||
netpkg "github.com/go-gost/x/internal/net"
|
||||
traffic_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||
xrecorder "github.com/go-gost/x/recorder"
|
||||
)
|
||||
|
||||
func (h *socks5Handler) handleConnect(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) error {
|
||||
func (h *socks5Handler) handleConnect(ctx context.Context, conn net.Conn, network, address string, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||
log = log.WithFields(map[string]any{
|
||||
"dst": fmt.Sprintf("%s/%s", address, network),
|
||||
"cmd": "connect",
|
||||
@@ -35,7 +37,9 @@ func (h *socks5Handler) handleConnect(ctx context.Context, conn net.Conn, networ
|
||||
ctx = ctxvalue.ContextWithHash(ctx, &ctxvalue.Hash{Source: address})
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, network, address)
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), network, address)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
resp := gosocks5.NewReply(gosocks5.NetUnreachable, nil)
|
||||
log.Trace(resp)
|
||||
|
||||
@@ -148,17 +148,17 @@ func (h *socks5Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl
|
||||
|
||||
switch req.Cmd {
|
||||
case gosocks5.CmdConnect:
|
||||
return h.handleConnect(ctx, conn, "tcp", address, log)
|
||||
return h.handleConnect(ctx, conn, "tcp", address, ro, log)
|
||||
case gosocks5.CmdBind:
|
||||
return h.handleBind(ctx, conn, "tcp", address, log)
|
||||
case socks.CmdMuxBind:
|
||||
return h.handleMuxBind(ctx, conn, "tcp", address, log)
|
||||
case gosocks5.CmdUdp:
|
||||
ro.Network = "udp"
|
||||
return h.handleUDP(ctx, conn, log)
|
||||
return h.handleUDP(ctx, conn, ro, log)
|
||||
case socks.CmdUDPTun:
|
||||
ro.Network = "udp"
|
||||
return h.handleUDPTun(ctx, conn, "udp", address, log)
|
||||
return h.handleUDPTun(ctx, conn, "udp", address, ro, log)
|
||||
default:
|
||||
err = ErrUnknownCmd
|
||||
log.Error(err)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package v5
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -16,9 +17,10 @@ import (
|
||||
"github.com/go-gost/x/internal/net/udp"
|
||||
"github.com/go-gost/x/internal/util/socks"
|
||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||
xrecorder "github.com/go-gost/x/recorder"
|
||||
)
|
||||
|
||||
func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, log logger.Logger) error {
|
||||
func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||
log = log.WithFields(map[string]any{
|
||||
"cmd": "udp",
|
||||
})
|
||||
@@ -59,7 +61,9 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, log logger
|
||||
log.Debugf("bind on %s OK", cc.LocalAddr())
|
||||
|
||||
// obtain a udp connection
|
||||
c, err := h.options.Router.Dial(ctx, "udp", "") // UDP association
|
||||
var buf bytes.Buffer
|
||||
c, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "udp", "") // UDP association
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package v5
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
@@ -14,9 +15,10 @@ import (
|
||||
"github.com/go-gost/x/internal/net/udp"
|
||||
"github.com/go-gost/x/internal/util/socks"
|
||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||
xrecorder "github.com/go-gost/x/recorder"
|
||||
)
|
||||
|
||||
func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) error {
|
||||
func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, network, address string, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||
log = log.WithFields(map[string]any{
|
||||
"cmd": "udp-tun",
|
||||
})
|
||||
@@ -37,7 +39,9 @@ func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, network
|
||||
}
|
||||
|
||||
// obtain a udp connection
|
||||
c, err := h.options.Router.Dial(ctx, "udp", "") // UDP association
|
||||
var buf bytes.Buffer
|
||||
c, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "udp", "") // UDP association
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
@@ -136,7 +137,9 @@ func (h *ssHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.H
|
||||
ctx = ctxvalue.ContextWithHash(ctx, &ctxvalue.Hash{Source: addr.String()})
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, "tcp", addr.String())
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", addr.String())
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
@@ -120,7 +121,9 @@ func (h *ssuHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.
|
||||
}
|
||||
|
||||
// obtain a udp connection
|
||||
c, err := h.options.Router.Dial(ctx, "udp", "") // UDP association
|
||||
var buf bytes.Buffer
|
||||
c, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "udp", "") // UDP association
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
@@ -132,7 +133,9 @@ func (h *forwardHandler) handleDirectForward(ctx context.Context, conn *sshd_uti
|
||||
return xbypass.ErrBypass
|
||||
}
|
||||
|
||||
cc, err := h.options.Router.Dial(ctx, "tcp", targetAddr)
|
||||
var buf bytes.Buffer
|
||||
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", targetAddr)
|
||||
ro.Route = buf.String()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -291,6 +291,8 @@ func SetTLSOptions(cfg *tls.Config, opts *config.TLSOptions) {
|
||||
cfg.CipherSuites = append(cfg.CipherSuites, tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
|
||||
}
|
||||
}
|
||||
|
||||
cfg.NextProtos = opts.ALPN
|
||||
}
|
||||
|
||||
func loadCA(caFile string) (cp *x509.CertPool, err error) {
|
||||
|
||||
@@ -44,6 +44,8 @@ type TLSRecorderObject struct {
|
||||
CompressionMethod uint8 `json:"compressionMethod"`
|
||||
Proto string `json:"proto"`
|
||||
Version string `json:"version"`
|
||||
ClientHello string `json:"clientHello"`
|
||||
ServerHello string `json:"serverHello"`
|
||||
}
|
||||
|
||||
type DNSRecorderObject struct {
|
||||
@@ -68,6 +70,7 @@ type HandlerRecorderObject struct {
|
||||
HTTP *HTTPRecorderObject `json:"http,omitempty"`
|
||||
TLS *TLSRecorderObject `json:"tls,omitempty"`
|
||||
DNS *DNSRecorderObject `json:"dns,omitempty"`
|
||||
Route string `json:"route,omitempty"`
|
||||
Err string `json:"err,omitempty"`
|
||||
Duration time.Duration `json:"duration"`
|
||||
Time time.Time `json:"time"`
|
||||
|
||||
Reference in New Issue
Block a user