mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-19 00:36:38 +00:00
add clusters logic
This commit is contained in:
@@ -164,15 +164,40 @@ func (m Manager) proxyURLAllowList() []string {
|
||||
for _, addr := range reverseProxyAddresses {
|
||||
proxyUrl, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
// TODO: log?
|
||||
log.WithError(err).Debugf("failed to parse proxy URL %s", addr)
|
||||
continue
|
||||
}
|
||||
host, _, err := net.SplitHostPort(proxyUrl.Host)
|
||||
if err != nil {
|
||||
// TODO: log?
|
||||
host = proxyUrl.Host
|
||||
}
|
||||
allowedProxyURLs = append(allowedProxyURLs, host)
|
||||
}
|
||||
return allowedProxyURLs
|
||||
}
|
||||
|
||||
// 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 custom domains, the cluster is determined by looking up the CNAME target.
|
||||
func (m Manager) DeriveClusterFromDomain(ctx context.Context, domain string) (string, error) {
|
||||
allowList := m.proxyURLAllowList()
|
||||
if len(allowList) == 0 {
|
||||
return "", fmt.Errorf("no proxy clusters available")
|
||||
}
|
||||
|
||||
if cluster, ok := ExtractClusterFromFreeDomain(domain, allowList); ok {
|
||||
return cluster, nil
|
||||
}
|
||||
|
||||
cluster, valid := m.validator.ValidateWithCluster(ctx, domain, allowList)
|
||||
if valid {
|
||||
return cluster, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("domain %s does not match any available proxy cluster", domain)
|
||||
}
|
||||
|
||||
// GetAvailableClusters returns a list of available proxy cluster addresses.
|
||||
func (m Manager) GetAvailableClusters() []string {
|
||||
return m.proxyURLAllowList()
|
||||
}
|
||||
|
||||
@@ -32,28 +32,43 @@ func NewValidator(resolver resolver) *Validator {
|
||||
// The comparison is very simple, so wildcards will not match if included
|
||||
// in the acceptable domain list.
|
||||
func (v *Validator) IsValid(ctx context.Context, domain string, accept []string) bool {
|
||||
_, valid := v.ValidateWithCluster(ctx, domain, accept)
|
||||
return valid
|
||||
}
|
||||
|
||||
// ValidateWithCluster validates a custom domain and returns the matched cluster address.
|
||||
// Returns the cluster address and true if valid, or empty string and false if invalid.
|
||||
func (v *Validator) ValidateWithCluster(ctx context.Context, domain string, accept []string) (string, bool) {
|
||||
if v.resolver == nil {
|
||||
v.resolver = net.DefaultResolver
|
||||
}
|
||||
|
||||
// Prepend subdomain for ownership validation because we want to check
|
||||
// for the record being a wildcard ("*.example.com"), but you cannot
|
||||
// look up a wildcard so we have to add a subdomain for the check.
|
||||
cname, err := v.resolver.LookupCNAME(ctx, "validation."+domain)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"domain": domain,
|
||||
}).WithError(err).Error("Error resolving CNAME from resolver")
|
||||
return false
|
||||
return "", false
|
||||
}
|
||||
|
||||
// Remove a trailing "." from the CNAME (most people do not include the trailing "." in FQDN, so it is easier to strip this when comparing).
|
||||
nakedCNAME := strings.TrimSuffix(cname, ".")
|
||||
for _, domain := range accept {
|
||||
// Currently, the match is a very simple string comparison.
|
||||
if nakedCNAME == strings.TrimSuffix(domain, ".") {
|
||||
return true
|
||||
for _, acceptDomain := range accept {
|
||||
normalizedAccept := strings.TrimSuffix(acceptDomain, ".")
|
||||
if nakedCNAME == normalizedAccept {
|
||||
return acceptDomain, true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return "", false
|
||||
}
|
||||
|
||||
// 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)
|
||||
// It matches the domain suffix against available clusters and returns the matching cluster.
|
||||
func ExtractClusterFromFreeDomain(domain string, availableClusters []string) (string, bool) {
|
||||
for _, cluster := range availableClusters {
|
||||
if strings.HasSuffix(domain, "."+cluster) {
|
||||
return cluster, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user