Skip to content

Latest commit

Β 

History

History
406 lines (364 loc) Β· 35.5 KB

0001-general-design.md

File metadata and controls

406 lines (364 loc) Β· 35.5 KB
authors state
Anton Repin (github.com/xdire)
wip

RFD 1 - General Design

What

This RFD Details the aspects of implementation of TCP load balancer up the following minimal requirements:

Library

  • A least connections forwarder implementation that tracks the number of connections per upstream.
  • A per-client connection rate limiter implementation that tracks the number of client connections.
  • Health checking for unhealthy upstreams. Should not be eligible to receive connections until upstream determined to be healthy.

Server

  • mTLS authentication to have the server verify identity of the client and client of the server
  • A simple authorization scheme that defines what upstreams are available to which clients
  • Accept and forward connections to upstreams using library

Why

TCP Proxy Load balancer with mTLS can solve the following set of problems:

  • Distribute the load for the domain record using the ruleset enforced by the customer
  • Serve as a secure communications Gateway pass-through for the network of services
  • Provide access management per client resource scope

Details


Design will discuss following areas:

Structure


Balancer provides following components in order of flow and appearance:

  1. Rate Limiting System
    • Per Resource Token Bucket based Rate Limiter
    • Per LB β€” LRU TTL Rate Limiter
  2. Resource Cache
    • map of customer pool records
  3. Forwarder β€” backend entity providing management per customer pool
    • allows selection of the strategy (if supported more than single)
    • provides health check host tracker per pool
    • provides ability to add to the pool or remove from the pool
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚   IP LRU TTL   β”‚    β”‚ Resource β”‚   β”‚  Resource β”‚                       β”‚ Healthy  β”‚            β”‚ No error β”‚
     β”‚Rate Limit Checkβ”‚    β”‚  lookup  β”œβ”€β”€β”€β–Ά   cache   β”‚                       β”‚  found   β”œβ”€β”€β”€β”€β”€β”      β”‚          β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                       β””β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”˜     β”‚      └────▲──────
              β–²                  β”‚              β”‚                                  β”‚           β”‚           β”‚     β”‚
              β”‚                  β”‚              β”‚                                  β”‚           β”‚           β”‚     └────┐
              β”‚                 β•±β–ˆβ•²             β”‚                                 β•±β–ˆβ•²          β”‚          β•±β–ˆβ•²         β”‚
              └──────────┐     β•±β–ˆβ–ˆβ–ˆβ•²            β”‚                                β•±β–ˆβ–ˆβ–ˆβ•²         β”‚         β•±β–ˆβ–ˆβ–ˆβ•²        β”‚
                         β”‚    β•±β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•²           β”‚                               β•±β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•²        β”‚        β•±β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•²       β”‚
                         β”‚   β•±β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•²     β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β•±β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•²       β”‚       β•±β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•²      β”‚
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”  β”‚  β•±β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•²    β”‚  Rate   β”‚   β”‚           β”‚        β•±β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•²      β””β”€β”€β”€β”€β”€β”€β–Άβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•²   β”Œβ”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”
───▢ Request β”œβ”€β”€β–Ά TLS β”‚β”€β”€β”΄β”€β–Άβ–ˆHANDSHAKEβ–ˆβ–   β”‚ limiter β”œβ”€β”€β”€β–Ά Forwarder β”œβ”€β”€β”€β”€β”€β”€β”€β–Άβ–ˆSTRATEGYβ–ˆβ–ˆβ–           β–•β–ˆDIAL HOSTβ–ˆβ–  β”‚ Connect β”‚
   β””β”€β”€β”€β”€β”€β–²β”€β”€β”€β”˜  β”‚ portβ”‚     β•²β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•±    β”‚  check  β”‚   β”‚           β”‚        β•²β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•±             β•²β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•±   β”‚ streams β”‚
         β”‚      β””β”€β”€β”€β”€β”€β”˜      β•²β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•±     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚           β”‚         β•²β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–²       .─.     β•²β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•±    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                    β•²β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•±                    β”‚  β”Œβ”€β”€β”€β”€β”€β”  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β–ˆβ–ˆβ–ˆβ–ˆβ•±β”‚ β”Œβ”€β”€β”€β”€( 2 )     β•²β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•±
         β”‚                     β•²β–ˆβ–ˆβ–ˆβ•±                     β”‚β”Œβ”€β”€Cacheβ”œβ”€β”β”‚  β”Œβ”€β”΄β”€β”€β”   β•²β–ˆβ–ˆβ–ˆβ•± β”‚ β”‚ Ask `┬'       β•²β–ˆβ–ˆβ–ˆβ•±
         β”‚                      β•²β–ˆβ•±                      β”‚β”‚ β””β”€β”€β”€β”€β”€β”˜ ◀┼───Peekβ”‚    β•²β–ˆβ•±  └── next β”‚         β•²β–ˆβ•±
         β”‚                    β”Œβ”€β”€β”€β”€β”                     β”‚β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”β”‚β”‚  β””β”€β”€β”€β”€β”˜     β”‚     β”‚ host β”‚          β”‚
         β”‚                    β”‚Failβ”‚                     β”‚β”‚β”‚ Route β”‚β”‚β”‚             β”‚     β””β”¬β”€β”€β”€β”€β”€β”˜          β”‚
         β”‚                    β””β”€β”€β”¬β”€β”˜                     β”‚β”‚β””β”€β”€β”€β”€β”€β”€β”€β”˜β”‚β”‚             β”‚      β”‚      .─.       β”‚
         β”‚                       β”‚                       β”‚β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”β”‚β”‚             β”‚    β”Œβ”€β”΄β”€β”€β”€β”€β”€( 1 ) β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
         β”‚                       β”‚                       β”‚β”‚β”‚ Route β”‚β”‚β”‚             β”‚    β”‚  Mark  `┬'  β”‚   Error  β”‚
         β”‚                       β”‚                       β”‚β”‚β””β”€β”€β”€β”€β”€β”€β”€β”˜β—€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€unhealthy◀────          β”‚
         β”‚                       β–Ό                       β”‚β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”β”‚β”‚             β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                 β”‚β”‚β”‚ Route β”‚β”‚β”‚             β”‚
         β”‚                β”‚ IP LRU TTL β”‚                 β”‚β”‚β””β”€β”€β”€β”€β”€β”€β”€β”˜β”‚β”‚             β”‚
         β”‚                β”‚Rate Limiterβ”‚                 β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚        β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
         β”‚                β”‚ Add Record β”‚                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚ Unhealthyβ”‚
         β”‚                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                      β”‚   only   β”‚
    β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”                  β”‚             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚  Close  β”‚β—€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β”‚
         β–²                       β”‚
         β”‚                       β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Components


Configuration

LoadBalancer can be configured on new instance creation with following slice of Services provided at the time of instance creation:

{services: []ServicePool} Where ServicePool is representing following interface:

type ServicePool interface {
    // How each ServicePool identified, CN match
    Identity() string   
    // Port to listen for incoming traffic
    Port() int
    // Rate of times per time.Duration
    RateQuota() (int, time.Duration)
    // How many unauthorized attempts before IP cache placement
    UnathorizedAttempts() int
    // Bring host back in routable healthy state after this amount of validations
    HealthCheckValidations() int
    // Routes to route
    Routes() []Route
}

type Route interface {
    // Stores path of the upstream
    Path()   string
    // Provides information if route is active, in case of update
    // function can provide false and that will adjust behavior of forwarder
    Active() bool
}

As well load balancer will have method AddServicePool(pool ServicePool) to do following:

  • if pool exists for identity, update this pool
  • if pool did not exist, spawn all the required items and run routing

Forwarder

                               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€Forwarder Selector β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                              β”‚
β”‚                                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                  β”‚
β”‚         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€   Slice   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚         β”‚                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                        β”‚         β”‚
β”‚         β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”            β”Œβ”€β”€β”€β”€β”€β”€β”€β”            β”Œβ”€β”€β”€β”€β”€β”€β”€β”     β”‚         β”‚
β”‚         β”‚ β”Œβ”€β”€β”€β”€*Route β”œβ”€β”€β”€β”    β”Œβ”€β”€β”€β”€*Route β”œβ”€β”€β”€β”    β”Œβ”€β”€β”€β”€*Route β”œβ”€β”€β”€β” β”‚         β”‚
β”‚         β”‚ β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚    β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚    β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚ β”‚         β”‚
β”‚         β”‚ β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚    β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚    β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ β”‚         β”‚
β”‚         β”‚ β”‚β”‚   Address   β”‚β”‚    β”‚β”‚   Address   β”‚β”‚    β”‚β”‚   Address   β”‚β”‚ β”‚         β”‚
β”‚         β”‚ β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚    β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚    β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ β”‚         β”‚
β”‚         β”‚ β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚    β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚    β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ β”‚         β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β–Άβ”‚   Healthy   β”‚β”‚    β”‚β”‚   Healthy   β”‚β”‚    β”‚β”‚   Healthy   │◀─┼─────┐   β”‚
β”‚ β”‚       β”‚ β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚    β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚    β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ β”‚     β”‚   β”‚
β”‚ β”‚       β”‚ β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚    β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚    β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ β”‚     β”‚   β”‚
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β–Άβ”‚ Connections β”‚β”‚    β”‚β”‚ Connections β”‚β”‚    β”‚β”‚ Connections β”‚β”‚ β”‚     β”‚   β”‚
β”‚β”Œβ”΄β”      β”‚ β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚    β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚    β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ β”‚    β”Œβ”΄β”  β”‚
β”‚β”‚Aβ”‚      β”‚ β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚    β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚    β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ β”‚    β”‚Aβ”‚  β”‚
β”‚β”‚Tβ”œβ”€β”€β”€β”€β”€β”€β”Όβ”€β–Άβ”‚   Active    β”‚β”‚    β”‚β”‚   Active    β”‚β”‚    β”‚β”‚   Active    │◀─┼─────Tβ”‚  β”‚
β”‚β”‚Oβ”‚      β”‚ β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚    β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚    β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ β”‚    β”‚Oβ”‚  β”‚
β”‚β”‚Mβ”‚      β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚    β”‚Mβ”‚  β”‚
β”‚β”‚Iβ”‚      β”‚                                                             β”‚    β”‚Iβ”‚  β”‚
β”‚β”‚Cβ”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚Cβ”‚  β”‚
β”‚β””β”¬β”˜                              β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”                             β””β”¬β”˜  β”‚
β”‚ β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚Mark !Activeβ”‚          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚
β”‚ β”‚  β”‚              β”‚             β”‚ Append new β”‚          β”‚                β”‚  β”‚   β”‚
β”‚ └──│   Strategy   β”‚             β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜       β”Œβ”€β–Άβ”‚ Health-watcher β”‚β”€β”€β”˜   β”‚
β”‚    β”‚              β”‚              β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”        β”‚  β”‚                β”‚      β”‚
β”‚    └──────────────┴────┐         β”‚  Update  β”‚        β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚                      ╔═╩════╦────▢   Mutex  β”‚        β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚                      β•‘ Each β•‘    β””β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”˜        β”‚      β”‚   Add   β”‚         β”‚
β”‚                      β•‘Next()β•‘         β”‚              └───────  Route  β”‚         β”‚
β”‚                      β•šβ•β•β•β•β•β•β•         β”‚                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”
                                   β”‚ Update  β”‚
                                   β”‚ Routes  β”‚
                                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ 

Forwarder provides the reference to the slice of []*Route.

Property updates

Both Strategy and Health-Watcher can use the slice and use atomics to update each *Route individually.

Pool updates

In case if []*Route should change Forwarder will block on the Update Mutex adding to the slice and marking entities that should be removed as inactive (as they still can be in reference with the strategy which will block only on Next() entry).

Updates are rare, this design does not target additional optimizations.

Strategy Next()

Provided strategy will use the current reference for provide the selection mechanics as a forward iteration loop.

Strategy will block updateMutex on Next() but in following way:

func (s Strategy) Next() *Route {
	s.fwd.updateMutex.Lock()
	s.fwd.updateMutex.Unlock()
	// ... rest of the code
	// range s.fwd.Routes
}

This will adjust behavior to not pick the stale []*Route if Update Routes started to mark the entries and replacing the slice reference.

However, it will try to use the stale list once if it was fetched before Update Routes happened.


Rate Limiter

Introducing 2 paths to enforce rate limiting per customer pool and for unauthorized connections.

     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”Œβ”€β”€β”€β”€β”€Authorized β”œβ”€β”€β”€β”€β”                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Token Bucket  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     β”‚          β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚ β”Œβ”€β”€β”€β”€β”€β”  β”‚                              β”Œβ”€β”€β”€ Params β”œβ”€β”€β”  β”‚
β”‚  β”‚ Route Pool 1 │───┼──Has 1β”œβ”€β”€β–Ά                              β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚ β””β”€β”€β”€β”€β”€β”˜  β”‚  β”Œβ”€β”                         β”‚CAP:10  TOK:10β”‚  β”‚
β”‚                     β”‚          β”‚  β”‚0β”‚   ─┬─                   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚ β”Œβ”€β”€β”€β”€β”€β”  β”‚  β”‚ β”‚    β”‚  β”Œβ”€β”€β”¬β”€β”€β”¬β”€β”€β”        β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚  β”‚ Route Pool 2 │───┼──Has 1β”œβ”€β”€β–Ά  β”‚1β”‚    β”‚  β”‚R1β”‚R2β”‚R3β”‚        β”‚-3      TOK:7 β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚ β””β”€β”€β”€β”€β”€β”˜  β”‚  β”‚ β”‚    β”‚  β””β”€β”€β”΄β”€β”€β”΄β”€β”€β”˜        β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚                     β”‚          β”‚  β”‚2β”‚    β”‚                    β”‚ 0      TOK:7 β”‚  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚ β”Œβ”€β”€β”€β”€β”€β”  β”‚  β”‚ β”‚    β”‚  β”Œβ”€β”€β”¬β”€β”€β”¬β”€β”€β”¬β”€β”€β”     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚  β”‚ Route Pool N │───┼──Has 1β”œβ”€β”€β–Ά  β”‚3β”‚    β”‚  β”‚R4β”‚R5β”‚R6β”‚R7β”‚     β”‚+1 -4   TOK:3 β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚ β””β”€β”€β”€β”€β”€β”˜  β”‚  β”‚ β”‚    β”‚  β”œβ”€β”€β”Όβ”€β”€β”Όβ”€β”€β”Όβ”€β”€β”€ β”Œβ”€β”€β”β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚  β”‚4β”‚ β”Œβ”€β”β”‚  β”‚R8β”‚R9β”‚R0β”‚R1β”‚ β”‚XXβ”‚β”‚+1 -4   TOK:0 β”‚  β”‚
                                 β”‚  β”‚ β”‚ β”‚ β”‚β”‚  β”œβ”€β”€β”Όβ”€β”€β”Όβ”€β”€β”Όβ”€β”€β”˜ β””β”€β”€β”˜β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
                                 β”‚  β”‚5β”‚ β”‚ β”‚β”‚  β”‚R2β”‚XXβ”‚XXβ”‚        β”‚+1 -1   TOK:0 β”‚  β”‚
                                 β”‚  β”‚ β”‚ β”‚Tβ”‚β”‚  β”œβ”€β”€β”Όβ”€β”€β”Όβ”€β”€β”Όβ”€β”€β”     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
                                 β”‚  β”‚6β”‚ β”‚Iβ”‚β”‚  β”‚R3β”‚XXβ”‚XXβ”‚XXβ”‚     β”‚+1 -1   TOK:0 β”‚  β”‚
                                 β”‚  β”‚ β”‚ β”‚Mβ”‚β”‚  β”œβ”€β”€β”Όβ”€β”€β”Όβ”€β”€β”Όβ”€β”€β”€     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
                                 β”‚  β”‚7β”‚ β”‚Eβ”‚β”‚  β”‚R4β”‚XXβ”‚XXβ”‚XXβ”‚     β”‚+1 -1   TOK:0 β”‚  β”‚
                                 β”‚  β”‚ β”‚ β”‚ β”‚β”‚  β””β”€β”€β”΄β”€β”€β”΄β”€β”€β”΄β”€β”€β”˜     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
                                 β”‚  β”‚8β”‚ β”‚ β”‚β”‚                    β”‚ 0      TOK:0 β”‚  β”‚
                                 β”‚  β”‚ β”‚ β””β”€β”˜β”‚                    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
                                 β”‚  β”‚9β”‚    β”‚                    β”‚ 0      TOK:0 β”‚  β”‚
                                 β”‚  β”‚ β”‚    β”‚                    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
                                 β”‚  β”‚0β”‚   ─┼─                   β”‚ 0      TOK:0 β”‚  β”‚
                                 β”‚  β”‚ β”‚    β”‚  β”Œβ”€β”€β”¬β”€β”€β”¬β”€β”€β”        β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
                                 β”‚  β”‚1β”‚    β”‚  β”‚R4β”‚R5β”‚R6β”‚        β”‚+4 -3   TOK:1 β”‚  β”‚
                                 β”‚  β”‚ β”‚    β”‚  β”œβ”€β”€β”Όβ”€β”€β”΄β”€β”€β”˜        β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
                                 β”‚  β”‚2β”‚    β”‚  β”‚R7β”‚              β”‚+1 -1   TOK:1 β”‚  β”‚
                                 β”‚  β””β”€β”˜    β”‚  β””β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
                                 β”‚         β–Ό                                      β”‚
                                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜



    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”Œβ”€β”€β”€β”€Unauthorizedβ”œβ”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚              β”‚ Not In Cache │───┐
β”‚                    β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”      β”‚                     Ξ›           β”‚  β”Œβ”€β”€β”€β”€  LRU+TTL CACHE  β”œβ”€β”€β”€β”
β”‚      β”‚ IP 1 │──────┼────┐               β•± β•²          β”‚  β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚      β””β”€β”€β”€β”€β”€β”€β”˜      β”‚    β”‚              β•±   β•²         └──┼▢──────┬────┬──────────┐ β”‚
β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”      β”‚    β”‚             β•±     β•²           β”‚β”‚IPADDRβ”‚ 1  β”‚*time.Timeβ”‚ β”‚
β”‚      β”‚ IP 2 │──────┼─────            β•±       β•²          β”‚β”œβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚
β”‚      β””β”€β”€β”€β”€β”€β”€β”˜      β”‚    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Ά Check   ▏         β”‚β”‚IPADDRβ”‚ 4  β”‚*time.Timeβ”‚ β”‚
β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”      β”‚    β”‚            β•² Cache β•±          β”‚β”œβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚
β”‚      β”‚ IP 3 │──────┼─────             β•²     β•±           β”‚β”‚IPADDRβ”‚ 5  β”‚*time.Timeβ”‚ β”‚
β”‚      β””β”€β”€β”€β”€β”€β”€β”˜      β”‚    β”‚              β•²   β•±            β”‚β””β”€β”€β”€β”€β”€β”€β”΄β”€β–²β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”      β”‚    β”‚               β•² β•±             β”‚    β”Œβ”€β”€β”€β”€β”˜               β”‚
β”‚      β”‚ IP N β”‚β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”˜                V              β””β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚      β””β”€β”€β”€β”€β”€β”€β”˜      β”‚             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚
β”‚                    β”‚             β”‚   In Cache   β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚         β”‚
                                           β”‚              β”‚Incrementβ”‚
                                           β”‚              β”‚ counter β”‚
                                           └─────────────▢│         β”‚
                                                          β”‚If < thanβ”‚
                                                          β”‚thresholdβ”‚
                                                          β”‚         β”‚
                                                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Per-session: When TLS Handshake happened and session got authorization

In this path we provide a Token bucket for each customer pool resource, which will provide the sliding window for the authorized sessions.

For this design we assuming customer is using one balancer services pool as one instance of the service provided and by that design implies rate limiter per one identity of customer pool.

Per IP address: When TLS Handshake failed

As we must address possibly super-large chunk of IP data to store in memory, in the scope of this library (not distributed) we will provide LRU TTL cache of size, which will update and purge while being called for the records.

  1. Before TLS Handshake β€” we will peek in the cache to see if we should perform TLS at all
  2. After TLS Handshake failed β€” we will put record in the cache

Health Check Scheduler

For managing Unhealthy routes we can create simple service based on concurrent Min-time-to-next-check PriorityQueue. Forwarder can offer *Route to this scheduler.

  • Scheduler will process *Route entries while Active and !Healthy.
  • Scheduler can be configured to do multiple checks before promote to Healthy with checks param
  • If *Route not Active anymore, it will not do Push() after Pop()

Design scheme represents all above properties nicely:

                                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  Health Check Routine  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ SubmitUnhealthy() β”‚         β”‚             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”‚
            β”‚                   β”‚                 β”‚ Priority Queue β”‚                    β”‚
            β”‚                   β”‚                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
            β”‚                   β”‚                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”            β”‚                 β”‚     Poll()     β”‚                    β”‚
     β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚            β”‚                 β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
     β”‚ β”‚ *Route β”‚  β”‚            β”‚                         β”‚                             β”‚
     β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚            β”‚                         β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”                   β”‚
     β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚            β”‚                        β•± β•²β”‚ Mutex β”‚                   β”‚
     β”‚ β”‚ checks β”‚  β”‚            β”‚                       β•±   β””β”€β”€β”€β”€β”€β”€β”€β”˜    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
     β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚            β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”           β”Œβ”€β”€β”€β”€β”€β”           β”‚priority β”‚    β”‚
     β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚            β”‚  β”‚ Empty ◀───────────│PEEK β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Ά    >    β”‚    β”‚
     β”‚ β”‚ passed β”‚  β”‚            β”‚  β””β”€β”€β”€β”¬β”€β”€β”€β”˜           β””β”€β”€β”€β”€β”€β”˜           β”‚time.Now β”‚    β”‚
     β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚            β”‚      β”‚                β•²   β•±            β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜    β”‚
     β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚            β”‚      β”‚                 β•² β•±                  β”‚         β”‚
     β”‚ β”‚  next  β”‚  β”‚            β”‚      β”‚                  β”‚                   β”‚         β”‚
     β”‚ β”‚ check  β”‚  β”‚            β”‚β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”            β”‚            β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”  β”‚
     β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚            β”‚β”‚   Await   β”‚       β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”       β”‚    Await    β”‚  β”‚
     β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜            β”‚β”‚           β”‚       β”‚time.Now β”‚       β”‚             β”‚  β”‚
        β”Œβ”€β”€β”€β”΄β”€β”€β”€β”€β”              β”‚β”‚ <-newTask β”‚       β”‚    >    β”‚       β”‚  <-newTask  β”‚  β”‚
        β”‚ Push() β”‚              β”‚β”‚<-ctx.Done β”‚       β”‚ priorityβ”‚       β”‚<-time.After β”‚  β”‚
        β””β”€β”€β”€β”¬β”€β”€β”€β”€β”˜              β”‚β”‚           β”‚       β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜       β”‚ <-ctx.Done  β”‚  β”‚
            β”‚                   β”‚β”‚sleeping=1 β”‚            β”‚            β”‚             β”‚  β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚ Priority Queue           β”‚    β”‚                    β”‚  Pop()  β”‚                        β”‚
β”‚                          β”‚    β”‚                    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜                        β”‚
β”‚ MIN:(time.Now+nextCheck) β”‚    β”‚                         β”‚                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚                    β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”                        β”‚
            β”‚                   β”‚             β”Œβ”€β”€β”€β”€β”€β”€β”‚re Dial()│──────┐                 β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”            β”‚             β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚                 β”‚
     β”‚             β”‚            β”‚             β”‚                       β–Ό                 β”‚
     β”‚ if sleeping β”‚            β”‚             β–Ό                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚
     β”‚  newTask <- β”‚            β”‚        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚ passed  β”‚            β”‚
     β”‚  sleeping=0 β”‚            β”‚        β”‚passed=0β”‚              β”‚   ==    β”‚            β”‚
     β”‚             β”‚            β”‚        β””β”€β”€β”€β”€β”¬β”€β”€β”€β”˜              β”‚ checks  β”‚            β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚             β”‚                  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜            β”‚
                                β”‚             β”‚                       β”‚                 β”‚
                                β”‚        β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”              β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”            β”‚
                                β”‚        β”‚ Push() β”‚              β”‚ *Route  β”‚            β”‚
                                β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚ active  β”‚            β”‚
                                β”‚                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚
                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Security Authentication and Credential provision


Proposed mTLS layer consists of the following scheme:

                                                                    ╔════════════╗
                                                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•£    Load    ╠─────────────┐
                                                      β”‚             β•‘  balancer  β•‘             β”‚
                                                      β”‚             β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•             β”‚
                                                      β”‚                                        β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                          β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”‚
β”‚          β”‚                                       β”Œβ”€β”€β”Όβ”€β”€β”€β”€β”€β”€β–Άβ”‚  Accept Cert  β”‚                β”‚
β”‚  CACert  │───────┐        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚  β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
β”‚          β”‚       β”‚        β”‚            β”‚         β”‚  β”‚               β”‚                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”Œβ”€β”€β”€β”€β”΄β”€β”€β”     β”‚   Client   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”΄β” β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”                β”‚
              β”‚Produceβ”‚     β”‚    Cert    β”œβ”€β”€β”€Connectβ”‚ β”‚       β”‚  Fetch CN     β”‚                β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  TLS  β”œβ”€β”€β”€β”€β–Άβ”‚            β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
β”‚  Client  β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”˜     β”‚ CN=Identityβ”‚            β”‚               β”‚                        β”‚
β”‚ Frontend β”‚       β”‚        β”‚            β”‚            β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β”˜                        β”‚
β”‚  Access  β”‚β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚       β”‚                                β”‚
β”‚    key   β”‚                                         β”Œβ”΄β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                         β”‚ Lookup Access  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
                                                     β”‚  Key in Cache  β”‚    β”‚  Dispatch to    β”‚ β”‚
                                                     β”‚  of available  │────▢correct Forwarderβ”‚ β”‚
                                                     β”‚ customer pools β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
                                                     β””β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                        β”‚
                                                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Common Name Identity

Provided to Load Balancer with AddForwarderPool(pool ServicePool) method where ServicePool is the interface for the persistent configuration. ServicePool.Identity() will be used to ensure CN match for authorization.

This design will limit scope of Identity to simple selection of the whole set of the customer pool for such identity.

As the future next steps certificate can be enriched with property like the OU=role and this will provide ability to have customer pools to routed for the authentication with additional precision.

Scope

For the scope of the project and simplicity of initial implementation we consider following:

  • Encryption Key RSA 3072
  • Cipher Suites: TLS v1.3 compliant set
  • Client Common Name will be pre-filled with Identity Key (for Forwarder selectors)
  • TLS v1.3 as default configuration

Considerations

  • mTLS Layer will match CN Access Key to the available Identity Keys in the connection manager at the time of connection, scope should be limited to memory intensive operations for authorizing the connection
  • DDoS event might pile up the waiting connections on the port, raising opened descriptors on the Linux machine to the limits, after which we can lose replica. For this to happen flow of the connections should exceed processing power for certificate signature verification + hashMap access time.
  • System should be able to drop connection and close descriptors as fast as possible
  • Local IP Rate Limiter cache should help to drop unwanted connections for reasonable amount of IP Address records, taking the LRU structure per IP at ~approx:
    • max(4 bytes (16 for str) + 1byte + Time(8 bytes) + DLL(8 + 8 + 8 bytes) + MAP(8 + 8 bytes)) < 128 bytes
    • in 1Kb we can carry at least 8 LRU records, 8000 in 1Mb or 800000 in 100Mb, 8M in 1Gb
    • capacity of 8M records to be dropped before additional CPU cycles can give some insurance