Documentation
¶
Overview ¶
Package tlslimit provides a rate limiter to fewer expensive TLS handshakes.
Example ¶
package main
import (
"crypto/tls"
"net/http"
"time"
"github.com/shaj13/tlslimit"
)
func main() {
// Declare the actual callbacks to retrieve the server certificate
// you don't need both callbacks, choose the one that suits your application needs.
//
// Most callers prefer the GetCertificate.
getCert := func(ci *tls.ClientHelloInfo) (*tls.Certificate, error) {
// Return actual certificate.
return nil, nil
}
getConfig := func(ci *tls.ClientHelloInfo) (*tls.Config, error) {
// Return actual config.
return nil, nil
}
// Define a Limiter to enforce TLS rate limiting.
// To prevent a client from exhausting application resources
// and mitigates SSL/TLS exhaustion DDoS attacks.
//
// For Example Allow 20 TLS handshakes per minute for each client IP.
lim := tlslimit.NewLimiter(
tlslimit.WithBursts(20),
tlslimit.WithLimit(time.Minute),
tlslimit.WithTLSClientIP(),
// Use WithGetCertificate or WithGetConfigForClient
tlslimit.WithGetCertificate(getCert),
tlslimit.WithGetConfigForClient(getConfig),
)
// Tie the Limiter to the tls.Config.
cfg := &tls.Config{
// Use GetCertificate or GetConfigForClient
GetCertificate: lim.GetCertificate,
GetConfigForClient: lim.GetConfigForClient,
MinVersion: tls.VersionTLS13,
}
srv := http.Server{
TLSConfig: cfg,
}
_ = srv.ListenAndServeTLS("", "")
}
Index ¶
- type Limiter
- type Option
- func WithBursts(b int) Option
- func WithCacheMaxSize(size int) Option
- func WithGetCertificate(fn func(*tls.ClientHelloInfo) (*tls.Certificate, error)) Option
- func WithGetConfigForClient(fn func(*tls.ClientHelloInfo) (*tls.Config, error)) Option
- func WithLimit(r time.Duration) Option
- func WithTLSClientIP() Option
- func WithTLSHostname() Option
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Limiter ¶
type Limiter struct {
// contains filtered or unexported fields
}
Limiter controls how frequently TLS handshakes are allowed to happen. It implements a "token bucket" of size b, initially full and refilled at rate r tokens per duration. See https://en.wikipedia.org/wiki/Token_bucket for more about token buckets.
The zero value is a valid Limiter, but it will reject all TLS handshakes. Use NewLimiter to create non-zero Limiters.
Limiter has two main methods, GetCertificate, and GetConfigForClient suitable to be used in tls.Config
Each of the two methods consumes a single token. If no token is available, It returns error to abort TLS handshake. If client reuse TLS connections (HTTP2), the two methods will not be invoked by "crypto/tls" package then the rate limiting will not be applied. This translates to fewer expensive TLS handshakes, mitigates SSL/TLS exhaustion DDoS attacks, and an overall reduction in required server resources without affecting the overall number of concurrent requests that the server can handle.
Limiter by default applies global rate limiting. Use WithTLSHostname or WithTLSClientIP to apply rate limiting per ip or domain.
func NewLimiter ¶
NewLimiter returns a new Limiter that allows TLS handshakes up to rate r and permits bursts of at most b tokens.
func (*Limiter) GetCertificate ¶
func (lim *Limiter) GetCertificate(ci *tls.ClientHelloInfo) (*tls.Certificate, error)
func (*Limiter) GetConfigForClient ¶
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option configures Limiter using the functional options paradigm popularized by Rob Pike and Dave Cheney. If you're unfamiliar with this style, see https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html and https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis.
func WithBursts ¶
WithBursts defines the maximum number of TLS handshakes. A zero Burst allows no TLS handshakes.
func WithCacheMaxSize ¶
WithCacheMaxSize defines maximum number of cache entries.
func WithGetCertificate ¶
func WithGetCertificate(fn func(*tls.ClientHelloInfo) (*tls.Certificate, error)) Option
WithGetCertificate returns a tls.Certificate based on the given tls.ClientHelloInfo. It will only be called if the Limiter.GetCertificate sat in tls.Config and client TLS handshakes rate limits does not exceeded.
If fn is nil or returns nil, then the TLS handshakes will be aborted.
See the documentation of tls.Config: https://pkg.go.dev/crypto/tls#Config for more information.
func WithGetConfigForClient ¶
WithGetConfigForClient returns a tls.Config based on the given tls.ClientHelloInfo. It will only be called if the Limiter.GetConfigForClient sat in tls.Config and client tls handshakes rate limit does not exceeded.
If fn is nil or returns nil, then the original tls.Config will be used.
See the documentation of tls.Config: https://pkg.go.dev/crypto/tls#Config for more information.
func WithLimit ¶
WithLimit defines the maximum frequency of TLS handshakes. A zero Limit allows no TLS handshakes.
func WithTLSClientIP ¶
func WithTLSClientIP() Option
WithTLSClientIP apply rate limiting per IP by using *tls.ClientHelloInfo.Conn.RemoteAddr() as a key.
func WithTLSHostname ¶
func WithTLSHostname() Option
WithTLSHostname apply rate limiting per domain by using *tls.ClientHelloInfo.ServerName as a key.