fix http body recorder

This commit is contained in:
ginuerzh
2024-10-22 22:51:33 +08:00
parent 3b4fd643de
commit a97ac1f30a
14 changed files with 159 additions and 51 deletions
+19
View File
@@ -271,3 +271,22 @@ func (p *localAdmission) Close() error {
} }
return nil return nil
} }
type admissionGroup struct {
admissions []admission.Admission
}
func AdmissionGroup(admissions ...admission.Admission) admission.Admission {
return &admissionGroup{
admissions: admissions,
}
}
func (p *admissionGroup) Admit(ctx context.Context, addr string, opts ...admission.Option) bool {
for _, admission := range p.admissions {
if admission != nil && !admission.Admit(ctx, addr, opts...) {
return false
}
}
return true
}
+26
View File
@@ -252,3 +252,29 @@ func (p *authenticator) Close() error {
} }
return nil return nil
} }
type authenticatorGroup struct {
authers []auth.Authenticator
}
func AuthenticatorGroup(authers ...auth.Authenticator) auth.Authenticator {
return &authenticatorGroup{
authers: authers,
}
}
func (p *authenticatorGroup) Authenticate(ctx context.Context, user, password string, opts ...auth.Option) (string, bool) {
if len(p.authers) == 0 {
return "", false
}
for _, auther := range p.authers {
if auther == nil {
continue
}
if id, ok := auther.Authenticate(ctx, user, password, opts...); ok {
return id, ok
}
}
return "", false
}
+43
View File
@@ -6,6 +6,7 @@ import (
"errors" "errors"
"io" "io"
"net" "net"
"slices"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -288,3 +289,45 @@ func (bp *localBypass) Close() error {
} }
return nil return nil
} }
type bypassGroup struct {
bypasses []bypass.Bypass
}
func BypassGroup(bypasses ...bypass.Bypass) bypass.Bypass {
return &bypassGroup{
bypasses: bypasses,
}
}
func (p *bypassGroup) Contains(ctx context.Context, network, addr string, opts ...bypass.Option) bool {
var whitelist, blacklist []bool
for _, bypass := range p.bypasses {
result := bypass.Contains(ctx, network, addr, opts...)
if bypass.IsWhitelist() {
whitelist = append(whitelist, result)
} else {
blacklist = append(blacklist, result)
}
}
status := false
if len(whitelist) > 0 {
if slices.Contains(whitelist, false) {
status = false
} else {
status = true
}
}
if !status && len(blacklist) > 0 {
if slices.Contains(blacklist, true) {
status = true
} else {
status = false
}
}
return status
}
func (p *bypassGroup) IsWhitelist() bool {
return false
}
+2 -2
View File
@@ -4,10 +4,10 @@ import (
"crypto/tls" "crypto/tls"
"strings" "strings"
"github.com/go-gost/core/bypass"
"github.com/go-gost/core/chain" "github.com/go-gost/core/chain"
"github.com/go-gost/core/hop" "github.com/go-gost/core/hop"
"github.com/go-gost/core/logger" "github.com/go-gost/core/logger"
xbypass "github.com/go-gost/x/bypass"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
"github.com/go-gost/x/config/parsing" "github.com/go-gost/x/config/parsing"
bypass_parser "github.com/go-gost/x/config/parsing/bypass" bypass_parser "github.com/go-gost/x/config/parsing/bypass"
@@ -115,7 +115,7 @@ func ParseHop(cfg *config.HopConfig, log logger.Logger) (hop.Hop, error) {
xhop.NameOption(cfg.Name), xhop.NameOption(cfg.Name),
xhop.NodeOption(nodes...), xhop.NodeOption(nodes...),
xhop.SelectorOption(sel), xhop.SelectorOption(sel),
xhop.BypassOption(bypass.BypassGroup(bypass_parser.List(cfg.Bypass, cfg.Bypasses...)...)), xhop.BypassOption(xbypass.BypassGroup(bypass_parser.List(cfg.Bypass, cfg.Bypasses...)...)),
xhop.ReloadPeriodOption(cfg.Reload), xhop.ReloadPeriodOption(cfg.Reload),
xhop.LoggerOption(log.WithFields(map[string]any{ xhop.LoggerOption(log.WithFields(map[string]any{
"kind": "hop", "kind": "hop",
+3 -3
View File
@@ -6,14 +6,13 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/go-gost/core/bypass"
"github.com/go-gost/core/chain" "github.com/go-gost/core/chain"
"github.com/go-gost/core/connector" "github.com/go-gost/core/connector"
"github.com/go-gost/core/dialer" "github.com/go-gost/core/dialer"
"github.com/go-gost/core/logger" "github.com/go-gost/core/logger"
"github.com/go-gost/core/metadata" "github.com/go-gost/core/metadata"
mdutil "github.com/go-gost/x/metadata/util"
xauth "github.com/go-gost/x/auth" xauth "github.com/go-gost/x/auth"
xbypass "github.com/go-gost/x/bypass"
xchain "github.com/go-gost/x/chain" xchain "github.com/go-gost/x/chain"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
"github.com/go-gost/x/config/parsing" "github.com/go-gost/x/config/parsing"
@@ -21,6 +20,7 @@ import (
bypass_parser "github.com/go-gost/x/config/parsing/bypass" bypass_parser "github.com/go-gost/x/config/parsing/bypass"
tls_util "github.com/go-gost/x/internal/util/tls" tls_util "github.com/go-gost/x/internal/util/tls"
mdx "github.com/go-gost/x/metadata" mdx "github.com/go-gost/x/metadata"
mdutil "github.com/go-gost/x/metadata/util"
"github.com/go-gost/x/registry" "github.com/go-gost/x/registry"
) )
@@ -149,7 +149,7 @@ func ParseNode(hop string, cfg *config.NodeConfig, log logger.Logger) (*chain.No
opts := []chain.NodeOption{ opts := []chain.NodeOption{
chain.TransportNodeOption(tr), chain.TransportNodeOption(tr),
chain.BypassNodeOption(bypass.BypassGroup(bypass_parser.List(cfg.Bypass, cfg.Bypasses...)...)), chain.BypassNodeOption(xbypass.BypassGroup(bypass_parser.List(cfg.Bypass, cfg.Bypasses...)...)),
chain.ResoloverNodeOption(registry.ResolverRegistry().Get(cfg.Resolver)), chain.ResoloverNodeOption(registry.ResolverRegistry().Get(cfg.Resolver)),
chain.HostMapperNodeOption(registry.HostsRegistry().Get(cfg.Hosts)), chain.HostMapperNodeOption(registry.HostsRegistry().Get(cfg.Hosts)),
chain.MetadataNodeOption(nm), chain.MetadataNodeOption(nm),
+8 -7
View File
@@ -6,9 +6,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-gost/core/admission"
"github.com/go-gost/core/auth" "github.com/go-gost/core/auth"
"github.com/go-gost/core/bypass"
"github.com/go-gost/core/chain" "github.com/go-gost/core/chain"
"github.com/go-gost/core/handler" "github.com/go-gost/core/handler"
"github.com/go-gost/core/hop" "github.com/go-gost/core/hop"
@@ -18,6 +16,9 @@ import (
"github.com/go-gost/core/recorder" "github.com/go-gost/core/recorder"
"github.com/go-gost/core/selector" "github.com/go-gost/core/selector"
"github.com/go-gost/core/service" "github.com/go-gost/core/service"
xadmission "github.com/go-gost/x/admission"
xauth "github.com/go-gost/x/auth"
xbypass "github.com/go-gost/x/bypass"
xchain "github.com/go-gost/x/chain" xchain "github.com/go-gost/x/chain"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
"github.com/go-gost/x/config/parsing" "github.com/go-gost/x/config/parsing"
@@ -84,7 +85,7 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
} }
var auther auth.Authenticator var auther auth.Authenticator
if len(authers) > 0 { if len(authers) > 0 {
auther = auth.AuthenticatorGroup(authers...) auther = xauth.AuthenticatorGroup(authers...)
} }
admissions := admission_parser.List(cfg.Admission, cfg.Admissions...) admissions := admission_parser.List(cfg.Admission, cfg.Admissions...)
@@ -155,7 +156,7 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
listener.AutherOption(auther), listener.AutherOption(auther),
listener.AuthOption(auth_parser.Info(cfg.Listener.Auth)), listener.AuthOption(auth_parser.Info(cfg.Listener.Auth)),
listener.TLSConfigOption(tlsConfig), listener.TLSConfigOption(tlsConfig),
listener.AdmissionOption(admission.AdmissionGroup(admissions...)), listener.AdmissionOption(xadmission.AdmissionGroup(admissions...)),
listener.TrafficLimiterOption(registry.TrafficLimiterRegistry().Get(cfg.Limiter)), listener.TrafficLimiterOption(registry.TrafficLimiterRegistry().Get(cfg.Limiter)),
listener.ConnLimiterOption(registry.ConnLimiterRegistry().Get(cfg.CLimiter)), listener.ConnLimiterOption(registry.ConnLimiterRegistry().Get(cfg.CLimiter)),
listener.ServiceOption(cfg.Name), listener.ServiceOption(cfg.Name),
@@ -235,7 +236,7 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
auther = nil auther = nil
if len(authers) > 0 { if len(authers) > 0 {
auther = auth.AuthenticatorGroup(authers...) auther = xauth.AuthenticatorGroup(authers...)
} }
var recorders []recorder.RecorderObject var recorders []recorder.RecorderObject
@@ -277,7 +278,7 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
handler.RouterOption(xchain.NewRouter(routerOpts...)), handler.RouterOption(xchain.NewRouter(routerOpts...)),
handler.AutherOption(auther), handler.AutherOption(auther),
handler.AuthOption(auth_parser.Info(cfg.Handler.Auth)), handler.AuthOption(auth_parser.Info(cfg.Handler.Auth)),
handler.BypassOption(bypass.BypassGroup(bypass_parser.List(cfg.Bypass, cfg.Bypasses...)...)), handler.BypassOption(xbypass.BypassGroup(bypass_parser.List(cfg.Bypass, cfg.Bypasses...)...)),
handler.TLSConfigOption(tlsConfig), handler.TLSConfigOption(tlsConfig),
handler.RateLimiterOption(registry.RateLimiterRegistry().Get(cfg.RLimiter)), handler.RateLimiterOption(registry.RateLimiterRegistry().Get(cfg.RLimiter)),
handler.TrafficLimiterOption(registry.TrafficLimiterRegistry().Get(cfg.Handler.Limiter)), handler.TrafficLimiterOption(registry.TrafficLimiterRegistry().Get(cfg.Handler.Limiter)),
@@ -309,7 +310,7 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
} }
s := xservice.NewService(cfg.Name, ln, h, s := xservice.NewService(cfg.Name, ln, h,
xservice.AdmissionOption(admission.AdmissionGroup(admissions...)), xservice.AdmissionOption(xadmission.AdmissionGroup(admissions...)),
xservice.PreUpOption(preUp), xservice.PreUpOption(preUp),
xservice.PreDownOption(preDown), xservice.PreDownOption(preDown),
xservice.PostUpOption(postUp), xservice.PostUpOption(postUp),
+11 -8
View File
@@ -561,17 +561,18 @@ func (h *httpHandler) proxyRoundTrip(ctx context.Context, rw io.ReadWriter, req
ctx = ctxvalue.ContextWithLogger(ctx, log) ctx = ctxvalue.ContextWithLogger(ctx, log)
resp, err := h.transport.RoundTrip(req.WithContext(ctx)) resp, err := h.transport.RoundTrip(req.WithContext(ctx))
if err != nil {
res.Write(rw)
return
}
defer resp.Body.Close()
if reqBody != nil { if reqBody != nil {
ro.HTTP.Request.Body = reqBody.Content() ro.HTTP.Request.Body = reqBody.Content()
ro.HTTP.Request.ContentLength = reqBody.Length() ro.HTTP.Request.ContentLength = reqBody.Length()
} }
if err != nil {
res.Write(rw)
return
}
defer resp.Body.Close()
ro.HTTP.StatusCode = resp.StatusCode ro.HTTP.StatusCode = resp.StatusCode
ro.HTTP.Response.Header = resp.Header.Clone() ro.HTTP.Response.Header = resp.Header.Clone()
ro.HTTP.Response.ContentLength = resp.ContentLength ro.HTTP.Response.ContentLength = resp.ContentLength
@@ -607,15 +608,17 @@ func (h *httpHandler) proxyRoundTrip(ctx context.Context, rw io.ReadWriter, req
resp.Body = respBody resp.Body = respBody
} }
if err = resp.Write(rw); err != nil { err = resp.Write(rw)
return fmt.Errorf("write response: %v", err)
}
if respBody != nil { if respBody != nil {
ro.HTTP.Response.Body = respBody.Content() ro.HTTP.Response.Body = respBody.Content()
ro.HTTP.Response.ContentLength = respBody.Length() ro.HTTP.Response.ContentLength = respBody.Length()
} }
if err != nil {
return fmt.Errorf("write response: %v", err)
}
return return
} }
+8 -4
View File
@@ -37,11 +37,15 @@ func (h *tunnelHandler) handleBind(ctx context.Context, conn net.Conn, network,
v := md5.Sum([]byte(tunnelID.String())) v := md5.Sum([]byte(tunnelID.String()))
endpoint := hex.EncodeToString(v[:8]) endpoint := hex.EncodeToString(v[:8])
addr := address host, port, _ := net.SplitHostPort(address)
host, port, _ := net.SplitHostPort(addr) if host == "" || h.md.ingress == nil {
if host == "" { host = endpoint
addr = net.JoinHostPort(endpoint, port) } else if host != endpoint {
if rule := h.md.ingress.GetRule(ctx, host); rule != nil && rule.Endpoint != tunnelID.String() {
host = endpoint
}
} }
addr := net.JoinHostPort(host, port)
af := &relay.AddrFeature{} af := &relay.AddrFeature{}
err = af.ParseFrom(addr) err = af.ParseFrom(addr)
+1 -1
View File
@@ -72,7 +72,7 @@ func (h *tunnelHandler) handleConnect(ctx context.Context, req *relay.Request, c
} }
defer cc.Close() defer cc.Close()
log.Debugf("new connection to tunnel: %s, connector: %s", tunnelID, cid) log.Debugf("connected to node=%s tunnel=%s connector=%s", node, tunnelID, cid)
if node == h.id { if node == h.id {
if _, err := resp.WriteTo(conn); err != nil { if _, err := resp.WriteTo(conn); err != nil {
+2 -2
View File
@@ -68,11 +68,11 @@ func (d *Dialer) Dial(ctx context.Context, network string, tid string) (conn net
} }
node = service.Node node = service.Node
cid = service.Name cid = service.ID
dialer := net.Dialer{ dialer := net.Dialer{
Timeout: d.timeout, Timeout: d.timeout,
} }
conn, err = dialer.DialContext(ctx, network, service.Address) conn, err = dialer.DialContext(ctx, "tcp", service.Address)
return return
} }
+11 -8
View File
@@ -324,6 +324,12 @@ func (ep *entrypoint) httpRoundTrip(ctx context.Context, rw io.ReadWriter, req *
ctx = ctxvalue.ContextWithLogger(ctx, log) ctx = ctxvalue.ContextWithLogger(ctx, log)
resp, err := ep.transport.RoundTrip(req.WithContext(ctx)) resp, err := ep.transport.RoundTrip(req.WithContext(ctx))
if reqBody != nil {
ro.HTTP.Request.Body = reqBody.Content()
ro.HTTP.Request.ContentLength = reqBody.Length()
}
if err != nil { if err != nil {
if errors.Is(err, ErrTunnelRoute) || errors.Is(err, ErrPrivateTunnel) { if errors.Is(err, ErrTunnelRoute) || errors.Is(err, ErrPrivateTunnel) {
res.StatusCode = http.StatusBadGateway res.StatusCode = http.StatusBadGateway
@@ -334,11 +340,6 @@ func (ep *entrypoint) httpRoundTrip(ctx context.Context, rw io.ReadWriter, req *
} }
defer resp.Body.Close() defer resp.Body.Close()
if reqBody != nil {
ro.HTTP.Request.Body = reqBody.Content()
ro.HTTP.Request.ContentLength = reqBody.Length()
}
ro.HTTP.StatusCode = resp.StatusCode ro.HTTP.StatusCode = resp.StatusCode
ro.HTTP.Response.Header = resp.Header ro.HTTP.Response.Header = resp.Header
ro.HTTP.Response.ContentLength = resp.ContentLength ro.HTTP.Response.ContentLength = resp.ContentLength
@@ -365,15 +366,17 @@ func (ep *entrypoint) httpRoundTrip(ctx context.Context, rw io.ReadWriter, req *
resp.Body = respBody resp.Body = respBody
} }
if err = resp.Write(rw); err != nil { err = resp.Write(rw)
return fmt.Errorf("write response: %v", err)
}
if respBody != nil { if respBody != nil {
ro.HTTP.Response.Body = respBody.Content() ro.HTTP.Response.Body = respBody.Content()
ro.HTTP.Response.ContentLength = respBody.Length() ro.HTTP.Response.ContentLength = respBody.Length()
} }
if err != nil {
return fmt.Errorf("write response: %v", err)
}
return return
} }
+12 -8
View File
@@ -453,16 +453,18 @@ func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, node
} }
} }
if err = req.Write(cc); err != nil { err = req.Write(cc)
res.Write(rw)
return
}
if reqBody != nil { if reqBody != nil {
ro.HTTP.Request.Body = reqBody.Content() ro.HTTP.Request.Body = reqBody.Content()
ro.HTTP.Request.ContentLength = reqBody.Length() ro.HTTP.Request.ContentLength = reqBody.Length()
} }
if err != nil {
res.Write(rw)
return
}
xio.SetReadDeadline(cc, time.Now().Add(h.ReadTimeout)) xio.SetReadDeadline(cc, time.Now().Add(h.ReadTimeout))
resp, err := http.ReadResponse(bufio.NewReader(cc), req) resp, err := http.ReadResponse(bufio.NewReader(cc), req)
if err != nil { if err != nil {
@@ -514,16 +516,18 @@ func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, node
resp.Body = respBody resp.Body = respBody
} }
if err = resp.Write(rw); err != nil { err = resp.Write(rw)
log.Errorf("write response: %v", err)
return
}
if respBody != nil { if respBody != nil {
ro.HTTP.Response.Body = respBody.Content() ro.HTTP.Response.Body = respBody.Content()
ro.HTTP.Response.ContentLength = respBody.Length() ro.HTTP.Response.ContentLength = respBody.Length()
} }
if err != nil {
log.Errorf("write response: %v", err)
return
}
return resp.Close, nil return resp.Close, nil
} }
+11 -7
View File
@@ -323,15 +323,17 @@ func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, req *
} }
} }
if err = req.Write(cc); err != nil { err = req.Write(cc)
return
}
if reqBody != nil { if reqBody != nil {
ro.HTTP.Request.Body = reqBody.Content() ro.HTTP.Request.Body = reqBody.Content()
ro.HTTP.Request.ContentLength = reqBody.Length() ro.HTTP.Request.ContentLength = reqBody.Length()
} }
if err != nil {
return
}
xio.SetReadDeadline(cc, time.Now().Add(h.ReadTimeout)) xio.SetReadDeadline(cc, time.Now().Add(h.ReadTimeout))
resp, err := http.ReadResponse(bufio.NewReader(cc), req) resp, err := http.ReadResponse(bufio.NewReader(cc), req)
if err != nil { if err != nil {
@@ -377,16 +379,18 @@ func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, req *
resp.Body = respBody resp.Body = respBody
} }
if err = resp.Write(rw); err != nil { err = resp.Write(rw)
err = fmt.Errorf("write response: %w", err)
return
}
if respBody != nil { if respBody != nil {
ro.HTTP.Response.Body = respBody.Content() ro.HTTP.Response.Body = respBody.Content()
ro.HTTP.Response.ContentLength = respBody.Length() ro.HTTP.Response.ContentLength = respBody.Length()
} }
if err != nil {
err = fmt.Errorf("write response: %w", err)
return
}
return resp.Close, nil return resp.Close, nil
} }
+2 -1
View File
@@ -117,8 +117,9 @@ func (p *grpcPlugin) Get(ctx context.Context, name string) ([]*sd.Service, error
continue continue
} }
services = append(services, &sd.Service{ services = append(services, &sd.Service{
Node: v.Node, ID: v.Id,
Name: v.Name, Name: v.Name,
Node: v.Node,
Network: v.Network, Network: v.Network,
Address: v.Address, Address: v.Address,
}) })