relay: add direct routing for tunnel
This commit is contained in:
parent
02a5f4dde4
commit
6f9f5ce6ab
@ -333,7 +333,7 @@ func ParseIngress(cfg *config.IngressConfig) ingress.Ingress {
|
||||
}
|
||||
|
||||
rules = append(rules, xingress.Rule{
|
||||
Host: rule.Hostname,
|
||||
Hostname: rule.Hostname,
|
||||
Endpoint: rule.Endpoint,
|
||||
})
|
||||
}
|
||||
|
@ -19,13 +19,12 @@ func (c *relayConnector) parseMetadata(md mdata.Metadata) (err error) {
|
||||
const (
|
||||
connectTimeout = "connectTimeout"
|
||||
noDelay = "nodelay"
|
||||
tunnelID = "tunnelID"
|
||||
)
|
||||
|
||||
c.md.connectTimeout = mdutil.GetDuration(md, connectTimeout)
|
||||
c.md.noDelay = mdutil.GetBool(md, noDelay)
|
||||
|
||||
if s := mdutil.GetString(md, tunnelID); s != "" {
|
||||
if s := mdutil.GetString(md, "tunnelID", "tunnel.id"); s != "" {
|
||||
uuid, err := uuid.Parse(s)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -132,7 +132,11 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
|
||||
|
||||
log.Debugf("%s >> %s", conn.RemoteAddr(), target.Addr)
|
||||
|
||||
cc, err := h.router.Dial(ctx, network, target.Addr)
|
||||
addr := target.Addr
|
||||
if _, _, err := net.SplitHostPort(addr); err != nil {
|
||||
addr += ":0"
|
||||
}
|
||||
cc, err := h.router.Dial(ctx, network, addr)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
// TODO: the router itself may be failed due to the failed node in the router,
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/go-gost/x/internal/net/udp"
|
||||
"github.com/go-gost/x/internal/util/mux"
|
||||
relay_util "github.com/go-gost/x/internal/util/relay"
|
||||
metrics "github.com/go-gost/x/metrics/wrapper"
|
||||
xservice "github.com/go-gost/x/service"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@ -129,23 +130,32 @@ func (h *relayHandler) bindUDP(ctx context.Context, conn net.Conn, network, addr
|
||||
Status: relay.StatusOK,
|
||||
}
|
||||
|
||||
var pc net.PacketConn
|
||||
var err error
|
||||
bindAddr, _ := net.ResolveUDPAddr(network, address)
|
||||
pc, err := net.ListenUDP(network, bindAddr)
|
||||
pc, err = net.ListenUDP(network, bindAddr)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
serviceName := fmt.Sprintf("%s-ep-%s", h.options.Service, pc.LocalAddr())
|
||||
log = log.WithFields(map[string]any{
|
||||
"service": serviceName,
|
||||
"listener": "udp",
|
||||
"handler": "ep-udp",
|
||||
"bind": fmt.Sprintf("%s/%s", pc.LocalAddr(), pc.LocalAddr().Network()),
|
||||
})
|
||||
pc = metrics.WrapPacketConn(serviceName, pc)
|
||||
// pc = admission.WrapPacketConn(l.options.Admission, pc)
|
||||
// pc = limiter.WrapPacketConn(l.options.TrafficLimiter, pc)
|
||||
|
||||
defer pc.Close()
|
||||
|
||||
af := &relay.AddrFeature{}
|
||||
err = af.ParseFrom(pc.LocalAddr().String())
|
||||
if err != nil {
|
||||
if err := af.ParseFrom(pc.LocalAddr().String()); err != nil {
|
||||
log.Warn(err)
|
||||
}
|
||||
|
||||
// Issue: may not reachable when host has multi-interface
|
||||
af.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||
af.AType = relay.AddrIPv4
|
||||
resp.Features = append(resp.Features, af)
|
||||
if _, err := resp.WriteTo(conn); err != nil {
|
||||
log.Error(err)
|
||||
@ -183,7 +193,6 @@ func (h *relayHandler) handleBindTunnel(ctx context.Context, conn net.Conn, netw
|
||||
resp.WriteTo(conn)
|
||||
return
|
||||
}
|
||||
|
||||
connectorID := relay.NewConnectorID(uuid[:])
|
||||
if network == "udp" {
|
||||
connectorID = relay.NewUDPConnectorID(uuid[:])
|
||||
|
@ -123,11 +123,10 @@ func (h *relayHandler) handleConnectTunnel(ctx context.Context, conn net.Conn, n
|
||||
if ingress := h.md.ingress; ingress != nil {
|
||||
tid = parseTunnelID(ingress.Get(host))
|
||||
}
|
||||
|
||||
if !tid.Equal(tunnelID) {
|
||||
if !tid.Equal(tunnelID) && !h.md.directTunnel {
|
||||
resp.Status = relay.StatusBadRequest
|
||||
resp.WriteTo(conn)
|
||||
err := fmt.Errorf("tunnel %s not found", tunnelID.String())
|
||||
err := fmt.Errorf("not route to host %s", host)
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
@ -177,8 +177,13 @@ func (h *tunnelHandler) Handle(ctx context.Context, conn net.Conn, opts ...handl
|
||||
if h.ingress != nil {
|
||||
tunnelID = parseTunnelID(h.ingress.Get(host))
|
||||
}
|
||||
if tunnelID.IsZero() {
|
||||
err := fmt.Errorf("no route to host %s", host)
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
if tunnelID.IsPrivate() {
|
||||
err := fmt.Errorf("access denied: tunnel %s is private", tunnelID)
|
||||
err := fmt.Errorf("access denied: tunnel %s is private for host %s", tunnelID, host)
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ type metadata struct {
|
||||
hash string
|
||||
entryPoint string
|
||||
ingress ingress.Ingress
|
||||
directTunnel bool
|
||||
}
|
||||
|
||||
func (h *relayHandler) parseMetadata(md mdata.Metadata) (err error) {
|
||||
@ -47,13 +48,23 @@ func (h *relayHandler) parseMetadata(md mdata.Metadata) (err error) {
|
||||
|
||||
h.md.entryPoint = mdutil.GetString(md, entryPoint)
|
||||
h.md.ingress = registry.IngressRegistry().Get(mdutil.GetString(md, "ingress"))
|
||||
h.md.directTunnel = mdutil.GetBool(md, "tunnel.direct")
|
||||
|
||||
if h.md.ingress == nil {
|
||||
if ss := strings.Split(mdutil.GetString(md, "tunnel"), ":"); len(ss) == 2 {
|
||||
var rules []xingress.Rule
|
||||
for _, s := range strings.Split(mdutil.GetString(md, "tunnel"), ",") {
|
||||
ss := strings.SplitN(s, ":", 2)
|
||||
if len(ss) != 2 {
|
||||
continue
|
||||
}
|
||||
rules = append(rules, xingress.Rule{
|
||||
Hostname: ss[0],
|
||||
Endpoint: ss[1],
|
||||
})
|
||||
}
|
||||
if len(rules) > 0 {
|
||||
h.md.ingress = xingress.NewIngress(
|
||||
xingress.RulesOption([]xingress.Rule{
|
||||
{Host: ss[0], Endpoint: ss[1]},
|
||||
}),
|
||||
xingress.RulesOption(rules),
|
||||
xingress.LoggerOption(logger.Default().WithFields(map[string]any{
|
||||
"kind": "ingress",
|
||||
})),
|
||||
|
@ -87,14 +87,9 @@ func (t *Tunnel) GetConnector(network string) *Connector {
|
||||
|
||||
var connectors []*Connector
|
||||
for _, c := range t.connectors {
|
||||
if network == "udp" {
|
||||
if c.id.IsUDP() {
|
||||
connectors = append(connectors, c)
|
||||
}
|
||||
} else {
|
||||
if !c.id.IsUDP() {
|
||||
connectors = append(connectors, c)
|
||||
}
|
||||
if network == "udp" && c.id.IsUDP() ||
|
||||
network != "udp" && !c.id.IsUDP() {
|
||||
connectors = append(connectors, c)
|
||||
}
|
||||
}
|
||||
if len(connectors) == 0 {
|
||||
@ -181,14 +176,14 @@ func parseTunnelID(s string) (tid relay.TunnelID) {
|
||||
return relay.NewTunnelID(uuid[:])
|
||||
}
|
||||
|
||||
func getTunnelConn(network string, pool *ConnectorPool, tunnelID relay.TunnelID, retry int, log logger.Logger) (conn net.Conn, err error) {
|
||||
func getTunnelConn(network string, pool *ConnectorPool, tid relay.TunnelID, retry int, log logger.Logger) (conn net.Conn, err error) {
|
||||
if retry <= 0 {
|
||||
retry = 1
|
||||
}
|
||||
for i := 0; i < retry; i++ {
|
||||
c := pool.Get(network, tunnelID)
|
||||
c := pool.Get(network, tid)
|
||||
if c == nil {
|
||||
err = fmt.Errorf("tunnel %s not available", tunnelID.String())
|
||||
err = fmt.Errorf("tunnel %s not available", tid.String())
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
type Rule struct {
|
||||
Host string
|
||||
Hostname string
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
@ -122,10 +122,10 @@ func (ing *ingress) reload(ctx context.Context) error {
|
||||
rules := make(map[string]Rule)
|
||||
|
||||
fn := func(rule Rule) {
|
||||
if rule.Host == "" || rule.Endpoint == "" {
|
||||
if rule.Hostname == "" || rule.Endpoint == "" {
|
||||
return
|
||||
}
|
||||
host := rule.Host
|
||||
host := rule.Hostname
|
||||
if host[0] == '*' {
|
||||
host = host[1:]
|
||||
}
|
||||
@ -210,7 +210,7 @@ func (ing *ingress) parseRules(r io.Reader) (rules []Rule, err error) {
|
||||
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
if rule := ing.parseLine(scanner.Text()); rule.Host != "" {
|
||||
if rule := ing.parseLine(scanner.Text()); rule.Hostname != "" {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
@ -287,7 +287,7 @@ func (ing *ingress) parseLine(s string) (rule Rule) {
|
||||
}
|
||||
|
||||
return Rule{
|
||||
Host: sp[0],
|
||||
Hostname: sp[0],
|
||||
Endpoint: sp[1],
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user