tunnel: fix tunnel routing for public entrypoint

This commit is contained in:
ginuerzh
2024-11-22 22:04:44 +08:00
parent 2e8a5d6f51
commit 6f001a779a
6 changed files with 61 additions and 19 deletions
+5 -3
View File
@@ -406,11 +406,13 @@ type HTTPNodeConfig struct {
// Deprecated: use requestHeader instead // Deprecated: use requestHeader instead
Header map[string]string `yaml:",omitempty" json:"header,omitempty"` Header map[string]string `yaml:",omitempty" json:"header,omitempty"`
// additional request header // additional request header
RequestHeader map[string]string `yaml:",omitempty" json:"requestHeader,omitempty"` RequestHeader map[string]string `yaml:"requestHeader,omitempty" json:"requestHeader,omitempty"`
// additional response header // additional response header
ResponseHeader map[string]string `yaml:",omitempty" json:"responseHeader,omitempty"` ResponseHeader map[string]string `yaml:"responseHeader,omitempty" json:"responseHeader,omitempty"`
// rewrite URL // Deprecated: use rewriteURL instead
Rewrite []HTTPURLRewriteConfig `yaml:",omitempty" json:"rewrite,omitempty"` Rewrite []HTTPURLRewriteConfig `yaml:",omitempty" json:"rewrite,omitempty"`
// rewrite URL
RewriteURL []HTTPURLRewriteConfig `yaml:"rewriteURL,omitempty" json:"rewriteURL,omitempty"`
// rewrite response body // rewrite response body
RewriteBody []HTTPBodyRewriteConfig `yaml:"rewriteBody,omitempty" json:"rewriteBody,omitempty"` RewriteBody []HTTPBodyRewriteConfig `yaml:"rewriteBody,omitempty" json:"rewriteBody,omitempty"`
// HTTP basic auth // HTTP basic auth
+6 -1
View File
@@ -215,7 +215,12 @@ func ParseNode(hop string, cfg *config.NodeConfig, log logger.Logger) (*chain.No
})), })),
) )
} }
for _, v := range cfg.HTTP.Rewrite {
rewriteURL := cfg.HTTP.RewriteURL
if rewriteURL == nil {
rewriteURL = cfg.HTTP.Rewrite
}
for _, v := range rewriteURL {
if pattern, _ := regexp.Compile(v.Match); pattern != nil { if pattern, _ := regexp.Compile(v.Match); pattern != nil {
settings.RewriteURL = append(settings.RewriteURL, chain.HTTPURLRewriteSetting{ settings.RewriteURL = append(settings.RewriteURL, chain.HTTPURLRewriteSetting{
Pattern: pattern, Pattern: pattern,
+4 -1
View File
@@ -92,7 +92,10 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
ro.ClientIP = conn.RemoteAddr().String() ro.ClientIP = conn.RemoteAddr().String()
if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" { if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" {
ro.ClientIP = string(clientAddr) ro.ClientIP = string(clientAddr)
} else {
ctx = ctxvalue.ContextWithClientAddr(ctx, ctxvalue.ClientAddr(conn.RemoteAddr().String()))
} }
if h, _, _ := net.SplitHostPort(ro.ClientIP); h != "" { if h, _, _ := net.SplitHostPort(ro.ClientIP); h != "" {
ro.ClientIP = h ro.ClientIP = h
} }
@@ -100,7 +103,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
log := h.options.Logger.WithFields(map[string]any{ log := h.options.Logger.WithFields(map[string]any{
"remote": conn.RemoteAddr().String(), "remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(), "local": conn.LocalAddr().String(),
"sid": ctxvalue.SidFromContext(ctx), "sid": ro.SID,
"client": ro.ClientIP, "client": ro.ClientIP,
}) })
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
+17 -1
View File
@@ -23,6 +23,7 @@ import (
"github.com/go-gost/x/internal/util/sniffing" "github.com/go-gost/x/internal/util/sniffing"
tls_util "github.com/go-gost/x/internal/util/tls" tls_util "github.com/go-gost/x/internal/util/tls"
rate_limiter "github.com/go-gost/x/limiter/rate" rate_limiter "github.com/go-gost/x/limiter/rate"
mdutil "github.com/go-gost/x/metadata/util"
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
xrecorder "github.com/go-gost/x/recorder" xrecorder "github.com/go-gost/x/recorder"
"github.com/go-gost/x/registry" "github.com/go-gost/x/registry"
@@ -93,7 +94,10 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
ro.ClientIP = conn.RemoteAddr().String() ro.ClientIP = conn.RemoteAddr().String()
if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" { if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" {
ro.ClientIP = string(clientAddr) ro.ClientIP = string(clientAddr)
} else {
ctx = ctxvalue.ContextWithClientAddr(ctx, ctxvalue.ClientAddr(conn.RemoteAddr().String()))
} }
if h, _, _ := net.SplitHostPort(ro.ClientIP); h != "" { if h, _, _ := net.SplitHostPort(ro.ClientIP); h != "" {
ro.ClientIP = h ro.ClientIP = h
} }
@@ -101,7 +105,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
log := h.options.Logger.WithFields(map[string]any{ log := h.options.Logger.WithFields(map[string]any{
"remote": conn.RemoteAddr().String(), "remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(), "local": conn.LocalAddr().String(),
"sid": ctxvalue.SidFromContext(ctx), "sid": ro.SID,
"client": ro.ClientIP, "client": ro.ClientIP,
}) })
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
@@ -137,6 +141,13 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
return rate_limiter.ErrRateLimit return rate_limiter.ErrRateLimit
} }
var host string
if md, ok := conn.(mdata.Metadatable); ok {
if v := mdutil.GetString(md.Metadata(), "host"); v != "" {
host = v
}
}
var proto string var proto string
if network == "tcp" && h.md.sniffing { if network == "tcp" && h.md.sniffing {
if h.md.sniffingTimeout > 0 { if h.md.sniffingTimeout > 0 {
@@ -193,6 +204,11 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
} }
var target *chain.Node var target *chain.Node
if host != "" {
target = &chain.Node{
Addr: host,
}
}
if h.hop != nil { if h.hop != nil {
target = h.hop.Select(ctx, target = h.hop.Select(ctx,
hop.ProtocolSelectOption(proto), hop.ProtocolSelectOption(proto),
+25 -9
View File
@@ -33,19 +33,35 @@ func (h *tunnelHandler) handleConnect(ctx context.Context, req *relay.Request, c
host, _, _ := net.SplitHostPort(dstAddr) host, _, _ := net.SplitHostPort(dstAddr)
// client is a public entrypoint.
if tunnelID.Equal(h.md.entryPointID) {
resp.WriteTo(conn)
return h.ep.Handle(ctx, conn)
}
if !h.md.directTunnel {
var tid relay.TunnelID var tid relay.TunnelID
if ingress := h.md.ingress; ingress != nil && host != "" { if ingress := h.md.ingress; ingress != nil && host != "" {
if rule := ingress.GetRule(ctx, host); rule != nil { if rule := ingress.GetRule(ctx, host); rule != nil {
tid = parseTunnelID(rule.Endpoint) tid = parseTunnelID(rule.Endpoint)
} }
} }
// visitor is a public entrypoint.
if tunnelID.Equal(h.md.entryPointID) {
if tid.IsZero() {
resp.Status = relay.StatusNetworkUnreachable
resp.WriteTo(conn)
err := fmt.Errorf("no route to host %s", host)
log.Error(err)
return err
}
if tid.IsPrivate() {
resp.Status = relay.StatusHostUnreachable
resp.WriteTo(conn)
err := fmt.Errorf("tunnel %s is private for host %s", tid, host)
log.Error(err)
return err
}
} else {
// direct routing
if h.md.directTunnel {
tid = tunnelID
}
if !tid.Equal(tunnelID) { if !tid.Equal(tunnelID) {
resp.Status = relay.StatusHostUnreachable resp.Status = relay.StatusHostUnreachable
resp.WriteTo(conn) resp.WriteTo(conn)
@@ -63,7 +79,7 @@ func (h *tunnelHandler) handleConnect(ctx context.Context, req *relay.Request, c
timeout: 15 * time.Second, timeout: 15 * time.Second,
log: log, log: log,
} }
cc, node, cid, err := d.Dial(ctx, network, tunnelID.String()) cc, node, cid, err := d.Dial(ctx, network, tid.String())
if err != nil { if err != nil {
log.Error(err) log.Error(err)
resp.Status = relay.StatusServiceUnavailable resp.Status = relay.StatusServiceUnavailable
@@ -72,7 +88,7 @@ func (h *tunnelHandler) handleConnect(ctx context.Context, req *relay.Request, c
} }
defer cc.Close() defer cc.Close()
log.Debugf("connected to node=%s tunnel=%s connector=%s", node, tunnelID, cid) log.Debugf("connect to node=%s tunnel=%s connector=%s OK", node, tid, cid)
if node == h.id { if node == h.id {
if _, err := resp.WriteTo(conn); err != nil { if _, err := resp.WriteTo(conn); err != nil {
+1 -1
View File
@@ -260,7 +260,7 @@ func (t *Tunnel) clean() {
var connectors []*Connector var connectors []*Connector
for _, c := range t.connectors { for _, c := range t.connectors {
if c.IsClosed() { if c.IsClosed() {
c.log.Debugf("remove connector: %s", t.id, c.id) c.log.Debugf("remove connector: %s %s", t.id, c.id)
continue continue
} }