You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2018/07/05 17:18:47 UTC
[trafficserver] 02/03: SNI based IP_ALLOW
This is an automated email from the ASF dual-hosted git repository.
bcall pushed a commit to branch 8.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit a9c9081684a7ea982e35975057b469d893396dde
Author: Persia Aziz <pe...@yahoo-inc.com>
AuthorDate: Thu Apr 5 17:43:42 2018 -0500
SNI based IP_ALLOW
(cherry picked from commit b61b82cdfb1ad1cd9c8e03bc3363396aea034123)
---
configs/ssl_server_name.yaml.default | 4 ++-
iocore/net/P_SNIActionPerformer.h | 61 +++++++++++++++++++++++++++++++++---
iocore/net/SNIActionPerformer.cc | 8 +++--
iocore/net/SSLSNIConfig.cc | 2 ++
iocore/net/SSLUtils.cc | 6 +++-
iocore/net/YamlSNIConfig.cc | 10 ++++--
iocore/net/YamlSNIConfig.h | 2 ++
7 files changed, 83 insertions(+), 10 deletions(-)
diff --git a/configs/ssl_server_name.yaml.default b/configs/ssl_server_name.yaml.default
index ed2c956..60bb6ea 100644
--- a/configs/ssl_server_name.yaml.default
+++ b/configs/ssl_server_name.yaml.default
@@ -13,6 +13,8 @@
# client_cert - sets the client certificate to present to the server specified in dest_host; parameters = certificate file .
# The location of the certificate file is relative to proxy.config.ssl.server.cert.path directory.
# tunnel_route - sets the e2e tunnel route
+# ip_allow - lists or range of client IP addresses, subnets that are allowed for this connection. This accepts CIDR format
+# for subnet specification.
#
# Example:
#
@@ -23,4 +25,4 @@
# verify_client: MODERATE
# - fqdn: two.com
# tunnel_route: two.com
-#
+# ip_allow = '10.0.0.1-10.0.0.255'
diff --git a/iocore/net/P_SNIActionPerformer.h b/iocore/net/P_SNIActionPerformer.h
index f876a70..c40091e 100644
--- a/iocore/net/P_SNIActionPerformer.h
+++ b/iocore/net/P_SNIActionPerformer.h
@@ -35,6 +35,7 @@
//#include"P_UnixNetProcessor.h"
#include <vector>
#include "P_SSLNextProtocolAccept.h"
+#include "ts/ink_inet.h"
extern Map<int, SSLNextProtocolSet *> snpsMap;
// enum of all the actions
@@ -50,7 +51,7 @@ enum PropertyActions { TS_VERIFY_SERVER = 200, TS_CLIENT_CERT };
class ActionItem
{
public:
- virtual void SNIAction(Continuation *cont) = 0;
+ virtual int SNIAction(Continuation *cont) = 0;
virtual ~ActionItem(){};
};
@@ -60,7 +61,7 @@ public:
DisableH2() {}
~DisableH2() override {}
- void
+ int
SNIAction(Continuation *cont) override
{
auto ssl_vc = reinterpret_cast<SSLNetVConnection *>(cont);
@@ -69,6 +70,7 @@ public:
auto nps = snpsMap.get(accept_obj->id);
ssl_vc->registerNextProtocolSet(reinterpret_cast<SSLNextProtocolSet *>(nps));
}
+ return SSL_TLSEXT_ERR_OK;
}
};
@@ -80,12 +82,63 @@ public:
VerifyClient(const char *param) : mode(atoi(param)) {}
VerifyClient(uint8_t param) : mode(param) {}
~VerifyClient() override {}
- void
+ int
SNIAction(Continuation *cont) override
{
auto ssl_vc = reinterpret_cast<SSLNetVConnection *>(cont);
Debug("ssl_sni", "action verify param %d", this->mode);
setClientCertLevel(ssl_vc->ssl, this->mode);
+ return SSL_TLSEXT_ERR_OK;
+ }
+};
+
+class SNI_IpAllow : public ActionItem
+{
+ IpMap ip_map;
+
+public:
+ SNI_IpAllow(std::string const &ip_allow_list, cchar *servername)
+ {
+ // the server identified by item.fqdn requires ATS to do IP filtering
+ if (ip_allow_list.length()) {
+ IpAddr addr1;
+ IpAddr addr2;
+ // check format first
+ // check if the input is a comma separated list of IPs
+ ts::TextView content(ip_allow_list);
+ while (!content.empty()) {
+ ts::TextView list{content.take_prefix_at(',')};
+ if (0 != ats_ip_range_parse(list, addr1, addr2)) {
+ Debug("ssl_sni", "%.*s is not a valid format", static_cast<int>(list.size()), list.data());
+ break;
+ } else {
+ Debug("ssl_sni", "%.*s added to the ip_allow list %s", static_cast<int>(list.size()), list.data(), servername);
+ ip_map.fill(IpEndpoint().assign(addr1), IpEndpoint().assign(addr2), reinterpret_cast<void *>(1));
+ }
+ }
+ }
+ } // end function SNI_IpAllow
+
+ int
+ SNIAction(Continuation *cont) override
+ {
+ // i.e, ip filtering is not required
+ if (ip_map.getCount() == 0) {
+ return SSL_TLSEXT_ERR_OK;
+ }
+
+ auto ssl_vc = reinterpret_cast<SSLNetVConnection *>(cont);
+ auto ip = ssl_vc->get_remote_endpoint();
+
+ // 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));
+ Debug("ssl_sni", "%s is not allowed. Denying connection", buff);
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+ }
}
};
@@ -93,5 +146,5 @@ class SNIActionPerformer
{
public:
SNIActionPerformer() = default;
- static void PerformAction(Continuation *cont, cchar *servername);
+ static int PerformAction(Continuation *cont, cchar *servername);
};
diff --git a/iocore/net/SNIActionPerformer.cc b/iocore/net/SNIActionPerformer.cc
index 710a7b5..0561096 100644
--- a/iocore/net/SNIActionPerformer.cc
+++ b/iocore/net/SNIActionPerformer.cc
@@ -37,7 +37,7 @@
extern Map<int, SSLNextProtocolSet *> snpsMap;
-void
+int
SNIActionPerformer::PerformAction(Continuation *cont, cchar *servername)
{
SNIConfig::scoped_config params;
@@ -47,8 +47,12 @@ SNIActionPerformer::PerformAction(Continuation *cont, cchar *servername)
} else {
for (auto it : *actionvec) {
if (it) {
- it->SNIAction(cont);
+ auto ret = it->SNIAction(cont);
+ if (ret != SSL_TLSEXT_ERR_OK) {
+ return ret;
+ }
}
}
}
+ return SSL_TLSEXT_ERR_OK;
}
diff --git a/iocore/net/SSLSNIConfig.cc b/iocore/net/SSLSNIConfig.cc
index a735444..71ff860 100644
--- a/iocore/net/SSLSNIConfig.cc
+++ b/iocore/net/SSLSNIConfig.cc
@@ -82,6 +82,8 @@ SNIConfigParams::loadSNIConfig()
TunnelMap.emplace(item.fqdn.data(), item.tunnel_destination);
}
+ auto ai3 = new SNI_IpAllow(item.ip_allow, servername);
+ aiVec->push_back(ai3);
// set the next hop properties
SSLConfig::scoped_config params;
auto clientCTX = params->getCTX(servername);
diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc
index acc8d57..93d7fb3 100644
--- a/iocore/net/SSLUtils.cc
+++ b/iocore/net/SSLUtils.cc
@@ -448,12 +448,16 @@ extern SNIActionPerformer sni_action_performer;
static int
ssl_servername_only_callback(SSL *ssl, int * /* ad */, void * /*arg*/)
{
+ int ret = SSL_TLSEXT_ERR_OK;
SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Debug("ssl", "Requested servername is %s", servername);
if (servername != nullptr) {
- sni_action_performer.PerformAction(netvc, servername);
+ ret = sni_action_performer.PerformAction(netvc, servername);
}
+ if (ret != SSL_TLSEXT_ERR_OK)
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+
netvc->callHooks(TS_EVENT_SSL_SERVERNAME);
return SSL_TLSEXT_ERR_OK;
}
diff --git a/iocore/net/YamlSNIConfig.cc b/iocore/net/YamlSNIConfig.cc
index 5ab7ad2..5d20ccd 100644
--- a/iocore/net/YamlSNIConfig.cc
+++ b/iocore/net/YamlSNIConfig.cc
@@ -52,8 +52,8 @@ YamlSNIConfig::loader(const char *cfgFilename)
TsEnumDescriptor LEVEL_DESCRIPTOR = {{{"NONE", 0}, {"MODERATE", 1}, {"STRICT", 2}}};
-std::set<std::string> valid_sni_config_keys = {TS_fqdn, TS_disable_H2, TS_verify_client,
- TS_tunnel_route, TS_verify_origin_server, TS_client_cert};
+std::set<std::string> valid_sni_config_keys = {
+ TS_fqdn, TS_disable_H2, TS_verify_client, TS_tunnel_route, TS_verify_origin_server, TS_client_cert, TS_ip_allow};
namespace YAML
{
@@ -70,6 +70,8 @@ template <> struct convert<YamlSNIConfig::Item> {
if (node[TS_fqdn]) {
item.fqdn = node[TS_fqdn].as<std::string>();
+ } else {
+ return false; // servername must be present
}
if (node[TS_disable_H2]) {
item.fqdn = node[TS_disable_H2].as<bool>();
@@ -101,6 +103,10 @@ template <> struct convert<YamlSNIConfig::Item> {
if (node[TS_client_cert]) {
item.client_cert = node[TS_client_cert].as<std::string>();
}
+
+ if (node[TS_ip_allow]) {
+ item.ip_allow = node[TS_ip_allow].as<std::string>();
+ }
return true;
}
};
diff --git a/iocore/net/YamlSNIConfig.h b/iocore/net/YamlSNIConfig.h
index e3fcd11..cb57d5b 100644
--- a/iocore/net/YamlSNIConfig.h
+++ b/iocore/net/YamlSNIConfig.h
@@ -32,6 +32,7 @@ constexpr char TS_verify_client[] = "verify_client";
constexpr char TS_tunnel_route[] = "tunnel_route";
constexpr char TS_verify_origin_server[] = "verify_origin_server";
constexpr char TS_client_cert[] = "client_cert";
+constexpr char TS_ip_allow[] = "ip_allow";
const int start = 0;
struct YamlSNIConfig {
@@ -54,6 +55,7 @@ struct YamlSNIConfig {
std::string tunnel_destination;
uint8_t verify_origin_server = 0;
std::string client_cert;
+ std::string ip_allow;
};
ts::Errata loader(const char *cfgFilename);