|  | 
|  | 1 | +# Initial DNS Seedlist Discovery | 
|  | 2 | + | 
|  | 3 | +- Status: Accepted | 
|  | 4 | +- Minimum Server Version: N/A | 
|  | 5 | + | 
|  | 6 | +______________________________________________________________________ | 
|  | 7 | + | 
|  | 8 | +## Abstract | 
|  | 9 | + | 
|  | 10 | +Presently, seeding a driver with an initial list of ReplicaSet or MongoS addresses is somewhat cumbersome, requiring a | 
|  | 11 | +comma-delimited list of host names to attempt connections to. A standardized answer to this problem exists in the form | 
|  | 12 | +of SRV records, which allow administrators to configure a single SRV record to return a list of host names. Supporting | 
|  | 13 | +this feature would assist our users by decreasing maintenance load, primarily by removing the need to maintain seed | 
|  | 14 | +lists at an application level. | 
|  | 15 | + | 
|  | 16 | +This specification builds on the [Connection String](../connection-string/connection-string-spec.md) specification. It | 
|  | 17 | +adds a new protocol scheme and modifies how the | 
|  | 18 | +[Host Information](../connection-string/connection-string-spec.md#host-information) is interpreted. | 
|  | 19 | + | 
|  | 20 | +## META | 
|  | 21 | + | 
|  | 22 | +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and | 
|  | 23 | +"OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). | 
|  | 24 | + | 
|  | 25 | +## Specification | 
|  | 26 | + | 
|  | 27 | +### Connection String Format | 
|  | 28 | + | 
|  | 29 | +The connection string parser in the driver is extended with a new protocol `mongodb+srv` as a logical pre-processing | 
|  | 30 | +step before it considers the connection string and SDAM specifications. In this protocol, the comma separated list of | 
|  | 31 | +host names is replaced with a single host name. The format is: | 
|  | 32 | + | 
|  | 33 | +``` | 
|  | 34 | +mongodb+srv://{hostname}/{options}  | 
|  | 35 | +``` | 
|  | 36 | + | 
|  | 37 | +`{options}` refers to the optional elements from the [Connection String](../connection-string/connection-string-spec.md) | 
|  | 38 | +specification following the `Host Information`. This includes the `Auth database` and `Connection Options`. | 
|  | 39 | + | 
|  | 40 | +For the purposes of this document, `{hostname}` will be divided using the following terminology. If an SRV `{hostname}` | 
|  | 41 | +has: | 
|  | 42 | + | 
|  | 43 | +1. Three or more `.` separated parts, then the left-most part is the `{subdomain}` and the remaining portion is the | 
|  | 44 | +   `{domainname}`. | 
|  | 45 | + | 
|  | 46 | +    - Examples: | 
|  | 47 | +        - `{hostname}` = `cluster_1.tests.mongodb.co.uk` | 
|  | 48 | + | 
|  | 49 | +            - `{subdomain}` = `cluster_1` | 
|  | 50 | +            - `{domainname}` = `tests.mongodb.co.uk` | 
|  | 51 | + | 
|  | 52 | +        - `{hostname}` = `hosts_34.example.com` | 
|  | 53 | + | 
|  | 54 | +            - `{subdomain}` = `hosts_34` | 
|  | 55 | +            - `{domainname}` = `example.com` | 
|  | 56 | + | 
|  | 57 | +2. One or two `.` separated part(s), then the `{hostname}` is equivalent to the `{domainname}`, and there is no | 
|  | 58 | +   subdomain. | 
|  | 59 | + | 
|  | 60 | +    - Examples: | 
|  | 61 | +        - `{hostname}` = `{domainname}` = `localhost` | 
|  | 62 | +        - `{hostname}` = `{domainname}` = `mongodb.local` | 
|  | 63 | + | 
|  | 64 | +Only `{domainname}` is used during SRV record verification and `{subdomain}` is ignored. | 
|  | 65 | + | 
|  | 66 | +### MongoClient Configuration | 
|  | 67 | + | 
|  | 68 | +#### srvMaxHosts | 
|  | 69 | + | 
|  | 70 | +This option is used to limit the number of mongos connections that may be created for sharded topologies. This option | 
|  | 71 | +limits the number of SRV records used to populate the seedlist during initial discovery, as well as the number of | 
|  | 72 | +additional hosts that may be added during | 
|  | 73 | +[SRV polling](../polling-srv-records-for-mongos-discovery/polling-srv-records-for-mongos-discovery.md). This option | 
|  | 74 | +requires a non-negative integer and defaults to zero (i.e. no limit). This option MUST only be configurable at the level | 
|  | 75 | +of a `MongoClient`. | 
|  | 76 | + | 
|  | 77 | +#### srvServiceName | 
|  | 78 | + | 
|  | 79 | +This option specifies a valid SRV service name according to | 
|  | 80 | +[RFC 6335](https://datatracker.ietf.org/doc/html/rfc6335#section-5.1), with the exception that it may exceed 15 | 
|  | 81 | +characters as long as the 63rd (62nd with prepended underscore) character DNS query limit is not surpassed. This option | 
|  | 82 | +requires a string value and defaults to "mongodb". This option MUST only be configurable at the level of a | 
|  | 83 | +`MongoClient`. | 
|  | 84 | + | 
|  | 85 | +#### URI Validation | 
|  | 86 | + | 
|  | 87 | +The driver MUST report an error if either the `srvServiceName` or `srvMaxHosts` URI options are specified with a non-SRV | 
|  | 88 | +URI (i.e. scheme other than `mongodb+srv`). The driver MUST allow specifying the `srvServiceName` and `srvMaxHosts` URI | 
|  | 89 | +options with an SRV URI (i.e. `mongodb+srv` scheme). | 
|  | 90 | + | 
|  | 91 | +If `srvMaxHosts` is a positive integer, the driver MUST throw an error in the following cases: | 
|  | 92 | + | 
|  | 93 | +- The connection string contains a `replicaSet` option. | 
|  | 94 | +- The connection string contains a `loadBalanced` option with a value of `true`. | 
|  | 95 | + | 
|  | 96 | +When validating URI options, the driver MUST first do the SRV and TXT lookup and then perform the validation. For | 
|  | 97 | +drivers that do SRV lookup asynchronously this may result in a `MongoClient` being instantiated but erroring later | 
|  | 98 | +during operation execution. | 
|  | 99 | + | 
|  | 100 | +### Seedlist Discovery | 
|  | 101 | + | 
|  | 102 | +#### Validation Before Querying DNS | 
|  | 103 | + | 
|  | 104 | +It is an error to specify a port in a connection string with the `mongodb+srv` protocol, and the driver MUST raise a | 
|  | 105 | +parse error and MUST NOT do DNS resolution or contact hosts. | 
|  | 106 | + | 
|  | 107 | +It is an error to specify more than one host name in a connection string with the `mongodb+srv` protocol, and the driver | 
|  | 108 | +MUST raise a parse error and MUST NOT do DNS resolution or contact hosts. | 
|  | 109 | + | 
|  | 110 | +If `mongodb+srv` is used, a driver MUST implicitly also enable TLS. Clients can turn this off by passing `tls=false` in | 
|  | 111 | +either the Connection String, or options passed in as parameters in code to the MongoClient constructor (or equivalent | 
|  | 112 | +API for each driver), but not through a TXT record (discussed in a later section). | 
|  | 113 | + | 
|  | 114 | +#### Querying DNS | 
|  | 115 | + | 
|  | 116 | +In this preprocessing step, the driver will query the DNS server for SRV records on the hostname, prefixed with the SRV | 
|  | 117 | +service name and protocol. The SRV service name is provided in the `srvServiceName` URI option and defaults to | 
|  | 118 | +`mongodb`. The protocol is always `tcp`. After prefixing, the URI should look like: `_{srvServiceName}._tcp.{hostname}`. | 
|  | 119 | +This DNS query is expected to respond with one or more SRV records. | 
|  | 120 | + | 
|  | 121 | +The priority and weight fields in returned SRV records MUST be ignored. | 
|  | 122 | + | 
|  | 123 | +If the DNS result returns no SRV records, or no records at all, or a DNS error happens, an error MUST be raised | 
|  | 124 | +indicating that the URI could not be used to find hostnames. The error SHALL include the reason why they could not be | 
|  | 125 | +found. | 
|  | 126 | + | 
|  | 127 | +A driver MUST verify that the host names returned through SRV records share the original SRV's `{domainname}`. In | 
|  | 128 | +addition, SRV records with fewer than three `.` separated parts, the returned hostname MUST have at least one more | 
|  | 129 | +domain level than the SRV record hostname. Drivers MUST raise an error and MUST NOT initiate a connection to any | 
|  | 130 | +returned hostname which does not fulfill these requirements. | 
|  | 131 | + | 
|  | 132 | +The driver MUST NOT attempt to connect to any hosts until the DNS query has returned its results. | 
|  | 133 | + | 
|  | 134 | +If `srvMaxHosts` is zero or greater than or equal to the number of hosts in the DNS result, the driver MUST populate the | 
|  | 135 | +seedlist with all hosts. | 
|  | 136 | + | 
|  | 137 | +If `srvMaxHosts` is greater than zero and less than the number of hosts in the DNS result, the driver MUST randomly | 
|  | 138 | +select that many hosts and use them to populate the seedlist. Drivers SHOULD use the | 
|  | 139 | +[Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm) for | 
|  | 140 | +randomization. | 
|  | 141 | + | 
|  | 142 | +### Default Connection String Options | 
|  | 143 | + | 
|  | 144 | +As a second preprocessing step, a Client MUST also query the DNS server for TXT records on `{hostname}`. If available, a | 
|  | 145 | +TXT record provides default connection string options. The maximum length of a TXT record string is 255 characters, but | 
|  | 146 | +there can be multiple strings per TXT record. A Client MUST support multiple TXT record strings and concatenate them as | 
|  | 147 | +if they were one single string in the order they are defined in each TXT record. The order of multiple character strings | 
|  | 148 | +in each TXT record is guaranteed. A Client MUST NOT allow multiple TXT records for the same host name and MUST raise an | 
|  | 149 | +error when multiple TXT records are encountered. | 
|  | 150 | + | 
|  | 151 | +Information returned within a TXT record is a simple URI string, just like the `{options}` in a connection string. | 
|  | 152 | + | 
|  | 153 | +A Client MUST only support the `authSource`, `replicaSet`, and `loadBalanced` options through a TXT record, and MUST | 
|  | 154 | +raise an error if any other option is encountered. Although using `mongodb+srv://` implicitly enables TLS, a Client MUST | 
|  | 155 | +NOT allow the `ssl` option to be set through a TXT record option. | 
|  | 156 | + | 
|  | 157 | +TXT records MAY be queried either before, in parallel, or after SRV records. Clients MUST query both the SRV and the TXT | 
|  | 158 | +records before attempting any connection to MongoDB. | 
|  | 159 | + | 
|  | 160 | +A Client MUST use options specified in the Connection String, and options passed in as parameters in code to the | 
|  | 161 | +MongoClient constructor (or equivalent API for each driver), to override options provided through TXT records. | 
|  | 162 | + | 
|  | 163 | +If any connection string option in a TXT record is incorrectly formatted, a Client MUST throw a parse exception. | 
|  | 164 | + | 
|  | 165 | +This specification does not change the behaviour of handling unknown keys or incorrect values as is set out in the | 
|  | 166 | +[Connection String spec](../connection-string/connection-string-spec.md#defining-connection-options). Unknown keys or | 
|  | 167 | +incorrect values in default options specified through TXT records MUST be handled in the same way as unknown keys or | 
|  | 168 | +incorrect values directly specified through a Connection String. For example, if a driver that does not support the | 
|  | 169 | +`authSource` option finds `authSource=db` in a TXT record, it MUST handle the unknown option according to the rules in | 
|  | 170 | +the Connection String spec. | 
|  | 171 | + | 
|  | 172 | +### CNAME not supported | 
|  | 173 | + | 
|  | 174 | +The use of DNS CNAME records is not supported. Clients MUST NOT check for a CNAME record on `{hostname}`. A system's DNS | 
|  | 175 | +resolver could transparently handle CNAME, but because of how clients validate records returned from SRV queries, use of | 
|  | 176 | +CNAME could break validation. Seedlist discovery therefore does not recommend or support the use of CNAME records in | 
|  | 177 | +concert with SRV or TXT records. | 
|  | 178 | + | 
|  | 179 | +## Example | 
|  | 180 | + | 
|  | 181 | +If we provide the following URI: | 
|  | 182 | + | 
|  | 183 | +``` | 
|  | 184 | +mongodb+srv://server.mongodb.com/ | 
|  | 185 | +``` | 
|  | 186 | + | 
|  | 187 | +The driver needs to request the DNS server for the SRV record `_mongodb._tcp.server.mongodb.com`. This could return: | 
|  | 188 | + | 
|  | 189 | +``` | 
|  | 190 | +Record                            TTL   Class    Priority Weight Port  Target | 
|  | 191 | +_mongodb._tcp.server.mongodb.com. 86400 IN SRV   0        5      27317 mongodb1.mongodb.com. | 
|  | 192 | +_mongodb._tcp.server.mongodb.com. 86400 IN SRV   0        5      27017 mongodb2.mongodb.com. | 
|  | 193 | +``` | 
|  | 194 | + | 
|  | 195 | +The returned host names (`mongodb1.mongodb.com` and `mongodb2.mongodb.com`) must share the same domainname | 
|  | 196 | +(`mongodb.com`) as the provided host name (`server.mongodb.com`). | 
|  | 197 | + | 
|  | 198 | +The driver also needs to request the DNS server for the TXT records on `server.mongodb.com`. This could return: | 
|  | 199 | + | 
|  | 200 | +``` | 
|  | 201 | +Record              TTL   Class    Text | 
|  | 202 | +server.mongodb.com. 86400 IN TXT   "replicaSet=replProduction&authSource=authDB" | 
|  | 203 | +``` | 
|  | 204 | + | 
|  | 205 | +From the DNS results, the driver now MUST treat the host information as if the following URI was used instead: | 
|  | 206 | + | 
|  | 207 | +``` | 
|  | 208 | +mongodb://mongodb1.mongodb.com:27317,mongodb2.mongodb.com:27107/?ssl=true&replicaSet=replProduction&authSource=authDB | 
|  | 209 | +``` | 
|  | 210 | + | 
|  | 211 | +If we provide the following URI with the same DNS (SRV and TXT) records: | 
|  | 212 | + | 
|  | 213 | +``` | 
|  | 214 | +mongodb+srv://server.mongodb.com/?authSource=otherDB | 
|  | 215 | +``` | 
|  | 216 | + | 
|  | 217 | +Then the default in the TXT record for `authSource` is not used as the value in the connection string overrides it. The | 
|  | 218 | +Client MUST treat the host information as if the following URI was used instead: | 
|  | 219 | + | 
|  | 220 | +``` | 
|  | 221 | +mongodb://mongodb1.mongodb.com:27317,mongodb2.mongodb.com:27107/?ssl=true&replicaSet=replProduction&authSource=otherDB | 
|  | 222 | +``` | 
|  | 223 | + | 
|  | 224 | +## Test Plan | 
|  | 225 | + | 
|  | 226 | +### Prose Tests | 
|  | 227 | + | 
|  | 228 | +See README.md in the accompanying [test directory](tests/README.md). | 
|  | 229 | + | 
|  | 230 | +### Spec Tests | 
|  | 231 | + | 
|  | 232 | +See README.md in the accompanying [test directory](tests/README.md). | 
|  | 233 | + | 
|  | 234 | +Additionally, see the `mongodb+srv` test `invalid-uris.yml` in the | 
|  | 235 | +[Connection String Spec tests](../connection-string/tests/README.md). | 
|  | 236 | + | 
|  | 237 | +## Motivation | 
|  | 238 | + | 
|  | 239 | +Several of our users have asked for this through tickets: | 
|  | 240 | + | 
|  | 241 | +- <https://jira.mongodb.org/browse/DRIVERS-201> | 
|  | 242 | +- <https://jira.mongodb.org/browse/NODE-865> | 
|  | 243 | +- <https://jira.mongodb.org/browse/CSHARP-536> | 
|  | 244 | + | 
|  | 245 | +## Design Rationale | 
|  | 246 | + | 
|  | 247 | +The design specifically calls for a pre-processing stage of the processing of connection URLs to minimize the impact on | 
|  | 248 | +existing functionality. | 
|  | 249 | + | 
|  | 250 | +## Justifications | 
|  | 251 | + | 
|  | 252 | +### Why Are Multiple Key-Value Pairs Allowed in One TXT Record? | 
|  | 253 | + | 
|  | 254 | +One could imagine an alternative design in which each TXT record would allow only one URI option. No `&` character would | 
|  | 255 | +be allowed as a delimiter within TXT records. | 
|  | 256 | + | 
|  | 257 | +In this spec we allow multiple key-value pairs within one TXT record, delimited by `&`, because it will be common for | 
|  | 258 | +all options to fit in a single 255-character TXT record, and it is much more convenient to configure one record in this | 
|  | 259 | +case than to configure several. | 
|  | 260 | + | 
|  | 261 | +Secondly, in some cases the order in which options occur is important. For example, readPreferenceTags can appear both | 
|  | 262 | +multiple times, and the order in which they appear is significant. Because DNS servers may return TXT records in any | 
|  | 263 | +order, it is only possible to guarantee the order in which readPreferenceTags keys appear by having them in the same TXT | 
|  | 264 | +record. | 
|  | 265 | + | 
|  | 266 | +### Why Is There No Mention of UTF-8 Characters? | 
|  | 267 | + | 
|  | 268 | +Although DNS TXT records allow any octet to exist in its value, many DNS providers do not allow non-ASCII characters to | 
|  | 269 | +be configured. As it is unlikely that any option names or values in the connection string have non-ASCII characters, we | 
|  | 270 | +left the behaviour of supporting UTF-8 characters as unspecified. | 
|  | 271 | + | 
|  | 272 | +## Reference Implementation | 
|  | 273 | + | 
|  | 274 | +None yet. | 
|  | 275 | + | 
|  | 276 | +## Backwards Compatibility | 
|  | 277 | + | 
|  | 278 | +There are no backwards compatibility concerns. | 
|  | 279 | + | 
|  | 280 | +## Future Work | 
|  | 281 | + | 
|  | 282 | +In the future we could consider using the priority and weight fields of the SRV records. | 
|  | 283 | + | 
|  | 284 | +## ChangeLog | 
|  | 285 | + | 
|  | 286 | +- 2024-09-24: Removed requirement for URI to have three '.' separated parts; these SRVs have stricter parent domain | 
|  | 287 | +  matching requirements for security. Create terminology section. Remove usage of term `{TLD}`. The `{hostname}` now | 
|  | 288 | +  refers to the entire hostname, not just the `{subdomain}`. | 
|  | 289 | + | 
|  | 290 | +- 2024-03-06: Migrated from reStructuredText to Markdown. | 
|  | 291 | + | 
|  | 292 | +- 2022-10-05: Revise spec front matter and reformat changelog. | 
|  | 293 | + | 
|  | 294 | +- 2021-10-14: Add `srvMaxHosts` MongoClient option and restructure Seedlist Discovery section. Improve documentation for | 
|  | 295 | +  the `srvServiceName` MongoClient option and add a new URI Validation section. | 
|  | 296 | + | 
|  | 297 | +- 2021-09-15: Clarify that service name only defaults to `mongodb`, and should be defined by the `srvServiceName` URI | 
|  | 298 | +  option. | 
|  | 299 | + | 
|  | 300 | +- 2021-04-15: Adding in behaviour for load balancer mode. | 
|  | 301 | + | 
|  | 302 | +- 2019-03-07: Clarify that CNAME is not supported | 
|  | 303 | + | 
|  | 304 | +- 2018-02-08: Clarify that `{options}}` in the [Specification](#specification) section includes all the optional | 
|  | 305 | +  elements from the Connection String specification. | 
|  | 306 | + | 
|  | 307 | +- 2017-11-21: Add clause that using `mongodb+srv://` implies enabling TLS. Add restriction that only `authSource` and | 
|  | 308 | +  `replicaSet` are allows in TXT records. Add restriction that only one TXT record is supported share the same parent | 
|  | 309 | +  domain name as the given host name. | 
|  | 310 | + | 
|  | 311 | +- 2017-11-17: Add new rule that indicates that host names in returned SRV records MUST share the same parent domain name | 
|  | 312 | +  as the given host name. Remove language and tests for non-ASCII characters. | 
|  | 313 | + | 
|  | 314 | +- 2017-11-07: Clarified that all parts of listable options such as readPreferenceTags are ignored if they are also | 
|  | 315 | +  present in options to the MongoClient constructor. Clarified which host names to use for SRV and TXT DNS queries. | 
|  | 316 | + | 
|  | 317 | +- 2017-11-01: Clarified that individual TXT records can have multiple strings. | 
|  | 318 | + | 
|  | 319 | +- 2017-10-31: Added a clause that specifying two host names with a `mongodb+srv://` URI is not allowed. Added a few more | 
|  | 320 | +  test cases. | 
|  | 321 | + | 
|  | 322 | +- 2017-10-18: Removed prohibition of raising DNS related errors when parsing the URI. | 
|  | 323 | + | 
|  | 324 | +- 2017-10-04: Removed from [Future Work](#future-work) the line about multiple MongoS discovery. The current | 
|  | 325 | +  specification already allows for it, as multiple host names which are all MongoS servers is already allowed under | 
|  | 326 | +  SDAM. And this specification does not modify SDAM. Added support for connection string options through TXT records. | 
|  | 327 | + | 
|  | 328 | +- 2017-09-19: Clarify that host names in `mongodb+srv://` URLs work like normal host specifications. | 
|  | 329 | + | 
|  | 330 | +- 2017-09-01: Updated test plan with YAML tests, and moved prose tests for URI parsing into invalid-uris.yml in the | 
|  | 331 | +  Connection String Spec tests. | 
0 commit comments