PowerDNS MongoDB

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску

PowerDNS + MongoDB

Требуется - настроить ДНС сервер который будет брать данные из Монго. Почему Монго - так хочет заказчик. Заполнять базу будет отдельное приложение, днс будет частью системы.

Сборка плагина

Ни одна из бинарных сборок которые я попробовал не включала плагина для работы с монго. В gentoo не было ключа для включение плагина при компиляции. Путь один - собирать сервер руками. (чуть позже - собрать пакет для своей системы, rpm )
Для сборки требуются исходники mongo. Я не нашел как передать путь к хедерам монго - насколько я могу судить путь захардкожен. Потому (знаю что не правильно) просто скопировал все хедеры в папку с плагином (/usr/src/pdns-3.0.1/modules/mongodbbackend/)
Далее традиционно

./configure
make

Обратить внимание на описание проблем со сборкой ниже - мне пришлось "патчить" модуль до рабочего состояния. Возможно вам не прийдется, или это особенность моего дистрибутива или сборки.
make install не делаю а беру модуль и подкладываю его там где ищет pdns_server

Ошибка в плагине

Мне пришлось закоментировать использование хинтов - с ними я получал ошибку:

Jun 08 14:15:19 [MONGODBBackend: (1)] (getSOA) Query: { name: "smtp-servers.example.com" }
Jun 08 14:15:19 [MONGODBBackend: (1)] (getSOA) Query: { name: "example.com" }
Jun 08 14:15:19 We have authority, zone='example.com', id=10
Jun 08 14:15:19 UeberBackend received question for ANY of smtp-servers.example.com
Jun 08 14:15:19 [MONGODBBackend: (1)] (lookup) Query: { query: { name: "smtp-servers.example.com" }, $hint: { name: 1 } }
Jun 08 14:15:19 Ueber get() was called for a ANY record
Jun 08 14:15:19 [MONGODBBackend: (1)] (get) Error: The record '{ $err: "bad hint", code: 10113 }' is missing required element(s) for the query '{ query: { name: "smtp-servers.example.com" }, $hint: { name: 1 } }'
Jun 08 14:15:19 UeberBackend reached end of backends
Jun 08 14:15:19 After first ANY query for 'smtp-servers.example.com', id=10: weDone=0, weHaveUnauth=0, weRedirected=0
Jun 08 14:15:19 Found nothing in the ANY, but let's try wildcards..
Jun 08 14:15:19 UeberBackend received question for ANY of *.example.com
Jun 08 14:15:19 [MONGODBBackend: (1)] (lookup) Query: { query: { name: "*.example.com" }, $hint: { name: 1 } }
Jun 08 14:15:19 Ueber get() was called for a ANY record
Jun 08 14:15:19 [MONGODBBackend: (1)] (get) Error: The record '{ $err: "bad hint", code: 10113 }' is missing required element(s) for the query '{ query: { name: "*.example.com" }, $hint: { name: 1 } }'
Jun 08 14:15:19 UeberBackend reached end of backends
Jun 08 14:15:19 Found nothing in the ANY and wildcards, let's try NS referral
Jun 08 14:15:19 UeberBackend received question for NS of smtp-servers.example.com
Jun 08 14:15:19 [MONGODBBackend: (1)] (lookup) Query: { query: { name: "smtp-servers.example.com", type: "NS" }, $hint: { name: 1, type: 1 } }
Jun 08 14:15:19 Ueber get() was called for a NS record
Jun 08 14:15:19 [MONGODBBackend: (1)] (get) Error: The record '{ $err: "bad hint", code: 10113 }' is missing required element(s) for the query '{ query: { name: "smtp-servers.example.com", type: "NS" }, $hint: { name: 1, type: 1 } }'

Насколько я могу понять - нужно писать hint { ... } а не $hint. Предположительно это баг.

В файле minimal.cc удалил строку:

mongo_query.hint(q_type == "ANY" ? BSON("name" << 1) : BSON("name" << 1 << "type" << 1));

MongoDB - минимальные записи записи

Для того что бы ДНС заработал нужно внести некоторое минимально число записей и описание зоны. в Монго при попытке вставить данные в несуществующий объект он будет создан что несколько упрощает жизнь.
Имена используемых коллекций я не менял: (определяется в конфиге PowerDNS вероятно).

collection-domains = domains
collection-records = records
collection-domainmetadata = domainmetadata
collection-cryptokeys = cryptokeys
collection-tsigkeys = tsigkeys


Работа с монго из консоли - заполнить зону

mongo - утилита для работы из консоли. Тут короткое описание как вставлять записи. Пример со вставкой полдразумевает что зона уже создана и сервер стартован.
Использовать правильную базу:

use dns

Проверяю что записи нет:

sirmax@sirmax ~ $ host start4.example.com 192.168.15.1
Using domain server:
Name: 192.168.15.1
Address: 192.168.15.1#53
Aliases: 

Определяю переменную, а потом вствляю ее:

#mongo
> test = {"domain_id" : 10, "name" : "start4.example.com", "type" : "A", "ttl" : 120, "content" : [ {"data" : "192.168.2.2"} ] }
{
	"domain_id" : 10,
	"name" : "start4.example.com",
	"type" : "A",
	"ttl" : 120,
	"content" : [
		{
			"data" : "192.168.2.2"
		}
	]
}
>db.records.insert(test)
>db.records.find();
<skipped>
{ "_id" : ObjectId("4fd1fb484a6ee59df5031fea"), "domain_id" : 10, "name" : "start4.example.com", "type" : "A", "ttl" : 120, "content" : [ { "data" : "192.168.2.2" } ] }
sirmax@sirmax ~ $ host start4.example.com 192.168.15.1
Using domain server:
Name: 192.168.15.1
Address: 192.168.15.1#53
Aliases: 

start4.example.com has address 192.168.2.2

Я сделал следующие записи:

domains

{"domain_id" : 10, "name" : "example.com", "type" : "NATIVE", "ttl" : 120, "SOA" : {"hostmaster" : "ahu.example.com", "nameserver" : "ns1.example.com", "serial" : 2000081501, "refresh" : 28800, "retry" : 7200, "expire" : 604800, "default_ttl" : 86400 } }
{"domain_id" : 10, "name" : "example.com", "type" : "NS", "ttl" : 120, "content" : [ {"data" : "ns1.example.com"}, {"data" : "ns2.example.com"} ] }
{"domain_id" : 10, "name" : "example.com", "type" : "MX", "ttl" : 120, "content" : [ {"prio" : 10, "data" : "smtp-servers.example.com"}, {"prio" : 15, "data" : "smtp-servers.test.com"} ] }
{"domain_id" : 10, "name" : "ns1.example.com", "type" : "A", "ttl" : 120, "content" : [ {"data" : "192.168.1.1"} ] }
{"domain_id" : 10, "name" : "ns2.example.com", "type" : "A", "ttl" : 120, "content" : [ {"data" : "192.168.1.2"} ] }
{"domain_id" : 10, "name" : "smtp-servers.example.com", "type" : "A", "ttl" : 120, "content" : [ {"data" : "192.168.0.2"}, {"data" : "192.168.0.3"}, {"data" : "192.168.0.4"} ] }


records

{"domain_id" : 10, "name" : "example.com", "type" : "NS", "ttl" : 120, "content" : [ {"data" : "ns1.example.com"}, {"data" : "ns2.example.com"} ] }
{"domain_id" : 10, "name" : "example.com", "type" : "MX", "ttl" : 120, "content" : [ {"prio" : 10, "data" : "smtp-servers.example.com"}, {"prio" : 15, "data" : "smtp-servers.test.com"} ] }
{"domain_id" : 10, "name" : "ns1.example.com", "type" : "A", "ttl" : 120, "content" : [ {"data" : "192.168.1.1"} ] }
{"domain_id" : 10, "name" : "ns2.example.com", "type" : "A", "ttl" : 120, "content" : [ {"data" : "192.168.1.2"} ] }
{"domain_id" : 10, "name" : "smtp-servers.example.com", "type" : "A", "ttl" : 120, "content" : [ {"data" : "192.168.0.2"}, {"data" : "192.168.0.3"}, {"data" : "192.168.0.4"} ] }
 db.records.find();
{ "_id" : ObjectId("4fd1dae01ac5e9baad14dc49"), "domain_id" : 10, "name" : "smtp-servers.example.com", "type" : "A", "ttl" : 120, "content" : [ 	{ 	"data" : "192.168.0.2" }, 	{ 	"data" : "192.168.0.3", 	"ttl" : 60 }, 	{ 	"data" : "192.168.0.4" } ] }
{ "_id" : ObjectId("4fd1dccd1ac5e9baad14dc4a"), "domain_id" : 10, "name" : "ns1.example.com", "type" : "A", "ttl" : 120, "content" : [ { "data" : "192.168.1.1" } ] }
{ "_id" : ObjectId("4fd1dce71ac5e9baad14dc4b"), "domain_id" : 10, "name" : "example.com", "type" : "NS", "ttl" : 120, "content" : [ { "data" : "ns1.example.com" }, { "data" : "ns2.example.com" } ] }
{ "_id" : ObjectId("4fd1dd7a1ac5e9baad14dc4c"), "domain_id" : 10, "name" : "ns2.example.com", "type" : "A", "ttl" : 120, "content" : [ { "data" : "192.168.1.2" } ] }
{ "_id" : ObjectId("4fd1de521ac5e9baad14dc4d"), "domain_id" : 10, "name" : "example.com", "type" : "NS", "ttl" : 120, "content" : [ { "data" : "ns1.example.com" }, { "data" : "ns2.example.com" } ] }

Думаю, вцелом все более-менее ясно. Примеры записей есть тут: http://wiki.powerdns.com/trac/browser/trunk/pdns/modules/mongodbbackend/test Так же есть примеры с работой с json и заливкой данных.

rpm для CentOS

Со сборкой RPM пришлось повозиться. отмечу что для сборки нужен g++ Кроме того - несколько патчей.

pdns.spec

Summary:	A modern, advanced and high performance authoritative-only nameserver
Name:		pdns
Version:	3.1
Release:	10%{?dist}

Group:		System Environment/Daemons
License:	GPLv2
URL:		http://powerdns.com
BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Source0:	http://downloads.powerdns.com/releases/%{name}-%{version}.tar.gz
#Patch0:		%{name}-fixinit.patch
#Patch1:		%{name}-gcc44.patch
#Patch2:		pdns-fix-postgres-detection.patch
#Patch3:		pdns-fix-crash-on-sigstop.patch
Patch0:         pdns-fix-mongo-backend.patch
Patch1:		pdns-fix-md5sum-bug.patch
Patch2:		pdns-fix-hint.patch
#Patch1:         pdns-fix-lua-detection.patch



Requires(post):	%{_sbindir}/useradd, /sbin/chkconfig
Requires(preun):	/sbin/service, /sbin/chkconfig

BuildRequires:	boost-devel, chrpath
Provides:	powerdns = %{version}-%{release}

%description
The PowerDNS Nameserver is a modern, advanced and high performance
authoritative-only nameserver. It is written from scratch and conforms
to all relevant DNS standards documents.
Furthermore, PowerDNS interfaces with almost any database.

%package	backend-mysql
Summary:	MySQL backend for %{name}
Group:		System Environment/Daemons
Requires:	%{name} = %{version}-%{release}
BuildRequires:	mysql-devel

%package	backend-postgresql
Summary:	PostgreSQL backend for %{name}
Group:		System Environment/Daemons
Requires:	%{name} = %{version}-%{release}
BuildRequires:	postgresql-devel

%package	backend-pipe
Summary:	Pipe backend for %{name}
Group:		System Environment/Daemons
Requires:	%{name} = %{version}-%{release}

%package	backend-geo
Summary:	Geo backend for %{name}
Group:		System Environment/Daemons
Requires:	%{name} = %{version}-%{release}

%package	backend-ldap
Summary:	LDAP backend for %{name}
Group:		System Environment/Daemons
Requires:	%{name} = %{version}-%{release}
BuildRequires:	openldap-devel

%package	backend-sqlite
Summary:	SQLite backend for %{name}
Group:		System Environment/Daemons
Requires:	%{name} = %{version}-%{release}
BuildRequires:	sqlite-devel


%package	backend-mongodb
Summary:	MongoDB backend for %{name}
Group:		System Environment/Daemons
Requires:	%{name}%{?_isa} = %{version}-%{release}
BuildRequires:	mongodb-devel

%description	backend-mysql
This package contains the gmysql backend for %{name}

%description	backend-postgresql
This package contains the gpgsql backend for %{name}

%description	backend-pipe
This package contains the pipe backend for %{name}

%description	backend-geo
This package contains the geo backend for %{name}
It allows different answers to DNS queries coming from different
IP address ranges or based on the geographic location

%description	backend-ldap
This package contains the ldap backend for %{name}

%description	backend-sqlite
This package contains the SQLite backend for %{name}

%description    backend-mongodb
This package contains the MongoDB backend for %{name}


%prep
%setup -q
%patch0 -p1 -b .fixmongo
%patch1 -p1 -b .fixmd5
%patch2 -p1 -b .fixhint

#%patch1 -p1 -b .fixlua
#%patch0 -p1 -b .fixinit
#%patch1 -p1 -b .gcc44
#%patch2 -p1 -b .postgres
#%patch3 -p1 -b .sigstop

%build
export CPPFLAGS="-DLDAP_DEPRECATED %{optflags}"

%configure  \
	--sysconfdir=%{_sysconfdir}/%{name} \
	--libdir=%{_libdir}/%{name} \
	--disable-static \
	--with-modules='' \
	--with-dynmodules='pipe gmysql gpgsql geo ldap gsqlite3 mongodb' \
	--with-mysql-lib=%{_libdir}/mysql \
	--with-sqlite3-lib=%{_libdir}


#sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool
#sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool

make %{?_smp_mflags}

%install
%{__rm} -rf %{buildroot}
make install DESTDIR=%{buildroot}

%{__rm} -f %{buildroot}%{_libdir}/%{name}/*.la
%{__install} -p -D -m 0755 pdns/pdns %{buildroot}%{_initrddir}/pdns
%{__mv} %{buildroot}%{_sysconfdir}/%{name}/pdns.conf{-dist,}

# add the pdns user to the config file
sed -i '1i\setuid=pdns' %{buildroot}%{_sysconfdir}/%{name}/pdns.conf
sed -i '2i\setgid=pdns' %{buildroot}%{_sysconfdir}/%{name}/pdns.conf

# strip the static rpath from the binaries
chrpath --delete %{buildroot}%{_bindir}/pdns_control
chrpath --delete %{buildroot}%{_bindir}/zone2ldap
chrpath --delete %{buildroot}%{_bindir}/zone2sql
chrpath --delete %{buildroot}%{_sbindir}/pdns_server
chrpath --delete %{buildroot}%{_libdir}/%{name}/*.so

%post
if [ $1 -eq 1 ]; then
	/sbin/chkconfig --add pdns
	userid=`id -u pdns 2>/dev/null`
	if [ x"$userid" = x ]; then
		%{_sbindir}/useradd -c "PowerDNS user" -s /sbin/nologin -r -d / pdns > /dev/null || :
	fi
fi
%preun
if [ $1 -eq 0 ]; then
	/sbin/service pdns stop >/dev/null 2>&1 || :
	/sbin/chkconfig --del pdns
fi

%clean
%{__rm} -rf %{buildroot}

%files
%defattr(-,root,root,-)
#%doc ChangeLog TODO pdns/COPYING
%{_bindir}/pdns_control
%{_bindir}/zone2ldap
%{_bindir}/zone2sql
%{_bindir}/dnsreplay
%{_bindir}/pdnssec
%{_sbindir}/pdns_server
%{_mandir}/man8/pdns_control.8.gz
%{_mandir}/man8/pdns_server.8.gz
%{_mandir}/man8/zone2sql.8.gz
%{_initrddir}/pdns
%dir %{_libdir}/%{name}/
%dir %{_sysconfdir}/%{name}/
%config(noreplace) %{_sysconfdir}/%{name}/pdns.conf

%files backend-mysql
%defattr(-,root,root,-)
#%doc pdns/COPYING
%{_libdir}/%{name}/libgmysqlbackend.so

%files backend-postgresql
%defattr(-,root,root,-)
#%doc pdns/COPYING
%{_libdir}/%{name}/libgpgsqlbackend.so

%files backend-pipe
%defattr(-,root,root,-)
#%doc pdns/COPYING
%{_libdir}/%{name}/libpipebackend.so

%files backend-geo
%defattr(-,root,root,-)
#%doc pdns/COPYING modules/geobackend/README
%{_libdir}/%{name}/libgeobackend.so

%files backend-ldap
%defattr(-,root,root,-)
#%doc pdns/COPYING
%{_libdir}/%{name}/libldapbackend.so

%files backend-sqlite
%defattr(-,root,root,-)
#%doc pdns/COPYING
%{_libdir}/%{name}/libgsqlite3backend.so

%files backend-mongodb
%defattr(-,root,root,-)
%{_libdir}/%{name}/libmongodbbackend.so


%changelog


https://blog.benetasso.com/en/entry/mongodb_backend_2