Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ep:labs:061:contents:tasks:ex4 [2026/03/23 21:39]
radu.mantu removed
ep:labs:061:contents:tasks:ex4 [2026/04/07 12:47] (current)
radu.mantu
Line 1: Line 1:
-==== 04. [10pBonus - Protocol Options ​==== +==== 04. [30pImpact analysis of iptables rules ====
-<​spoiler>​+
  
-As you've probably already seen in the previous exercise, TCP uses protocol extensions (called options) in order to negotiate session parameters and improve overall performance. Note that this mechanism has existed since the very inception of the protocol approx. 30 years ago ([[https://datatracker.ietf.org/doc/html/rfc793#​section-3.1|RFC793 - Transmission Control Protocol]]), with many being added post-factum.+In [[https://ocw.cs.pub.ro/courses/ep/labs/05Lab 05]] you used bpftrace exclusively via one-liners (''​-e''​ flag). That works fine for quick investigationsbut as your probes get more complex (multiple hooks, conditionals,​ helper functions) you'll want to write proper **script files** (''​.bt''​ extension).
  
-While the same could be said for IP options ([[https://​datatracker.ietf.org/​doc/​html/​rfc791#​section-3.1|RFC791 - Internet Protocol]])there have always been... issues. In 2005 it was decided that [[https://​www2.eecs.berkeley.edu/​Pubs/​TechRpts/​2005/​EECS-2005-24.pdf| IP Options are not an option]]. Middleboxes (i.e.: network equipment in the Internet -- routersNATsfirewalls, etc.) would sometimes implement abridged versions of the protocol specifications. For IP options, this meant that the IHL field would be ignored ​and the header would always ​be considered to be 20 bytes in lengthAs a result, if a packet carried IP options, cheap network equipment would wrongly assume ​that the layer 4 header would start at a 20 byte offset and drop it due to erroneously perceived malformations.+The difference is minimal syntacticallybut it is quite important in practicea script file can have comments, be version-controlledbe shared with teammates, and be run with ''​sudo bpftrace script.bt''​ without the shell escaping headaches ​that come with one-liners.
  
-The authors of the 2005 report discovered that only a fraction (15%) of edge Autonomous Systems (AS -- huge, ISP-grade networks with a unified routing policy) were responsible for most packet drops. This made them optimistic towards a speedy resolution of this issue, but things haven't changed much in the past 15 or so years. Today IP options usually work just fine in local networks. As for the wider Internet, there are specific paths and networks where IP options can pass unthwarted, but only if the layer 4 protocol is ICMP. The logic may be that most IP options are used for path measurement anyway, so why use it in conjunction with anything other than ICMP (a pretty dumb argument, I admit... but it's not mine).+In this task you'll write two scripts targeting functions you observed ​in your **pwru** trace from Exercise 03.
  
-Luckily, one of these compliant networks is RoEduNetIf you're not working from the university'​s network, then start a VM instance on [[https://cloud-controller.grid.pub.ro/dashboard/auth/​login/?​next=/​dashboard/​|OpenStack]]. ISPs like RDS tend to drop IP Options. As a target, we will use [[https://​www.digitalocean.com/​|DigitalOcean]]. Based on some personal tests, I can guarantee that they don't drop any options, regardless of region.+<note important>​ 
 +**Before starting:** make sure you have a clean ''​iptables''​ stateRemove any DROP rules you added in the previous exercise: 
 +<code bash> 
 +$ sudo iptables -D OUTPUT -p udp -d 8.8.8.8 --dport 53 -j DROP 
 +</code> 
 +</note>
  
-{{ :ep:labs:​04:​contents:​tasks:​ip_recordroute.png?​700 |}} +=== [0p] Task ADemocoding style for bpftrace scripts ===
-<​html>​ +
-<​center>​ +
-<​b>​Figure 2:</​b>​ Layout of a layer 3 (IP) header with options. Their presence is confirmed by an Internet Header Length (IHL) value strictly larger than 5. Most options are Type-Length-Value (TLV) encoded. When the length is constant or there is no information to be included (e.g.: No Operation, End of Options List), deviations from this format can be accepted ​for the purpose of saving space. +
-</​center>​ +
-</​html>​+
  
-**Overarching Goal**+Before writing your own scripts, study this example. It is not a task — there is nothing to submit. It exists to show what a well-structured ''​.bt''​ script looks like, so you have a reference when writing the next two. 
  
-The first task is to modify outgoing traffic and include a Record Route option in an ICMP Echo Request. Check its description in [[https://datatracker.ietf.org/doc/html/rfc791|RFC791]] to understand what it does (and no, not "​Loose/​Strict Source and Record Route"​... keep hitting that Find key). The packet structure will resemble that in the picture above. Don't worry; for this step, we'll give you a little help ;)+You can also find out more about the bpftrace coding style [[https://bpftrace.org/docs/release_025/language|here]]
  
-Your second task will be to write a bash script that extracts the IP addresses from the ICMP Echo Response'​s Record Route option from a packet capture and perform an AS Lookup. In other words, you will determine the names of all the networks that the packet traverses on its way from the university to DigialOcean and back.+<​code ​bash nf_demo.bt> 
 +#​!/​usr/​bin/​bpftrace
  
-But let's take it step-by-step.+BEGIN 
 +
 +    printf("​Tracing nf_hook_slow... Ctrl+C to stop.\n\n"​);​ 
 +}
  
-**Task A Injecting IP Options**+/fentry fires at the entry of the kernel function. 
 + Faster and lower-overhead than kprobe. 
 + '​comm'​ is a bpftrace built-in: the name of the current process. 
 + *
 +fentry:​nf_hook_slow 
 +
 +    @invocations_by_process[comm]++;​ 
 +}
  
-Remember talking about **iptables** extensions earlier? **Netfilter Queue** is one of them and will be relevant for this task. What it is, is an **iptables** target. What it doesit redirects each matched packet to a userspace process for evaluation and optionally//​modification//​.+/Print and reset every 3 seconds ​*
 +interval:​s:​3 
 +
 +    printf("​-- %s --\n"strftime("​%H:​%M:​%S"​nsecs)); 
 +    print(@invocations_by_process);​ 
 +    printf("​\n"​);​ 
 +    clear(@invocations_by_process);​ 
 +}
  
-The userspace process receives each packet by polling a [[https://​www.man7.org/​linux/​man-pages/​man7/​netlink.7.html|Netlink Socket]]. After obtaining one, it can perform any type of analysis that it wants (e.g.: [[https://​dl.acm.org/​doi/​pdf/​10.1145/​1151659.1159952|deep packet inspection]]in order to reach a verdict. The verdict can be the already known built-ins (i.e.: //ACCEPT, DROP,// etc.) or it can redirect the packet to another queue, with another process listening. When setting the verdict, a modified packet can be provided to replace the original on its datapath through the kernel'​s network stack.+END 
 +
 +    printf("Done.\n")
 +}
  
-Enter [[https://​github.com/​RaduMantu/​ops-inject|ops-inject]]. This is a tool (that'​s still under development,​ mind you) that allows the annotation of matched packets with IP/TCP/UDP options. Why is this tool simple to use: all you have to do is provide a sequence of bytes representing the [[https://​www.iana.org/​assignments/​ip-parameters/​ip-parameters.xhtml|codepoints]] of the options that you want to append. This byte stream is passed to an internal decoder that //expands// each byte into a fully-fledged option, albeit in accordance to an arbitrary implementation. Once you clone the repo, you should look over two sources in particular: 
-  * ''​src/​main.cpp''​ : here, just understand what **libnetfilterqueue** library calls are made in order to set up the Unix socket, to receive the packet and to set its verdict. 
-  * ''​src/​ops_ip.c''​ : this is where all available IP Options are implemented;​ take a look at the **ip_decoders** vtable at the bottom to associate options and codepoints. 
- 
-First of all, let's fetch the tool and compile it. 
-<code bash> 
-$ git clone https://​github.com/​RaduMantu/​ops-inject.git 
-$ cd !$:t:r 
-$ make -j $(nproc) 
 </​code>​ </​code>​
 +Run it for a few seconds while generating some traffic and observe the output. Then read through the script again. This is the style expected in Task B.
  
-<note tip> +=== [30pTask BThe cost of a bloated rule chain ===
-//Pro tip #3//: [[https://​www.gnu.org/​software/​bash/​manual/​html_node/​Modifiers.html|Bash Modifiers]] and [[https://​www.gnu.org/​software/​bash/​manual/​html_node/​Word-Designators.html|Word Designators]] +
-  * ''​!$''​ is substituted with the final argument ​of previously executed command +
-  * '':​t''​ removes the leading pathname components, leaving //​ops-inject.git//​ +
-  * '':​r''​ removes exactly one trailing suffix, leaving //​ops-inject//​+
  
-----+''​nf_hook_slow()'',​ which is visible in your **pwru** trace from Task 03, is the function that walks the **iptables** rule chain for every packet. Its cost is not fixed: it scales with the number of rules in the chain, and within each rule, with the number of match flags specified. A match rule such as ''​-p tcp -d 8.8.8.8 ​--dport 443''​ invokes three separate match callbacks in sequence; if any returns false, evaluation stops for that rule and moves on to the next one. On a long chain, this adds up.
  
 +A common real-world mistake: a sysadmin responds to unwanted traffic by adding one DROP rule per offending source IP, one at a time, instead of a single rule covering the entire prefix. After hours or days of this, the chain has thousands of rules. Every packet, regardless of its actual destination,​ must walk the entire chain before reaching the default policy. On a modest server, this is enough to cause visible throughput degradation.
  
-Troubleshooting:​ +You are going to reproduce ​this and measure it.
-  * **IPPROTO_ETHERNET error** : if your //​netinet/​in.h//​ is missing ​this definition, you can delete line 36 from //​src/​str_proto.c//​. +
-  * **libnetfilter-queue missing** : consider installing //​libnetfilter-queue-dev// ​and //​libnetfilter-queue1//​. +
-</​note>​+
  
-Next, let's insert an **iptables** rule that matches all outgoing ICMP packets. +== What you need ==
-Take note of ''​%%--%%queue-num 0''​ for when we'​ll ​need to tell the userspace process which Netfilter Queue to subscribe. Also, ''​%%--%%queue-bypass''​ tells the **iptables** module to disable enqueuing packets if there'​s no process listening. Otherwise, the queue'​s buffer will fill up and overflowing packets will be dropped by default until some space is created.+
  
-<code bash> +  * **iperf3:** Tool for performing network throughput measurements. It's both a server and a client. 
-$ sudo iptables ​-I OUTPUT -p icmp -j NFQUEUE --queue-num 0 --queue-bypass +  * **bpftrace:​** High-level eBPF scripting tool for kernel profiling. 
-</​code>​+  * **python3:​** With ''​matplotlib''​ and optionally ''​pandas''​ for plotting.
  
-Finally, run **ops-inject** while telling it to append the Record Route option (0x07). Because the tool takes a file as input, and because we give it the PseudoTerminal Slave of a [[https://​www.gnu.org/​software/​bash/​manual/​html_node/​Command-Grouping.html|subshell]],​ things can get messy if we simply run it with **sudo**. As result, it's easier to just switch to **root**. To get a feel of what the other options do, just run ''​ops-inject %%--%%help''​ once.+== Sub-task 01Setting up local iperf3 server ==
  
-<​code>​ +Running a local server eliminates network variability from the experiment, the iptables overhead signal becomes much cleaner and easier to observe in the plot. Pick one of the two options below depending on your setup.
-$ sudo su +
-./​bin/​ops-inject -p ip -q 0 -w <(printf '​\x07'​) +
-</​code>​+
  
-Having completed ​the setuplet's generate some traffic!+**Option 1: Docker container with Arch Linux** 
 + 
 +If you have Docker installed, you can spin up an Arch Linux container. This container will use the same TCP/IP stack as the hostbut will have distinct network devices, routing tables, firewall rules, etc. Any packet that leaves the container will have to pass through the network stack twice.
  
 <code bash> <code bash>
-ping -c 3 $(dig +short digitalocean.com | head -n 1) +# start the container 
-    PING 104.16.182.15 (104.16.182.15) 56(84) bytes of data. +hostdocker run -ti --rm archlinux
-    64 bytes from 104.16.182.15:​ icmp_seq=1 ttl=57 time=46.7 ms +
-    RR:     ​141.85.13.15 +
-            37.128.225.226 +
-            37.128.232.178 +
-            37.128.232.177 +
-            80.97.248.33 +
-            162.158.16.1 +
-            104.16.182.15 +
-            104.16.182.15 +
-            162.158.16.1+
  
-    64 bytes from 104.16.182.15:​ icmp_seq=2 ttl=57 time=14.2 ms     (same route) +# show IP address of container and run iperf3 
-    64 bytes from 104.16.182.15:​ icmp_seq=3 ttl=57 time=18.2 ms     (same route)+arch$ pacman -Sy --noconfirm iperf3 iproute2 
 +arch$ ip -c a s 
 +arch$ iperf -s 
 + 
 +# test if it works (should have >40Gbps throughput) 
 +host$ iperf3 -c ${container_ip} -p 5201 -t 5
 </​code>​ </​code>​
  
-Normally, we would need **wireshark** or **tcpdump** to see the result but fortunately,​ **ping** is able to understand the Record Route option. The reason for this is that it can generate it itself (see ''​-R''​ option). Should it have wondered that it received a Record Route option in response to a normal ICMP Echo Request? Apparently not...+**Option 2: network namespace (no Docker required)**
  
-<note important>​ +This creates an isolated network environment using Linux network namespaces and a virtual Ethernet pair (veth)exactly like Docker does internally. See [[https://ocw.cs.pub.ro/courses/rl/​labs/​10|RL Lab 10]] for a deeper dive into how this works.
-If your ISP is blocking IP optionstry **ping**-ing your //default gateway//.+
  
-Normally, that should work, but there is really no guaranteeA TP-Link router usually runs Linux 2.6 (at least) and does its job well. A Tenda router, however, most likely runs some garbage proprietary firmware and won't even reply to an ICMP Echo Request with IP options. +<code bash> 
-</​note>​+# 1Create the namespace 
 +$ sudo ip netns add iperf3-ns
  
-From this point onward, it's all you! :)+# 2. Create a veth pairone end stays on the host, one goes into the namespace 
 +$ sudo ip link add veth-host type veth peer name veth-ns
  
-**Task B Traffic capture**+# 3. Move one end into the namespace 
 +$ sudo ip link set veth-ns netns iperf3-ns
  
-Run the same experiment with ICMP Echo Request again, but this time capture the traffic using **tcpdump** and write it to a //pcap capture file//.+# 4. Configure ​the host-side interface 
 +$ sudo ip addr add 10.99.0.1/24 dev veth-host 
 +$ sudo ip link set veth-host up
  
-<note tip> +# 5. Configure ​the namespace-side interface 
-Consider using the ''​-U''​ option in **tcpdump** to avoid buffering packets if you plan to suddenly stop it with //Ctrl^C//. +$ sudo ip netns exec iperf3-ns ip addr add 10.99.0.2/24 dev veth-ns 
-</note>+$ sudo ip netns exec iperf3-ns ip link set veth-ns up 
 +$ sudo ip netns exec iperf3-ns ip link set lo up
  
-<note important>​ +# 6. Start iperf3 server inside the namespace (background) 
-If you had reachability problems at task A and IP options just can't get through, use {{:​ep:​labs:​04:​contents:​tasks:​ip-ops.zip|this pcap}} starting with Task C. It contains pretty much what you were supposed to get. +$ sudo ip netns exec iperf3-ns iperf3 -s -D
  
-As for Task B, show us that you can capture traffic correctly by targeting ​the //default gateway// again+# 7. Test from the host (server is at 10.99.0.2) 
-</note>+$ iperf3 -c 10.99.0.2 -p 5201 -t 5 
 +</code>
  
-<​solution -hidden>+Traffic from the host to ''​10.99.0.2''​ is routed through the kernel'​s normal IP output path and hits the OUTPUT chain where ''​nf_hook_slow''​ is instrumented correctly. 
 + 
 +When done with the experiment:
 <code bash> <code bash>
-$ sudo tcpdump ​-Uw ip-ops.pcap 'icmp and host 104.16.181.15'​+$ sudo ip netns delete iperf3-ns 
 +$ sudo ip link delete veth-host
 </​code>​ </​code>​
-</​solution>​ 
  
-**Task C Route extraction**+== Sub-task 02: The bpftrace script ==
  
-Use **tshark** to extract the Record Route payload of ICMP Echo Replies from the created ​//pcap//. \\ +Write a //bpftrace script// of your own that calculates ​the average time each packet spent being evaluated ​in ''​nf_hook_slow()''​.
-You only need the IPs of the intermediary hops; these will be further processed ​in your script at Task D.+
  
 <note tip> <note tip>
-  * Check out the ''​-Y'' ​option in ''​man tshark(1)''​+We reccomend using ''​kprobe''​/''​kretprobe''​ instead of ''​fentry''/​''​fexit''​ for portability,​ since kprobes work on kernels without full BTF support, which some VMs lackThe instrumentation overhead is slightly higher, but overall negligible.
-  * Look for the appropriate [[https://www.wireshark.org/​docs/​dfref/​i/​ip.html|IPv4 Display Filter]]. +
-  * Test filter expressions in **wireshark** before applying them in **tshark**.+
 </​note>​ </​note>​
  
-<​solution ​-hidden>+== Sub-task 03: Acquiring the data == 
 + 
 +Run a 5-10s **iperf3** throughput test between your host and the container. Meanwhile, use the script that you've written to measure the latency introduced by the OUTPUT Netfilter chain hook. 
 + 
 +Having no rules configured on your OUTPUT chain, this will serve as a __baseline__. Next, redo this experiment by continuously adding 100 **iptables** rules that are __guaranteed__ to fail (i.e., verdict will never be obtained until all rules are evaluated). Repeat these steps until you end up with ~3,000 rules in your OUTPUT chain. Save all these results (number of rules, average throughput, average Netfilter-induced latency) since you will have to plot them. 
 + 
 +Try to script this, since manually re-running all of this is very tiresome! 
 + 
 +<note> 
 +Flush your OUTPUT chain after you are done with the experiment:
 <code bash> <code bash>
-tshark ​-r ip-ops.pcap -Tfields -e ip.rec_rt '​icmp.type == 0 && ip.rec_rt'​+sudo iptables ​-F OUTPUT
 </​code>​ </​code>​
-</solution>+</note>
  
-**Task D - AS lookup** 
  
-Write a //bash script// starting from your **tshark** command. The script must perform an AS lookup and display information about each registered hop (e.g.IP, AS name, etc.), for all packets in the //pcap//. Run the script. What do you notice?+== Sub-task 04Plotting ​the data ==
  
-<​html>​ +Write Python script that creates two plots in the same figure
-    <​details>​ +  * **iperf3** throughput as a function ​of **iptabes** rules. 
-        <​summary>​The output should look something like this ± few info.</​summary>​ +  * Average elapsed time in the Netfilter hook as a function ​of **iptables** rules.
-        <​center>​ +
-            <img src="​https://​ocw.cs.pub.ro/​courses/​_media/​ep/​labs/​04/​contents/​tasks/​ip-rr_sample.png">​ +
-            <​br>​ +
-            <​b>​Figure 3:</​b>​ Packet sent from <​i>​104.16.181.15</​i>​ to <​i>​172.19.7.205</​i>​. In green are enumerated middleboxes (e.g.: routers) that added the IP of their outgoing interface to the buffer of the RR optionNot all may do so, depending on the implementation ​of their networking stack! In blue we have part of the publicly available information regarding the Autonomous System that said IP addresses belong to. +
-        </​center>​ +
-    </​details>​ +
-</​html>​+
  
-<note tip> +== Sub-task 05: Interpreting the data == 
-In order to get the required information,​ use the **whois** tool.+ 
 +Answer the following:​ 
 +  * At what approximate rule count does the throughput begin to visibly degrade? 
 +  * Is the latency increase in ''​nf_hook_slow()''​ linear with rule count? What does this tell you about the algorithm used to walk the chain? 
 +  ​What do you expect would happen if you were to perform this test on a [[https://​iperf3serverlist.net/|public iperf3 server]] instead of locally hosted one? 
 + 
 +<​solution -hidden>​ 
 + 
 +//Terminal 1 — sustained iperf3 test (300 seconds, JSON output)://
 <code bash> <code bash>
-whois ${SOME_IP} +iperf3 ​-c <​server> ​-p <​port> ​-t 300 -J --logfile iperf_results.json
-$ whois -h whois.cymru.com ​-- -v ${SOME_IP}+
 </​code>​ </​code>​
  
-Want to make your script'​s output look pretty? Remember that you have [[https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html|ANSI color escape codes]] :) +//Terminal 2 — bpftrace measurement:// 
-</note>+<code bash> 
 +$ sudo bpftrace nf_measure.bt 2>/dev/null tee bpf_results.txt 
 +</code>
  
-<solution -hidden+//Terminal 3 — inject rules progressively (run only after the other two are running)://​ 
-<file bash analyze_rr.sh> +<code bash
-#!/bin/bash+$ for ((i = 0; i 5000; i++)); do 
 +      echo -ne "​\r$i"​ 
 +      sudo iptables -I OUTPUT -d 192.168.${i} -j ACCEPT 
 +  ​done 
 +</code>
  
-# analize_rr.sh - perform AS lookup on IP RR content +<code bash nf_measure.bt> 
-  $1 : [requiredpath to a pcap file+#!/​usr/​bin/​bpftrace 
 +kprobe:nf_hook_slow 
 +
 +    @start[tid= nsecs; 
 +}
  
 +kretprobe:​nf_hook_slow
 +/ @start[tid] /
 +{
 +    @sum += nsecs - @start[tid];​
 +    @count++;
 +    delete(@start[tid]);​
 +}
  
-###############################################################################​ +interval:​s:​10 
-##############################​ ANSI ESCAPE CODES ##############################​ +{ 
-###############################################################################​+    ​printf("​avg. elapsed: %lu | count: %lu\n",​ @sum / @count, @count); 
 +    @sum = 0; 
 +    @count = 0; 
 +
 +</​code>​
  
-ANSI_RED='​\033[31m'​ +<code python plot_results.py>​ 
-ANSI_GREEN='​\033[32m'​ +#​!/​usr/​bin/​env python3 
-ANSI_YELLOW='​\033[33m'​ +import json 
-ANSI_BLUE='​\033[34m'​ +import re 
-ANSI_PURPLE='​\033[35m'​ +import sys 
-ANSI_CYAN='​\033[36m'​ +import matplotlib.pyplot as plt 
-ANSI_BOLD='​\033[1m'​ +import matplotlib.ticker as ticker
-ANSI_UNBOLD='​\033[2m'​ +
-ANSI_CLEAR='​\033[0m'​+
  
-###############################################################################​ +IPERF_JSON ​ = "​iperf_results.json"​ 
-#################################​ ENTRY POINT #################################​ +BPF_LOG ​    = "​bpf_results.txt"​ 
-###############################################################################​+OUTPUT_PNG ​ = "​results.png"​
  
-argument check +parsing the json 
-if [[ $# -ne 1 || ! -$1 ]]; then +with open(IPERF_JSON) as f: 
-    ​echo '​Usage: ​./​analize_rr.sh PCAP_FILE'​ +    ​data = json.load(f)
-    exit 1 +
-fi+
  
-# parse ICMP Echo Replies in pcap while extracting relevant fields +intervals = data["​intervals"​] 
-while read -r SRC_IP DST_IP ROUTE; do +times_s ​      = [iv["​sum"​]["​start"​] ​          for iv in intervals] 
-    # print info about src and dst IP for current packet +throughput ​   ​= ​[iv["​sum"​]["​bits_per_second"​] / 1e6 for iv in intervals] ​ # Mbit/s 
-    ​printf '​%b%b%15s%b ​==> %b%b%-15s%b\n' ​                  \ +cwnd_kb ​      = [iv["​streams"​][0]["​snd_cwnd"​] / 1024 for iv in intervals] ​ # KB
-        ​${ANSI_YELLOW} ${ANSI_BOLD} ${SRC_IP} ${ANSI_CLEAR} \ +
-        ${ANSI_YELLOW} ${ANSI_BOLD} ${DST_IP} ${ANSI_CLEAR}+
  
-    ​parse each hop in recorded route +parsing bpftrace output 
-    while read -d , -r HOP_IP; do +format: "avg. elapsed: 1243 | count: 8821" 
-        ​print recorded hop IP +bpf_times ​  = [] 
-        ​printf '\t%b%bHop%b%s%b\n' ​  \ +bpf_latency = [] 
-            ${ANSI_GREEN} ${ANSI_BOLD} ​\ +pattern = re.compile(r"​avg\. elapsed:\s*(\d+)\s*\|\s*count:​\s*(\d+)"​)
-            ${ANSI_UNBOLD} ${HOP_IP} ${ANSI_CLEAR}+
  
-        # get organization info +with open(BPF_LOG) as f: 
-        NOTE: whois can access either RIPE or ARIN databases +    t = 5  ​first interval midpoint (10s intervals) 
-        # ​      ​account ​for different formats +    for line in f: 
-        ​printf '​\t\t%b%b%-14s:​ %b%s%b\n'​ \ +        ​m = pattern.search(line
-            ${ANSI_BLUE} ${ANSI_BOLD} ​   \ +        ​if m
-            'Net Name' ${ANSI_UNBOLD} ​   \ +            ​bpf_times.append(t) 
-            "$(whois ${HOP_IP} ​          \ +            ​bpf_latency.append(int(m.group(1))) 
-            | grep -i '​netname' ​         \ +            ​t +10
-            | tail -n 1                  \ +
-            | awk '​{$1="";​ print $0}' ​   \ +
-            | xargs)" ​                   \ +
-            ${ANSI_CLEAR} +
-        ​printf '​\t\t%b%b%-14s%b%s%b\n'​ \ +
-            ​${ANSI_BLUE} ${ANSI_BOLD} ​   \ +
-            'Org Name' ${ANSI_UNBOLD} ​   \ +
-            ​"$(whois ${HOP_IP} ​          \ +
-            | grep -i '​orgname' ​         \ +
-            | tail -n                  \ +
-            ​| awk '{$1="";​ print $0}' ​   \ +
-            | xargs)" ​                   \ +
-            ${ANSI_CLEAR}+
  
-        ​fetch AS info in one request & print +making the plot 
-        ​IFS='​|'​ read -r AS_NUM IP BGP_PREFIX COUNTRY REGISTRY DATE AS_NAME \ +fig, (ax1, ax3) = plt.subplots(2, ​1, figsize=(12,​ 7), sharex=True) 
-            < <(whois -h whois.cymru.com -- -v ${HOP_IP} ​                  \ +fig.suptitle("​iptables rule chain overhead — nf_hook_slow vs. throughput",​ fontsize=13)
-              | tail -n                                                  \ +
-              | sed 's/[ ]*|[ ]*/​|/​g'​)+
  
-        printf '​\t\t%b%b%-14s%b%s%b\n' ​             \ +# Top subplotthroughput + cwnd 
-            ​${ANSI_BLUE} ${ANSI_BOLD} 'AS Num' ​       \ +color_tp ​  = "​steelblue"​ 
-            ​${ANSI_UNBOLD} ${AS_NUM:​-'​NA'​} ${ANSI_CLEAR} +color_cwnd = "​darkorange"​
-        printf '​\t\t%b%b%-14s:​ %b%s%b\n' ​             \ +
-            ${ANSI_BLUE} ${ANSI_BOLD} 'BGP Prefix' ​   \ +
-            ${ANSI_UNBOLD} ${BGP_PREFIX:​-'​NA'​} ${ANSI_CLEAR} +
-        printf '​\t\t%b%b%-14s:​ %b%s%b\n' ​             \ +
-            ${ANSI_BLUE} ${ANSI_BOLD} '​Country' ​      \ +
-            ${ANSI_UNBOLD} ${COUNTRY:​-'​NA'​} ${ANSI_CLEAR} +
-        printf '​\t\t%b%b%-14s:​ %b%s%b\n' ​             \ +
-            ${ANSI_BLUE} ${ANSI_BOLD} 'Reg Authority'​ \ +
-            ${ANSI_UNBOLD} ${REGISTRY:​-'​NA'​} ${ANSI_CLEAR} +
-        printf '​\t\t%b%b%-14s:​ %b%s%b\n' ​             \ +
-            ${ANSI_BLUE} ${ANSI_BOLD} 'Reg Date' ​     \ +
-            ${ANSI_UNBOLD} ${DATE:​-'​NA'​} ${ANSI_CLEAR}+
  
-    done <<<​"${ROUTE},"+ax1.plot(times_s,​ throughput, color=color_tp,​ label="​Throughput (Mbit/s)", ​linewidth=1.5) 
 +ax1.set_ylabel("Throughput (Mbit/​s)",​ color=color_tp) 
 +ax1.tick_params(axis="​y",​ labelcolor=color_tp)
  
-done < <(tshark -r ${1}             `# input pcap file`        \ +ax2 = ax1.twinx() 
-                -Y 'icmp.type == 0' `# filter ICMP echo reply` \ +ax2.plot(times_s,​ cwnd_kb, color=color_cwnd, label="TCP cwnd (KB)", linewidth=1.2,​ linestyle="​--") 
-                ​-T fields ​          `# output format` ​         \ +ax2.set_ylabel("​TCP Congestion Window (KB)", color=color_cwnd) 
-                ​-e ip.src ​          `# print src IP`           \ +ax2.tick_params(axis="​y",​ labelcolor=color_cwnd)
-                -e ip.dst           `# print dst IP`           \ +
-                -e ip.rec_rt ​       `# print recorded route` ​  )+
  
-</​file>​ +lines1, labels1 = ax1.get_legend_handles_labels() 
-</​solution>​+lines2, labels2 = ax2.get_legend_handles_labels() 
 +ax1.legend(lines1 + lines2, labels1 + labels2, loc="​upper right",​ fontsize=9)
  
-**Task E - AS lookup ​(part II)**+# Bottom subplot: nf_hook_slow latency 
 +ax3.step(bpf_times, bpf_latency,​ color="​crimson",​ where="​post",​ linewidth=1.5,​ 
 +         ​label="​avg nf_hook_slow latency (ns)"​) 
 +ax3.set_ylabel("​avg latency (ns)"​) 
 +ax3.set_xlabel("​Time (s)"​) 
 +ax3.legend(loc="​upper left", fontsize=9) 
 +ax3.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, _: f"​{int(x):,​}"​))
  
-As you might have noticed during the previous taskeven DigitalOcean uses CloudFlare. +# Marking iptables injection window 
-{{:​ep:​labs:​04:​contents:​tasks:​docean-icmp.zip|This archive}} contains a //pcap// with ICMP Echo Request/​Replies sent from the university to four VMs hosted on DigitalOceanRun your script againon this //pcap// and see if you can spot any interesting organization namesThenlook them up.+INJECT_START = 10   # seconds after iperf3 started when you ran Terminal 3 
 +INJECT_END ​  = 260  # approximate end of injection loop 
 +for ax in (ax1ax3): 
 +    ax.axvspan(INJECT_STARTINJECT_END, alpha=0.08color="​gray",​ 
 +               ​label="​rule injection window"​)
  
-Not really relevant, but here are the IP addresses of the VMs involved: +plt.tight_layout() 
-<​code>​ +plt.savefig(OUTPUT_PNG,​ dpi=150) 
-New York           134.122.28.219 +print(f"​Saved {OUTPUT_PNG}"​)
-Frankfurt ​         46.101.222.105 +
-Singapore ​         178.128.213.179 +
-Toronto ​           165.22.239.70 +
-UPB (localhost   ​10.5.0.1+
 </​code>​ </​code>​
  
-</spoiler>+</solution> 
ep/labs/061/contents/tasks/ex4.1774294779.txt.gz · Last modified: 2026/03/23 21:39 by radu.mantu
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