You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2017/11/27 17:07:33 UTC

[trafficserver] branch master updated: Doc: Add Layer 4 / SNI Routing documentation.

This is an automated email from the ASF dual-hosted git repository.

amc 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 91f1bb7  Doc: Add Layer 4 / SNI Routing documentation.
91f1bb7 is described below

commit 91f1bb7b54827f80bd5b976e83e25bc86e4e3a3b
Author: Alan M. Carroll <am...@apache.org>
AuthorDate: Tue Nov 21 10:38:04 2017 -0600

    Doc: Add Layer 4 / SNI Routing documentation.
---
 doc/admin-guide/files/index.en.rst                 |   6 +-
 doc/admin-guide/files/records.config.en.rst        |   5 +
 .../files/ssl_server_name.config.en.rst            | 141 +++++++++++++++++++++
 doc/admin-guide/index.en.rst                       |   2 +-
 doc/admin-guide/layer-4-routing.en.rst             | 128 +++++++++++++++++++
 doc/uml/Makefile                                   |  23 ++++
 doc/uml/images/.gitignore                          |   5 +
 doc/uml/images/l4-basic-sequence.svg               |  30 +++++
 doc/uml/images/l4-example-cdn-layout.svg           |  27 ++++
 doc/uml/images/l4-sni-routing-seq.svg              |  34 +++++
 doc/uml/l4-basic-sequence.uml                      |  24 ++++
 doc/uml/l4-example-cdn-layout.uml                  |  21 +++
 doc/uml/l4-sni-routing-seq.uml                     |  28 ++++
 doc/uml/l4-tcp-routing.uml                         |  23 ++++
 14 files changed, 495 insertions(+), 2 deletions(-)

diff --git a/doc/admin-guide/files/index.en.rst b/doc/admin-guide/files/index.en.rst
index e3cee5f..4a158f7 100644
--- a/doc/admin-guide/files/index.en.rst
+++ b/doc/admin-guide/files/index.en.rst
@@ -38,6 +38,7 @@ Configuration Files
    remap.config.en
    splitdns.config.en
    ssl_multicert.config.en
+   ssl_server_name.config.en
    storage.config.en
    vaddrs.config.en
    volume.config.en
@@ -88,9 +89,12 @@ Configuration Files
    Configures |TS| to use different server certificates for SSL termination
    when listening on multiple addresses or when clients employ SNI.
 
+:doc:`ssl_server_name.config.en`
+   Configures SNI based Layer 4 routing.
+
 :doc:`storage.config.en`
    Configures all storage devices and paths to be used for the |TS| cache.
-    
+
 :doc:`vaddrs.config.en`
    Deprecated file formerly used for cluster configuration.
 
diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst
index 24310a8..3718237 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -3194,6 +3194,11 @@ SSL Termination
    ``head -c48 /dev/urandom | openssl enc -base64 | head -c48 > file.ticket``. Also
    note that OpenSSL session tickets are sensitive to the version of the ca-certificates.
 
+.. ts:cv:: CONFIG proxy.config.ssl.servername.filename STRING ssl_server_name.config
+
+   The filename of the :file:`ssl_server_name.config` configuration file. If relative, it is relative to the
+   configuration directory (ts:cv:`proxy.config.config_dir`).
+
 .. ts:cv:: CONFIG proxy.config.ssl.max_record_size INT 0
 
   This configuration specifies the maximum number of bytes to write
diff --git a/doc/admin-guide/files/ssl_server_name.config.en.rst b/doc/admin-guide/files/ssl_server_name.config.en.rst
new file mode 100644
index 0000000..de40db9
--- /dev/null
+++ b/doc/admin-guide/files/ssl_server_name.config.en.rst
@@ -0,0 +1,141 @@
+.. 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
+
+ssl_server_name.config
+**********************
+
+.. configfile:: ssl_server_name.config
+
+Description
+===========
+
+This file is used to configure aspects of TLS connection handling for both inbound and outbound
+connections. The configuration is driven by the SNI values provided by the inbound connection. The
+file consists of a set of configuration items, each identified by an SNI value (``fqdn``).
+When an inbound TLS connection is made, the SNI value from the TLS negotiation is matched against
+the items specified by this file and if there is a match, the values specified in that item override
+the defaults. This is done during the inbound connection processing and be some outbound properties
+can be overridden again later, such as via :file:`remap.config` or plugins.
+
+By default this is named :file:`ssl_server_name.config`. The file can be changed by settting
+:ts:cv:`proxy.config.ssl.servername.filename`. This file is loaded on start up and by
+:option:`traffic_ctl config reload` if the file has been modified since process start.
+
+The configuration file is Lua based. After parsing and executing the Lua code, the global Lua
+variable :code:`server_config` is examined. Its value should be a list of tables. Each table is set
+of key / value pairs that create a configuration item.
+
+======================= ==============================================================================
+Key                     Meaning
+======================= ==============================================================================
+fqdn                    Fully Qualified Domain Name. This item is used if the SNI value matches this.
+
+verify_origin_server    One of the values :code:`NONE`, :code:`MODERATE`, or :code:`STRICT`.
+
+                        By default this is :ts:cv:`proxy.config.ssl.client.verify.server`.
+
+verify_client           One of the values :code:`NONE`, :code:`MODERATE`, or :code:`STRICT`.
+
+                        By default this is :ts:cv:`proxy.config.ssl.client.certification_level`.
+
+client_cert             The client certificate to use for the outbound connection.
+
+                        If this is relative it is relative to the path in
+                        :ts:cv:`proxy.config.ssl.server.cert.path`. If not set
+                        :ts:cv:`proxy.config.ssl.client.cert.filename` is used.
+
+disable_h2              :code:`true` or :code:`false`.
+
+                        If :code:`false` then HTTP/2 is removed from
+                        the valid next protocol list. It is not an error to set this to :code:`false`
+                        for proxy ports on which HTTP/2 is not enabled.
+
+tunnel_route            Destination as an FQDN and port, separated by a colon ``:``.
+======================= ==============================================================================
+
+Client verification, via ``verify_client``, correponds to setting
+:ts:cv:`proxy.config.ssl.client.certification_level` for this connection as noted below.
+
+:code:`NONE` -- ``0``
+   Do not request a client certificate, ignore it if one is provided.
+
+:code:`MODERATE` - ``1``
+   Request a client certificate and do verification if one is provided, but do not enforce
+   verification. If the verification fails the failure is logged to :file:`diags.log` but the
+   connection is allowed.
+
+:code:`STRICT` - ``2``
+   Request a client certificate and require one to be provided and verified.
+   If the verification fails the failure is logged to :file:`diags.log` and the connection is
+   denied.
+
+Upstream (server) verification, via ``verify_origin_server``, is similar to client verification
+except there is always an upstream certificate. This is equivalent to setting
+:ts:cv:`proxy.config.ssl.client.verify.server` for this connection.
+
+:code:`NONE` - ``0``
+   Do not verify the upstream server certificate.
+
+:code:`MODERATE` - ``2``
+   Do verification of the upstream certificate but do not enforce. If the verification fails the
+   failure is logged in :file:`diags.log` but the connection is allowed.
+
+:code:`STRICT` - ``1``
+   Do verification of the upstream certificate. If verification fails, the failure is
+   logged in :file:`diags.log` and the connection is denied.
+
+If ``tunnel_route`` is specified, none of the certificate verification will be done because the TLS
+negotiation will be tunneled to the upstream target, making those values irrelevant for that
+configuration item. This option is explained in more detail in :ref:`sni-routing`.
+
+Examples
+========
+
+Disable HTTP/2 for ``no-http2.example.com``.
+
+.. code-block:: Lua
+
+   server_config = {{ fqdn="no-http2.example.com", disable_h2=true }}
+
+Require client certificate verification for ``example.com`` and ``yahoo.com``.
+
+.. code-block:: Lua
+
+   server_config = {
+      { fqdn="example.com", verify_client=STRICT },
+      { fqdn="yahoo.com", verify_client=STRICT }
+   }
+
+Disable outbound server certificate verification for ``trusted.example.com`` and require a valid
+client certificate.
+
+.. code-block:: Lua
+
+   server_config = {
+      {
+         fqdn="trusted.example.com",
+         verify_origin_server=NONE,
+         verify_client=STRICT
+      }
+   }
+
+See Also
+========
+
+:ref:`sni-routing`
diff --git a/doc/admin-guide/index.en.rst b/doc/admin-guide/index.en.rst
index c2bf2eb..0557b69 100644
--- a/doc/admin-guide/index.en.rst
+++ b/doc/admin-guide/index.en.rst
@@ -37,6 +37,7 @@ Table of Contents:
    logging/index.en
    monitoring/index.en
    configuring-traffic-server.en
+   layer-4-routing.en
    performance/index.en
    files/index.en
 
@@ -54,4 +55,3 @@ running with your own instance of |TS|. Or so is our hope.
 Should you encounter problems, or find any of the instructions unclear or
 lacking, please seek help through one of the avenues listed in
 :ref:`intro-other-resources`.
-
diff --git a/doc/admin-guide/layer-4-routing.en.rst b/doc/admin-guide/layer-4-routing.en.rst
new file mode 100644
index 0000000..5395449
--- /dev/null
+++ b/doc/admin-guide/layer-4-routing.en.rst
@@ -0,0 +1,128 @@
+.. 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
+.. default-domain:: c
+.. _layer-4-routing:
+
+Layer 4 Routing
+**************************
+
+|TS| supports a limited set of layer 4 routing options. In such use |TS| acts effectively as a
+router, moving network data between two endpoints without modifying the data. The routing is
+accomplished by examining the initial data from the inbound connection to decide the outbound
+destination. The initial data is then sent to the destination and subsequently |TS| forwards all
+data read on one connection to the other and vice versa.
+
+.. image:: ../uml/images/l4-basic-sequence.svg
+   :align: center
+
+In this way it acts similary to `nc <https://linux.die.net/man/1/nc>`__.
+
+The primary differences between different types of layer 4 routing is the mechanism by which |TS|
+creates the outbound connection. This is described in detail in the type specific documentation.
+
+Transparency
+============
+
+Transparency is in some sense layer 4 routing because the outbound connection is determined by
+examining the destination address in the client TCP packets. This is discussed in detail
+:ref:`elsewhere <transparent-proxy>`.
+
+.. _sni-routing:
+
+SNI Routing
+===========
+
+Currently the only directly supported layer 4 routing (as of version 8.0) is SNI based routing. This
+imposes some requirements on the traffic.
+
+*  The inbound connection must be TLS.
+*  The outbound destination must handle the HTTP ``CONNECT`` method.
+
+SNI routing is configured by :file:`ssl_server_name.config`.
+
+If SNI Routing is enabled the initial "`CLIENT HELLO
+<https://tools.ietf.org/html/rfc5246#section-7.4.1.2>`__" data of an inbound TLS connection is
+examined to extract the "`SNI <https://tools.ietf.org/html/rfc3546#section-3.1>`__" value. This is
+matched against the configuration data to select an action for the inbound connection. In this case
+the option of interest is ``tunnel_route``. If this is set then |TS| will connect to the specified
+destination and issue an HTTP ``CONNECT`` request using the SNI value as the URL for the request.
+Because the destination and the ``CONNECT`` are the same in general it will be necessary to use
+a plugin to change the URL in the ``CONNECT``.
+
+Example
+-------
+
+Consider a Content Delivery Network (CDN) that has an edge layer of externally facing |TS|
+instances. The goal is to enable external clients to connect to internal services and do their own
+client certificate verification, possibly because distribution of private keys to the edge |TS|
+instances is too difficult or too risky. To achieve this, the edge |TS| instances can be configured
+to route inbound TLS connections with specific SNI values directly to the internal services without
+TLS termination on the edge. This enables the edge to provide controlled external access to the
+internal services without each internal service having to stand up its own edge. Note the services
+do not require global routable addresses as long as the edge |TS| instances can route to the
+services.
+
+The basic set up is therefore
+
+.. figure:: ../uml/images/l4-example-cdn-layout.svg
+   :align: center
+
+   A Client connects to an edge |TS| which forwards the connection to the internal Service.
+   The Client then negotiates TLS with the Service.
+
+
+For the example, let us define two services inside the corporate network of Example, Inc.
+``service-1`` and ``service-2``. ``service-1`` is on port 443 on host ``app-server-29`` while
+``service-2`` is on port 4443 on host ``app-server-56``. The SNI routing set up for this would be
+
+========================== =====================================
+SNI value                  Destination
+========================== =====================================
+service-1.example.com      app-server-29:443
+service-2.example.com      app-server-56:4443
+========================== =====================================
+
+The :file:`ssl_server_name.config` contents would be
+
+.. code-block:: lua
+
+   server_config = {
+      {
+         fqdn = 'service-1.example.com'
+         tunnel_route = 'app-server-29:443'
+      },
+      {
+         fqdn = 'service-2.example.com'
+         tunnel_route = 'app-server-56:4443'
+      }
+   }
+
+The sequence of network activity for a Client connecting to ``service-2`` is
+
+.. image:: ../uml/images/l4-sni-routing-seq.svg
+   :align: center
+
+Note the destination for the outbound TCP connection and the HTTP ``CONNECT`` is the same. If this
+is a problem (which it will be in general) a plugin is needed to change the URL in the ``CONNECT``.
+In this case the proxy request is available in the :c:macro:`TS_HTTP_TXN_START_HOOK` hook. This
+cannot be done using remap because for a ``CONNECT`` there is no remap phase. Note that for a
+tunneled connection like this, the only transaction hooks that will be triggered are
+:c:macro`TS_HTTP_TXN_START_HOOK` and :c:macro:`TS_HTTP_TXN_CLOSE_HOOK`. In addition, because |TS|
+does not terminate (and thefore does not decrypt) the connection, it cannot be cached or served from
+cache.
diff --git a/doc/uml/Makefile b/doc/uml/Makefile
new file mode 100644
index 0000000..0f387a9
--- /dev/null
+++ b/doc/uml/Makefile
@@ -0,0 +1,23 @@
+# doc/uml Makefile
+#
+#  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 is exlicitly not tied in to the general make setup. It is intended
+# to be run manually only as needed so that only people who need to update
+# diagrams must install Java support for plantuml.
+all:
+	java -jar ~/bin/plantuml.jar -o images -tsvg *.uml
diff --git a/doc/uml/images/.gitignore b/doc/uml/images/.gitignore
new file mode 100644
index 0000000..85efa6a
--- /dev/null
+++ b/doc/uml/images/.gitignore
@@ -0,0 +1,5 @@
+## Directory for images generated from UML diagrams.
+# Ignore everything - files are only checked in / updated here manually using `git add -f`.
+# That may change if requiring Java to build the docs for plantuml is approved.
+*
+!.gitignore
diff --git a/doc/uml/images/l4-basic-sequence.svg b/doc/uml/images/l4-basic-sequence.svg
new file mode 100644
index 0000000..6a0c687
--- /dev/null
+++ b/doc/uml/images/l4-basic-sequence.svg
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="496px" preserveAspectRatio="none" style="width:428px;height:496px;" version="1.1" viewBox="0 0 428 496" width="428px" zoomAndPan="magnify"><defs><filter height="300%" id="fsmtqap5irkzc" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMa [...]
+@startuml
+
+actor Inbound
+participant "Traffic\nServer" as TS
+participant Outbound
+
+Inbound <-[#green]> TS : <font color="green">//TCP//</font> Handshake
+Inbound -[#blue]> TS : <font color="blue">//initial data//</font>
+note over TS : Examine initial data\nselect Outbound
+TS <-[#green]> Outbound : <font color="green">//TCP//</font> Handshake
+note over TS, Outbound : Additional Setup\n(in some cases)
+TS -[#blue]> Outbound : <font color="blue">//initial data//</font>
+note left : Duplicate of data from Inbound.
+note over TS : Forward bytes\nInbound <&arrow-thick-left> <&arrow-thick-right> Outbound
+Inbound <- -> Outbound
+
+@enduml
+
+PlantUML version 1.2017.18(Fri Oct 06 11:56:32 CDT 2017)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 1.8.0_151-b12
+Operating System: Linux
+OS Version: 4.13.13-200.fc26.x86_64
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
diff --git a/doc/uml/images/l4-example-cdn-layout.svg b/doc/uml/images/l4-example-cdn-layout.svg
new file mode 100644
index 0000000..14a0e2f
--- /dev/null
+++ b/doc/uml/images/l4-example-cdn-layout.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="109px" preserveAspectRatio="none" style="width:513px;height:109px;" version="1.1" viewBox="0 0 513 109" width="513px" zoomAndPan="magnify"><defs><filter height="300%" id="f18p37jwo5ssms" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorM [...]
+@startuml
+hide empty members
+
+node Client
+cloud "Untrusted\nNetworks" as Cloud
+node "Edge TS"
+package "Corporate Net" {
+    node Service
+}
+
+[Client] <-> [Cloud]
+[Cloud] <-> [Edge TS]
+[Edge TS] <-> [Service]
+@enduml
+
+PlantUML version 1.2017.18(Fri Oct 06 11:56:32 CDT 2017)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 1.8.0_151-b12
+Operating System: Linux
+OS Version: 4.13.13-200.fc26.x86_64
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
diff --git a/doc/uml/images/l4-sni-routing-seq.svg b/doc/uml/images/l4-sni-routing-seq.svg
new file mode 100644
index 0000000..8a965be
--- /dev/null
+++ b/doc/uml/images/l4-sni-routing-seq.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="613px" preserveAspectRatio="none" style="width:596px;height:613px;" version="1.1" viewBox="0 0 596 613" width="596px" zoomAndPan="magnify"><defs><filter height="300%" id="fz7842w3qribd" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMa [...]
+@startuml
+
+actor Inbound
+participant "Traffic\nServer" as TS
+entity "app-server-56:4443" as Outbound
+
+Inbound <-[#green]> TS : <font color="green">//TCP//</font> Handshake
+Inbound -[#blue]> TS : <font color="blue">//TLS//</font> Client HELLO\nSNI=service-2.example.com
+note over TS : Examine SNI value\nSelect Outbound
+TS <-[#green]> Outbound : <font color="green">//TCP//</font> Handshake
+TS -> Outbound : <font color="red">//HTTP//</font> ""CONNECT"" app-server-56:4443
+Outbound -> TS : ""200 OK""
+TS -[#blue]> Outbound : <font color="blue">//TLS//</font> Client HELLO\nSNI=service-2.example.com
+note left : Duplicate of Inbound HELLO
+note over TS : Forward bytes\nInbound <&arrow-thick-left> <&arrow-thick-right> Outbound
+note over Inbound, Outbound : <font color="blue">TLS negotiation</font>
+Inbound <-[#blue]-> Outbound
+note over Inbound, Outbound : Transactions
+Inbound <-[#black]-> Outbound
+
+@enduml
+
+PlantUML version 1.2017.18(Fri Oct 06 11:56:32 CDT 2017)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 1.8.0_151-b12
+Operating System: Linux
+OS Version: 4.13.13-200.fc26.x86_64
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
diff --git a/doc/uml/l4-basic-sequence.uml b/doc/uml/l4-basic-sequence.uml
new file mode 100644
index 0000000..5ecc3c5
--- /dev/null
+++ b/doc/uml/l4-basic-sequence.uml
@@ -0,0 +1,24 @@
+' Licensed 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.
+
+@startuml
+
+actor Inbound
+participant "Traffic\nServer" as TS
+participant Outbound
+
+Inbound <-[#green]> TS : <font color="green">//TCP//</font> Handshake
+Inbound -[#blue]> TS : <font color="blue">//initial data//</font>
+note over TS : Examine initial data\nselect Outbound
+TS <-[#green]> Outbound : <font color="green">//TCP//</font> Handshake
+note over TS, Outbound : Additional Setup\n(in some cases)
+TS -[#blue]> Outbound : <font color="blue">//initial data//</font>
+note left : Duplicate of data from Inbound.
+note over TS : Forward bytes\nInbound <&arrow-thick-left> <&arrow-thick-right> Outbound
+Inbound <--> Outbound
+
+@enduml
diff --git a/doc/uml/l4-example-cdn-layout.uml b/doc/uml/l4-example-cdn-layout.uml
new file mode 100644
index 0000000..5f4f8b5
--- /dev/null
+++ b/doc/uml/l4-example-cdn-layout.uml
@@ -0,0 +1,21 @@
+' Licensed 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.
+
+@startuml
+hide empty members
+
+node Client
+cloud "Untrusted\nNetworks" as Cloud
+node "Edge TS"
+package "Corporate Net" {
+    node Service
+}
+
+[Client] <-> [Cloud]
+[Cloud] <-> [Edge TS]
+[Edge TS] <-> [Service]
+@enduml
diff --git a/doc/uml/l4-sni-routing-seq.uml b/doc/uml/l4-sni-routing-seq.uml
new file mode 100644
index 0000000..00eb967
--- /dev/null
+++ b/doc/uml/l4-sni-routing-seq.uml
@@ -0,0 +1,28 @@
+' Licensed 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.
+
+@startuml
+
+actor Inbound
+participant "Traffic\nServer" as TS
+entity "app-server-56:4443" as Outbound
+
+Inbound <-[#green]> TS : <font color="green">//TCP//</font> Handshake
+Inbound -[#blue]> TS : <font color="blue">//TLS//</font> Client HELLO\nSNI=service-2.example.com
+note over TS : Examine SNI value\nSelect Outbound
+TS <-[#green]> Outbound : <font color="green">//TCP//</font> Handshake
+TS -> Outbound : <font color="red">//HTTP//</font> ""CONNECT"" app-server-56:4443
+Outbound -> TS : ""200 OK""
+TS -[#blue]> Outbound : <font color="blue">//TLS//</font> Client HELLO\nSNI=service-2.example.com
+note left : Duplicate of Inbound HELLO
+note over TS : Forward bytes\nInbound <&arrow-thick-left> <&arrow-thick-right> Outbound
+note over Inbound, Outbound : <font color="blue">TLS negotiation</font>
+Inbound <-[#blue]-> Outbound
+note over Inbound, Outbound : Transactions
+Inbound <-[#black]-> Outbound
+
+@enduml
diff --git a/doc/uml/l4-tcp-routing.uml b/doc/uml/l4-tcp-routing.uml
new file mode 100644
index 0000000..f59ff34
--- /dev/null
+++ b/doc/uml/l4-tcp-routing.uml
@@ -0,0 +1,23 @@
+' Licensed 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.
+
+@startuml
+
+actor Inbound
+participant "Traffic\nServer" as TS
+participant Outbound
+
+Inbound <-[#green]> TS : //TCP Connect//
+Inbound -[#blue]-> TS : <font color="blue">//initial data//</font>
+note over TS : Examine initial data\nselect Outbound
+TS <-[#green]> Outbound : //TCP Connect//
+TS -[#blue]-> Outbound : <font color="blue">//initial data//</font>
+note right : Duplicate of data from Inbound.
+note over TS : Forward bytes between Inbound <&arrow-thick-left> <&arrow-thick-right> Outbound
+Inbound <--> Outbound
+
+@enduml

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].