mararc


Index
NAME
MARARC FILE FORMAT
COMMENTS
MARARC VARIABLES
DICTIONARY VARIABLE FORMAT
DICTIONARY VARIABLES
NORMAL VARIABLE FORMAT
NORMAL VARIABLES
EXAMPLE MARARC FILE
BUGS
LEGAL DISCLAIMER

Section: MaraDNS reference (5)
Updated: October 2001
 

NAME

mararc - Format of the mararc zone file that MaraDNS uses

 

MARARC FILE FORMAT

Mararc files use a syntax that is a subset of Python 1.5.2 syntax. In particular, Python 1.5.2 (and possibly other versions of Python) can read a properly formatted mararc file without error.

Unlike Python, however, a mararc file can only use certain variable names, and the variables can only be declared as described below.

 

COMMENTS

Comments (lines ignored by the MaraDNS parser) start with the '#' character, like this:

# This is a comment

The MaraDNS parser also ignores lines which contain only white space.

 

MARARC VARIABLES

Follows is a listing of variables that can be declared in the mararc file.

 

DICTIONARY VARIABLE FORMAT

A dictionary variable is an array that can have multiple elements. Unlike a traditional array, these arrays are indexed by strings instead of numbers. These are analogous to assoscitative arrays, or what Perl somewhat inaccurately calls hashes.

The syntax of a dictionary variable is in the following form:

name["index"] = "value"

Where name is the name of the dictionary variable, index is the index of the array, and value is the value stored at that index.

Every time we have a dictionary-type variable (such as csv1), we must first initialize it using a line in the following form:

csv1 = {}

Here, csv1 is the name of the "dictionary" variable that we are initializing.

 

DICTIONARY VARIABLES

Here is a listing of all "dictionary"-style variables that MaraDNS uses:

csv1

csv1: Used to indicate the filename to use for a given zone.

csv1["zone"] = "filename"

csv1: A pipe-separated-file. See csv1(5) for a description of this file's format.

zone: the zone that file in question is authoritative for

filename: the file with the CSV1 zone data

Note that csv1 files are read after MaraDNS is chrooted, and, hence the filename is relative to the chroot_dir.

See csv1(5) for a technical description of the file format that a csv1 zone file uses.

ipv4_alias

ipv4_alias: Used to give nicknames or aliases for ip/netmask pairs for ipv4 (standard 32-bit) IP addresses.

ipv4_alias["name"] = "ip1/netmask,ip2/netmask,etc"

name: The name of the alias in question

ip: The ip portion of an ip/netmask pair

netmask: the mask portion of an ip/netmask pair

,: Used to separate ip/netmask pairs. It is important to not have spaces before or after the comma.

An ip is in dotted-decimal format, e.g. "10.1.2.3".

The netmask can be in one of two formats: A single number between 1 and 32, which indicates the number of leading "1" bits in the netmask, or a 4-digit dotted-decimal netmask.

The netmask is used to specify a range of IPs.

ipv4_alias examples

10.1.1.1/24 indicates that any ip from 10.1.1.0 to 10.1.1.255 will match.

10.1.1.1/255.255.255.0 is identical to 10.1.1.1/24

10.2.3.4/16 indicates that any ip from 10.2.0.0 to 10.2.255.255 will match.

10.2.3.4/255.255.0.0 is identical to 10.2.3.4/16

127.0.0.0/8 indicates that any ip with "127" as the first octet (number) will match.

127.0.0.0/255.0.0.0 is identical to 127.0.0.0/8

The netmask is optional, and, if not present, indicates that only a single IP will "match". e.g:

10.9.9.9/32 , 10.9.9.9/255.255.255.255 , and 10.9.9.9 are all functionally identical, and indicate that only the ip 10.9.9.9 will match.

The significance of "match" depends on what we use the ipv4 alias for.

ipv4 aliases can nest. E.g:

ipv4_alias["susan"] = "10.6.7.8/24"

ipv4_alias["office"] = "susan,10.9.9.9"

Where "susan" in the "office" alias matches the value of the ipv4_alias susan.

Multiple levels of nesting are allowed. Self-referring nests will result in an error.

root_servers

root_servers: This is a special "dictionary" element that can (currently) only have one element: ".", which points to either an ip, or a pointer to an ipv4 alias which is a listing of root name servers.

root_servers["."] = "list_of_servers"

Where "." is the only allowed array reference for the root servers (this format is used to allow potential future expansion), and list_of_servers is a list of root name servers in the exact same format as ipv4_aliases.

Note that, while ips in the list of root name servers can have netmasks, the netmask portion is ignored.

Final note on dictionary variables

csv1, ipv4_alias, and root_servers are currently the only existing dictionary variables.

 

NORMAL VARIABLE FORMAT

Normal variables. These are variables that can only take a single value.

The syntax of a normal variable is in the form

name = "value"

Where name is the name of the normal variable, and value is the value of the variable in question.

 

NORMAL VARIABLES

Here is a listing of normal variables that MaraDNS uses:

bind_address

bind_address: The IP address to give the MaraDNS server.

This accepts a single IP in dotted-decimal (e.g. "127.0.0.1") notation, and specifies what IP address the MaraDNS server will listen on. To bind MaraDNS to all IPs that a given server has, give this the value "0.0.0.0".

chroot_dir

chroot_dir: The directory MaraDNS chroots to

This accepts a single value: The full path to the directory to use as a chroot jail.

Note that csv1 zone files are read after the chroot operation. Hence, the chroot jail needs to have any and all zone files that MaraDNS will load.

maradns_uid

maradns_uid: The numeric UID that MaraDNS will run as

This accepts a single numerical value: The UID to run MaraDNS as.

MaraDNS, as soon as possible drops root privledges, minimizing the damage a potential attacker can cause should there be a security problem with MaraDNS. This is the UID maradns becomes.

maradns_gid

maradns_gid: An optional numeric GID that MaraDNS will run as.

This accepts a single numerical value: The GID to run MaraDNS as.

This optional parameter allows MaraDNS to also drop any and all special group privledges that she has.

maxprocs

maxprocs: The maximum number of threads or processes that MaraDNS is allowed to run at the same time.

This variable is used to minimize the impact on the server when MaraDNS is heavily loaded. When this number is reached, it is impossible for MaraDNS to spawn new threads/processes until the number of threads/processes is reduced.

max_tcp_procs

max_tcp_procs: The (optional) maximum number of processes the zone server is allowed to run.

Sometimes, it is desirable to have a different number of maximum allowed tcp processes than maximum allowed threads. If this variable is not set, the maximum number of allowed tcp processes is "maxprocs".

no_fingerprint

no_fingerprint: Flag that allows MaraDNS to be harder to detect.

Some people do not feel it is appropriate to have some information, such as the version number of MaraDNS being run, be publically available.

The normal value is 0.

By setting no_fingerprint to 1, it is possible to have MaraDNS not reveal this information publically.

default_rrany_set

defult_rrany_set: Number which determines which RRs to return if a ANY query is sent to MaraDNS.

Some registers require that an ANY reuqest returns NS ans SOA records also.

When default_rrany_set is set to 3 (the default value), ANY requests return only A and MX records.

When default_rrany_set is set to 15, ANY requests return A, MX, NS, and SOA records.

max_chain

max_chain: The maximum number of records to display in a chain of records.

With DNS, it is possible to have more than one RR for a given domain label. For example, "example.com" can have, as the A record, a list of multiple ip addresses.

This sets the maximum number of records MaraDNS will show for a single RR.

MaraDNS normally round-robin rotates records. Hence, all records for a given DNS label (e.g. "example.com.") will be visible, although not at the same time if there are more records than the value allowed with max_chain

max_ar_chain

max_ar_chain: The maximum number of records to display if a record in the additional section (e.g., the IP of a NS server or the ip of a MX exchange) has more than one value.

This is similiar to max_chain, but applies to records in the "additional" (or AR) section.

Due to limitations in the internal data structures that MaraDNS uses to store RRs, if this has a value besides one, round robin rotates of records are disabled.

max_total

max_total: The maximum number of records to show total for a given DNS request.

This is the maximum total number of records that MaraDNS will make available in a DNS reply.

verbose_level

verbose_level: The number of messages we log to stdout

This can have four values:

0: No messages except for the legal disclaimer and fatal parsing errors

1: Only startup messages logged (Default level)

2: Error queries logged

3: All queries logged

zone_transfer_acl

zone_transfer_acl: List of ips allowed to perform zone transfers with the zone server

The format of this string is identical to the format of an ipv4_alias entry.

recursive_acl

recursive_acl: List of ips allowed to perform recursive queries with the recursive portion of the MaraDNS server

The format of this string is identical to the format of an ipv4_alias entry.

random_seed_file

randsom_seed_file: The file from which we read 16 bytes from to get the 128-bit seed for the secure psudo random number generator.

This is ideally a file which is a good source of random numbers (e.g. /dev/urandom), but can also be a fixed file if your OS does not have a decent random number generator.  In that case, make sure the
contents of that file is random and with 600 perms, owned by root. We read the file *before* dropping root privledges.

maximum_cache_elements

maximum_cache_elements: The maximum number of elements we can have in the cache of recursive queries.

This cache of recursive queries is used to store entries we have previously obtained from recursive queries.

If we approach this limit, the "custodian" kicks in to effect. The custodian removes elements at random from the cache---8 elements removed per query---until we are at the 99% or so level again.

spammers

spammers: A list of DNS servers which the recursive resolver will not query.

This is mainly used to not allow spam-friendly domains to resolve, since spammers are starting to get in the habit of using spam-friendly DNS servers to resolve their domains, allowing them to hop from ISP to ISP.

The format of this string is identical to the format of an ipv4_alias entry.

max_glueless_level

Maximum glueless level allowed when performing recursive lookups. The default value is 10.

This is the maximum number of times MaraDNS will "go back to the root servers" in order to find out the IP of a name server for which we do not have a glue IP for, or to find out the A value for a given CNAME record.

max_queries_total

Maximum number of queries to perform when performing recursive lookups. The default value is 32.

This is the maximum number of times MaraDNS will send a query to nameservers in order to find out the andwer to a DNS question.

timeout_seconds

This only applies when performing recursive lookups.

The amount of time, in seconds, to wait for a reply from a remote DNS server before giving up and trying the next server on this list. The default value is 2 seconds.

Note that, the larger this value is, the slower MaraDNS will process recursive queries when a DNS server is not responding to DNS queries.

hide_disclaimer

If this is set to "YES", MaraDNS will not display the legal disclaimer when starting up.

 

EXAMPLE MARARC FILE

# Example mararc file

# The various zones we support

# First, we must initialize the csv1 hash, or things will fail with a
# (potentially) obscure error message
csv1 = {}

# This is just to show the format of the file
csv1["example.com."] = "db.example.com"

# The address this DNS server runs on.  If you want to bind
# to all addresses a given machine has, use "0.0.0.0".
bind_address = "127.0.0.1"
# The directory with all of the zone files
chroot_dir = "/usr/local/etc/maradns"
# The numeric UID MaraDNS will run as
maradns_uid = 99
# The maximum number of processes MaraDNS is allowed to use
maxprocs = 64

# The number of messages we log to stdout
# 0: No messages, except syntax error messages 
# 1: Only startup messages logged (Default)
# 2: Error queries logged
# 3: All queries logged (not very verbosely right now)
verbose_level = 1

# Normally, MaraDNS has some MaraDNS-specific features, such as DDIP
# synthesizing, a special DNS query (erre-con-erre-cigarro.maradns.org.
# with a TXT query returns the version of MaraDNS that a server is
# running), unique handling of multiple QDCOUNTs, etc.  Some people
# might not like these features, so I have added a switch that lets
# a sys admin disable all these features.  Just give "no_fingerprint"
# a value of one here, and MaraDNS should be more or less
# indistinguishable from a tinydns server.
no_fingerprint = 0
 
# Normally, MaraDNS only returns A and MX records when given a
# QTYPE=* (all RR types) query.  Changing the value of default_rrany_set
# to 15 causes MaraDNS to also return the MX and SOA records, which
# some registars require.  The default value of this is 3
default_rrany_set = 3

# These constants limit the number of records we will display, in order
# to help keep packets 512 bytes or smaller.  This, combined with 
# round_robin record rotation, help to use DNS as a crude load-balancer.
 
# The maximum number of records to display in a chain of records (list
# of records) for a given host name
max_chain = 8
# The maximum number of records to display in a list of records in the
# additional section of a query.  If this is any value besides one,
# round robin rotation is disabled (due to limitations in the current
# data structure MaraDNS uses)
max_ar_chain = 1
# The maximum number of records to show total for a given question
max_total = 20

# Initialize the IP aliases, which are used by the list of root 
# name servers, the ACL for zone transfers, and the ACL of who 
# gets to perform recursive queries
ipv4_alias = {}

# Various sets of root name servers
# Note: Netmasks can exist, but are ignored when specifying root 
# name server

# ICANN, the most common and most controversial root name server
ipv4_alias["icann"] = "198.41.0.4,128.9.0.107,192.33.4.12,128.8.10.90,192.203.230.10,192.5.5.241,192.112.36.4,128.63.2.53,192.36.148.17,198.41.0.10,193.0.14.129,198.32.64.12,202.12.27.33"

# OSRC: http://www.open-rsc.org/
ipv4_alias["osrc"] = "199.166.24.1,205.189.73.102,199.166.24.3,204.80.125.130,207.126.103.16,195.117.6.10,199.166.31.3,199.166.31.250,199.5.157.128,205.189.73.10,204.57.55.100,213.196.2.97"

# AlterNIC: http://www.alternic.org/
ipv4_alias["alternic"] = "160.79.129.192,65.2.214.15,160.79.133.70,24.13.64.102,216.99.37.240,199.224.64.190,160.79.133.66,216.99.37.246,216.99.37.247"

# OpenNIC: http://www.opennic.unrated.net/
ipv4_alias["opennic"] = "209.21.75.51,216.74.72.7,216.74.72.8,209.21.75.53,209.104.33.250,209.104.63.249"

# Pacific Root: http://www.pacificroot.com/
ipv4_alias["pacificroot"] = "204.107.129.2,208.179.42.162,12.28.140.20,204.107.129.10,212.115.192.151,202.76.159.5,209.54.94.3,167.160.132.2"

# IRSC: http://www.irsc.ah.net/
ipv4_alias["irsc"] = "203.21.205.2,203.21.205.3,212.234.36.20,212.234.36.19,207.180.91.9,198.199.168.92,207.180.91.10"

# TINC: http://www.tinc-org.com/
ipv4_alias["tinc"] = "64.6.65.10,208.128.113.35,212.172.21.254,207.112.147.14,145.89.234.7,209.133.38.16"

# Super Root: http://www.superroot.org/
ipv4_alias["superroot"] = "195.117.6.10,199.166.31.3,199.5.157.128,205.189.73.10,199.166.31.250,199.166.24.1,205.189.73.102,199.166.24.3,204.80.125.130,207.126.103.16,204.57.55.100"

# Here is the ACL which restricts who is allowed to perform 
# zone transfer from the zoneserver program

# VERY IMPORTANT: Do not put spaces in the zone_transfer_acl list
# Good: zone_transfer_acl = "office,home"
# Bad:  zone_transfer_acl = "office, home"

# Simplest form: 10.1.1.1/24 (IP: 10.1.1.1, 24 left bits 
# in IP need to match) and 10.100.100.100/255.255.255.224 
# (IP: 10.100.100.100, netmask 255.255.255.224) are allowed 
# to connect to the zone server 
# zone_transfer_acl = "10.1.1.1/24,10.100.100.100/255.255.255.224"

# More complex: We create two aliases: One called "office" 
# and another called "home".  We allow anyone in the office or 
# at home to perform zone transfers
# ipv4_alias["office"] = "10.1.1.1/24"
# ipv4_alias["home"] = "10.100.100.100/255.255.255.224"
# zone_transfer_acl = "office,home"

# More complex then the last example.  We have three employees,
# Susan, Becca, and Mia, whose computers we give zone transfer 
# rights to.  Susan and Becca are system administrators, and 
# Mia is a developer.  They are all part of the company.  We 
# give the entire company zone transfer access
# ipv4_alias["susan"]     = "10.6.7.8/32"  # Single IP allowed
# ipv4_alias["becca"]     = "10.7.8.9"     # also a single IP
# ipv4_alias["mia"]       = "10.8.9.10/255.255.255.255" # 1 IP
# ipv4_alias["sysadmins"] = "susan,becca"
# ipv4_alias["devel"]     = "mia"
# ipv4_alias["company"]   = "sysadmins,devel"
# This is equivalent to the above line
# ipv4_alias["company"]   = "susan,becca,mia"
# zone_transfer_acl       = "company"

# Recursive ACL: Who is allowd to perform recursive queries.  
# The format is identical to that of "zone_transfer_acl", 
# including ipv4_alias support 
# ipv4_alias["localhost"] = "127.0.0.0/8"
# recursive_acl = "localhost"

# Random seed file: The file form which we read 16 bytes from 
# to get the 128-bit random Rijndael key.  This is ideally a 
# file which is a good source of random runbers, but can also be 
# a fixed file if your OS does not have a decent random number 
# generator (make sure the contents of that file is random and 
# with 600 perms, owned by root, since we read the file *before*
# dropping root privledges)

# random_seed_file = "/dev/urandom"

# The maximum number of elements we can have in the cache.  If 
# we have more elements in the cache than this amount, the 
# "custodian" kicks in to effect, removing elements at random from 
# the cache (8 elements removed per query) until we are at the 99% 
# level or so again.

# maximum_cache_elements = 1024

# The root servers which we use when making recursive queries.

# The following line must be uncommented to enable recursive queries
# root_servers = {}

# You can choose which set of root servers to use.  Current 
# values (set above) are: icann, osrc, alternic, opennic,
# pacificroot, irsc, tinc, and superroot.
# root_servers["."] = "osrc"

# You can tell MaraDNS to *not* query certain DNS servers when in 
# recursive mode.  This is mainly used to not allow spam-friendly 
# domains to resolve, since spammers are starting to get in the habit 
# of using spam-friendly DNS servers to resolve their domains, allowing 
# them to hop from ISP to ISP.  The format of this is the same as for 
# zone_transfer_acl and recursive_acl

# As of August 12, 2001, azmalink.net is a known spam-friendly DNS 
# provider (see doc/detailed/spammers/azmalink.net for details).
# Note that this is based on IPs, and azmalink.net constantly
# changes IPs (as they constantly have to change ISPs)
ipv4_alias["azmalink"] = "206.169.88.7/24"

# As of September 20, 2001, hiddenonline.net is a known spam-friendly
# DNS provider (see doc/detailed/spammers/hiddenonline for details).
ipv4_alias["hiddenonline"] = "65.107.225.0/24"

spammers = "azmalink,hiddenonline"

 

BUGS

If one should declare the same the same index twice with a dictionary variable, MaraDNS will exit with a fatal error. This is because earlier versions of MaraDNS acted in a different manner than Python 1.5.2. With Python 1.5.2, the last declaration is used, while MaraDNS used to use the first declaration.

 

LEGAL DISCLAIMER

THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.