-
Notifications
You must be signed in to change notification settings - Fork 103
HTTP tables
Tempesta FW's HTTP tables is an extension of standard Linux iptables and/or nftables for the network application layer, HTTP(S) protocol in particilar. The network layers, layer 7 for the HTTP tables and layers 3 & 4 for iptables and nftables, are integrated by netfilter packets marking. Using HTTP tables glued with iptables/nftables by mark, you can define complex and efficient multi-layer rules for load balancing, Web security, and DDoS mitigation.
HTTP tables look inside of an HTTP request and examines it's contents such as URI and headers to find out the target virtual host. The work of HTTP tables is represented by a list of linked HTTP chains. Each chain contains pattern-matching rules that map certain header field values to virtual host.
The full syntax is as follows:
http_chain NAME {
[ FIELD [HDR_NAME] == (!=) ARG ] -> ACTION [ = VAL];
...
}
NAME
: Unique identifier of HTTP chain
FIELD
is an HTTP request field such as uri, host, etc.
Supported FIELD
keywords:
-
uri
- only a part of URI is looked at that contains the path and the query string if any (e.g. "/abs/path.html?query&key=val#fragment"). -
host
- the host part from URI in HTTP request line, or the value of "Host" header field. The Host part in URI takes priority over the Host header field value. -
method
- HTTP request method. Supported ARG values for this field are: "copy", "delete", "get", "head", "lock", "mkcol", "move", "options", "patch", "post", "propfind", "proppatch", "put", "trace", "unlock", "purge". -
hdr
- the content of specific HTTP header. In this case HDR_NAME field is used to specify the name of header; the value of header should be specified in ARG. Matching of special headers: "X-Forwarded-For", "If-None-Match", "Referer", "Cookie", "User-Agent", "Content-Type", "Connection", "Host" - is accelerated; proccessing of other headers may be slow as it requires walking over all headers of an HTTP request. Also, suffix OP is not supported for not special headers. -
mark
- the value of netfilter mark of request's skb.
In configuration example below
http_chain {
mark == 1 -> app;
...
means that all requests with netfilter
MARK set to 1 must be passed to virtual host app
. Netfilter MARK can be set via iptables
command line interface:
iptables -t mangle -A PREROUTING -p tcp -s 192.168.1.1 -j MARK --set-mark 1
Command specified above means that all tcp
packets arrived from 192.168.1.1
address, must be marked with 1 value (MARK is set in PREROUTING
netfilter chain).
ARG
is an argument (such as "/foo/bar.html", "example.com", etc.) for comparison
with FIELD
. The type of comparison for FIELD
and ARG
depends on ==
(!=
) sign
and on wildcard existance in ARG
:
-
==
: "ARG" =>eq
, "ARG*" =>eq_prefix
, "*ARG" =>eq_suffix
. -
!=
: "ARG" =>non_eq
, "ARG*" =>non_eq_prefix
, "*ARG" =>non_eq_suffix
.
Types of comparison operations:
-
eq
-FIELD
is fully equal to the string specified inARG
. -
non_eq
-FIELD
is not equal to the string specified inARG
. -
eq_prefix
-FIELD
starts with the string specified inARG
. -
non_eq_prefix
-FIELD
doesn't starts with the string specified inARG
. -
eq_suffix
-FIELD
ends with the string specified inARG
. -
non_eq_suffix
-FIELD
doesn't ends with the string specified inARG
.
Wildcard inside of ARG
has no any special meaning and is a regular symbol. Backslach can be used in ARG
- during configuration processing it is just dropped, leaving escaped symbol in ARG
(e.g. \\
means regular simple backslash symbol \
). If wildcard (at the beginning or end of ARG
) is escaped, then it will not have any special prefix/suffix
meaning and will be used as a regular symbol. Also HTTP tables cannot match double-wildcard patterns *ARG*
, so prefix pattern automatically applied in such cases.
ACTION
is a rule action with appropriate type; possible types are:
-
vhost
reference - rule with such action pass the request to specified virtual host (must be defined earlier in configuration file). -
chain
reference - rule redirects request to other HTTP chain (must be defined earlier and must not be the same as current). -
mark
- rule setnetfilter
marks into all skbs for all matched requests. -
block
- rule blocks all matched requests.
VAL
is possible value for specified action; only mark
action is allowed to
have value (unsigned integer type).
Note: all
http_chain
directives must be defined after definition of all virtual hosts; configuration ordersrv_groups/servers -> vhosts -> http_chains
is mandatory.
Rule entry is a single instruction for HTTP table that says: take the FIELD
of http request, compare it with ARG
. If they match, then apply rule ACTION
(with possible VAL
) to that request.
For every HTTP request, HTTP table executes all rule instructions in all
linked HTTP chains (beginning from the main chain) sequentially until it finds
a match. If no match is found, then the request is dropped.
Note: rules with
mark
conditions (in whichFIELD
==mark
) are processed before any other rules in each configured HTTP chain. So, even if user placed such rules in the end of HTTP chain - they nevertheless will be processed at the beginning of that chain.
Default match rule can be specified. Its syntax looks like this:
-> ACTION;
This rule works as last resort option, and if specified it applies designated action to requests that didn't match any more specific rule. As all match rules are processed in sequential order, this rule must come last to serve the intended role. One main HTTP chain (without name) must be specified after all other chains in configuration file. If no main chain is specified, it is created implicitly. In this case one default match rule pointing to default virtual host will be created in implicit main chain if default virtual host is present in configuration and if such default rule (with default virtual host) have not been specified explicitly in any chain in configuration. User can explicitly create main HTTP chain with empty list of rules, which means the complete absence of rules - all incoming requests will be dropped in such configuration.
Below are examples of HTTP table configuration:
srv_group static { ... }
srv_group nts_app { ... }
srv_group foo_app { ... }
srv_group bar_app { ... }
srv_group default { ... }
vhost base {
proxy_pass static;
...
}
vhost app {
proxy_pass default;
location prefix "?" {
proxy_pass foo_app;
...
}
location prefix "/static/" {
proxy_pass static;
...
}
...
}
vhost heavy {
proxy_pass bar_app backup=foo_app;
...
}
vhost nts {
proxy_pass nts_app backup=bar_app;
...
}
http_chain {
-> mark = 7;
-> heavy;
}
http_chain stat {
-> mark = 6;
-> base;
}
http_chain natsys {
host == "static.*" -> stat;
host == "*.example.com" -> example;
-> mark = 5;
-> nts;
}
http_chain {
mark == 1 -> app;
mark == 2 -> block;
hdr_conn == "keep-alive" -> heavy;
hdr_host == "bar.*" -> heavy;
hdr_host == "*natsys-lab.com" -> natsys;
hdr_host == "bar.natsys-lab.com" -> mark = 3;
hdr_raw == "X-Custom-Bar-Hdr: *" -> mark = 4;
uri == "*.php" -> app;
host == "static.*" -> app;
host == "*tempesta-tech.com" -> base;
host == "foo.example.com" -> base;
-> app;
}
Reaction to server unavailability. HTTP tables doesn't work with servers, so the reaction depends only on load balancing schedulers attached to the groups.