package server import ( "fmt" "time" "github.com/proxy-pool/proxy-pool/internal/config" "github.com/proxy-pool/proxy-pool/internal/gateway/policy" platformAdmission "github.com/proxy-pool/proxy-pool/internal/platform/admission" "github.com/proxy-pool/proxy-pool/internal/platform/httpsecurity" ) type Protection struct { Auth Guard Access Guard Admission Guard ClientIPs *ClientIPResolver } func BuildProtection(listener config.Listener) (Protection, error) { clientIPs, err := NewClientIPResolver(listener.Access.TrustedProxies) if err != nil { return Protection{}, err } access, err := NewAccessGuard(clientIPs, listener.Access.AllowCIDRs) if err != nil { return Protection{}, err } auth, err := buildConfiguredAuth(listener) if err != nil { return Protection{}, err } var admission Guard if listener.Limits.RequestsPerMinute > 0 || listener.Limits.RequestsPerMinutePerClient > 0 { limiter, limiterErr := platformAdmission.NewFixedWindow(platformAdmission.FixedWindowConfig{ Window: time.Minute, Global: listener.Limits.RequestsPerMinute, PerKey: listener.Limits.RequestsPerMinutePerClient, }) if limiterErr != nil { return Protection{}, fmt.Errorf("build gateway admission: %w", limiterErr) } admission = NewAdmissionGuard(clientIPs, limiter) } return Protection{Auth: auth, Access: access, Admission: admission, ClientIPs: clientIPs}, nil } func ConfigFromListener(listener config.Listener) Config { return Config{ MaxAttempts: listener.Retry.MaxAttempts, RetryMethods: append([]string(nil), listener.Retry.RetryMethods...), MaxConcurrentRequests: listener.Limits.MaxConcurrentConnections, } } func TargetPolicyFromListener(listener config.Listener) (*policy.TargetPolicy, error) { destination := listener.DestinationPolicy return policy.NewTargetPolicy(policy.Config{ DenyCIDRs: append([]string(nil), destination.DenyCIDRs...), AllowedPorts: append([]uint16(nil), destination.AllowedPorts...), AllowPrivateNetworks: explicitlyAllowed(destination.DenyPrivateNetworks), AllowLoopback: explicitlyAllowed(destination.DenyLoopback), AllowLinkLocal: explicitlyAllowed(destination.DenyLinkLocal), }) } func explicitlyAllowed(deny *bool) bool { return deny != nil && !*deny } func buildConfiguredAuth(listener config.Listener) (Guard, error) { switch listener.Auth.Mode { case "", "none": return nil, nil } authListener := config.Listener{ Access: config.Access{ TrustedProxies: append([]string(nil), listener.Access.TrustedProxies...), }, Auth: listener.Auth, } protection, err := httpsecurity.NewFromListener( authListener, httpsecurity.ClientSourceIP, httpsecurity.ProxySemantics, nil, ) if err != nil { return nil, fmt.Errorf("build gateway authentication: %w", err) } return protection, nil }