[Pdns-users] proof of concept: clone domains
Reinoud van Leeuwen
pdns at spoetnik.xs4all.nl
Wed Mar 3 14:59:03 UTC 2010
Hi,
Every now and then I tend to maintain domains that end up to be clones of
other domeins. The company has registered company.com, and wants the same
DNS records for company.net or maybe even brandx.com.
So I thought up a solution for this, implemented in the postgreSQL
backend: I replaced the table records with a view. This solution has the
following features:
- domain.org can be a clone of domain.com
- domain.org can have extra records that do not exist in domain.com
(hoeever: at this moment not the opposite)
at the moment it is not yet possible to 'override' a record in domain.org.
To avoid confusion, I used copcepts SOURCE and COPY, to avoid names like
MASTER and SLAVE.
-- NOTE: this is a PROOF OF CONCEPT. Not thoroughly tested. Not suitable
for production yet.
The main difference is the table virtdomains, that links a set of records
to multiple DNS zones.
This is the SQL I used.
create table supermasters (
ip VARCHAR(25) NOT NULL,
nameserver VARCHAR(255) NOT NULL,
account VARCHAR(40) DEFAULT NULL
);
GRANT SELECT ON supermasters TO pdns;
GRANT ALL ON domains_org TO pdns;
GRANT ALL ON domains_org_id_seq TO pdns;
GRANT ALL ON records_org TO pdns;
GRANT ALL ON records_org_id_seq TO pdns;
create table domains (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
master VARCHAR(128) DEFAULT NULL,
last_check INT DEFAULT NULL,
type VARCHAR(6) NOT NULL,
notified_serial INT DEFAULT NULL,
account VARCHAR(40) DEFAULT NULL
);
CREATE UNIQUE INDEX name_index ON domains(name);
create type virttype as enum ('SOURCE', 'COPY', 'EXTENSION');
-- this is an extra table that links DNS records to multiple zones.
-- SOURCE identifies a 'normal' zone.
-- COPY identifes that a zone is a copy of another (SOURCE) zone
-- EXTENSION makes it possible to add records to a copy zone that do not
exist in the SOURCE
create table virtdomains (
id SERIAL PRIMARY KEY,
domain_id INT DEFAULT NULL,
recordtype virttype default 'SOURCE',
copydomain_id INT DEFAULT NULL,
CONSTRAINT domain_exists
FOREIGN KEY(domain_id) REFERENCES domains(id)
ON DELETE CASCADE
);
-- todo: constraint to check that copydomain is not null
-- when recordtype = 'COPY'
-- todo: constraint to check that extension points to the same domain of
-- an existing copy zone
CREATE UNIQUE INDEX virt_domain_id ON virtdomains (domain_id,
recordtype);
CREATE TABLE realrecords (
id SERIAL PRIMARY KEY,
virtdomain_id INT DEFAULT NULL,
name VARCHAR(255) DEFAULT NULL,
type VARCHAR(6) DEFAULT NULL,
content VARCHAR(255) DEFAULT NULL,
ttl INT DEFAULT NULL,
prio INT DEFAULT NULL,
change_date INT DEFAULT NULL,
CONSTRAINT virtdomain_exists
FOREIGN KEY(virtdomain_id) REFERENCES virtdomains(id)
ON DELETE CASCADE
);
CREATE INDEX rec_name_index ON realrecords(name);
CREATE INDEX nametype_index ON realrecords(name,type);
CREATE INDEX domain_id ON realrecords(virtdomain_id);
create view records as
select d.id * 100000 + r.id as id,
v.domain_id as domain_id,
trim (leading '.' from r.name || '.' || d.name) as name,
r.type as type,
r.content as content,
r.ttl as ttl,
r.prio as prio,
r.change_date as change_date
from realrecords r,
virtdomains v,
domains d
where d.id = v.domain_id
and ( (v.recordtype in ('SOURCE', 'EXTENSION') and r.virtdomain_id =
v.id )
OR (v.recordtype = 'COPY' and r.virtdomain_id =
v.copydomain_id ));
-- todo: fix view to make sure a record in the extension zone has
-- precedence over SOURCE records
-- todo: create a rule so it is possible to do inserts in records table
-- insert some testdata:
-- we have 3 domains:
insert into domains (name, type)
values ('company.com', '');
insert into domains (name, type)
values ('company.net', '');
insert into domains (name, type)
values ('company.org', '');
-- company.com has copyzones company.net and company.org
insert into virtdomains (domain_id, recordtype)
select id, 'SOURCE'
from domains
where name = 'company.com';
insert into virtdomains (domain_id, recordtype, copydomain_id)
select d1.id, 'COPY', d2.id
from domains d1,
domains d2
where d1.name = 'company.net'
and d2.name = 'company.com';
insert into virtdomains (domain_id, recordtype, copydomain_id)
select d1.id, 'COPY', d2.id
from domains d1,
domains d2
where d1.name = 'company.org'
and d2.name = 'company.com';
-- make a virtual zone that extends the COPY zone company.org to hold
extra records only for company.org
insert into virtdomains (domain_id, recordtype)
select d1.id, 'EXTENSION'
from domains d1
where d1.name = 'company.org';
-- insert some DNS records for all zones:
insert into realrecords (virtdomain_id, name, type, content)
select v.id, '', 'SOA', 'ns1.company.com hostmaster.company.com
2010030301'
from virtdomains v,
domains d
where d.name = 'company.com'
and d.id = v.domain_id;
insert into realrecords (virtdomain_id, name, type, content)
select v.id, 'www', 'A', '192.168.1.1'
from virtdomains v,
domains d
where d.name = 'company.com'
and d.id = v.domain_id;
insert into realrecords (virtdomain_id, name, type, content)
select v.id, 'ftp', 'A', '192.168.1.2'
from virtdomains v,
domains d
where d.name = 'company.com'
and d.id = v.domain_id;
-- insert a record that only exists in the zone company.org
insert into realrecords (virtdomain_id, name, type, content)
select v.id, 'orgonly', 'A', '192.168.1.3'
from virtdomains v,
domains d
where d.name = 'company.org'
and d.id = v.domain_id
and v.recordtype = 'EXTENSION';
-- SQL check:
# select * from domains;
id | name | master | last_check | type | notified_serial | account
----+-------------+--------+------------+------+-----------------+---------
1 | company.com | | | | |
2 | company.net | | | | |
3 | company.org | | | | |
(3 rows)
^^ 3 domains (as expected)
# select id, domain_id, name, type, content from records ;
id | domain_id | name | type |
content
--------+-----------+---------------------+------+---------------------------------------------------
100001 | 1 | company.com | SOA | ns1.company.com
hostmaster.company.com 2010030301
100002 | 1 | www.company.com | A | 192.168.1.1
100003 | 1 | ftp.company.com | A | 192.168.1.2
200001 | 2 | company.net | SOA | ns1.company.com
hostmaster.company.com 2010030301
200002 | 2 | www.company.net | A | 192.168.1.1
200003 | 2 | ftp.company.net | A | 192.168.1.2
300001 | 3 | company.org | SOA | ns1.company.com
hostmaster.company.com 2010030301
300002 | 3 | www.company.org | A | 192.168.1.1
300003 | 3 | ftp.company.org | A | 192.168.1.2
300004 | 3 | orgonly.company.org | A | 192.168.1.3
(10 rows)
^^^
3 records for each domain, and 1 extra that only exists in de company.org
zone
(note that the ID is made unique here by adding the record id to 100,000
times the domain_id. Some tools
might rely on the fact that id is unique)
# select id, virtdomain_id, name, type, content from realrecords;
id | virtdomain_id | name | type | content
----+---------------+---------+------+---------------------------------------------------
1 | 1 | | SOA | ns1.company.com
hostmaster.company.com 2010030301
2 | 1 | www | A | 192.168.1.1
3 | 1 | ftp | A | 192.168.1.2
4 | 4 | orgonly | A | 192.168.1.3
(4 rows)
^^^
only 4 real records.
--
__________________________________________________
"Nothing is as subjective as reality"
Reinoud van Leeuwen reinoud.v at n.leeuwen.net
http://reinoud.van.leeuwen.net kvk 27320762
__________________________________________________
More information about the Pdns-users
mailing list