This is an automated email from the ASF dual-hosted git repository.
eze pushed a commit to branch 9.2.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/9.2.x by this push:
new ce942e0aca Add a setting to choose the data source of IP address for
ACL (#12294)
ce942e0aca is described below
commit ce942e0acacd5cc9f38bd07565a1dfc5ffed0e33
Author: Masakazu Kitajo <[email protected]>
AuthorDate: Mon Jun 16 15:30:56 2025 -0600
Add a setting to choose the data source of IP address for ACL (#12294)
* Add a setting to choose the data source of IP address for ACL
---
.../configuration/proxy-protocol.en.rst | 4 +
doc/admin-guide/files/records.config.en.rst | 14 ++
iocore/net/P_SNIActionPerformer.h | 17 ++-
iocore/net/libinknet_stub.cc | 2 +
mgmt/RecordsConfig.cc | 8 ++
proxy/IPAllow.cc | 33 ++++-
proxy/IPAllow.h | 4 +
proxy/http/HttpSessionAccept.cc | 10 ++
proxy/http/remap/UrlRewrite.cc | 28 +++-
proxy/http2/Http2SessionAccept.cc | 16 ++-
.../gold_tests/autest-site/trafficserver.test.ext | 14 +-
tests/gold_tests/remap/remap_acl.test.py | 39 +++++-
.../remap_acl_get_post_allowed_pp.replay.yaml | 152 +++++++++++++++++++++
13 files changed, 322 insertions(+), 19 deletions(-)
diff --git a/doc/admin-guide/configuration/proxy-protocol.en.rst
b/doc/admin-guide/configuration/proxy-protocol.en.rst
index a83fe5b137..bb25a6f47d 100644
--- a/doc/admin-guide/configuration/proxy-protocol.en.rst
+++ b/doc/admin-guide/configuration/proxy-protocol.en.rst
@@ -47,6 +47,10 @@ configured with
:ts:cv:`proxy.config.http.proxy_protocol_allowlist`.
If the allowlist is configured, requests will only be accepted from
these
IP addresses and must be prefaced with the PROXY v1/v2 header.
+By default, |TS| uses client's IP address that is from the peer when it
applies ACL. If you configure a port to
+enable PROXY protocol and want to apply ACL against the IP address delivered
by PROXY protocol, you need to have ``PROXY`` in
+:ts:cv:`proxy.config.acl.subjects`.
+
1. HTTP Forwarded Header
The client IP address in the PROXY protocol header is passed to the origin
server via an HTTP `Forwarded:
diff --git a/doc/admin-guide/files/records.config.en.rst
b/doc/admin-guide/files/records.config.en.rst
index 7db9e6a9f6..44e857da91 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -2102,6 +2102,20 @@ Security
policies is set in the corresponding :file:`sni.yaml` file entry and the
:file:`sni.yaml` entry does not override
this value via a :ref:`host_sni_policy<override-host-sni-policy>` attribute.
+.. ts:cv:: CONFIG proxy.config.acl.subjects STRING PEER
+
+ Specifies the list of data sources for getting client's IP address for ACL.
+ The value is a comma separated string, and the first available data source
+ will be used. If you configure a port to enable PROXY protocol, you probably
+ need to adjust this setting to have ``PROXY`` in the list.
+
+ =============
======================================================================
+ Value Description
+ =============
======================================================================
+ ``PEER`` Use the IP address of the peer
+ ``PROXY`` Use the IP address from PROXY protocol
+ =============
======================================================================
+
Cache Control
=============
diff --git a/iocore/net/P_SNIActionPerformer.h
b/iocore/net/P_SNIActionPerformer.h
index eebe44b75a..aaa7627aad 100644
--- a/iocore/net/P_SNIActionPerformer.h
+++ b/iocore/net/P_SNIActionPerformer.h
@@ -35,6 +35,7 @@
#include "SSLTypes.h"
#include "tscore/ink_inet.h"
+#include "../../proxy/IPAllow.h"
#include <vector>
@@ -442,15 +443,25 @@ public:
return SSL_TLSEXT_ERR_OK;
}
- auto ssl_vc = dynamic_cast<SSLNetVConnection *>(snis);
- auto ip = ssl_vc->get_remote_endpoint();
+ auto ssl_vc = dynamic_cast<SSLNetVConnection *>(snis);
+ const sockaddr *ip = nullptr;
+ for (int i = 0; i < IpAllow::Subject::MAX_SUBJECTS; ++i) {
+ if (IpAllow::Subject::PEER == IpAllow::subjects[i]) {
+ ip = ssl_vc->get_remote_addr();
+ break;
+ } else if (IpAllow::Subject::PROXY == IpAllow::subjects[i] &&
+ ssl_vc->get_proxy_protocol_version() !=
ProxyProtocolVersion::UNDEFINED) {
+ ip = ssl_vc->get_proxy_protocol_src_addr();
+ break;
+ }
+ }
// check the allowed ips
if (ip_map.contains(ip)) {
return SSL_TLSEXT_ERR_OK;
} else {
char buff[256];
- ats_ip_ntop(&ip.sa, buff, sizeof(buff));
+ ats_ip_ntop(ip, buff, sizeof(buff));
Debug("ssl_sni", "%s is not allowed. Denying connection", buff);
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
diff --git a/iocore/net/libinknet_stub.cc b/iocore/net/libinknet_stub.cc
index a48273372a..76d1629b81 100644
--- a/iocore/net/libinknet_stub.cc
+++ b/iocore/net/libinknet_stub.cc
@@ -192,3 +192,5 @@ PreWarmManager::reconfigure()
}
PreWarmManager prewarmManager;
+
+uint8_t IpAllow::subjects[Subject::MAX_SUBJECTS];
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index e645bb6c6f..c127d1eafa 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -147,6 +147,14 @@ static const RecordElement RecordsConfig[] =
{RECT_CONFIG, "proxy.config.srv_enabled", RECD_INT, "0", RECU_DYNAMIC,
RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
,
+
//##############################################################################
+ //#
+ //# ACL
+ //#
+
//##############################################################################
+ {RECT_CONFIG, "proxy.config.acl.subjects", RECD_STRING, "PEER",
RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+ ,
+
//##############################################################################
//#
//# Support for disabling check for Accept-* / Content-* header mismatch
diff --git a/proxy/IPAllow.cc b/proxy/IPAllow.cc
index 9f0976d4b1..0ed85d6ccc 100644
--- a/proxy/IPAllow.cc
+++ b/proxy/IPAllow.cc
@@ -25,6 +25,8 @@
*/
#include <sstream>
+#include <string_view>
+
#include "IPAllow.h"
#include "tscore/BufferWriter.h"
#include "tscore/ts_file.h"
@@ -114,6 +116,7 @@ const IpAllow::ACL IpAllow::DENY_ALL_ACL;
size_t IpAllow::configid = 0;
bool IpAllow::accept_check_p = true; // initializing global flag for fast deny
+uint8_t IpAllow::subjects[Subject::MAX_SUBJECTS];
static ConfigUpdateHandler<IpAllow> *ipAllowUpdate;
@@ -202,7 +205,35 @@ IpAllow::match(sockaddr const *ip, match_key_t key)
// End API functions
//
-IpAllow::IpAllow(const char *config_var) :
config_file(ats_scoped_str(RecConfigReadConfigPath(config_var)).get()) {}
+IpAllow::IpAllow(const char *config_var) :
config_file(ats_scoped_str(RecConfigReadConfigPath(config_var)).get())
+{
+ RecString subjects_char;
+ REC_ReadConfigStringAlloc(subjects_char, "proxy.config.acl.subjects");
+ std::string_view subjects_sv{subjects_char};
+ int i = 0;
+ std::string_view::size_type s, e;
+
+ for (s = 0, e = 0; s < subjects_sv.size() && e != subjects_sv.npos; s = e +
1) {
+ e = subjects_sv.find(",", s);
+ std::string_view subject_sv = subjects_sv.substr(s, e);
+ if (i >= MAX_SUBJECTS) {
+ Error("Too many ACL subjects were provided");
+ }
+ if (subject_sv == "PEER") {
+ subjects[i] = Subject::PEER;
+ ++i;
+ } else if (subject_sv == "PROXY") {
+ subjects[i] = Subject::PROXY;
+ ++i;
+ } else {
+ Debug("ip-allow", "Unknown subject %.*s was ignored",
static_cast<int>(subject_sv.length()), subject_sv.data());
+ }
+ }
+ if (i < Subject::MAX_SUBJECTS) {
+ subjects[i] = Subject::MAX_SUBJECTS;
+ }
+ ats_free(subjects_char);
+}
void
IpAllow::PrintMap(const IpMap *map) const
diff --git a/proxy/IPAllow.h b/proxy/IPAllow.h
index 9221e7525b..8b1b2e75d9 100644
--- a/proxy/IPAllow.h
+++ b/proxy/IPAllow.h
@@ -102,6 +102,8 @@ public:
static constexpr const char *MODULE_NAME = "IPAllow";
+ enum Subject { PEER, PROXY, MAX_SUBJECTS };
+
/** An access control record and support data.
* The primary point of this is to hold the backing configuration in memory
while the ACL
* is in use.
@@ -182,6 +184,8 @@ public:
const ts::file::path &get_config_file() const;
+ static uint8_t subjects[Subject::MAX_SUBJECTS];
+
private:
static size_t configid; ///< Configuration ID for update
management.
static const Record ALLOW_ALL_RECORD; ///< Static record that allows all
access.
diff --git a/proxy/http/HttpSessionAccept.cc b/proxy/http/HttpSessionAccept.cc
index 29416da112..2bc19a1fb5 100644
--- a/proxy/http/HttpSessionAccept.cc
+++ b/proxy/http/HttpSessionAccept.cc
@@ -33,6 +33,16 @@ HttpSessionAccept::accept(NetVConnection *netvc, MIOBuffer
*iobuf, IOBufferReade
IpAllow::ACL acl;
ip_port_text_buffer ipb;
+ for (int i = 0; i < IpAllow::Subject::MAX_SUBJECTS; ++i) {
+ if (IpAllow::Subject::PEER == IpAllow::subjects[i]) {
+ client_ip = netvc->get_remote_addr();
+ break;
+ } else if (IpAllow::Subject::PROXY == IpAllow::subjects[i] &&
+ netvc->get_proxy_protocol_version() !=
ProxyProtocolVersion::UNDEFINED) {
+ client_ip = netvc->get_proxy_protocol_src_addr();
+ break;
+ }
+ }
acl = IpAllow::match(client_ip, IpAllow::SRC_ADDR);
if (!acl.isValid()) { // if there's no ACL, it's a hard deny.
Warning("client '%s' prohibited by ip-allow policy",
ats_ip_ntop(client_ip, ipb, sizeof(ipb)));
diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc
index cddc865a65..78dd61d9c2 100644
--- a/proxy/http/remap/UrlRewrite.cc
+++ b/proxy/http/remap/UrlRewrite.cc
@@ -402,6 +402,26 @@ UrlRewrite::PerformACLFiltering(HttpTransact::State *s,
url_mapping *map)
bool client_enabled_flag = true;
ink_release_assert(ats_is_ip(&s->client_info.src_addr));
+ const IpEndpoint *src_addr = nullptr;
+ const IpEndpoint *local_addr = nullptr;
+ const ProxyProtocol &pp_info =
s->state_machine->get_ua_txn()->get_netvc()->get_proxy_protocol_info();
+ for (int i = 0; i < IpAllow::Subject::MAX_SUBJECTS; ++i) {
+ if (IpAllow::Subject::PEER == IpAllow::subjects[i]) {
+ src_addr = &s->client_info.src_addr;
+ local_addr = &s->client_info.dst_addr;
+ break;
+ } else if (IpAllow::Subject::PROXY == IpAllow::subjects[i] &&
pp_info.version != ProxyProtocolVersion::UNDEFINED) {
+ src_addr = &pp_info.src_addr;
+ local_addr = &pp_info.dst_addr;
+ break;
+ }
+ }
+
+ if (src_addr == nullptr) {
+ // Use addresses from peer if none of the configured sources are
avaialable
+ src_addr = &s->client_info.src_addr;
+ local_addr = &s->client_info.dst_addr;
+ }
for (acl_filter_rule *rp = map->filter; rp && client_enabled_flag; rp =
rp->next) {
bool match = true;
@@ -421,7 +441,7 @@ UrlRewrite::PerformACLFiltering(HttpTransact::State *s,
url_mapping *map)
if (match && rp->src_ip_valid) {
match = false;
for (int j = 0; j < rp->src_ip_cnt && !match; j++) {
- bool in_range =
rp->src_ip_array[j].contains(s->client_info.src_addr);
+ bool in_range = rp->src_ip_array[j].contains(*src_addr);
if (rp->src_ip_array[j].invert) {
if (!in_range) {
match = true;
@@ -438,16 +458,14 @@ UrlRewrite::PerformACLFiltering(HttpTransact::State *s,
url_mapping *map)
Debug("url_rewrite", "match was true and we have specified a in_ip
field");
match = false;
for (int j = 0; j < rp->in_ip_cnt && !match; j++) {
- IpEndpoint incoming_addr;
-
incoming_addr.assign(s->state_machine->ua_txn->get_netvc()->get_local_addr());
if (is_debug_tag_set("url_rewrite")) {
char buf1[128], buf2[128], buf3[128];
- ats_ip_ntop(incoming_addr, buf1, sizeof(buf1));
+ ats_ip_ntop(local_addr, buf1, sizeof(buf1));
rp->in_ip_array[j].start.toString(buf2, sizeof(buf2));
rp->in_ip_array[j].end.toString(buf3, sizeof(buf3));
Debug("url_rewrite", "Trying to match incoming address %s in range
%s - %s.", buf1, buf2, buf3);
}
- bool in_range = rp->in_ip_array[j].contains(incoming_addr);
+ bool in_range = rp->in_ip_array[j].contains(*local_addr);
if (rp->in_ip_array[j].invert) {
if (!in_range) {
match = true;
diff --git a/proxy/http2/Http2SessionAccept.cc
b/proxy/http2/Http2SessionAccept.cc
index f0226fdee8..6cf0ae775f 100644
--- a/proxy/http2/Http2SessionAccept.cc
+++ b/proxy/http2/Http2SessionAccept.cc
@@ -36,8 +36,20 @@ Http2SessionAccept::~Http2SessionAccept() = default;
bool
Http2SessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf,
IOBufferReader *reader)
{
- sockaddr const *client_ip = netvc->get_remote_addr();
- IpAllow::ACL session_acl = IpAllow::match(client_ip, IpAllow::SRC_ADDR);
+ sockaddr const *client_ip = nullptr;
+
+ for (int i = 0; i < IpAllow::Subject::MAX_SUBJECTS; ++i) {
+ if (IpAllow::Subject::PEER == IpAllow::subjects[i]) {
+ client_ip = netvc->get_remote_addr();
+ break;
+ } else if (IpAllow::Subject::PROXY == IpAllow::subjects[i] &&
+ netvc->get_proxy_protocol_version() !=
ProxyProtocolVersion::UNDEFINED) {
+ client_ip = netvc->get_proxy_protocol_src_addr();
+ break;
+ }
+ }
+
+ IpAllow::ACL session_acl = IpAllow::match(client_ip, IpAllow::SRC_ADDR);
if (!session_acl.isValid()) {
ip_port_text_buffer ipb;
Warning("HTTP/2 client '%s' prohibited by ip-allow policy",
ats_ip_ntop(client_ip, ipb, sizeof(ipb)));
diff --git a/tests/gold_tests/autest-site/trafficserver.test.ext
b/tests/gold_tests/autest-site/trafficserver.test.ext
index 80848aa2cf..6979523508 100755
--- a/tests/gold_tests/autest-site/trafficserver.test.ext
+++ b/tests/gold_tests/autest-site/trafficserver.test.ext
@@ -44,7 +44,7 @@ def MakeATSProcess(
enable_quic=False,
block_for_debug=False,
log_data=default_log_data,
- use_traffic_out=True):
+ use_traffic_out=True, enable_proxy_protocol=False):
#####################################
# common locations
@@ -328,6 +328,14 @@ def MakeATSProcess(
if enable_tls:
get_port(p, "ssl_port")
get_port(p, "ssl_portv6")
+
+ if enable_proxy_protocol:
+ get_port(p, "proxy_protocol_port")
+ get_port(p, "proxy_protocol_portv6")
+
+ if enable_tls:
+ get_port(p, "proxy_protocol_ssl_port")
+ get_port(p, "proxy_protocol_ssl_portv6")
else:
p.Variables.port = 8080
p.Variables.portv6 = 8080
@@ -381,6 +389,10 @@ def MakeATSProcess(
if enable_quic:
port_str += " {ssl_port}:quic {ssl_portv6}:quic:ipv6".format(
ssl_port=p.Variables.ssl_port,
ssl_portv6=p.Variables.ssl_portv6)
+ if enable_proxy_protocol:
+ port_str += f" {p.Variables.proxy_protocol_port}:pp
{p.Variables.proxy_protocol_portv6}:pp:ipv6"
+ if enable_tls:
+ port_str += f" {p.Variables.proxy_protocol_ssl_port}:pp:ssl
{p.Variables.proxy_protocol_ssl_portv6}:pp:ssl:ipv6"
#p.Env['PROXY_CONFIG_HTTP_SERVER_PORTS'] = port_str
p.Disk.records_config.update({
'proxy.config.http.server_ports': port_str,
diff --git a/tests/gold_tests/remap/remap_acl.test.py
b/tests/gold_tests/remap/remap_acl.test.py
index 288c8d7de2..08c913cba2 100644
--- a/tests/gold_tests/remap/remap_acl.test.py
+++ b/tests/gold_tests/remap/remap_acl.test.py
@@ -43,7 +43,7 @@ class Test_remap_acl:
def __init__(
self, name: str, replay_file: str, ip_allow_content: str,
deactivate_ip_allow: bool,
- acl_configuration: str, named_acls: List[Tuple[str, str]],
expected_responses: List[int]):
+ acl_configuration: str, named_acls: List[Tuple[str, str]],
expected_responses: List[int], proxy_protocol: bool):
"""Initialize the test.
:param name: The name of the test.
@@ -64,7 +64,7 @@ class Test_remap_acl:
tr = Test.AddTestRun(name)
self._configure_server(tr)
self._configure_traffic_server(tr)
- self._configure_client(tr)
+ self._configure_client(tr, proxy_protocol)
def _configure_server(self, tr: 'TestRun') -> None:
"""Configure the server.
@@ -83,16 +83,17 @@ class Test_remap_acl:
"""
name = f"ts-{Test_remap_acl._ts_counter}"
- ts = tr.MakeATSProcess(name, enable_cache=False, enable_tls=True)
+ ts = tr.MakeATSProcess(name, enable_cache=False, enable_tls=True,
enable_proxy_protocol=True)
Test_remap_acl._ts_counter += 1
self._ts = ts
ts.Disk.records_config.update(
{
'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'http|url|remap|ip_allow',
+ 'proxy.config.diags.debug.tags':
'http|url|remap|ip-allow|proxyprotocol',
'proxy.config.http.push_method_enabled': 1,
'proxy.config.http.connect_ports':
self._server.Variables.http_port,
+ 'proxy.config.acl.subjects': 'PROXY,PEER',
})
remap_config_lines = []
@@ -111,14 +112,15 @@ class Test_remap_acl:
ts.Disk.remap_config.AddLines(remap_config_lines)
ts.Disk.ip_allow_yaml.AddLines(self._ip_allow_content.split("\n"))
- def _configure_client(self, tr: 'TestRun') -> None:
+ def _configure_client(self, tr: 'TestRun', proxy_protocol: bool) -> None:
"""Run the test.
:param tr: The TestRun object to associate the client process with.
"""
name = f"client-{Test_remap_acl._client_counter}"
- p = tr.AddVerifierClientProcess(name, self._replay_file,
http_ports=[self._ts.Variables.port])
+ port = self._ts.Variables.port if proxy_protocol == False else
self._ts.Variables.proxy_protocol_port
+ p = tr.AddVerifierClientProcess(name, self._replay_file,
http_ports=[port])
Test_remap_acl._client_counter += 1
p.StartBefore(self._server)
p.StartBefore(self._ts)
@@ -159,6 +161,25 @@ def replay_proxy_response(filename, replay_file,
get_proxy_response, post_proxy_
with open(replay_file, "w") as f:
f.write(dump(data))
+IP_ALLOW_CONTENT = f'''
+ip_allow:
+ - apply: in
+ ip_addrs: 0/0
+ action: allow
+ methods:
+ - GET
+'''
+
+test_ip_allow_optional_methods_pp = Test_remap_acl(
+ "Verify non-allowed methods are blocked (PP).",
+ replay_file='remap_acl_get_post_allowed_pp.replay.yaml',
+ ip_allow_content=IP_ALLOW_CONTENT,
+ deactivate_ip_allow=True,
+ acl_configuration='@action=allow @src_ip=1.2.3.4 @method=GET @method=POST',
+ named_acls=[],
+ expected_responses=[200, 200, 403, 403, 403],
+ proxy_protocol=True)
+
"""
Test all acl combinations
# """
@@ -178,6 +199,7 @@ for idx, test in enumerate(all_acl_combination_tests):
acl_configuration=test["inline"],
named_acls=[("acl", test["named_acl"])] if test["named_acl"] != ""
else [],
expected_responses=[test["GET response"], test["POST response"]],
+ proxy_protocol=False,
)
"""
@@ -202,7 +224,9 @@ for idx, test in enumerate(all_deactivate_ip_allow_tests):
deactivate_ip_allow=test["deactivate_ip_allow"],
acl_configuration=test["inline"],
named_acls=[("acl", test["named_acl"])] if test["named_acl"] != ""
else [],
- expected_responses=[test["GET response"], test["POST response"]])
+ expected_responses=[test["GET response"], test["POST response"]],
+ proxy_protocol=False,
+ )
"""
Test combination of named filters
@@ -223,4 +247,5 @@ for idx, test in enumerate(named_filter_combination_tests):
acl_configuration="",
named_acls=[("acl_1", test["named_acl_1"]), ("acl_2",
test["named_acl_2"])],
expected_responses=[test["GET response"], test["POST response"]],
+ proxy_protocol=False,
)
diff --git a/tests/gold_tests/remap/remap_acl_get_post_allowed_pp.replay.yaml
b/tests/gold_tests/remap/remap_acl_get_post_allowed_pp.replay.yaml
new file mode 100644
index 0000000000..5d2eb68c67
--- /dev/null
+++ b/tests/gold_tests/remap/remap_acl_get_post_allowed_pp.replay.yaml
@@ -0,0 +1,152 @@
+# 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.
+
+# This expects a remap.config that allows GET and POST, but denies all other
+# methods.
+
+meta:
+ version: "1.0"
+
+ blocks:
+ - standard_response: &standard_response
+ server-response:
+ status: 200
+ reason: OK
+ headers:
+ fields:
+ - [ Content-Length, 20 ]
+
+sessions:
+- protocol:
+ - name: http
+ version: 1
+ - name: proxy-protocol
+ version: 2
+ src-addr: "1.2.3.4:1111"
+ dst-addr: "5.6.7.8:2222"
+ transactions:
+
+ - client-request:
+ method: "GET"
+ version: "1.1"
+ url: /test/ip_allow/test_get
+ headers:
+ fields:
+ - [ Content-Length, 0 ]
+ - [ uuid, get ]
+ - [ X-Request, get ]
+
+ <<: *standard_response
+
+ proxy-response:
+ status: 200
+
+ # POST also is in the allow list.
+ - client-request:
+ method: "POST"
+ version: "1.1"
+ url: /test/ip_allow/test_post
+ headers:
+ fields:
+ - [Content-Length, 10]
+ - [ uuid, post ]
+ - [ X-Request, post ]
+
+ <<: *standard_response
+
+ proxy-response:
+ status: 200
+
+ # PUT rejected
+ - client-request:
+ method: "PUT"
+ version: "1.1"
+ url: /test/ip_allow/test_put
+ headers:
+ fields:
+ - [ Host, example.com ]
+ - [ uuid, put ]
+ - [ X-Request, put ]
+ - [ Content-Length, 113 ]
+ content:
+ encoding: plain
+ data: "HTTP/1.1 200 OK\nServer: ATS/10.0.0\nAccept-Ranges:
bytes\nContent-Length: 6\nCache-Control: public,max-age=2\n\nCACHED"
+
+ # Not received.
+ <<: *standard_response
+
+ # Verify that ATS rejected the PUSH.
+ proxy-response:
+ status: 403
+
+- protocol:
+ - name: http
+ version: 1
+ - name: proxy-protocol
+ version: 2
+ src-addr: "1.2.3.4:1111"
+ dst-addr: "5.6.7.8:2222"
+ delay: 2s
+ transactions:
+
+ # DELETE rejected
+ - client-request:
+ method: "DELETE"
+ version: "1.1"
+ url: /test/ip_allow/test_delete
+ headers:
+ fields:
+ - [ Host, example.com ]
+ - [ uuid, delete ]
+ - [ X-Request, delete ]
+ - [ Content-Length, 0 ]
+
+ <<: *standard_response
+
+ # Verify that ATS rejects the DELETE.
+ proxy-response:
+ status: 403
+
+- protocol:
+ - name: http
+ version: 1
+ - name: proxy-protocol
+ version: 2
+ src-addr: "1.2.3.4:1111"
+ dst-addr: "5.6.7.8:2222"
+ delay: 4s
+ transactions:
+
+ # PUSH rejected
+ - client-request:
+ method: "PUSH"
+ version: "1.1"
+ url: /test/ip_allow/test_push
+ headers:
+ fields:
+ - [ Host, example.com ]
+ - [ uuid, push ]
+ - [ X-Request, push ]
+ - [ Content-Length, 113 ]
+ content:
+ encoding: plain
+ data: "HTTP/1.1 200 OK\nServer: ATS/10.0.0\nAccept-Ranges:
bytes\nContent-Length: 6\nCache-Control: public,max-age=2\n\nCACHED"
+
+ <<: *standard_response
+
+ # Verify that ATS rejected the PUSH.
+ proxy-response:
+ status: 403