@import "./support/support"; @import "./color_schemes/"; @import "./modules"; @import "./custom/custom";
Link

Lab 6 - Networking 102

26 min read

Table of contents

  1. Overview
  2. Network Interfaces
    1. /etc/network/interfaces
    2. Checkpoint
  3. /proc filesystem
    1. /proc/net/
      1. /proc/net/dev
      2. /proc/net/[tcp|udp|raw]
      3. /proc/net/route
      4. /proc/net/arp
      5. /proc/net/snmp
    2. /proc/sys/
      1. /proc/sys/net/core/
      2. /proc/sys/net/ipv4/
    3. Checkpoint
  4. ARP configuration
  5. DNS configuration
    1. /etc/hosts
    2. /etc/resolv.conf
    3. /etc/nsswitch.conf
  6. DHCP client configuration
    1. Timing
  7. Sysadmin commands
    1. ifupdown
    2. mtr
    3. iptables
    4. Checkpoint
  8. Exercises
    1. 🔥 This is fine 🔥
      1. IMPORTANT NOTE
      2. Setup
      3. Problem Instructions
      4. Debugging Bank
    2. Net Ninjas (Optional)

Overview

This lab will go over some concepts of networking and how certain parts of a network stack are implemented and configured in linux systems. It is assumed that you are familiar with basic networking concepts such as those presented in Lab b5.

Additional information about certain files discussed here can be found in their corresponding man pages by typing man <filename>.

As with the previous labs, there will be questions sprinkled throughout- head over to Gradescope to submit your answers to them!


Network Interfaces

Network interfaces represent a point of connection between a computer and a network. Typically network interfaces are associated with a physical piece of hardware, like a network interface card. However, interfaces can also be entirely implemented in software and have no physical counterpart – take the loopback interface lo for example. lo is a virtual interface; it simulates a network interface with only software.

/etc/network/interfaces

Network interface configurations are stored under the /etc/network/interfaces file on your system. Here, there is plenty of room for complexity. For example, you can have certain interfaces automatically brought up by hooking them to system boot scripts or specify some interfaces to only be available under certain circumstances, with some of the provided control flow options.

This lab will go over some common configuration keywords, but there is much more to the file. For a detailed page of the features and syntax of the file simply type man interfaces to pull up the man page for the file.

Firstly, configurations are logically divided into units known as stanzas. The /etc/network/interfaces file is comprised of zero or more stanzas which begin with iface, mapping, auto, allow-, source, or source-directory. For brevity, we will go over the two most commonly used stanzas auto and iface.

The auto stanza is fairly simple, its syntax is auto <iface>. The auto stanza flags an interface to be brought up whenever ifup is run with the -a option (More on ifup below). Since system boot scripts use ifup with the -a option, these interfaces are brought up during boot. Multiple auto stanzas will be executed in the same order as they are written in the file.

The iface stanzas lets you express complex configurations for individual interfaces by leveraging its features. Its syntax is iface <iface> <address-family> <method>. Let’s go over some of the arguments the stanza takes.

<address-family> identifies the addressing that the interface will be using. The most common address families that you’re probably familiar with are:

  • IPv4 denoted by inet in the file
  • IPv6 denoted by inet6 in the file

Address families can be configured via different methods expressed by the <method> option. Some common methods you should be familiar with are:

  • loopback defines this interface as the loopback.
  • dhcp is for interface configuration via a DHCP server.
  • static is for static interface configuration.
  • manual brings up the interface with no default configuration.

Methods also have options that let you supply certain configuration parameters. For example, for the static method you can additionally use the address <ip-address> and netmask <mask> options to specify the static IP address and netwask you want the interface to use.

Moreover, the iface stanza additionally has its own options compatible with all families and methods. To present just a few, we have:

  • pre-[up|down] <command> runs the given <command> before the interface is either taken up or down
  • post-[up|down] <command> runs the given <command> after the interface is either taken up or down

As a final note, any changes to the configurations done in this file during runtime are not applied automatically. Changes have to be reloaded via calls to ifupdown, the de facto command suite for interacting with /etc/network/interfaces.

Checkpoint

Question 1a: Is the result of running ping enough to determine whether or not you can reach a server? Why or why not?

Question 1b: Here’s a quick check for your understanding – below is a very common default configuration for /etc/network/interfaces:

auto lo
iface lo inet loopback

In your own words, explain what this configuration does. What would happen if you deleted these lines and rebooted?

Question 1c: Write a few stanzas that configure an interface called test that is brought up on boot and given the following address: 192.168.13.37/16.

/proc filesystem

proc is a virtual filesystem that presents runtime system information in a file-like structure. This file-like interface provides a standardized method for querying and interacting with the kernel, which dumps metrics in the read-only files located in this directory. Using a tool like cat, you can dynamically read those files at runtime. But keep in mind, there are no ‘real’ files within proc.

/proc/net/

We will be focusing on certain portions of proc, the first of which being /proc/net/. This subdirectory in proc contains information about various parts of the network stack in the form of virtual files. Many commands, such as netstat, use these files when you run them.

/proc/net/dev

This file contains information and statistics on network devices. ifconfig is an example command that reads from this file. Take a look below and notice how the information presented in the ifconfig output corresponds to data dumped in dev on how many bytes and packets have been received or transmitted by an interface. alt text

/proc/net/[tcp|udp|raw]

Thetcp, raw, and udp files each contain metrics on open system sockets for their respective protocols, i.e. reading tcp displays info on TCP sockets. As a side note, raw sockets are network sockets that offer a finer degree of control over the header and payload of packets at each network layer as opposed to leaving that responsibility to the kernel. They are ideal for uses cases that send or receive packets of a type not explicitly supported by a kernel, think ICMP. For additional information check this article out. These files are read by ss, netstat, etc. Check out the example for tcp below. alt text

/proc/net/route

This file contains information about the kernel routing table. Some commands that use this file include ip and netstat. Take a look at how the file is parsed and processed by the netstat command.

alt text

/proc/net/arp

This file contains a dump of the system’s ARP cache. The arp command reads from this file. For example, look at how closely the output of the arp command resembles the raw text dumped by the kernel into the file.

alt text

/proc/net/snmp

This file contains statistics intended to be used by SNMP agents, which are a part of the Simple Network Management Protocol (SNMP). Regardless of whether or not your system is running SNMP, the data in this file is useful for investigating the network stack. Take the screenshot below for example, examining the fields we see InDiscards which according to RFC 1213 indicates packets that are discarded since problems were encountered that prevented their continued processing. Lack of buffer space is a possible cause of having a high number of discards. Having a statistic like this one, amonst others, can help pinpoint a network issue. For additional information on fields please refer to the header file here. The image is a bit small so feel free to right click -> “Open image in a new tab” to magnify the output.

alt text

/proc/sys/

Whereas the files and subdirectories mentioned above are read-only that isn’t true about the /proc/sys subdirectory which contains virtual files that also allow writes. You can not only query for system runtime parameters but also write new parameters into these files. This means you have the power to adjust kernel behavior without the need for a reboot or recompilation.

Mind-blowing.

While the /proc/sys directory contains a variety of subdirectories corresponding to aspects of the machine, the one we will be focusing on is /proc/sys/net which concerns various networking topics. Depending on configurations at the time of kernel compilation, different subdirectories are made available in /proc/sys/net, such as ethernet/, ipx/, ipv4/, and etc. Given the sheer variety of possible configurations, we will confine the scope of this discussion to the most common directories.

/proc/sys/net/core/

core/ is the first subdirectory that we’ll cover. As its name implies, it deals with core settings that direct how the kernel interacts with various networking layers.

Now we can go over some specific files in this directory, their functionality, and motivations behind adjusting them.

  • message_burst and message_cost Both of these parameters take a single integer argument and together control the logging frequency of the kernel. message_burst defines entry frequency and message_cost defines time frequency in seconds. For example, let’s take a look at their defaults. message_burst defaults to 10 and message_cost defaults to 5. This means the kernel is limited to logging 10 entries every 5 seconds.

    When adjusting the parameters in these two files, a sysadmin must keep in mind that the tradeoff here is between the granularity of the logs and the performance/storage limitations of the system. Increasing overall logging frequency can translate to a hit to system performance or huge log files eating up disk. But if logging is too infrequent, parts of the network may fail silently and bugs may become much harder to identify.

  • netdev_max_backlog This file takes one integer parameter that defines the maximum number of packets allowed to queue on a particular interface.
  • rmem_default and rmem_max These files define the default and maximum buffer sizes for receive sockets, respectively.
  • smem_default and smem_max These files define the default and maximum buffer sizes for send sockets, respectively.

    For the above sets of system parameters, adjusting queue lengths have the nice effect of allowing our system to hold more packets and avoid dropping packets due to a fast sender for example. This boils down to optimizing flow control. However, there is no such thing as a free lunch. Increasing queue sizes can only mitigate problems with arrival rates being greater than service rates for so long. For more information on why that is check out queueing theory. Moreover, having many packets stored in long queues also has its own drawback. Storing packet information isn’t free and the more packets stored in the queue, the more resources the system needs. As a result, too many packets may lead to increased paging and ultimately thrashing. Once again, we have another tradeoff, but this time between flow control and paging.

As a sysadmin many of the configuration decisions you make will be balancing between two extremes and the optimal point isn’t hard and fast. Many times you’ll have to adjust system parameters on a case-by-case basis and, after empirical testing, come to a good point.

/proc/sys/net/ipv4/

ipv4/ is another common subdirectory that contains setting relevant to IPv4. Often the settings used in this subdirectory are used, in conjunction with other tools, as a security measure to mitigate network attacks or to customize behavior when the system acts as a router.

  • icmp_echo_ignore_all This file configures the system’s behavior towards ICMP ECHO packets. This file has two states 0 for off and 1 for on. If on, the system will ignore ICMP ECHO packets from every host.
  • icmp_echo_ignore_broadcasts This file is similar to the one above, except turning this parameter on only makes the system ignore ICMP ECHO packets from broadcast and multicast.

One argument against disabling ICMP is that it makes obtaining diagnostic information about servers much harder. The output of tools that rely on ICMP, i.e. ping, are no longer as useful. On the other hand, allowing ICMP might be a bad idea if your goal is to hide certain machines. Additionally, ICMP has been used in the past in DOS attacks.

  • ip_forward Turning this parameter on permits interfaces on the system to forward packets. Take for example, if your computer has two interfaces, each connected to two different subnets, A and B. While your machine can individually send and receive traffic to hosts on either network, machines on A cannot send packets to machines on B via your machine. Turning ip_forward on is the first step to configuring your linux machine to act as a router. It is common to see this on machines that act as VPN servers, forwarding traffic on behalf of hosts.

  • ip_default_ttl This is a simple file that configures the default TTL (time to live) for outbound IP packets.
  • ip_local_port_range This file takes two integer parameters. The first integer specifies the lower bound of the range and the second specifies the upper bound. Together, the two numbers define the range of ports that can be used by TCP or UDP when a local port is needed. For example, when a socket is instantiated to send a TCP SYN, the port given to the socket is selected by the operating system and lies within the specified range. The ports in this range are as known as ephemeral ports.
  • tcp_syn_retries This file limits the number of times the system re-transmits a SYN packet when attempting to make a connection. When attempting to connect to either a ‘flaky’ host or over a ‘flaky’ network, setting this number higher might be desirable. But this comes at the cost of adding additional traffic to the network and potential blocking other processes while waiting for a SYN-ACK that might never come.
  • tcp_retries1 This file limits the number of re-transmissions before signaling the network layer about a potential problem with the connection.
  • tcp_retries2 This file limits the number of re-transmissions before killing active connections. This implies the following relationship: tcp_retries2 >= tcp_retries1. The two retry values configure how ‘patient’ your system should be when it comes to waiting on RTOs.

Additional information on configurable system parameters can be found either at this tutorial or in documentation via kernel.org or bootlin.

Checkpoint

Question 2a: Describe the tcp_syncookies sysctl option. How can we toggle this value on, and when would we want this on?

ARP configuration

The entries in the kernel’s arp cache can be read during system runtime via /proc/net/arp as mentioned above.

Additionally, ARP can be configured with persistent static entries. This typically done via a file. Batches of static entries can be included in such a file. The line-by-line format should be <mac-address> <ip-address>. To load the file’s entries into the system’s ARP cache one can run arp -f <file>. Typically the file that holds these entries has the path /etc/ethers.

Static ARP entries are cleared from the system ARP cache on reboot, meaning one would have to run the above command on each boot if we wanted the mappings to ‘persist’. To automate the procedure of running the command we can leverage the interface configuration workflow. Recall that /etc/network/interfaces provides the auto stanza to identify interfaces to be automatically configured on boot. Used in conjunction with the iface stanza and its post-up <command> option, we can execute the arp -f /etc/ethers command. This effectively has static entries ‘persist’ by having them added alongside interface configuration during boot.

DNS configuration

Some of the DNS configuration files that we will be going over are /etc/hosts, /etc/resolv.conf, /etc/nsswitch.conf.

/etc/hosts

This is simple text file that stores static mappings from IP addresses to hostnames. The format for each line is <ip-address> <cannonical-hostname> [aliases]. An example line would be 31.13.70.36 www.facebook.com fb ZuccBook

Thanks to this entry we have mapped www.facebook.com and any aliases we listed to 31.13.70.36. A very common example entry is localhost which also has the aliases ip6-localhost,ip6-loopback which explains why running something like ping localhost or ping ip6-loopback works. This file is one way to manually define translations for certain hostnames.

/etc/resolv.conf

Whereas /etc/hosts is for static translations of specific hostnames, many times we want to dynamically resolve names by issuing a query to a name server. There are usually many nameservers, public or private, available to fufill such a query and deciding which ones to query is the job of /etc/resolv.conf amongst other configuration options.

/etc/resolv.conf is the configuration file for the system resolver which is the entity that communciates with DNS name servers on your machine’s behalf. If this file does not exist, queries will default to the name server on your local machine. This file consists of one domain or search lines up to three nameserver lines and any number of options. Let’s dive into the details behind these configuration options.

  • domain Using this option will specific a local domain name. Short queries, which are queries that don’t contain any domain identifiers, then have the local domain appended to them during DNS queries.

    To understand this better take death as one of the machines within the OCF domain, ocf.berkeley.edu. One can issue a DNS query for death by typing dig death.ocf.berkeley.edu but that’s an awful lot to type. By specifying domain ocf.berkeley.edu in /etc/resolv.conf the query can be shortened to just dig death. In fact, any tool that takes a domain name can now use this shortened version, i.e. ping death. This is because your machine’s resolver is responsible for translating this domain name, and the domain configuration automatically appends the written domain to these short queries.

  • search The format for this option is search <search-list>. Using this options specifies a list of domain names to iterate through when attempting to look up queries.

    Let’s examine an example use case, imagine we owned two networks ocf.berkeley.edu and xcf.berkeley.edu and wanted to query a machine which may either be in either network. To enable this we can simply add the line search ocf.berkeley.edu xcf.berkeley.edu. Queries to resolve a domain name will now append those listed domains in order until a successful DNS response. If we assume death is on ocf.berkeley.edu and another machine, life, is on xcf.berkeley.edu, both dig death and dig life are now resolved properly thanks to our configuration.

One thing to note is that search and domain are mutually exclusive keywords and having both defined causes the last instance to take precedence and override earlier entries.

  • nameserver The nameserver keyword is fairly self explanatory and follows the format of nameserver <ip-address> where <ip-address> is the IP address of the intended name server. One can have up to MAXNS (default 3) nameserver entries in this file. The resolver will query nameservers in the same order as they are written in the file.

Following are additional useful configurable options in this file. Options are defined in this format options <option1> [additional-options]. Some example options follow below:

  • ndots This option, formatted as ndots:n, configures the threshold,n, at which an initial absolute query is made. Since the default value for this option is 1, any name with at least 1 dot will first be queried as an absolute name before appending domains from search. When less than ndots are present, the queries automatically begin appending elements in <search-list>.

    Take death.ocf.berkeley.edu as an example, and let’s assume we have the following line search ocf.berkeley.edu in our configuration. Running ping death works because there are 0 dots in death and the query automatically appends search elements so that our query becomes death.ocf.berkeley.edu. If we instead ran ping death. the resolver will first issue a query for death. since it has 1 dot, which fails.

  • timeout This opton is in the format timeout:n and configures the amount of time n, in seconds, that a resolver will wait for a response from a name server before retrying the query via another name server.

  • attempts This option is in the format attempts:n and configures the number of attempts n that the resolver will make to the entire list of name servers in this file.

/etc/nsswitch.conf

With multiple sources of information for resolving hostnames, one can’t help but wonder how the system decides which sources to query and in what order. This is answered with the /etc/nsswitch.conf file. It is this file’s responsibility to list sources of information and configure prioritization between sources. Similar information sources can be grouped into categories that are referred to as ‘databases’ within the context of the file. The format of the file is as follows: database [sources]. While this file provides configuration for a wide array of name-service databases, we will focus on an example relevant to the topic at hand.

The hosts database configures the behavior of system name resolution. So far we have introduced two ways to resolve names:

  1. Using entries in /etc/hosts
  2. Using a resolver to issue DNS queries to DNS name servers

To let the system know about the above two sources of information there are corresponding keywords, files and dns, respectively.

We can then configure name resolution by writing the line hosts: files dns The example syntax above tells the system to first prioritize files before issuing DNS queries. Naturally, this can be customized to best fit your use case.

DHCP client configuration

The Internet Systems Consortium DHCP client, known as dhclient, ships with Debian and can be configured via /etc/dhcp/dhclient.conf. Lines in this file are terminated with a semicolon unless contained within brackets, like in the C programming language. Some potentially interesting parameters to configure include:

Timing

  • timeout This format for this statement is timeout <time> and defines time to the maximum amount of time, in seconds, that a client will wait for a response from a DHCP server.

    Once a timeout has occured the client will look for static leases defined in the configuration file, or unexpired leases in /var/lib/dhclient/dhclient.leases. The client will loop through these leases and if it finds one that appears to be valid, it will use that lease’s address. If there are no valid static leases or unexpired leases in the lease database, the client will restart the protocol after the defined retry interval.

  • retry The format for this statement is retry <time> and configures the amount of time, in seconds, that a client must wait after a timeout before attempting to contact a DHCP server again.

A client with multiple network interfaces may require different behaviour depending on the interface being configured. Timing parameters and certain declarations can be enclosed in an interface declaration, and those parameters will then be used only for the interface that matches the specified name.

The syntax for an example interface snippet is:

interface <iface-name> {
    send host-name "death.ocf.berkeley.edu";
    request subnet-mask, broadcast-address, time-offset, routers,
       domain-search, domain-name, domain-name-servers, host-name;
    [additional-declarations];
}

As mentioned above this file also supports defining static leases via a lease declaration. Defining such leases may be useful as a fallback in the event that a DHCP server cannot be contacted.

The syntax for a example static lease is:

lease {
#  interface "eth0";
#  fixed-address 192.33.137.200;
#  option host-name "death.ocf.berkeley.edu";
#  option subnet-mask 255.255.255.0;
#  option broadcast-address 192.33.137.255;
#  option routers 192.33.137.250;
#  option domain-name-servers 127.0.0.1;
#  renew 2 2000/1/12 00:00:01;
#  rebind 2 2000/1/12 00:00:01;
#  expire 2 2000/1/12 00:00:01;
#}

While the function of most keywords in the above snippet can be inferred from their syntax, more information can be found by simply reading the man page for this file (man dhclient.conf).

Sysadmin commands

ifupdown

ifupdowm is a simple suite of commands for interacting with network interfaces. The two commands you’ll be using most are ifup and ifdown which are relatively self-explanatory. ifup brings and interface up and vice versa for ifdown. These two commands should be your de facto commands for bringing interfaces up or down since using these commands loads configurations defined in /etc/network/interfaces.

mtr

mtr is a command that combines the functionality of traceroute with that of ping. Take a look at this article for a good primer for using mtr and interpreting its output.

iptables

In favor of not reinventing the wheel please check out these excellent and pretty short articles by DigitalOcean, who sponsored this semester’s offering of the decal by supplying us with VMs.

  1. An Introduction to iptables
  2. Adding rules
  3. Deleting rules
  4. Common rules and tips

Checkpoint

Question 3a: If we preferred name resolution be done dynamically rather than using static entries in /etc/hosts what file do we need to edit and what is the line we should add?

Question 3b: Assume the following information:

  • /etc/resolv.conf file has 3 nameserver entries and a options timeout:1 entry.
  • A successful DNS response takes 20 ms.

    You need to add the attempts:n option so that you retry a query as many times as possible but the total time to resolve a name, irrelevant of success or failure, takes less than 5 seconds. What should the value of n be?

Exercises

Now, let’s break things do some experimentation! Remember to submit your answers to Gradescope when you’re done. (Also, don’t forget to submit the checkpoint questions from the sections above!)

The files for these exercises can be found in the decal-labs repository. Clone it now: git clone https://github.com/0xcf/decal-labs

🔥 This is fine 🔥

This section will have you thinking like a sysadmin.

IMPORTANT NOTE

Do not run the scripts directly in your student VM! These scripts are dangerous and will brick your VM so please follow the provided setup instructions. However, if you have physical access (or out-of-band management access) to a Linux machine, feel free to run the scripts directly and reboot when necessary, as all changes made are temporary.

Each script might make changes to your network stack with the intent of damaging your machine’s connectivity. To confine the scope of the ‘attacks’, scripts will specifically try to alter your connectivity to google.com and ocf.berkeley.edu.

Setup

  1. If you haven’t already, ssh into your student VM (username@username.decal.xcf.sh) and clone decal-labs.
  2. Go into the vm directory: cd decal-labs/a6/vm
  3. Get Virtualbox: sudo apt install virtualbox
  4. Get Vagrant: curl -O https://releases.hashicorp.com/vagrant/2.2.18/vagrant_2.2.18_x86_64.deb then sudo apt install ./vagrant_2.2.18_x86_64.deb
  5. Get Ansible: sudo apt install ansible
  6. Start a Vagrant instance: vagrant up
  7. Enter your Vagrant instance: ssh vagrant@192.168.42.42. The default password is vagrant.
  8. The decal-labs repo should be available in the Vagrant instance. If it isn’t there, you can sudo apt install git then clone it again.
  9. cd decal-labs/a6/scenario.

Problem Instructions

There should be 6 scripts, named 1.py to 6.py. Your task is to choose at least 3 of these to run and attempt to fix the problem that they cause (if any).

Launch each script with sudo, i.e. sudo python3 <script.py>.

For each script, follow this two step process. Only move onto another script once you have finished resolving your current one.

  1. Analyze whether or not your connectivity has been damaged. If your stack has been damaged identify the issue or which part of your network is no longer functioning as intended.

  2. If you concluded there was a problem, resolve the issue. What commands did you use and how did you conclude things were fully functional again?

    Additionally, for each step you must explain the tools you used and how you came to your conclusions i.e.

    I ran example --pls --fix computer and I noticed that line 3: computer-is-broken meant my machine was f*****.

    This script damaged my ability to connect to google.com by poisoning my arp cache with bogus entries.

Debugging Bank

I can’t ssh into my Vagrant instance!

  • You might need to run vagrant provision and then re-run vagrant up.
  • Also, make sure you’re running ssh 192.168.42.42 and not vagrant ssh.

I accidentally bricked something, how do I reset my Vagrant instance?

  • Run vagrant destroy and then vagrant up in the vm folder.

I’ve tried running vagrant provision a bunch of times and it never seems to work :(

I accidentally ran the scripts in my student VM and not in the Vagrant instance and now I can’t log in. What do I do?

  • You’ll need to ask us to reset your VM. Contact us in #decal-general or over email to arrange this.

Net Ninjas (Optional)

Run this in your Vagrant instance. The file should be found in decal-labs/a6/.

  1. The ninja has spent a few years training in a dojo and has mastered fireball (火球) jutsu. He can use his new skills to tamper with your network stack, incinerating your attempts to catch him. Run sudo python3 advanced_ninja_port.py. Fix the damage he has done and then successfully send him a found you message!