As we saw in the previous article, Linux provides a lot of helpful utilities. We reviewed these tools with regard to the OSI model, and now we’re arrived at the application layer—maybe the most interesting layer, full of useful protocols and related utilities. In this article we’ll go through a case study. With the help of the needs of a fictional little firm, we’ll build a useful network consisting of Cisco routers/switches and Linux machines. We’ll need to use various technologies covered by the CCNA curriculum, while getting familiar with Linux solutions also.

First a few words about the topology, which is shown in the next figure (the Internet cloud should be connected to the NIC in the host machine, which connects to the Internet):

Our firm uses VLANs named Accounting, Engineers, and the Server. The connectivity between the VLANs is provided by the GW router, which works in “router-on-a-stick” mode, and is the gateway to the Internet. The access to the various resources is controlled by ACLs and by the Linux firewall. The IP addressing scheme is shown here:

Device name Interface IP address/mask VLAN ID/name
GW f0/0 DHCP
GW f0/1.1 1/default
GW f0/1.5 5/Accounting
GW f0/1.10 10/Engineers
GW f0/1.15 15/Server
SW1 VLAN1 DHCP 1/default
Accounting eth0 DHCP 5/Accounting
Engineers eth0 DHCP 10/Engineers
Debian4Cisco 15/Server

Our first scenario is to provide DHCP service for VLANs 1, 5 and 10 on the GW router. For the DNS server, you can use your own, or the public for example. On the Linux hosts, we need to use the dhclient eth0 command to get the addressing information but, before this, we need to gain root privileges by using the sudo su command. On the Debian server we need to use the following commands:

The DNS settings are stored in a file called /etc/resolv.conf; open it with a text editor and add the next line (if there are already servers in it, this may be unnecessary):


We need Internet access to all devices, so set up PAT accordingly (I don’t want to show the complete configuration, just two pieces of advice: the NAT inside interfaces are the F0/1 subinterfaces, and the ACL can be to cover all the inside LANs). Test the connectivity by pinging a public address/domain name from every machine.

For the improved security we want to separate the Accounting and Engineers VLANs with ACLs on the GW. This is homework again, but the solution can be found in the attached GNS3 lab configuration file. We also want to protect our server, so we’ll use the built-in Linux firewall called NetFilter, which can be configured by the iptables command. By default, the firewall rules accept any kind of traffic; examine this with the following command:

It can be seen that there are three chains of rules: the INPUT is for filtering the traffic destined to the server itself, the FORWARD for the traffic that goes through the machine, and the OUTPUT is for the traffic that originates in the machine. There are default policies as well, all of them in ACCEPT state. So close down the access with the following command:

iptables –P INPUT DROP

This sets the policy to drop every incoming packet. This, of course, prevents any service from working, so we need to allow the reply packets for (most of) the output traffic. The simplest method is to use the state module of NetFilter; this just does that:

iptables -A INPUT -m state –state ESTABLISHED -j ACCEPT

Now install our private DNS server. This will be a caching-only server at first: It uses the root DNS servers and recursive lookups for unknown addresses first, but the answers will be cached and this way it gets smarter and smarter. The software we should install is called BIND, the best-known DNS software, with the command of apt-get install bind9. The program is functioning as a caching-only server almost out of the box, just little “cosmetics”: the name server will be itself for itself, so change the nameserver value to in the /etc/resolv.conf file. There’s another thing to do: Allow UDP port 53 to come into the server (the state module doesn’t handle this) and allow the traffic from the loopback:

iptables -I INPUT -p udp –dport 53 -j ACCEPT
iptables -I INPUT -s -j ACCEPT

Finally, we need to set up the networks the server allows queries for. Locate the /etc/bind/named.conf.options file, then insert the following line before the last one (with the value of “};”) :

allow-query { localhost;; };

Restart the server with the service bind9 restart command.

There are some useful utilities to check the DNS: nslookup, host and, dig (domain information groper). Just issue this command and see the output: It displays the root servers as the main source of information, the server IP of, and the query time; this can be important information soon.

Now modify the DHCP configuration on the GW so that the clients use our server as DNS, and renew the configuration by using the dhclient eth0 command on both the client PCs. The interesting part is coming: Try to ping a public address from the PCs. At the first try, the response from the DNS will be a bit slow, but try it again and it should be noticeably faster. It’s because BIND first has to perform a recursive DNS query, but it caches the answer and the next time it serves this to the clients. Use the dig command on the server itself to see the exact query times, and watch the traffic with Wireshark in GNS3—it’ll be instructive.

If we have a DNS server, we can use it for serving our own domain also—in our lab, of course, it will be hidden to the outside world. Let’s choose the domain name of my.lab and create the zone configuration for this. The zone file itself is located in /etc/bind/ directory under the name of, and its contents:

We just have to copy the db.local file, which is part of the bind package, and modify it accordingly. (You can read about the structure of the zone file at the end of the article). The second step is to put the following lines into /etc/bind/named.conf.local, the configuration file that holds the information about the local zones:

After reloading BIND (you can use the rndc reload command also), we can test it by issuing the nslookup on one of the client PCs:

The forward lookup looks OK, but for a perfect DNS server we should have the reverse lookup function as well. This is homework for the curious!

The next step is to modify the infrastructure so that we move the DHCP service from the GW to the Debian server. Stop the DHCP on the GW first by clearing the corresponding configuration, and put the ip helper-address command into the f0/1.5 and f0/1.10 subinterface configuration in order to DHCP relaying. Then install the isc-dhcp-server package on Linux. During the install we need to tell the interface to listen on (eth0), and then configure it because at first it doesn’t have any pool to serve. Locate the /etc/dhcp/dhcpd.conf file, then modify and add the following information:

After restarting the DHCP server with the service isc-dhcp-server restart command, the client PCs should get the new information. On the server locate the /var/lib/dhcp/dhcpd.leases file, which contains information about the leased addresses.

Let’s continue by installing some application layer services to experiment with. The first one can be a web server: The best-known is Apache, but there are numerous other program available for Linux: nginx, lighttpd and so on. We’ll use the apache2 package. Some other packages will be installed also, and in the end we’ll have a functioning web server. How to test it? First, use the netstat –atp command on the server and search for either the software’s name or the port name (http) in the output. Second, we can test it without any browser, just telnet to the TCP port 80 of the server from a client:

This clearly presents the way HTTP works by default: The client (usually a browser) connects to the server and uses some method (usually a GET) to describe what resource it needs. The server answers with the content of the required resource; in this case it is an HTML code—if we know the basics of HTML, we can easily decode the content. Apache is a very powerful application but I just mention one important thing here: If we want to serve our own web pages, then we have to put the content into the /var/www directory on the server. A secure way for this is using Secure Copy (SCP for short), so let’s install the OpenSSH packages with apt-get install openssh-server: With this we’ll able to manage the server remotely, too. From now on we can use the ssh –l username server.address command to log in remotely, and scp localfile username@server.address:/directory/path/ command to copy a file to the server. If we have to copy more files, we can use sftp username@server.address command which is similar to a regular FTP client. By the way, FTP server can be easily installed also: Linux has a lot of different FTP servers; the most famous are ProFTPd and vsftpd. If we choose the proftpd-basic package, normal (I mean registered) users can immediately use it. If we want anonymous access, locate the /etc/proftpd/proftpd.conf file, and the last section contains a ready-to-use configuration, just uncomment the appropriate lines. FTP service can be useful to store Cisco IOS and configuration files, as described in a previous article.

“Time is money”—this statement is true in the networks also, because time synchronization among our devices can be really important and affects the functions of many services (for example, proper logging, authentication services, and so on). There’s a convenient way to keep the clocks of our devices in sync: this protocol is called network time protocol (NTP). The time sources are very accurate clocks to which the other servers synchronize their clocks. The concept of stratum means the “distance” of a particular server from this source: The publicly available time servers are stratum 1 or stratum 2 servers; see the list at the end of this article. In our networks, the stratum number must be higher (but not more than 16). Cisco routers can act as time servers and clients also, but in this lab we’ll configure Linux as server and GW as client.

The server part first: Install the necessary packages with apt-get install ntp ntpdate. First, we want our server to be immediately synchronized with a public NTP server. Issue the ntpdate command, where is a time server near you. Check the result with the date command. Next, we have to make some modifications in the server configuration file located at /etc/ntp.conf. Open it with an editor. We have to define the allowed clients that can query the server, so locate the lines starting with restrict and put in the following line:

restrict netmask notrap nomodify

This allows queries from all subnets. Now save the file and then restart the NTP service with service
ntp restart command. To check things issue the ntpq command as can be seen on the following picture:

The “-p” parameter prints the servers from the pool defined in the configuration (see the comments in the file). The “st” column is the stratum value. The “-c rv” parameter displays more information, the important one is the stratum again: If you see the value of 16, then wait for some time and issue the command again: NTP sometimes takes a while to make the synchronization.

Continue on the Cisco device. Girst check the clock on the router with show clock. Then configure it as a client by the ntp server command (it’s a bit confusing that the client mode must be configured by server keyword, but don’t worry). Then issue the following commands to check NTP operation:

Note that the stratum on the router is one higher than on the server. Now the clocks are synchronized but, if the router supports it, another command can be useful too: ntp update-calendar synchronizes the hardware clock.

This is the end of our journey through the OSI model and collecting Linux solutions, but the warehouse of Linux is not exhausted yet to support Cisco devices; follow me still!

Useful Links

DNS zone file structure:


NTP servers list: