dnsdist, as a load-balancer, receives the UDP datagrams and terminates the TCP connections with the client. It therefore knows the source IP address and port of that client, as well as the original destination address, port, and protocol.
Very often the backend needs to know that information as well, to pass EDNS Client Subnet to an authoritative server, to do GeoIP-based processing or even custom filtering.
-There are several ways to pass that information using dnsdist: EDNS Client Subnet, X-Proxied-For and the Proxy Protocol.
+There are several ways to pass that information using dnsdist: the :ref:`Proxy Protocol` and :ref:`EDNS Client Subnet<EDNS Client Subnet>`.
+
+When the backend supports it (ISC Bind, Knot, Knot Resolver, PowerDNS Authoritative, PowerDNS Recursor, Unbound, HAProxy, nginx, postfix and many others do), the proxy protocol is the best option.
+
+.. note::
+ X-Proxied-For (XPF) was a third option but it has been deprecated for a while, and support has been removed in 2.0.0.
+
+.. _Proxy Protocol:
+
+Proxy Protocol
+--------------
+
+.. note:
+ The Proxy Protocol has been designed by the HAProxy folks for HTTP over TCP, but is generic enough to be used in other places, and is a de-facto standard with implementations in ISC Bind, Knot, Knot Resolver, PowerDNS Authoritative, PowerDNS Recursor, Unbound, HAProxy, nginx, postfix and many others.
+ It works by pre-pending a small header at the very beginning of a UDP datagram or TCP connection, which holds the initial source and destination addresses and ports, and can also contain several custom values in a Type-Length-Value format. More information about the Proxy Protocol can be found at https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt
+
+From dnsdist to its backend
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To enable the use of the proxy protocol between dnsdist and its backend, the ``useProxyProtocol`` parameter can be used when creating a :func:`new server <newServer>`:
+
+.. code-block:: lua
+
+ newServer{address="192.0.2.1:53", useProxyProtocol=true}
+
+This parameter indicates whether a Proxy Protocol version 2 (binary) header should be prepended to the query before forwarding it to the backend, over UDP or TCP.
+
+Both the PowerDNS Authoritative Server and the Recursor can parse PROXYv2 headers, if configured to do so with their `proxy-protocol-from` setting::
+
+ proxy-protocol-from=192.0.2.2
+
+For more informations, see the `authoritative server's documentation <https://doc.powerdns.com/authoritative/settings.html#proxy-protocol-from>`_ or the `recursor's documentation <https://docs.powerdns.com/recursor/settings.html#proxy-protocol-from>`_.
+
+From clients to dnsdist
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Such a Proxy Protocol header can also be passed from the client to dnsdist, using :func:`setProxyProtocolACL` to specify which clients to accept it from:
+
+.. code-block:: lua
+
+ setProxyProtocolACL({'192.0.2.0/24'})
+
+Note that a proxy protocol payload will be required from these clients, regular DNS queries will no longer be accepted if they are not preceded by a proxy protocol payload.
+
+If :func:`setProxyProtocolApplyACLToProxiedClients` is set (default is false), the general ACL will be applied to the source IP address as seen by dnsdist first, but also to the source IP address provided in the Proxy Protocol header.
+
+Passing additional information
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Custom values can be added to the header via :meth:`DNSQuestion:addProxyProtocolValue`, :meth:`DNSQuestion:setProxyProtocolValues`, :func:`SetAdditionalProxyProtocolValueAction` and :func:`SetProxyProtocolValuesAction`.
+
+Be careful that Proxy Protocol values are sent once at the beginning of the TCP connection for TCP and DoT queries.
+That means that values received on an incoming TCP connection will be inherited by subsequent queries received over the same incoming TCP connection, if any, but values set to a query will not be inherited by subsequent queries.
+
+Please also note that the maximum size of a Proxy Protocol header dnsdist is willing to accept is 512 bytes by default, although it can be set via :func:`setProxyProtocolMaximumPayloadSize`.
+
+.. _EDNS Client Subnet:
Using EDNS Client Subnet
------------------------
-EDNS Client Subnet (ECS) is a standardized EDNS option designed to pass a bit of information about the client from a resolver to authoritative servers. While it was not designed with our use-case in mind, it can be used by dnsdist to send the source IP, but only the source IP, to its backend.
+.. note:
+ EDNS Client Subnet (ECS) is a standardized EDNS option designed to pass a bit of information about the client from a resolver to authoritative servers. While it was not designed with our use-case in mind, it can be used by dnsdist to send the source IP, but only the source IP, to its backend.
+
+In order to provide the downstream server with the address of the real client, or at least the one talking to dnsdist, the ``useClientSubnet`` parameter can be used when creating a :func:`new server <newServer>`:
-In order to provide the downstream server with the address of the real client, or at least the one talking to dnsdist, the ``useClientSubnet`` parameter can be used when creating a :func:`new server <newServer>`. This parameter indicates whether an EDNS Client Subnet option should be added to the request.
+.. code-block:: lua
+
+ newServer{address="192.0.2.1:53", useClientSubnet=true}
+
+This parameter indicates whether an EDNS Client Subnet option should be added to the request.
The default source prefix-length is 24 for IPv4 and 56 for IPv6, meaning that for a query received from 192.0.2.42, the EDNS Client Subnet value sent to the backend will be 192.0.2.0.
-This can be changed with :func:`setECSSourcePrefixV4` and :func:`setECSSourcePrefixV6`.
+This can be changed with :func:`setECSSourcePrefixV4` and :func:`setECSSourcePrefixV6`:
+
+.. code-block:: lua
+
+ setECSSourcePrefixV4(32)
+ setECSSourcePrefixV6(128)
+
+If the incoming request already contains an EDNS Client Subnet value, it will not be overridden unless :func:`setECSOverride` is set to ``true``:
+
+.. code-block:: lua
+
+ setECSOverride(true)
-If the incoming request already contains an EDNS Client Subnet value, it will not be overridden unless :func:`setECSOverride` is set to ``true``.
+Advanced usage
+^^^^^^^^^^^^^^
In addition to the global settings, rules and Lua bindings can alter this behavior per query:
In effect this means that for the EDNS Client Subnet option to be added to the request, ``useClientSubnet`` should be set to ``true`` for the backend used (default to ``false``) and ECS should not have been disabled by calling :func:`SetDisableECSAction` or setting ``dq.useECS`` to ``false`` (default to true).
-Note that any trailing data present in the incoming query is removed when an OPT record has to be inserted.
+Drawbacks
+^^^^^^^^^
+
+.. warning::
+ Note that any trailing data present in the incoming query is removed when an OPT record has to be inserted.
In addition to the drawback that it can only pass the source IP address, and the fact that it needs to override any existing ECS option, adding that option requires parsing and editing the query, as well as parsing and editing the response in most cases.
| Response, EDNS with ECS | remove or edit the ECS option if needed |
+----------------------------+-------------------------------------------------+
-Proxy Protocol
---------------
-
-The Proxy Protocol has been designed by the HAProxy folks for HTTP over TCP, but is generic enough to be used in other places, and is a de-facto standard with implementations in nginx and postfix, for example.
-It works by pre-pending a small header at the very beginning of a UDP datagram or TCP connection, which holds the initial source and destination addresses and ports, and can also contain several custom values in a Type-Length-Value format. More information about the Proxy Protocol can be found at https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt
-
-In order to use it in dnsdist, the ``useProxyProtocol`` parameter can be used when creating a :func:`new server <newServer>`.
-This parameter indicates whether a Proxy Protocol version 2 (binary) header should be prepended to the query before forwarding it to the backend, over UDP or TCP.
-Such a Proxy Protocol header can also be passed from the client to dnsdist, using :func:`setProxyProtocolACL` to specify which clients to accept it from. Note that a proxy protocol payload will be required from these clients, regular DNS queries will no longer be accepted if they are not preceded by a proxy protocol payload.
-
-If :func:`setProxyProtocolApplyACLToProxiedClients` is set (default is false), the general ACL will be applied to the source IP address as seen by dnsdist first, but also to the source IP address provided in the Proxy Protocol header.
-
-Custom values can be added to the header via :meth:`DNSQuestion:addProxyProtocolValue`, :meth:`DNSQuestion:setProxyProtocolValues`, :func:`SetAdditionalProxyProtocolValueAction` and :func:`SetProxyProtocolValuesAction`.
-Be careful that Proxy Protocol values are sent once at the beginning of the TCP connection for TCP and DoT queries.
-That means that values received on an incoming TCP connection will be inherited by subsequent queries received over the same incoming TCP connection, if any, but values set to a query will not be inherited by subsequent queries.
-Please also note that the maximum size of a Proxy Protocol header dnsdist is willing to accept is 512 bytes by default, although it can be set via :func:`setProxyProtocolMaximumPayloadSize`.
-
-dnsdist 1.5.0 only supports outgoing Proxy Protocol. Support for parsing incoming Proxy Protocol headers has been implemented in 1.6.0, except for DoH where it does not make sense anyway, since HTTP headers already provide a mechanism for that.
-
-Both the PowerDNS Authoritative Server and the Recursor can parse PROXYv2 headers, if configured to do so with their `proxy-protocol-from` setting.
-
X-Proxied-For
-------------
addAction(RecordsTypeCountRule(DNSSection.Additional, 65280, 1, 65535), DropAction())
+.. _Influence on caching:
+
Influence on caching
--------------------