-
Notifications
You must be signed in to change notification settings - Fork 103
Sticky Cookie
HTTP cookies are used as HTTP session identifiers. TempestaFW reads the Cookie:
request header and mathes the cookies to list of known sessions to provide
load balancing stickiness,
i.e. all requests from the same HTTP agent are forwarded to the same backend
server.
There is two ways to set the session cookie ether learn the cookies advertised by backend servers or create them on TempestaFW's side. While learned cookies are good for load balancing stickiness, the own TempestaFW's cookies can provide extra DDoS mitigation possibilities.
Session management options are configured per-vhost inside sticky
block.
Defining sticky
block outside of any vhost will modify session management
defaults for vhosts below the definition.
vhost static_content.com {
# Session managemet is disabled.
}
vhost example.com {
sticky {
# Session management for vhost example.com
}
}
sticky {
# Modify session management defaults.
}
vhost other-example.com {
# Modified session management defaults will be used for vhost
# other-example.com
}
Sticky cookie is a special HTTP cookie that is generated by TempestaFW and advertised to client. It allows for unique identification of each client and can be used as challenge cookie for simple L7 DDoS mitigation when bots are unable to process cookies. It can be even more fortified with the JavaScript challenge discussed below.
When used, TempestaFW sticky cookie is expected in incoming HTTP requests.
Otherwise, TempestaFW will respond with redirect and the Set-Cookie:
header.
By default the sticky cookie is disabled.
Normal browsers supports cookies and follows redirects:
Bots not supporting cookies will be filtered:
The use and behaviour of TempestaFW sticky cookies is controlled by a single configuration directive that can have several parameters. The full form of the directive and parameters is as follows:
sticky {
cookie [name=<COOKIE_NAME>] [enforce] [max_misses=<LIMIT>] [timeout=<TMT>] [options=<OPT>];
}
name
parameter specifies a custom TempestaFW sticky cookie name COOKIE_NAME
for use in HTTP requests. It is expected that it is a single word without
whitespaces. If not specified explicitly, a default name __tfw
is used.
enforce
parameter demands that TempestaFW sticky cookie is present in each
HTTP request. If it is not present in a request, a client receives HTTP 302
response from TempestaFW that redirects the client to the same URI, and prompts
that TempestaFW sticky cookie is set in requests from the client.
max_misses
parameter sets the maximum count of redirected requests
(with no cookie or with incorrect cookie value). This option is applicable
only if 'enforce' mode is enabled. If configured limit is exhausted, the
corresponding client will be blocked. LIMIT
is non-negative integer
(default value is 0, which means that limit verification is disabled).
timeout
- sets the maximum period between the first redirected request and
successful cookie verification. This option is applicable only if 'enforce' mode
is enabled and 'max_misses' parameter has value greater then zero. If configured
timeout is expired, the corresponding client will be blocked. TMT
is non-negative
integer (default value is 0, which means that timeout tracking is disabled).
options
- string of extra options for TempestaFW sticky cookie. Added after
cookie value as plain string in 'Set-Cookie' header. The field may contain
multiple options, in this case, the options must be split with semi-colon
and space.
Below are examples of TempestaFW sticky cookie directive.
sticky {
cookie;
}
Enable TempestaFW sticky cookie. Default cookie name is used. TempestaFW expects
that TempestaFWsticky cookie is present in each HTTP request. If it is not
present, then TempestaFWincludes Set-Cookie
header field in an HTTP response,
which prompts that TempestaFWsticky cookie with default name is set in requests
from the client.
sticky {
cookie enforce;
}
Enable TempestaFW sticky cookie. Default cookie name is used. TempestaFW expects
that TempestaFWsticky cookie is present in each HTTP request. If it is not
present, TempestaFWsends HTTP 302 response that redirects the client to
the same URI and includes Set-Cookie
header field, which prompts that
TempestaFWsticky cookie with default name is set in requests from the client.
sticky {
cookie name="__cookie__";
}
Enable TempestaFWsticky cookie. The name of the cookie is __cookie__
.
TempestaFWexpects that TempestaFWsticky cookie is present in each HTTP request.
If it is not present, then TempestaFWincludes Set-Cookie
header field in
an HTTP response, which prompts that TempestaFWsticky cookie with the name
__cookie__
is set in requests from the client.
sticky {
cookie name="__cookie__" enforce max_misses=10 timeout=15;
}
Enable TempestaFWsticky cookie. The name of the cookie is __cookie__
.
TempestaFWexpects that TempestaFWsticky cookie is present in each HTTP request.
If it is not present, TempestaFWsends HTTP 302 response that redirects
the client to the same URI and includes Set-Cookie
header field, which
prompts that TempestaFWsticky cookie with the name __cookie__
is set in
requests from the client. If the number of HTTP requests without sticky cookie
will exceed 10 or 15 seconds have elapsed since first redirected request until
successful cookie verification, such client will be blocked.
sticky {
cookie options="Domain=example.com ; Secure ; HttpOnly";
}
The Set-Cookie:
header will be formatted with extra values and will look like
Set-Cookie: __tfw=<HMAC_VALUE> Domain=example.com ; Secure ; HttpOnly;
.
Exact meanings of the options can be found in
MDN.
sticky {
cookie options="Max-Age=3600";
}
The expire time in seconds is defined for the cookie in seconds, transforming
the cookie form the session to permanent for HTTP agent. Client will continue
to use the cookie until it's expired.
Sticky cookie value is calculated on top of client IP, User-Agent, session timestamp and the secret used as a key for HMAC.
secret <SECRET_PHRASE>;
The option sets the secret string used for HMAC
calculation. It's desirable to keep this value in secret to prevent automatic
cookies generation on attacker side.
Defaults: a new random value on every start. This means that all user HTTP sessions are
invalidated on TempestaFWrestart.
<SECRET_PHRASE>
: quoted secret string, maximum length is 20 bytes.
Example:
secret "f00)9eR59*_/22";
Client too often trying to reach resource with incorrect Sticky Cookie value will be blocked. Client too often trying to request a new sticky cookie will be blocked. Client trying to acquire too lot of simultaneous sessions will be blocked.
The feature is still under development and is planned for upcoming 0.7 release.
While the Sticky Cookie option is a good solution to protect backend servers from the simplest bots, JavaScript Challenge options enhances the protection to filter bots which are capable to follow redirects and support cookies.
When a new client client tries to access the protected resource, TempestaFW
responds with 503 status code, Set-Cookie:
header and JavaScript code in
message body. JavaScript code will force client to reload resource at
allowed time frame. After the client reloads resource at allowed time frame
it will be granted to have access to the protected resource. JavaScript
challenge won't be sent to the client once again in this session. After the
sticky cookie assigned to the client will expire, a new JS challenge will be
performed.
If client tries to reach resource outside of allowed time frame, it's requests will be treated as Sticky Cookie violation and will be filtered. Client will be blocked if it violates cookies too often.
If bot is a full web stack client (full featured web browser), it can process JavaScript challenge and proper configuration of Sticky Cookie rate limits is required.
Not all requests can be challenged with JavaScript. Browsers don't run
JavaScript for responses to images, multimedia and non-GET responses. But
when a user loads page in his browser (following a link, opening bookmark
or manually inputting address in the address bar), the very first request
is used to get and build DOM. Such request always contain text/html
token in Accept
header and browser evaluates JS code even on direct
links to images. Thus only the very first request is subject for
JS challenge. But if HTTP client sends non-challengable request until the session is
confirmed, it receives 503
response with Retry-After:
hint or gets
blocked by connection close.
The JavaScript challenge requires explicit sticky cookie configuration, so
cookie
option with at least enforce
attribute is required for the JS
challenge sticky
configuration.
sticky {
cookie enforce;
js_challenge delay_min=<TIME> delay_range=<TIME> [resp_code=<CODE>]
[delay_limit=<TIME>] [SCRIPT_TEMPLATE];
}
delay_min
: Start of allowed time frame - delay before client is allowed to
repeat it's request with Sticky Cookie set. Value is used in JS challenge code
and to be sent to client.
delay_range
: Duration of allowed time frame - maximum delay when client is
allowed to send request with Sticky Cookie set. Value is used in JS challenge
code and to be sent to client.
delay_limit
: Maximum difference between current time on evaluation client's
request and Sticky Cookie generation time. Optional parameter.
resp_code
: Status code for response with JS challenge. Optional parameter,
default is 503
.
<SCRIPT_TEMPLATE>
: Path to response template with JS challenge script.
Optional parameter, default is /etc/tempesta/js_challenge.html
, see
Custom JS challenge template chapter.
<TIME>
: time in usecs.
NOTE: During start process
tempesta.sh
usesgrep
to update <SCRIPT_TEMPLATE> file with values described injs_challenge
directive, so line breaks are not allowed inside directivesjs_challenge
andsticky
.
Examples:
sticky {
cookie name=my_js_cookie enforce max_misses=3 timeout=3;
js_challenge resp_code=503 delay_min=1000 delay_range=1000 delay_limit=3000 /etc/ddos_redirect.html;
}
sticky {
cookie enforce;
js_challenge delay_min=1000 delay_range=1000;
}
Note that browswers automatically retry error responses such as 3xx or 5xx. It's recommended to use
resp_code=503
with the JavaScript challenge since a browser should display a 5xx response body by RFC 7231 6.6 (i.e. don't ignore the response body). The retry timeout is crucial for the JavaScript challenge, so any earlier retries from a browser side may lead to full client blocking. At the moment we do no send Retry-After due to vague state of all the browser implementations. Also see the Mozilla bug report. Please file us a bug report face any issues with the redirection timeouts.
It's recommended to modify default JS challenge response template file
js_challenge.tpl
located in configuration files directory
(/etc/tempesta/
by default) rather than provide a brand new template file
since JS challenge code must be synchronised with TempestaFW configuration file.
Attribute name
of sticky
directive, attributes delay_min
and delay_range
of js_challenge
directive must be passed to JS challenge code template.
By default Sticky cookie only provide challenge to mitigate DDoS attacks
and doesn't imply session persistence. To pin the session to the backend server
additional directive sticky_session
should be used.
When client passes sticky cookie challenge, his session is confirmed but not assigned to any backend server. First request in the session is scheduled to server groups assigned to the vhost as usual. All the following requests will be forwarded to that server.
The situation, how a request is handled if the pinned server goes down depends
in allow_failover
option. If the option is set, the session is re-pinned to
other server and stays there even when the original server goes back online.
Otherwise client will receive 502 response code until backend comes back online,
no re-pinning will happen.
sticky_sessions [allow_failover];
If the directive is set, the session is pinned
to backend server. allow_failover
option allows to re-pin session to other
server, if original goes down.
Learned sessions can't be used to mitigate DDoS attacks. It doesn't involve any challenges to clients before accessing backends and requests are forwarded to backends immediately.
TempestaFW reads Set-Cookie:
header from backend server response and creates
a new session entry pinned to that backend server. All the requests with the
same cookie will be forwarded to that server.
Unlike native TempestaFW sticky cookie the learned cookie doesn't cryptographically confirm the exact cookie owner - client with it's own unique IP-address and User-Agent, so malicious clients may try to steal the session and try to bypass the load balancer and exhaust singe backend server. Thus the option should be used with caution.
If clients doesn't set the cookie advertised by backend, no pinning is performed and all the requests are forwarded to backend servers with load balancing rules.
To configure the learned session directive learn
should be used.
sticky {
learn name=<NAME>;
}
Where NAME
- name of the cookie advertised by backend server and used by
clients.
Directives cookie
, js_challenge
conflicts with the learn
directives.
Directive secret
has no affect on learn
directive.
Session lifetime is different from cookie lifetime. Cookie lifetime is
configured in Set-Cookie:
response header and controls how long clients will
keep the cookie and try to use it. Session lifetime controls how long the
session entry is stored in TempestaFW database.
If the sticky cookie session is expired then client is forced to restart the cookie challenge. If the learned session is expired, the request will be forwarded to any configured backed server and a new session will be learned from its response.
sess_lifetime <SECONDS>
: HTTP session lifetime in seconds. For
sticky cookie sessions - total session lifetime, for learned - lifetime
from last request using the session.
Defaults: 0
, i.e. unlimited life time.
Example:
sess_lifetime 900;
Sessions are stored in TempestaDB. The following configuration options controls the location and size of database.
sessions_db <PATH_TO_DB>
: Path to a sessions database files.
Defaults: /opt/tempesta/db/sessions.tdb
The PATH must be absolute and the directory must exist. The database file
must end with .tbd
.
sessions_tbl_size <SIZE>
: Size of sessions database file in bytes.
Defaults: 16777216
(16MB).
Suffixes like 'MB' are not supported yet. The size must be multiple of 2MB
(Tempesta DB extent size).
- Home
- Requirements
- Installation
-
Configuration
- Migration from Nginx
- On-the-fly reconfiguration
- Handling clients
- Backend servers
- Load Balancing
- Caching Responses
- Non-Idempotent Requests
- Modify HTTP Messages
- Virtual hosts and locations
- HTTP Session Management
- HTTP Tables
- HTTP(S) Security
- Header Via
- Health monitor
- TLS
- Virtual host confusion
- Traffic Filtering by Fingerprints
- Run & Stop
- Application Performance Monitoring
- Use cases
- Performance
- Contributing