.. include:: vars.rst


.. _section-sec-HO5:

Hands-On 5: Checking that Your DDS Traffic Is Protected
=======================================================

In this Hands-On, you will learn about the effects that enabling DDS Security
has on the wire. We will start by disabling security in our project and viewing
the contents of RTPS packets with Wireshark. Then we will re-enable the
protections defined in :ref:`section-sec-HO2`. We will use Wireshark again to
verify that messages from the publisher are encrypted.

.. note::

   We will use Wireshark to capture and analyze the packets on the network. For
   instructions on getting and installing Wireshark, please refer to
   :link_external_wireshark_users_guide:`Building and Installing Wireshark in Wireshark's
   User's Guide <#ChapterBuildInstall>`. For instructions on enabling convenient
   coloring rules for the RTPS protocol, see
   :link_external_community_howto:`How To configure Wireshark to show RTPS packets with
   specific colors <how-configure-wireshark-show-rtps-packets-specific-colors>`
   from our Knowledge Base.

.. _section-sec-HO5-disabling-security:

Disabling Security and Preparing Your Project for Traffic Capturing
-------------------------------------------------------------------

In :ref:`section-sec-HO1` we defined a QoS profile named Alice to enable the
|RTI_SP_PRODUCT|. This profile inherits from the builtin profile,
``BuiltinQosLib::Generic.Security``, which tells your |DP| to
enable the |RTI_SP_PRODUCT|. (See :link_connext_dds_secure_um:`Properties for Enabling Security
<p2_core/building_apps.html#properties-for-enabling-security>`)
in the |SP_UM|. We can instead
use the ``BuiltinQosLib::Generic.Common`` profile to have an application that
does not load the |RTI_SP_PRODUCT|.

We will also need to force communication over UDPv4 to capture traffic using
Wireshark. We need to do this because, by default, applications running on the
same machine will communicate using shared memory (for more details, see
:link_external_community_kb:`How to capture traffic if my Connext DDS applications are
communicating through shared memory
<how-capture-traffic-if-my-connext-dds-applications-are-communicating-through-shared-memory>`
from our Knowledge Base).


#. Modify :file:`USER_QOS_PROFILES.xml` to load the
   ``BuiltinQosLib::Generic.Common`` profile and force communication over the
   UDPv4 transport protocol:

   .. code-block:: xml

      <qos_profile name="Alice" base_name="BuiltinQosLib::Generic.Common" is_default_qos="true">
           <domain_participant_qos>
              <!-- Disable shared memory to capture UDP packets on Wireshark -->
              <transport_builtin>
                  <mask>UDPv4</mask>
              </transport_builtin>
              ...

   Please note that this change affects both the publisher and subscriber
   applications. |br| |br|

#. Change your publisher's source code to send a message that we will read using
   Wireshark:

   .. only:: cpp98

      .. literalinclude:: snippets/snippets.py
         :language: C++
         :start-after: snippet_cpp98_PatientMonitoring_publisher_actual_data
         :end-before: """

      After this step, you will need to rebuild your project (see
      :ref:`section-sec-HO1-linking-your-applications`).

   .. only:: cpp11

      .. literalinclude:: snippets/snippets.py
         :language: C++
         :start-after: snippet_cpp11_PatientMonitoring_publisher_actual_data
         :end-before: """

      After this step, you will need to rebuild your project (see
      :ref:`section-sec-HO1-linking-your-applications`).


Analyzing RTPS Packets in Wireshark
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#. Open Wireshark and start capturing packets on the loopback interface [#]_.
   Alternatively, you may want to use another interface if your publisher and
   subscriber applications are on different machines [#]_. To filter out packets
   that are not related to your applications, apply the following display
   filter:

   .. code-block:: text

      rtps.domain_id == 1

   .. note::

      In most cases, you want to start capturing packets before you start your
      DDS applications. This way, you will be able to analyze the communication
      from the beginning, including DDS Discovery traffic.

#. Run your publisher and subscriber as explained in
   :ref:`section-sec-HO1-running-applications`. Specify |DOMAIN| *1* with the
   :command:`-d` option in the command line. You should see communication:


   .. only:: cpp98

      .. tabs::

         .. group-tab:: Linux

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp98_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp98_d1_actual_data
               :end-before: """

         .. group-tab:: macOS

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp98_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp98_d1_actual_data
               :end-before: """

         .. group-tab:: Windows

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_publisher_cpp98_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_subscriber_cpp98_d1_actual_data
               :end-before: """

   .. only:: cpp11

      .. tabs::

         .. group-tab:: Linux

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp11_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp11_d1_actual_data
               :end-before: """

         .. group-tab:: macOS

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp11_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp11_d1_actual_data
               :end-before: """

         .. group-tab:: Windows

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_publisher_cpp11_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_subscriber_cpp11_d1_actual_data
               :end-before: """


#. In the Wireshark capture, you should see a series of RTPS packets, as shown
   in the following screenshot. You can see the DDS data samples by looking at
   the *serializedData* field of :submsg:`DATA` submessages. Since the current
   scenario does not load the |RTI_SP_PRODUCT|, security is completely disabled and the
   payload can be decoded as ASCII plaintext.

   .. figure:: static/Wireshark01.png
      :scale: 73%
      :alt:
      :name: FigureWireshark01
      :align: center

      Wireshark capture of unprotected communication. The payload can be decoded
      as ASCII plaintext.

If we focus on the structure of captured packets, we can see that RTPS messages
consist of a *header* and one or several *submessages*. In turn, every
submessage has its *header*, *metadata*, and *contents*. In the previous
screenshot, we can see a :submsg:`DATA` submessage with some *Flags* in its
header, then some metadata such as the *writerEntityId*, and finally, its
serialized payload for the content. The following diagram outlines the structure
of an unprotected RTPS packet.

.. figure:: /../shared_content/static/unprotected-data-submsg.png
   :scale: 50%
   :alt:
   :name: FigureUnprotectedDia
   :align: center

   Structure of an unprotected RTPS packet.

When our application uses security, the contents of the RTPS packets will show
some differences. For example, cryptographic metadata will be added around the
protected parts, which may be encrypted depending on the configured protection.
For further details, see :link_connext_dds_secure_um:`Securing DDS Messages on The Wire
<p2_core/cryptography.html#securing-dds-messages-on-the-wire>`
in the |SP_UM|.

.. [#] Recording on the loopback interface on a Windows system may require
   additional software (see :link_external_community_kb:`How to capture traffic from the
   loopback interface using Wireshark in Windows
   <how-capture-traffic-loopback-interface-using-wireshark-windows>` from our
   Knowledge Base).

.. [#] The screenshots in this Hands-On show the publisher and subscriber
   running on two different machines (with different IP addresses). We have
   edited the *Resolved Name* in Wireshark to better identify the applications.
   If the publisher and subscriber run on the same machine, you can still
   differentiate them by looking at the UDP ports.

.. _section-sec-HO5-encrypting-serialized-payload:

Encrypting the Serialized Payload
---------------------------------

In the previous section, you configured your |DPs| so they did
not load the |RTI_SP_PRODUCT|, making *PatientMonitoring* data vulnerable to
eavesdropping and tampering attacks. In this section, we will analyze the
effects that encrypting the payload has on the RTPS packets.

#. Modify :file:`USER_QOS_PROFILES.xml` to load the
   ``BuiltinQosLib::Generic.Security`` profile:

   .. code-block:: xml

      <qos_profile name="Alice" base_name="BuiltinQosLib::Generic.Security" is_default_qos="true">
           <domain_participant_qos>
           ...

   Please note that this change affects both the publisher and subscriber
   applications. |br| |br|

#. Make sure that this profile loads the |GovernanceDoc| that we defined in
   :ref:`section-sec-HO2`, which configures payload protection by setting the
   :xmltag:`data_protection_kind` to :xmlval:`ENCRYPT`.

Analyzing RTPS Packets in Wireshark
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#. Rerun your publisher and subscriber as explained in
   :ref:`section-sec-HO1-running-applications`. Specify |DOMAIN| *1* with the
   :command:`-d` option in the command line. You should see communication:

   .. only:: cpp98

      .. tabs::

         .. group-tab:: Linux

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp98_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp98_d1_actual_data
               :end-before: """

         .. group-tab:: macOS

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp98_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp98_d1_actual_data
               :end-before: """

         .. group-tab:: Windows

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_publisher_cpp98_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_subscriber_cpp98_d1_actual_data
               :end-before: """

   .. only:: cpp11

      .. tabs::

         .. group-tab:: Linux

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp11_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp11_d1_actual_data
               :end-before: """

         .. group-tab:: macOS

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp11_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp11_d1_actual_data
               :end-before: """

         .. group-tab:: Windows

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_publisher_cpp11_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_subscriber_cpp11_d1_actual_data
               :end-before: """


#. Go back to Wireshark and look at the *serializedData* field of :submsg:`DATA`
   submessages. You can check that the payload is now encrypted. Therefore it
   cannot be decoded as ASCII plaintext and trying to do so results in garbled
   output, as seen here:

   .. figure:: static/Wireshark02.png
      :scale: 73%
      :alt: 
      :name: FigureWireshark02
      :align: center

      Wireshark capture of communication protected with
      :xmltag:`data_protection_kind` set to :xmlval:`ENCRYPT`. The payload is
      encrypted.

Notice that the length of the data field has increased. The reason is that the
*serializedData* field now includes a header and a footer with cryptographic
information. The *CryptoHeader* includes information such as an identifier for
the key used to encrypt the payload. The *CryptoFooter* includes the generated
message authentication code (MAC). This additional information allows the
receiver to decrypt the message and verify its integrity.
For further details, see :link_connext_dds_secure_um:`Securing DDS Messages on The Wire
<p2_core/cryptography.html#securing-dds-messages-on-the-wire>`
in the |SP_UM|.

You may also notice that the field named *encapsulation options* has changed to
``0x0002``. Although a *CryptoHeader* is now at the beginning of the
*serializedData*, Wireshark does not have enough information to parse it. In
fact, Wireshark does not know whether or not the *serializedData* is encrypted.
For this reason, it always displays the *encapsulation header* (*encapsulation
kind* and *encapsulation options*) at the beginning of the *serializedData*
field. In this case, the payload is encrypted and these four bytes correspond to
the *transformation kind* field in the *CryptoHeader*, where ``0x00000002``
means that the AES-128 GCM transformation has been applied (the default for
:xmlval:`ENCRYPT`).

The following diagram depicts the structure of an RTPS packet protected with
payload encryption:

.. figure:: /../shared_content/static/data-protection.png
   :scale: 50%
   :alt:
   :name: FigurePayloadProtectionDia
   :align: center

   Structure of an RTPS packet with payload protection kinds, configured by the
   ``<data_protection_kind>`` rule.

Congratulations! You have verified that your payload is safe from a potential
eavesdropper in your network.

.. _section-sec-HO5-troubleshooting:

Troubleshooting
---------------

* My Wireshark captures are hard to read because message-type coloring is not
  active:

  Make sure that your Wireshark contains the coloring rules for the RTPS
  protocol (see :link_external_community_howto:`How To configure Wireshark to show RTPS
  packets with specific colors
  <how-configure-wireshark-show-rtps-packets-specific-colors>`
  from our Knowledge Base). |br| |br|

* When I run the publisher/subscriber, they don't communicate:

  Make sure that the |GovernanceDoc| is the same for both applications
  (publisher and subscriber). Otherwise, communication won't work. Remember to
  sign the |GovernanceDoc| after modifying it and to restart your applications
  so changes take effect (see
  :ref:`section-sec-HO2-signing-governance-file`). |br| |br|

* When I run the publisher/subscriber, I get this error:

  .. code-block:: text

     RTI_Security_AccessControl_create_participant:participant not allowed: no rule found; default DENY

  Make sure your applications are running in the allowed domain, in this case
  |DOMAIN| *1* (requirement from :ref:`section-sec-HO3`). |br| |br|

* When I run the publisher/subscriber, I get this error:

  .. code-block:: text

     RTI_Security_AccessControl_validate_remote_permissions:failed to validate permissions

  Make sure both your publisher and subscriber have permissions signed by the
  same Permissions CA. |br| |br|

* When I run the publisher/subscriber, I get this error:

  .. code-block:: text

     RTI_Security_AccessControl_get_participant_sec_attributes:failed to verify governance document signature

  Make sure that the |GovernanceDoc| has been signed by the right Permissions
  CA. |br| |br|

* I cannot capture traffic from the loopback interface on a Windows system:

  Recording on the loopback interface on a Windows system may require additional
  software (see :link_external_community_kb:`How to capture traffic from the loopback
  interface using Wireshark in Windows
  <how-capture-traffic-loopback-interface-using-wireshark-windows>` from our
  Knowledge Base).
