Tutorial 2 - Wireshark, Spanning Tree and Traceroute
Submission process:
- Submission deadline is November 16, 14:00 CET (before the lecture) .
- Commit and push your solution as single notebook file via git as ./tutorial/tutorial2/tutorial2.ipynb. Please take care of the correct subfolder/filename since submission is denied otherwise.
- During the first lecture after the deadline we will discuss a sample solution in class.
- Afterwards, you have time until November 23, 14:00 CET (before the lecture) to submit a corrected version of your submission:
- Rework your solution according to our discussion in class.
- Commit and push the corrected version as single file via git as ./tutorial/tutorial2/tutorial2.ipynb. Please take care of the correct filename since submission is denied otherwise.
Remarks:
- Grading is done based on both versions of your submission.
- If the first submission is missing your submission will not be graded.
- If the second submission contains major flaws after revision not more than half of the credits for this tutorial can be achieved.
- A sample solution is provided after November 23, 14:00 CET eventually.
- Please use acn@net.in.tum.de for questions regarding lecture, tutorial, and project of ACN.
Problem 1 Wireshark (5 credits)
We consider the following hexdumps. It is known that these dumps represent Ethernet (IEEE 802.3u) frames including L2 headers but without FCS. In the following, we will dissect the whole frames.
To print the hexdump we use the hexdump Python module, which is not installed by default. Run the following cell to install it.
!pip3 install hexdump
Requirement already satisfied: hexdump in /opt/homebrew/lib/python3.11/site-packages (3.3) [notice] A new release of pip is available: 23.2.1 -> 23.3.2 [notice] To update, run: python3.11 -m pip install --upgrade pip
import binascii
from hexdump import hexdump
def prtyprnt(dump):
hexdump(dump)
# Here is an example how you can compare fields of a bytearray
# bytearray(b'\x01\x02\x03\x04')[2:4] == bytearray(b'\x03\x04')
dump_ipv4 = bytearray(b'\xfc\xe9\x98\x97\xec\xea\x44\xd9\xe7\x00\x40\x01\x08\x00\x45\x00\x00\x38\x00\x00\x00\x00\xf1\x01\x8c\x2b\x3e\x9a\x59\x2e\xac\x13\xf9\xbd\x0b\x00\xbf\x50\x00\x00\x00\x00\x45\x00\x00\x3c\x15\xb2\x00\x00\x01\x11\xea\x81\xac\x13\xf9\xbd\x81\xbb\x91\xf1\xd4\x0f\x82\xbe\x00\x28\xde\xb8')
dump_ipv6 = bytearray(b'\x33\x33\xff\xd7\x6d\xa0\x90\xe2\xba\x7a\xa7\x34\x86\xdd\x60\x00\x00\x00\x00\x20\x3a\xff\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x25\x90\xff\xfe\x54\x73\x9a\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xd7\x6d\xa0\x87\x00\x19\xc9\x00\x00\x00\x00\x20\x01\x4c\xa0\x20\x01\x00\x11\x02\x25\x90\xff\xfe\xd7\x6d\xa0\x01\x01\x00\x25\x90\x54\x73\x9a')
print('IPv4 packet:')
prtyprnt(dump_ipv4)
print('\nIPv6 packet:')
prtyprnt(dump_ipv6)
IPv4 packet: 00000000: FC E9 98 97 EC EA 44 D9 E7 00 40 01 08 00 45 00 ......D...@...E. 00000010: 00 38 00 00 00 00 F1 01 8C 2B 3E 9A 59 2E AC 13 .8.......+>.Y... 00000020: F9 BD 0B 00 BF 50 00 00 00 00 45 00 00 3C 15 B2 .....P....E..<.. 00000030: 00 00 01 11 EA 81 AC 13 F9 BD 81 BB 91 F1 D4 0F ................ 00000040: 82 BE 00 28 DE B8 ...(.. IPv6 packet: 00000000: 33 33 FF D7 6D A0 90 E2 BA 7A A7 34 86 DD 60 00 33..m....z.4..`. 00000010: 00 00 00 20 3A FF FE 80 00 00 00 00 00 00 02 25 ... :..........% 00000020: 90 FF FE 54 73 9A FF 02 00 00 00 00 00 00 00 00 ...Ts........... 00000030: 00 01 FF D7 6D A0 87 00 19 C9 00 00 00 00 20 01 ....m......... . 00000040: 4C A0 20 01 00 11 02 25 90 FF FE D7 6D A0 01 01 L. ....%....m... 00000050: 00 25 90 54 73 9A .%.Ts.
a) [0.5 credits] Briefly explain which purpose the FCS serves and how it is computed.
The frame check sequence (FCS) is appended at the end of each frame. Its purpose is to detect bit errors that occur during transfer. For Ethernet the FCS is computed using cyclic redundancy check (CRC). Depending on the CRC polynomial different kinds of errors can be detected. However, burst errors longer than the checksum can never be detected reliably as the error may be a multiple of the CRC polynomial. Note that CRC is normally not used for error correction although very special types of errors are indeed recoverable using CRC. Error correcting codes such has Hamming codes, Reed Solomon Codes, etc. are used by line codes on the physical layer.
b) [0.1 credits] Write the body of the given function extend_hexdump(). The function gets a hexdump without the FCS as an input and should return the extended hexdump with the FCS at the correct position and with the correct length. extend_hexdump() may not modify the original hexdump. You do not need to calculate the correct FCS but can set all bits of the FCS to '1'.
def extend_hexdump(dump):
# begin insert code
return dump + bytearray(b'\xFF\xFF\xFF\xFF')
# end insert code
return dump
prtyprnt(extend_hexdump(dump_ipv4))
00000000: FC E9 98 97 EC EA 44 D9 E7 00 40 01 08 00 45 00 ......D...@...E. 00000010: 00 38 00 00 00 00 F1 01 8C 2B 3E 9A 59 2E AC 13 .8.......+>.Y... 00000020: F9 BD 0B 00 BF 50 00 00 00 00 45 00 00 3C 15 B2 .....P....E..<.. 00000030: 00 00 01 11 EA 81 AC 13 F9 BD 81 BB 91 F1 D4 0F ................ 00000040: 82 BE 00 28 DE B8 FF FF FF FF ...(......
c) [0.2 credits] Write two functions which return the source and destination MAC of a given Ethernet frame.
- getSrcMAC() shall return a bytearray containing the source MAC address
- getDstMAC() shall return a bytearray containing the destination MAC address
def getSrcMAC(dump):
# begin insert code
# src is the second address in the ethernet frame
return dump[6:12]
# end insert code
return dump
prtyprnt(getSrcMAC(dump_ipv6))
00000000: 90 E2 BA 7A A7 34 ...z.4
def getDstMAC(dump):
# begin insert code
# dst is the first address in the ethernet frame
return dump[0:6]
# end insert code
return dump
prtyprnt(getDstMAC(dump_ipv6))
00000000: 33 33 FF D7 6D A0 33..m.
d) [0.5 credits] Try to identify the hardware vendors, based on MAC addresses given in the IPv6 hexdump.
- Dst MAC: 33:33:ff -> IPv6 Multicast -- No associated company
- Src MAC: 90:e2:ba -> Intel Corp
Taken from http://standards-oui.ieee.org/oui.txt
e) [0.6 credits]
Without knowing that the given hexdump is an Ethernet frame, we would not be able to decode it as we had no clue what the data fields represent. Knowing that it is Ethernet enables us to parse the first header.
- Write a function that is able to check for a given hexdump whether the frame contains an IPv4 packet as its payload or not.
- Write a function that is able to check for a given hexdump whether the frame contains an IPv6 packet as its payload or not.
- Write a function that returns the type of the layer 3 payload. It should return 4/6 for IPv4/IPv6 and None otherwise.
Note: You can assume Ethernet frames without VLANs, i.e., no IEEE 802.3q.
def isIPv4(dump):
# begin insert code
# Ethertype has fixed position => cut out respective bytes
ethertype = dump[12:14]
# length check (nice to have but not strictly required for this problem)
if len(ethertype) == 0:
print('frame too short')
return False
# check ethertype value
# 0x0800 => IPv4
# A list of standardized Ethertypes is maintained by IANA
# (Internet Assigned Numbers Authority)
# https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml
if ethertype == bytearray(b'\x08\x00'):
return True
# This piece of code only handles Layer 2 not Layer 3.
# You may additionally check the IP version field but it is not required
# for this exercise. Checking only the Layer 3 version field would not
# suffice as we do not know the header of the Layer 3 protocol without
# checking Layer 2 first.
# end insert code
return False
print('Does dump_ipv4 contain a valid IPv4 packet?', isIPv4(dump_ipv4))
Does dump_ipv4 contain a valid IPv4 packet? True
def isIPv6(dump):
# begin insert code
# Ethertype has fixed position => cut out respective bytes
ethertype = dump[12:14]
# length check (nice to have but not strictly required for this problem)
if len(ethertype) == 0:
print('frame too short')
return False
# check ethertype value
# 0x86DD => IPv4
# A list of standardized Ethertypes is maintained by IANA
# (Internet Assigned Numbers Authority)
# https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml
if ethertype == bytearray(b'\x86\xDD'):
return True
# This piece of code only handles Layer 2 not Layer 3.
# You may additionally check the IP version field but it is not required
# for this exercise. Checking only the Layer 3 version field would not
# suffice as we do not know the header of the Layer 3 protocol without
# checking Layer 2 first.
# end insert code
return False
print('Does dump_ipv6 contain a valid IPv6 packet?', isIPv6(dump_ipv6))
Does dump_ipv6 contain a valid IPv6 packet? True
def getL3Type(dump):
# begin insert code
# check if IPv4
if isIPv4(dump):
return 4
# check if IPv6
if isIPv6(dump):
return 6
# return None otherwise
return None
# end insert code
return None
print('dump_ipv4 contains IP version {}'.format(getL3Type(dump_ipv4)))
print('dump_ipv6 contains IP version {}'.format(getL3Type(dump_ipv6)))
dump_ipv4 contains IP version 4 dump_ipv6 contains IP version 6
f) [0.5 credits] How can the beginning of the payload be determined for Ethernet frames?
For traditional Ethernet there is a fixed header length (Dst MAC address 6 Byte, Src MAC address 6 Byte, Ethertype 2 Byte). Since the header has a fixed length, there is no need to indicate the beginning of the payload itself.
Later in the lecture we present VLAN (IEEE 802.1Q).
For frames following that standard the header length varies.
If no VLAN tag is present, the traditional header is used.
In case of VLAN tagged frames, the location of the original Ethertype contains a 0x8100
, followed by the Tag Control Information (TCI, 16 bit).
After that the Ethertype of the payload is defined and after that the payload begins.
The header size for frames of this kind is 4 Bytes longer.
According to IEEE 802.1ad (also known as QinQ) it is possible to define two VLANs.
There the TCI of the first VLAN is followed by 0x8100
and a second TCI, before the Ethertype of the payload starts.
After that the payload begins.
The header size for frames of this kind is 4 Bytes longer than IEEE 802.1Q tagged frames.
g) [0.6 credits] How can the beginning of the payload be determined for IP packets? What is the difference between IPv4 and IPv6?
IPv4 has a variable header length and IPv6 can have extension headers after a fixed size header, so the begin of the payload is not fixed.
- IPv4: header length is defined in the IP header length (IHL) field, these 4 Bit determine the length of the IP header in 32 bit words [RFC 791]
- IPv6: next header field, defines the following header which can either be the payload, e.g., TCP or an extension header. The extension headers itself have a next header field and a length forming a chain of extension headers. The payload starts after this chain of extension headers. [RFC 8200]
h) [0.6 credits] Write three functions:
- cutL2PDU() shall return a bytearray containing the Layer 2 PDU
- cutL2SDU() shall return a bytearray containing the Layer 2 SDU
- cutIPPDU() shall return a bytearray containing the Layer 3 PDU.
cutIPPDU() should only cut out valid IPv4 or IPv6 packets. In case no IPv4 or IPv6 packet is found an empty bytearray should be returned.
All functions get an Ethernet hexdump as input with the FCS excluded. The functions should work not only on the given hexdump but on an arbitrary packet hexdump. For this exercise you can assume correct packets, i.e. your functions do not need to validate the given data.
def cutL2PDU(dump):
# begin insert code
# Validation of packet data was omitted intentionally.
# The protocol data unit (PDU) contains the header and the payload.
# No changes required for the given input data.
# end insert code
return dump
prtyprnt(cutL2PDU(dump_ipv4))
00000000: FC E9 98 97 EC EA 44 D9 E7 00 40 01 08 00 45 00 ......D...@...E. 00000010: 00 38 00 00 00 00 F1 01 8C 2B 3E 9A 59 2E AC 13 .8.......+>.Y... 00000020: F9 BD 0B 00 BF 50 00 00 00 00 45 00 00 3C 15 B2 .....P....E..<.. 00000030: 00 00 01 11 EA 81 AC 13 F9 BD 81 BB 91 F1 D4 0F ................ 00000040: 82 BE 00 28 DE B8 ...(..
def cutL2SDU(dump):
# begin insert code
# Validation of packet data was omitted intentionally.
# The service data unit (SDU) contains only the payload data
# This requires the header to be removed from the layer 2 frame
return dump[14:len(dump)]
# end insert code
return dump
prtyprnt(cutL2SDU(dump_ipv4))
00000000: 45 00 00 38 00 00 00 00 F1 01 8C 2B 3E 9A 59 2E E..8.......+>.Y. 00000010: AC 13 F9 BD 0B 00 BF 50 00 00 00 00 45 00 00 3C .......P....E..< 00000020: 15 B2 00 00 01 11 EA 81 AC 13 F9 BD 81 BB 91 F1 ................ 00000030: D4 0F 82 BE 00 28 DE B8 .....(..
def cutIPPDU(dump):
# begin insert code
# L2 SDU == L3 PDU
# check if there is IPv4
if isIPv4(dump) or isIPv6(dump):
return cutL2SDU(dump)
else:
return bytearray()
# end insert code
return dump
prtyprnt(cutIPPDU(dump_ipv4))
00000000: 45 00 00 38 00 00 00 00 F1 01 8C 2B 3E 9A 59 2E E..8.......+>.Y. 00000010: AC 13 F9 BD 0B 00 BF 50 00 00 00 00 45 00 00 3C .......P....E..< 00000020: 15 B2 00 00 01 11 EA 81 AC 13 F9 BD 81 BB 91 F1 ................ 00000030: D4 0F 82 BE 00 28 DE B8 .....(..
i) [0.2 credits] Write a function which helps to identify the type of payload an IPv4 or IPv6 packet is carrying. You can assume that the identifyPayploadIP() gets an Ethernet hexdump as input with the FCS excluded. It should return a bytearray containing the L4 payload identifier or an empty bytearray if neither an IPv4 nor an IPv6 payload was found.
Hint: you can assume that there are no Extension Headers within the IPv6 packets.
def identifyPayloadIP(dump):
# begin insert code
ip_pdu = cutIPPDU(dump)
if getL3Type(dump) == 4:
# Protocol field contains protocol of payload
return ip_pdu[9:10]
elif getL3Type(dump) == 6:
# Next Header field contains protocol of payload in this case
return ip_pdu[6:7]
else:
# Return an empty byterarry otherwise
return bytearray()
# end insert code
return dump
prtyprnt(identifyPayloadIP(dump_ipv4))
prtyprnt(identifyPayloadIP(dump_ipv6))
00000000: 01 . 00000000: 3A :
j) [0.2 credits] Based on your answer of i), what are the protocols contained in the two given hexdumps.
Protocol numbers are also maintained by the IANA. The IPv4 header contains a protocol field. Its value 0x01 identifies the L3-SDU as ICMPv4. The IPv6 header contains a next header field. Its value 0x3a identifies the L3-SDU as ICMPv6.
k) [0.5 credits] Explain the payload (header fields and the content type) of the IPv4 packet identified in j).
Knowing that the L3 SDU is ICMPv4, we can identify the content using the ICMPv4 type and code header fields yielding Time Exceeded / TTL expired in transit. For those ICMP messages the following 4 B are unused and thus set to zero. The payload consists in the IPv4 header of the original message that timed out plus the first 8 B of the following header.
We can thus parse this IPv4 header and find that the payload must be UDP as the protocol field is 0x11. The last 8 B are thus a UDP header containing in particular source and destination port numbers.
The IPv6 dump contains the ICMPv6 NDP neighbor solicitation message for 2001:4ca0:2001:11:225:90ff:fed7:6da0. As the Source does not know the destinations MAC address it sends it to the IPv6 multicast address.
Problem 2 Spanning Tree Protocol (2.5 credits)
We consider the network topology shown in the following figure. The bridge IDs of B1 to B5 correspond to their number, i. e., B1 has ID 1, B2 has ID 2, etc. For the sake of simplicity, we assume equal costs for each bridge port. The network segments are labeled by letters A to H.
To visualize the graph we use the networkx module, which probably needs to be installed.
%matplotlib inline
import networkx as nx
import matplotlib.pyplot as plt
edges = [
# (src, dst, weight)
('netA', 'B2', 1),
('netA', 'B5', 1),
('netB', 'B5', 1),
('netB', 'B1', 1),
('netC', 'B2', 1),
('netC', 'B3', 1),
('netD', 'B5', 1),
('netD', 'B4', 1),
('netE', 'B3', 1),
('netE', 'B4', 1),
('netF', 'B1', 1),
('netF', 'B4', 1),
('netG', 'B4', 1),
('netH', 'B1', 1),
]
networks = {
# 'name':(posX, posY)
'netA':(0,0),
'netB':(20,-20),
'netC':(0,-40),
'netD':(10,-60),
'netE':(0,-80),
'netF':(20,-80),
'netG':(10,-100),
'netH':(30,-60)
}
bridges = {
# 'name':(posX, posY)
'B1':(20,-60),
'B2':(0,-20),
'B3':(0,-60),
'B4':(10,-80),
'B5':(10,-20)
}
ports = {
# 'name':(posX, posY)
'b1pa':(21.5,-60),
'b1pb':(20,-55),
'b1pc':(20,-65),
'b2pa':(0,-15),
'b2pb':(0,-25),
'b3pa':(0,-55),
'b3pb':(0,-65),
'b4pa':(10,-75),
'b4pb':(10,-85),
'b4pc':(8.5,-80),
'b4pd':(11.5,-80),
'b5pa':(11.5,-20),
'b5pb':(10,-25),
'b5pc':(8.5,-17)
}
def plotNetwork(edges, networks, bridges, bp, dp, rp):
# set plot size
plt.figure(3,figsize=(10,10))
# draw graph
G = nx.Graph()
G.add_weighted_edges_from(edges)
nx.draw_networkx_edges(G, pos=dict(dict(networks, **bridges), **ports), nodelist = [], edgelist = edges)
nx.draw_networkx_nodes(G, pos=networks, nodelist=networks.keys(), node_color = 'lightblue', node_size=1000)
nx.draw_networkx_nodes(G, pos=bridges, nodelist=bridges.keys(), node_color = 'red', node_shape='s', node_size=500)
nx.draw_networkx_nodes(G, pos=ports, nodelist=dp, node_color='blue', node_size=250)
nx.draw_networkx_nodes(G, pos=ports, nodelist=rp, node_color='green', node_size=250)
nx.draw_networkx_nodes(G, pos=ports, nodelist=bp, node_color='black', node_size=250)
nx.draw_networkx_labels(G, pos=dict(dict(networks, **bridges), **ports))
# remove axis and plot
plt.axis('off')
plt.show()
plotNetwork(edges, networks, bridges, {}, {}, {})
a) [0.25 credits] What is the difference between a shortest path tree (SPT) and a minimum spanning tree (MST)?
- SPT: A shortest path tree (SPT) contains the shortest paths from one node (the tree’s root) to all other nodes.
- MST: A minimum spanning tree (MST) connects all nodes of the network in a way such that the sum of edge weights is minimized.
Both variants are spanning trees and neither tree is unique. The outcome of the spanning tree protocol is an SPT rooted at the root bridge.
b) [0.25 credits] Explain the problem that is being solved by using the spanning tree protocol in a switched network.
The STP is useful when there are loops on layer 2, which would cause a broadcast storm since bridges forward frames to broadcast or unknown destination addresses via all ports except the port from which the frame has been received. Creating a spanning tree ensures that frames are not forwarded back and forth indefinitely. The minimum spanning tree in addition guarantees that the minimum number of network segments (bridges) are traversed.
Remember, there is no TTL or MaxHops counter in Ethernet as there is for IP. Furthermore, the STP creates backup paths in case of link or bridge failures.
c) [0.5 credits] Explain the purpose of the root bridge and how it is elected.
The root bridge acts as reference point in the network as the resulting SPT depends on which bridge is chosen. The root bridge is determined via an election process:
- Initially, each bridge assumes it is the root bridge and starts transmitting bridge protocol data units (BPDUs). These contain the transmitters bridge ID, the root bridge ID, and the distance from the transmitter to the root bridge. The bridge ID itself consists of a (configurable) priority field and the bridge’s MAC address.
- Bridges listen for incoming BPDUs on all ports. BPDUs are not forwarded but evaluated:
- The port from where the BPDU with the lowest bridge ID is received (with the lowest path length) becomes the root port of a bridge.
- If two ports connect the networks to the root bridge the one with the higher cost, or in case of same costs the bridge with the higher id blocks its ports to this network.
- All other ports become designated ports
Given some time, the algorithm outlined above converges and leads to an SPT with the root bridge as root node. Note that any segment has precisely one designated port. In case of segments that have two or more bridges with identical path lengths to the root bridge, the bridge with the lower bridge ID will serve that segment. The other bridges set their ports to that segment into blocking mode. Otherwise, the root bridge with the unique lowest path length to the root bridge serves a segment.
d) [1 credits] How does the resulting spanning tree look like after the spanning tree algorithm has been applied to the given network topology?
# fill these lists with the names of the blocked/designated/root ports
# use the names already predefined e.g., blocked = ['b1pa'] for blocking port a of bridge b1
# take care that each port only occurs once
# if a port is assigned multiple times your answer will not be accepted
blocked = [
# begin insert code
'b5pb', 'b3pa'
# end insert code
]
designated = [
# begin insert code
'b1pb', 'b1pa', 'b1pc', 'b4pb', 'b4pc', 'b4pa', 'b5pc', 'b2pb'
# end insert code
]
root = [
# begin insert code
'b5pa', 'b4pd', 'b3pb', 'b2pa'
# end insert code
]
plotNetwork(edges, networks, bridges, blocked, designated, root)
e) [0.5 credits] What happens if bridge B1 fails?
If B1 fails, it stops transmitting BPDUs. When the neighboring bridges do not receive those BPDUs over a given time interval, they recognize that the root bridge is gone. According to the algorithm above a new bridge becomes the root bridge, in our example this will be B2.
As long as B1 is not available, netH will be disconnected from the network.
Problem 3 Network Topology and Tracing Routes (5 credits)
In this task, you will make yourself familiar with the tool traceroute, which can be used to get a glimpse at a network’s topology.
a) [0.5 credits] Explain the basic principle behind traceroute, i.e., how does it work and what is it being used for?
- Send IP packets with increasing TTL values starting at a value of 1.
- Routers decrease the TTL on forwarding if TTL is not 0.
- When the TTL reaches 0 (or conversely if a router receives a packet with TTL=1 that shall be forwarded), the respective router discards the packet and creates an ICMP Time Exceeded / TTL Exceeded , which is returned to the original sender of the packet.
- This error message contains the IP address of the router that discarded the packet (source IP) as well as the original, dropped packet starting from the L3 header.
- Traceroute is a tool which tries to figure out certain metrics of a path to a destination.
- It can be used to detect network problems, analyze routing behavior and get an approximate path length to a network host.
b) [0.5 credits] Discuss the advantages and disadvantages when using packets with different protocols / payload types to generate the traces.
There are three types of traceroutes:
- ICMP: Sends ICMP echo request packets with increasing TTLs, receives ICMP TTL exceeded error packets in response. Sending ICMP packets requires root permissions.
- TCP: Sends TCP packets with increasing TTLs, receives ICMP TTL exceeded error packets in response. Sending TCP SYN packets requires root permissions. By default, port 80 is used as destination port. Easier to bypass firewalls.
- UDP: Sends UDP packets with increasing TTLs, receives ICMP TTL exceeded error packets in response. Sending UDP packets does not require root permissions. Traces are sent with increasing “unlikely” port numbers or a fixed port. Can make the receiving part confused by sending random data, potentially no reply by last hop.
The following cell shows an output of traceroute to caida.org.
# traceroute to www.caida.org (2001:48d0:101:501::122), 30 hops max, 80 byte packets
# 1 * * 2a00:4700:0:9::1 (2a00:4700:0:9::1) 1.663 ms
# 2 2a00:4700:0:8::1 (2a00:4700:0:8::1) 1.512 ms 1.363 ms 1.107 ms
# 3 2a00:4700:0:1::3 (2a00:4700:0:1::3) 1.458 ms 1.263 ms 1.056 ms
# 4 * * *
# 5 cr-fra2-be14.x-win.dfn.de (2001:638:c:c071::1) 10.762 ms * *
# 6 dfn.mx1.fra.de.geant.net (2001:798:14:10aa::9) 10.881 ms 10.644 ms 10.492 ms
# 7 ae7.mx1.ams.nl.geant.net (2001:798:cc::19) 16.758 ms 16.595 ms 16.446 ms
# 8 internet2-gw.mx1.ams.nl.geant.net (2001:798:99:1::2a) 111.152 ms 111.005 ms *
# 9 fourhundredge-0-0-0-2.4079.core1.ashb.net.internet2.edu (2001:468:0:1::74) 166.537 ms 167.209 ms 166.795 ms
#10 fourhundredge-0-0-0-16.4079.core2.ashb.net.internet2.edu (2001:468:0:1::3) 167.301 ms fourhundredge-0-0-0-18.4079.core2.ashb.net.internet2.edu (2001:468:0:1::6b) 167.122 ms fourhundredge-0-0-0-17.4079.core2.ashb.net.internet2.edu (2001:468:0:1::9) 166.943 ms
#11 fourhundredge-0-0-0-1.4079.core2.clev.net.internet2.edu (2001:468:0:1::8b) 166.439 ms 166.259 ms fourhundredge-0-0-0-23.4079.core2.clev.net.internet2.edu (2001:468:0:1::193) 166.082 ms
#12 fourhundredge-0-0-0-2.4079.core2.eqch.net.internet2.edu (2001:468:0:1::111) 167.631 ms 167.452 ms 167.275 ms
#13 fourhundredge-0-0-0-17.4079.core1.eqch.net.internet2.edu (2001:468:0:1::40) 167.947 ms fourhundredge-0-0-0-2.4079.core2.chic.net.internet2.edu (2001:468:0:1::112) 166.519 ms fourhundredge-0-0-0-18.4079.core1.eqch.net.internet2.edu (2001:468:0:1::42) 167.564 ms
#14 fourhundredge-0-0-0-1.4079.core1.chic.net.internet2.edu (2001:468:0:1::ce) 166.520 ms 166.388 ms fourhundredge-0-0-0-22.4079.core1.chic.net.internet2.edu (2001:468:0:1::60) 167.456 ms
#15 fourhundredge-0-0-0-1.4079.core2.kans.net.internet2.edu (2001:468:0:1::11d) 167.196 ms 167.011 ms 166.830 ms
#16 fourhundredge-0-0-0-1.4079.core2.denv.net.internet2.edu (2001:468:0:1::fa) 167.063 ms 166.883 ms 166.705 ms
#17 fourhundredge-0-0-0-3.4079.core2.salt.net.internet2.edu (2001:468:0:1::a9) 167.973 ms 167.795 ms 167.617 ms
#18 fourhundredge-0-0-0-8.4079.core1.losa.net.internet2.edu (2001:468:0:1::72) 165.542 ms * *
#19 hpr-lax-agg10--i2.cenic.net (2607:f380:1::108:9a41:ac81) 164.806 ms 176.149 ms 175.724 ms
#20 * * *
#21 hpr-sdsc-100ge--sdg-hpr3.cenic.net (2607:f380:1::108:9a41:a2b1) 167.048 ms 166.858 ms 167.170 ms
#22 2001:48d0:101:501::122 (2001:48d0:101:501::122) 167.055 ms 166.921 ms 167.033 ms
# Use the following simplified output for plotting
traceroute_output = """
2a00:4700:0:9::1 * * 1.663 ms
2a00:4700:0:8::1 1.512 ms 1.363 ms 1.107 ms
2a00:4700:0:1::3 1.458 ms 1.263 ms 1.056 ms
* * *
2001:638:c:c071::1 10.762 ms * *
2001:798:14:10aa::9 10.881 ms 10.644 ms 10.492 ms
2001:798:cc::19 16.758 ms 16.595 ms 16.446 ms
2001:798:99:1::2a 111.152 ms 111.005 ms *
2001:468:0:1::74 166.537 ms 167.209 ms 166.795 ms
2001:468:0:1::3 167.301 ms 167.122 ms 166.943 ms
2001:468:0:1::8b 166.439 ms 166.259 ms 166.082 ms
2001:468:0:1::111 167.631 ms 167.452 ms 167.275 ms
2001:468:0:1::40 167.947 ms 166.519 ms 167.564 ms
2001:468:0:1::ce 166.520 ms 166.388 ms 167.456 ms
2001:468:0:1::11d 167.196 ms 167.011 ms 166.830 ms
2001:468:0:1::fa 167.063 ms 166.883 ms 166.705 ms
2001:468:0:1::a9 167.973 ms 167.795 ms 167.617 ms
2001:468:0:1::72 165.542 ms * *
2607:f380:1::108:9a41:ac81 164.806 ms 176.149 ms 175.724 ms
* * *
2607:f380:1::108:9a41:a2b1 167.048 ms 166.858 ms 167.170 ms
2001:48d0:101:501::122 167.055 ms 166.921 ms 167.033 ms
"""
c) [0.25 credits] What does the line * * * mean?
The asterisks (*) signal that there was no answer for the respective request. Possible reasons are lost packets, firewalling, and ICMP rate limiting.
d) [0.75 credits] Execute the traceroute command in the following cell from your VM. Compare these results to the given trace and explain what you find.
!traceroute www.caida.org # just execute this cell to start a traceroute
traceroute to www.caida.org (192.172.226.122), 64 hops max, 52 byte packets 1 scylla (131.159.20.11) 1.557 ms 0.475 ms 0.489 ms 2 nz-bb1-net.in.tum.de (131.159.252.147) 0.667 ms 0.637 ms 0.615 ms 3 nz-csr1-kw5-bb1.rbg.tum.de (131.159.252.2) 0.948 ms 1.020 ms 1.132 ms 4 vl-3010.csr1-2wr.lrz.de (129.187.0.149) 1.202 ms 1.151 ms 1.131 ms 5 cr-gar1-be2-147.x-win.dfn.de (188.1.37.89) 1.225 ms 1.309 ms 1.077 ms 6 cr-fra2-be14.x-win.dfn.de (188.1.145.229) 10.125 ms 10.134 ms 9.876 ms 7 dfn.rt1.fra.de.geant.net (62.40.124.217) 9.763 ms 9.839 ms 9.994 ms 8 internet2-gw.mx1.lon.uk.geant.net (62.40.124.45) 106.444 ms 107.602 ms 105.890 ms 9 fourhundredge-0-0-0-0.4079.core1.ashb.net.internet2.edu (163.253.1.118) 165.621 ms 165.197 ms 167.688 ms 10 fourhundredge-0-0-0-1.4079.core1.clev.net.internet2.edu (163.253.1.123) 165.694 ms 164.719 ms 164.376 ms 11 fourhundredge-0-0-0-2.4079.core1.eqch.net.internet2.edu (163.253.1.211) 166.541 ms 166.913 ms 165.246 ms 12 fourhundredge-0-0-0-1.4079.core1.chic.net.internet2.edu (163.253.1.206) 165.248 ms 165.548 ms 165.150 ms 13 fourhundredge-0-0-0-1.4079.core2.kans.net.internet2.edu (163.253.2.29) 164.850 ms 167.214 ms 166.811 ms 14 fourhundredge-0-0-0-1.4079.core2.denv.net.internet2.edu (163.253.1.250) 165.533 ms 165.172 ms 166.376 ms 15 fourhundredge-0-0-0-3.4079.core2.salt.net.internet2.edu (163.253.1.169) 164.191 ms 166.718 ms 165.111 ms 16 fourhundredge-0-0-0-8.4079.core1.losa.net.internet2.edu (163.253.1.114) 164.882 ms 166.150 ms 165.168 ms 17 hpr-lax-agg10--i2.cenic.net (137.164.26.200) 163.386 ms 163.248 ms 163.476 ms 18 hpr-sdg-agg4--lax-agg10-100ge.cenic.net (137.164.25.89) 166.253 ms 171.295 ms hpr-lax-agg10--i2.cenic.net (137.164.26.200) 167.081 ms 19 hpr-sdg-agg4--lax-agg10-100ge.cenic.net (137.164.25.89) 166.872 ms 165.533 ms 165.811 ms 20 hpr-sdsc-100ge--sdg-hpr3.cenic.net (137.164.26.43) 165.671 ms 165.651 ms 165.545 ms 21 medusa-mx960.sdsc.edu (192.12.207.46) 165.898 ms 165.810 ms 167.311 ms 22 proxy.caida.org (192.172.226.122) 165.518 ms 165.522 ms 165.470 ms
- This command executes an IPv4 traceroute scan.
- Most available reverse DNS names are similar
- 10 hops only respond in the IPv6 trace. All of them are from Internet2
- Latency difference is neglectable
e) [0.75 credits] Plot the average RTT deltas between consecutive hops from the given traceroute output, e.g., $\Delta RTT_{0\rightarrow1} = RTT_1 − RTT_0$.
Hint: Use the given csv reader to extract the numbers from the traceroute output. Graphs can be generated using the python library matplotlib. The differences in this subproblem can be nicely plotted with a bar chart.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import csv
# read data from traceroute
reader = csv.reader(traceroute_output.splitlines(), delimiter=' ', skipinitialspace=True)
# begin insert code
line = []
raw = [0]
for row in reader:
for col in row:
try:
res = float(col)
line = line + [res]
except ValueError:
pass
if len(line) > 0:
raw = raw + [np.average(line)]
line = []
# calculate diff
diff = np.diff(raw).tolist()
# print data
print("Raw data from traceroute:")
print(raw)
print('')
print("RTT deltas:")
print(diff)
#plot
N = len(diff)
x = range(N)
plt.figure(3,figsize=(20,10))
plt.bar(x, diff, align='center')
plt.xticks(x)
plt.ylabel('RTT delta [ms]')
plt.title('Differences between hops of a traceroute')
plt.show()
# end insert code
Raw data from traceroute: [0, 1.663, 1.3273333333333335, 1.2590000000000001, 10.762, 10.672333333333333, 16.599666666666664, 111.07849999999999, 166.84699999999998, 167.12199999999999, 166.26, 167.45266666666666, 167.34333333333333, 166.788, 167.01233333333334, 166.8836666666667, 167.795, 165.542, 172.22633333333337, 167.02533333333335, 167.00300000000001] RTT deltas: [1.663, -0.33566666666666656, -0.06833333333333336, 9.503, -0.0896666666666679, 5.927333333333332, 94.47883333333333, 55.76849999999999, 0.2750000000000057, -0.8619999999999948, 1.1926666666666677, -0.10933333333332484, -0.5553333333333228, 0.22433333333333394, -0.12866666666664628, 0.9113333333332889, -2.252999999999986, 6.68433333333337, -5.201000000000022, -0.02233333333333576]
f) [0.25 credits] Try to find an explanation for the largest RTT difference calculated in the previous subproblem.
The traceroute is started in Munich, Germany and ends in San Diego, US. The distance between these two locations is about 9600km. The big difference between hops 7 & 9 is most likely the transcontinental hop and through the United States.
- 7 ae7.mx1.ams.nl.geant.net (2001:798:cc::19) 16.758 ms 16.595 ms 16.446 ms
- 8 internet2-gw.mx1.ams.nl.geant.net (2001:798:99:1::2a) 111.152 ms 111.005 ms *
- 9 fourhundredge-0-0-0-2.4079.core1.ashb.net.internet2.edu (2001:468:0:1::74) 166.537 ms 167.209 ms 166.795 ms
Hop 7 is closer to Munich based on the RTTs and most likely located in the Netherlands. See also the network map by Internet2 (Link).
g) [0.5 credits] Explain why the RTT differences should be always positive in theory. Why does this assumption not always hold in practice?
A negative difference means, that the next hop is sending out ICMP responses faster than the previous hop. The two respecive measurements are quite close to each other the routers may also be physically close to each other.
A possible reason for this seemingly unintuitive behavior could be that slower router does ICMP throttling, thus delaying ICMP responses. Another possibility is that ICMP packets have a lower priority (when under load).
h) [0.5 credits] Try to find out different ways to determine the approximate geographical location of the hops in the given traceroute.
- GeoIP location services, e.g. maxmind
- Sometimes the DNS names give a hint to the location. Names may suggest the location of the router or the direction where the cable goes to. However, this information might be misleading (compare 3f) ). To get the DNS name for a given IP reverse DNS (rDNS) can be used.
- There are other ways, e.g. RTT triangulation from several known vantage points, DNS LOC records, or crowd sorced data [RIPE Atlas]
- Some providers offer additional information: e.g., GEANT
- Some operators offer rough maps of their network, e.g., Internet2
i) [1 credit] Figure out the approximate location for as many hops as possible. Use at least two different methods to determine the location
IP address | rDNS | GeoIP service | rDNS location hints |
---|---|---|---|
2a00:4700:0:9::1 | - | Germany | - |
2a00:4700:0:8::1 | - | Germany | - |
2a00:4700:0:1::3 | - | Germany | - |
2001:638:c:c071::1 | cr-fra2-be14.x-win.dfn.de | Germany | fra - Frankfurt, Germany |
2001:798:14:10aa::9 | dfn.mx1.fra.de.geant.net | Netherlands | fra - Frankfurt, Germany |
2001:798:cc::19 | ae7.mx1.ams.nl.geant.net | Netherlands | ams.nl - Amsterdam, Netherlands |
2001:798:99:1::2a | internet2-gw.mx1.ams.nl.geant.net | United States | ams.nl - Amsterdam, Netherlands |
2001:468:0:1::74 | fourhundredge-0-0-0-2.4079.core1.ashb.net.internet2.edu | United States | ashb - Ashburn, Virginia |
2001:468:0:1::3 | fourhundredge-0-0-0-16.4079.core2.ashb.net.internet2.edu | United States | ashb - Ashburn, Virginia |
2001:468:0:1::8b | fourhundredge-0-0-0-1.4079.core2.clev.net.internet2.edu | United States | clev - Cleveland, Ohio |
2001:468:0:1::111 | fourhundredge-0-0-0-2.4079.core2.eqch.net.internet2.edu | United States | eqch - Probably Chicago, Illinois |
2001:468:0:1::40 | fourhundredge-0-0-0-17.4079.core1.eqch.net.internet2.edu | United States | eqch - Probably Chicago, Illinois |
2001:468:0:1::ce | fourhundredge-0-0-0-1.4079.core1.chic.net.internet2.edu | United States | chic - Chicago, Illinois |
2001:468:0:1::11d | fourhundredge-0-0-0-1.4079.core2.kans.net.internet2.edu | United States | kans - Kansas City, Missouri |
2001:468:0:1::fa | fourhundredge-0-0-0-1.4079.core2.denv.net.internet2.edu | United States | denv - Denver, Colorado |
2001:468:0:1::a9 | fourhundredge-0-0-0-3.4079.core2.salt.net.internet2.edu | United States | salt - Salt Lake City, Utah |
2001:468:0:1::72 | fourhundredge-0-0-0-8.4079.core1.losa.net.internet2.edu | United States | losa - Los Angeles, California |
2607:f380:1::108:9a41:ac81 | hpr-lax-agg10--i2.cenic.net | United States | lax - Los Angeles, California |
2607:f380:1::108:9a41:a2b1 | hpr-sdsc-100ge--sdg-hpr3.cenic.net | United States | sdg - San Diego, California |
2001:48d0:101:501::122 | - | United States | - |
The data shows that the location services are quite coarse and in some cases misleading. Always keep that in mind when using them.
Advanced Computer Networking by Prof. Dr.-Ing. Georg Carle
Teaching assistants: Sebastian Gallenmüller, Benedikt Jaeger, Max Helm, Patrick Sattler, Johannes Zirngibl, Marcel Kempf