Difference between revisions of "Network/DNS"

From LunaSys
Jump to navigation Jump to search
(Created page with "== PowerDNS == MySQL tables (and samples): <pre> DROP TABLE IF EXISTS `domains`; →‎!40101 SET @saved_cs_client = @@character_set_client: ; /*!40101 SET character_set_cli...")
 
 
(12 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
== Bind ==
 +
 +
=== Configuration ===
 +
 +
Keep only the following 2 lines in '''named.conf''':
 +
<pre>
 +
include "/etc/bind/named.conf.options";
 +
include "/etc/bind/named.conf.local";
 +
</pre>
 +
 +
Replace the content of '''named.conf.local''' by:
 +
<pre>
 +
include "/etc/bind/geoip/GeoIP.acl";
 +
include "/etc/bind/geoip/GeoIPv6.acl";
 +
 +
logging {
 +
  channel simple_log {
 +
    file "/var/log/named/bind.log" versions 3 size 5m;
 +
    //severity client;
 +
    print-time yes;
 +
    print-severity yes;
 +
    print-category yes;
 +
  };
 +
  category default{
 +
    simple_log;
 +
  };
 +
};
 +
 +
 +
view "America" {
 +
match-clients { US; CA; };
 +
recursion no;
 +
include "/etc/bind/named.conf.default-zones";
 +
//include "/etc/bind/named.conf.zones";
 +
zone "lunasys.fr" {
 +
  type master;
 +
  file "/etc/bind/geoip/us.lunasys.fr.hosts";
 +
};
 +
};
 +
 +
 +
view "Asia" {
 +
match-clients { HK; CN; };
 +
recursion no;
 +
include "/etc/bind/named.conf.default-zones";
 +
//include "/etc/bind/named.conf.zones";
 +
zone "lunasys.fr" {
 +
  type master;
 +
  file "/etc/bind/geoip/as.lunasys.fr.hosts";
 +
};
 +
};
 +
 +
 +
view "Europe" {
 +
match-clients { FR; };
 +
recursion no;
 +
include "/etc/bind/named.conf.default-zones";
 +
//include "/etc/bind/named.conf.zones";
 +
zone "lunasys.fr" {
 +
  type master;
 +
  file "/etc/bind/geoip/eu.lunasys.fr.hosts";
 +
};
 +
};
 +
 +
 +
view "Default" {
 +
match-clients { any; };
 +
recursion no;
 +
include "/etc/bind/named.conf.default-zones";
 +
//include “/etc/bind/named.conf.zones";
 +
zone "lunasys.fr" {
 +
  type master;
 +
  file "/etc/bind/geoip/us.lunasys.fr.hosts";
 +
};
 +
};
 +
</pre>
 +
 +
Create the log directory:
 +
 +
mkdir /var/log/named
 +
chown bind /var/log/named
 +
 +
 +
Setup all the zone files, with for example the file '''geoip/us.lunasys.fr.hosts''' for the US zone:
 +
<pre>
 +
$TTL 86400 ; 24 hours could have been written as 24h or 1d
 +
$ORIGIN lunasys.fr.
 +
@  1D  IN SOA ns1.lunasys.fr. hostmaster.lunasys.fr. (
 +
      2002022401 ; serial
 +
      3H ; refresh
 +
      15 ; retry
 +
      1w ; expire
 +
      3h ; minimum
 +
    )
 +
      IN  NS    ns1.lunasys.fr.    ; in the domain
 +
      IN  MX  10 mail.google.com.
 +
; server host definitions
 +
ns1    IN  A      198.245.55.128
 +
yuki    IN  A    103.5.15.123
 +
yuko    IN  A    198.245.55.128
 +
</pre>
 +
 +
=== GeoIP database ===
 +
 +
Then write the GeoIP.acl and GeoIPv6.acl files with the following scripts.
 +
 +
These scripts are from [http://phix.me/geodns/ here].
 +
 +
'''geoip.sh''':
 +
<pre>
 +
#!/bin/bash
 +
 +
[ -f GeoIPCountryCSV.zip ] || wget -T 5 -t 1 http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
 +
 +
echo -n "Creating CBE (Country,Begin,End) CSV file..."
 +
unzip -p GeoIPCountryCSV.zip GeoIPCountryWhois.csv | awk -F \" '{print $10","$6","$8}' > cbe.csv
 +
echo -ne "DONE\nGenerating BIND GeoIP.acl file..."
 +
 +
(for c in $(awk -F , '{print $1}' cbe.csv | sort -u)
 +
do
 +
  echo "acl \"$c\" {"
 +
  grep "^$c," cbe.csv | awk -F , 'function s(b,e,l,m,n) {l = int(log(e-b+1)/log(2)); m = 2^32-2^l; n = and(m,e); if (n == and(m,b)) printf "\t%u.%u.%u.%u/%u;\n",b/2^24%256,b/2^16%256,b/2^8%256,b%256,32-l; else {s(b,n-1); s(n,e)}} s($2,$3)'
 +
  echo -e "};\n"
 +
done) > GeoIP.acl
 +
 +
rm -f cbe.csv
 +
echo "DONE"
 +
 +
exit 0
 +
</pre>
 +
 +
 +
'''geoip_v6.py''':
 +
<pre>
 +
#!/usr/bin/python
 +
 +
from sys import stdin
 +
from mpmath import mag
 +
 +
def s(b,e):
 +
    l = mag(e-b+1)-1
 +
    m = 2**128-2**l
 +
    n = m & e
 +
 +
    if n == m & b:
 +
        print '\t%x:%x:%x:%x:%x:%x:%x:%x/%u;' % tuple([b/2**p%65536 for p in xrange(112,-1,-16)]+[128-l])
 +
    else:
 +
        s(b,n-1)
 +
        s(n,e)
 +
</pre>
 +
 +
'''geoip_v6.sh''':
 +
<pre>
 +
for r in (map(int,l.split(',')[1:3]) for l in stdin): s(*r)
 +
#!/bin/bash
 +
 +
d=http://geolite.maxmind.com/download/geoip/database/
 +
f=$(wget -qT 5 -t 1 -O- $d | egrep -o 'GeoIPv6-[0-9]{8}\.csv\.gz' | sort -r | head -1)
 +
[ -z "$f" ] && exit 1; [ -f $f ] || wget -T 5 -t 1 $d$f || exit 1
 +
 +
echo -n "Creating CBE (Country,Begin,End) CSV file..."
 +
gunzip -c $f | awk -F \" '{print $10","$6","$8}' > cbe.csv
 +
echo -e "DONE\nGenerating BIND GeoIPv6.acl file..."
 +
 +
(for c in $(awk -F , '{print $1}' cbe.csv | sort -u)
 +
do
 +
  echo "$c" >&2
 +
  echo "acl \"${c}v6\" {"
 +
  grep "^$c," cbe.csv | ./geoip_v6.py | sed 's \(:0\)\+/ ::/ '
 +
  echo -e "};\n"
 +
done) > GeoIPv6.acl
 +
 +
rm -f cbe.csv
 +
echo "DONE"
 +
 +
exit 0
 +
</pre>
 +
 +
Move into '''/etc/bind/geoip''' in which the 3 scripts above must be present, and run both '''geoip_v6.sh''' and '''geoip_v6.sh'''. This will generate GeoIP.acl and GeoIPv6.acl.
 +
 
== PowerDNS ==
 
== PowerDNS ==
  
MySQL tables (and samples):
+
=== Installation (Debian) ===
 +
 
 +
Install the package (tested in squeeze):
 +
 
 +
apt-get install pdns-server pdns-backend-geo pdns-backend-mysql mysql-server
 +
 
 +
=== General Configuration ===
 +
 
 +
Setup basic configuration in '''/etc/powerdns/pdns.conf''':
 +
<pre>
 +
allow-recursion=127.0.0.1
 +
config-dir=/etc/powerdns
 +
daemon=yes
 +
disable-axfr=yes
 +
guardian=yes
 +
lazy-recursion=yes
 +
local-address=0.0.0.0
 +
local-port=53
 +
loglevel=8
 +
module-dir=/usr/lib/powerdns
 +
setgid=pdns
 +
setuid=pdns
 +
socket-dir=/var/run
 +
webserver=yes
 +
webserver-address=0.0.0.0
 +
webserver-password=<pass>
 +
webserver-port=8080
 +
version-string=powerdns
 +
launch=gmysql,geo
 +
include=/etc/powerdns/pdns.d
 +
</pre>
 +
 
 +
=== MySQL ===
 +
 
 +
Create the base MySQL tables (and samples):
 
<pre>
 
<pre>
 
DROP TABLE IF EXISTS `domains`;
 
DROP TABLE IF EXISTS `domains`;
/*!40101 SET @saved_cs_client    = @@character_set_client */;
 
/*!40101 SET character_set_client = utf8 */;
 
 
CREATE TABLE `domains` (
 
CREATE TABLE `domains` (
 
   `id` int(11) NOT NULL AUTO_INCREMENT,
 
   `id` int(11) NOT NULL AUTO_INCREMENT,
Line 17: Line 229:
 
   UNIQUE KEY `name_index` (`name`)
 
   UNIQUE KEY `name_index` (`name`)
 
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
 
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
 
INSERT INTO `domains` VALUES (1,'lunasys.fr',NULL,NULL,'NATIVE',NULL,NULL);
 
 
  
 
DROP TABLE IF EXISTS `records`;
 
DROP TABLE IF EXISTS `records`;
/*!40101 SET @saved_cs_client    = @@character_set_client */;
 
/*!40101 SET character_set_client = utf8 */;
 
 
CREATE TABLE `records` (
 
CREATE TABLE `records` (
 
   `id` int(11) NOT NULL AUTO_INCREMENT,
 
   `id` int(11) NOT NULL AUTO_INCREMENT,
Line 38: Line 245:
 
   KEY `domain_id` (`domain_id`)
 
   KEY `domain_id` (`domain_id`)
 
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
 
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
 
INSERT INTO `records` VALUES (3,1,'as.www.lunasys.fr','A','3.1.1.1',600,NULL,NULL),(4,1,'us.www.lunasys.fr','A','2.1.1.1',600,NULL,NULL),(5,1,'eu.www.lunasys.fr','A','4.1.1.1',600,NULL,NULL);
 
 
  
 
DROP TABLE IF EXISTS `supermasters`;
 
DROP TABLE IF EXISTS `supermasters`;
/*!40101 SET @saved_cs_client    = @@character_set_client */;
 
/*!40101 SET character_set_client = utf8 */;
 
 
CREATE TABLE `supermasters` (
 
CREATE TABLE `supermasters` (
 
   `ip` varchar(25) NOT NULL,
 
   `ip` varchar(25) NOT NULL,
Line 52: Line 254:
 
</pre>
 
</pre>
  
 +
Grant access to a specific user:
 +
<pre>
 +
GRANT ALL ON pdns.* TO pdns@localhost IDENTIFIED BY '<pass>';
 +
</pre>
  
/etc/powerdns/pdns.conf
+
You can also insert some records for tests:
 
<pre>
 
<pre>
allow-recursion=127.0.0.1
+
INSERT INTO `domains` VALUES (1,'lunasys.fr',NULL,NULL,'NATIVE',NULL,NULL);
config-dir=/etc/powerdns
+
INSERT INTO `records` VALUES (3,1,'as.www.lunasys.fr','A','3.1.1.1',600,NULL,NULL),
daemon=yes
+
(4,1,'us.www.lunasys.fr','A','2.1.1.1',600,NULL,NULL),
disable-axfr=yes
+
(5,1,'eu.www.lunasys.fr','A','4.1.1.1',600,NULL,NULL);
guardian=yes
+
</pre>
lazy-recursion=yes
+
 
local-address=0.0.0.0
+
Then, in '''pdns.d/pdns.local''', add:
local-port=53
+
 
loglevel=8
+
<pre>
module-dir=/usr/lib/powerdns
+
gmysql-host=127.0.0.1
setgid=pdns
+
gmysql-user=pdns
setuid=pdns
+
gmysql-password=<pass>
socket-dir=/var/run
+
gmysql-dbname=pdns
webserver=yes
 
webserver-address=0.0.0.0
 
webserver-password=<pass>
 
webserver-port=8080
 
version-string=powerdns
 
launch=gmysql,geo
 
include=/etc/powerdns/pdns.d
 
 
</pre>
 
</pre>
  
pdns.d/pdns.local
+
=== Geo ===
 +
 
 +
In '''pdns.d/pdns.local''', add:
  
 
<pre>
 
<pre>
Line 84: Line 285:
 
geo-ip-map-zonefile=/etc/powerdns/zz.countries.nerd.dk.rbldnsd
 
geo-ip-map-zonefile=/etc/powerdns/zz.countries.nerd.dk.rbldnsd
 
geo-maps=/etc/powerdns/geo-maps
 
geo-maps=/etc/powerdns/geo-maps
 
gmysql-host=127.0.0.1
 
gmysql-user=root
 
gmysql-password=<pass>
 
gmysql-dbname=pdns
 
 
</pre>
 
</pre>
  
geo-maps/lunasys
+
Write '''geo-maps/lunasys''':
  
 
<pre>
 
<pre>
Line 103: Line 299:
 
0 eu.www
 
0 eu.www
 
</pre>
 
</pre>
 +
 +
Finally retrieve countries zone file with the following rsync command:
 +
 +
rsync -avz rsync://countries-ns.mdc.dk/zone .
 +
 +
And copy the '''zz.countries.nerd.dk.rbldnsd''' in '''/etc/powerdns/'''

Latest revision as of 13:44, 24 June 2012

Bind

Configuration

Keep only the following 2 lines in named.conf:

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";

Replace the content of named.conf.local by:

include "/etc/bind/geoip/GeoIP.acl";
include "/etc/bind/geoip/GeoIPv6.acl";

logging {
  channel simple_log {
    file "/var/log/named/bind.log" versions 3 size 5m;
    //severity client;
    print-time yes;
    print-severity yes;
    print-category yes;
  };
  category default{
    simple_log;
  };
};


view "America" {
 match-clients { US; CA; };
 recursion no;
 include "/etc/bind/named.conf.default-zones";
 //include "/etc/bind/named.conf.zones";
 zone "lunasys.fr" {
  type master;
  file "/etc/bind/geoip/us.lunasys.fr.hosts";
 };
};


view "Asia" {
 match-clients { HK; CN; };
 recursion no;
 include "/etc/bind/named.conf.default-zones";
 //include "/etc/bind/named.conf.zones";
 zone "lunasys.fr" {
  type master;
  file "/etc/bind/geoip/as.lunasys.fr.hosts";
 };
};


view "Europe" {
 match-clients { FR; };
 recursion no;
 include "/etc/bind/named.conf.default-zones";
 //include "/etc/bind/named.conf.zones";
 zone "lunasys.fr" {
  type master;
  file "/etc/bind/geoip/eu.lunasys.fr.hosts";
 };
};


view "Default" {
 match-clients { any; };
 recursion no;
 include "/etc/bind/named.conf.default-zones";
 //include “/etc/bind/named.conf.zones";
 zone "lunasys.fr" {
  type master;
  file "/etc/bind/geoip/us.lunasys.fr.hosts";
 };
};

Create the log directory:

mkdir /var/log/named
chown bind /var/log/named


Setup all the zone files, with for example the file geoip/us.lunasys.fr.hosts for the US zone:

$TTL	86400 ; 24 hours could have been written as 24h or 1d
$ORIGIN lunasys.fr.
@  1D  IN	 SOA ns1.lunasys.fr.	hostmaster.lunasys.fr. (
			      2002022401 ; serial
			      3H ; refresh
			      15 ; retry
			      1w ; expire
			      3h ; minimum
			     )
       IN  NS     ns1.lunasys.fr.    ; in the domain
       IN  MX  10 mail.google.com.
; server host definitions
ns1    IN  A      198.245.55.128
yuki    IN  A     103.5.15.123
yuko    IN  A     198.245.55.128

GeoIP database

Then write the GeoIP.acl and GeoIPv6.acl files with the following scripts.

These scripts are from here.

geoip.sh:

#!/bin/bash

[ -f GeoIPCountryCSV.zip ] || wget -T 5 -t 1 http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip

echo -n "Creating CBE (Country,Begin,End) CSV file..."
unzip -p GeoIPCountryCSV.zip GeoIPCountryWhois.csv | awk -F \" '{print $10","$6","$8}' > cbe.csv
echo -ne "DONE\nGenerating BIND GeoIP.acl file..."

(for c in $(awk -F , '{print $1}' cbe.csv | sort -u)
do
  echo "acl \"$c\" {"
  grep "^$c," cbe.csv | awk -F , 'function s(b,e,l,m,n) {l = int(log(e-b+1)/log(2)); m = 2^32-2^l; n = and(m,e); if (n == and(m,b)) printf "\t%u.%u.%u.%u/%u;\n",b/2^24%256,b/2^16%256,b/2^8%256,b%256,32-l; else {s(b,n-1); s(n,e)}} s($2,$3)'
  echo -e "};\n"
done) > GeoIP.acl

rm -f cbe.csv
echo "DONE"

exit 0


geoip_v6.py:

#!/usr/bin/python

from sys import stdin
from mpmath import mag

def s(b,e):
    l = mag(e-b+1)-1
    m = 2**128-2**l
    n = m & e

    if n == m & b:
        print '\t%x:%x:%x:%x:%x:%x:%x:%x/%u;' % tuple([b/2**p%65536 for p in xrange(112,-1,-16)]+[128-l])
    else:
        s(b,n-1)
        s(n,e)

geoip_v6.sh:

for r in (map(int,l.split(',')[1:3]) for l in stdin): s(*r)
#!/bin/bash

d=http://geolite.maxmind.com/download/geoip/database/
f=$(wget -qT 5 -t 1 -O- $d | egrep -o 'GeoIPv6-[0-9]{8}\.csv\.gz' | sort -r | head -1)
[ -z "$f" ] && exit 1; [ -f $f ] || wget -T 5 -t 1 $d$f || exit 1

echo -n "Creating CBE (Country,Begin,End) CSV file..."
gunzip -c $f | awk -F \" '{print $10","$6","$8}' > cbe.csv
echo -e "DONE\nGenerating BIND GeoIPv6.acl file..."

(for c in $(awk -F , '{print $1}' cbe.csv | sort -u)
do
  echo "$c" >&2
  echo "acl \"${c}v6\" {"
  grep "^$c," cbe.csv | ./geoip_v6.py | sed 's \(:0\)\+/ ::/ '
  echo -e "};\n"
done) > GeoIPv6.acl

rm -f cbe.csv
echo "DONE"

exit 0

Move into /etc/bind/geoip in which the 3 scripts above must be present, and run both geoip_v6.sh and geoip_v6.sh. This will generate GeoIP.acl and GeoIPv6.acl.

PowerDNS

Installation (Debian)

Install the package (tested in squeeze):

apt-get install pdns-server pdns-backend-geo pdns-backend-mysql mysql-server

General Configuration

Setup basic configuration in /etc/powerdns/pdns.conf:

allow-recursion=127.0.0.1
config-dir=/etc/powerdns
daemon=yes
disable-axfr=yes
guardian=yes
lazy-recursion=yes
local-address=0.0.0.0
local-port=53
loglevel=8
module-dir=/usr/lib/powerdns
setgid=pdns
setuid=pdns
socket-dir=/var/run
webserver=yes
webserver-address=0.0.0.0
webserver-password=<pass>
webserver-port=8080
version-string=powerdns
launch=gmysql,geo
include=/etc/powerdns/pdns.d

MySQL

Create the base MySQL tables (and samples):

DROP TABLE IF EXISTS `domains`;
CREATE TABLE `domains` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `master` varchar(128) DEFAULT NULL,
  `last_check` int(11) DEFAULT NULL,
  `type` varchar(6) NOT NULL,
  `notified_serial` int(11) DEFAULT NULL,
  `account` varchar(40) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name_index` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

DROP TABLE IF EXISTS `records`;
CREATE TABLE `records` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `domain_id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `type` varchar(10) DEFAULT NULL,
  `content` varchar(64000) DEFAULT NULL,
  `ttl` int(11) DEFAULT NULL,
  `prio` int(11) DEFAULT NULL,
  `change_date` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `rec_name_index` (`name`),
  KEY `nametype_index` (`name`,`type`),
  KEY `domain_id` (`domain_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

DROP TABLE IF EXISTS `supermasters`;
CREATE TABLE `supermasters` (
  `ip` varchar(25) NOT NULL,
  `nameserver` varchar(255) NOT NULL,
  `account` varchar(40) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Grant access to a specific user:

GRANT ALL ON pdns.* TO pdns@localhost IDENTIFIED BY '<pass>';

You can also insert some records for tests:

INSERT INTO `domains` VALUES (1,'lunasys.fr',NULL,NULL,'NATIVE',NULL,NULL);
INSERT INTO `records` VALUES (3,1,'as.www.lunasys.fr','A','3.1.1.1',600,NULL,NULL),
(4,1,'us.www.lunasys.fr','A','2.1.1.1',600,NULL,NULL),
(5,1,'eu.www.lunasys.fr','A','4.1.1.1',600,NULL,NULL);

Then, in pdns.d/pdns.local, add:

gmysql-host=127.0.0.1
gmysql-user=pdns
gmysql-password=<pass>
gmysql-dbname=pdns

Geo

In pdns.d/pdns.local, add:

geo-zone=lunasys.fr
#geo-ns-records=ns0.lunasys.fr
geo-ip-map-zonefile=/etc/powerdns/zz.countries.nerd.dk.rbldnsd
geo-maps=/etc/powerdns/geo-maps

Write geo-maps/lunasys:

$RECORD www
$ORIGIN lunasys.fr.
56 eu.www
344 as.www
250 eu.www
840 us.www
124 us.www
0 eu.www

Finally retrieve countries zone file with the following rsync command:

rsync -avz rsync://countries-ns.mdc.dk/zone .

And copy the zz.countries.nerd.dk.rbldnsd in /etc/powerdns/