proxy-pool/internal/gateway/server/bootstrap.go
youfak 4de3ffb85f
Some checks are pending
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run
ci / race (push) Waiting to run
feat: add ephemeral proxy activity pool
2026-07-29 12:51:18 +08:00

94 lines
2.7 KiB
Go

package server
import (
"fmt"
"time"
"proxy-pool/internal/config"
"proxy-pool/internal/gateway/policy"
platformAdmission "proxy-pool/internal/platform/admission"
"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
}