In the lab 3, you will learn about kernel module programming and linux kernel network stacks. We strongly suggest you to read Chapter 2~5, 7 (about work queue) and 17 (about socket buffer) from Linux Device Drivers book and Linux netfilter Hacking HOWTO before you start this lab. (Note: the linked netfilter document is outdated and NF_IP_XXX must be replaced by NF_INET_XXX)
Your task is to write a kernel module that 1) allows you to open / block TCP connections (similar to IP table), 2) captures packets of your interest and delivers them to userspace (similar to pcap), and 3) performs deep packet inspection (DPI) on packets of your interest. There are many ways to hijack packets from linux kernel stack, and we will use netfilter for our purpose. Then, through character device interface and system calls such as open / close / read / ioctl, you will control the ip table and communicate with kernel space.
You can load the module at the command line as follows:
# insmod ./sniffer_mod.koSimilarly you can unload the module as follows:
# rmmod sniffer_modThen, you can control the kernel module invoking sniffer_control:
# ./sniffer_control [mode] [src_ip] [src_port] [dst_ip] [dst_port] [action]and read captured packets from kernel space by invoking sniffer_read:
# ./sniffer_read [-i input file] [-o output file]For example, to enable access to port 4000 on your local machine while capturing packets destined to the port, run
# ./sniffer_control --mode enable --dst_ip localhost --dst_port 4000 --action captureThen, you can display captured packets to your terminal screen as follows:
# ./sniffer_read 192.168.1.1:5000 -> 192.168.3.1:5000 ......
Start by downloading the skeletal code from CMS (sniffer.tar.gz), then copy it (using scp/rsync) to your home directory on one of your Fractus Cloud instances (recall that
prompt> denotes your own machine, while
# denotes the Fractus Cloud instance). Use the same image you created during Lab 0b. You should be able to get the files from your local box to your instance and build like this:
prompt>scp -i ~/.euca/id-rsa-kp-kl568-test sniffer.tar.gz email@example.com.XXX:~/ prompt>ssh -i ~/.euca/id-rsa-kp-kl568-test firstname.lastname@example.org.XXX # tar -xzf sniffer.tar.gz # cd sniffer # make
makewill generate a kernel module binary file, namely
sniffer_mod.ko, as well as two userspace applications:
sniffer_read. You can load the compiled module like this:
# insmod ./sniffer_mod.koIf the module is successfully loaded, you can see the module from the loaded module list:
# lsmod | grep sniffer sniffer 12753 0Or
# dmesg | tail -n 1 [ XXX.XXXXXX] sniffer_init
dmesgprints the kernel debug buffer on the screen. What you print in kernel space using printk will be shown with
dmesg. The combination of
printkis the easiest (but not the most efficient) way to debug the kernel module (LDD Chapter 4). The provided kernel module by default creates a character device for you. You need to find out what the major number of the character device is (LDD Chapter 3).
# cat /proc/devices | grep sniffer 251 snifferThen, you need to create a device file to read from the character device interface.
# sudo mknod sniffer.dev c 251 0Now, you can read from the kernel module through the device file, for example,
# ./sniffer_read -i sniffer.devAbove command will show nothing, however, because the kernel module and
sniffer_readare not finished yet.
sniffer_readmust behave as follows:
sniffer_control. Each member of four tuples can be "any", meaning any IP or port number is acceptable. Duplicated flows with different commands/actions will be overwritten, and handling conflicting rules is up to your implementation. For example, you can simply pick the oldest rule. You should mainly modify
readover the character device interface.
readwill be blocked when there is no packet in the buffer (use
sniffer_readdumps packets following a format specified in
sniffer_read.cto a file or
stdout. Be careful of race condition while handling
read, i.e. packets can be inserted into the buffer while
sniffer_readis reading from the buffer. Also make sure at most one process can read from the dev file anytime (Use atomic counter).
Please finish Filtering part by Oct. 10th and check with one of TAs during the lab session.
# cat /proc/sniffer # [command] [src_ip] [src_port] [dst_ip] [dst_port] [action] 1 enable any any 127.0.0.1 4000 None 2 enable 18.104.22.168 80 any any DPI ...
fireless.cs.cornell.edu:80, then run
# ./sniffer_control --mode enable --dst_ip localhost --dst_port 4000 # ./sniffer_control --mode enable --src_ip fireless.cs.cornell.edu --src_port 80 # cd <directory to your proxy> # ./tcp-proxy fireless.cs.cornell.edu 80 4000The proxy should run without any problems.
sniffer.tar.gzfile on CMS.
If you have any problems about submission, please contact the TAs.
dmesg) to identify what caused the crash. Then, reboot your instance with