Linux Network Stack Administration: A Developer’s Approach

Of late, Linux has been gaining popularity in IT-enabled industries. Linux networking has grown side by side with the operating system, and it’s very common to see Linux-enabled devices in the networking domain.

Linux provides a very versatile, efficient and well-organised network stack. The TCP/IP implementation of Linux could be considered one of the best amongst operating systems. While packet processing through TCP/IP is a very interesting topic, this article will cover monitoring and managing the Linux TCP/IP stack. Although there are many tools that can be used for the same purpose, this article aims to explore administration of the networking stack without using external tools. This is more useful, especially for developers while working on embedded or remote systems where such ‘external’ tools are not available.

This article attempts to cover the various methods of managing the networking stack, i.e., by application-level C programs, kernel-level C programs, the proc filesystem, etc.

proc is a virtual filesystem that can be located under the /proc mount point. This is really not a filesystem, but a window to look into the Linux kernel. The files inside /proc are not really files but can be termed as calls to kernel functions. Therefore, reading or writing a proc file results in a function call invoked in kernel space, which can be used to read/write kernel parameters and therefore monitor and/or control the Linux networking stack. The Linux networking stack also provides many virtual files inside /proc, which can be used to monitor and/or control the networking stack.

This article is divided into three sections—monitoring, management/control and security, though sometimes it is difficult to make a clear distinction between these three aspects.

Monitoring

Here, we will cover some of the methods to monitor the TCP/IP networking stack.

Packet monitoring: The primary requirement of network stack administration is to monitor the packet flow through the system. Linux provides a file named /proc/net/dev, which shows the packet flow through every interface in the system. The following table shows an example from /proc/net/dev file. Although the file has many more fields, some have been stripped down for a better understanding.

foo@localhost:~$ cat /proc/net/dev

Inter-|   Receive                              Transmit
face |   bytes    packets errs drop  |  bytes    packets errs drop
    lo:    80036    1597      0      0    |  80036    1597      0     0
eth0:      0             0         0      0    |    0             0         0     0
eth1:   26922      154       0      0    |  19871     194       0     0

As the example shows, the system has received 26922 bytes and 154 packets over the eth1 interface while the eth0 interface has not received any packet. Similarly, the system has transmitted 19871 bytes and 194 packets over the eth1 interface. Clearly, no error packets were received, and none were dropped either.

Therefore this file can be used for a quick view of packet flow through the system.

As the received/transmitted packets are processed by IP and TCP/UDP protocols, a deeper look of the packet flow can be viewed in /proc/net/snmp file. A stripped down view of the file is shown below:

Ip: InReceives InDiscards OutRequests OutDiscards
Ip:      2725             0              2519                0
Icmp: InMsgs InErrors OutMsgs OutErrors
Icmp:  72            0              73           0
Udp: InDatagrams NoPorts  InErrors OutDatagrams
Udp:   116                   0              0              116

The above example shows the packet distribution at the upper layers. This file shows many more packet counts for different cases like packet header errors, address errors, port errors, etc.

Therefore this file is useful for a quick view of connection patterns through the system.

Packet capturing: Linux provides a very powerful and versatile socket interface that can be used to pick packets directly from the Ethernet or IP layer. These sockets are called PF_PACKET sockets. The following small snippet of C code shows how to use PF_PACKET sockets to capture packets arriving at the system.

#define IF_NAME "eth0"
struct ifreq ifr = {0}

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

/* Set promiscuous mode to capture even those packets which are not destined to our host */
    strncpy(ifr.ifr_name, IF_NAME, IFNAMSIZ);
    ioctl(fd, SIOCGIFFLAGS, &ifr);
    ifr.ifr_flags |= IFF_PROMISC;
    ioctl(fd, SIOCSIFFLAGS, &ifr);

/* bind to "eth0" if only those packet arriving on "eth0" are required */
    strncpy(ifr.ifr_name, IF_NAME, IFNAMSIZ);
    setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (char*)&ifr, sizeof(ifr));

    recv(fd, buf, sizeof(buf), 0);

The above code snippet, with ignored error checks, shows how to capture a packet arriving at the interface eth0. The packet contents can be used to have a deeper look into the established or attempted connections/flows.

In the above example, socket_type is used as SOCK_RAW to receive the entire packet including the link layer header. The SOCK_DGRM socket_type can be used to capture packets with the link layer header removed.

When the protocol field is set to ETH_P_ALL, all protocol packets are received.

Many packet-capturing tools are based on PF_PACKET sockets. Those packet-capturing tools provide the additional functions of packet filtering, organised display of packet contents, etc, which make administration simpler.

Management/Control

This section describes some methods for the management and control of the TCP/IP networking stack.

Packet forwarding: A networking system running Linux can be configured to run as a host or as the router. In the latter case, the system can forward packets destined for other machines, to the appropriate next hop. Packet forwarding on Linux can be controlled, per interface, by modifying /proc/sys/net/ipv4/conf/<device_name>/forwarding. Writing 0 in this file disables packet forwarding while 1 enables packet forwarding.

Address resolution: The ARP protocol is used for IP address resolution. Complex networking systems have many interfaces and many IP addresses. It is possible to control which source address is put in to the ARP protocol headers using the file located at /proc/sys/net/ipv4/conf/<device_name>/arp_announce. It takes the following values:

  • 0 – (default) any local address
  • 1 – uses the address from the same subnet as the target address
  • 2 – prefers the primary address

Therefore, this file provides a way to control address resolution.

Resolution timeout: The Linux kernel tries to resolve an IP address through ARP if the address is not already resolved. This process queues the outgoing application packets and starts the address resolution procedure.However, if the target system is not reachable, the kernel must give up address resolution after some tries and intimate the application about the unreachable destination. The maximum number of attempts to resolve the IP address through multicast/broadcast ARP can be specified in the file /proc/sys/net/ipv4/neigh/<device_name>/mcast_solicit.

Local port range: If a networking application does not specify the transport port (i.e., binds to port 0), the kernel assigns one local port to the application. The port is chosen from a range that can be controlled by file /proc/sys/net/ipv4/ip_local_port_range.

Security

The Linux networking stack provides many ways to perform stack hardening. This helps in making the system more secure and less vulnerable to external attacks.

Capabilities: The Linux kernel provides an API, “int capable(int cap)”, which can be used to verify the credentials of a running application, and if the application does not have sufficient privileges, the process can be terminated. Linux defines several capabilities like CAP_NET_ADMIN, CAP_NET_RAW, etc. Details for all the capabilities can be looked up in the include/linux/capability.h file. The following code snippet shows how to verify whether the application holds privileges to open raw sockets:

if (!capable(CAP_NET_RAW))
return –EPERM;  /* application does not have privileges to open raw sockets */

ICMP Redirect: ICMP Redirect is sent by gateways to a host if it, due to a wrong assumption, sends a packet to the gateway destined for the local host in the same subnet. However, an attacker can forge and send an ICMP Redirect packet to a host, to divert packets for certain destinations through the attacker’s host.

Therefore, sometimes it is necessary to control ICMP Redirect messages. This can be done by editing /proc/sys/net/ipv4/conf/<device_name>/accept_redirects. Writing 0 in this file forces the system to ignore all ICMP Redirect messages.

Secure redirect: To combat a forged ICMP redirect message and still accept a valid ICMP redirect message, Linux provides a secure redirect mechanism, which is accessed by editing the file /proc/sys/net/ipv4/conf/<device_name>/secure_redirect.

Writing 0 to this file forces Linux to accept the ICMP redirect message from any host, while 1 means Linux will accept the ICMP redirect message only from gateways present in the default gateway list. This prevents most of the malicious ICMP redirects and accepts only legitimate redirects.

Cache poisoning: The ARP protocol provisions for gratuitous ARP messages, by which a host itself can announce the IP and MAC address. All the hosts receiving gratuitous ARP messages update their ARP cache with the new MAC address announced.

However, this feature can be exploited by malicious hosts that announce some other host’s IP address as their MAC address. Thereby, the attacker causes all other hosts in the network to forward packets destined to a legitimate host, to the attacker.

Linux provides gratuitous ARP message processing control by editing the file /proc/sys/net/ipv4/conf/<device_name>/arp_accept.

For example, the command echo 0 > /proc/sys/net/ipv4/conf/<device_name>/arp_accept forces the system to drop all gratuitous ARP messages on the given device.

Note: ARP gratuitous messages can be useful for networking systems that provide IP address redundancy over multiple interfaces. In such cases, for example, eth0 and eth1 having the same IP address but different MAC addresses, only one of the interfaces remains active. As soon as an active interface goes down for some reason, the standby interface becomes active and sends a gratuitous ARP message with the same IP address but a different MAC address. Therefore, all the hosts in the network update their ARP cache and start sending traffic to the eth1 interface, thereby providing IP address redundancy.

Cache thrashing: Since the Linux kernel accepts ARP responses (including gratuitous ARP responses) to update the ARP cache, it is possible to mount an ARP cache thrashing attack where continuous ARP responses are flooded to the victim system. To prevent such attacks, the Linux kernel provides a way to specify the minimum time interval between two consecutive ARP responses to be accepted. The time interval can be specified in the file /proc/sys/net/ipv4/neigh/<device_name>/locktime.

ICMP flood: The ICMP echo request and echo reply messages are used to verify network connectivity between two hosts. These messages do not carry any user data or useful data, and are only used to check network connectivity. However, it is possible to flood a system with ICMP echo messages causing the target system to do unnecessary processing and making the system slow down.

Linux provides a way to control such ICMP echo messages by editing the following files:

  • /proc/sys/net/ipv4/icmp_echo_ignore_all
  • /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

As the names suggest, the above files can be used to selectively drop either all or broadcast ICMP echo messages. Therefore, it is possible to prevent any ICMP flood attacks using the above mentioned files.

Although this article covers some of the features of administering the Linux networking stack, Linux is much richer and more flexible than indicated here, in terms of management and control.

This flexibility makes Linux one of the most sought after operating systems in the networking industry. Linux will go a long way in the years to come.

All published articles are released under Creative Commons Attribution-NonCommercial 3.0 Unported License, unless otherwise noted.
Open Source For You is powered by WordPress, which gladly sits on top of a CentOS-based LEMP stack.

Creative Commons License.