router: router.id is optional

This commit is contained in:
ginuerzh
2025-02-11 20:54:52 +08:00
parent fc12e33786
commit ef440e8b4a
5 changed files with 86 additions and 44 deletions
+2
View File
@@ -90,9 +90,11 @@ func (c *routerConnector) Connect(ctx context.Context, conn net.Conn, network, a
af.ParseFrom(address) af.ParseFrom(address)
req.Features = append(req.Features, af) // dst address req.Features = append(req.Features, af) // dst address
if !c.md.routerID.IsZero() {
req.Features = append(req.Features, &relay.TunnelFeature{ req.Features = append(req.Features, &relay.TunnelFeature{
ID: c.md.routerID, ID: c.md.routerID,
}) })
}
if _, err := req.WriteTo(conn); err != nil { if _, err := req.WriteTo(conn); err != nil {
return nil, err return nil, err
-8
View File
@@ -30,13 +30,5 @@ func (c *routerConnector) parseMetadata(md mdata.Metadata) (err error) {
c.md.routerID = relay.NewTunnelID(uuid[:]) c.md.routerID = relay.NewTunnelID(uuid[:])
} }
if c.md.routerID.IsZero() {
uuid, err := uuid.NewUUID()
if err != nil {
return err
}
c.md.routerID = relay.NewTunnelID(uuid[:])
}
return return
} }
+51 -12
View File
@@ -10,6 +10,7 @@ import (
"math" "math"
"net" "net"
"sync" "sync"
"time"
"github.com/go-gost/core/common/bufpool" "github.com/go-gost/core/common/bufpool"
"github.com/go-gost/core/limiter" "github.com/go-gost/core/limiter"
@@ -48,7 +49,7 @@ func (h *routerHandler) handleAssociate(ctx context.Context, conn net.Conn, netw
rid = parseRouterID(rule.Endpoint) rid = parseRouterID(rule.Endpoint)
} }
if rid.IsZero() || !rid.Equal(routerID) { if !rid.Equal(routerID) {
resp.Status = relay.StatusHostUnreachable resp.Status = relay.StatusHostUnreachable
resp.WriteTo(conn) resp.WriteTo(conn)
err := fmt.Errorf("no route to host %s", host) err := fmt.Errorf("no route to host %s", host)
@@ -111,13 +112,19 @@ func (h *routerHandler) handleAssociate(ctx context.Context, conn net.Conn, netw
Name: clientID, Name: clientID,
Node: h.id, Node: h.id,
}) })
ctx, cancel := context.WithCancel(ctx)
defer cancel()
go h.sdRenew(ctx, clientID, connectorID.String())
} }
log.Debugf("%s/%s: router=%s, connector=%s, weight=%d established", host, network, routerID, connectorID, connectorID.Weight()) log.Debugf("%s/%s: router=%s, connector=%s, weight=%d established", host, network, routerID, connectorID, connectorID.Weight())
for {
b := bufpool.Get(h.md.bufferSize) b := bufpool.Get(h.md.bufferSize)
defer bufpool.Put(b)
for {
n, err := conn.Read(b) n, err := conn.Read(b)
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
@@ -130,9 +137,25 @@ func (h *routerHandler) handleAssociate(ctx context.Context, conn net.Conn, netw
} }
} }
func (h *routerHandler) handlePacket(ctx context.Context, data []byte, routerID relay.TunnelID, log logger.Logger) error { func (h *routerHandler) sdRenew(ctx context.Context, clientID string, connectorID string) {
defer bufpool.Put(data) tc := time.NewTicker(h.md.sdRenewInterval)
defer tc.Stop()
for {
select {
case <-tc.C:
h.md.sd.Renew(ctx, &sd.Service{
ID: connectorID,
Name: clientID,
Node: h.id,
})
case <-ctx.Done():
return
}
}
}
func (h *routerHandler) handlePacket(ctx context.Context, data []byte, routerID relay.TunnelID, log logger.Logger) error {
var dstIP net.IP var dstIP net.IP
if waterutil.IsIPv4(data) { if waterutil.IsIPv4(data) {
header, err := ipv4.ParseHeader(data) header, err := ipv4.ParseHeader(data)
@@ -167,16 +190,10 @@ func (h *routerHandler) handlePacket(ctx context.Context, data []byte, routerID
rid := routerID.String() rid := routerID.String()
var route *router.Route route := h.getRoute(ctx, rid, dstIP.String())
if r := registry.RouterRegistry().Get(rid); r != nil {
route = r.GetRoute(ctx, dstIP.String(), router.IDOption(rid))
}
if route == nil && h.md.router != nil {
route = h.md.router.GetRoute(ctx, dstIP.String(), router.IDOption(rid))
}
if route == nil || route.Gateway == "" { if route == nil || route.Gateway == "" {
// no route to host, discard // no route to host, discard
return fmt.Errorf("route to host %s", dstIP) return fmt.Errorf("no route to host %s", dstIP)
} }
if log.IsLevelEnabled(logger.TraceLevel) { if log.IsLevelEnabled(logger.TraceLevel) {
@@ -218,6 +235,28 @@ func (h *routerHandler) handlePacket(ctx context.Context, data []byte, routerID
return nil return nil
} }
func (h *routerHandler) getRoute(ctx context.Context, rid string, dst string) *router.Route {
if h.md.routerCacheEnabled {
if item := h.routeCache.Get(dst); item != nil && !item.Expired() {
v, _ := item.Value().(*router.Route)
return v
}
}
var route *router.Route
if r := registry.RouterRegistry().Get(rid); r != nil {
route = r.GetRoute(ctx, dst, router.IDOption(rid))
}
if route == nil && h.md.router != nil {
route = h.md.router.GetRoute(ctx, dst, router.IDOption(rid))
}
if h.md.routerCacheEnabled {
h.routeCache.Set(dst, cache.NewItem(route, h.md.routerCacheExpiration))
}
return route
}
func (h *routerHandler) getAddrforRoute(ctx context.Context, routerID, gateway string) net.Addr { func (h *routerHandler) getAddrforRoute(ctx context.Context, routerID, gateway string) net.Addr {
if h.md.sd == nil { if h.md.sd == nil {
return nil return nil
+2 -6
View File
@@ -47,6 +47,7 @@ type routerHandler struct {
limiter traffic.TrafficLimiter limiter traffic.TrafficLimiter
cancel context.CancelFunc cancel context.CancelFunc
sdCache *cache.Cache sdCache *cache.Cache
routeCache *cache.Cache
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
@@ -58,6 +59,7 @@ func NewHandler(opts ...handler.Option) handler.Handler {
return &routerHandler{ return &routerHandler{
options: options, options: options,
sdCache: cache.NewCache(time.Minute), sdCache: cache.NewCache(time.Minute),
routeCache: cache.NewCache(time.Minute),
} }
} }
@@ -203,12 +205,6 @@ func (h *routerHandler) Handle(ctx context.Context, conn net.Conn, opts ...handl
} }
} }
if routerID.IsZero() {
resp.Status = relay.StatusBadRequest
resp.WriteTo(conn)
return ErrRouterID
}
if user != "" { if user != "" {
log = log.WithFields(map[string]any{"user": user}) log = log.WithFields(map[string]any{"user": user})
} }
+14 -1
View File
@@ -25,7 +25,11 @@ type metadata struct {
ingress ingress.Ingress ingress ingress.Ingress
sd sd.SD sd sd.SD
sdCacheExpiration time.Duration sdCacheExpiration time.Duration
sdRenewInterval time.Duration
router router.Router router router.Router
routerCacheEnabled bool
routerCacheExpiration time.Duration
observerPeriod time.Duration observerPeriod time.Duration
observerResetTraffic bool observerResetTraffic bool
@@ -45,12 +49,21 @@ func (h *routerHandler) parseMetadata(md mdata.Metadata) (err error) {
h.md.ingress = registry.IngressRegistry().Get(mdutil.GetString(md, "ingress")) h.md.ingress = registry.IngressRegistry().Get(mdutil.GetString(md, "ingress"))
h.md.sd = registry.SDRegistry().Get(mdutil.GetString(md, "sd")) h.md.sd = registry.SDRegistry().Get(mdutil.GetString(md, "sd"))
h.md.sdCacheExpiration = mdutil.GetDuration(md, "sd.cacheExpiration") h.md.sdCacheExpiration = mdutil.GetDuration(md, "sd.cache.expiration")
if h.md.sdCacheExpiration <= 0 { if h.md.sdCacheExpiration <= 0 {
h.md.sdCacheExpiration = defaultCacheExpiration h.md.sdCacheExpiration = defaultCacheExpiration
} }
h.md.sdRenewInterval = mdutil.GetDuration(md, "sd.renewInterval")
if h.md.sdRenewInterval < time.Second {
h.md.sdRenewInterval = defaultTTL
}
h.md.router = registry.RouterRegistry().Get(mdutil.GetString(md, "router")) h.md.router = registry.RouterRegistry().Get(mdutil.GetString(md, "router"))
h.md.routerCacheEnabled = mdutil.GetBool(md, "router.cache")
h.md.routerCacheExpiration = mdutil.GetDuration(md, "router.cache.expiration")
if h.md.routerCacheExpiration <= 0 {
h.md.routerCacheExpiration = defaultCacheExpiration
}
h.md.observerPeriod = mdutil.GetDuration(md, "observePeriod", "observer.period", "observer.observePeriod") h.md.observerPeriod = mdutil.GetDuration(md, "observePeriod", "observer.period", "observer.observePeriod")
if h.md.observerPeriod == 0 { if h.md.observerPeriod == 0 {