94 lines
2.7 KiB
Go
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
|
|
}
|