mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-26 14:29:08 +01:00
optimize the DeriveClusterFromDomain function
1. validate domain only for proxy urls 2. use registered target cluster for custom domain extraction
This commit is contained in:
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@@ -223,57 +222,19 @@ func (m Manager) ValidateDomain(ctx context.Context, accountID, userID, domainID
|
|||||||
}
|
}
|
||||||
|
|
||||||
// proxyURLAllowList retrieves a list of currently connected proxies and
|
// proxyURLAllowList retrieves a list of currently connected proxies and
|
||||||
// their URLs (as reported by the proxy servers). It performs some clean
|
// their URLs
|
||||||
// up on those URLs to attempt to retrieve domain names as we would
|
|
||||||
// expect to see them in a validation check.
|
|
||||||
func (m Manager) proxyURLAllowList() []string {
|
func (m Manager) proxyURLAllowList() []string {
|
||||||
var reverseProxyAddresses []string
|
var reverseProxyAddresses []string
|
||||||
if m.proxyURLProvider != nil {
|
if m.proxyURLProvider != nil {
|
||||||
reverseProxyAddresses = m.proxyURLProvider.GetConnectedProxyURLs()
|
reverseProxyAddresses = m.proxyURLProvider.GetConnectedProxyURLs()
|
||||||
}
|
}
|
||||||
var allowedProxyURLs []string
|
return reverseProxyAddresses
|
||||||
for _, addr := range reverseProxyAddresses {
|
|
||||||
if addr == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
host := extractHostFromAddress(addr)
|
|
||||||
if host != "" {
|
|
||||||
allowedProxyURLs = append(allowedProxyURLs, host)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return allowedProxyURLs
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractHostFromAddress extracts the hostname from an address string.
|
|
||||||
// It handles both URL format (https://host:port) and plain hostname (host or host:port).
|
|
||||||
func extractHostFromAddress(addr string) string {
|
|
||||||
// If it looks like a URL with a scheme, parse it
|
|
||||||
if strings.Contains(addr, "://") {
|
|
||||||
proxyUrl, err := url.Parse(addr)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Debugf("failed to parse proxy URL %s", addr)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
host, _, err := net.SplitHostPort(proxyUrl.Host)
|
|
||||||
if err != nil {
|
|
||||||
return proxyUrl.Host
|
|
||||||
}
|
|
||||||
return host
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise treat as hostname or host:port
|
|
||||||
host, _, err := net.SplitHostPort(addr)
|
|
||||||
if err != nil {
|
|
||||||
// No port, use as-is
|
|
||||||
return addr
|
|
||||||
}
|
|
||||||
return host
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeriveClusterFromDomain determines the proxy cluster for a given domain.
|
// DeriveClusterFromDomain determines the proxy cluster for a given domain.
|
||||||
// For free domains (those ending with a known cluster suffix), the cluster is extracted from the domain.
|
// For free domains (those ending with a known cluster suffix), the cluster is extracted from the domain.
|
||||||
// For custom domains, the cluster is determined by looking up the CNAME target.
|
// For custom domains, the cluster is determined by checking the registered custom domain's target cluster.
|
||||||
func (m Manager) DeriveClusterFromDomain(ctx context.Context, domain string) (string, error) {
|
func (m Manager) DeriveClusterFromDomain(ctx context.Context, accountID, domain string) (string, error) {
|
||||||
allowList := m.proxyURLAllowList()
|
allowList := m.proxyURLAllowList()
|
||||||
if len(allowList) == 0 {
|
if len(allowList) == 0 {
|
||||||
return "", fmt.Errorf("no proxy clusters available")
|
return "", fmt.Errorf("no proxy clusters available")
|
||||||
@@ -283,14 +244,28 @@ func (m Manager) DeriveClusterFromDomain(ctx context.Context, domain string) (st
|
|||||||
return cluster, nil
|
return cluster, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster, valid := m.validator.ValidateWithCluster(ctx, domain, allowList)
|
customDomains, err := m.store.ListCustomDomains(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("list custom domains: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
targetCluster, valid := extractClusterFromCustomDomains(domain, customDomains)
|
||||||
if valid {
|
if valid {
|
||||||
return cluster, nil
|
return targetCluster, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", fmt.Errorf("domain %s does not match any available proxy cluster", domain)
|
return "", fmt.Errorf("domain %s does not match any available proxy cluster", domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func extractClusterFromCustomDomains(domain string, customDomains []*domain.Domain) (string, bool) {
|
||||||
|
for _, customDomain := range customDomains {
|
||||||
|
if strings.HasSuffix(domain, "."+customDomain.Domain) {
|
||||||
|
return customDomain.TargetCluster, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
// ExtractClusterFromFreeDomain extracts the cluster address from a free domain.
|
// ExtractClusterFromFreeDomain extracts the cluster address from a free domain.
|
||||||
// Free domains have the format: <name>.<nonce>.<cluster> (e.g., myapp.abc123.eu.proxy.netbird.io)
|
// Free domains have the format: <name>.<nonce>.<cluster> (e.g., myapp.abc123.eu.proxy.netbird.io)
|
||||||
// It matches the domain suffix against available clusters and returns the matching cluster.
|
// It matches the domain suffix against available clusters and returns the matching cluster.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const unknownHostPlaceholder = "unknown"
|
|||||||
|
|
||||||
// ClusterDeriver derives the proxy cluster from a domain.
|
// ClusterDeriver derives the proxy cluster from a domain.
|
||||||
type ClusterDeriver interface {
|
type ClusterDeriver interface {
|
||||||
DeriveClusterFromDomain(ctx context.Context, domain string) (string, error)
|
DeriveClusterFromDomain(ctx context.Context, accountID, domain string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type managerImpl struct {
|
type managerImpl struct {
|
||||||
@@ -137,7 +137,7 @@ func (m *managerImpl) CreateService(ctx context.Context, accountID, userID strin
|
|||||||
|
|
||||||
var proxyCluster string
|
var proxyCluster string
|
||||||
if m.clusterDeriver != nil {
|
if m.clusterDeriver != nil {
|
||||||
proxyCluster, err = m.clusterDeriver.DeriveClusterFromDomain(ctx, service.Domain)
|
proxyCluster, err = m.clusterDeriver.DeriveClusterFromDomain(ctx, accountID, service.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Warnf("could not derive cluster from domain %s, updates will broadcast to all proxy servers", service.Domain)
|
log.WithError(err).Warnf("could not derive cluster from domain %s, updates will broadcast to all proxy servers", service.Domain)
|
||||||
return nil, status.Errorf(status.PreconditionFailed, "could not derive cluster from domain %s: %v", service.Domain, err)
|
return nil, status.Errorf(status.PreconditionFailed, "could not derive cluster from domain %s: %v", service.Domain, err)
|
||||||
@@ -239,7 +239,7 @@ func (m *managerImpl) UpdateService(ctx context.Context, accountID, userID strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if m.clusterDeriver != nil {
|
if m.clusterDeriver != nil {
|
||||||
newCluster, err := m.clusterDeriver.DeriveClusterFromDomain(ctx, service.Domain)
|
newCluster, err := m.clusterDeriver.DeriveClusterFromDomain(ctx, accountID, service.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Warnf("could not derive cluster from domain %s", service.Domain)
|
log.WithError(err).Warnf("could not derive cluster from domain %s", service.Domain)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user