32c3d33afd
Extract Handle into handleRawForwarding, handleSniffedProtocol, SnifferBuilder, newRecorderObject, and checkRateLimit across forward.go, sniffing.go, and util.go. Replace redundant x509.ParseCertificate with tlsCert.Leaf (already populated by tls.LoadX509KeyPair since Go 1.23).
94 lines
2.4 KiB
Go
94 lines
2.4 KiB
Go
package local
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/go-gost/core/chain"
|
|
"github.com/go-gost/core/hop"
|
|
"github.com/go-gost/core/logger"
|
|
xctx "github.com/go-gost/x/ctx"
|
|
ictx "github.com/go-gost/x/internal/ctx"
|
|
xnet "github.com/go-gost/x/internal/net"
|
|
"github.com/go-gost/x/internal/net/proxyproto"
|
|
xrecorder "github.com/go-gost/x/recorder"
|
|
)
|
|
|
|
// handleRawForwarding performs node selection, dials the target through the
|
|
// router, and pipes the raw connection. It is used when sniffing is disabled
|
|
// or the protocol was not HTTP/TLS.
|
|
func (h *forwardHandler) handleRawForwarding(ctx context.Context, conn net.Conn, ro *xrecorder.HandlerRecorderObject, log logger.Logger, network, proto string) error {
|
|
target := &chain.Node{}
|
|
if curHop := h.getHop(); curHop != nil {
|
|
target = curHop.Select(ctx,
|
|
hop.ProtocolSelectOption(proto),
|
|
)
|
|
}
|
|
if target == nil {
|
|
log.Error(errNodeNotAvailable)
|
|
return errNodeNotAvailable
|
|
}
|
|
addr := target.Addr
|
|
if opts := target.Options(); opts != nil {
|
|
switch opts.Network {
|
|
case "unix":
|
|
network = opts.Network
|
|
default:
|
|
if _, _, err := net.SplitHostPort(addr); err != nil {
|
|
addr += ":0"
|
|
}
|
|
}
|
|
}
|
|
|
|
ro.Network = network
|
|
ro.Host = addr
|
|
|
|
log = log.WithFields(map[string]any{
|
|
"node": target.Name,
|
|
"dst": addr,
|
|
"network": network,
|
|
})
|
|
|
|
log.Debugf("%s >> %s", conn.RemoteAddr(), addr)
|
|
|
|
var buf bytes.Buffer
|
|
cc, err := h.options.Router.Dial(ictx.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,
|
|
// the dead marker may be a wrong operation.
|
|
if marker := target.Marker(); marker != nil {
|
|
marker.Mark()
|
|
}
|
|
return err
|
|
}
|
|
if marker := target.Marker(); marker != nil {
|
|
marker.Reset()
|
|
}
|
|
defer cc.Close()
|
|
|
|
cc = proxyproto.WrapClientConn(
|
|
h.md.proxyProtocol,
|
|
xctx.SrcAddrFromContext(ctx),
|
|
xctx.DstAddrFromContext(ctx),
|
|
cc)
|
|
|
|
log = log.WithFields(map[string]any{"src": cc.LocalAddr().String(), "dst": cc.RemoteAddr().String()})
|
|
ro.SrcAddr = cc.LocalAddr().String()
|
|
ro.DstAddr = cc.RemoteAddr().String()
|
|
|
|
t := time.Now()
|
|
log.Infof("%s <-> %s", conn.RemoteAddr(), target.Addr)
|
|
if err := xnet.Pipe(ctx, conn, cc, xnet.WithReadTimeout(h.md.readTimeout)); err != nil {
|
|
log.Debugf("pipe: %v", err)
|
|
}
|
|
log.WithFields(map[string]any{
|
|
"duration": time.Since(t),
|
|
}).Infof("%s >-< %s", conn.RemoteAddr(), target.Addr)
|
|
|
|
return nil
|
|
}
|