trafficserver-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From shinr...@apache.org
Subject [trafficserver] branch master updated: Traffic Dump: Adding an SNI filtering option. (#6645)
Date Tue, 21 Apr 2020 13:44:51 GMT
This is an automated email from the ASF dual-hosted git repository.

shinrich pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new eed1f74  Traffic Dump: Adding an SNI filtering option. (#6645)
eed1f74 is described below

commit eed1f74d81b583941370eb00784ba819fd78421a
Author: Brian Neradt <brian.neradt@gmail.com>
AuthorDate: Tue Apr 21 08:44:41 2020 -0500

    Traffic Dump: Adding an SNI filtering option. (#6645)
    
    Co-authored-by: bneradt <bneradt@verizonmedia.com>
---
 doc/admin-guide/plugins/traffic_dump.en.rst        |   4 +
 plugins/experimental/traffic_dump/traffic_dump.cc  |  55 ++++++--
 .../pluginTest/traffic_dump/gold/200_sni_bob.gold  |  11 ++
 .../pluginTest/traffic_dump/gold/200_sni_dave.gold |  12 ++
 .../pluginTest/traffic_dump/ssl/server.key         |  28 ++++
 .../pluginTest/traffic_dump/ssl/server.pem         |  21 +++
 .../pluginTest/traffic_dump/ssl/signed-foo.key     |  28 ++++
 .../pluginTest/traffic_dump/ssl/signed-foo.pem     |  19 +++
 .../pluginTest/traffic_dump/ssl/signer.pem         |  17 +++
 .../traffic_dump/traffic_dump_sni_filter.test.py   | 144 +++++++++++++++++++++
 10 files changed, 326 insertions(+), 13 deletions(-)

diff --git a/doc/admin-guide/plugins/traffic_dump.en.rst b/doc/admin-guide/plugins/traffic_dump.en.rst
index eece215..76bedf3 100644
--- a/doc/admin-guide/plugins/traffic_dump.en.rst
+++ b/doc/admin-guide/plugins/traffic_dump.en.rst
@@ -50,6 +50,10 @@ Plugin Configuration
 
    (`optional`) - a comma seperatated list of HTTP case-insensitive field names whose values
are considered sensitive information. Traffic Dump will not dump the incoming field values
for any of these fields but will instead dump a generic value for them of the same length
as the original. If this option is not used, a default list of "Cookie,Set-Cookie" is used.
Providing this option overwrites that default list with whatever values the user provides.
Pass a quoted empty string as the a [...]
 
+   .. option:: --sni-filter <SNI_Name>
+
+   (`optional`) - an SNI with which to filter sessions. Only HTTPS sessions with the provided
SNI will be dumped. The sample option will apply a sampling rate to these filtered sessions.
Thus, with a sample value of 2, 1/2 of all sessions with the specified SNI will be dumped.
+
 ``traffic_ctl`` <command>
    * ``traffic_ctl plugin msg traffic_dump.sample N`` - changes the sampling ratio N as mentioned
above.
    * ``traffic_ctl plugin msg traffic_dump.reset`` - resets the disk usage counter.
diff --git a/plugins/experimental/traffic_dump/traffic_dump.cc b/plugins/experimental/traffic_dump/traffic_dump.cc
index cfe5b36..34ca15d 100644
--- a/plugins/experimental/traffic_dump/traffic_dump.cc
+++ b/plugins/experimental/traffic_dump/traffic_dump.cc
@@ -31,6 +31,7 @@
 #include <cerrno>
 #include <arpa/inet.h>
 #include <netinet/in.h>
+#include <openssl/ssl.h>
 
 #include <algorithm>
 #include <sstream>
@@ -49,6 +50,8 @@ namespace
 {
 const char *PLUGIN_NAME   = "traffic_dump";
 const std::string closing = "]}]}";
+uint64_t session_counter  = 0;
+
 std::string defaut_sensitive_field_value;
 
 // A case-insensitive comparitor used for comparing HTTP field names.
@@ -87,6 +90,7 @@ std::unordered_set<std::string, StringHashByLower, InsensitiveCompare>
default_s
 std::unordered_set<std::string, StringHashByLower, InsensitiveCompare> sensitive_fields;
 
 ts::file::path log_path{"dump"};               // default log directory
+std::string sni_filter;                        // The SNI requested for filtering against.
 int s_arg_idx = 0;                             // Session Arg Index to pass on session data
 std::atomic<int64_t> sample_pool_size(1000);   // Sampling ratio
 std::atomic<int64_t> max_disk_usage(10000000); //< Max disk space for logs (approximate)
@@ -597,9 +601,29 @@ global_ssn_handler(TSCont contp, TSEvent event, void *edata)
     return TS_SUCCESS;
   }
   case TS_EVENT_HTTP_SSN_START: {
-    // Grab session id to do sampling
+    // Grab session id for logging against a global value rather than the local
+    // session_counter.
     int64_t id = TSHttpSsnIdGet(ssnp);
-    if (id % sample_pool_size != 0) {
+
+    // If the user has asked for SNI filtering, filter on that first because
+    // any sampling will apply just to that subset of connections that match
+    // that SNI.
+    if (!sni_filter.empty()) {
+      TSVConn ssn_vc           = TSHttpSsnClientVConnGet(ssnp);
+      TSSslConnection ssl_conn = TSVConnSslConnectionGet(ssn_vc);
+      SSL *ssl_obj             = (SSL *)ssl_conn;
+      if (ssl_obj == nullptr) {
+        TSDebug(PLUGIN_NAME, "global_ssn_handler(): Ignore non-HTTPS session %" PRId64 "...",
id);
+        break;
+      }
+      const std::string sni = SSL_get_servername(ssl_obj, TLSEXT_NAMETYPE_host_name);
+      if (sni != sni_filter) {
+        TSDebug(PLUGIN_NAME, "global_ssn_handler(): Ignore HTTPS session with non-filtered
SNI: %s", sni.c_str());
+        break;
+      }
+    }
+    const auto this_session_count = session_counter++;
+    if (this_session_count % sample_pool_size != 0) {
       TSDebug(PLUGIN_NAME, "global_ssn_handler(): Ignore session %" PRId64 "...", id);
       break;
     } else if (disk_usage >= max_disk_usage) {
@@ -632,10 +656,10 @@ global_ssn_handler(TSCont contp, TSEvent event, void *edata)
     std::string beginning = R"({"meta":{"version":"1.0"},"sessions":[{"protocol":[)" + result
+ "]" + R"(,"connection-time":)" +
                             std::to_string(start.count()) + R"(,"transactions":[)";
 
-    // Grab session id and use its hex string as fname
+    // Use the session count's hex string as the filename.
     std::stringstream stream;
-    stream << std::setw(16) << std::setfill('0') << std::hex << id;
-    std::string session_id = stream.str();
+    stream << std::setw(16) << std::setfill('0') << std::hex << this_session_count;
+    std::string session_hex_name = stream.str();
 
     // Use client ip as sub directory name
     char client_str[INET6_ADDRSTRLEN];
@@ -653,7 +677,7 @@ global_ssn_handler(TSCont contp, TSEvent event, void *edata)
     TSMutexLock(ssnData->disk_io_mutex);
     if (ssnData->log_fd < 0) {
       ts::file::path log_p = log_path / ts::file::path(std::string(client_str, 3));
-      ts::file::path log_f = log_p / ts::file::path(session_id);
+      ts::file::path log_f = log_p / ts::file::path(session_hex_name);
 
       // Create subdir if not existing
       std::error_code ec;
@@ -682,7 +706,7 @@ global_ssn_handler(TSCont contp, TSEvent event, void *edata)
     break;
   }
   case TS_EVENT_HTTP_SSN_CLOSE: {
-    // Write session and log file closing
+    // Write session and close the log file.
     int64_t id = TSHttpSsnIdGet(ssnp);
     TSDebug(PLUGIN_NAME, "global_ssn_handler(): Closing session %" PRId64 "...", id);
     // Retrieve SsnData
@@ -721,12 +745,11 @@ TSPluginInit(int argc, const char *argv[])
 
   bool sensitive_fields_were_specified = false;
   /// Commandline options
-  static const struct option longopts[] = {{"logdir", required_argument, nullptr, 'l'},
-                                           {"sample", required_argument, nullptr, 's'},
-                                           {"limit", required_argument, nullptr, 'm'},
-                                           {"sensitive-fields", required_argument, nullptr,
'f'},
-                                           {nullptr, no_argument, nullptr, 0}};
-  int opt                               = 0;
+  static const struct option longopts[] = {
+    {"logdir", required_argument, nullptr, 'l'},     {"sample", required_argument, nullptr,
's'},
+    {"limit", required_argument, nullptr, 'm'},      {"sensitive-fields", required_argument,
nullptr, 'f'},
+    {"sni-filter", required_argument, nullptr, 'n'}, {nullptr, no_argument, nullptr, 0}};
+  int opt = 0;
   while (opt >= 0) {
     opt = getopt_long(argc, const_cast<char *const *>(argv), "l:", longopts, nullptr);
     switch (opt) {
@@ -751,6 +774,12 @@ TSPluginInit(int argc, const char *argv[])
       }
       break;
     }
+    case 'n': {
+      // --sni-filter is used to filter sessions based upon an SNI.
+      sni_filter = std::string(optarg);
+      TSDebug(PLUGIN_NAME, "Filtering to only dump connections with SNI: %s", sni_filter.c_str());
+      break;
+    }
     case 'l': {
       log_path = ts::file::path{optarg};
       break;
diff --git a/tests/gold_tests/pluginTest/traffic_dump/gold/200_sni_bob.gold b/tests/gold_tests/pluginTest/traffic_dump/gold/200_sni_bob.gold
new file mode 100644
index 0000000..1fb2a8f
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/gold/200_sni_bob.gold
@@ -0,0 +1,11 @@
+``
+* Hostname bob was found in DNS cache
+``
+> GET / HTTP/2
+> Host: bob
+``
+< HTTP/2 200 
+< content-length: 0
+``
+< server: ATS/10.0.0
+``
diff --git a/tests/gold_tests/pluginTest/traffic_dump/gold/200_sni_dave.gold b/tests/gold_tests/pluginTest/traffic_dump/gold/200_sni_dave.gold
new file mode 100644
index 0000000..55211bc
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/gold/200_sni_dave.gold
@@ -0,0 +1,12 @@
+``
+* Hostname dave was found in DNS cache
+``
+> GET / HTTP/2
+> Host: dave
+``
+< HTTP/2 200 
+< content-length: 0
+``
+< server: ATS/10.0.0
+``
+
diff --git a/tests/gold_tests/pluginTest/traffic_dump/ssl/server.key b/tests/gold_tests/pluginTest/traffic_dump/ssl/server.key
new file mode 100644
index 0000000..9cdfc36
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/ssl/server.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCZkEXSlZ+ZFKFg
+CPpcDG39e73BuK6E5uE38q2PHh4DV0xcsJnIUx51viqLPwYughxfP0crHyBdXoHV
+dW/3WX4gpiGrdiM/dvCouheo0DPaqUUJ2nZKVYh2M57oyeiuJidlKb7BGkfw3HWP
+9TV7dVyGWok/cowjopqaLHJWxg/kh2KqvUBD0CHt9Kd1XvgXVmHwE7vCv0j5owv2
+MaExTsFb16uWmVLhl1gNHI2RqCX2yLaebH1DvtbLrit1XErjtaSYeJE9clVRaqT6
+vsvLOhyB5tA9WfZqfBYr/MHDeXQfrbIf+4Cp3aTpq5grc5InIMMH0eOk6/f/4tW+
+nq1lfszZAgMBAAECggEAYvYAqRbXRRVwca0Xel5gO2yU+tSDUw5esWlow8RK3yhR
+A6KjV9+Iz6P/UsEIwMwEcLUcrgNfHgybau5Fe4dmqq+lHxQA3xNNP869FIMoB4/x
+98mbVYgNau8VRztnAWOBG8ZtMZA4MFZCRMVm8+rL96E8tXCiMwzEyPo/rP/ymfhN
+3GRunX+GhfIA79AYNbd7HMVL+cvWWUGUF5Bc5i1wXcLy4I7b9NYtv920BeCLzSFK
+BypFB7ku/vKgTcBxe4yxThxPeXPwm4WFzGYKk/Afl1j8tVXCE2U4Y3yykfC0Qk6S
+ECZbCKLO2Rxi9fclIDZBHWuKejZhdjHfjeNvZ2vLoQKBgQDJzLmkVLvWAxgl1yvF
+U7gwqj/TzYqtVowbjEvTNEnPU1j/hIVI343SVV/EvJmif/iRUop6sRYfLsUjpMsH
+CmPysNKL3UtgSYOxLs+0xLhG4OOQRpPSf/uvl9YyWY9G3AqiC7ScthkQjEhZa4c1
+eycYy0jr42kX0OL9MuIH9q0ENQKBgQDCzvGKMs8r5E/Qd3YB9VYB60dx+6G83AHZ
+YqIelykObhCdxL9n4K+p4VKKLvgTcCOLYYIkBSWRJWR+ue3s3ey9+XWd2/q4Xvfh
+TCjAuO2ibMV+y5ClNlW0fQ/doIVWSDbjO2tZW1jh7YWZ4CtuVrsEisv1sk3KltMB
+MguhpTUylQKBgG6TfrncMFzxrx61C+gBmvEXqQffHfkjbnx94OKnSTaQ3jiNHhez
+X9v8KhD8o1bWtpay2uyl8pA9qYqBdzqxZ9kJKSW4qd/mCIJjOy87iBpWint5IPD8
+biZmldlbF9ZlJnJq5ZnlclCN/er5r8oPZHoCkj+nieOh8294nUBt25ptAoGAMnPA
+EIeaKgbmONpHgLhWPwb9KOL/f1cHT5KA5CVH58nPmdyTqcaCGCAX7Vu+ueIIApgN
+SWDf2thxT3S9zuOm5YiO0oRfSZKm5f2AbHE4ciFzgKQd4PvSdH0TN9XT0oW/WVhR
+NAI5YcHPIQvyk4/4vXNo4Uf9Z6NqIFwisQmFXoUCgYBK/ZI/HsFsvnR5MV0tFdGM
+AdNe6bsQRSZkowoaPxuWbklE4Hn6QvwEmQg3ST2O+vCQV1f1yI6YiWYoptOYscJc
+MSs/HxhhaaO5ZsiuPUO6WEPzpNb2CxuIGDDtl83VtUQyjxCmOb6pqqjwzFmZ2bsw
+JNMaBCzokrJTxknvauCuSQ==
+-----END PRIVATE KEY-----
diff --git a/tests/gold_tests/pluginTest/traffic_dump/ssl/server.pem b/tests/gold_tests/pluginTest/traffic_dump/ssl/server.pem
new file mode 100644
index 0000000..2b56cc8
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/ssl/server.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDZDCCAkygAwIBAgIJANod1+h9CtCaMA0GCSqGSIb3DQEBCwUAMEcxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIDAJJTDEPMA0GA1UECgwGQXBhY2hlMRowGAYDVQQDDBFy
+YW5kb20uc2VydmVyLmNvbTAeFw0xODExMTkxNzEwMTlaFw0yODExMTYxNzEwMTla
+MEcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJJTDEPMA0GA1UECgwGQXBhY2hlMRow
+GAYDVQQDDBFyYW5kb20uc2VydmVyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAJmQRdKVn5kUoWAI+lwMbf17vcG4roTm4TfyrY8eHgNXTFywmchT
+HnW+Kos/Bi6CHF8/RysfIF1egdV1b/dZfiCmIat2Iz928Ki6F6jQM9qpRQnadkpV
+iHYznujJ6K4mJ2UpvsEaR/DcdY/1NXt1XIZaiT9yjCOimposclbGD+SHYqq9QEPQ
+Ie30p3Ve+BdWYfATu8K/SPmjC/YxoTFOwVvXq5aZUuGXWA0cjZGoJfbItp5sfUO+
+1suuK3VcSuO1pJh4kT1yVVFqpPq+y8s6HIHm0D1Z9mp8Fiv8wcN5dB+tsh/7gKnd
+pOmrmCtzkicgwwfR46Tr9//i1b6erWV+zNkCAwEAAaNTMFEwHQYDVR0OBBYEFI2y
+qm0+UAChDAnLrAINeFOuyUlhMB8GA1UdIwQYMBaAFI2yqm0+UAChDAnLrAINeFOu
+yUlhMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAA3ZNFbqxcOX
+szS5A4EXCepyBJBFejEYy0CsvwQX/ai/pMrw5jqVeF0GAOTpBCVLddyY+ZV1arD2
+Pqi7Qwot9OxEZOzbCBiuMJGotruKgnWFQDHzJ9HA7KDQs270uNESAOG/xW9os9zN
+MXApzqfBSR5EIQU5L3RtaiPzoKdQenGQUOj86s0Kon7snDSUzaA2VcfstMWgGvXP
+JHtaVusULm0gry32cEap5G5UK+gII6DfLWgFwFGhHHmTz3mKjyGiJQ+09XBtu4lb
+ENE+HGRBBA49dUKSr3kwErO4HyHnS0YrsTDnbYURCsGUDma12oijX2sCos6Q4zn8
+3svaouRrucw=
+-----END CERTIFICATE-----
diff --git a/tests/gold_tests/pluginTest/traffic_dump/ssl/signed-foo.key b/tests/gold_tests/pluginTest/traffic_dump/ssl/signed-foo.key
new file mode 100644
index 0000000..e2c7066
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/ssl/signed-foo.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDJheOsr0o4C0QV
+elo8viYl/IjWvkj4Y6YojnO/E9T5HSfWxkRikRT8X7yqs9ClrjNcYoPNNQP5vgl1
+qAIeixUrbZZklcZ3kHF/MXdzuYV//uT3YfWrsOTdfbcu6adHtBr/Qc0w9GSbBpp4
+2ZALxzjZ2hZZq51XmKvcz55/gm/9YvlGErzvsPzkejdH6U1GKeLqGaZOqkV7N2J4
+zKmJyiPzwrmR/8y7k+9jDHQX+A2wa5gaiAMGdIM8aTV+XsNNAvespvXyX7UhwxDs
+w0er0GLv4ssYCru5hF+tUcjeOCHxSnCoEC45b2zDZHATLLjr7AIJ52TcSo1kTaTi
+rAOAiHRLAgMBAAECggEAB7fXBnAYOZlE3EW5WwY1U9MeMotLJCg83uTFzhWmXHwf
+YHxrdhL0aM4J3cfRP+cyFGG5hox3QINkvVrX6e+NugISdnu+BCpGDocIeigq0sIi
+Zs8bp524xjrgXy2XuIlPV2NfxnY1vDI+jE5Y0/qnVMCjhn+qIQa53lUdTujh/SRR
+3U7di+QMK4mdGwRnInos++ENy33A+2LqtUK8i0ERkzPFa1yMQEE4DOFPzZcW+jhK
+arvzBwPIn37PZmL5oyiQB1YiGPGt4XNfPBwACTMYM8LlYBfEBHG77k3bMtUf0WqE
+GctoT5SIe5+YbyrWkpfHgoKPxggH3I3TrFnVvqrKQQKBgQDmcV1YbuNEQLeif521
+iGqMgPQYmnpO6k27RsZrM9ikhIgm9bVJsOqnaYzQFeSfJ3eNLXYUL6IF8g46xddw
+fDBtrEjDAA9OUkNRcizbeKF+GJRMtX11d4ZNbnG1wyMZYkArZGfraZBLHPEF1pya
+2iFdVfokQCBpLmX7BMQEPePyuwKBgQDf33H9njf9oO0l9GfuWDvSoaV8GwqV9x55
+sFjggQYD/xqwEprrzr524X5Y2ZiTUpBu+kqqM8GYfm3bzBKkZU1rnjwxADUwBw8U
+L2U/Z7Id3om8tAdzHOSI9d7mxWA8uTsScMm0IFv2l/XBQo1+AAJSD03pcsabr4Lf
+SuJGmoFTsQKBgQDVzPASEC+DL5gwh75Gop5YZXwTJ5+6f+BGlM+avquNV/kKTIU6
+LY5IbMFcfjNzBicBMOCQsfDdG0rgdJYBovc7idCoOvH4dJJIimnb5fvPBfbxhKE1
+zwMn7ARL4xQ5hNKMb8eKvpJFXkCwbgE2GpNCCXbfEy/+5jFvx2gll1ZZ6QKBgG3J
+OzJ/w796irHBQLKOzI+HvAq3jCJs9KICjCNUwql1EhZkmVqooZjVDkvuMbeVlsUF
+s1XyWa852RAf7Mh38VakW6pACtVJsOhaMdG9PYkOWAeVVc3qzlwoDy6mfoJo6AIs
+E45lDBRLAzbKN28h/AFYBgJEygcRNCHirEKphGCRAoGAEhcaxbmMo2fHBYuvOR1Q
+ZAIq1EPvysDROUBHhdTJqN1wHsuJsmVJxX42+YHcZdjtgeCdjU3HMoyCnTaRxDee
+K3VeB4PobN1WpQwFklFoqcvAhW6eicdZXme7ktK120NPQsXrmjgN6Lfg3PNjosn0
+tqSxQhQ4DrSf60fxx0/M/rw=
+-----END PRIVATE KEY-----
diff --git a/tests/gold_tests/pluginTest/traffic_dump/ssl/signed-foo.pem b/tests/gold_tests/pluginTest/traffic_dump/ssl/signed-foo.pem
new file mode 100644
index 0000000..6f6aecf
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/ssl/signed-foo.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAnQCCQC81MtBCwmQtzANBgkqhkiG9w0BAQsFADCBnTELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh
+aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u
+ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j
+b20wHhcNMTgxMDE1MTU1NjMzWhcNMjgxMDEyMTU1NjMzWjByMQswCQYDVQQGEwJV
+UzELMAkGA1UECAwCSUwxEjAQBgNVBAcMCUNoYW1wYWlnbjEQMA4GA1UECgwHRXhh
+bXBsZTEQMA4GA1UEAwwHZm9vLmNvbTEeMBwGCSqGSIb3DQEJARYPYm9iQGV4YW1w
+bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyYXjrK9KOAtE
+FXpaPL4mJfyI1r5I+GOmKI5zvxPU+R0n1sZEYpEU/F+8qrPQpa4zXGKDzTUD+b4J
+dagCHosVK22WZJXGd5BxfzF3c7mFf/7k92H1q7Dk3X23LumnR7Qa/0HNMPRkmwaa
+eNmQC8c42doWWaudV5ir3M+ef4Jv/WL5RhK877D85Ho3R+lNRini6hmmTqpFezdi
+eMypicoj88K5kf/Mu5PvYwx0F/gNsGuYGogDBnSDPGk1fl7DTQL3rKb18l+1IcMQ
+7MNHq9Bi7+LLGAq7uYRfrVHI3jgh8UpwqBAuOW9sw2RwEyy46+wCCedk3EqNZE2k
+4qwDgIh0SwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBALr2gm+KgveEcTXwURM0wxJC
+m0yOR8w6MX8fxHKaekhJH1U84G64Ub0gbn2beOdLBQkG+4czLiOOOgyeukPaJJ81
+od2ooE7DrGUPGnbHYxW/70EtVF5nQEctcqpKNF/d04mVKrqI90919MJSxJ5KedHK
+2H11+gUPwDWy/mAwJzEJ
+-----END CERTIFICATE-----
diff --git a/tests/gold_tests/pluginTest/traffic_dump/ssl/signer.pem b/tests/gold_tests/pluginTest/traffic_dump/ssl/signer.pem
new file mode 100644
index 0000000..111cd07
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/ssl/signer.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICszCCAhwCCQD4jSkztmlO1TANBgkqhkiG9w0BAQsFADCBnTELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh
+aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u
+ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j
+b20wHhcNMTcwODI4MDM0NDQ1WhcNMjcwODI2MDM0NDQ1WjCBnTELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh
+aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u
+ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j
+b20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYwc6JQX45GZmMDEjwxYT11
+uVvuBBInfpYJeU8WIXHrKcX5LUSRcBikiKnlfSnMNRohsu6TElQACc60wQ7Q8KDE
+lBSsS1FaHzCIl1t1AkXRmz/1H65JSBvrV/6Z1NC+Gp58EbH7Gul8ByC1xaJm5ID1
+Dd++kOPlY5ZI9ZcFS7HLAgMBAAEwDQYJKoZIhvcNAQELBQADgYEATX7975NdhIbJ
+glda+sXI9a86GgOpiuKO+vKubRJQZA+UlPf2vHEONjC2+7Y1aZvZYaKYL74vxGky
+zkgp6ANSPl45lqD632x0e1Z7vzW5TkqK1JB2/xH2WgDcQZmP0FuQHzVNs4GjghDr
+HCp1+sQDhfPB4aLmLFeyN0TkhdH1N3M=
+-----END CERTIFICATE-----
diff --git a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_sni_filter.test.py b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_sni_filter.test.py
new file mode 100644
index 0000000..9b02065
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_sni_filter.test.py
@@ -0,0 +1,144 @@
+"""
+Verify traffic_dump functionality.
+"""
+#  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.
+
+import os
+Test.Summary = '''
+Verify traffic_dump functionality.
+'''
+
+Test.SkipUnless(
+    Condition.PluginExists('traffic_dump.so'),
+)
+
+# Configure the origin server.
+server = Test.MakeOriginServer("server")
+
+request_header = {"headers": "GET / HTTP/1.1\r\n"
+                  "Host: www.example.com\r\nContent-Length: 0\r\n\r\n",
+                  "timestamp": "1469733493.993", "body": ""}
+response_header = {"headers": "HTTP/1.1 200 OK"
+                   "\r\nConnection: close\r\nContent-Length: 0"
+                   "\r\nSet-Cookie: classified_not_for_logging\r\n\r\n",
+                   "timestamp": "1469733493.993", "body": ""}
+server.addResponse("sessionfile.log", request_header, response_header)
+
+# Define ATS and configure
+ts = Test.MakeATSProcess("ts", select_ports=True, enable_tls=True)
+replay_dir = os.path.join(ts.RunDirectory, "ts", "log")
+
+ts.addSSLfile("ssl/server.pem")
+ts.addSSLfile("ssl/server.key")
+ts.addSSLfile("ssl/signer.pem")
+
+ts.Disk.records_config.update({
+    'proxy.config.diags.debug.enabled': 1,
+    'proxy.config.diags.debug.tags': 'traffic_dump',
+
+    'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
+    'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir),
+    'proxy.config.ssl.client.verify.server':  0,
+    'proxy.config.url_remap.pristine_host_hdr': 1,
+    'proxy.config.ssl.CA.cert.filename': '{0}/signer.pem'.format(ts.Variables.SSLDir),
+    'proxy.config.exec_thread.autoconfig.scale': 1.0,
+    'proxy.config.http.host_sni_policy': 2,
+    'proxy.config.ssl.TLSv1_3': 0,
+})
+
+ts.Disk.ssl_multicert_config.AddLine(
+    'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
+)
+
+ts.Disk.remap_config.AddLine(
+    'map / http://127.0.0.1:{0}'.format(server.Variables.Port)
+)
+
+ts.Disk.sni_yaml.AddLines([
+    'sni:',
+    '- fqdn: boblite',
+    '  verify_client: STRICT',
+    '  host_sni_policy: PERMISSIVE',
+    '- fqdn: bob',
+    '  verify_client: STRICT',
+])
+
+# Configure traffic_dump to filter to only dump with connections with SNI bob.
+sni_filter = "bob"
+ts.Disk.plugin_config.AddLine(
+    'traffic_dump.so --logdir {0} --sample 1 --limit 1000000000 '
+    '--sni-filter "{1}"'.format(replay_dir, sni_filter)
+)
+
+# Set up trafficserver expectations.
+ts.Streams.stderr += Testers.ContainsExpression(
+        "Filtering to only dump connections with SNI: {}".format(sni_filter),
+        "Verify filtering for the expected SNI.")
+
+ts.Streams.stderr += Testers.ContainsExpression(
+        "Ignore HTTPS session with non-filtered SNI: dave",
+        "Verify that the non-desired SNI session was filtered out.")
+
+# Set up the json replay file expectations.
+replay_file_session_1 = os.path.join(replay_dir, "127", "0000000000000000")
+ts.Disk.File(replay_file_session_1, exists=True)
+
+# The second session should be filtered out because it doesn't have the
+# expected SNI (note exists is set to False).
+replay_file_session_2 = os.path.join(replay_dir, "127", "0000000000000001")
+ts.Disk.File(replay_file_session_2, exists=False)
+
+#
+# Test 1: Verify dumping a session with the desired SNI and not dumping
+#         the session with the other SNI.
+#
+
+# Execute the first transaction.
+tr = Test.AddTestRun("Verify dumping of a session with the filtered SNI")
+tr.Setup.Copy("ssl/signed-foo.pem")
+tr.Setup.Copy("ssl/signed-foo.key")
+tr.Processes.Default.StartBefore(server, ready=When.PortOpen(server.Variables.Port))
+tr.Processes.Default.StartBefore(Test.Processes.ts)
+tr.Processes.Default.Command = \
+        ('curl --tls-max 1.2 -k -H"Host: bob" --resolve "bob:{0}:127.0.0.1" '
+         '--cert ./signed-foo.pem --key ./signed-foo.key --verbose https://bob:{0}'.format(ts.Variables.ssl_port))
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.stderr = "gold/200_sni_bob.gold"
+tr.StillRunningAfter = server
+tr.StillRunningAfter = ts
+
+# Execute the second transaction.
+tr = Test.AddTestRun("Verify that a session of a different SNI is not dumped.")
+tr.Processes.Default.Command = \
+        ('curl --tls-max 1.2 -k -H"Host: dave" --resolve "dave:{0}:127.0.0.1" '
+         '--cert ./signed-foo.pem --key ./signed-foo.key --verbose https://dave:{0}'.format(ts.Variables.ssl_port))
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.stderr = "gold/200_sni_dave.gold"
+tr.StillRunningAfter = server
+tr.StillRunningAfter = ts
+
+# Verify the properties of the replay file for the dumped transaction.
+tr = Test.AddTestRun("Verify the json content of the first session")
+verify_replay = "verify_replay.py"
+tr.Setup.CopyAs(verify_replay, Test.RunDirectory)
+tr.Processes.Default.Command = "python3 {0} {1} {2}".format(
+        verify_replay,
+        os.path.join(Test.Variables.AtsTestToolsDir, 'lib', 'replay_schema.json'),
+        replay_file_session_1)
+tr.Processes.Default.ReturnCode = 0
+tr.StillRunningAfter = server
+tr.StillRunningAfter = ts


Mime
View raw message