diff --git a/source/index.md b/source/index.md index 502e450c34..5b6f82fc28 100644 --- a/source/index.md +++ b/source/index.md @@ -39,6 +39,7 @@ - [Retryable Writes](retryable-writes/retryable-writes.md) - [Run Command](run-command/run-command.md) - [SDAM Logging and Monitoring Specification](server-discovery-and-monitoring/server-discovery-and-monitoring-logging-and-monitoring.md) +- [SOCKS5 Support](socks5-support/socks5.md) - [Server Discovery And Monitoring](server-discovery-and-monitoring/server-discovery-and-monitoring.md) - [Server Discovery And Monitoring -- Summary](server-discovery-and-monitoring/server-discovery-and-monitoring-summary.md) - [Server Discovery And Monitoring -- Test Plan](server-discovery-and-monitoring/server-discovery-and-monitoring-tests.md) diff --git a/source/socks5-support/socks5.md b/source/socks5-support/socks5.md index abfdb53f6d..df1f88c98a 100644 --- a/source/socks5-support/socks5.md +++ b/source/socks5-support/socks5.md @@ -1,188 +1,132 @@ -============== -SOCKS5 Support -============== +# SOCKS5 Support -:Status: Accepted -:Minimum Server Version: N/A +- Status: Accepted +- Minimum Server Version: N/A -.. contents:: +______________________________________________________________________ --------- +## Abstract -Abstract -======== +SOCKS5 is a standardized protocol for connecting to network services through a separate proxy server. It can be used for +connecting to hosts that would otherwise be unreachable from the local network by connecting to a proxy server, which +receives the intended target host's address from the client and then connects to that address. -SOCKS5 is a standardized protocol for connecting to network services through -a separate proxy server. It can be used for connecting to hosts that would -otherwise be unreachable from the local network by connecting to a proxy -server, which receives the intended target host’s address from the client -and then connects to that address. +This specification defines driver behaviour when connecting to MongoDB services through a SOCKS5 proxy. -This specification defines driver behaviour when connecting to MongoDB services -through a SOCKS5 proxy. +## META -META -==== +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and +"OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). -The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", -"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be -interpreted as described in `RFC 2119 `__. +## Specification -Specification -============= +### Terms +#### SOCKS5 -Terms ------ +The SOCKS protocol, version 5, as defined in [RFC1928](https://datatracker.ietf.org/doc/html/rfc1928), restricted to +either no authentication or username/password authentication as defined in +[RFC1929](https://datatracker.ietf.org/doc/html/rfc1929). -SOCKS5 -^^^^^^ +### MongoClient Configuration -The SOCKS protocol, version 5, as defined in `RFC1928 `__, -restricted to either no authentication or username/password authentication -as defined in `RFC1929 `__. +#### proxyHost +To specify to the driver to connect using a SOCKS5 proxy, a connection string option of `proxyHost=host` MUST be added +to the connection string or passed through an equivalent `MongoClient` option. This option specifies a domain name or +IPv4 or IPv6 address on which a SOCKS5 proxy is listening. This option MUST only be configurable at the level of a +`MongoClient`. -MongoClient Configuration -------------------------- +#### proxyPort -proxyHost -^^^^^^^^^ +To specify to the driver to connect using a SOCKS5 proxy listening on a non-default port, a connection string option of +`proxyPort=port` MUST be added to the connection string or passed through an equivalent `MongoClient` option. This +option specifies a TCP port number. The default for this option MUST be `1080`. This option MUST only be configurable at +the level of a `MongoClient`. Drivers MUST error if this option was specified and `proxyHost` was not specified. -To specify to the driver to connect using a SOCKS5 proxy, a connection string -option of :code:`proxyHost=host` MUST be added to the connection string -or passed through an equivalent :code:`MongoClient` option. -This option specifies a domain name or IPv4 or IPv6 address on which -a SOCKS5 proxy is listening. -This option MUST only be configurable at the level of a :code:`MongoClient`. +#### proxyUsername -proxyPort -^^^^^^^^^ +To specify to the driver to connect using a SOCKS5 proxy requiring username/password authentication, a connection string +option of - Code:`proxyUsername=username` MUST be added to the connection string or passed through an equivalent +`MongoClient` option. This option specifies a string of non-zero length. Drivers MUST ignore this option if it specifies +a zero-length string. Drivers MUST error if this option was specified and `proxyHost` was not specified or +`proxyPassword` was not specified. -To specify to the driver to connect using a SOCKS5 proxy listening -on a non-default port, a connection string option of :code:`proxyPort=port` -MUST be added to the connection string or passed through an -equivalent :code:`MongoClient` option. -This option specifies a TCP port number. The default for this option -MUST be :code:`1080`. -This option MUST only be configurable at the level of a :code:`MongoClient`. -Drivers MUST error if this option was specified and :code:`proxyHost` -was not specified. +#### proxyPassword -proxyUsername -^^^^^^^^^^^^^ +To specify to the driver to connect using a SOCKS5 proxy requiring username/password authentication, a connection string +option of - Code:`proxyPassword=password` MUST be added to the connection string or passed through an equivalent +`MongoClient` option. This option specifies a string of non-zero length. Drivers MUST ignore this option if it specifies +a zero-length string. Drivers MUST error if this option was specified and `proxyHost` was not specified or +`proxyUsername` was not specified. -To specify to the driver to connect using a SOCKS5 proxy requiring -username/password authentication, a connection string option of -:code:`proxyUsername=username` MUST be added to the connection string -or passed through an equivalent :code:`MongoClient` option. -This option specifies a string of non-zero length. Drivers MUST ignore -this option if it specifies a zero-length string. Drivers MUST error -if this option was specified and :code:`proxyHost` was not specified -or :code:`proxyPassword` was not specified. +### Connection Pooling -proxyPassword -^^^^^^^^^^^^^ +#### Connection Establishment -To specify to the driver to connect using a SOCKS5 proxy requiring -username/password authentication, a connection string option of -:code:`proxyPassword=password` MUST be added to the connection string -or passed through an equivalent :code:`MongoClient` option. -This option specifies a string of non-zero length. Drivers MUST ignore -this option if it specifies a zero-length string. Drivers MUST error -if this option was specified and :code:`proxyHost` was not specified -or :code:`proxyUsername` was not specified. +When establishing a new outgoing TCP connection, drivers MUST perform the following steps if `proxyHost` was specified: -Connection Pooling ------------------------- +1. Connect to the SOCKS5 proxy host, using `proxyHost` and `proxyPort` as specified. -Connection Establishment -^^^^^^^^^^^^^^^^^^^^^^^^ +2. Perform a SOCKS5 handshake as specified in RFC1928. -When establishing a new outgoing TCP connection, drivers MUST perform -the following steps if :code:`proxyHost` -was specified: + > If `proxyUsername` and `proxyPassword` were passed, drivers MUST indicate in the handshake that both "no + > authentication" and "username/password authentication" are supported. Otherwise, drivers MUST indicate support for + > "no authentication" only. + > + > Drivers MUST NOT attempt to perform DNS A or AAAA record resolution of the destination hostname and instead pass + > the hostname to the proxy as-is. -#. Connect to the SOCKS5 proxy host, using :code:`proxyHost` and :code:`proxyPort` as specified. +3. Continue with connection establishment as if the connection was one to the destination host. -#. Perform a SOCKS5 handshake as specified in RFC1928. +Drivers MUST use the SOCKS5 proxy for connections to MongoDB services and +[client-side field-level encryption KMS servers](../client-side-encryption/client-side-encryption.md#kms-provider). - If :code:`proxyUsername` and :code:`proxyPassword` were passed, - drivers MUST indicate in the handshake that both "no authentication" - and "username/password authentication" are supported. Otherwise, - drivers MUST indicate support for "no authentication" only. +Drivers MUST NOT use the SOCKS5 proxy for connections to - Code:`mongocryptd` processes spawned for automatic +client-side field-level encryption. - Drivers MUST NOT attempt to perform DNS A or AAAA record resolution - of the destination hostname and instead pass the hostname to the - proxy as-is. +Drivers MUST treat a connection failure when connecting to the SOCKS5 proxy or a SOCKS5 handshake or authentication +failure the same as a network error (e.g. `ECONNREFUSED`). -#. Continue with connection establishment as if the connection was one - to the destination host. +### Events -Drivers MUST use the SOCKS5 proxy for connections to MongoDB services -and `client-side field-level encryption KMS servers <../client-side-encryption/client-side-encryption.md#kms-provider>`__. +SOCKS5 proxies are fully transparent to connection monitoring events. In particular, in `CommandStartedEvent`, +`CommandSucceededEvent`, and - Code:`CommandFailedEvent`, the driver SHOULD NOT reference the SOCKS5 proxy as part of +the `connectionId` field or other fields. -Drivers MUST NOT use the SOCKS5 proxy for connections to -:code:`mongocryptd` processes spawned for automatic client-side field-level encryption. +### Q&A -Drivers MUST treat a connection failure when connecting to the SOCKS5 -proxy or a SOCKS5 handshake or authentication failure the same as a -network error (e.g. `ECONNREFUSED`). +#### Why not include DNS requests in the set of proxied network communication? -Events ------- +While SOCKS5 as a protocol does support UDP forwarding, using this feature has a number of downsides. Notably, only a +subset of SOCKS5 client libraries and SOCKS5 server implementations support UDP forwarding (e.g. the OpenSSH client's +dynamic forwarding feature does not). This would also considerably increase implementation complexity in drivers that do +not use DNS libraries in which the driver is in control of how the UDP packets are sent and received. -SOCKS5 proxies are fully transparent to connection monitoring events. -In particular, in :code:`CommandStartedEvent`, :code:`CommandSucceededEvent`, and -:code:`CommandFailedEvent`, the driver SHOULD NOT reference the SOCKS5 -proxy as part of the :code:`connectionId` field or other fields. +#### Why not support other proxy protocols, such as Socks4/Socks4a, HTTP Connect proxies, etc.? -Q&A ---- +SOCKS5 is a powerful, standardized and widely used proxy protocol. It is likely that almost all users which require +tunneling/proxying of some sort will be able to use it, and those who require another protocol or a more advanced setup +like proxy chaining, can work around that by using a local SOCKS5 intermediate proxy. -Why not include DNS requests in the set of proxied network communication? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -While SOCKS5 as a protocol does support UDP forwarding, using this feature has a number -of downsides. Notably, only a subset of SOCKS5 client libraries and SOCKS5 server -implementations support UDP forwarding (e.g. the OpenSSH client’s dynamic -forwarding feature does not). This would also considerably increase implementation -complexity in drivers that do not use DNS libraries in which the driver is -in control of how the UDP packets are sent and received. - -Why not support other proxy protocols, such as Socks4/Socks4a, HTTP Connect proxies, etc.? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -SOCKS5 is a powerful, standardized and widely used proxy protocol. It is likely that -almost all users which require tunneling/proxying of some sort will be able to use it, -and those who require another protocol or a more advanced setup like proxy chaining, -can work around that by using a local SOCKS5 intermediate proxy. - -Why are the connection string parameters generic, with no explicit mention of SOCKS5? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In the case that future changes will enable drivers using other proxy protocols, -keeping the option names generic allows their re-use. -In that case, another option would specify the protocol and SOCKS5 would be the -implied default. However, since there is no reason to believe that such additions -will be made in the foreseeable future, no option for specifying the proxy protocol -is introduced here. +#### Why are the connection string parameters generic, with no explicit mention of SOCKS5? -Why is support for authentication methods limited to no authentication and username/password authentication? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In the case that future changes will enable drivers using other proxy protocols, keeping the option names generic allows +their re-use. In that case, another option would specify the protocol and SOCKS5 would be the implied default. However, +since there is no reason to believe that such additions will be made in the foreseeable future, no option for specifying +the proxy protocol is introduced here. -This matches the set of authentication methods most commonly implemented by SOCKS5 -client libraries and thus reduces implementation complexity for drivers. -This advantage is sufficient to ignore the possible advantages that would -come with enabling other authentication methods. +#### Why is support for authentication methods limited to no authentication and username/password authentication? -Design Rationales ------------------ +This matches the set of authentication methods most commonly implemented by SOCKS5 client libraries and thus reduces +implementation complexity for drivers. This advantage is sufficient to ignore the possible advantages that would come +with enabling other authentication methods. -Alternative Designs -------------------- +### Design Rationales -Changelog -========= +### Alternative Designs -:2022-10-05: Remove spec front matter +## Changelog + +- 2024-09-04: Migrated from reStructuredText to Markdown. +- 2022-10-05: Remove spec front matter diff --git a/source/socks5-support/socks5.rst b/source/socks5-support/socks5.rst new file mode 100644 index 0000000000..269e2c9a8b --- /dev/null +++ b/source/socks5-support/socks5.rst @@ -0,0 +1,4 @@ + +.. note:: + This specification has been converted to Markdown and renamed to + `socks5.md `_. diff --git a/source/socks5-support/tests/README.md b/source/socks5-support/tests/README.md index e8781eb532..42ee9ff69c 100644 --- a/source/socks5-support/tests/README.md +++ b/source/socks5-support/tests/README.md @@ -1,86 +1,53 @@ -==================== -SOCKS5 Support Tests -==================== +# SOCKS5 Support Tests -.. contents:: +______________________________________________________________________ ----- - -Introduction -============ +## Introduction This document describes how drivers should test support for SOCKS5 proxies. -Testing Requirements -==================== +## Testing Requirements -For a single server version (at least 5.0), drivers MUST add two -Evergreen tasks: one with a replica set with TLS enabled, and one -with TLS disabled. The servers of the replica set may listen on any free ports. +For a single server version (at least 5.0), drivers MUST add two Evergreen tasks: one with a replica set with TLS +enabled, and one with TLS disabled. The servers of the replica set may listen on any free ports. -Each task MUST also start up two SOCKS5 proxies: one requiring authentication, -and one that does not require authentication. +Each task MUST also start up two SOCKS5 proxies: one requiring authentication, and one that does not require +authentication. -SOCKS5 Proxy Configuration --------------------------- +### SOCKS5 Proxy Configuration -Drivers MUST use the ``socks5srv.py`` script in ``drivers-evergreen-tools`` -to run the SOCKS5 proxy servers for Evergreen tasks. This script MUST -be run after the backing replica set has already been started, -and MUST be started with ``--map "localhost:12345 to "` where -``host` is the host:port identifier of an arbitrary member of the replica set. -The SOCKS5 proxy server requiring authentication MUST be started with -``--port 1080 --auth username:p4ssw0rd`, the one not requiring authentication -with `--port 1081``. +Drivers MUST use the `socks5srv.py` script in `drivers-evergreen-tools` to run the SOCKS5 proxy servers for Evergreen +tasks. This script MUST be run after the backing replica set has already been started, and MUST be started with +`` --map "localhost:12345 to "` where `host` is the host:port identifier of an arbitrary member of the replica set. The SOCKS5 proxy server requiring authentication MUST be started with `` +--port 1080 --auth username:p4ssw0rd`, the one not requiring authentication with `--port 1081 \`\`. -Prose Tests -=========== +## Prose Tests Drivers MUST test the following connection strings: -.. list-table:: - :header-rows: 1 - - * - Connection String - - Expected Result - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1080&directConnection=true` - - (fails) - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1081&directConnection=true` - - (succeeds) - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1080` - - (fails) - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1081` - - (succeeds) - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1080&proxyUsername=nonexistentuser&proxyPassword=badauth&directConnection=true` - - (fails) - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1081&proxyUsername=nonexistentuser&proxyPassword=badauth&directConnection=true` - - (succeeds) - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1081&proxyUsername=nonexistentuser&proxyPassword=badauth` - - (succeeds) - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1080&proxyUsername=username&proxyPassword=p4ssw0rd&directConnection=true` - - (succeeds) - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1081&directConnection=true` - - (succeeds) - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1080&proxyUsername=username&proxyPassword=p4ssw0rd` - - (succeeds) - * - :code:`mongodb:///?proxyHost=localhost&proxyPort=1081` - - (succeeds) - -where :code:`` stands for all hosts in the tests replica set -and :code:`mappedhost` stands for :code:`localhost:12345`. For the -Evergreen task in which TLS is enabled, the required :code:`tls` and -:code:`tlsCAFile` connection string options are appended to all connection strings -listed above. - -Drivers MUST create a :code:`MongoClient` for each of these connection strings, -and attempt to run a :code:`hello` command using each client. -The operation must succeed for table entries marked (succeeds) and fail -for table entries marked (fails). The connection strings MUST all -be accepted as valid connection strings. - -Drivers MUST run variants of these tests in which the proxy options are -substituted for :code:`MongoClient` options. - -Drivers MUST verify for at least one of the connection strings -marked (succeeds) that command monitoring events do not reference the -SOCKS5 proxy host where the MongoDB service server/port are referenced. +| Connection String | Expected Result | +| -------------------------------------------------------------------------------------------------------------------------------------- | --------------- | +| `mongodb:///?proxyHost=localhost&proxyPort=1080&directConnection=true` | (fails) | +| `mongodb:///?proxyHost=localhost&proxyPort=1081&directConnection=true` | (succeeds) | +| `mongodb:///?proxyHost=localhost&proxyPort=1080` | (fails) | +| `mongodb:///?proxyHost=localhost&proxyPort=1081` | (succeeds) | +| `mongodb:///?proxyHost=localhost&proxyPort=1080&proxyUsername=nonexistentuser&proxyPassword=badauth&directConnection=true` | (fails) | +| `mongodb:///?proxyHost=localhost&proxyPort=1081&proxyUsername=nonexistentuser&proxyPassword=badauth&directConnection=true` | (succeeds) | +| `mongodb:///?proxyHost=localhost&proxyPort=1081&proxyUsername=nonexistentuser&proxyPassword=badauth` | (succeeds) | +| `mongodb:///?proxyHost=localhost&proxyPort=1080&proxyUsername=username&proxyPassword=p4ssw0rd&directConnection=true` | (succeeds) | +| `mongodb:///?proxyHost=localhost&proxyPort=1081&directConnection=true` | (succeeds) | +| `mongodb:///?proxyHost=localhost&proxyPort=1080&proxyUsername=username&proxyPassword=p4ssw0rd` | (succeeds) | +| `mongodb:///?proxyHost=localhost&proxyPort=1081` | (succeeds) | + +where `` stands for all hosts in the tests replica set and `mappedhost` stands for `localhost:12345`. For +the Evergreen task in which TLS is enabled, the required `tls` and - Code:`tlsCAFile` connection string options are +appended to all connection strings listed above. + +Drivers MUST create a `MongoClient` for each of these connection strings, and attempt to run a `hello` command using +each client. The operation must succeed for table entries marked (succeeds) and fail for table entries marked (fails). +The connection strings MUST all be accepted as valid connection strings. + +Drivers MUST run variants of these tests in which the proxy options are substituted for `MongoClient` options. + +Drivers MUST verify for at least one of the connection strings marked (succeeds) that command monitoring events do not +reference the SOCKS5 proxy host where the MongoDB service server/port are referenced. diff --git a/source/uri-options/uri-options.md b/source/uri-options/uri-options.md index 2e636cc812..2432a65383 100644 --- a/source/uri-options/uri-options.md +++ b/source/uri-options/uri-options.md @@ -57,7 +57,7 @@ For URI option validation in Load Balancer mode (i.e. `loadBalanced=true`), plea ### SOCKS5 options For URI option validation pertaining to `proxyHost`, `proxyPort`, `proxyUsername` and `proxyPassword` please see the -[SOCKS5 support spec](../socks5-support/socks5.rst#mongoclient-configuration) for details. +[SOCKS5 support spec](../socks5-support/socks5.md#mongoclient-configuration) for details. ### List of specified options @@ -88,10 +88,10 @@ to URI options apply here. | maxConnecting | positive integer | defined in the [Connection Pooling spec](../connection-monitoring-and-pooling/connection-monitoring-and-pooling.md#connection-pool-options-1) | required for drivers with connection pools | The maximum number of Connections a Pool may be establishing concurrently. | | maxStalenessSeconds | -1 (no max staleness check) or integer >= 90 | defined in [max staleness spec](../max-staleness/max-staleness.md#api) | no | The maximum replication lag, in wall clock time, that a secondary can suffer and still be eligible for server selection | | minPoolSize | non-negative integer | defined in the [Connection Pooling spec](../connection-monitoring-and-pooling/connection-monitoring-and-pooling.md#connection-pool-options-1) | required for drivers with connection pools | The number of connections the driver should create and maintain in the pool even when no operations are occurring. This count includes connections which are currently checked out. | -| proxyHost | any string | defined in the [SOCKS5 support spec](../socks5-support/socks5.rst#mongoclient-configuration) | no | The IPv4/IPv6 address or domain name of a SOCKS5 proxy server used for connecting to MongoDB services. | -| proxyPort | non-negative integer | defined in the [SOCKS5 support spec](../socks5-support/socks5.rst#mongoclient-configuration) | no | The port of the SOCKS5 proxy server specified in `proxyHost`. | -| proxyUsername | any string | defined in the [SOCKS5 support spec](../socks5-support/socks5.rst#mongoclient-configuration) | no | The username for username/password authentication to the SOCKS5 proxy server specified in `proxyHost`. | -| proxyPassword | any string | defined in the [SOCKS5 support spec](../socks5-support/socks5.rst#mongoclient-configuration) | no | The password for username/password authentication to the SOCKS5 proxy server specified in `proxyHost`. | +| proxyHost | any string | defined in the [SOCKS5 support spec](../socks5-support/socks5.md#mongoclient-configuration) | no | The IPv4/IPv6 address or domain name of a SOCKS5 proxy server used for connecting to MongoDB services. | +| proxyPort | non-negative integer | defined in the [SOCKS5 support spec](../socks5-support/socks5.md#mongoclient-configuration) | no | The port of the SOCKS5 proxy server specified in `proxyHost`. | +| proxyUsername | any string | defined in the [SOCKS5 support spec](../socks5-support/socks5.md#mongoclient-configuration) | no | The username for username/password authentication to the SOCKS5 proxy server specified in `proxyHost`. | +| proxyPassword | any string | defined in the [SOCKS5 support spec](../socks5-support/socks5.md#mongoclient-configuration) | no | The password for username/password authentication to the SOCKS5 proxy server specified in `proxyHost`. | | readConcernLevel | any string ([to allow for forwards compatibility with the server](../read-write-concern/read-write-concern.md#unknown-levels-and-additional-options-for-string-based-readconcerns)) | no read concern specified | no | Default read concern for the client | | readPreference | any string; currently supported values are defined in the [server selection spec](../server-selection/server-selection.md#mode), but must be lowercase camelCase, e.g. "primaryPreferred" | defined in [server selection spec](../server-selection/server-selection.md#mode) | no | Default read preference for the client (excluding tags) | | readPreferenceTags | comma-separated key:value pairs (e.g. "dc:ny,rack:1" and "dc:ny)

can be specified multiple times; each instance of this key is a separate tag set | no tags specified | no | Default read preference tags for the client; only valid if the read preference mode is not primary

The order of the tag sets in the read preference is the same as the order they are specified in the URI |