Linux Networking Cookbook

By Gregory Boyce
    What do you get with a Packt Subscription?

  • Instant access to this title and 7,500+ eBooks & Videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Free Chapter
    Configuring a Router
About this book
Linux can be configured as a networked workstation, a DNS server, a mail server, a firewall, a gateway router, and many other things. These are all part of administration tasks, hence network administration is one of the main tasks of Linux system administration. By knowing how to configure system network interfaces in a reliable and optimal manner, Linux administrators can deploy and configure several network services including file, web, mail, and servers while working in large enterprise environments. Starting with a simple Linux router that passes traffic between two private networks, you will see how to enable NAT on the router in order to allow Internet access from the network, and will also enable DHCP on the network to ease configuration of client systems. You will then move on to configuring your own DNS server on your local network using bind9 and tying it into your DHCP server to allow automatic configuration of local hostnames. You will then future enable your network by setting up IPv6 via tunnel providers. Moving on, we’ll configure Samba to centralize authentication for your network services; we will also configure Linux client to leverage it for authentication, and set up a RADIUS server that uses the directory server for authentication. Toward the end, you will have a network with a number of services running on it, and will implement monitoring in order to detect problems as they occur.
Publication date:
June 2016


Chapter 1. Configuring a Router

In this chapter, we will cover:

  • Setting up the physical network

  • Configuring IPv4

  • Configuring IPv4 permanently

  • Connecting two networks

  • Enabling NAT to the outside

  • Setting up DHCP

  • Setting up a firewall with IPtables

  • Setting up port forwarding

  • Adding VLAN Tagging



This chapter introduces some of the basic networking concepts and the methods to utilize them on Linux systems. It provides us with a good base to build upon. We're going to start with two computers connected with a single network cable and work our way from there to configure a router to connect your network to the Internet.

Routers are devices that are configured to span multiple networks and forward packets between them as needed. They also perform Network Address Translation (NAT) in order to allow your private network to share a single public IPv4 address.


Setting up the physical network

Before we start configuring the networking within Linux, we need to physically connect the systems. The simplest configuration involves connecting the two computers with a single cable, although connecting them to a switch may make more sense for additional expansion. Once physically connected, we need to confirm that they are working as expected.

How to do it…

On each Linux system, use the ip command to check for a network link as shown:

# ip link set dev eth0 up
# ip link show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:6e:8f:ab brd ff:ff:ff:ff:ff:ff

Some people may choose to use ethtool, mii-tool, or mii-diag to perform the same action.

Make sure to run the same command on both the systems, especially if you're connecting to a switch rather than directly connecting the two systems.

How it works…

The first command brings up the network interface card (NIC). This activates the interface and allows it to start the process to check for a network link or electrical connection between the two systems.

Next, the show command gives you a bunch of information about the link. You should see a state showing UP. If it shows DOWN, then you have a link issue of some sort. This could be a disconnected/bad cable, a bad switch, or you forgot to bring up the network interface.


Configuring IPv4

Now that we've established a link between the machines, let's put some IP addresses on the systems so that we can communicate between them. For now, let's look at manually configuring IP addresses rather than auto-configuring them via DHCP.

How to do it…

We need to manually configure the IP addresses using the ip command. Let's start with server 1:

# ip addr add dev eth0
# ip addr list eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:6e:8f:ab brd ff:ff:ff:ff:ff:ff
    inet brd scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe6e:8fab/64 scope link
       valid_lft forever preferred_lft forever

Now we need to perform the same action on server 2, but with instead of

How it works…

There are a few things in play here, so it probably makes sense to go through them one at a time.

First, let's start off by looking at the IP address that we're configuring. The and are a part of a series of netblocks set aside for private networks by RFC1918, IP Address Allocation for Private Internets. RFC1918 sets aside three large ranges, (, (, and (

For our purpose, we're configuring, which is an IP range that includes This includes 256 addresses, of which 254 are usable after setting aside as the network address and as the broadcast address. Both our systems get one IP in that range, which should allow them to communicate between them.

Next, we use the ip command to define an address on the eth0 device using one of the IP addresses in that range. You need to make sure that each machine in that range has a different IP address in order to prevent IP address conflicts, which would make communication between the two systems impossible and communication with different systems difficult.

Some people may be accustomed to seeing the ifconfig command rather than the ip command used here. While it will certainly do the job in most cases, net-tool (and its ifconfig command) has been deprecated by most distributions since the turn of the century, in favor of iproute2 and its ip command.

Once the commands have been run on both servers, you should be able to ping them from each other. Log in to and run the following:

# ping –c 2 –n

If everything is configured properly, you will be able to see successful ping responses at this point.


Configuring IPv4 permanently

In the previous section we configured the network interface, but this configuration is only valid while the system is up and running. A reboot will clear this configuration, unless you take steps to make sure that it is configured on each boot. This configuration will be specific to the distribution that you are running, although most distributions fall under either the Debian or Red Hat methods.

How to do it…

Let' see how it works in Debian/Ubuntu:

  1. Add eth0 configuration to /etc/network/interfaces:

    auto eth0
    iface eth0 inet static
  2. Bring up the network interface:

    # ifup eth0

Let' see how it works in Red Hat/CentOS:

  1. Add the eth0 configuration to /etc/sysconfig/network-scripts/ifcfg-eth0:

  2. Bring up the network interface:

    # ifup eth0

How it works…

Linux distributions are configured through init systems, such as Upstart, SystemD, or SysVInit. During the initialization process, the interfaces, or ifcfg-eth0 files, are used as a configuration for the networking setup scripts. These scripts then use the same ip commands, or possibly ifconfig commands to set up and bring up the network interface.


Connecting two networks

For our next step, we're going to add a second interface to server 1. In addition to being configured on eth0, we're going to configure on eth1. The second interface could just as easily be, but let's make sure that the networks are obviously different.

The systems should be configured similar to Figure 1:

How to do it…

Let's connect two networks:

  1. Configure the network interface on eth1 on server 1:

    # ip link set dev eth1 up
    # ip addr add dev eth1
    # ip addr list eth1
    3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 00:0c:29:99:ff:c1 brd ff:ff:ff:ff:ff:ff
        inet scope global eth1
           valid_lft forever preferred_lft forever
        inet6 fe80::20c:29ff:fe99:ffc1/64 scope link
           valid_lft forever preferred_lft forever
  2. Connect your third system to eth1 on server 1.

  3. Configure eth0 on server 3 with an IP address of

    # ip link set dev eth0 up
    # ip addr add dev eth0
    # ip addr list eth1
    3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 00:0c:29:99:ff:c2 brd ff:ff:ff:ff:ff:ff
        inet scope global eth1
           valid_lft forever preferred_lft forever
        inet6 fe80::20c:29ff:fe99:ffc1/64 scope link
           valid_lft forever preferred_lft forever
  4. Add a default route on server 3:

    # ip route add default via
  5. Enable routing on server 1:

    # echo net.ipv4.ip_forward=1 > /etc/sysctl.conf
    # sysctl -p /etc/sysctl.conf
  6. Add a default route on server 2:

    # ip route add default via

How it works…

When you configure an IP address on a Linux system, you automatically have a route defined, which states that in order to access another IP address in the same subnet, you should use as your gateway. This tells the IP stack that the system, if it exists, will be on the same layer as the two network segments, and that it should use ARP to determine the MAC address it should communicate with.

If you want to talk to a machine outside of that subnet, the system will need to know how to communicate with it. This is done by defining a route with a gateway IP address that you forward the packet to. You then depend on the gateway system to forward the packet to the correct destination.

Most commonly, you'll deal with a default route, which is the route that the system uses for any packet that is not deemed to be local. In our configuration, we tell the system that the default route is, which asks us to forward any non-local packets to an IP address configured on our server 1 box. This means that server 1 will act as our router.

You can also define more specific routes where you can explicitly define an IP address to forward packets to a specific IP address or subnet. This can be useful in a network where one router provides access to the Internet and a second router provides access to a second internal network.

At this point server 3, configured as, knows that IP addresses on are local and any other packet should be sent to in order to be forwarded. However, if you attempt to ping a system that is outside your local network (for example, it will not arrive. This is because routing on Linux systems is disabled by default and needs to be enabled on server 1 before it can forward packets. Enabling routing can be done by setting /proc/sys/net/ipv4/ip_forward to 1, or via sysctl, which is the manner in which we've chosen to set it.

Once routing is enabled, packets addressed from server 3 will be received by your router and forwarded to (server 2) via eth0 on the router. will receive the packet from your router and promptly attempt to respond. This response will fail, as server 2 does not have a defined route for accessing the network. This is fixed by adding a default route on server 2 as well, but sending to the router's interface on the network.

Now server 3 knows how to address server 2, server 2 knows how to address server 3, and server 1 routes packets between the two as needed. Congratulations, you have connected two networks.


Enabling NAT to the outside

Connecting two local networks is useful, but these days it's more common to want to connect a local network to the Internet. The basic concept works the same, but with the necessary addition of NAT. NAT rewrites your packet headers in order to make them appear as if they come from your router, thus effectively hiding your system's address from the destination.

How to do it…

Create a third NIC (eth2) on server 1 and connect it to your cable modem or ISP's router.

  1. Configure eth2 to receive an IP address via DHCP:

    auto eth2
    iface eth2 inet dhcp
  2. Use iptables to enable NAT on packets heading out through eth2:

    # /sbin/iptables -t nat -A POSTROUTING -o eth2 \
    # /sbin/iptables -A FORWARD -i eth2 -o eth0 -m \
      state --state RELATED,ESTABLISHED -j ACCEPT
    # /sbin/iptables -A FORWARD -i eth0 –o eth2 -j ACCE PT

How it works…

In the last section, we discussed how in order for two systems on different networks to be able to talk to each other, they need to have routes defined which will forward packets to a router that can deliver the packet to the appropriate destination. The same is true on the Internet.

If server 2 attempts to contact an IP address on the Internet, for example Google's nameserver at, your router will pass them onto the destination. Let's give that a try:

# ping -c 2
PING ( 56(84) bytes of data.
--- ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 999ms

No responses were received. So what went wrong here?

You'll recall that I said the IP addresses that we were using were defined by RFC1918 as internal IP address space. Due to this, these IP addresses are not directly usable as Internet hosts. In our example, one of the two following things will happen:

  • Our router will send packets out of the Internet-facing interface, where it will travel across the Internet to our destination, which will respond to the packet. The response will not be able to find its way back to our system due to the un-routed nature of the destination.

  • Our router will send the packets out of its Internet-facing interface, where the next hop will drop the packets due to implementing egress filtering of traffic with invalid source addresses.

Iptables is a command-line tool in Linux for interfacing with the Linux kernel firewall, which is implemented as a part of the netfilter subsystem.

Let's break down the first command line:

  • The -t option specifies the packet matching table to use. In this case, we're going to use the nat table.

  • f-A indicates that the specified rule should be appended to the selected chain, which in this case is POSTROUTING. The POSTROUTING chain is processed after the kernel handles packet routing.

  • -o specifies the output interface. In our example, the eth0 interface contains the internal IP systems and eth2 leads to the Internet.

  • -j specifies what to do if the packet matches the rule. In this case, we're going to masquerade the packet (modify the IP).

Put them together and we have matching packets heading out on eth2; rewrite the source IP address and track it in the NAT table.

The second command is added in the -m command, which matches a packet property, in this case state. For the packets that came in on eth1 (from the Internet), and destined to eth0 (lan), check to see if they are related to or are a part of an established connection. If so, accept the packet and assign it to the FORWARD chain. The FORWARD chain handles any packet that is being passed through your router rather than the packets originating from the system (OUTPUT chain) or packets destined to your system (INPUT chain).

Finally, any packets that come in on eth0 (lan) and are heading out on eth2 (Internet) are just automatically accepted.


Setting up DHCP

You now have a router that provides Internet access to all systems behind it, but the systems behind it need to be manually configured with IP addresses while avoiding conflicts. You also need to configure them with DNS servers for resolving host information. To solve this, we're going to configure a DHCP server on your router to be responsible for handing out addresses.

Dynamic Host Configuration Protocol (DHCP) allows you to centralize your IP address management. Machines which are added to a network will issue a DHCP request asking any available DHCP server to provide it with configuration information including IP address, subnet mask, gateway, DNS server, and so on.

How to do it…

Let's set up DHCP in Debian/Ubuntu:

  1. Install a DHCP server:

    # sudo apt-get install isc-dhcp-server
  2. Modify /etc/default/isc-dhcp-server to add the interface which you should serve requests on:

    # sudo sed –i "s/^INTERFACES.*/INTERFACES="eth0"\
  3. Modify /etc/dhcp3/dhcpd.conf to configure the network information you want to serve:

    ddns-update-style none;
    option domain-name "";
    option domain-name-servers,;
    default-lease-time 600;
    max-lease-time 7200;
    subnet netmask {
      option routers;

Let's set up DHCP in Red Hat/CentOS

  1. Install a DHCP server:

    # sudo yum install dhcp
  2. Modify /etc/dhcp/dhcpd.conf to configure the network information you want to serve:

    ddns-update-style none;
    option domain-name "";
    option domain-name-servers,;
    default-lease-time 600;
    max-lease-time 7200;
    subnet netmask {
      option routers;

How it works…

The first thing you might notice about the difference between Debian-and Red Hat-based systems is that in Debian-based systems, you need to explicitly define the interfaces to listen on, while this is not needed on Red Hat systems. This is because Red Hat has chosen to trust ISC DHCP's built-in restriction to only listen on interfaces that have an IP address in the same subnet as DHCP leases were set up for.

Let's look at the configuration for the DHCP server itself.

The first section defines the global configuration parameters:

  • ddns-update-style: This defines optional functionality to update a DNS server with hostnames for the machines in your network. We'll look at this option in detail later in the book.

  • option domain-name: This defines the domain name for your network. On Linux DHCP clients, this populates the search field that specifies the domain to search in for non-fully qualified domain names.

  • option domain-name-servers: This specifies the default DNS servers, which your clients should use for domain resolution. In this example, we've used Google's public nameserver, but you may instead want to use your ISP's nameservers or a different public service.

  • Max-lease-time and default-lease-time: This defines how many seconds the IP address can dedicate to the requesting machine. Clients can also request for a specific lease length. Max-lease-time puts a cap on how long they can request it for, while default-lease-time comes into play if they don't request a specific lease length. Longer leases cut down on the number of IP address changes you may experience, while shorter leases make sure that you don't run out of IP addresses if you have a lot of short-term users on the network.

  • authoritative directive: This tells the DHCP server that it is the authority for this particular network. Sometimes, clients that have recently had a lease on another network may attempt to re-request the same IP address. An authoritative server may send them a DHCPNAK (negative acknowledgement) to tell them that they must request a new IP address. If your DHCP server is not the only one on the network, you may set it as not authoritative in order to avoid this behavior.

The second section is the subnet declaration. Your DHCP server must know about all the subnets configured on the interface that it has been told to serve DHCP addresses on. For the subnets on which it should serve addresses, you should define the range of IPs to hand out and you most likely want to define your network gateway as well. If your machine has multiple IP addresses on the interface and you only want to serve IPs to one of them, you should still define the subnet, but leave out the range and gateway information from within the brackets. For example:

subnet netmask {

Now that your DHCP server is configured, it will automatically hand out the IP addresses to all machines that connect to the network which are configured to request addresses via the DHCP protocol, which is often the default. It will keep track of these leases in a human-readable format in /var/lib/dhcpd/dhcpd.leases, in order to avoid having multiple machines receive the same address.


Setting up a firewall with IPtables

We touched upon iptables a little while discussing NAT, but now we're going to go a bit deeper into configuring a secure firewall for your network.

How to do it…

A properly configured firewall should be configured in a default deny configuration with specific allows (Whitelist) for what you want to accept:

# iptables -A INPUT -i lo -j ACCEPT 
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 
# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# iptables -P INPUT DROP 
# iptables -P FORWARD DROP
# iptables -P OUTPUT ACCEPT
# iptables -A FORWARD -i eth0 -j ACCEPT
# iptables -t nat -A POSTROUTING -o eth2 \
# iptables -A FORWARD -i eth2 -o eth0 -m \
# iptables -A FORWARD -i eth0 -j ACCEPT

How it works…

We start off by setting an ACCEPT policy on traffic destined to the local system on the localhost adapter (-i lo). A lot of software expects to be able to communicate over the localhost adapter, so we want to make sure we don't inadvertently filter it.

Next, we set an ACCEPT policy for any packet that matches a state (-m state) of ESTABLISHED, RELATED. This command accepts packets which are a part of, or related to, an established connection. ESTABLISHED should be pretty straightforward. RELATED packets are special cases that the connection tracking module needs to have a prior knowledge of. An example of this is the FTP protocol operating in active mode. The FTP client in active mode connects to the server on port 21. Data transfers however, operate on a second connection originating from the ftp server from port 20. During the operation of the connection, the port 21 packets are ESTABLISHED, while the port 20 packets are RELATED.

The third command accepts any TCP connection (-p tcp) destined for port 22 (--dport 22) that is destined for your system. This rule allows you to SSH into the machine.

Next, we will define the default policies. By default, we drop packets on the INPUT and FORWARD chains and accept packets on the OUTPUT chain.

The last three lines you'll recognize from the NAT section, which tells the firewall to allow any packets starting on the internal network and heading out to the Internet.

Additional ACCEPT rules based upon destination ports can be opened as needed as INPUT lines, like the port 22 one.


Setting up port forwarding

In the previous section, we configured iptables to accept connections to port 22 in order to allow people to SSH into the host. Sometimes, you want to forward a port to a system behind the firewall instead of having the service run on the firewall itself. For example, you may have a web server running on port 8080 on an internal box that you want to expose to the Internet via port 80 on the firewall.

How to do it…

  1. Rewrite packets addressed to port 80 to instead go to port 8080:

    # iptables -t nat -A PREROUTING -p tcp -i eth2 --dport 80 \
    -j DNAT --to-destination 
  2. Accept any packets addressed to port 8080:

    # iptables -A FORWARD -p tcp -d \
    --dport 8080 -m state --state NEW,ESTABLISHED,RELATED \
    -j ACCEPT 

How it works…

This example is a lot simpler since it builds upon concepts we've already learned. We just have two simple commands:

  • First we set up a PREROUTING rule which will be processed once the packet is received, prior to any routing rules being applied. If the packet is TCP and came in on the Internet interface (eth2) with a destination port, then the packet is added to the destination NAT (DNAT) chain with a final destination of port 8080.

  • Next, any packet destined for port 8080 is either a new connection or an established connection; the packet is then accepted for forwarding to the destination.


Adding VLAN Tagging

Right now we have a rather simple network configuration. We have a single router with a public-facing IP address on one interface and a private IP address on the second interface. But what if we want to have multiple private networks behind the route?

Our first option in this scenario would be to add additional IP addresses to the internal interface. The ip command allows you to assign multiple IPs to a single interface, with optional interface aliases like eth0:0. This will allow you to assign IP addresses to systems behind the firewall within one of the few ranges and have them all route appropriately.

The downside of this approach is that all the internal IPs exist within the same collision domain of the network. This has a few implications, including the ability to move systems between those IP ranges and potentially bypassing access control rules, as well as problems assigning addresses via DHCP due to confusion about what address range to hand out.

The second option would be to put a third network card in the router and then either plug the additional card into a dedicated switch or separate out the existing switch into multiple VLANs and plugging the new network card into a port on a dedicated VLAN for that network. The downside here is the additional cost of the NIC (assuming you have space to add it) and then either the usage of an extra switch port or an extra switch.

The third option is to configure the switch into dedicated VLANs and plug the LAN side of your router into a port configured as a trunk. From there, Linux can be configured to use VLAN tagging to split your single physical interface into a pair of virtual interfaces and tag packets, as appropriate, so that the switch automatically adds them to the appropriate VLAN.

How to do it...

There are two steps required in order to use VLAN tagging on your Linux server:

  1. The first is to hook it up to a switch that has VLAN enabled, connected to a port which is allowed to act as a trunk. The specifics around how to configure a switch in this mode are outside of the scope of this book, since they are specific to the switch itself. You'll want to find a managed switch which supports the 802.1Q standard and consult its documentation for configuration.

  2. The second thing you'll need is to create virtual interfaces assigned to the desired VLAN. In our case, we're going to create two virtual interfaces, which are assigned to vlans 1 and 2.

    # ip link add link eth0 name eth0.1 type vlan id 1
    # ip link add link eth0 name eth0.2 type vlan id 2

Now that they exist, you can treat them like normal network interfaces and configure them as we did in the section on adding a second network.


Note that eth0.1 is a naming convention, not a requirement at this point. You could instead choose to name the interfaces names wireless and wired if you wanted to.

Making this change permanent can be rather distribution specific and may depend on the use of the vconfig command, which is distributed through the VLAN package on Debian/Ubuntu. Debian-based distributions will automatically create VLAN interfaces if you specify an interface in /etc/network/interfaces which is named as a physical interface, followed by a period, and then a VLAN ID, as eth0.1 is our example.

How it works...

VLAN tagging, as defined by the 802.1Q standard, functions at the Ethernet layer level. A standard Ethernet frame contains 4 fields, the destination MAC address, the source MAC address, the EtherType or length field (depending on the type of frame), the data (the IP packet), and a frame check sequence (FCS). 802.1Q works by adding a VLAN tag between the source MAC address and then the EtherType/length field.

A switch that supports 802.1Q may have one or more network ports that are configured to act as a Trunk. Trunk ports will accept VLAN tagged packets and will pass them along as appropriate. They will detect the specified VLAN tag, determine the appropriate VLAN the packet is destined to, and will deliver the packet to any switch ports that are on that VLAN. Tagged packets can even pass between multiple switches as long as they are properly configured. If a packet is received without a tag on it, it will have a tag added automatically, based upon the VLAN associated with the switch port it was received on.

About the Author
  • Gregory Boyce

    Gregory Boyce is a technologist with nearly 20 years of experience in using and managing Linux systems. When he's not at work or spending time with his wife and two daughters, he is playing around with new technologies.

    Browse publications by this author
Latest Reviews (6 reviews total)
Linux Networking Cookbook
Unlock this book and the full library FREE for 7 days
Start now