Skip to content
  • Brad House's avatar
    URI parser/writer for ares_set_servers_csv()/ares_get_servers_csv() (#882) · 9dd78e2f
    Brad House authored
    The DNS server format is insufficient for future configurations, such as
    supporting DNS over TLS (DoT) and DNS over HTTPS (DoH), as well as
    additional functionality such as domain-specific servers. Already, in
    the case where different UDP and TCP ports are used, it is impossible to
    represent in the current format.
    
    In order to try to use some standardized format, we are going to define
    our own URI schemes that should be parse-able by any URI parser. The new
    scheme will only be used when the configuration cannot otherwise be
    expressed using the current `ipaddr%iface:port` format, which is the
    format used as the nameserver configuration in `/etc/resolv.conf`.
    However, the parser `ares_set_servers_csv()` shall accept the new URI
    scheme format even when it is not necessary.
    
    This PR implements a URI parser and writer and hooks the basic usage
    into `ares_set_servers_csv()` and `ares_get_servers_csv()` as well as
    provides updated documentation in the relevant manpages.
    
    We will define these URI schemes:
    * `dns://` - Normal DNS server (UDP + TCP). We need to be careful not to
    conflict with query params defined in
    https://datatracker.ietf.org/doc/html/rfc4501 since we'd technically be
    extending this URI scheme. Port defaults to `53`.
    * `dns+tls://` - DNS over TLS. Port defaults to `853`.
    * `dns+https://` - DNS over HTTPS. Port defaults to `443`.
    
    We initially will define these query parameters (additional arguments
    may be required in the future to specify options such as TLS certificate
    validation rules):
    * `tcpport` - TCP port to use, only for `dns://` scheme. The `port`
    specified as part of the `authority` component of the URI will be used
    for both UDP and TCP by default, this option will override the TCP port.
    * `ipaddr` - Only for `dns+tls://` and `dns+https://`. If the
    `authority` component of the URI contains a hostname, this is used to
    specify the ip address of the hostname. If not specified, will need to
    use a non-secure server to perform a DNS lookup to retrieve this
    information. It is always recommended to have both the ip address and
    fully qualified domain name specified.
    * `hostname` - Only for `dns+tls://` and `dns+https://`. If the
    `authority` component of the URI contains an ip address, this is used to
    specify the fully qualified domain name of the server. If not specified,
    will need to use a non-secure server to perform a DNS reverse lookup to
    retrieve this information. It is always recommended to have both the ip
    address and fully qualified domain name specified.
    * `domain` - If specified, this server is a domain-specific server. Any
    queries for this domain will be routed to this server. Multiple servers
    may be tagged with the same domain.
    
    Examples:
    ```
    dns://8.8.8.8
    dns://[2001:4860:4860::8888]
    dns://[fe80::b542:84df:1719:65e3%en0]
    dns://192.168.1.1:55
    dns://192.168.1.1?tcpport=1153
    dns://10.0.1.1?domain=myvpn.com
    dns+tls://8.8.8.8?hostname=dns.google
    dns+tls://one.one.one.one?ipaddr=1.1.1.1
    ```
    
    NOTE: While we are defining the scheme for things like domain-specific
    servers, DNS over TLS and DNS over HTTPS, the underlying implementations
    for those features do not yet exist and therefore will result in errors
    if they are attempted to be used.
    
    ### Non-compliance in implementation
    
    All these could be easily implemented/fixed if desired, however any such
    changes would be of no use to the current c-ares usage of URIs:
    * Does not currently support relative references
    * Requires use of the authority section, blank is not allowed
    * The query string is interpreted to be in
    [application/x-www-form-urlencoded](https://en.wikipedia.org/wiki/Application/x-www-form-urlencoded)
    format only and will result in parse errors if it is not. This is the
    most common format used, however technically not valid to mandate this
    format is used. We could add flags in the future to treat the query
    string as opaque and leave it to the user to process. Or we could
    internally have a list of schemes that use this format.
    * [IDNA](https://en.wikipedia.org/wiki/Internationalized_domain_name
    
    ) is
    not supported.
    * Does not support hex-encoded IPv4 addresses (this is compliant with RFC3986, but not WHATWG)
    
    Authored-By: default avatarBrad House <(@bradh352)>
    9dd78e2f