fixed IP whitelist bugs

This commit is contained in:
Turbootzz committed 2025-10-24 20:39:11 +02:00
1 parent e48098090d
commit 8cea6d1f8c
5 files changed
+93 -27

No files matched your search

+17
View File
@@ -2,6 +2,7 @@ package config
import (
"fmt"
"net"
"net/url"
"os"
"strings"
@@ -56,6 +57,9 @@ func Load() (*Config, error) {
for _, ip := range ips {
trimmed := strings.TrimSpace(ip)
if trimmed != "" {
if err := validateIPOrCIDR(trimmed); err != nil {
return nil, fmt.Errorf("invalid IP in ALLOWED_IPS (%s): %w", trimmed, err)
}
cfg.AllowedIPs = append(cfg.AllowedIPs, trimmed)
}
}
@@ -107,3 +111,16 @@ func parseDuration(s string) time.Duration {
}
return d
}
// validateIPOrCIDR validates if a string is a valid IP address or CIDR range
func validateIPOrCIDR(s string) error {
// Try parsing as CIDR first
if _, _, err := net.ParseCIDR(s); err == nil {
return nil
}
// Try parsing as IP address
if net.ParseIP(s) != nil {
return nil
}
return fmt.Errorf("not a valid IP address or CIDR range")
}
+26 -12
View File
@@ -58,7 +58,7 @@ func New(allowedIPs []string, enableGitHub bool) (*IPWhitelist, error) {
logger.Warn.Printf("Invalid IP '%s'", ipStr)
continue
}
wl.allowedIPs[ipStr] = true
wl.allowedIPs[ip.String()] = true
logger.Info.Printf("Added IP to whitelist: %s", ipStr)
}
}
@@ -87,12 +87,17 @@ func (wl *IPWhitelist) Middleware() fiber.Handler {
clientIP := c.IP()
if wl.IsAllowed(clientIP) {
logger.Info.Printf("IP allowed: %s", clientIP)
// Handle comma-separated IPs from X-Forwarded-For header
// Take the first IP (original client IP before proxies)
ips := strings.Split(clientIP, ",")
realClientIP := strings.TrimSpace(ips[0])
if wl.IsAllowed(realClientIP) {
logger.Debug.Printf("IP allowed: %s", realClientIP)
return c.Next()
}
logger.Warn.Printf("IP blocked (not whitelisted): %s on %s %s", clientIP, c.Method(), c.Path())
logger.Warn.Printf("IP blocked (not whitelisted): %s on %s %s", realClientIP, c.Method(), c.Path())
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
"error": "access denied: IP not whitelisted",
})
@@ -109,8 +114,8 @@ func (wl *IPWhitelist) IsAllowed(ipStr string) bool {
return false
}
// Check single IPs
if wl.allowedIPs[ipStr] {
// Check single IPs (normalize IP for consistent matching)
if wl.allowedIPs[ip.String()] {
return true
}
@@ -174,21 +179,30 @@ func (wl *IPWhitelist) updateGitHubIPRanges() error {
}
// StartPeriodicUpdate starts a goroutine that updates GitHub IP ranges periodically
func (wl *IPWhitelist) StartPeriodicUpdate(interval time.Duration) {
// Returns a stop function that should be called to clean up the goroutine
func (wl *IPWhitelist) StartPeriodicUpdate(interval time.Duration) func() {
if !wl.enableGitHub {
return
return func() {}
}
ticker := time.NewTicker(interval)
done := make(chan struct{})
go func() {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for range ticker.C {
if err := wl.updateGitHubIPRanges(); err != nil {
logger.Error.Printf("Failed to update GitHub IP ranges: %v", err)
for {
select {
case <-ticker.C:
if err := wl.updateGitHubIPRanges(); err != nil {
logger.Error.Printf("Failed to update GitHub IP ranges: %v", err)
}
case <-done:
return
}
}
}()
logger.Info.Printf("Started GitHub IP range auto-update (every %v)", interval)
return func() { close(done) }
}
+21 -7
View File
@@ -2,6 +2,7 @@ package vaultwarden
import (
"context"
"encoding/json"
"fmt"
"os"
"os/exec"
@@ -14,6 +15,10 @@ import (
var bitwardenInitMutex sync.Mutex
type BitwardenStatus struct {
Status string `json:"status"`
}
func InitializeBitwardenCLI(serverURL, clientID, clientSecret, password string) (string, error) {
bitwardenInitMutex.Lock()
defer bitwardenInitMutex.Unlock()
@@ -29,12 +34,18 @@ func InitializeBitwardenCLI(serverURL, clientID, clientSecret, password string)
cancel()
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
cmd = exec.CommandContext(ctx, "bw", "status")
statusOutput, _ := cmd.CombinedOutput()
cancel()
statusOutput, err := cmd.CombinedOutput()
if err != nil {
logger.Warn.Printf("Failed to check status: %v", err)
}
statusStr := strings.TrimSpace(string(statusOutput))
isLoggedIn := strings.Contains(statusStr, `"status":"unlocked"`) || strings.Contains(statusStr, `"status":"locked"`)
var status BitwardenStatus
isLoggedIn := false
if err := json.Unmarshal(statusOutput, &status); err == nil {
isLoggedIn = status.Status == "unlocked" || status.Status == "locked"
}
if !isLoggedIn {
logger.Info.Println("Logging in to Bitwarden...")
@@ -67,11 +78,14 @@ func InitializeBitwardenCLI(serverURL, clientID, clientSecret, password string)
if strings.Contains(outputStr, "Rate limit") {
logger.Warn.Printf("Rate limited (attempt %d/%d)", attempt, maxRetries)
loginErr = fmt.Errorf("rate limited: %s", outputStr)
continue
} else {
logger.Warn.Printf("Login failed (attempt %d/%d): %v - %s", attempt, maxRetries, err, outputStr)
loginErr = fmt.Errorf("login failed: %w - %s", err, outputStr)
}
loginErr = fmt.Errorf("login failed: %w - %s", err, outputStr)
break
if attempt < maxRetries {
continue
}
}
if loginErr != nil {