mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-18 07:16:57 +00:00
Fix ensure only nameservers nodes added on schema for caddy load balancing
This commit is contained in:
parent
e95ecfb12a
commit
79a489d650
@ -19,6 +19,7 @@ type Credentials struct {
|
|||||||
IssuedAt time.Time `json:"issued_at"`
|
IssuedAt time.Time `json:"issued_at"`
|
||||||
LastUsedAt time.Time `json:"last_used_at,omitempty"`
|
LastUsedAt time.Time `json:"last_used_at,omitempty"`
|
||||||
Plan string `json:"plan,omitempty"`
|
Plan string `json:"plan,omitempty"`
|
||||||
|
NamespaceURL string `json:"namespace_url,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CredentialStore manages credentials for multiple gateways
|
// CredentialStore manages credentials for multiple gateways
|
||||||
|
|||||||
@ -72,6 +72,12 @@ func PerformSimpleAuthentication(gatewayURL, wallet, namespace string) (*Credent
|
|||||||
return nil, fmt.Errorf("failed to request API key: %w", err)
|
return nil, fmt.Errorf("failed to request API key: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build namespace gateway URL from the gateway URL
|
||||||
|
namespaceURL := ""
|
||||||
|
if domain := extractDomainFromURL(gatewayURL); domain != "" {
|
||||||
|
namespaceURL = fmt.Sprintf("https://ns-%s.%s", namespace, domain)
|
||||||
|
}
|
||||||
|
|
||||||
// Create credentials
|
// Create credentials
|
||||||
creds := &Credentials{
|
creds := &Credentials{
|
||||||
APIKey: apiKey,
|
APIKey: apiKey,
|
||||||
@ -79,6 +85,7 @@ func PerformSimpleAuthentication(gatewayURL, wallet, namespace string) (*Credent
|
|||||||
UserID: wallet,
|
UserID: wallet,
|
||||||
Wallet: wallet,
|
Wallet: wallet,
|
||||||
IssuedAt: time.Now(),
|
IssuedAt: time.Now(),
|
||||||
|
NamespaceURL: namespaceURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("\n🎉 Authentication successful!\n")
|
fmt.Printf("\n🎉 Authentication successful!\n")
|
||||||
|
|||||||
@ -156,6 +156,9 @@ func handleAuthLogin(wallet, namespace string) {
|
|||||||
fmt.Printf("🎯 Wallet: %s\n", creds.Wallet)
|
fmt.Printf("🎯 Wallet: %s\n", creds.Wallet)
|
||||||
fmt.Printf("🏢 Namespace: %s\n", creds.Namespace)
|
fmt.Printf("🏢 Namespace: %s\n", creds.Namespace)
|
||||||
fmt.Printf("🔑 API Key: %s\n", creds.APIKey)
|
fmt.Printf("🔑 API Key: %s\n", creds.APIKey)
|
||||||
|
if creds.NamespaceURL != "" {
|
||||||
|
fmt.Printf("🌐 Namespace URL: %s\n", creds.NamespaceURL)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleAuthLogout() {
|
func handleAuthLogout() {
|
||||||
@ -184,6 +187,9 @@ func handleAuthWhoami() {
|
|||||||
fmt.Println("✅ Authenticated")
|
fmt.Println("✅ Authenticated")
|
||||||
fmt.Printf(" Wallet: %s\n", creds.Wallet)
|
fmt.Printf(" Wallet: %s\n", creds.Wallet)
|
||||||
fmt.Printf(" Namespace: %s\n", creds.Namespace)
|
fmt.Printf(" Namespace: %s\n", creds.Namespace)
|
||||||
|
if creds.NamespaceURL != "" {
|
||||||
|
fmt.Printf(" NS Gateway: %s\n", creds.NamespaceURL)
|
||||||
|
}
|
||||||
fmt.Printf(" Issued At: %s\n", creds.IssuedAt.Format("2006-01-02 15:04:05"))
|
fmt.Printf(" Issued At: %s\n", creds.IssuedAt.Format("2006-01-02 15:04:05"))
|
||||||
if !creds.ExpiresAt.IsZero() {
|
if !creds.ExpiresAt.IsZero() {
|
||||||
fmt.Printf(" Expires At: %s\n", creds.ExpiresAt.Format("2006-01-02 15:04:05"))
|
fmt.Printf(" Expires At: %s\n", creds.ExpiresAt.Format("2006-01-02 15:04:05"))
|
||||||
@ -231,6 +237,9 @@ func handleAuthStatus() {
|
|||||||
fmt.Println(" Status: ✅ Authenticated")
|
fmt.Println(" Status: ✅ Authenticated")
|
||||||
fmt.Printf(" Wallet: %s\n", creds.Wallet)
|
fmt.Printf(" Wallet: %s\n", creds.Wallet)
|
||||||
fmt.Printf(" Namespace: %s\n", creds.Namespace)
|
fmt.Printf(" Namespace: %s\n", creds.Namespace)
|
||||||
|
if creds.NamespaceURL != "" {
|
||||||
|
fmt.Printf(" NS Gateway: %s\n", creds.NamespaceURL)
|
||||||
|
}
|
||||||
if !creds.ExpiresAt.IsZero() {
|
if !creds.ExpiresAt.IsZero() {
|
||||||
fmt.Printf(" Expires: %s\n", creds.ExpiresAt.Format("2006-01-02 15:04:05"))
|
fmt.Printf(" Expires: %s\n", creds.ExpiresAt.Format("2006-01-02 15:04:05"))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/DeBrosOfficial/network/pkg/logging"
|
"github.com/DeBrosOfficial/network/pkg/logging"
|
||||||
@ -143,8 +146,10 @@ func (n *Node) ensureBaseDNSRecords(ctx context.Context) error {
|
|||||||
value string
|
value string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base domain records (e.g., dbrs.space, *.dbrs.space) — for round-robin across all nodes
|
// Base domain records (e.g., dbrs.space, *.dbrs.space) — only for nameserver nodes.
|
||||||
if baseDomain != "" {
|
// Only nameserver nodes run Caddy (HTTPS), so only they should appear in base domain
|
||||||
|
// round-robin. Non-nameserver nodes would cause TLS failures for clients.
|
||||||
|
if baseDomain != "" && n.isNameserverNode(ctx) {
|
||||||
records = append(records,
|
records = append(records,
|
||||||
struct{ fqdn, value string }{baseDomain + ".", ipAddress},
|
struct{ fqdn, value string }{baseDomain + ".", ipAddress},
|
||||||
struct{ fqdn, value string }{"*." + baseDomain + ".", ipAddress},
|
struct{ fqdn, value string }{"*." + baseDomain + ".", ipAddress},
|
||||||
@ -176,8 +181,9 @@ func (n *Node) ensureBaseDNSRecords(ctx context.Context) error {
|
|||||||
n.ensureSOAAndNSRecords(ctx, baseDomain)
|
n.ensureSOAAndNSRecords(ctx, baseDomain)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Claim an NS slot for the base domain (ns1/ns2/ns3)
|
// Claim an NS slot for the base domain (ns1/ns2/ns3) — only if this node
|
||||||
if baseDomain != "" {
|
// was installed with --nameserver (i.e. runs Caddy + CoreDNS).
|
||||||
|
if baseDomain != "" && n.isNameserverPreference() {
|
||||||
n.claimNameserverSlot(ctx, baseDomain, ipAddress)
|
n.claimNameserverSlot(ctx, baseDomain, ipAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,6 +375,37 @@ func (n *Node) cleanupStaleNodeRecords(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isNameserverPreference checks if this node was installed with --nameserver flag
|
||||||
|
// by reading the preferences.yaml file. Only nameserver nodes should claim NS slots.
|
||||||
|
func (n *Node) isNameserverPreference() bool {
|
||||||
|
oramaDir := filepath.Join(os.ExpandEnv(n.config.Node.DataDir), "..")
|
||||||
|
prefsPath := filepath.Join(oramaDir, "preferences.yaml")
|
||||||
|
data, err := os.ReadFile(prefsPath)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Simple check: look for "nameserver: true" in the YAML
|
||||||
|
return strings.Contains(string(data), "nameserver: true")
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNameserverNode checks if this node has claimed a nameserver slot (ns1/ns2/ns3).
|
||||||
|
// Only nameserver nodes run Caddy for HTTPS, so only they should be in base domain DNS.
|
||||||
|
func (n *Node) isNameserverNode(ctx context.Context) bool {
|
||||||
|
if n.rqliteAdapter == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
nodeID := n.GetPeerID()
|
||||||
|
if nodeID == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
db := n.rqliteAdapter.GetSQLDB()
|
||||||
|
var count int
|
||||||
|
err := db.QueryRowContext(ctx,
|
||||||
|
`SELECT COUNT(*) FROM dns_nameservers WHERE node_id = ?`, nodeID,
|
||||||
|
).Scan(&count)
|
||||||
|
return err == nil && count > 0
|
||||||
|
}
|
||||||
|
|
||||||
// getWireGuardIP returns the IPv4 address assigned to the wg0 interface, if any
|
// getWireGuardIP returns the IPv4 address assigned to the wg0 interface, if any
|
||||||
func (n *Node) getWireGuardIP() (string, error) {
|
func (n *Node) getWireGuardIP() (string, error) {
|
||||||
iface, err := net.InterfaceByName("wg0")
|
iface, err := net.InterfaceByName("wg0")
|
||||||
@ -411,5 +448,21 @@ func (n *Node) getNodeIPAddress() (string, error) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
localAddr := conn.LocalAddr().(*net.UDPAddr)
|
localAddr := conn.LocalAddr().(*net.UDPAddr)
|
||||||
|
if localAddr.IP.IsPrivate() || localAddr.IP.IsLoopback() {
|
||||||
|
// UDP dial returned a private/loopback IP (e.g. WireGuard 10.0.0.x).
|
||||||
|
// Fall back to scanning interfaces for a public IPv4.
|
||||||
|
addrs, err := net.InterfaceAddrs()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("private IP detected (%s) and failed to list interfaces: %w", localAddr.IP, err)
|
||||||
|
}
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && !ipnet.IP.IsPrivate() {
|
||||||
|
if ipnet.IP.To4() != nil {
|
||||||
|
return ipnet.IP.String(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("private IP detected (%s) and no public IPv4 found on interfaces", localAddr.IP)
|
||||||
|
}
|
||||||
return localAddr.IP.String(), nil
|
return localAddr.IP.String(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user