|
| 1 | +.. _install_sandboxes_tls_sni: |
| 2 | + |
| 3 | +TLS Server name indication (``SNI``) |
| 4 | +==================================== |
| 5 | + |
| 6 | +.. sidebar:: Requirements |
| 7 | + |
| 8 | + .. include:: _include/docker-env-setup-link.rst |
| 9 | + |
| 10 | + :ref:`curl <start_sandboxes_setup_curl>` |
| 11 | + Used to make ``HTTP`` requests. |
| 12 | + |
| 13 | + :ref:`jq <start_sandboxes_setup_jq>` |
| 14 | + Parse ``json`` output from the upstream echo servers. |
| 15 | + |
| 16 | +This example demonstrates an Envoy proxy that listens on three ``TLS`` domains |
| 17 | +on the same ``IP`` address. |
| 18 | + |
| 19 | +The first two domains (``domain1`` and ``domain2``) terminate the ``TLS`` and proxy |
| 20 | +to upstream ``HTTP`` hosts. |
| 21 | + |
| 22 | +The other domain (``domain3``) is proxied unterminated, based on the ``SNI`` headers. |
| 23 | + |
| 24 | +It also demonstrates Envoy acting as a client proxy connecting to upstream ``SNI`` services. |
| 25 | + |
| 26 | +.. _install_sandboxes_tls_sni_step1: |
| 27 | + |
| 28 | +Step 1: Create keypairs for each of the domain endpoints |
| 29 | +******************************************************** |
| 30 | + |
| 31 | +Change directory to ``examples/tls-sni`` in the Envoy repository. |
| 32 | + |
| 33 | +The example creates two Envoy ``TLS`` endpoints and they will require their own |
| 34 | +keypairs. |
| 35 | + |
| 36 | +Create self-signed certificates for these endpoints as follows: |
| 37 | + |
| 38 | +.. code-block:: console |
| 39 | +
|
| 40 | + $ pwd |
| 41 | + envoy/examples/tls-sni |
| 42 | +
|
| 43 | + $ mkdir -p certs |
| 44 | +
|
| 45 | + $ openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 \ |
| 46 | + -subj "/C=US/ST=CA/O=MyExample, Inc./CN=domain1.example.com" \ |
| 47 | + -keyout certs/domain1.key.pem \ |
| 48 | + -out certs/domain1.crt.pem |
| 49 | + Generating a RSA private key |
| 50 | + .............+++++ |
| 51 | + ...................+++++ |
| 52 | + writing new private key to 'certs/domain1.key.pem' |
| 53 | + ----- |
| 54 | +
|
| 55 | + $ openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 \ |
| 56 | + -subj "/C=US/ST=CA/O=MyExample, Inc./CN=domain2.example.com" \ |
| 57 | + -keyout certs/domain2.key.pem \ |
| 58 | + -out certs/domain2.crt.pem |
| 59 | + Generating a RSA private key |
| 60 | + .............+++++ |
| 61 | + ...................+++++ |
| 62 | + writing new private key to 'certs/domain2.key.pem' |
| 63 | + ----- |
| 64 | +
|
| 65 | +.. warning:: |
| 66 | + |
| 67 | + ``SNI`` does *not* validate that the certificates presented are correct for the domain, or that they |
| 68 | + were issued by a recognised certificate authority. |
| 69 | + |
| 70 | + See the :ref:`Securing Envoy quick start guide <start_quick_start_securing>` for more information about |
| 71 | + :ref:`validating cerfificates <start_quick_start_securing_validation>`. |
| 72 | + |
| 73 | +.. _install_sandboxes_tls_sni_step2: |
| 74 | + |
| 75 | +Step 2: Start the containers |
| 76 | +**************************** |
| 77 | + |
| 78 | +Build and start the containers. |
| 79 | + |
| 80 | +This starts two upstream ``HTTP`` containers listening on the internal Docker network on port ``80``, and |
| 81 | +an upstream ``HTTPS`` service listening on internal port ``443`` |
| 82 | + |
| 83 | +In front of these is an Envoy proxy that listens on https://localhost:10000 and serves three ``SNI`` routed |
| 84 | +``TLS`` domains: |
| 85 | + |
| 86 | +- ``domain1.example.com`` |
| 87 | +- ``domain2.example.com`` |
| 88 | +- ``domain3.example.com`` |
| 89 | + |
| 90 | +The first two domains use the keys and certificates :ref:`you created in step 1 <install_sandboxes_tls_sni_step1>` to terminate ``TLS`` and |
| 91 | +proxy to the two upstream ``HTTP`` servers. |
| 92 | + |
| 93 | +The third domain proxies to the upstream ``TLS`` server based on the requested ``SNI`` address, but does no ``TLS`` termination itself. |
| 94 | + |
| 95 | +The composition also starts an Envoy proxy client which listens on http://localhost:20000. |
| 96 | + |
| 97 | +The client proxy has no ``TLS`` termination but instead proxies three routed paths - |
| 98 | +``/domain1``, ``/domain2`` and ``/domain3`` - to the ``SNI``-enabled proxy. |
| 99 | + |
| 100 | +.. code-block:: console |
| 101 | +
|
| 102 | + $ pwd |
| 103 | + envoy/examples/tls-sni |
| 104 | + $ docker-compose build --pull |
| 105 | + $ docker-compose up -d |
| 106 | + $ docker-compose ps |
| 107 | +
|
| 108 | + Name Command State Ports |
| 109 | + ------------------------------------------------------------------------------------------- |
| 110 | + tls-sni_http-upstream1_1 node ./index.js Up |
| 111 | + tls-sni_http-upstream2_1 node ./index.js Up |
| 112 | + tls-sni_http-upstream3_1 node ./index.js Up |
| 113 | + tls-sni_proxy_1 /docker-entrypoint.sh /usr ... Up 0.0.0.0:10000->10000/tcp |
| 114 | + tls-sni_proxy-client_1 /docker-entrypoint.sh /usr ... Up 0.0.0.0:20000->10000/tcp |
| 115 | +
|
| 116 | +Step 2: Query the ``SNI`` endpoints directly with curl |
| 117 | +****************************************************** |
| 118 | + |
| 119 | +You can use curl to query the ``SNI``-routed ``HTTPS`` endpoints of the Envoy proxy directly. |
| 120 | + |
| 121 | +To do this you must explicitly tell curl to resolve the ``DNS`` for the endpoints correctly. |
| 122 | + |
| 123 | +Each endpoint should proxy to the respective ``http-upstream`` or ``https-upstream`` service. |
| 124 | + |
| 125 | +.. code-block:: console |
| 126 | +
|
| 127 | + $ curl -sk --resolve domain1.example.com:10000:127.0.0.1 \ |
| 128 | + https://domain1.example.com:10000 \ |
| 129 | + | jq -r '.os.hostname' |
| 130 | + http-upstream1 |
| 131 | +
|
| 132 | + $ curl -sk --resolve domain2.example.com:10000:127.0.0.1 \ |
| 133 | + https://domain2.example.com:10000 \ |
| 134 | + | jq -r '.os.hostname' |
| 135 | + http-upstream2 |
| 136 | +
|
| 137 | + $ curl -sk --resolve domain3.example.com:10000:127.0.0.1 \ |
| 138 | + https://domain3.example.com:10000 \ |
| 139 | + | jq -r '.os.hostname' |
| 140 | + https-upstream3 |
| 141 | +
|
| 142 | +Step 3: Query the ``SNI`` endpoints via an Envoy proxy client |
| 143 | +************************************************************* |
| 144 | + |
| 145 | +Next, query the Envoy proxy client using the routed paths. |
| 146 | + |
| 147 | +These route via the ``SNI`` proxy endpoints to the respective ``http-upstream`` or |
| 148 | +``https-upstream`` services. |
| 149 | + |
| 150 | +.. code-block:: console |
| 151 | +
|
| 152 | + $ curl -s http://localhost:20000/domain1 \ |
| 153 | + | jq '.os.hostname' |
| 154 | + http-upstream1 |
| 155 | +
|
| 156 | + $ curl -s http://localhost:20000/domain2 \ |
| 157 | + | jq '.os.hostname' |
| 158 | + http-upstream2 |
| 159 | +
|
| 160 | + $ curl -s http://localhost:20000/domain3 \ |
| 161 | + | jq '.os.hostname' |
| 162 | + https-upstream3 |
| 163 | +
|
| 164 | +.. seealso:: |
| 165 | + |
| 166 | + :ref:`Securing Envoy quick start guide <start_quick_start_securing>` |
| 167 | + Outline of key concepts for securing Envoy. |
| 168 | + |
| 169 | + :ref:`TLS sandbox <install_sandboxes_tls>` |
| 170 | + Sandbox featuring examples of how Envoy can be configured to make |
| 171 | + use of encrypted connections using ``HTTP`` over ``TLS``. |
| 172 | + |
| 173 | + :ref:`Double proxy sandbox <install_sandboxes_double_proxy>` |
| 174 | + An example of securing traffic between proxies with validation and |
| 175 | + mutual authentication using ``mTLS`` with non-``HTTP`` traffic. |
0 commit comments