01. [30p] Primer / Reminder

Pro tip #1: since you'll be using man a lot in this exercise, add this to your .bashrc or .zshrc:

# color schemes for man pages
man() {
    LESS_TERMCAP_mb=$'\e[1;34m'   \
    LESS_TERMCAP_md=$'\e[1;32m'   \
    LESS_TERMCAP_so=$'\e[1;33m'   \
    LESS_TERMCAP_us=$'\e[1;4;31m' \
    LESS_TERMCAP_me=$'\e[0m'      \
    LESS_TERMCAP_se=$'\e[0m'      \
    LESS_TERMCAP_ue=$'\e[0m'      \
    command man "$@"

Source the file and test that it works.

[10p] Task A - tcpdump

tcpdump is a network traffic monitoring tool. At its core, it uses libpcap which in turn uses a technology called Extended Berkley Packet Filter (eBPF).

BPF was first proposed around 1995 when filtering mechanisms (and firewalls) were still a novel concept and were based on interpreters. BPF (now referred to as Classic BPF - cBPF) was the initial version of a Motorola inspired virtual ISA (i.e.: had no hardware implementation – think CHIP-8). eBPF is basically still BPF but more compatible with 64-bit architectures so that Just In Time (JIT) translators have an easier time running the code.

At first, the whole idea was to compile packet filtering programs and attach them to sockets in kernelspace. These programs would filter out packets that userspace processes would not be interested in. Consequently, this would reduce the quantity of data copied over the kernelspace/userspace boundary, only to ultimately be discarded.

Today, eBPF is used heavily for system profiling by companies such as Netflix and Facebook. Linux has had a kernel VM capable of running and statically analyzing eBPF code since around 2006. tcpdump is one of the few examples that still use it for its original purpose. Ask your assistant if you want to know more about eBPF tracing (not part of the lab, don't panic!)

The Task

Use tcpdump to output outgoing NTP queries and incoming http(s) responses. Use the -d flag to see an objdump of the filter program's code.

Complete the tcpdump command in order to satisfy the following formatting requirements:

  • print the packet number
  • print the elapsed time (in nanoseconds) since the first packet was captured
  • print the content of each packet (without l2 header) in hex and ASCII
  • do not resolve IP addresses to names

How to test:

$ ntpdate -q ro.pool.ntp.org
$ curl ocw.cs.pub.ro

tpcdump can list the available interfaces if run with -D. In addition to your network interfaces, you may also see a Bluetooth device or the dbus-system (depending on your desktop).

If you don't specify the interface with -i, the first entry in the printed list will be used by default. This may not always be your active network interface but in stead, your docker bridge (for example).

[20p] Task B - iptables

iptables is a configuration tool for the kernel packet filter.

The system as a whole provides many functionalities that are grouped by tables: filter, nat, mangle, raw, security. If you want to alter a packet header, you place a rule in the mangle table. If you want to mask the private IP address of an internal host with the external IP address of the default gateway, you place a rule in the nat table. Depending on the table you choose, you will gain or lose access to some chains. If not specified, the default is the filter table.

Chains are basically lists of rules. The five built-in chains are PREROUTING, FORWARD, POSTROUTING, INPUT, OUTPUT. Each of these corresponds to certain locations in the network stack where packets trigger Netfilter hooks (here is the PREROUTING kernel hook as an example – not that hard to add one, right?) For a selected chain, the order in which the rules are evaluated is determined primarily by the priority of their tables and secondarily by the user's discretionary arrangement (i.e.: order in which rules are inserted).

Figure 1: Netfilter hooks; each has a subset of associated tables. Tables categorize the actions (i.e.: targets) taken when a match occurs. E.g: NAT cannot be performed on the FORWARD chain. When multiple rules exist on the same chain, their processing order is primarily determined by the priority of the table they are defined in.

A rule consists of two entities: a sequence of match criteria and a jump target.

The jump target represents an action to be taken. You are most likely familiar with the built-in actions such as ACCEPT or DROP. These actions decide the ultimate fate of the packet and are final (i.e.: rule iteration stops when these are invoked). However, there are also extended actions (see man iptables-extensions(8)) that are not terminal verdicts and can be used for various tasks such as auditing, forced checksum recalculation or removal of Explicit Congestion Notification (ECN) bits.

The match criteria of every rule are checked to determine if the jump target is applied. The way this is designed is very elegant: every type of feature (e.g.: l3 IP address vs l4 port) that you can check has a match callback function defined in the kernel. If you want, you can write your own such function in a Linux Kernel Module (LKM) and thus extend the functionality of iptables (Writing Netfilter Modules with code example). However, you will need to implement a userspace shared library counterpart. When you start an iptables process, it searches in /usr/lib/xtables/ and automatically loads certain shared libraries (note: this path can be overwritten or extended using the XTABLES_LIBDIR environment variable). Each library there must do three things:

  • define iptables flags for the new criteria that you want to include.
  • define help messages for when iptables --help is called (its help message is an amalgamation of each library's help snippet).
  • provide an initialization function for the structure containing the rule parameters; this structure will end up in the kernel's rule chain.

So when you want to test the efficiency of the iptables rule evaluation process, keep in mind that each rule may imply the invocation of multiple callbacks such as this.

The Task (1)

Write an iptables rule according to the following specifications:

  • chain: OUTPUT
  • match rule: TCP packets originating from ephemeral ports bound to a socket created by root
  • target: enable kernel logging of matched packets with the “EP: ” prefix

How to test:

$ sudo curl www.google.com
$ sudo dmesg

multiport, owner modules

$ man 8 iptables-extensions

The Task (2)

Write an iptables rule according to the following specifications:

  • chain: OUTPUT
  • match rule: BPF program that filters UDP traffic to port 53 (try bash command substitution)
  • target: set TTL to 1 (initially)

Continue appending the same rule with incremented TTL value until the DNS request goes through.

How to test:

$ dig +short fep.grid.pub.ro @

bpf module

$ man 8 iptables-extensions nfbpf_compile

If you are working on Ubuntu, there is a chance that nfbpf_compile did not come with the iptables package (oh Canonical… maybe there's something in the Universe repos?).
Anyway, you can still install it manually:

$ sudo apt install libpcap-dev
$ wget https://raw.githubusercontent.com/netgroup-polito/iptables/master/utils/nfbpf_compile.c
$ gcc -o nfbpf_compile nfbpf_compile.c -lpcap

Also, use this man page rather than installing it separately.

The Task (3)

Give an example when iptables is unable to catch a packet.

ep/labs/04/contents/tasks/ex1.txt · Last modified: 2022/10/29 14:31 by vlad.stefanescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0