-
Notifications
You must be signed in to change notification settings - Fork 103
Sticky Cookie
HTTP cookies are used as HTTP session identifiers. Tempesta FW reads the Cookie:
request header and matches 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 Tempesta FW's side. While learned cookies are good for load balancing stickiness, the own Tempesta FW's cookies can provide extra DDoS mitigation possibilities.
Session management options are configured per-vhost inside sticky
block.
sticky {
cookie [name=<COOKIE_NAME>] [enforce] [max_misses=<LIMIT>];
cookie_options [OPTIONS];
learn name=<NAME>;
secret <SECRET_PHRASE>;
js_challenge delay_min=<TIME> delay_range=<TIME> [resp_code=<CODE>]
[SCRIPT_TEMPLATE];
sticky_sessions [allow_failover];
}
The sections at the below describe each directive in details.
A sticky
block outside of any vhost modifies session management
defaults for vhosts below and doesn't affect configuration of previously defined
vhosts. Default values can be modified multiple times, but every time a new
sticky
section is added, results of the previous one are negated. Example:
# Vhost description has no 'sticky' section, thus session management is disabled.
vhost static_content.com {
}
# Vhost description has 'sticky' section, session management is configured as
# defined there.
vhost example.com {
sticky {
cookie name=__tfw;
}
}
# Modify session management defaults for all vhosts below. Directives not listed
# in this section will follow default values from the documentation.
sticky {
cookie name=__tfw;
}
# Vhost description without 'sticky' section follows modified defaults:
# directive 'cookie name=__tfw' is inherited here.
vhost inherit.com {
}
# Vhost description with explicit 'sticky' directive will use the modified
# defaults unless other values are described in 'sticky' section: 'cookie'
# directive will be inherited, while 'sticky_sessions' is redefined here.
vhost inherit-n-update.com {
sticky {
sticky_sessions;
}
}
# Modify session management defaults once again. All the previous
# modifications are removed.
sticky {
...
}
The only exception is the cookie
, js_challenge
and cookie_options
directives,
which can be inherited together only. Since js_challenge
and cookie_options
are
highly depended on cookie
configuration, they can be inherited only with cookie
directive.
If the cookie
directive is explicitly set in a vhost, then the js_challenge
and
cookie_options
directives are not derived.
Detailed description of every directive is at the below, but there is also an article on migration from NGINX in our wiki.
Sticky cookie is a special HTTP cookie that is generated by Tempesta FW 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, Tempesta FW sticky cookie is expected in incoming HTTP requests.
Otherwise, Tempesta FW 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 Tempesta FW 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>];
}
name
parameter specifies a custom Tempesta FW 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 Tempesta FW sticky cookie is present in each
HTTP request. If it is not present in a request, a client receives HTTP 302
response from Tempesta FW that redirects the client to the same URI, and prompts
that Tempesta FW 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 1).
cookie_options
parameter sets additional cookie options. If it is not explicitly set
Path='/' and Max-Age='session lifetime' are added to cookie options. If Expires is set
in cookie options and Max-Age is not Tempesta FW doesn't add Max-Age to cookie options.
Exact meanings of the options can be found in
MDN
Below are examples of Tempesta FW sticky cookie directive.
sticky {
cookie;
}
Enable Tempesta FW sticky cookie. Default cookie name is used. Tempesta FW expects
that Tempesta FW sticky cookie is present in each HTTP request. If it is not
present, then Tempesta FW includes Set-Cookie
header field in an HTTP response,
which prompts that Tempesta FW sticky cookie with default name is set in requests
from the client.
sticky {
cookie enforce;
}
Enable Tempesta FW sticky cookie. Default cookie name is used. Tempesta FW expects
that Tempesta FW sticky cookie is present in each HTTP request. If it is not
present, Tempesta FW sends HTTP 302 response that redirects the client to
the same URI and includes Set-Cookie
header field, which prompts that
Tempesta FW sticky cookie with default name is set in requests from the client.
sticky {
cookie name="__cookie__";
}
Enable Tempesta FW sticky cookie. The name of the cookie is __cookie__
.
Tempesta FW expects that Tempesta FW sticky cookie is present in each HTTP request.
If it is not present, then Tempesta FW includes Set-Cookie
header field in
an HTTP response, which prompts that Tempesta FW sticky cookie with the name
__cookie__
is set in requests from the client.
sticky {
cookie name="__cookie__" enforce max_misses=10;
}
Enable Tempesta FW sticky cookie. The name of the cookie is __cookie__
.
Tempesta FW expects that Tempesta FW sticky cookie is present in each HTTP request.
If it is not present, Tempesta FW sends HTTP 302 response that redirects
the client to the same URI and includes Set-Cookie
header field, which
prompts that Tempesta FW sticky cookie with the name __cookie__
is set in
requests from the client. If the number of HTTP requests without sticky cookie
will exceed 10 such client will be blocked.
sticky {
cookie;
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; Path=/; Max-Age=4294967295;
.
It is important to note that Tempesta FW by default adds Path and Max-Age cookie options if they
are not explicitly set.
Exact meanings of the options can be found in
MDN.
sticky {
cookie;
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 Tempesta FW restart.
<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.
The challenge mitigates application-level (L7) DDoS attacks by
- allowing only JavaScript-enabled clients (browsers) to access the protected website
- and requiring all clients to slow down their request rate.
This challenge isn't assumed to prevent a targeted attack, which was developed precisely against a particular website. Also it isn't assumed to prevent low-rate bot attacks like scrappers, carders and so on. Please check Tempesta FW page or contact us for Tempesta FW enterprise version providing advanced bots protection.
When a new client tries to access the protected resource, Tempesta FW
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 new sticky cookie will be sent to such client. If client violates cookies too often (exceeded max-misses limit) such client will be blocked.
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 requests. 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 response from cache if it is present or 503
response with
Retry-After:
a hint.
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>]
[SCRIPT_TEMPLATE];
}
delay_min
- milliseconds, the minimum delay when a client is allowed to
repeat its request with Sticky Cookie set. Value is used in JS challenge code
and to be sent to client.
delay_range
- milliseconds, the period of time during which a client is
allowed to send request with Sticky Cookie set. Value is used in JS challenge
code and to be sent to client.
When a client receives the JS challenge it must wait (delay) for
delay_min + <random>
milliseconds (<random>
is between 0
and delay_range
)
and send the redirected request. When Tempesta FW receives the redirected request
it ensures that it is received not earlier than delay_min
(to mitigate a DDoS
attack by slowing down the request rate).
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.
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 thejs_challenge
andsticky
directives.
Examples:
sticky {
cookie name=my_js_cookie enforce max_misses=3;
js_challenge resp_code=503 delay_min=1000 delay_range=1000 /etc/ddos_redirect.html;
}
sticky {
cookie enforce;
js_challenge delay_min=1000 delay_range=1000;
}
Note that browsers 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 if you face any issues with the redirection timeouts.
Learn how to configure JavaScrip challenge when migrating from NGINX and testcookie-nginx-module.
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_sessions
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.
Learn how to configure session persistence when migrating from NGINX.
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;
Session lifetime is used to set Max-Age cookie option if it is not explicitly set by administrator.
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 .tdb
.
sessions_tbl_size <SIZE>
: Size of sessions database file in bytes.
Defaults: 16M
.
Can use suffixes K, M, G. 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