Files
DnsServer/Apps/SplitHorizonApp/README.md

6.0 KiB

Split Horizon

The Split Horizon app provides two distinct features which can be used independently:

  1. Create APP records in primary and forwarder zones that can return different sets of A, AAAA, or CNAME records for clients querying over public, private, or other specified networks.

  2. Translate IP addresses in a DNS response for A and AAAA type requests based on the client's network address and the configured 1:1 translation.

The following sections describe each feature in more detail.

A / AAAA / CNAME

To respond with different A, AAAA, or CNAME records to different clients, create an APP record with the respective name in a primary or forwarder zone. Select the Split Horizon app and the SplitHorizon.SimpleAddress class for A and AAAA records or SplitHorizon.SimpleCNAME for CNAME records.

Each APP record is configured with a JSON document which looks like the following:

{
  "public": [
    "1.1.1.1",
    "2.2.2.2"
  ],
  "private": [
    "192.168.1.1",
    "::1"
  ],
  "custom-networks": [
    "172.16.1.1"
  ],
  "10.0.0.0/8": [
    "10.1.1.1"
  ]
}

An example for CNAME replacements:

{
  "public": "api.example.com",
  "private": "api.example.corp",
  "custom-networks": "custom.example.corp",
  "10.0.0.0/8": "api.intranet.example.corp"
}

Keys can be one of the following:

  • a network specification (like 10.0.0.0/8)
  • a named network defined in the global app configuration (see [Address Translation])
  • private: private IP ranges defined in RFC 1918
  • public: all IPs outside the private IP ranges defined in RFC 1918

Values are either lists of IPv4 and IPv6 addresses which get mapped to A and AAAA records in the response or a single string to be used as the resulting CNAME response.

The lists don't have to be exhaustive: requests from clients which don't match any of the networks are processed as if the APP record didn't exist. For example, this could mean that a request is forwarded via a FWD record.

Address Translation

Translates IP addresses in a DNS response for A and AAAA type request based on the client's network address and the configured 1:1 translation. Also supports reverse (PTR) queries for translated addresses.

Configuration

This feature is both a post processor as well as a request handler. That means, it modifies a response generated by the DNS server before it is sent to the client and also serves authoritative responses for some requests. It is configured globally in the app settings. Its configuration file is a JSON document which looks like the following:

{
    "networks": {
        "custom-networks": [
            "172.16.1.0/24",
            "172.16.10.0/24",
            "172.16.2.1"
        ]
    },
    "enableAddressTranslation": false,
    "networkGroupMap": {
        "10.0.0.0/8": "local1",
        "172.16.0.0/12": "local2",
        "192.168.0.0/16": "local3"
    },
    "groups": [
        {
            "name": "local1",
            "enabled": true,
            "translateReverseLookups": true,
            "externalToInternalTranslation": {
               "1.2.3.0/24": "10.0.0.0/24",
               "5.6.7.8": "10.0.0.5"
            }
        },
        {
            "name": "local2",
            "enabled": true,
            "translateReverseLookups": true,
            "externalToInternalTranslation": {
               "1.2.3.4": "172.16.0.4",
               "5.6.7.8": "172.16.0.5"
            }
        },
        {
            "name": "local3",
            "enabled": true,
            "translateReverseLookups": true,
            "externalToInternalTranslation": {
               "1.2.3.4": "192.168.0.4",
               "5.6.7.8": "192.168.0.5"
            }
        }
    ]
}

The individual settings are:

  • networks: a map of network names to lists of network addresses. This can used to name networks for use in APP records for this app. By using named networks, it becomes easy to change a network definition which is reused across multiple APP records.
  • enableAddressTranslation: when set to false, address translation is disabled and the original response is passed through unmodified.
  • networkGroupMap: maps given networks to one of the following named groups. The IP of the requesting client is usses the group with the most specific network mask. Example: if you have mappings "192.168.1.0/24" = "local1" and "192.168.0.0/16" = "local2", the client with the IP 192.168.1.10 is considered a member of group local1.
  • groups: a list of groups. A group has the following properties:
    • name: the name of the group.
    • enabled: flag whether to perform address translation for this group.
    • translateReverseLookups: flag whether to respond to PTR queries for internal IPs (see below)
    • externalToInternalTranslation: a mapping from external to internal network addresses (see below). The networks must be of the same size (have the same prefix length).

Processing

Forward lookups (A and AAAA) which fulfill all of the following requirements are processed by this app:

  • the requesting client is a member of a group defined in networkGroupMap
  • the response code is NoError
  • the response has at least one answer

Note that NXDOMAIN, SERVFAIL, and NODATA answers are passed through unmodified.

For every A and AAAA record in the response, the app replaces any IP according to the rules defined in externalToInternalTranslation of the client's network group. The translation is a 1:1 mapping which just replaces the network part of an IP. For example, given externalToInternalTranslation": { "1.2.3.0/24": "10.0.0.0/24 }, the response 1.2.3.4 is replaced with 10.0.0.4.

If translateReverseLookups is enabled for a given group, the app also modifies PTR queries for domains representing the internal IPs of the group by responding with a CNAME record for a domain representing the corresponding IP in the external range. For example, given externalToInternalTranslation": { "1.2.3.0/24": "10.0.0.0/24 }, a PTR query for 4.0.0.10.in-addr.arpa will receive the response CNAME 4.3.2.1.in-addr.arpa.