In-Class Lab 2 (10 points)
Explore basic client-server communication using netcat (nc) and capture the traffic with tcpdump. Analyze the captured packets to understand the interaction between client and server.
Upon the completion of all activities, have your instructor review your work and track your progress to receive full credit.
Environment
Write your program in VSCode connected to WSL (Ubuntu). If you have not yet set this up, refer to the instructions in lab 1.
Run Server Program
Complete the following server program. Review the code and understand what it does. Run it in the first terminal. Ensure that it is listening on the correct port that you are going to use for the client.
import socket
def main() -> None:
host = "0.0.0.0"
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(5)
print(f"Listening on {host}:{port}")
except Exception as e:
print(f"Failed to set up server: {e}")
return
try:
while True:
conn, addr = s.accept()
with conn:
print(f"Client connected: {addr}")
while True:
data = conn.recv(4096)
if not data:
break
text = data.decode("utf-8")
response = text.upper()
responseBytes = response.encode("utf-8")
conn.sendall(responseBytes)
# capture keyboard interrupt to gracefully shutdown the server
except KeyboardInterrupt:
print("Shutting down server.")
s.close()
if __name__ == "__main__":
main()Verify Server
- Use
ss -tulnpto verify that the server is listening on the expected port. - Use
nc localhost <port>to connect to the server and verify it responds correctly.
What does nc or netcat do?
Client Program
Update the following socket client. Modify it as needed to connect to the server you started in the first terminal. Run it in the second terminal.
import socket
HOST = "127.0.0.1"
PORT = 8000
def main() -> None:
# see https://docs.python.org/3/library/socket.html
# Example -> Echo client program
# Create a TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# TODO: connect to the server
sock.connect((HOST, PORT))
# ask for user input in a loop
while True:
message = input("> ")
if message == "exit":
break
# TODO: encode user input into bytes
# TODO: send the bytes to the server
# TODO: receive the response from the server
# TODO: decode the response into a string
# TODO: print the response
print(f"Not Server Response: {message}")
# TODO: close the connection to the server
if __name__ == "__main__":
main()Capture Traffic
In the third terminal, run tcpdump or tshark to capture the traffic between the client and server. Filter by port number to minimize noise. Run man tcpdump or see lab 1 for the correct command line flags. Observe the packets being exchanged. Save your capture to a file for later analysis.
sudo tcpdump -i any --print -w ... port <port>
sudo tshark -i any -w ... -f "tcp port <port>"- Why do we need
sudoto run these commands? - What does the
-i anyflag do? - What does the
-wflag do?
Analyze Capture
Use Wireshark to open the saved capture file. Analyze the packets exchanged between the client and server. Identify the request and response messages. Note any interesting details about the protocol being used. Reason about how you would distinguish messages from different clients if multiple clients were connected simultaneously.
- Where did the communication begin? Do you see the SYN, SYN-ACK, ACK handshake in the TCP connection setup?
- Where did the communication end? Do you see the FIN, ACK, FIN, ACK handshake in the TCP connection teardown?
- How many bytes were sent in each direction? Identify the packets carrying the actual data.
Instructor Review
To complete the lab, show your instructor the following:
- Packet capture that includes the TCP handshake, client-server communication, and TCP teardown
- The client and server terminal outputs that demonstrate the working client-server interaction
- Your client code with the TODOs completed