.. 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_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_community_howto:`How To configure Wireshark to show RTPS packets with 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 |SP|. This profile inherits from the builtin profile, ``BuiltinQosLib::Generic.Security``, which tells your |DP| to enable the |SP|. (See :link_sec_um:`Properties for Enabling Security in the RTI Security Plugins User's Manual `). We can instead use the ``BuiltinQosLib::Generic.Common`` profile to have an application that does not load the |SP|. 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_community_kb:`How to 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 UDPv4 ... 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 |SP|, 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_sec_um:`Securing DDS Messages on The Wire in the Security Plugins User's Manual `. .. [#] Recording on the loopback interface on a Windows system may require additional software (see :link_community_kb:`How to capture traffic from the loopback interface using Wireshark in 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 |SP|, 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 ... Please note that this change affects both the publisher and subscriber applications. |br| |br| #. Make sure that this profile loads the |GovernanceFile| 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_sec_um:`Securing DDS Messages on The Wire in the Security Plugins User's Manual `. 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 AES128 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 ```` 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_community_howto:`How To configure Wireshark to show RTPS packets with specific colors ` from our Knowledge Base). |br| |br| * When I run the publisher/subscriber, they don't communicate: Make sure that the |GovernanceFile| is the same for both applications (publisher and subscriber). Otherwise, communication won't work. Remember to sign the |GovernanceFile| 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 |GovernanceFile| 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_community_kb:`How to capture traffic from the loopback interface using Wireshark in Windows ` from our Knowledge Base).