15. Remote Backend

15.1. Compiling
15.2. Usage
15.3. API
15.4. Examples

[Warning]Warning

The Remote Backend is available since PowerDNS Authoritative Server 3.2. This backend is marked as experimental!

Table A.14. Remote backend capabilities

NativeYes
MasterYes*
Slave 
Superslave 
AutoserialYes*
DNSSECYes*
Multiple instancesYes

* If provided by the underlying backend.

This backend provides unix socket / pipe / http remoting for powerdns.

15.1. Compiling

To compile this backend, you need to configure --with-modules="remote pipe", for now. If you want to use http connector, you need libcurl and use --enable-remotebackend-http.

15.2. Usage

The only configuration option for this backend is remote-connection-string. It comprises of two elements: type of backend, and parameters.

remote-connection-string=<type>:<param>=<value>,<param>=<value>...

You can pass as many parameters as you want. For unix and pipe backends, these are passed along to the remote end as initialization. See Section 15.3, “API”. Initialize is not called for http backend.

Unix backend

parameters: path, timeout (default 2000ms)

remote-connection-string=unix:path=/path/to/socket

Pipe backend

parameters: command,timeout (default 2000ms)

remote-connection-string=unix:command=/path/to/executable,timeout=2000

HTTP backend

parameters: url, url-suffix, timeout (default 2000)

HTTP backend tries to do RESTful requests to your server. See examples.

URL should not end with /, and url-suffix is optional, but if you define it, it's up to you to write the ".php" or ".json". Lack of dot causes lack of dot in URL. Timeout is divided by 1000 because libcurl only supports seconds, but this is given in milliseconds for consistency with other backends.

15.3. API

Queries

Unix and Pipe backend sends JSON formatted string to the remote end. Each JSON query has two sections, 'method' and 'parameters'.

HTTP backend calls methods based on URL and has parameters in the query string. Most calls are GET; see the methods listing for details.

Replies

You *must* always reply with JSON hash with at least one key, 'result'. This must be boolean false if the query failed. Otherwise it must conform to the expected result. For HTTP backend, to signal bare success, you can just reply with HTTP 200 OK, and omit any output. This will result in same outcome as sending {"result":true}.

You can optionally add 'log' array, each line in this array will be logged in PowerDNS.

Methods

Method: initialize
Mandatory:

Yes (except HTTP backend)

Parameters:

all parameters in connection string

Reply:

true on success / false on failure

Description

Called to initialize the backend. This is not called for HTTP backend. You should do your initializations here.

Example JSON/RPC:

Query:

{"method":"initialize", "parameters":{"command":"/path/to/something", "timeout":"2000", "something":"else"}}

Response:

{"result":true}

Method: lookup
Mandatory:

Yes

Parameters:

qtype, qname, zone_id

Optional parameters:

remote, local, real-remote

Reply:

array of <qtype,qname,content,ttl,domain_id,priority,scopeMask,auth>

Optional values:

domain_id, scopeMask and auth

Description

This method is used to do the basic query. You can omit auth, but if you are using DNSSEC this can lead into trouble.

Example JSON/RPC:

Query:

{"method":"lookup", "parameters":{"qtype":"ANY", "qname":"www.example.com", "remote":"192.168.0.24", "local":"192.168.0.1", "real-remote":"192.168.0.24", "zone-id":-1}}

Response:

{"result":[{"qtype":"A", "qname":"www.example.com", "content":"192.168.1.2", "ttl": 60}]}

Example HTTP/RPC:

Query:

GET /dnsapi/lookup/www.example.com/ANY HTTP/1.1
X-RemoteBackend-remote: 192.168.0.24
X-RemoteBackend-local: 192.168.0.1
X-RemoteBackend-real-remote: 192.168.0.24
X-RemoteBackend-zone-id: -1

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8

{"result":[{"qtype":"A", "qname":"www.example.com", "content":"192.168.1.2", "ttl": 60}]}

Method: list
Mandatory:

No (Gives AXFR support)

Parameters:

zonename, domain_id

Optional parameters:

domain_id

Reply:

array of <qtype,qname,content,ttl,domain_id,priority,scopeMask,auth>

Optional values:

domain_id, scopeMask and auth

Description

Lists all records for the zonename. If you are running dnssec, you should take care of setting auth to appropriate value, otherwise things can go wrong.

Example JSON/RPC:

Query:

{"method":"list", "parameters":{"zonename":"example.com","domain_id":-1}}

Response (split into lines for ease of reading)

{"result":[
  {"qtype":"SOA", "qname":"example.com", "content":"dns1.icann.org. hostmaster.icann.org. 2012081600 7200 3600 1209600 3600", "ttl": 3600},
  {"qtype":"NS", "qname":"example.com", "content":"ns1.example.com", "ttl": 60},
  {"qtype":"MX", "qname":"example.com", "content":"mx1.example.com.", "ttl": 60, "priority":10},
  {"qtype":"A", "qname":"www.example.com", "content":"192.168.1.2", "ttl": 60},
  {"qtype":"A", "qname":"ns1.example.com", "content":"192.168.0.2", "ttl": 60},
  {"qtype":"A", "qname":"mx1.example.com", "content":"192.168.0.3", "ttl": 60} 
]}

Example HTTP/RPC:

Query:

GET /dnsapi/list/example.com HTTP/1.1
X-RemoteBackend-domain-id: -1

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8

{"result":[{"qtype":"SOA", "qname":"example.com", "content":"dns1.icann.org. hostmaster.icann.org. 2012081600 7200 3600 1209600 3600", "ttl": 3600},{"qtype":"NS", "qname":"example.com", "content":"ns1.example.com", "ttl": 60},{"qtype":"MX", "qname":"example.com", "content":"mx1.example.com.", "ttl": 60, "priority":10},{"qtype":"A", "qname":"www.example.com", "content":"192.168.1.2", "ttl": 60},{"qtype":"A", "qname":"ns1.example.com", "content":"192.168.0.2", "ttl": 60},{"qtype":"A", "qname":"mx1.example.com", "content":"192.168.0.3", "ttl": 60}]}

Method: getBeforeAndAfterNamesAbsolute
Mandatory:

for NSEC/NSEC3 non-narrow

Parameters:

id, qname

Reply:

before, after

Description

Asks the names before and after qname. qname is given without dots or domain part. The query can also be hashed. Care must be taken to handle wrap-around when qname is first or last in the ordered list. Do not return nil for either one.

Example JSON/RPC:

Query:

{"method":"getbeforeandafternamesabsolute", "params":{"id":0,"qname":"www.example.com"}}

Response:

{”result":{"before":"ns1","after":""}}

Example HTTP/RPC:

Query:

/dnsapi/getbeforeandafternamesabsolute/0/www.example.com

Response:

{”result":{"before":"ns1","after":""}}

Method: getDomainMetadata
Mandatory:

No

Parameters:

name, kind

Reply:

array of strings

Description

Returns the value(s) for variable kind for zone name. Most commonly it's one of NSEC3PARAM, PRESIGNED, SOA-EDIT. Can be others, too. You *must* always return something, if there are no values, you shall return empty array or false.

Example JSON/RPC:

Query:

{"method":"getdomainmetadata", "parameters":{"name":"example.com","kind":"PRESIGNED"}}

Response:

{"result":["NO"]}

Example HTTP/RPC:

Query:

GET /dnsapi/getdomainmetadata/example.com/PRESIGNED HTTP/1.1

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8

{"result":["NO"]}

Method: setDomainMetadata
Mandatory:

No

Parameters:

name, kind, value

Reply:

true on success, false on failure

Description

Replaces the value(s) on domain name for variable kind to string(s) on array value. The old value is discarded. Value can be an empty array, which can be interprepted as deletion request.

Example JSON/RPC:

Query:

{"method":"setdomainmetadata","parameters":{"name":"example.com","kind":"PRESIGNED","value":["YES"]}}

Response:

{"result":true}

Example HTTP/RPC:

Query:

POST /dnsapi/setdomainmetadata/example.com/PRESIGNED HTTP/1.1
Content-Type: application/x-www-form-urlencoded 
Content-Length: 12

value1=YES&

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8

{"result":true}

Method: getDomainKeys
Mandatory:

for DNSSEC

Parameters:

name, kind

Reply:

array of <id, flags, active, content>

Description

Retrieves any keys of kind. The id, flags are unsigned integers, and active is boolean. Content must be valid key record in format that PowerDNS understands. You are encouraged to implement the section called “Method: addDomainKey”, as you can use Section 5, “'pdnssec' for PowerDNSSEC command & control” to provision keys.

Example JSON/RPC:

Query:

{"method":"getdomainkeys","parameters":{"name":"example.com","kind":0}}

Response:

{"result":[{"id":1,"flags":256,"active":true,"content":"Private-key-format: v1.2
Algorithm: 8 (RSASHA256)
Modulus: r+vmQll38ndQqNSCx9eqRBUbSOLcH4PZFX824sGhY2NSQChqt1G4ZfndzRwgjXMUwiE7GkkqU2Vbt/g4iP67V/+MYecMV9YHkCRnEzb47nBXvs9JCf8AHMCnma567GQjPECh4HevPE9wmcOfpy/u7UN1oHKSKRWuZJadUwcjbp8=
PublicExponent: AQAB
PrivateExponent: CY93UtVnOM6wrFJZ+qA9+Yx+p5yk0CSi0Q7c+/6EVMuABQ5gNyTuu0j65lU3X81bwUk2wHPx6smfgoVDRAW5jjO4jgIFV6nE4inzk5YQKycQSL8YG3Nm9GciLFya1KUXs81sHsQpkvK7MNaSbvkaHZQ6iv16bZ4t73Wascwa/E=
Prime1: 6a165cIC0nNsGlTW/s2jRu7idq5+U203iE1HzSIddmWgx5KIKE/s3I+pwfmXYRUmq+4H9ASd/Yot1lSYW98szw==
Prime2: wLoCPKxxnuxDx6/9IKOYz8t9ZNLY74iCeQ85koqvTctkFmB9jpOUHTU9BhecaFY2euP9CuHV7z3PLtCoO8s1MQ==
Exponent1: CuzJaiR/7UboLvL4ekEy+QYCIHpX/Z6FkiHK0ZRevEJUGgCHzRqvgEBXN3Jr2WYbwL4IMShmGoxzSCn8VY9BkQ==
Exponent2: LDR9/tyu0vzuLwcommit 20B22FzNdd5rFF2wAQTQ0yF/3Baj5NAi9w84l0u07KgKQZX4g0N8qUyypnU5YDyzc6ZoagQ==
Coefficient: 6S0vhIQITWzqfQSLj+wwRzs6qCvJckHb1+SD1XpwYjSgMTEUlZhf96m8WiaE1/fIt4Zl2PC3fF7YIBoFLln22w=="}]}

Example HTTP/RPC:

Query:

GET /dnsapi/getdomainkeys/example.com/0 HTTP/1.1

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8

{"result":[{"id":1,"flags":256,"active":true,"content":"Private-key-format: v1.2
Algorithm: 8 (RSASHA256)
Modulus: r+vmQll38ndQqNSCx9eqRBUbSOLcH4PZFX824sGhY2NSQChqt1G4ZfndzRwgjXMUwiE7GkkqU2Vbt/g4iP67V/+MYecMV9YHkCRnEzb47nBXvs9JCf8AHMCnma567GQjPECh4HevPE9wmcOfpy/u7UN1oHKSKRWuZJadUwcjbp8=
PublicExponent: AQAB
PrivateExponent: CY93UtVnOM6wrFJZ+qA9+Yx+p5yk0CSi0Q7c+/6EVMuABQ5gNyTuu0j65lU3X81bwUk2wHPx6smfgoVDRAW5jjO4jgIFV6nE4inzk5YQKycQSL8YG3Nm9GciLFya1KUXs81sHsQpkvK7MNaSbvkaHZQ6iv16bZ4t73Wascwa/E=
Prime1: 6a165cIC0nNsGlTW/s2jRu7idq5+U203iE1HzSIddmWgx5KIKE/s3I+pwfmXYRUmq+4H9ASd/Yot1lSYW98szw==
Prime2: wLoCPKxxnuxDx6/9IKOYz8t9ZNLY74iCeQ85koqvTctkFmB9jpOUHTU9BhecaFY2euP9CuHV7z3PLtCoO8s1MQ==
Exponent1: CuzJaiR/7UboLvL4ekEy+QYCIHpX/Z6FkiHK0ZRevEJUGgCHzRqvgEBXN3Jr2WYbwL4IMShmGoxzSCn8VY9BkQ==
Exponent2: LDR9/tyu0vzuLwcommit 20B22FzNdd5rFF2wAQTQ0yF/3Baj5NAi9w84l0u07KgKQZX4g0N8qUyypnU5YDyzc6ZoagQ==
Coefficient: 6S0vhIQITWzqfQSLj+wwRzs6qCvJckHb1+SD1XpwYjSgMTEUlZhf96m8WiaE1/fIt4Zl2PC3fF7YIBoFLln22w=="}]}

Method: addDomainKey
Mandatory:

No

Parameters:

name, key=<flags,active,content>

Reply:

true for success, false for failure

Description

Adds key into local storage. See the section called “Method: getDomainKeys” for more information.

Example JSON/RPC:

Query:

{"method":"adddomainkey", "parameters":{"key":{"id":1,"flags":256,"active":true,"content":"Private-key-format: v1.2
Algorithm: 8 (RSASHA256)
Modulus: r+vmQll38ndQqNSCx9eqRBUbSOLcH4PZFX824sGhY2NSQChqt1G4ZfndzRwgjXMUwiE7GkkqU2Vbt/g4iP67V/+MYecMV9YHkCRnEzb47nBXvs9JCf8AHMCnma567GQjPECh4HevPE9wmcOfpy/u7UN1oHKSKRWuZJadUwcjbp8=
PublicExponent: AQAB
PrivateExponent: CY93UtVnOM6wrFJZ+qA9+Yx+p5yk0CSi0Q7c+/6EVMuABQ5gNyTuu0j65lU3X81bwUk2wHPx6smfgoVDRAW5jjO4jgIFV6nE4inzk5YQKycQSL8YG3Nm9GciLFya1KUXs81sHsQpkvK7MNaSbvkaHZQ6iv16bZ4t73Wascwa/E=
Prime1: 6a165cIC0nNsGlTW/s2jRu7idq5+U203iE1HzSIddmWgx5KIKE/s3I+pwfmXYRUmq+4H9ASd/Yot1lSYW98szw==
Prime2: wLoCPKxxnuxDx6/9IKOYz8t9ZNLY74iCeQ85koqvTctkFmB9jpOUHTU9BhecaFY2euP9CuHV7z3PLtCoO8s1MQ==
Exponent1: CuzJaiR/7UboLvL4ekEy+QYCIHpX/Z6FkiHK0ZRevEJUGgCHzRqvgEBXN3Jr2WYbwL4IMShmGoxzSCn8VY9BkQ==
Exponent2: LDR9/tyu0vzuLwcommit 20B22FzNdd5rFF2wAQTQ0yF/3Baj5NAi9w84l0u07KgKQZX4g0N8qUyypnU5YDyzc6ZoagQ==
Coefficient: 6S0vhIQITWzqfQSLj+wwRzs6qCvJckHb1+SD1XpwYjSgMTEUlZhf96m8WiaE1/fIt4Zl2PC3fF7YIBoFLln22w=="}}}

Response:

{"result":true}

Example HTTP/RPC:

Query:

POST /dnsapi/adddomainkey/example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 965

flags=256&active=1&content=Private-key-format: v1.2
Algorithm: 8 (RSASHA256)
Modulus: r+vmQll38ndQqNSCx9eqRBUbSOLcH4PZFX824sGhY2NSQChqt1G4ZfndzRwgjXMUwiE7GkkqU2Vbt/g4iP67V/+MYecMV9YHkCRnEzb47nBXvs9JCf8AHMCnma567GQjPECh4HevPE9wmcOfpy/u7UN1oHKSKRWuZJadUwcjbp8=
PublicExponent: AQAB
PrivateExponent: CY93UtVnOM6wrFJZ+qA9+Yx+p5yk0CSi0Q7c+/6EVMuABQ5gNyTuu0j65lU3X81bwUk2wHPx6smfgoVDRAW5jjO4jgIFV6nE4inzk5YQKycQSL8YG3Nm9GciLFya1KUXs81sHsQpkvK7MNaSbvkaHZQ6iv16bZ4t73Wascwa/E=
Prime1: 6a165cIC0nNsGlTW/s2jRu7idq5+U203iE1HzSIddmWgx5KIKE/s3I+pwfmXYRUmq+4H9ASd/Yot1lSYW98szw==
Prime2: wLoCPKxxnuxDx6/9IKOYz8t9ZNLY74iCeQ85koqvTctkFmB9jpOUHTU9BhecaFY2euP9CuHV7z3PLtCoO8s1MQ==
Exponent1: CuzJaiR/7UboLvL4ekEy+QYCIHpX/Z6FkiHK0ZRevEJUGgCHzRqvgEBXN3Jr2WYbwL4IMShmGoxzSCn8VY9BkQ==
Exponent2: LDR9/tyu0vzuLwcommit 20B22FzNdd5rFF2wAQTQ0yF/3Baj5NAi9w84l0u07KgKQZX4g0N8qUyypnU5YDyzc6ZoagQ==
Coefficient: 6S0vhIQITWzqfQSLj+wwRzs6qCvJckHb1+SD1XpwYjSgMTEUlZhf96m8WiaE1/fIt4Zl2PC3fF7YIBoFLln22w==

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8

{"result":true}

Method: removeDomainKey
Mandatory:

No

Parameters:

name, id

Reply:

true for success, false for failure

Description

Removes key id from domain name.

Example JSON/RPC:

Query:

{"method":"removedomainkey","parameters":"{"name":"example.com","id":1}}

Response:

{"result":true}

Example HTTP/RPC:

Query:

DELETE /dnsapi/removedomainkey/example.com/1 HTTP/1.1

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8

{"result":true}

Method: activateDomainKey
Mandatory:

No

Parameters:

name, id

Reply:

true for success, false for failure

Description

Activates key id for domain name.

Example JSON/RPC:

Query:

{"method":"activatedomainkey","parameters":{"name":"example.com","id":1}}

Response:

{"result":true}

Example HTTP/RPC:

Query:

POST /dnsapi/activatedomainkey/example.com/1 HTTP/1.1

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; utf-8

{"result": true}

Method deactivateDomainKey
Mandatory:

No

Parameters:

name, id

Reply:

true for success, false for failure

Description

Deactivates key id for domain name.

Example JSON/RPC:

Query:

{"method":"deactivatedomainkey","parameters":{"name":"example.com","id":1}}

Response:

{"result": true}

Example HTTP/RPC:

Query:

POST /dnsapi/deactivatedomainkey/example.com/1 HTTP/1.1

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; utf-8

{"result": true}

Method: getTSIGKey
Mandatory:

No

Parameters:

name

Reply:

algorithm, content

Description

Retrieves the key needed to sign AXFR.

Example JSON/RPC:

Query:

{"method":"gettsigkey","parameters":{"name":"example.com"}}

Response:

{"result":{"algorithm":"hmac-md5","content:"kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="}}

Example HTTP/RPC:

Query:

GET /dnsapi/gettsigkey/example.com

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8

{"result":{"algorithm":"hmac-md5","content:"kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="}}

Method: getDomainInfo
Mandatory:

No

Parameters:

name

Reply:

zone

Optional values:

serial, kind, id, notified_serial, last_check, masters

Description

Retrieves information about given domain from the backend. If your return value has no zone attribute, the backend will signal error. Everything else will default to something. Default values: serial:0, kind:NATIVE, id:-1, notified_serial:-1, last_check:0, masters: []. Masters, if present, must be array of strings.

Example JSON/RPC:

Query:

{"method":"getdomaininfo","parameters":{"name":"example.com"}}

Response:

{"result":{id:1,"zone":"example.com","kind":"NATIVE","serial":2002010100}}

Example HTTP/RPC:

Query:

GET /dnsapi/getdomaininfo/example.com HTTP/1.1

Response:

HTTP/1.1 200 OK
content-Type: text/javascript: charset=utf-8

{"result":{id:1,"zone":"example.com","kind":"NATIVE","serial":2002010100}}

Method: setNotified
Mandatory:

No

Parameters:

id, serial

Reply:

true for success, false for failure

Description

Updates last notified serial for the domain id. Any errors are ignored.

Example JSON/RPC:

Query:

{"method":"setnotified","parameters":{"id":1,"serial":2002010100}}

Response:

{"result":true}

Example HTTP/RPC:

Query:

POST /dnsapi/setnotified/1
Content-Type: application/x-www-form-urlencoded
Content-Length: 17

serial=2002010100

Response:

HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8

{"result":true}

15.4. Examples

Scenario: SOA lookup via pipe or unix

Query:

{ 
  "method": "lookup",
  "parameters": {
     "qname": "example.com", 
     "qtype": "SOA",
     "zone_id": "-1"
  }
}

Reply:

{
  "result": 
   [ 
     { "qtype": "SOA",
       "qname": "example.com", 
       "content": "dns1.icann.org. hostmaster.icann.org. 2012080849 7200 3600 1209600 3600",
       "ttl": 3600,
       "priority": 0,
       "domain_id": -1
     }
   ]
}

Scenario: SOA lookup via HTTP backend

Query:

/dns/lookup/example.com/SOA

Reply:

{
  "result":
   [
     { "qtype": "SOA",
       "qname": "example.com",
       "content": "dns1.icann.org. hostmaster.icann.org. 2012080849 7200 3600 1209600 3600",
       "ttl": 3600,
       "priority": 0,
       "domain_id": -1
     }
   ]
}