Friday, 18 February 2011

HOWTO: MASTER and SLAVE with Bind

So you have built yourself an authoritative nameserver and now you want to build a slave for it to replicate to.

Unfortunately, this is one of those things that is unnecessarily difficult to do on Linux. There are lot's of guides and howto's but they all seem to be missing bits and pieces of the puzzle. The good news is that after a few days of frustration I've figured out how to do it and I'm here to share the secret. Once you know what to do it is really extremely simple.

I'm using Ubuntu LTS Server 10.04 "Lucid Lynx", but as usual any debian based distro should be fine.

Pre-requisites:
Two working authoritative DNS servers built according to this guide. Both of these servers should be able to authoritatively resolve names for your local network.

Note:
In this howto we will using an MD5 key. The key used in this guide is sanitized (ie: not a real key) and should not be used "as is".

Example Network:
For the example network the domain I will be using is tuxnetworks.net, the MASTER server will be on 10.1.1.1 and the SLAVE server on 10.1.1.2. Of course you should substitute these values for ones that are valid on your own network. The two servers will be named ns1 and ns2.

OK, let's get cracking.

First up, before we can start doing zone transfers, we need to enable "dns security extensions" on both servers;

On BOTH servers, edit your named.conf.options file;

sudo vi /etc/bind/named.conf.options

Add this line within the options { }; section;

dnssec-enable yes;

Modify the allow recursions line so that it looks similar to this (using your own IP address's of course).

allow-recursion { 127.0.0.1; 10.1.1.0/24; };

Note:
These are all the hosts and networks that will be allowed to query the server(s) and should include both the Bind servers we are building. Since both our servers are in the 10.1.1.0/24 subnet we don't need to explicitly define them, if they weren't you would put their IP address in here too.

When we install bind, it will create a key that we can use. However, the keys will be different on the two servers. Let's copy the key from the MASTER to the SLAVE.

On the SLAVE, backup the old key file;

sudo cp /etc/bind/rndc.key /etc/bind/default.rndc.key

Cat the rndc.key file on the MASTER;

sudo cat /etc/bind/rndc.key
key "rndc-key" {
algorithm hmac-md5;
secret "BCRNAwUG2DRqz3fYleLO/g==";
};


On the SLAVE edit the rndc.key file and change the "secret" so that it is the same as the secret in the MASTER key.

sudo vi /etc/bind/rndc.key

The "secret" line should be changed to look the same as on the MASTER;

secret "BCRNAwUG2DRqz3fYleLO/g==";

Great. Now we need to edit the zone definition files on both servers. If you followed my guide to build your servers then it will be in named.conf.myzone-net. Other guides might put this info into named.conf or named.conf.options. The file is the one with the zone myzone { }; definition for your zone in it.

On BOTH servers, edit your zone definition file;

sudo vi /etc/bind/named.conf.tuxnetworks-net

Add this line to the end of the file.

include "/etc/bind/rndc.key";

Now we reach the part where the MASTER and SLAVE servers are configured differently.

We will begin with the MASTER server. On the MASTER, edit your zone definition file again;

sudo vi /etc/bind/named.conf.tuxnetworks-net

Add this section (using the IP address of the SLAVE server);
server 10.1.1.2 {
keys {
rndc-key;
};
};


Next we configure the SLAVE. Again, we edit the zone definition file;

sudo vi /etc/bind/named.conf.tuxnetworks-net

Inside the definition for the zone change the type from "master" to "slave" and add two lines to define the master servers details and specifically allow it to update the SLAVE.

Here is an example (use the IP address of your MASTER server here);
# This is the zone definition for the tuxnetworks.net zone.
zone "tuxnetworks.net" {
type slave;
file "/etc/bind/db.tuxnetworks.net";
masters { 10.1.1.1; };
allow-notify { 10.1.1.1; };
};

Also, add another section (using the MASTER IP address) to tell it to use the rndc-key;
server 10.1.1.1 {
keys {
rndc.key;
};
};


And that's it. We also need to ensure that both the servers are listed in the SOA section of your zone file (the zone file is the one where all the IP addresses for your network are located.

On BOTH servers open your zone file;

sudo vi /etc/bind/db.tuxnetworks.net

The top or second line should look like this (ie it should be showing both your DNS servers);

tuxnetworks.net. IN SOA ns1.tuxnetworks.net. ns2.tuxnetworks.net. (


Your NS servers should be defined properly;
; DNS Servers
tuxnetworks.net. IN NS ns1.tuxnetworks.net.
tuxnetworks.net. IN NS ns2.tuxnetworks.net.

We also need to define the IP address for both servers;
ns1             IN      A       10.1.1.1
ns2 IN A 10.1.1.2


Finally, for replication to occur, the two servers must be in close time sync. To ensure their internal clocks are synced properly, we will install ntpdate on both servers (this may already be installed on your systems)

sudo apt-get install ntpdate

Update the system time on both servers;

sudo ntpdate ntp.ubuntu.com

Check that the times are both in sync with the date command on both servers;

date
Wed Feb 11 10:30:16 EST 2011


Both systems should be within a few seconds. If they are way out, check that the timezones on both systems are the same;

dpkg-reconfigure tzdata

NOTE:
There is a bug in Ubuntu 10.04 bind package. When you it installs bind it fails to set the permissions correctly on the /etc/bind directory. I'm not sure if this affects other debian based distro's or not. A tell tale sign that the bug is in place (apart from slave updates not working) is an error in the syslog "bind dumping master file permission denied". To fix this change the ownership of the directory to the bind user;

sudo chown bind:bind /etc/bind

To make all the changes, restart bind on both servers;

sudo service bind9 restart

To test if your replication is working, go to the master server and edit the zone file. Increment the "serial" by one and issue a reload command on both servers;

sudo rndc reload

Now, if you look at the zone file on the slave, it should have been updated with the new serial.

When you are satisfied that both servers are working properly, you should remember to update your clients (or more likely your DHCP server) so that all your clients use both of your servers for resolving names.

Troubleshooting:
- Check your server times are in sync
- Check the permissions on /etc/bind
- Check that there are no firewalls between the two servers

A word on zone files:
Any time you make a change to the zone file on the master you need to update the serial. There is no set rule as to how the serial number should be formed. It can simply be an integer that you increment for each change if you like. I prefer to use the date in the form YYYMMDD with two trailing digits to allow for multiple increments within a day. That way I can know the date the last time the file was modified. As always YMMV.

I've tried to make this as simple to follow as possible. If there is something I haven't made clear enough then by all means leave me a message in the comments and I will tweak this howto accordingly.

Also, to make things a bit easier, you might like to download copies of all the example config files and modify them to suit your network.

Otherwise, enjoy your new DNS servers!

Friday, 4 February 2011

HOWTO: Configure A Router

Now we get to turn our debian or ubuntu server into a router. Read on!

Prerequisites;
1) A server as per this guide.

2) A working PPPoE or PPPoA based Internet connection. Most consumer ADSL and Cable Internet is provided using one of these protocols, support for which is built into the consumer "router" I am assuming you are currently using.

3) The ISP provided username and password combo for your Internet connection. If you have a "router" that was provided by your ISP they sometimes print these on a label attached to the device, otherwise it will be written on the documentation you received when you signed up (and promptly lost I'm sure). You will have to call your ISP on the actual telephone to retrieve this information if you have lost it.

4) An Ethernet switch and sufficient cables to connect at least two devices. Your current Internet Gateway may currently have the Ethernet switch built in to it. Alternately, you may use a separate switch if you prefer.

5) If you are intending to use a discreet modem (cable or ADSL) and a separate switch then two LAN cards are required. Unless you are one of the incredibly lucky few who have access to FttH you will most likely have some form of ADSL or Cable service with speeds measured in single-figure MegaBits. This means that it is perfectly OK to reuse a discarded old 100baseT adapter (or indeed even a 10baseT if you still have one of those in the antiques cupboard) for your WAN interface. Even the slowest LAN card will be considerably faster than most current Internet connections. If you intend to go down the Router-in-bridged-mode road then a single Ethernet adapter will suffice.

OK, now that you have all the prerequisites in order, and a basic server up and running we can get on with bidness proper.

The first thing we need to do is install a few packages we will need before we disconnect ourselves from the Internet.

apt-get install pppoeconf ppp

Next we configure the LAN side of the network.

Note: I will assume that your LAN adapter is eth0 from this point onwards. If you are using two Ethernet adapters this would make your WAN interface eth1.

Because we are configuring a router, we must use a static IP address for our LAN adapter. If you followed my server guide then you have already done that, otherwise you should backtrack and configure a static IP address as per that guide.
Pro Tip: For testing purposes, I recommend that you configure some other PC on your LAN with a static IP in the 10.1.1.x subnet with a default gateway of 10.1.1.1. We will be using this PC from time to time for testing. This can be either a Linux or Windows PC.

Plug both the server and client hosts into your LAN and check that you can ping the server at 10.1.1.1 from the client.

OK. Once you can ping your server from the test PC we can continue.
The next step varies depending on whether you are using a single adapter and a router in "bridged mode" or a separate modem and 2 Ethernet adapters.

Separate modem and two adapters: You must configure eth1 as per the above instructions for eth0 using any old IP address you like. I suggest you use 192.168.254.254/24. The address will not be used for anything on your network but is required so that the pppoeconf utility in the next section can locate your modem. Make sure you plug your modem into this interface

Consumer router in "bridged" mode: You will need to configure the router in "bridged" mode[1] according to the instructions provided by the manufacturer of the device. On my DG834G it is a simple matter of browsing to http://192.168.0.254/setup.cgi?next_file=mode.htm (where 192.168.0.254 is the address of my gateway) and setting the drop-down box to "Modem Only". I found that info via a Google search here. You should do a Google search for something like my-gw-model-number +"bridged mode" or similar to find instructions on how to configure your particular router.

Once you have your router in bridge mode, we can use the pppoeconf utility to configure a PPP connection to our ISP;

sudo pppoeconf

Go through each screen choosing the default option until you get to the "ENTER USERNAME" screen. Enter the username for your ISP account here.

The next screen asks for your password, enter that too.

In the "USE PEER DNS" screen select "No"

Select the default option on all the remaining screens.

You should now have Internet connectivity on this host. You can check this with the ifconfig command;

ifconfig ppp0
ppp0 Link encap:Point-to-Point Protocol
inet addr:123.4.56.789 P-t-P:123.4.8.1 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1492 Metric:1
RX packets:59687317 errors:0 dropped:0 overruns:0 frame:0
TX packets:50606162 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3
RX bytes:2967668270 (2.9 GB) TX bytes:2950135549 (2.9 GB)



You should (hopefully) see a ppp0 adapter in the output similar to this. If you do, we should do a few more tests. First, lets check we can ping our DNS server. To find your DNS server type;

cat /etc/resolv.conf

There should be an entry "nameserver" with an IP address in the output.

Let's ping that IP address and see if it works;

ping -c 4 208.67.222.222
PING 208.67.222.222 (208.67.222.222) 56(84) bytes of data.
64 bytes from 208.67.222.222: icmp_seq=1 ttl=55 time=322 ms
64 bytes from 208.67.222.222: icmp_seq=2 ttl=55 time=196 ms
64 bytes from 208.67.222.222: icmp_seq=3 ttl=55 time=281 ms
64 bytes from 208.67.222.222: icmp_seq=4 ttl=55 time=547 ms

--- 208.67.222.222 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 196.763/337.020/547.292/129.589 ms


(The IP above is for OpenDNS)

We can test that DNS is working by pinging by name;

ping -c 4 www.google.com
PING www.l.google.com (74.125.237.18) 56(84) bytes of data.
64 bytes from 74.125.237.18: icmp_seq=1 ttl=57 time=261 ms
64 bytes from 74.125.237.18: icmp_seq=2 ttl=57 time=285 ms
64 bytes from 74.125.237.18: icmp_seq=3 ttl=57 time=24.2 ms
64 bytes from 74.125.237.18: icmp_seq=4 ttl=57 time=122 ms


If you got this far then that is great, but please be aware that although our Internet connection is now up and working, we have not done enough to get our LAN clients up and on the 'net. For that we need to configure routing, NAT and a firewall.

We can configure routing by issuing editing the following file;

sudo vi /etc/sysctl.conf

Find the following line and change it from 0 to 1;

net.ipv4.ip_forward=1

To configure an extremely basic firewall, create a file in a suitable location such as /usr/sbin/ with the following contents;

sudo vi /usr/sbin/firewall
8< - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#!/bin/bash

WAN=ppp0
LAN=eth0

sudo /sbin/iptables --flush

# Accept ALL packets inbound from our local networks
sudo /sbin/iptables -A INPUT -i $LAN -j ACCEPT
sudo /sbin/iptables -A INPUT -i lo -j ACCEPT

# Do NAT for LAN clients
sudo /sbin/iptables -t nat -A POSTROUTING -o $WAN -j MASQUERADE

# Allow ping packets
sudo /sbin/iptables -A INPUT -p icmp -j ACCEPT

# Allow returning packets for established sessions
sudo /sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo /sbin/iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow all traffic out from this host and our LAN clients
sudo /sbin/iptables -A OUTPUT -j ACCEPT
sudo /sbin/iptables -A FORWARD -i $LAN -j ACCEPT

# Drop all other traffic inbound from the Internet
sudo /sbin/iptables -A INPUT -i $WAN -j DROP
sudo /sbin/iptables -A FORWARD -i $WAN -j DROP

8< - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Note: This is not a particularly secure firewall, it basically allows any host on your LAN to send anything out and only drops unwanted packets coming in via the WAN interface (ppp0).

Make the firewall script executable;

chmod +x /usr/sbin/firewall

To make the firewall start at boot simply edit your rc.local file.

vi /etc/rc.local

Add this line to the end (but before the "exit 0" line)

/usr/sbin/firewall

You should reboot your router/server now and redo the ping tests as shown above.

Now that the router has been rebooted and assuming the ping tests have worked OK, you should be able to use your LAN client with the static IP address and ping/browse to the Internet.

That's great, but we don't want to be configuring all our clients with static addresses, so we probably should configure our router as a DHCP server as well.

And while we are at it, why don't you take the next step and turn your router into a funky caching DNS server too.

Or even better, connect your sites together with encrypted VPN's using this super easy Five Minute VPN Guide

[1] AKA "modem" or "modem only" mode.

-

Thursday, 27 January 2011

HOWTO: Caching Authoritative Nameserver

OK, so you have built yourself a Linux Router and now you want to add DNS support for extra goodness.

Here's what to do.

I'll be working on Debian 6.01 "squeeze" but any Debian based distro should be fine. I've also tested on Ubuntu 10.04 without problems. I am using 10.1.1.0/24 as my local network and tuxnetworks.net as my local domain. Where you see references in italics to these you should change them to suit your own network.

First we will log in as root

As root, install Bind v9 from the standard repositories;

apt-get install bind9

Now we need to tell Bind to listen for queries on our IPv4 LAN.

Open this file for editing;

vi /etc/bind/named.conf.options

add the following lines inside the "options { };" section ;

listen-on { any; };
allow-recursion { 127.0.0.1; 10.1.1.0/24; };


Note:
"Recursion" is a fancy term for "which clients can query our server". Basically, you want to enter the local loop interface (127.0.0.1) and the subnet of your LAN. You can add any other hosts or subnets as required. Also, if you are not intending to use IPv6 you can comment or remove the "listen-on-v6" line out if you like.

Now we will create a zone file for our local zone;

Note:
I prefer to keep the configuration details for zones in separate files so I am going to create a file in which I will define the details for the "tuxnetworks.net" zone. If you don't want to do this just add the following code section to named.conf.options

vi /etc/bind/named.conf.tuxnetworks-net

Adjust the following code to suit your own network and then add it to the zone file;
# This is the zone declaration for our local zone.
zone "tuxnetworks.net" {
type master;
file "/etc/bind/db.tuxnetworks.net";
};

# This is the zone declaration for reverse DNS
zone "1.1.10.in-addr.arpa" {
type master;
file "/etc/bind/db.1.1.10.in-addr.arpa";
};

Now that we have created our zone declaration file, we have to tell bind to load this file when it starts. We do this by adding an "include" line to named.conf

Edit named.conf;

vi /etc/bind/named.conf

Append this line to the end;

include "/etc/bind/named.conf.tuxnetworks-net";

Now we need to make a zone file for our domain. This is where we define the names and attributes of our zone.

Create a zone file;

vi /etc/bind/db.tuxnetworks.net

Modify these details and save them to your zone file;
$TTL    3600
tuxnetworks.net. IN SOA ns.tuxnetworks.net. jupiter.tuxnetworks.net. (
2011051701 ; Serial
86400 ; Refresh
7200 ; Retry
3600000 ; Expire
172800 ) ; Minimum TTL

; DNS Servers
tuxnetworks.net. IN NS ns.tuxnetworks.net.

tuxnetworks.net. IN MX 10 mail.tuxnetworks.net.

@ IN A 10.1.1.1
ns IN A 10.1.1.1
www IN A 10.1.1.1
mail IN A 10.1.1.1
jupiter IN A 10.1.1.1

Note: Take note that several names in this file have a trailing period (fullstop). Make sure that your file matches the format of this one exactly, only changing the names and IP addresses, but where present keeping the periods intact.

We also need to make a reverse zone file. Create a new file;

vi /etc/bind/db.1.1.10.in-addr.arpa

Add this code (modified to suit your network of course);
;
; BIND reverse data file for local network
;
$TTL 604800
@ IN SOA jupiter. ns. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns.
1 IN PTR ns.

Finally, there is one thing more to do if we are going to be good netizens and that is to ensure that we play by the rules according to RFC 1918

After running your server for a while you might take a look at /var/log/syslog and notice lots of bind related errors saying something like "RFC 1918 response from Internet for . . . .".

If you do then this means that your server is not playing nice with the root servers and is forwarding on requests for private IP ranges. That is not something we want to do.

To fix it edit your named.conf file;

vi /etc/bind/named.conf

Add the following line to the end;

include "/etc/bind/zones.rfc1918";

This stops any requests for private IP address's (192.168 etc) from being passed on to the Internet root servers. One wonders why Bind isn't configured like this by default . . .

And that's it. Of course we need to restart bind before our changes take effect;

service bind9 restart

Also, before we can query our new DNS server, we need to configure the client to look to this server for name resolution.

To do that, edit your resolv.conf file;

vi /etc/resolv.conf

Remove any exiting lines and add these (modified to suit your own network of course);

nameserver 10.1.1.1
domain tuxnetworks.net


Optional:
If you don't wish to query against the Internet root servers, edit your named.conf.options file and configure a forwarder or two.

vi ./etc/bind/named.conf.options

Uncomment the "forwarders {" section and replace the 0.0.0.0 with the ip address of the upstream DNS server(s) you would like to use.
  forwarders {
208.67.222.222;
208.67.220.220;
};

Now let's do some tests to see if it is all good with our new server;

Let's dig our domain;

dig tuxnetworks.net

; <<>> DiG 9.7.0-P1 <<>> tuxnetworks.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28277
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;tuxnetworks.net. IN A

;; ANSWER SECTION:
tuxnetworks.net. 3600 IN A 10.1.1.1

;; AUTHORITY SECTION:
tuxnetworks.net. 3600 IN NS ns.tuxnetworks.net.

;; ADDITIONAL SECTION:
ns.tuxnetworks.net. 3600 IN A 10.1.1.1

;; Query time: 1 msec
;; SERVER: 10.1.1.1#53(10.1.1.1)
;; WHEN: Tue May 17 12:09:08 2011
;; MSG SIZE rcvd: 82


We can see from this that we received an answer (ANSWER: 1) along with some other details about our domain. Also note the AUTHORITY: 1
which lets us know that this server is acting as the authority for the domain.

We can also do some ping tests.

Do a test ping to an internal name (we don't need to provide the domain name because we used the "domain" directive in resolv.conf which will automatically append our domain to any query that doesn't include a domain. Neat!;

ping -c 4 www
PING www.tuxnetworks.net (10.1.1.1) 56(84) bytes of data.
64 bytes from jupiter.tuxnetworks.com (10.1.1.1): icmp_seq=1 ttl=64 time=0.130 ms
64 bytes from jupiter.tuxnetworks.com (10.1.1.1): icmp_seq=2 ttl=64 time=0.089 ms
64 bytes from jupiter.tuxnetworks.com (10.1.1.1): icmp_seq=3 ttl=64 time=0.090 ms
64 bytes from jupiter.tuxnetworks.com (10.1.1.1): icmp_seq=4 ttl=64 time=0.091 ms

--- www.tuxnetworks.net ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2998ms
rtt min/avg/max/mdev = 0.089/0.100/0.130/0.017 ms


Our Bind server will forward any requests that it isn't an authority for out to the Internets DNS root servers which means we no longer need to rely on our dodgy ISP's DNS servers where they are quite likely engaged in DNS Hijacking shenaningans.

Do a test ping to the outside world;

ping -c 4 www.google.com
PING www.l.google.com (74.125.237.84) 56(84) bytes of data.
64 bytes from 74.125.237.84: icmp_seq=1 ttl=57 time=57 ms
64 bytes from 74.125.237.84: icmp_seq=2 ttl=57 time=40.3 ms
64 bytes from 74.125.237.84: icmp_seq=3 ttl=57 time=59 ms
64 bytes from 74.125.237.84: icmp_seq=4 ttl=57 time=45 ms

--- www.l.google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 90.384/137.973/159.187/28.004 ms


So, our DNS server is all up and running, it is acting as authority for tuxnetworks.net and passing any other requests out to the Internet. It is also caching any queries to reduce on net traffic!

OK, we are all done now, grab yourself a beverage and relax!

Now that you have built yourself a DNS server, why not build a second one and configure it as a SLAVE?

Monday, 27 December 2010

HOWTO: DHCP Server On Debian

For a Ubuntu flavoured version of this post see this article

Pre-requisites:

A working LAN where clients can ping each other from static IP address's. For more information on configuring a Debian or Ubuntu server with a static IP address see this article.

Login as root;

su -l

Setting up DHCP is a fairly simple affair. We start by installing dhcp-server from the repositories;

apt-get install dhcp3-server

We need to tell it which interface to listen for client requests on;

vi /etc/default/isc-dhcp-server

Add your (space separated) interface(s) like so;

INTERFACES=”eth0″

There is a lot of useful documentation in the default configuration file, however this tends to make things a bit cluttered. I prefer a minimalist config file so we will backup the default one for future reference;

mv /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.default

Now, we create a new config file;

vi /etc/dhcp/dhcpd.conf

Add the following contents, modifying as applicable for your own network of course;
default-lease-time 600;
max-lease-time 7200;

subnet 10.1.1.0 netmask 255.255.255.0 {
range 10.1.1.10 10.1.1.200;
option subnet-mask 255.255.255.0;
option broadcast-address 10.1.1.255;
option routers 10.1.1.1;
option smtp-server 10.1.1.1;
option domain-name "tuxnetworks.net";
option domain-name-servers 10.1.1.1, 10.1.1.2;

host earth {
hardware ethernet 00:1f:d0:c0:3b:9d;
fixed-address 10.1.1.10;
}
}

Notes:
I have added a fixed address for the host "earth" identified by MAC address 00:1f:d0:c0:3b:9d. This is for illustrative purposes only and can be removed if it is not needed.

The above example assumes you have DNS servers running on the your network on hosts 10.1.1.1 and 10.1.1.2. If you want to use upstream DNS resolvers enter the addresses for your ISP DNS servers instead. Alternately you can use the servers provided by OpenDNS[1] or configure your own DNS server.


To apply the changes, restart the dhcp server daemon;

service isc-dhcp-server restart

Now you should refresh the IP address on a PC configured as a dhcp client and you should receive a shiny new DHCP lease.

Now that you have a DHCP server, why not improve it by adding DDNS (Dynamic DNS) updates so that your clients names are automagically added to your DNS Server?

[1] OpenDNS use error redirects (DNS Hijacking) as a way to generate income. If you are like me and don't like such shenanigans then I recommend that you configure your own DNS server.

HOWTO: DHCP Server On Ubuntu

For a Debian flavoured version of this post see this article

Pre-requisites:

A working LAN where clients can ping each other from static IP address's. For more information on configuring a Debian or Ubuntu server with a static IP address see this article.

Login as root;

sudo -i

Setting up DHCP is a fairly simple affair. We start by installing dhcp-server from the repositories;

apt-get install dhcp3-server

We need to tell it which interface to listen for client requests on;

vi /etc/default/dhcp3-server

Add your (space separated) interface(s) like so;

INTERFACES=”eth0″

There is a lot of useful documentation in the default configuration file, however this tends to make things a bit cluttered. I prefer a minimalist config file so we will backup the default one for future reference;

mv /etc/dhcp3/dhcpd.conf /etc/dhcp3/dhcpd.conf.default

Now, we create a new config file;

vi /etc/dhcp3/dhcpd.conf

Add the following contents, modifying as applicable for your own network of course;
default-lease-time 600;
max-lease-time 7200;

subnet 10.1.1.0 netmask 255.255.255.0 {
range 10.1.1.10 10.1.1.200;
option subnet-mask 255.255.255.0;
option broadcast-address 10.1.1.255;
option routers 10.1.1.1;
option smtp-server 10.1.1.1;
option domain-name "tuxnetworks.net";
option domain-name-servers 10.1.1.1, 10.1.1.2;

host earth {
hardware ethernet 00:1f:d0:c0:3b:9d;
fixed-address 10.1.1.10;
}
}

Notes:
I have added a fixed address for the host "earth" identified by MAC address 00:1f:d0:c0:3b:9d. This is for illustrative purposes only and can be removed if it is not needed.

The above example assumes you have DNS servers running on the your network on hosts 10.1.1.1 and 10.1.1.2. If you want to use upstream DNS resolvers enter the addresses for your ISP DNS servers instead. Alternately you can use the servers provided by OpenDNS[1] or configure your own DNS server.


To apply the changes, restart the dhcp server daemon;

service dhcp3-server restart

Now you should refresh the IP address on a PC configured as a dhcp client and you should receive a shiny new DHCP lease.

Now that you have a DHCP server, why not improve it by adding DDNS (Dynamic DNS) updates so that your clients names are automagically added to your DNS Server?

[1] OpenDNS use error redirects (DNS Hijacking) as a way to generate income. If you are like me and don't like such shenanigans then I recommend that you configure your own DNS server.

Friday, 17 December 2010

Intellinet 150n USB WiFi key

I had some trouble getting my new "Intellinet 150n Wireless LAN Adapter" working in Ubuntu 10.04 (Lucid)

The problem is that one of the other Realtek drivers (rt2800usb) conflicts with the driver we need (rt2870sta)

To fix it you need to stop the rt2800usb driver from loading by blacklisting it.

sudo vi /etc/modprobe.d/blacklist.conf

Add this line;

blacklist rt2800usb

Reboot and you should be up and running.

Thursday, 18 November 2010

HOWTO: Configure a NAS/Fileserver with LVM

LVM is a logical volume manager for the Linux kernel; it manages disk drives and similar mass-storage devices, in particular large ones. The term "volume" refers to a disk drive or partition thereof. (Source: wikipedia)

The way to visualise LVM is that you have the bottom layer, which are your physical drives. On top of that you place an abstraction layer which can span multiple, disparate drive devices. On top of this layer you then create your logical volumes. These become like the hard disk devices that you would normally mount but can be carved up into whatever sizes you like.

For example, you may have 3 hard disks in these sizes, 1Tb, 750GB and 500GB.

These drives can all be used to create a 2250GB "Volume Group".

Then, say we want 1.5TB to store media files and 400GB for user home directories. We go ahead and create the appropriate sized "Logical Volumes" leaving 850GB unused. At any time in the future it is extremely easy to expand one of your logical volumes, add a new one, add new physical disks to the volume group or replace one of the smaller disks with a bigger drive.

I am going to step through the process of installing and configuring LVM such as you might use for storing large numbers of files on a file server or NAS. In my case I will be using four almost identical 1TB drives but as mentioned earlier, using an eclectic mix of different sized drives works just as well. In fact the ability to join a number of different drives together to for one (or more) logical volumes is one of the main benefits of using LVM.

So let's get started. Actually. before we do a warning.

We will be messing around with filesystems and partition tables in this guide and that is ALWAYS a recipe for disaster. Please, do not attempt this if you have valuable data stored on any of the drives on the system you will be working on. If you do for the love of dog make a backup before you proceed. You have been warned!


OK, now that's done we can begin.

What physical disks are we going to be using for our logical volumes?

Let's take a look at the disks presently in our system;

$sudo fdisk -l

Disk /dev/sda: 8069 MB, 8069677056 bytes
255 heads, 63 sectors/track, 981 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000771b4

Device Boot Start End Blocks Id System
/dev/sda1 * 1 933 7490560 83 Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2 933 981 387072 82 Linux swap / Solaris
Partition 2 does not end on cylinder boundary.


Disk /dev/sdc: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xda92f63f

Disk /dev/sdc doesn't contain a valid partition table

[trimmed remaining output]


What we are looking for here are all the drives that say "doesn't contain a valid partition table".

In my system I have 4, they are all 1TB drives (I trimmed the output for the last three) They are /dev/sdc /dev/sdd /dev/sde /dev/sdf.

We need to partition the drives as LVM members. Let's do the first one, /dev/sdc;

Open the disk with fdisk;

sudo fdisk /dev/sdc

You should use the 'p' command to check that the drive is indeed empty, once you are sure then we create a primary partition (using all the default entries);

Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-10443, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-10443, default 10443): 10443


The drive now has a partition but we also need to define the type of partition we want. In our case of course it will be an LVM partion (Hex code 8e).

While still in fdisk we set our partition type, save and exit;

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): 8e
Changed system type of partition 1 to 8e (Linux LVM)

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.


Now, if we redo our fdisk command from earlier we should see that /dev/sdc now has an LVM partition;

sudo fdisk -l

Disk /dev/sdc: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xda92f63f

Device Boot Start End Blocks Id System
/dev/sdc1 1 121601 976760001 8e Linux LVM


In particular, we are interested in the line that says;

/dev/sdc1 1 121601 976760001 8e Linux LVM

If the output for your drive looks like this then great, you should go ahead and repeat the process for every drive that you want to include in our LVM group.

Checkpoint: At this stage you should have 1 or more drives that are partitioned as LVM and you should know which ones they are (/dev/sdb1, /dev/sdc1 etc). Make a list!


Next, we need to install some packages;

sudo apt-get install lvm2 dmsetup reiserfsprogs xfsprogs

Using our list of member drives we create a "physical volume";

sudo pvcreate /dev/sdc1 /dev/sdd1 /dev/sde1 /dev/sdf1
Physical volume "/dev/sdc1" successfully created
Physical volume "/dev/sdd1" successfully created
Physical volume "/dev/sde1" successfully created
Physical volume "/dev/sdf1" successfully created


We can take a look at our handiwork like so;

sudo pvdisplay
"/dev/sdc1" is a new physical volume of "931.51 GiB"
--- NEW Physical volume ---
PV Name /dev/sdc1
VG Name
PV Size 931.51 GiB
Allocatable NO
PE Size 0
Total PE 0
Free PE 0
Allocated PE 0
PV UUID 3Qjtvy-I6DX-YpT9-1Abk-IWu3-oJT0-kqBLHv

[trimmed output for 3 remaining drives]


Assuming that went well, now we can go ahead and create a "volume group"

sudo vgcreate store /dev/sdc1 /dev/sdd1 /dev/sde1 /dev/sdf1
Volume group "store" successfully created


Let's take a look at the new volume group;

sudo vgdisplay
--- Volume group ---
VG Name store
System ID
Format lvm2
Metadata Areas 4
Metadata Sequence No 1
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0
Max PV 0
Cur PV 4
Act PV 4
VG Size 3.64 TiB
PE Size 4.00 MiB
Total PE 953865
Alloc PE / Size 0 / 0
Free PE / Size 953865 / 3.64 TiB
VG UUID AhHEFG-Q0ql-0WV4-2q4d-Wv0B-uuz3-I7dvf3


OK, that's looking good. Now we can create our logical volumes. I am only going to create one but there is no need to use the full capacity of the volume group because another one of the great things about LVM is that it is trivially easy to enlarge (or reduce) volumes as necessary. In fact, let's do that now;

We will create a LV that does not take up the entire capacity we have available. In my case I have 3.6TB available but I will create a 2TB LV.

sudo lvcreate --name archive --size 2000G store
Logical volume "archive" created


We can take a look and see what we have created;

sudo lvdisplay
--- Logical volume ---
LV Name /dev/store/archive
VG Name store
LV UUID Pc0EVc-DF1b-n2Mt-jIfr-YHHX-CrtU-SPtyW0
LV Write Access read/write
LV Status available
# open 0
LV Size 1.95 TiB
Current LE 512000
Segments 3
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 251:0


So, just say we actually need more room in our "archive" volume. Well, that is no problem, we just need to extend it;

sudo lvextend -L3600G /dev/store/archive
Extending logical volume archive to 3.52 TiB
Logical volume archive successfully resized


We can confirm that this has worked by checking with the lvdisplay command again;

sudo lvdisplay
--- Logical volume ---
LV Name /dev/store/archive
VG Name store
LV UUID Pc0EVc-DF1b-n2Mt-jIfr-YHHX-CrtU-SPtyW0
LV Write Access read/write
LV Status available
# open 0
LV Size 3.52 TiB
Current LE 921600
Segments 4
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 251:0


Checkpoint: You should have all your drives added to the 'volume group" and have created one (or more) "logical volumes" at this point. Make sure the output from the "lvdisplay" command above corresponds with what you are seeing here.


So, we have set up our LVM volumes but just like any other hard drive we can't use them without a filesystem, let's format ours with ext3

sudo mkfs.ext3 /dev/store/archive
mke2fs 1.41.11 (14-Mar-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
235929600 inodes, 943718400 blocks
47185920 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=0
28800 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
102400000, 214990848, 512000000, 550731776, 644972544

Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 25 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.


When that finally completes all we need to do now is create a mountpoint and add the volume to fstab.

I prefer to use uuid's rather than the physical device paths so that is the way we are going to mount our volume here. If you prefer of course you can mount the volume just like any device in fstab.

First, create a mountpoint for the volume;

sudo mkdir -p /store/archive

Now we need to find the UUID of our new volume;

sudo blkid /dev/store/archive

This will return something like this;

/dev/store/archive: UUID="ee88bfd6-1a7e-486f-85ff-2f2e4c81bd6d" SEC_TYPE="ext2" TYPE="ext3"

You want to select and copy the UUID string (without the quotes).

Now, edit /etc/fstab

sudo vi /etc/fstab

Add a line like this;

UUID=ee88bfd6-1a7e-486f-85ff-2f2e4c81bd6d /store/archive ext3 errors=remount-ro 0 1

Let's test to see if we can mount the new volume.

sudo mount /store/archive

If all goes well there should be no error returned.

Let's see if it is mounted;

df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 7.1G 5.1G 1.7G 76% /
none 998M 220K 997M 1% /dev
none 1002M 0 1002M 0% /dev/shm
tmpfs 250G 40K 250G 1% /tmp
none 1002M 284K 1002M 1% /var/run
none 1002M 0 1002M 0% /var/lock
none 1002M 0 1002M 0% /lib/init/rw
/dev/sdb1 688G 389G 265G 60% /mnt/sdb1
/dev/mapper/store-archive
3.5T 197M 3.3T 1% /store/archive

Great! As we can see above, /dev/mapper/store-archive is now mounted to /store/archive

The final tweak is optional and involves setting the reserved block count down from 5% to something more reasonable. On very large filesystems 5% is too much and by reducing these reserved blocks we can free up gigabytes of space.

Use tune2fs to set reserved blocks at 1%;

sudo tune2fs -m 1 /dev/store/archive

And that's it. You should now be able start placing data in your new LVM volume!

Here are some other commands that you will find useful, they are pretty self explanatory so I'm not going to detail their use here.

vgrename

lvreduce

lvremove

pvrename

pvremove

lvrename

vgscan

lvscan