联系方式

  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp

您当前位置:首页 >> Python编程Python编程

日期:2018-10-12 09:45

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 1/27

CS 3640: Introduction to Networks and Their

Applications [Fall 2018]

Instructor: Rishab Nithyanand (Office hours: Wednesday 9-10 am or by appointment)

Teaching assistant: Md. Kowsar Hossain (Office hours: Monday 1:30-2:30 pm)

Assignment 3: Internet Routing

Released on: October 4th, 2018 | Due by: October 18th, 2018 (11:59:59 pm)

Maximum score: 100 | Value towards final grade: 13%

I. Groups

As stated in class, on the website, and on Piazza, this assignment will be done in groups of 4 or 5.

Here are the groups for this assignment.

Group ID Hawk IDs of group members

1 'kzhang24', 'dstutz', 'xxing2', 'atran4'

2 'lburden', 'hrunning', 'ppeterschmidt', 'jglowacki'

3 'bzhang22', 'mfmrphy', 'jmagri', 'sklemm'

4 'yzheng19', 'hpen', 'apizzimenti', 'tgoodmn'

5 'ywang391', 'okueter', 'ymann', 'lye1'

6 'msmith3', 'jblue', 'zluo1', 'yonghfan'

7 'gongyzhou', 'mcagley', 'ywang455', 'kdzhou'

8 'gmich', 'xiaosong', 'tsimonson', 'shangwchen'

9 'nsonalkar', 'bchoskins', 'apatrck', 'yitzhou'

10 'awestemeier', 'uupadhyay', 'tnlowry', 'jpflint'

11 'jpthiede', 'nicgoh', 'rdong6', 'susmerano'

12 'godkin', 'cweiske', 'weigui', 'jstoltz'

13 'jdhatch', 'xchen117', 'trjns', 'zzhang103'

Getting in touch with your team

Use the HawkIDs listed to email your team-mates or make a post on Piazza. If you're unable to get

in touch with any member of your team, let me know ASAP!

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 2/27

Congeniality and healthy collaboration

I will take complaints of discrimination and harassment extremely seriously and these will be

reported to the appropriate authorities. You are expected to treat your classmates with respect and

kindness.

II. Submission

Each group is to submit this notebook after filling in the blank cells as instructed. The submissions

are due on ICON at 23:59:59 on October 19th, 2018. The last submission submitted by a team

member before midnight on the due date will be the one graded unless ALL team members let the

TA and me know that they want another submission to be graded (the late penalty if a submission

made past the due date is chosen).

Late submissions

I am being generous in the amount of time allotted to this assignment to account for difficulties in

scheduling meetings, etc. There will be no extensions of the due date under any circumstances. If a

submission is received past the due date, the late policy detailed on the course webpage will apply.

Team-mate feedback

Each team member may also send me an email (rishab-nithyanand@uiowa.edu (mailto:rishabnithyanand@uiowa.edu))

with subject "Feedback: Assignment 3, Group N" detailing their

experience working with each of their team-mates. For each team member, tell me at least

one good thing and one thing they could improve. These will be anonymized and released to

each individual at the end of the term. It's important to know how to work well in a team and

early feedback before you move on to bigger and better things is always helpful. Sending

feedback for all 4 assignments will fetch you a 4% bonus at the end of the term. Note: Sending

with an incorrect subject line means that the email will not get forwarded to the right inbox.

III. Learning goals

My goal is to give you assignments that will help you build a nice starter pack of computer

networking skills that will help you get a better picture of how the Internet works in addition to

helping you in the real-world.

In this assignment you will learn how BGP and Internet routing works in the real world. I expect that

by the end of this assignment you should know how to:

Parse BGP route announcements and withdrawals (Task 1)

Build a simplified router which maintains a routing table based on BGP updates it receives (Task

2)

Identify BGP route announcements that appear to be malicious (Task 2)

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 3/27

This assignment is especially cool because you will be dealing with real BGP data from a real world

Autonomous System obtained by the RouteViews project at the University of Oregon. You can read

more about RouteViews here: http://www.routeviews.org/routeviews/

(http://www.routeviews.org/routeviews/). You will also be identifying and defending against a real

BGP hijack that took YouTube off the Internet for about 15 minutes in 2008. You can read about this

BGP hijack here: https://www.cnet.com/news/how-pakistan-knocked-youtube-offline-and-how-tomake-sure-it-never-happens-again/

(https://www.cnet.com/news/how-pakistan-knocked-youtubeoffline-and-how-to-make-sure-it-never-happens-again/)

Note

Some of the IP address manipulation you will do in this assignment will be very complicated. I highly

recommed that you get familiar with the ipaddr python library (from Google). Documentation is

limited, but the source code (available here: https://github.com/google/ipaddrpy/blob/master/ipaddr.py

(https://github.com/google/ipaddr-py/blob/master/ipaddr.py)) will show

you what classes and methods it makes available. Use this instead of reinventing the wheel and

implementing your own library/functions!

IV. Team Information

Fill in your team information in this cell.

Group ID: XX

Group members: AAA, BBB, CCC, DDD, EEE

V. Task 1: Parsing BGP update messages [30 points]

Goal: Your first task is to parse BGP updates received by BGP routers.

Data:

BGP updates are archived in a MRT (Multi-threaded Routing Toolkit) binary format.

The BGP updates that you will use are in the ~/Desktop/assignment-

3/archive.routeviews.org/bgpdata/2008.02/UPDATES folder.

The filenames are formatted as updates.<YYYY><MM><DD>.<HH><MM>.bz2 where YYYY is

the 4-digit year, MM is the 2-digit month, DD is the 2-digit day, HH is the 2-digit hour, and MM

is the 2-digit minute.

Each of these MRT files contains multiple MRT records. Each MRT record contains a dump of

the BGP messages received by the router. These include all the paths announced and

withdrawn by neighboring routers.

The data provided is for the week of Feb 19-25, 2008.

Resources:

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 4/27

You can read more about the MRT format specs here: https://tools.ietf.org/html/rfc6396

(https://tools.ietf.org/html/rfc6396)

You can see an example of how to parse MRT files using pybgpdump here:

https://github.com/alexchap/Albatros-Project/tree/master/testing/tools/mdfmt/pybgpdumpread-only/samples

(https://github.com/alexchap/AlbatrosProject/tree/master/testing/tools/mdfmt/pybgpdump-read-only/samples)

Place your imports in the following cell. Remember your code will be executed on the exact version

of the VM that I supplied, so do not rely on things that you just installed.

In:

You will first populate the code in the following class called ParseUpdates which will handle all

functions related to reading and parsing an MRT file.

The __init__ method, which initializaed all the public attributes of the class, has been

written for you.

A blank template for each method is provided in the following cell. It is here just to make sure

that we don't have any errors while testing. You will overload these methods in subsequent

cells. Do not populate them here.

from pybgpdump import BGPDump

from dpkt import bgp

import ipaddr

import socket

import time

import sys

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 5/27

In?[?]:

Step 1: Opening and iterating through an MRT file (5 points)

The first method you will write/overload in the ParseUpdates class is parse_updates . This

function will be called any time we want to start parsing the file passed while initializing the

ParseUpdates object.

Name: parse_updates

Arguments: None

Logic:

You will create a dump of the MRT file using the BGPDump method from the pybgpdump

library.

You will then iterate through each update in each BGP message of each MRT record in the

dump to figure out if the record is an route announcement or a route withdrawal. You might find

class ParseUpdates:

"""ParseUpdates will handle all functions related to parsing an MRT file


Attributes:

filename (str): The name of the file that this ParseUpdate object is

announcements (dict of lists): Keyed by the MRT header timestamp.

Contains list of all route announceme

withdrawals (dict of lists): Keyed by the MRT header timestamp.

Contains list of all route withdrawals

n_announcements (int): The number of routes announced by BGP message

n_withdrawals (int): The number of routes withdrawn by BGP messages

time_to_parse (int): The time taken to parse the updates contained i

start_time (int): The timestamp of the first update seen in this fil

end_time (int): The timestamp of the last update seen in this file.

"""


def __init__(self, filename):

self.filename = filename

self.announcements, self.withdrawals = {}, {}

self.n_announcements, self.n_withdrawals = 0, 0

self.time_to_parse, self.start_time, self.end_time = 0, 0, 0


def parse_updates(self):

return


def __parse_announcement_update(self, mrt_header, bgp_header, bgp_messag

self.n_announcements += 1

return


def __parse_withdrawal_update(self, mrt_header, bgp_header, bgp_message,

self.n_withdrawals += 1

return


def get_next_updates(self):

return

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 6/27

this example useful: https://github.com/alexchap/AlbatrosProject/blob/master/testing/tools/mdfmt/pybgpdump-read-only/samples/simple.py

(https://github.com/alexchap/Albatros-Project/blob/master/testing/tools/mdfmt/pybgpdumpread-only/samples/simple.py).

Some things to know about the files you are parsing:

A single MRT file can have multiple MRT records, each with its own MRT header.

A single MRT record can have multiple BGP messages, each with its own BGP header.

A single BGP message can have multiple updates -- i.e., route announcements and route

withdrawals.

If the update is an announcement, then you should call the

__parse_announcement_update method.

If the update is a withdrawal, then you should call the __parse_withdrawal_update

method.

You should record how long it takes to parse the entire file in the time_to_parse attribute.

Returns: True if the file was successfully parsed. False if an exception occurred. Make sure to

print the exception after you catch it.

Testing function: You may use the testing method task_1_step_1_test to check if your

parse_updates method is working as expected.

In:

The task_1_step_1_test method should print:

the number of announcement and withdrawal records seen by the parse_updates method.

the time taken to parse all records in an MRT file.

Output: For the file updates.20080219.0015.bz2 , this is what your output should be.

Time taken to parse all records: 1 seconds

Routes announced: 74851 | Routes withdrawn: 8393

In:

Step 2: Parsing announcement updates (10 points)

The next method that you will write/overload in the ParseUpdates class is

__parse_announcement_update .

Name: __parse_announcement_update

class ParseUpdates(ParseUpdates):

def parse_updates(self):

return True

def task_1_step_1_test():

pu = ParseUpdates(filename="./archive.routeviews.org/bgpdata/2008.02/UPD

pu.parse_updates()

print("Time taken to parse all records: %d second(s)" % pu.time_to_parse

print("Routes announced: %d | Routes withdrawn: %d" % (pu.n_announcement

task_1_step_1_test()

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 7/27

Arguments:

mrt_header : This is the header of the MRT record containing the route announcement.

bgp_header : This is the header of the BGP message containing the route announcement.

bgp_message : This is the BGP message containing the route announcement.

announcement : This is the actual announcement in the BGP message.

Logic:

You will need to extract the timestamp of the message. You can get this by looking in the MRT

header.

You will need to extract the CIDR IP address block being updated by the BGP message. You

can get this from the actual announcement. Note: Use the socket.inet_ntoa method to

convert binary prefix into a readable IP address. You might find it helpful to convert the IP

address block into an IPv4Network format (from the ipaddr library. You can see the

methods available through the ipaddr library here: https://github.com/google/ipaddrpy/blob/master/ipaddr.py

(https://github.com/google/ipaddr-py/blob/master/ipaddr.py) and look

at how to use some of these on the wiki here: https://github.com/google/ipaddrpy/blob/master/wiki/ExampleUsage.wiki

(https://github.com/google/ipaddrpy/blob/master/wiki/ExampleUsage.wiki).

You will need to extract the source AS of the BGP message. You can get this by looking in the

BGP header.

You will need to extract the AS path advertised. You can get this by looking in the attributes of

the BGP header.

You will need to extract the IP address of the next hop router. You can get this by looking in the

attributes of the BGP message. You will need to convert this from an int representation into a

standard IP string format.

You will create a dictionary update which has the following keys populated by the data you

just extracted: timestamp , destination_block (this is the advertised CIDR IP address

block being updated), next_hop , source_as , and as_path .

Update the announcements attribute with this new record. Remember: announcements is

a dictionary of lists keyed by timestamp . There will be multiple messages for a single

timestamp, so make sure that you aren't overwriting any existing entries when you should be

appending to the already existing entries instead.

Returns: True if the announcement was successfully parsed. False if an exception occurred.

Make sure to print the exception after you catch it.

Testing function: You may use the testing method task_1_step_2_test to check if your

__parse_announcement_update method is working as expected.

Resources:

You may borrow code from the MRT parser shown here: https://github.com/alexchap/AlbatrosProject/blob/master/testing/tools/mdfmt/pybgpdump-read-only/samples/route_btoa.py

(https://github.com/alexchap/Albatros-Project/blob/master/testing/tools/mdfmt/pybgpdumpread-only/samples/route_btoa.py)

You might find the dir(object) instruction useful to see what attributes are available in

mrt_header , bgp_header , and bgp_message . Note: Some of these will be in binary --

but you really don't need these.

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 8/27

An explanation of how to parse MRT files using pybgpdump from its author:

https://jon.oberheide.org/blog/2009/03/25/dpkt-tutorial-4-as-paths-from-mrt-bgp/

(https://jon.oberheide.org/blog/2009/03/25/dpkt-tutorial-4-as-paths-from-mrt-bgp/)

In:

The task_1_step_2_test method should print:

the number of unique announcement timestamps.

the number of times that the __parse_announcement_record method was called.

the total number of announcements processed successfully.

the time taken to parse all records.

Output: For the file updates.20080219.0015.bz2 , this is what your output should be.

Number of unique announcement timestamps: 801

Number of times method was called: 74851

Number of announcements processed successfully: 74851

Time taken to parse all records: 4 second(s)

In:

Step 3: Parsing withdrawal updates (10 points)

The next method that you will write/overload in the ParseUpdates class is

__parse_withdrawal_update .

Name: __parse_withdrawal_update

Arguments:

mrt_header : This is the header of the MRT record containing the route withdrawal.

bgp_header : This is the header of the BGP message containing the route withdrawal.

bgp_message : This is the BGP message containing the route withdrawal.

withdrawal : This is the actual withdrawal in the BGP message.

class ParseUpdates(ParseUpdates):

def __parse_announcement_update(self, mrt_header, bgp_header, bgp_messag

self.n_announcements += 1

return True

def task_1_step_2_test():

pu = ParseUpdates(filename="./archive.routeviews.org/bgpdata/2008.02/UPD

pu.parse_updates()

print("Number of unique announcement timestamps: %d" % len(pu.announceme

print("Number of times method was called: %d " % pu.n_announcements)

valid_announcements = 0

for timestamp in pu.announcements.keys():

valid_announcements += len(pu.announcements[timestamp])

print("Number of announcements processed successfully: %d" % valid_annou

print("Time taken to parse all records: %d second(s)" % pu.time_to_parse

task_1_step_2_test()

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 9/27

Logic:

You will need to extract the timestamp of the message. You can get this by looking in the MRT

header.

You will need to extract the CIDR IP address block being updated by the BGP message. You

can get this from the actual announcement. Note: Use the socket.inet_ntoa method to

convert binary prefix into a readable IP address. You might find it helpful to convert the IP

address block into an IPv4Network format (from the ipaddr library. You can see the

methods available through the ipaddr library here: https://github.com/google/ipaddrpy/blob/master/ipaddr.py

(https://github.com/google/ipaddr-py/blob/master/ipaddr.py) and look

at how to use some of these on the wiki here: https://github.com/google/ipaddrpy/blob/master/wiki/ExampleUsage.wiki

(https://github.com/google/ipaddrpy/blob/master/wiki/ExampleUsage.wiki).

You will need to extract the source AS of the BGP message. You can get this by looking in the

BGP header.

You will create a dictionary update which has the following keys populated by the data you

just extracted: timestamp , destination_block (this is the advertised CIDR IP address

block being updated), and source_as .

Update the withdrawals attribute with this new record. Remember: withdrawals is a

dictionary of lists keyed by timestamp . There will be multiple messages for a single

timestamp, so make sure that you aren't overwriting any existing entries when you should be

appending to the already existing entries instead.

Returns: True if the announcement was successfully parsed. False if an exception occurred.

Make sure to print the exception after you catch it.

Testing function: You may use the testing method task_1_step_3_test to check if your

__parse_withdrawal_update method is working as expected.

Resources:

You may borrow code from the MRT parser shown here: https://github.com/alexchap/AlbatrosProject/blob/master/testing/tools/mdfmt/pybgpdump-read-only/samples/route_btoa.py

(https://github.com/alexchap/Albatros-Project/blob/master/testing/tools/mdfmt/pybgpdumpread-only/samples/route_btoa.py)

You might find the dir(object) instruction useful to see what attributes are available in

mrt_header , bgp_header , and bgp_message . Note: Some of these will be in binary --

but you really don't need these.

An explanation of how to parse MRT files using pybgpdump from its author:

https://jon.oberheide.org/blog/2009/03/25/dpkt-tutorial-4-as-paths-from-mrt-bgp/

(https://jon.oberheide.org/blog/2009/03/25/dpkt-tutorial-4-as-paths-from-mrt-bgp/)

In:

The task_1_step_3_test method should print:

the number of unique withdrawal timestamps.

class ParseUpdates(ParseUpdates):

def __parse_withdrawal_update(self, mrt_header, bgp_header, bgp_message,

self.n_withdrawals += 1

return True

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 10/27

the number of times that the __parse_withdrawal_record method was called.

the total number of withdrawals processed successfully.

the time taken to parse all records.

Output: For the file updates.20080219.0015.bz2 , this is what your output should be.

Number of unique withdrawal timestamps: 685

Number of times method was called: 8393

Number of withdrawal processed successfully: 8393

Time taken to parse all records: 4 second(s)

In:

Step 4: Streaming BGP updates (5 points)

The next method that you will write/overload in the ParseUpdates class is

get_next_updates . This method will allow us to stream the BGP update messages from our

objects. Basically we'll end up with a method that we can call anytime we want to know the next

batch of updates a router would receive from its neighbors.

Name: get_next_updates

Arguments: None

Logic:

You will sort the unique keys (which are timestamps) of the announcements and

withdrawals attributes.

You will loop through the sorted keys and yield any announcements and withdrawals

associated with those keys in the following format: {"timestamp": <timestamp>,

"announcements": <list of announcements>, "withdrawals": <list of

withdrawals>} .

When there are no more updates to yield, return {"timestamp": None,

"announcements": None, "withdrawals": None} .

Example: Lets say we had the following announcements and withdrawals after parsing all the

updates.

announcements = {timestamp_0: [a_0, a_1, a_2], timestamp_2: [a_3]}

def task_1_step_3_test():

pu = ParseUpdates(filename="./archive.routeviews.org/bgpdata/2008.02/UPD

pu.parse_updates()

print("Number of unique withdrawal timestamps: %d" % len(pu.withdrawals.

print("Number of times method was called: %d " % pu.n_withdrawals)

valid_withdrawals = 0

for timestamp in pu.withdrawals.keys():

valid_withdrawals += len(pu.withdrawals[timestamp])

print("Number of withdrawal processed successfully: %d" % valid_withdraw

print("Time taken to parse all records: %d second(s)" % pu.time_to_parse

task_1_step_3_test()

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 11/27

withdrawals = {timestamp_0: [w_0, w_1], timestamp_1: [w_2]}

where timestamp_0 < timestamp_1 < timestamp_2 .

The first time you call the function it needs to return all the announcement and withdrawal updates

that came in at timestamp_0 -- i.e., {"timestamp": timestamp_0, "announcements":

[a_0, a_1, a_2], "withdrawals": [w_0, w_1]} . The next time you call it, it should return

all the updates that came in at timestamp_1 -- i.e., {"timestamp": timestamp_1,

"announcements": None, "withdrawals": w_2} . The third time you call it, it should return

all the updates that came in at timestamp_2 -- i.e., {"timestamp": timestamp_2,

"announcements": a_3, "withdrawals": None} . Now there are no more records to return.

If we reach this point and the function is called again, it needs to return {"timestamp": None,

"announcements": None, "withdrawals": None} .

Testing function: You may use the testing method task_1_step_4_test to check if your

__get_next_updates method is working as expected.

Resources:

If you are not familiar with how yield works or what generators are, you might want to read

this: https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do

(https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do)

In:

The task_1_step_4_test method should print:

the all the updates that were received in each of the unique timestamps seen in this MRT file.

Output: (a snippet from the end of the print) For the file updates.20080219.0015.bz2 , this is

what your output should be.

****Timestamp: 1203381003****

At timestamp 1203381003, we had: 30 announcements and 5 withdrawals

****Timestamp: 1203381004****

At timestamp 1203381004, we had: 9 announcements and 2 withdrawals

*** No more updates in file: ./archive.routeviews.org/bgpdata/2008.0

2/UPDATES/updates.20080219.0015.bz2 ***

Note: You can remove the comments around the looped print statements to actually see these

updates as they come in.

class ParseUpdates(ParseUpdates):

def get_next_updates(self):

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 12/27

In:

V. Task 2: Building a simple routing table using your BGP

update stream [30 points]

Goal: Build a simple routing table.

The ParseUpdates class and its get_next_updates method that you just wrote will provide

you with simplified BGP update messages that you will use to populate entries in your routing table.

The routing table you will end up building will be something that will actually work in the real world --

it won't allow you to apply the super complicated policies that ASes apply these days, but it will help

you get packets to where they need to go!

You will populate the code in the following class called RoutingTable which will handle all

functions related to handling our simplified BGP update messages.

The __init__ method, which initializes all the public attributes of the class, has been written

for you.

A blank template for each method is provided in the following cell. It is here just to make sure

that we don't have any errors while testing. You will overload these methods in subsequent

cells. Do not populate them here.

def task_1_step_4_test():

pu = ParseUpdates(filename="./archive.routeviews.org/bgpdata/2008.02/UPD

pu.parse_updates()

updates = pu.get_next_updates()

while True:

next_updates = updates.next()

try:

n_announcements = len(next_updates["announcements"])

#for announcement in next_updates["announcements"]:

# print announcement

except TypeError:

n_announcements = 0

try:

n_withdrawals = len(next_updates["withdrawals"])

#for withdrawal in next_updates["withdrawals"]:

# print withdrawal

except TypeError:

n_withdrawals = 0

try:

timestamp = next_updates["timestamp"]

print("\n****Timestamp: %d****" % next_updates["timestamp"])

print ("At timestamp %d, we had: %d announcements and %d withdra


except Exception:

print("\n\n*** No more updates in file: %s ***" % pu.filename)

break


task_1_step_4_test()

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 13/27

In?[?]:

Step 1: Handle incoming route announcements (5 points)

The first method you will write/overload in the RoutingTable class is apply_announcement .

This function will be called any time we want update our routing table with a new announcement

message.

Name: apply_announcement

Arguments:

announcement (dict): This contains entries for timestamp , source_as , next_hop ,

as_path , and destination_block .

Logic:

Update the total_updates_received attribute.

Update the time_of_earliest_update and time_of_latest_update attributes.

Check if entry an already exists in our routing table for destination block advertised by

announcement .

If an entry exists, you will check to see if the path advertised by announcement is shorter

than the path available through the current entry. If it is, then you will update the corresponding

class RoutingTable:

"""RoutingTable will handle all functions related to handling simplified


Attributes:

routing_table (dict): All the entries in the routing table. Keyed by

time_of_earliest_update (int): The timestamp of the first update see

time_of_latest_update (int): The timestamp of the last update seen b

total_updates_received (int): The total number of BGP updates ever s

total_paths_changed (int): The total number of paths to a destinatio

"""

def __init__(self):

self.routing_table = {}

self.time_of_earliest_update, self.time_of_latest_update = sys.maxin

self.total_updates_received = 0

self.total_paths_changed = 0

def apply_announcement(self, update):

return


def apply_withdrawal(self, update):

return


def find_path_to_destination(self, destination):

return


def measure_reachability(self):

return


def collapse_routing_table(self):

return

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 14/27

entry in the routing_table attribute and update the total_paths_changed attribute.

If no entry exists, create a new entry in the routing_table attribute for the destination block

advertised by announcement .

Routing table format: The routing table will be stored as a dictionary of dictionaries in the

routing_table attribute. The dictionary will be keyed by the CIDR IP block. Each value is a

dictionary containing source_as , timestamp , as_path , and next_hop entries.

Returns: True if no exceptions occurred. False if an exception occurred. Make sure to print the

exception after you catch it.

Testing function: You may use the testing method task_2_step_1_test to check if your

apply_announcement method is working as expected.

In:

The task_2_step_1_test method should print:

The number of entries in the routing table and all the integer attributes of the table.

Output: For the file updates.20080219.0015.bz2 , this is what your output should be.

Number of routing table entries: 5547

First update in table was received at: 1203380111 | Last update in t

able was received at: 1203381004

Total number of updates received: 70501 | Total number of path chang

es: 2394

class RoutingTable(RoutingTable):

def apply_announcement(self, announcement):

return True

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 15/27

In?[?]:

Step 2: Handle incoming route withdrawals (5 points)

The next method you will write/overload in the RoutingTable class is apply_withdrawal .

This function will be called any time we want update our routing table with a new withdrawal

message.

Name: apply_withdrawal

Arguments:

withdrawal (dict): This contains entries for timestamp , source_as , and

destination_block .

Logic:

Update the total_updates_received attribute.

Update the time_of_earliest_update and time_of_latest_update attributes.

Check if entry an already exists in our routing table for destination block advertised by

withdrawal .

If an entry exists, you will check to see if the source of the update is the same as the source of

the current entry. If it is, then you will delete the corresponding entry in the routing_table

attribute and update the total_paths_changed attribute.

If no entry exists (with the same source), you can ignore the update.

Returns: True if no exceptions occurred. False if an exception occurred. Make sure to print the

exception after you catch it.

def task_2_step_1_test():

pu = ParseUpdates(filename="./archive.routeviews.org/bgpdata/2008.02/UPD

rt = RoutingTable()

pu.parse_updates()

updates = pu.get_next_updates()

while True:

next_updates = updates.next()

try:

n_announcements = len(next_updates["announcements"])

except TypeError:

n_announcements = 0

if next_updates["timestamp"] == None:

break

for i in range(0, n_announcements):

rt.apply_announcement(next_updates["announcements"][i])

print("Number of routing table entries: %d" % len(rt.routing_table.keys(

print("First update in table was received at: %d | Last update in table


print("Total number of updates received: %d | Total number of path chang

task_2_step_1_test()

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 16/27

Testing function: You may use the testing method task_2_step_2_test to check if your

apply_withdrawal method is working as expected.

In:

The task_2_step_2_test method should print:

The number of entries in the routing table and all the integer attributes of the table.

Output: For the file updates.20080219.0015.bz2 , this is what your output should be.

Number of routing table entries: 5509

First update in table was received at: 1203380111 | Last update in t

able was received at: 1203381004

Total number of updates received: 79834 | Total number of path chang

es: 3720

In:

class RoutingTable(RoutingTable):

def apply_withdrawal(self, withdrawal):

return True

def task_2_step_2_test():

pu = ParseUpdates(filename="./archive.routeviews.org/bgpdata/2008.02/UPD

rt = RoutingTable()

pu.parse_updates()

updates = pu.get_next_updates()

while True:

next_updates = updates.next()

try:

n_announcements = len(next_updates["announcements"])

except TypeError:

n_announcements = 0

try:

n_withdrawals = len(next_updates["withdrawals"])

except TypeError:

n_withdrawals = 0

if next_updates["timestamp"] == None:

break

for i in range(0, n_announcements):

rt.apply_announcement(next_updates["announcements"][i])

for i in range(0, n_withdrawals):

rt.apply_withdrawal(next_updates["withdrawals"][i])


print("Number of routing table entries: %d" % len(rt.routing_table.keys(

print("First update in table was received at: %d | Last update in table


print("Total number of updates received: %d | Total number of path chang

task_2_step_2_test()

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 17/27

Step 3: Measure reachability (10 points)

The next method you will write/overload in the RoutingTable class is

measure_reachability . This function will report the fraction of IP addresses that are reachable

by the router with its current routing table.

Name: measure_reachability

Arguments: None

Logic:

Find CIDR blocks in your routing table that can be collapsed into a single CIDR block. For

example: 100.0.0.0/24 and 10.0.0.0/16 are two different entries that can both reach

10.0.0.0-255 .

Collapse these blocks (do not modify your routing table while doing so!)

Count how many unique IP address are contained in the collapsed CIDR blocks.

Returns: If no exceptions occur, the method returns the fraction of all IP addresses reachable by

your current routing table. Returns None otherwise.

Testing function: You may use the testing method task_2_step_3_test to check if your

measure_reachability method is working as expected.

2

32

In?[?]:

The task_2_step_3_test method should print:

The fraction of the IPv4 addresses that are reachable by the current routing table.

Output: For the file updates.20080219.0015.bz2 , this is what your output should be.

Number of routing table entries: 5509

First update in table was received at: 1203380111 | Last update in t

able was received at: 1203381004

Total number of updates received: 79834 | Total number of path chang

es: 3720

Percentage of IPv4 addresses reachable with our routing table: 1.003

39069031%

class RoutingTable(RoutingTable):

def measure_reachability(self):

return

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 18/27

In?[?]:

Step 4: Find routes (5 points)

The next method you will write/overload in the RoutingTable class is

find_path_to_destination . This function figure out what route an incoming packet should

take to reach its destination ip address. If there are multiple paths that are available, it will return

them all in order of decreasing CIDR prefix.

Name: find_path_to_destination

Arguments: destination_ip_address (str): The destination IP address to which the packet

must be routed.

Logic: You will implement "longest prefix match" routing. Read this for more about longest-prefix

matching: https://en.wikipedia.org/wiki/Longest_prefix_match

(https://en.wikipedia.org/wiki/Longest_prefix_match).

Find all paths that are available to a destination IP.

Sort them in order of prefix length, so that the longest prefix is the first entry in the list.

Returns:

def task_2_step_3_test():

pu = ParseUpdates(filename="./archive.routeviews.org/bgpdata/2008.02/UPD

rt = RoutingTable()

pu.parse_updates()

updates = pu.get_next_updates()

while True:

next_updates = updates.next()

try:

n_announcements = len(next_updates["announcements"])

except TypeError:

n_announcements = 0

try:

n_withdrawals = len(next_updates["withdrawals"])

except TypeError:

n_withdrawals = 0

if next_updates["timestamp"] == None:

break

for i in range(0, n_announcements):

rt.apply_announcement(next_updates["announcements"][i])

for i in range(0, n_withdrawals):

rt.apply_withdrawal(next_updates["withdrawals"][i])


print("Number of routing table entries: %d" % len(rt.routing_table.keys(

print("First update in table was received at: %d | Last update in table


print("Total number of updates received: %d | Total number of path chang

reachability = rt.measure_reachability()

print("Percentage of IPv4 addresses reachable with our routing table: %s

task_2_step_3_test()

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 19/27

A list of {"as_path": <as_path>, "next_hop": <next_hop>, "prefix_len": <prefix

len>, "source_as": <source_as>} dictionaries sorted in decreasing order of the prefix

length of the CIDR block that the corresponding routing table entry was for. Return [{"as_path":

None, "next_hop": None, "prefix_len": None, "source_as": None}] if there are

exceptions.

Testing function: You may use the testing method task_2_step_4_test to check if your

find_path_to_destination method is working as expected.

In:

The task_2_step_4_test method should print:

The AS-level paths and next_hop entries for a sequence of IP destinations.

Output: For the file updates.20080219.0015.bz2 , this is what your output should look like.

Paths available to destination: 8.8.8.8

0 8.8.8.8 {'prefix_len': None, 'next_hop': None, 'as_path': None, 's

ource_as': None}

Paths available to destination: 125.161.0.1

0 125.161.0.1 {'prefix_len': 16, 'next_hop': IPv4Address('134.222.8

7.3'), 'as_path': [286, 3491, 24077, 7713, 17974], 'source_as': 286}

1 125.161.0.1 {'prefix_len': 18, 'next_hop': IPv4Address('134.222.8

7.3'), 'as_path': [286, 6762, 7473, 7713, 17974], 'source_as': 286}

Paths available to destination: 190.44.64.1

0 190.44.64.1 {'prefix_len': 16, 'next_hop': IPv4Address('164.128.3

2.11'), 'as_path': [3303, 3356, 3549, 22047], 'source_as': 3303}

1 190.44.64.1 {'prefix_len': 19, 'next_hop': IPv4Address('164.128.3

2.11'), 'as_path': [3303, 3356, 3549, 22047], 'source_as': 3303}

class RoutingTable(RoutingTable):

def find_path_to_destination(self, destination):

return

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 20/27

In?[?]:

Step 5: Collapse routing table [simple version: 5 points] or [more realistic

version: 10 points]

The next method you will write/overload in the RoutingTable class is

collapse_routing_table . This function will check to see if there are redundant entries in

routing_table and collapse them into a single entry.

Name: collapse_routing_table

Arguments: None

Logic:

For each entry in routing_table , check to see if there is another entry whose: (1)

destination CIDR IP block completely contains it and (2) has the same source_as ,

as_path , and next_hop attributes. If such a match exists, then delete the one with the

longest prefix.

If you merge records, update the timestamp attribute to the max of all the entries being

merged.

def task_2_step_4_test():

pu = ParseUpdates(filename="./archive.routeviews.org/bgpdata/2008.02/UPD

rt = RoutingTable()

pu.parse_updates()

updates = pu.get_next_updates()

while True:

next_updates = updates.next()

try:

n_announcements = len(next_updates["announcements"])

except TypeError:

n_announcements = 0

try:

n_withdrawals = len(next_updates["withdrawals"])

except TypeError:

n_withdrawals = 0

if next_updates["timestamp"] == None:

break

for i in range(0, n_announcements):

rt.apply_announcement(next_updates["announcements"][i])

for i in range(0, n_withdrawals):

rt.apply_withdrawal(next_updates["withdrawals"][i])

for destination in ["8.8.8.8", "125.161.0.1", "190.44.64.1"]:

paths = rt.find_path_to_destination(destination)

print("Paths available to destination: %s" % destination)

for idx, path in enumerate(paths):

print idx, destination, path


task_2_step_4_test()

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 21/27

Bonus (+5 points): In a real router you would also have to do CIDR block merging (which we

went over in class), which you may implement for a bonus of 5 points. Set is_bonus=True if

you want us to evaluate your attempt at the bonus question. If your method fails, you will

not score any points for this step.

Returns: True if no exceptions occurred. False if an exception occurred. Make sure to print the

exception after you catch it.

Important: Doing pairwise comparisons is prohibitively expensive and will likely run for a long time.

Think of more clever ways to collapse entries or rules that can filter out a large number of

comparisons. I was able to find a way to do this at the rate of 47 seconds/file on the VM using some

functions from the ipaddr library. Can you find a way to do this faster?

Testing function: You may use the testing method task_2_step_5_test to check if your

collapse_routing_table method is working as expected.

In:

The task_2_step_5_test method should print:

The number of entries in the routing table prior to the collapse call.

The routes to a set of destination IP addresses prior to the collapse call.

The number of entries in the routing table after the collapse call.

The routes to a set of destination IP addresses after the collapse call.

Output: For the file updates.20080219.0015.bz2 , this is what your output should look like.

class RoutingTable(RoutingTable):

def collapse_routing_table(self):


is_bonus = False

if is_bonus:

print("*** bonus attempted ***")


return

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 22/27

[Pre] | Number of routing table entries: 5509

[Pre] | Percentage of IPv4 addresses reachable with our routing tabl

e: 1.00339069031%

[Pre] | Paths available to destination: 8.8.8.8

0 8.8.8.8 {'prefix_len': None, 'next_hop': None, 'as_path': None, 's

ource_as': None}

[Pre] | Paths available to destination: 125.161.0.1

0 125.161.0.1 {'prefix_len': 16, 'next_hop': IPv4Address('134.222.8

7.3'), 'as_path': [286, 3491, 24077, 7713, 17974], 'source_as': 286}

1 125.161.0.1 {'prefix_len': 18, 'next_hop': IPv4Address('134.222.8

7.3'), 'as_path': [286, 6762, 7473, 7713, 17974], 'source_as': 286}

[Pre] | Paths available to destination: 190.44.64.1

0 190.44.64.1 {'prefix_len': 16, 'next_hop': IPv4Address('164.128.3

2.11'), 'as_path': [3303, 3356, 3549, 22047], 'source_as': 3303}

1 190.44.64.1 {'prefix_len': 19, 'next_hop': IPv4Address('164.128.3

2.11'), 'as_path': [3303, 3356, 3549, 22047], 'source_as': 3303}

[Post] | Number of routing table entries: 3364

[Post] | Percentage of IPv4 addresses reachable with our routing tab

le: 1.00339069031%

[Post] | Paths available to destination: 8.8.8.8

0 8.8.8.8 {'prefix_len': None, 'next_hop': None, 'as_path': None, 's

ource_as': None}

[Post] | Paths available to destination: 125.161.0.1

0 125.161.0.1 {'prefix_len': 14, 'next_hop': IPv4Address('134.222.8

7.3'), 'as_path': [286, 3491, 24399, 7713, 17974], 'source_as': 286}

[Post] | Paths available to destination: 190.44.64.1

0 190.44.64.1 {'prefix_len': 14, 'next_hop': IPv4Address('164.128.3

2.11'), 'as_path': [3303, 3356, 3549, 22047], 'source_as': 3303}

Notice several things in the output above.

The number of routing table entries shrunk from 5509 to 3364 (~40% space savings).

The IPv4 address reachability stayed the same.

The paths taken to reach our test destinations stayed the same. The prefix_len attribute

shows that the keys of the routing table collapsed into more general (larger) CIDR blocks.

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 23/27

In?[?]:

VI. Task 3: Identifying suspicious BGP announcements [30

points]

Goal: To build a system which identifies BGP announcements which might be associated with route

hijack attempts.

You now have a system to parse BGP updates and update a real routing table! While this is pretty

awesome, the bad news is that a router using your table might be susceptible to BGP hijacks like

the one carried out on YouTube by Pakistan Telecom (see: https://www.cnet.com/news/howdef

task_2_step_5_test():

pu = ParseUpdates(filename="./archive.routeviews.org/bgpdata/2008.02/UPD

rt = RoutingTable()

pu.parse_updates()

updates = pu.get_next_updates()

while True:

next_updates = updates.next()

try:

n_announcements = len(next_updates["announcements"])

except TypeError:

n_announcements = 0

try:

n_withdrawals = len(next_updates["withdrawals"])

except TypeError:

n_withdrawals = 0

if next_updates["timestamp"] == None:

break

for i in range(0, n_announcements):

rt.apply_announcement(next_updates["announcements"][i])

for i in range(0, n_withdrawals):

rt.apply_withdrawal(next_updates["withdrawals"][i])

print("[Pre] | Number of routing table entries: %d" % len(rt.routing_tab

reachability = rt.measure_reachability()

print("[Pre] | Percentage of IPv4 addresses reachable with our routing t

for destination in ["208.65.153.0", "125.161.0.1", "190.44.64.1"]:

paths = rt.find_path_to_destination(destination)

print("[Pre] | Paths available to destination: %s" % destination)

for idx, path in enumerate(paths):

print idx, destination, path

rt.collapse_routing_table()

print("[Post] | Number of routing table entries: %d" % len(rt.routing_ta

reachability = rt.measure_reachability()

print("[Post] | Percentage of IPv4 addresses reachable with our routing

for destination in ["208.65.153.0", "125.161.0.1", "190.44.64.1"]:

paths = rt.find_path_to_destination(destination)

print("[Post] | Paths available to destination: %s" % destination)

for idx, path in enumerate(paths):

print idx, destination, path


task_2_step_5_test()

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 24/27

pakistan-knocked-youtube-offline-and-how-to-make-sure-it-never-happens-again/)

(https://www.cnet.com/news/how-pakistan-knocked-youtube-offline-and-how-to-make-sure-itnever-happens-again/)).

In this task you will write code to automatically flag suspicious updates. This way a hijack is less

likely to occur.

You will have more flexibility in how you do your work in this task. Each step only has a description

of the inputs to the method and the outputs that should be generated.

In?[?]:

Step 1: Monitoring route updates to specific prefixes (5 points)

In the real world, we'd have a lot more resources than a single 2GB VM and we'd be able to monitor

all route updates to check for a potential hijack. In our case, we're only going to monitor route

updates to the destinations contained in the within specific CIDR blocks. You will write a method

monitor_updates_to_range to do this.

Name: monitor_updates_to_range

Arguments:

rt (RoutingTable): The RoutingTable instance which will be updated.

filelist (list): Contains the MRT filenames from which updates should be added to rt .

monitored_range (ipaddr.IPv4Network): The CIDR range that we will monitor updates for.

Returns: The updated rt object and all the updates (announcements and withdrawals) which

resulted in changes to the routing table.

You will call this function with the following parameters:

rt : A new RoutingTable instance.

filelist :

["./archive.routeviews.org/bgpdata/2008.02/UPDATES/updates.20080222.0208

monitored_range : ipaddr.IPv4Network('208.65.152.0/22')

Output: Print the announcements which resulted in routing table changes.

In?[?]:

Step 2: Identify suspicious updates (10 points)

You will now write a method is_update_suspicious which will flag suspicious BGP route

announcements. The method will replicate much of the functionality of the

monitor_updates_to_range method. The main addition is that it will screen each update

import glob

def monitor_updates_to_range(rt, filelist, monitored_range):

return

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 25/27

announcing a new route to any destination in a specific IP range. If an announcement is suspicious,

it will not apply it to the routing table. We will say that the announcement is suspicious if it satisfies

both the following conditions:

the AS path appears to terminate at an AS which has never advertised a route to addresses in

this range before

it is for a more specific range than any existing entries in the the routing table

Note: The first announcement for a destination address is not suspicious even if it meets the above

criteria.

Important: You will then flag the AS as suspicious and mark any subsequent route announcements

that have them as the final hop in the AS path as suspicious. You should also monitor the paths

advertised by the victim AS (the last hop in the as_path of the entry that would have been

replaced by the suspicious router).

Name: is_update_suspicious

Arguments:

rt (RoutingTable): The RoutingTable instance which will be updated.

filelist (list): Contains the MRT filenames from which updates should be added to rt .

monitored_range (ipaddr.IPv4Network): The CIDR range that we will monitor updates for.

Returns:

The updated rt object.

A list of updates that were marked as suspicious.

A list of updates that came from an AS which made atleast one suspicious update.

A list of updates that came from an AS that was the victim of the suspicious update (i.e., the

destination AS of the route would have been replaced by the suspicious announcement).

You will call this function with the following parameters:

rt : A new RoutingTable instance.

filelist :

["./archive.routeviews.org/bgpdata/2008.02/UPDATES/updates.20080222.0208

"./archive.routeviews.org/bgpdata/2008.02/UPDATES/updates.20080224.1839.b

"./archive.routeviews.org/bgpdata/2008.02/UPDATES/updates.20080224.2009.b

"./archive.routeviews.org/bgpdata/2008.02/UPDATES/updates.20080224.2026.b

"./archive.routeviews.org/bgpdata/2008.02/UPDATES/updates.20080224.2041.b

"./archive.routeviews.org/bgpdata/2008.02/UPDATES/updates.20080224.2056.b

monitored_range : ipaddr.IPv4Network('208.65.152.0/22')

Output: You will print all the announcements in your returned lists, sorted by their timestamp.

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 26/27

If you implement things correctly, you should see announcements which have AS 17557 and AS

36561 as the final hop for the same range of IP addresses. This is a sign of an ongoing hijack

attempt. Your program should have marked AS 17557 as the suspicious AS and AS 36561 as the

victim AS.

In?[?]:

Step 3: Mapping AS numbers to organizations (5 points)

To be able to tell the story of how a BGP hijack happens, it is always useful to know which

organizations are responsible for the attack and which organizations are impacted by it. To do this,

you need to map the AS numbers to organization names. We'll use data obtained from CAIDA to do

this. You will now write a function as_org_mapper that parses the data and returns a dictionary of

all mappings.

Data: A file containing mappings of ASes to organizations is located in the

~/Desktop/assignment-3/caida-as-org-mappings folder. The README file describes the

format in mappings.txt .

Name: as_org_mapper

Arguments:

mapping_path (str): Path to the CAIDA AS to org mapping.

keyed_by_as (bool): True (default) will cause this function to return a dictionary with AS

numbers as keys. False will cause this function to return a dictionary with organization names

as keys.

Returns: A dictionary of AS to organization mappings.

In:

Step 4: Telling the story of a BGP hijack with data (7 points)

You will now use the dictionary returned by your as_org_mapper to make sense of all the

announcements returned by your is_update_suspicious method. Use the cell below to write

code that presents the story of the hijack observed in our data. You should replace all the AS

numbers with organization names and replace timestamps with UTC human readable time.

Sample output:

def monitor_updates_to_range(rt, filelist, monitored_range):

return

def as_org_mapper(mapping_path, keyed_by_as=True):

return

2018/10/10 [CS3640, Assignment 3] Internet Routing

http://localhost:8888/notebooks/Downloads/qqq/%5BCS3640%2C%20Assignment%203%5D%20Internet%20Routing.ipynb 27/27

utc_time_0: route announcement for <ip range> from suspicious as <or

ganization name> : <as path>

victim as was <as organization>

utc_time_1: route announcement for <ip range> from victim as <organi

zation name> : <as path>

utc_time_2: route announcement fom suspicious as <organization name>

: <as path>

victim as was <as organization>

In:

Step 5: Telling the story of a BGP hijack with words (3 points)

Use your own words to explain your data presented above.

Use this cell to explain what is going on in your data presented above

VII. Task 4: Credit reel! [10 points]

You get 10 points just for submitting this assignment with a well written and formatted credit reel!

Use the following cell to:

tell us what references you used to complete this assignment -- e.g., online documentation,

stackoverflow posts, etc.

who helped you IRL or on Piazza.

which team-mates did which parts of the assignment.

Credit reel goes here



版权所有:编程辅导网 2021 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。 站长地图

python代写
微信客服:codinghelp