Objectives
In this project, you are going to build on the first project. You will have a server in the cloud that downloads and saves a web page in memory. You will then have clients connect to the server and retrives this content. This is the overly simplified idea behind a WEB PROXY. The client and server communications MUST use UDP (SOCK_DGRAM) and NOT TCP.
The objectives are:
– Learn to create robust network protocols
– Learn about reliable communication
– How a premitive proxy might work. You can use this to get around sensorship or firewalls.
Server Specifications
The server (we name it anonserver) takes two arguments:
$ anonserver -p <PORT> -s <LOG FILE LOCATION> -w <web page to download>
1.PORT
- The port server listens on.
2.Log file location
- Where you will keep a record of actions.
3.Web page to download
- Which webpage to download and serve.
For example:
$ anonserver -p 30000 -l /tmp/logfile -w www.nytimes.com
You can use python URLLIB2 to download the files. Here is a helpful tutorial: https://docs.python.org/3/howto/urllib2.html
Server’s Functional requirements
Client Specifications
The client (we name it anonclient) takes four arguments:
$ anonclient -s <SERVER-IP> -p <PORT> -l LOGFILE -f <file_to_write_to>
The client takes three arguments:
1.Server IP
- The IP address of the anonserver.
2.PORT
- The port the server listens on.
2.Log file location
- Where you will keep a record of packets you received.
2.File to write to
- Where you will write the retrieved content.
For example:
$ anonclient -s 192.168.2.1 -p 6543 -l LOGFILE -f test.txt
Packet Specification
The payload of each UDP packet sent by server and client MUST start with the following 12-byte header. All fields are in network order (most significant bit first):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Not Used |A|S|F|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Where:
Sequence Number (32 bits): The sequence number of the first data octet in this packet (except when SYN is present). If SYN is present the sequence number is the initial sequence number (randomly choosen).
Acknowledgement Number (32 bits): If the ACK control bit is set, this field contains the value of the next sequence number the sender of the segment is expecting to receive. Once a connection is established this is always sent.
The acknowledgement number is given in the unit of bytes (how many bytes you have sent)
Not Used (29 bits): Must be zero.
A (ACK, 1 bit): Indicates that there the value of Acknowledgment Number field is valid
S (SYN, 1 bit): Synchronize sequence numbers
F (FIN, 1 bit): Finish, No more data from sender
This is the protocol you will implement
The client opens a UDP socket and initiate 3-way handshake to the specified hostname/ip and port. For an explanation of how a three way handshake works, see the next three steps. Essentially, the client and server will exchange three packets with the following flags sets: (1) SYN (2) SYN|ACK (3)ACK. At the end of the handshake, they will have learned each other’s sequence number.
Handshake Step 1: Anonclient sends a UDP packet with the following parameters:
Here is what a sample interaction looks like:
Server Client
| |
| seq=12345, ack=0, SYN |
| <------------------------------------------|
| seq=100, ack=12346, SYN, ACK |
| ----------------------------------------- >|
| seq=12346, ack=101, ACK |
| <----------------------------------------- |####handshake complete, start getting data
|seq=101, ack=12347, ACK,512Byte payload |
| -----------------------------------------> |
| seq=12347, ack=614, ACK |
| <----------------------------------------- |
|seq=614,ack=12348,ACK,512Byte payload |
| ----------------------------------------- >|
| seq=12348, ack=1126, ACK |
| <----------------------------------------- |
|seq=1126, ack=12349,ACK,512Byte payload |
| ----------------------------------------- >|
| seq=12349, ack=1638, ACK |
| <----------------------------------------- |
|seq=1638, ack=12350, FIN, payload=5bytes |
| -----------------------------------------> |
|seq=12350, ack=1643, FIN, ACK |
| <----------------------------------------- |
Additional requirements:
"RECV" <Sequence Number> <Acknowledgement Number> ["ACK"] ["SYN"] ["FIN"]
"SEND" <Sequence Number> <Acknowledgement Number> ["ACK"] ["SYN"] ["FIN"]
def create_packet(**kwargs):
data = struct.pack('!I', s_n) #pack the version
....
data += struct.pack("!c", ack) #pack the ACK
data += struct.pack("!c", syn) #pack the SYN
data += struct.pack("!c", fin) #pack the FIN
....
return data
send_data = create_packet(sequence_number=100, ack_number=0, ack = 'Y', syn = 'N', fin = 'N', payload=data)