Internet Engineering Task Force | L. Song |
Internet-Draft | S. Kerr |
Intended status: Experimental | R. Wan |
Expires: August 20, 2016 | Beijing Internet Institute |
February 17, 2016 |
DNS wire-format over HTTP
draft-song-dns-wireformat-http-00
This memo introduces a way to tunnel DNS data over HTTP. This may be useful in any situation where DNS is not working properly, such as when there is middlebox misbehavior.
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at http://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
This Internet-Draft will expire on August 20, 2016.
Copyright (c) 2016 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.
RFC 1035 [RFC1035] specifies the wire format for DNS messages. It also specifies DNS transport on UDP and TCP on port 53, which is still used today. However, there are other ways to access DNS database, for example in a different data format or via alternative DNS transport. These approaches are summarized in [draft-shane-review-DNS-over-http].
One of alternative way of DNS described in that document is to transport DNS binary data inside HTTP, with the goal of improving DNS service availability. The DNS traffic is simply sent as web traffic using port 80/443 over HTTP. It can bypass badly behaving middle boxes like firewalls, proxies or traffic shaping devices on path which might interfere with normal DNS traffic [RFC5625] [DOTSE] [SAC035].
This approach has the advantage that HTTP usually makes it through even the worst coffee shop or hotel room firewalls, as Internet users expect web browsing to always work. It also benefits from HTTP's support for persistent TCP connections (see section 6.3 in [RFC7230]) and multiplexing (see section 5 in [RFC7540]). Note that 5966bis [I-D.ietf-dnsop-5966bis] specifies the persistent and query pipelining features for DNS on TCP port 53; HTTP is easy and mature to deploy.Finally, developers can choose HTTPS to provides data integrity and privacy as well.
Unlike a REST DNS API using JSON [I-D.bortzmeyer-dns-json] or XML [I-D.mohan-dns-query-xml] encoding for DNS data, in this approach wire-format data is wrapped with a HTTP header and transmitted on port 80 or 443. This protocol is not designed for web developers or advanced usage in application development in mind. It simply serves as a sort of DNS VPN, and does not introduce another format of DNS data.
This memo aims to describe how the DNS binary over HTTP concept works. Hopefully implementations by different developers following this memo can speak with each other.
This mechanism is designed for DNS transaction between client stub resolver with recursive server. Interaction with authority server like normal queries, DNS zone transfer, DNS updates are out-of-scope for this document.
As mentioned in introduction, the basic methodology is wrapping the DNS wire-format data into an HTTP header and transmitting on port 80 or 443; however, there are two different scenarios for implementation.
Scenario 1:
The DNS server implementation handles DNS queries and responses via both UDP and TCP on port 53, and HTTP on port 80 or 443. It works as follows:
Scenario 2:
In this scenario there is a DNS-HTTP proxy sitting between stub-resolver and the recursive server. The stub uses a client proxy and the recursive server uses a server proxy. This works like a DNS VPN and transmits wire-format DNS messages over HTTP between the proxy client and a server, as follows:
Note that the proxy client can be implemented listening to a loop-back address in the same host with stub-resolver. The proxy server can be implemented as a caching server as well. It is also possible to use the proxy server as a regular web server at the same time that it is acting as a proxy server.
Although this document simply proposes that HTTP be used for DNS massage exchange, it is informative to explore the context with HTTP-specific semantics, such as the HTTP request method, specific request-target, HTTP-version, and HTTP header field, all of which have impact on interoperability as well as performance.
In HTTP 1.1 specification section 3 in RFC 7230 [RFC7230], an HTTP message consists of three parts: start-line, header fields, and message body with an empty line between header fields and message body. The DNS over HTTP message also contains these parts.
By definition the HTTP start-line is either a request-line (for requests) or a status-line (for responses). A request-line consists of the request method, request-target, and HTTP-version with a CRLF in the end.
For a DNS query over HTTP, the request is always POST [section 4.3.3 in RFC 7230 [RFC7230]]. Note if a GET is sent to the server, it optionally returns a human-readable page showing its web server environment.
Usually the target URI is provides explicitly by the DNS services provider. Derived from the target URI, the request-target in request-line identifies the target resource upon which to apply the request. In the case of DNS query over HTTP, one approach is to always use a fixed string for request-target by default, like "/dns-over-http". It works if there is no other resource sharing the same request-target name, otherwise there may be a conflict. Another approach is to allow the server to use a defined URI which contains the specific request-target. Note in the BII proxy implementation, we use "/proxy_dns" for this purpose.
DNS transaction over HTTP has no specific requirement for transport protocol; developers can use any version of HTTP to accomplish the transaction. But developers should be aware that HTTP/1.1 RFC 7230 [RFC7230] and HTTP/2 RFC 7540 [RFC7540] do have differences in performance regarding multiplexing. HTTP/2 is fully multiplexed, instead of ordered and blocking. Because there is a general desire to achieve similar performance with DNS over UDP, the modern HTTP/2 is preferred for DNS over HTTP implementation. Note that there should be no problem for advanced HTTP protocol in the future deployed for DNS over HTTP.
For example, given HTTP-version is "HTTP/1.1". So the request-line is :
POST /dns-over-http HTTP/1.1
The status-line returns the status-code [Section 6 of RFC 7231 [RFC7231]], which only reflects status of HTTP connection. If the request has succeeded, the status-line is:
HTTP/1.1 200 OK
If the request fails, the proxy server will supply an appropriate error code, typically 4xx (client error) if the client has provided a query that the server cannot understand for some reasons, or 5xx (server error) if some server-side problem prevented a query from succeeding.
By definition header fields are key:value pairs that can be used to communicate data about the message, its payload, the target resource, or the connection (for example control data). Considering the proxy configuration in scenario 2, we use a new header field:
Proxy-DNS-Transport: xyz
Where xyz is either UDP or TCP, which is the client's indication of how it received the underlying DNS query, and which the server will use when sending the query to the far-end DNS server. This means if a stub DNS client asks for TCP, then that's what the far-end DNS server will see, and likewise for UDP. This header field is used for both request and response, for all DNS over HTTP message.
As mentioned, the message body is DNS wire-format data.
It is worth mentioning that DNS messages sent over TCP connections is prefixed with a two-byte length field which gives the message length[section 4.2.2 in RFC 1035 [RFC1035]], excluding the two-byte length field. This length field allows the low-level processing to assemble a complete message before beginning to parse it. In the context of HTTP, there is content-length header filed [section 3.3.2 in RFC 7230 [RFC7230]]in which the field-value is the same with two bytes length field in DNS over TCP.
In normal configuration, both client and server should assign a value for the DNS message length to HTTP content-length field. In proxy configuration, if Proxy-DNS-Transport is TCP, the proxy must aware the two-byte length field in DNS message over TCP before it handle HTTP request and response.
HTTPS is recommended for communication. It provides privacy and integrity for HTTP sessions.
As specified in RFC 5246 [RFC5246], both the DNS server and client can be authenticated or not authenticated. The DNS service providers can decide authenticated pattern on both server and client sides based on their own requirement for security and privacy. For an open resolver, clients do not require authentication.
Registration for a new HTTP header field: Proxy-DNS-Transport