Method: RhaproxyKeywords#tcp_request_content

Defined in:
lib/rhaproxy/keywords.rb

#tcp_request_content(params = nil) ⇒ Object

tcp-request content <action> [(if | unless) <condition>]

Perform an action on a new session depending on a layer 4-7 condition
May be used in sections :   defaults | frontend | listen | backend
                               no    |    yes   |   yes  |   yes
Arguments :
  <action>    defines the action to perform if the condition applies. Valid
              actions include : "accept", "reject", "track-sc1", "track-sc2".
              See "tcp-request connection" above for their signification.

  <condition> is a standard layer 4-7 ACL-based condition (see section 7).

A request's contents can be analysed at an early stage of request processing
called "TCP content inspection". During this stage, ACL-based rules are
evaluated every time the request contents are updated, until either an
"accept" or a "reject" rule matches, or the TCP request inspection delay
expires with no matching rule.

The first difference between these rules and "tcp-request connection" rules
is that "tcp-request content" rules can make use of contents to take a
decision. Most often, these decisions will consider a protocol recognition or
validity. The second difference is that content-based rules can be used in
both frontends and backends. In frontends, they will be evaluated upon new
connections. In backends, they will be evaluated once a session is assigned
a backend. This means that a single frontend connection may be evaluated
several times by one or multiple backends when a session gets reassigned
(for instance after a client-side HTTP keep-alive request).

Content-based rules are evaluated in their exact declaration order. If no
rule matches or if there is no rule, the default action is to accept the
contents. There is no specific limit to the number of rules which may be
inserted.

Three types of actions are supported :
  - accept :
  - reject :
  - { track-sc1 | track-sc2 } <key> [table <table>]

They have the same meaning as their counter-parts in "tcp-request connection"
so please refer to that section for a complete description.

Also, it is worth noting that if sticky counters are tracked from a rule
defined in a backend, this tracking will automatically end when the session
releases the backend. That allows per-backend counter tracking even in case
of HTTP keep-alive requests when the backend changes. While there is nothing
mandatory about it, it is recommended to use the track-sc1 pointer to track
per-frontend counters and track-sc2 to track per-backend counters.

Note that the "if/unless" condition is optional. If no condition is set on
the action, it is simply performed unconditionally. That can be useful for
"track-sc*" actions as well as for changing the default action to a reject.

It is perfectly possible to match layer 7 contents with "tcp-request content"
rules, but then it is important to ensure that a full request has been
buffered, otherwise no contents will match. In order to achieve this, the
best solution involves detecting the HTTP protocol during the inspection
period.

Example:
      # Accept HTTP requests containing a Host header saying "example.com"
      # and reject everything else.
      acl is_host_com hdr(Host) -i example.com
      tcp-request inspect-delay 30s
      tcp-request content accept if HTTP is_host_com
      tcp-request content reject

Example:
      # reject SMTP connection if client speaks first
      tcp-request inspect-delay 30s
      acl content_present req_len gt 0
      tcp-request content reject if content_present

      # Forward HTTPS connection only if client speaks
      tcp-request inspect-delay 30s
      acl content_present req_len gt 0
      tcp-request content accept if content_present
      tcp-request content reject

Example: track per-frontend and per-backend counters, block abusers at the
         frontend when the backend detects abuse.

      frontend http
          # Use General Purpose Couter 0 in SC1 as a global abuse counter
          # protecting all our sites
          stick-table type ip size 1m expire 5m store gpc0
          tcp-request connection track-sc1 src
          tcp-request connection reject if { sc1_get_gpc0 gt 0 }
          ...
          use_backend http_dynamic if { path_end .php }

      backend http_dynamic
          # if a source makes too fast requests to this dynamic site (tracked
          # by SC2), block it globally in the frontend.
          stick-table type ip size 1m expire 5m store http_req_rate(10s)
          acl click_too_fast sc2_http_req_rate gt 10
          acl mark_as_abuser sc1_inc_gpc0
          tcp-request content track-sc2 src
          tcp-request content reject if click_too_fast mark_as_abuser

See section 7 about ACL usage.

See also : "tcp-request connection", "tcp-request inspect-delay"


1471
1472
1473
1474
1475
1476
1477
1478
# File 'lib/rhaproxy/keywords.rb', line 1471

def tcp_request_content(params = nil)
  if @name_index
    @conf.insert(@name_index + @conf.length, "    " + "tcp-request content " + params.to_s + "\n")
  else
    puts "no #{@proxy_type} name assigned"
    return false
  end
end