When I tweeted that I had been messing around and finally mastered setting up Split DNS using views on Mac OS X Server without breaking the Server Admin GUI, I got some responses to blog about it. Some days later, when I started to think about what to write and how to start, I realized that this topic might be interesting to many more than just those, who understand what it is about when they read the title. Essentially it looks like geek pr0n. But it is much more valuable, if you understand what it is for, so let me try to explain the what and why of it:
The IT infrastructure for small business and schools is changing rapidly. In the “old” days, we were happy to have local networks with fileservers and printers. It was clear that you could not access those servers from remote locations. For the big corporations a lot changed when things like Microsofts Exchange Servers with calendaring, task management and contacts showed up in addition to email. Later Blackberries joined in and you could take those things with your mobile into your pocket. But it was expensive and only big companies had all the infrastructure to do this.
With all the iPhones and iPads popping up around us, cheaper server prices (just image the MacMini Server with Snow Leopard), more and more people want to have these Services on their own devices. The dilemma is, that they are still small businesses with the infrastructure of a small business. And as the need for services grows, most think of a new server, maybe new shiny hardware, but their networking infrastructure usually does not grow with them. The key to using the additional services is DNS. And DNS is also the key to Mac OS X Server (in fact Apple advertises OS X Server as “easy” – they should add a small print “as long as you get DNS right. 10.6. made that much better, but still). As I have seen in many many installations, most schools and small businesses do not really care about DNS. In most cases they have either no internal DNS and Namespace at all, or they just run their own, local DNS. If they are unlucky (or uneducated, or both) they choose the .local Namespace, which is wrong (and a totally different topic). If they are more lucky, they might be running a .lan or .private or even any fancy toplevel domain they like. Maybe they have already been thinking, that if they wanted to access their server from outside, they would need a recognizable and registered name for it. So they choose their own domain, where they already run their website and mail server on (typically hosted by some ISP) for their local area network, too. Next they get a fixed IP address for their DSL – most realize, that while you can achieve a lot using services like dyndns.org, it is not the way to do it “right”. So, lets see what our hypothetical organization has:
- a local network behind a DHCP/NAT router, maybe with some kind of Firewall, fixed IP for the router
- an OS X Server running DNS with their company domain, example.com
- some legacy services (maybe web, mail) hosted at the ISP
- some new services (Calendar Server, Address Book Server or other stuff) on their OS X Server in the LAN
- some mobile devices like iPhones, iPads and laptops
To the users it seems totally logical, that they can reach all their services from anywhere, be it on their LAN or at any remote location in the world. But it isn’t that simple. If they hand out their OS X Servers IP address as the DNS server for all the machines on the LAN, they can access all internal services while they are on the LAN. But they can no longer reach the old services, located outside, as their OS X Server claims to be authoritative for their domain and does not know about those legacy services. That can be solved by adding the ISP hosted services to the local DNS, but it creates another problem: You get all those entries twice, once in the public DNS, once in your local DNS. If there are any changes, you need to update both. And you did not yet solve your problem that you want to reach your internal services from the outside. So they might want to point the global DNS system to their own DNS Server, to have both control over it, consolidate all changes to one place and have all queries answered by the same DNS, pointing to the right server. This can be done by forwarding Port 53 (which is DNS) to the OS X Server on the LAN and setting the Primary DNS Server for your domain at the registration of the domain to point to your static IP address of your router. Now, there is one more catch to it. To use the services on the OS X Server, people from outside need to be pointed to the static IP address of the router (to be then port-forwarded to the OS X Server) while clients on the LAN need to be pointed to the servers IP on the LAN (a similar approach applies if you use two network interfaces on your server to be a “gateway” between the LAN and the Internet).
This is, where a view might come in handy. (Yes, I told you its geeky).
You can configure BIND (the DNS Server in OS X Server) to hand out different information based on who is asking. So clients on your LAN might get a response pointing to a local IP Adress (e.g. 192.168.0.2) while clients on the internet would get something totally different (the public, static IP address of your router). So you might want to have at least two views: a public one (for those asking fom outside) and a private one (for those asking from the inside). While the obvious reason is to give different IPs as answers to the same query, depending on who asked, there is also a security reason for using views: You need to tell outsiders only the names and IP addresses of the services they really need, nothing more which they could use as a intrusion vector.
OS X Server 10.6. already uses views for all zones edited in Server Admin. So you want to add another zone. On OS X Server they are defined in /etc/named
You will find a line like
include “/etc/dns/publicView.conf.apple”;
which includes Apples view used by Server Admin. Before we add our own zone, we need two things:
1) a disclaimer: All thing here are just what I experienced without any claim of being right or actually working. You should not try this at home and of course not to your production systems. Make sure to have good backups. If you break your DNS, its your problem.
2) understanding of how zones work
The second thing is quite easy if you figured it out, just using try and error will lead you to some pain. What I found, are some simple rules:
- if a client queries the DNS, it will try to match the client IP address to the views in the order they are defined in named.conf. If the range for the view matches the client IP, this view is used for the lookup, if there is no match, the next view is tried. Just to make it clear: if your views range and the client IP adress match, this view is used, no other views are ever considered. That means that any zone that should be available in different views, must be defined in all those views. Even if you have a zone that should be totally identical for both views, it must go into both views (of course both views could use the same zone files).
- the required zones, that is “.”, “localhost” and the reverse localhost “0.0.127.in-addr.arpa” have to be defined in all views
- don’t make typos. If you mess up your files, BIND might not load all info and work properly.
Ok, so to add a view to named.conf, you add a line like
include “/etc/dns/privateView.conf.myself”;
above the line including apples view for Server Admin. Of course you could use any naming scheme and save it anywhere you like, but to me it makes sense to stay in line with the Apple config. You need to add it above, because Apples view matches all IP adresses (in fact it has no match parameter, so it matches all). So by adding a private view above, we can define whatever we want for the private stuff while not breaking the Server Admin GUI for “everyone else”. By this we can still use the GUI to edit zones and have that applied to the outside world, while we will use a text editor of your choice to edit the private view.
We then create our file at /etc/dns/privateView.conf.myself. This file can actually contain one or more views. It must be a flat text file. Here is an example of what it could look like:
view “internal” {
match-clients { 192.168.0.0/24; }; // our internal network
recursion yes;
// required zone for recursive queries
zone “.” {
type hint;
file “named.ca”;
};
zone “example.com” {
type master;
// private zone file including local hosts
file “internal/db.example.com.”;
};
// required local host domain
zone “localhost” in{
type master;
file “localhost.zone”;
allow-update{none;};
};
// localhost reverse map
zone “0.0.127.in-addr.arpa” in{
type master;
file “named.local”;
allow-update{none;};
};
}; // end view
You could add more views the same way if you need to. As you can see above, the private view can include the same zone files as used by the Server Admin view. For the example.com zone we use a folder /var/named/internal. Again, you can use whatever you like, but to avoid problems later on, you might want to use some logical structure. If you had zones that should be exactly the same in both views, you can include the Zone file from Server Admin here.
And that’s it. Just tell BIND to reload all its files:
bash-3.2# sudo rndc -p 54 reload
Then everything should work. Yes, DNS is easy. Have fun.








