mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-30 14:26:36 +08:00
refactor(db): use version as primary key for ConfigVersion and reuse model layer
- Transition `of_config_versions` primary key from `id` to `version` string. - Add database migration files for PostgreSQL and SQLite. - Introduce GORM hooks to preserve JSON backward compatibility. - Remove all localized private structures (`configVersionRecord`, `configVersionRow`) across `agent` and `flared` modules. - Remove local database Row structures (`tlsCertificateRow`, `tunnelNodeRow`, `pagesProjectRow`) in `proxy_route` module. - Reuse `model` query methods directly to fetch active config, tunnel nodes, and pages projects. - Cache IP detection results in memory with a 10-minute TTL to prevent frequent HTTP egress queries to realip.cc. - Integrate multiple fallback IP lookup providers (ifconfig.me, ip.sb, icanhazip.com) to guarantee IP detection reliability.
This commit is contained in:
@@ -4,6 +4,7 @@ package nodeip
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/pkg/geoip"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
const (
|
||||
outboundIPLookupTimeout = 5 * time.Second
|
||||
publicIPPriorityScore = 2 // matches iputil.Score for public IPv4 addresses
|
||||
ipCacheTTL = 10 * time.Minute
|
||||
)
|
||||
|
||||
// LookupOutboundIP and LookupLocalIP are the provider functions used to detect the node's outbound/local IP.
|
||||
@@ -20,22 +22,39 @@ const (
|
||||
var (
|
||||
LookupOutboundIP = geoip.GetOutboundIP
|
||||
LookupLocalIP = DetectLocal
|
||||
|
||||
cacheMu sync.RWMutex
|
||||
cachedIP string
|
||||
lastDetected time.Time
|
||||
)
|
||||
|
||||
// Detect returns the best available outbound or local IPv4 address for this node.
|
||||
func Detect() string {
|
||||
if ip := detectOutbound(context.Background()); ip != "" {
|
||||
return ip
|
||||
}
|
||||
return LookupLocalIP()
|
||||
return DetectWithContext(context.Background())
|
||||
}
|
||||
|
||||
// DetectWithContext returns the best available outbound or local IPv4 address, respecting ctx for cancellation.
|
||||
func DetectWithContext(ctx context.Context) string {
|
||||
if ip := detectOutbound(ctx); ip != "" {
|
||||
cacheMu.RLock()
|
||||
if cachedIP != "" && time.Since(lastDetected) < ipCacheTTL {
|
||||
ip := cachedIP
|
||||
cacheMu.RUnlock()
|
||||
return ip
|
||||
}
|
||||
return LookupLocalIP()
|
||||
cacheMu.RUnlock()
|
||||
|
||||
var ip string
|
||||
if ip = detectOutbound(ctx); ip == "" {
|
||||
ip = LookupLocalIP()
|
||||
}
|
||||
|
||||
if ip != "" {
|
||||
cacheMu.Lock()
|
||||
cachedIP = ip
|
||||
lastDetected = time.Now()
|
||||
cacheMu.Unlock()
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
func detectOutbound(ctx context.Context) string {
|
||||
|
||||
@@ -187,10 +187,46 @@ func (a RealIPCCAdapter) DecodeIP(reader io.Reader) (net.IP, error) {
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// PlainTextIPAdapter decodes public IP responses from raw plain text endpoints.
|
||||
type PlainTextIPAdapter struct {
|
||||
ProviderName string
|
||||
URL string
|
||||
}
|
||||
|
||||
// Name returns the provider name.
|
||||
func (a PlainTextIPAdapter) Name() string {
|
||||
return a.ProviderName
|
||||
}
|
||||
|
||||
// Endpoint returns the plain text API URL.
|
||||
func (a PlainTextIPAdapter) Endpoint() string {
|
||||
return a.URL
|
||||
}
|
||||
|
||||
// DecodeIP parses a plain text response into a public IP address.
|
||||
func (a PlainTextIPAdapter) DecodeIP(reader io.Reader) (net.IP, error) {
|
||||
body, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipStr := strings.TrimSpace(string(body))
|
||||
ip := net.ParseIP(ipStr)
|
||||
if ip == nil {
|
||||
return nil, fmt.Errorf("invalid plain text IP %q", ipStr)
|
||||
}
|
||||
if ipv4 := ip.To4(); ipv4 != nil {
|
||||
return ipv4, nil
|
||||
}
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// DefaultOutboundIPStrategies returns the built-in public egress IP lookup strategies.
|
||||
func DefaultOutboundIPStrategies() []OutboundIPStrategy {
|
||||
return []OutboundIPStrategy{
|
||||
NewRealIPCCOutboundIPStrategy(),
|
||||
NewHTTPOutboundIPStrategy(PlainTextIPAdapter{ProviderName: "ifconfig.me", URL: "https://ifconfig.me"}, nil),
|
||||
NewHTTPOutboundIPStrategy(PlainTextIPAdapter{ProviderName: "ip.sb", URL: "https://api.ip.sb/ip"}, nil),
|
||||
NewHTTPOutboundIPStrategy(PlainTextIPAdapter{ProviderName: "icanhazip.com", URL: "https://icanhazip.com"}, nil),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user