Skip to content

Commit

Permalink
Merge ASF 9.2.x into our Edge 9.1.10 branch apache#869
Browse files Browse the repository at this point in the history
Conflicts:
      doc/admin-guide/files/sni.yaml.en.rst
      iocore/net/SSLSNIConfig.cc
      plugins/experimental/block_errors/block_errors.cc
      plugins/lua/example/test_vconn.lua
      plugins/lua/ts_lua.c
      plugins/lua/ts_lua_hook.c
      plugins/lua/ts_lua_http.c
      plugins/lua/ts_lua_util.c
      plugins/lua/ts_lua_util.h
      plugins/lua/ts_lua_vconn.c
      proxy/http2/HTTP2.cc
      proxy/http2/Http2ConnectionState.cc
      proxy/http2/Http2ConnectionState.h
  • Loading branch information
bneradt authored and GitHub Enterprise committed Oct 11, 2023
2 parents 9005465 + 6374731 commit 674fd2a
Show file tree
Hide file tree
Showing 24 changed files with 715 additions and 188 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG-9.2.3
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,17 @@ Changes with Apache Traffic Server 9.2.3
#10257 - Python 3.12: Make autest regex strings raw strings
#10266 - Python 3.12: add charset-nomalizer to tests/Pipfile
#10285 - Fix slice head request memory issue
#10286 - Abort a read when the disk is known to be bad
#10287 - Fix a crash due to bad disks
#10304 - Preserve unmapped url regardless of need for remapping
#10324 - Add TSVConnFdGet api
#10386 - Don't set port number as part of hostname
#10389 - 9.2.x: Proxy Verfier Upgrade to v2.10.1
#10391 - tls_verify4: Use traffic_manager for config reload
#10399 - Fix use-after-free issue
#10480 - Fix the SNI and HOST parsing properly
#10564 - Add an HTTP/2 related rate limiting
#10566 - s3_auth: Fix hash calculation
#10568 - Reallocate a buffer for H2 header block only if needed
#10571 - APIs to get the h2 error codes and a plugin to use them
#10573 - Add support for vconn start handler in lua plugin
7 changes: 7 additions & 0 deletions doc/admin-guide/files/records.config.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4326,6 +4326,13 @@ HTTP/2 Configuration
This limit only will be enforced if :ts:cv:`proxy.config.http2.stream_priority_enabled`
is set to 1.

.. ts:cv:: CONFIG proxy.config.http2.max_rst_stream_frames_per_minute INT 14
:reloadable:

Specifies how many RST_STREAM frames |TS| receives for a minute at maximum.
Clients exceeded this limit will be immediately disconnected with an error
code of ENHANCE_YOUR_CALM.

.. ts:cv:: CONFIG proxy.config.http2.min_avg_window_update FLOAT 2560.0
:reloadable:

Expand Down
268 changes: 142 additions & 126 deletions doc/admin-guide/files/sni.yaml.en.rst

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,13 @@ HTTP/2
maximum allowed number of priority frames per minute limit which is configured by
:ts:cv:`proxy.config.http2.max_priority_frames_per_minute`.

.. ts:stat:: global proxy.process.http2.max_rst_stream_frames_per_minute_exceeded integer
:type: counter

Represents the total number of closed HTTP/2 connections for exceeding the
maximum allowed number of rst_stream frames per minute limit which is configured by
:ts:cv:`proxy.config.http2.max_rst_stream_frames_per_minute`.

.. ts:stat:: global proxy.process.http2.insufficient_avg_window_update integer
:type: counter

Expand Down
73 changes: 73 additions & 0 deletions doc/admin-guide/plugins/block_errors.en.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. include:: ../../common.defs
.. _admin-plugins-block_errors:

Block Errors Plugin
*******************

Description
===========
The `block_errors` plugin blocks connections or downgrades the protocol from HTTP/2 to HTTP/1.1 for clients that have too many HTTP/2 errors on the server.

The plugin tracks users based on their IP address and blocks them for a configurable amount of time. `block_errors` can be configured to either block or downgrade the protocol, only use HTTP/1.1, for any new connections.
The existing connection that experience errors and is over the error limit will be closed. The plugin also supports on the fly configuration changes using the `traffic_ctl` command.


Configuration
=============

To enable the `block_errors` plugin, insert the following line in :file:`plugin.config`:

block_errors.so

Additional configuration options are available and can be set in :file:`plugin.config`:

block_errors.so <error limit> <timeout> <shutdown> <enable>

- ``error limit``: The number of errors allowed before blocking the client. Default: 1000 (per minute)
- ``timeout``: The time in minutes to block the client. Default: 4 (minutes)
- ``shutdown``: Shutdown (1) or downgrade (0) the protocol for new connections. Default: 0 (downgrade to HTTP/1.1)
- ``enable``: Enable (1) or disable (0) the plugin. Default: 1 (enabled)

Example Configuration
=====================

block_errors.so 1000 4 0 1

Run Time Configuration
======================
The plugin can be configured at run time using the `traffic_ctl` command. The following commands are available:

- ``block_errors.error_limit``: Set the error limit. Takes a single argument, the number of errors allowed before blocking the client.
- ``block_errors.timeout``: Set the block timeout. Takes a single argument, the number of minutes to block the client.
- ``block_errors.shutdown``: Set the shutdown mode. Takes a single argument, 0 to downgrade to HTTP/1.1, 1 to close the connection.
- ``block_errors.enable``: Enable or disable the plugin. Takes a single argument, 0 to disable, 1 to enable.

Example Run Time Configuration
==============================

traffic_ctl plugin msg block_errors.error_limit 10000

traffic_ctl plugin msg block_errors.timeout 10

traffic_ctl plugin msg block_errors.shutdown 1

traffic_ctl plugin msg block_errors.enable 1
4 changes: 4 additions & 0 deletions doc/admin-guide/plugins/index.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi
:hidden:

Access Control <access_control.en>
Block Errors <block_errors.en>
Cache Fill <cache_fill.en>
Certifier <certifier.en>
Cert Reporting Tool <cert_reporting_tool.en>
Expand Down Expand Up @@ -187,6 +188,9 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi
:doc:`Access Control <access_control.en>`
Access control plugin that handles various access control use-cases.

:doc:`Block Errors <block_errors.en>`
Blocks or downgrades new connections when the server receives too many errors from an IP address.

:doc:`Certifier <certifier.en>`
Manages and/or generates certificates for incoming HTTPS requests.

Expand Down
94 changes: 94 additions & 0 deletions doc/admin-guide/plugins/lua.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ script, and we can write this in remap.config:
This module can also act as a global plugin of Traffic Server. In this case we should provide one of these functions in
each lua script:

- **'do_global_vconn_start'**
- **'do_global_txn_start'**
- **'do_global_txn_close'**
- **'do_global_os_dns'**
Expand Down Expand Up @@ -620,6 +621,7 @@ Hook point constants

::

TS_LUA_HOOK_VCONN_START
TS_LUA_HOOK_OS_DNS
TS_LUA_HOOK_PRE_REMAP
TS_LUA_HOOK_READ_CACHE_HDR
Expand All @@ -645,6 +647,8 @@ Additional Information:
| | | do_remap() via | do_os_response() | global context via |
| | | ts.hook()? | via ts.hook()? | ts.hook()? |
+=======================+===========================+======================+====================+======================+
| TS_VCONN_START_HOOK | TS_LUA_HOOK_VCONN_START | NO | NO | YES |
+-----------------------+---------------------------+----------------------+--------------------+----------------------+
| TS_HTTP_TXN | TS_LUA_HOOK | NO | NO | YES |
| _START_HOOK | _TXN_START | | | |
+-----------------------+---------------------------+----------------------+--------------------+----------------------+
Expand Down Expand Up @@ -3384,6 +3388,66 @@ Here is an example

:ref:`TOP <admin-plugins-ts-lua>`

ts.http.get_ssn_remote_addr
---------------------------
**syntax:** *ts.http.get_ssn_remote_addr()*

**context:** after do_global_read_reqest

**description:** This function can be used to get the remote address (IP, port, family) of the session.

`TOP <#ts-lua-plugin>`_

ts.http.get_client_received_error
---------------------------------
**syntax:** *ts.http.get_client_received_error()*

**context:** after do_global_txn_close

**description:** This function can be used to get the client received error from transaction.

Here is an example

::

function do_global_txn_close()
local class, code = ts.http.get_client_received_error()
ts.debug('txn_close: '..class)
ts.debug('txn_close: '..code)
end

`TOP <#ts-lua-plugin>`_

ts.http.get_client_sent_error
-----------------------------
**syntax:** *ts.http.get_client_sent_error()*

**context:** after do_global_txn_close

**description:** This function can be used to get the client sent error from transaction.

`TOP <#ts-lua-plugin>`_

ts.http.get_server_received_error
---------------------------------
**syntax:** *ts.http.get_server_received_error()*

**context:** after do_global_txn_close

**description:** This function can be used to get the server received error from transaction.

`TOP <#ts-lua-plugin>`_

ts.http.get_server_sent_error
-----------------------------
**syntax:** *ts.http.get_server_sent_error()*

**context:** after do_global_txn_close

**description:** This function can be used to get the server sent error from transaction.

`TOP <#ts-lua-plugin>`_

ts.add_package_path
-------------------
**syntax:** *ts.add_package_path(lua-style-path-str)*
Expand Down Expand Up @@ -4566,6 +4630,36 @@ be returned with 4 functions to increment, decrement, get and set the value. Tha

:ref:`TOP <admin-plugins-ts-lua>`

ts.vconn.get_fd
---------------
**syntax:** *ts.vconn.get_fd()*

**context:** do_global_vconn_start

**description:** This function can be used to get the file descriptor of the virtual connection.

`TOP <#ts-lua-plugin>`_

ts.vconn.disable_h2
-------------------
**syntax:** *ts.vconn.disable_h2()*

**context:** do_global_vconn_start

**description:** This function can be used to disable http/2 for the virtual connection.

`TOP <#ts-lua-plugin>`_

ts.vconn.get_remote_addr
------------------------
**syntax:** *ts.vconn.get_remote_addr()*

**context:** do_global_vconn_start

**description:** This function can be used to get the remote address (IP, port, family) of the virtual connection.

`TOP <#ts-lua-plugin>`_

Todo
====
* ts.cache_xxx
Expand Down
26 changes: 26 additions & 0 deletions include/tscore/ink_inet.h
Original file line number Diff line number Diff line change
Expand Up @@ -1268,6 +1268,7 @@ struct IpAddr {
- Else: 0.
*/
uint32_t hash() const;
uint64_t hash64() const;

/** The hashing function embedded in a functor.
@see hash
Expand Down Expand Up @@ -1476,6 +1477,18 @@ IpAddr::hash() const
return zret;
}

inline uint64_t
IpAddr::hash64() const
{
uint64_t zret = 0;
if (this->isIp4()) {
zret = ntohl(_addr._ip4);
} else if (this->isIp6()) {
zret = _addr._u64[0] ^ _addr._u64[1];
}
return zret;
}

/// Write IP @a addr to storage @a dst.
/// @return @s dst.
sockaddr *ats_ip_set(sockaddr *dst, ///< Destination storage.
Expand Down Expand Up @@ -1611,3 +1624,16 @@ namespace bwf
detail::MemDump Hex_Dump(IpEndpoint const &addr);
} // namespace bwf
} // namespace ts

namespace std
{
/// Standard hash support for @a IPAddr.
template <> struct hash<IpAddr> {
size_t
operator()(IpAddr const &addr) const
{
return addr.hash64();
}
};

} // namespace std
68 changes: 68 additions & 0 deletions iocore/net/P_SNIActionPerformer.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,74 @@ class HTTP2BufferWaterMark : public ActionItem
int value = -1;
};

class HTTP2MaxSettingsFramesPerMinute : public ActionItem
{
public:
HTTP2MaxSettingsFramesPerMinute(int value) : value(value) {}
~HTTP2MaxSettingsFramesPerMinute() override {}

int
SNIAction(TLSSNISupport *snis, const Context &ctx) const override
{
snis->hints_from_sni.http2_max_settings_frames_per_minute = value;
return SSL_TLSEXT_ERR_OK;
}

private:
int value = -1;
};

class HTTP2MaxPingFramesPerMinute : public ActionItem
{
public:
HTTP2MaxPingFramesPerMinute(int value) : value(value) {}
~HTTP2MaxPingFramesPerMinute() override {}

int
SNIAction(TLSSNISupport *snis, const Context &ctx) const override
{
snis->hints_from_sni.http2_max_ping_frames_per_minute = value;
return SSL_TLSEXT_ERR_OK;
}

private:
int value = -1;
};

class HTTP2MaxPriorityFramesPerMinute : public ActionItem
{
public:
HTTP2MaxPriorityFramesPerMinute(int value) : value(value) {}
~HTTP2MaxPriorityFramesPerMinute() override {}

int
SNIAction(TLSSNISupport *snis, const Context &ctx) const override
{
snis->hints_from_sni.http2_max_priority_frames_per_minute = value;
return SSL_TLSEXT_ERR_OK;
}

private:
int value = -1;
};

class HTTP2MaxRstStreamFramesPerMinute : public ActionItem
{
public:
HTTP2MaxRstStreamFramesPerMinute(int value) : value(value) {}
~HTTP2MaxRstStreamFramesPerMinute() override {}

int
SNIAction(TLSSNISupport *snis, const Context &ctx) const override
{
snis->hints_from_sni.http2_max_rst_stream_frames_per_minute = value;
return SSL_TLSEXT_ERR_OK;
}

private:
int value = -1;
};

class TunnelDestination : public ActionItem
{
// ID of the configured variable. This will be used to know which function
Expand Down
4 changes: 4 additions & 0 deletions iocore/net/TLSSNISupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ class TLSSNISupport

struct HintsFromSNI {
std::optional<uint32_t> http2_buffer_water_mark;
std::optional<uint32_t> http2_max_settings_frames_per_minute;
std::optional<uint32_t> http2_max_ping_frames_per_minute;
std::optional<uint32_t> http2_max_priority_frames_per_minute;
std::optional<uint32_t> http2_max_rst_stream_frames_per_minute;
} hints_from_sni;

protected:
Expand Down

0 comments on commit 674fd2a

Please sign in to comment.