├── CN_Proj1_DNS Resolver ├── CN-P1.pdf ├── DNS-request.py ├── report.pdf └── urls.csv ├── CN_Proj2_Telnet Simulator ├── CN-P2.pdf ├── cert.pem ├── client.py ├── commands history.txt ├── key.pem ├── report.pdf ├── server files │ ├── sherek.png │ └── test.txt ├── server.py ├── sherek.png └── test.txt ├── CN_Proj3_DHCP ├── CN-P3.pdf ├── Client.py ├── Server.py ├── backup │ ├── Client.py │ └── Server.py ├── configs.json └── report.pdf └── README.md /CN_Proj1_DNS Resolver/CN-P1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/dab51bd7e31eccae6db50b0d24b48f04d3bd0c55/CN_Proj1_DNS Resolver/CN-P1.pdf -------------------------------------------------------------------------------- /CN_Proj1_DNS Resolver/DNS-request.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | import socket 3 | import sys 4 | import pandas as pd 5 | 6 | # resolved_urls = {url: times that url has resolved, ...} 7 | resloved_urls = {} 8 | # cached_urls = {url: ip, ...} 9 | cached_urls = {} 10 | 11 | def send_request(message, address): 12 | print("sending request to server: ", address) 13 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 14 | try: 15 | sock.sendto(binascii.unhexlify(message), (address, 53)) 16 | data, _ = sock.recvfrom(4096) 17 | finally: 18 | sock.close() 19 | return binascii.hexlify(data).decode("utf-8") 20 | 21 | 22 | def create_message(address): 23 | message = "" 24 | 25 | ID = 43690 # 16-bit identifier (0-65535) # 43690 equals 'aaaa' 26 | message += "{:04x}".format(ID) 27 | 28 | QR = "0" # 1bit Query=0, Response=1 29 | OPCODE = "0000" # 4bit 30 | AA = "0" # 1bit 31 | TC = "0" # 1bit 32 | RD = "1" # 1bit 33 | RA = "0" # 1bit 34 | Z = "000" # 3bit 35 | RCODE = "0000" # 4bit 36 | 37 | query_params = QR + OPCODE + AA + TC + RD + RA + Z + RCODE 38 | query_params = "{:04x}".format(int(query_params, 2)) 39 | message += query_params 40 | 41 | # when we're sending request, we have only Header and Question 42 | QDCOUNT = 1 # Number of questions 4bit 43 | message += "{:04x}".format(QDCOUNT) 44 | 45 | ANCOUNT = 0 # Number of answers 4bit 46 | message += "{:04x}".format(ANCOUNT) 47 | 48 | NSCOUNT = 0 # Number of authority records 4bit 49 | message += "{:04x}".format(NSCOUNT) 50 | 51 | ARCOUNT = 0 # Number of additional records 4bit 52 | message += "{:04x}".format(ARCOUNT) 53 | 54 | addr_parts = address.split(".") 55 | for part in addr_parts: 56 | addr_len = "{:02x}".format(len(part)) 57 | message += addr_len 58 | 59 | addr_part = binascii.hexlify(part.encode()) 60 | message += addr_part.decode() 61 | 62 | # Terminating bit for QNAME 63 | message += "00" 64 | 65 | # Type of request 66 | QTYPE = "0001" # type A 67 | message += QTYPE 68 | 69 | QCLASS = "0001" # IN: internet 70 | message += QCLASS 71 | 72 | return message 73 | 74 | def update_url_request(url): 75 | value = resloved_urls.get(url, "not exist") 76 | if value == "not exist": 77 | value = 1 78 | else: 79 | value += 1 80 | resloved_urls[url] = value 81 | return value 82 | 83 | def hex_to_ip(hex_ip): 84 | ip_decoded = "" 85 | for i in range(len(hex_ip)): 86 | if (i % 2) == 0: 87 | ip_decoded += str(int(hex_ip[i:i+2], 16)) 88 | ip_decoded += "." 89 | i += 1 90 | return ip_decoded[:-1] 91 | 92 | def parse_parts(message, start, parts): 93 | part_start = start + 2 94 | part_len = message[start:part_start] 95 | 96 | if len(part_len) == 0: 97 | return parts 98 | 99 | part_end = part_start + (int(part_len, 16) * 2) 100 | parts.append(message[part_start:part_end]) 101 | 102 | if message[part_end:part_end + 2] == "00" or part_end > len(message): 103 | return parts 104 | else: 105 | return parse_parts(message, part_end, parts) 106 | 107 | 108 | def parse_Question(response): 109 | QUESTION_SECTION_STARTS = 24 110 | question_parts = parse_parts(response, QUESTION_SECTION_STARTS, []) 111 | 112 | QTYPE_STARTS = QUESTION_SECTION_STARTS + (len("".join(question_parts))) + (len(question_parts) * 2) + 2 113 | QCLASS_STARTS = QTYPE_STARTS + 4 114 | QCLASS_ENDS = QCLASS_STARTS + 4 115 | 116 | return QCLASS_ENDS 117 | 118 | def parse_AN_NS_AR(count, server_response, start): 119 | ip = "" 120 | for c in range(count): 121 | if (start < len(server_response)): 122 | TYPE = server_response[start + 4:start + 8] 123 | LENGTH = int(server_response[start + 20:start + 24], 16) 124 | # print("type is:", TYPE) 125 | 126 | if TYPE == "0001": # A 127 | DATA = server_response[start + 24:start + 24 + (LENGTH * 2)] 128 | ip = hex_to_ip(DATA) 129 | start = start + 24 + (LENGTH * 2) 130 | 131 | elif TYPE == "0005" or TYPE == "0002": # CNAME or NS 132 | start = start + 24 + (LENGTH * 2) 133 | 134 | # print(start) 135 | return ip, start 136 | 137 | def find_ip(server_response): 138 | 139 | is_final_ip = False # in order to handle iterative search 140 | 141 | ANCOUNT = server_response[12:16] # number of answers 142 | ANCOUNT = int(ANCOUNT, 16) 143 | 144 | NSCOUNT = server_response[16:20] 145 | NSCOUNT = int(NSCOUNT, 16) 146 | 147 | ARCOUNT = server_response[20:24] 148 | ARCOUNT = int(ARCOUNT, 16) 149 | 150 | # parse Question section 151 | QCLASS_ENDS = parse_Question(server_response) 152 | 153 | if ANCOUNT != 0: # we have multiple answers 154 | # parse Answers section and return IP 155 | ip, _ = parse_AN_NS_AR(ANCOUNT, server_response, QCLASS_ENDS) 156 | is_final_ip = True 157 | return ip, is_final_ip 158 | 159 | else: # there is no Answer section, we should check Authority and Additional sections 160 | print("Searching in another server ...") 161 | # parsing Authority and Additional sections 162 | if NSCOUNT != 0: 163 | _, end_of_NS = parse_AN_NS_AR(NSCOUNT, server_response, QCLASS_ENDS) 164 | else: 165 | end_of_NS = QCLASS_ENDS 166 | 167 | if ARCOUNT != 0: 168 | ip, _ = parse_AN_NS_AR(ARCOUNT, server_response, end_of_NS) 169 | 170 | 171 | return ip, is_final_ip # ip of another server 172 | 173 | 174 | def handle_url(url): 175 | times_requested = update_url_request(url) 176 | 177 | if times_requested <= 3: 178 | message = create_message(url) 179 | print("Request for " + url +" URL :\n" + message + "\n") 180 | # response = send_request(message, "198.41.0.4") 181 | response = send_request(message, "1.1.1.1") 182 | print("Response for " + url +" URL:\n" + response + "\n") 183 | ip, is_final_ip = find_ip(response) 184 | print(ip) 185 | 186 | while not is_final_ip: 187 | response = send_request(message, ip) 188 | ip, is_final_ip = find_ip(response) 189 | print("Returned ip is: " + ip +"\n" + response + "\n") 190 | 191 | # update cache 192 | cached_urls[url] = ip 193 | 194 | else: 195 | print("Searching in cache for " + url + " ...") 196 | ip = cached_urls.get(url) 197 | 198 | print("Requested IP is: " + ip + "\n") 199 | return ip 200 | 201 | 202 | def read_from_csv(csv_file_name): 203 | df = pd.read_csv(csv_file_name) 204 | IPs = [] 205 | for i in range(0, len(df)): 206 | ip = handle_url(str(df.iloc[i,0])) 207 | IPs.append(ip) 208 | 209 | df["IPs"] = IPs 210 | print(df) 211 | df.to_csv('urls.csv') 212 | 213 | 214 | while True: 215 | option = input("Which option do you prefer? \n 1) Enter a URL \n 2) Import URLs from a csv file\n 3) Exit\n") 216 | 217 | if option == "1": 218 | url = input("Enter URL:\n") 219 | handle_url(url) 220 | elif option == "2": 221 | csv_file_name = input("Enter csv file name:\n") 222 | read_from_csv(csv_file_name) 223 | elif option == "3": 224 | exit() 225 | else: 226 | print("Wrong input!") 227 | -------------------------------------------------------------------------------- /CN_Proj1_DNS Resolver/report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/dab51bd7e31eccae6db50b0d24b48f04d3bd0c55/CN_Proj1_DNS Resolver/report.pdf -------------------------------------------------------------------------------- /CN_Proj1_DNS Resolver/urls.csv: -------------------------------------------------------------------------------- 1 | ,urls,IPs 2 | 0,google.com,142.250.186.174 3 | 1,p30download.com,5.144.130.115 4 | -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/CN-P2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/dab51bd7e31eccae6db50b0d24b48f04d3bd0c55/CN_Proj2_Telnet Simulator/CN-P2.pdf -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFTzCCAzegAwIBAgIJALtT92d4jzTgMA0GCSqGSIb3DQEBBQUAMCMxDTALBgNV 3 | BAsTBGNlaXQxEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0yMTA1MjgxNTUyMTVaFw0y 4 | MjA1MjgxNTUyMTVaMCMxDTALBgNVBAsTBGNlaXQxEjAQBgNVBAMTCWxvY2FsaG9z 5 | dDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALOt9IJjmV/NEyjxcM0w 6 | klTtjxNpkO8woaZzcFZo0D9NlKAE7L7k8TTZVLc/8bUijkyRhhW5GGVgI9VMaQx/ 7 | CZXtaYxZ5NkrvAXA0D375s+SHg0cXjungo1h9AgYY2kezmWmbbCTNgOaSZeqVlir 8 | 77If8NiPKa16uI5nVaEVFvrsHP6CD/22mQNQSu6IEFhnkOKi9XXhZ7XGhz+UwkCu 9 | y4OYfARgcLfmwfrvroImXNsZqAwLQgPxjSA8wUC+P/beLQhOoUUSd5EkYmpXU7ov 10 | l+wVhlsa8pTb/9QlrGSx7qUnX3dZoXoRj8VfURxyFBWMMPjTaWaLDasNmwMQdd5d 11 | miapHHtmlKwYtCOU4ZTUE/EqN7gIRzwKqrhg15xN5aQFGrYQfCpa9jE8RAVhHarA 12 | IHL8ZHkaWFrpjwX1lLeSkY855TZkjhRIKMJenp6fg0z84uDRntnEMbrCa59ocmRk 13 | MElJDFWpQskffKw2h3ZMb9fITgGU9CSQoBLaEUEby5vcZHFwNH6ud1jwRKhbFnsI 14 | YaXZGuyXXpKK7kjJIMD4RyVcr/cMkRCeGwPzFmw3x7kFf1U6bqmGgtNXxQZbRFKC 15 | fzHlOwuzg9QuLIa9bx0HlyJViizO2+mpkGtqLIJ9MW2x/3w/OA5dCLsXW19Qd+jK 16 | PMfoX8x0qbLOQE7LH18osjaBAgMBAAGjgYUwgYIwHQYDVR0OBBYEFDXpWbO4s1y+ 17 | iS2bJ0zrCbXRYTqNMFMGA1UdIwRMMEqAFDXpWbO4s1y+iS2bJ0zrCbXRYTqNoSek 18 | JTAjMQ0wCwYDVQQLEwRjZWl0MRIwEAYDVQQDEwlsb2NhbGhvc3SCCQC7U/dneI80 19 | 4DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCDZBYeo6OTjskhZQ+5 20 | quDVT9Xn2Y51RsGftMfTD0F+eFJHOby5a3E0hGddKi3YQ3Aa+bavGSBTo535yLB2 21 | EW4oTKGUM0GbWgerACrTHwlAfjL/QkQUPEpSRidMoU9e8IOnyXzUf9GTPoTO+Jj2 22 | j9lbrrjVuSnF7umzpmqEtsxRbUmxius94qi005v6fjtFiAEi0wRW9eSqxMU758P4 23 | WeZ41ujt6fRUBVuSk7lcC/LHd8tc1q6xrQfSDZYjILQhWT8WvnWzI5X/UiEp8RuU 24 | wM+hDcLpXIVAJJOb4XijcTSwFdQcu0+IJbBOoPkAk3aZiobAFnjQ+HQ8D2s0aAvg 25 | xsns9g/pf+T1AWkOUv6aSr/em8Z+EyRgqlVJS9uoN/jnmrDDuR6VFrK7t2tAQlBS 26 | we9qLXkMQQ2QY8dD077KzsD5Pg6qyeQ6pb5+d4SJynUN2KEHaNd3uqbC8v6aFOHh 27 | 2NbxY8qY4aOvUzBEljMu7LNmf/c6tB0GwxRCQbsXqyvjmwK1aprxZHD6ZQ0b6vrE 28 | AhfKBmRzxvK/O97HpS/IsjryVtV20ItElMDyKdg626vMz1r3Mx2y2+D1HOf2JZEz 29 | NDnKtJGeXncj/Qbsz0ow0ROJGgqNko4CDEJODiLhon3N6+d7KUKv7WkNCBVliJFo 30 | z7z4nEM2g4pYfaioa7GXG0IgAw== 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/client.py: -------------------------------------------------------------------------------- 1 | from socket import * 2 | import os, sys, ssl 3 | import mysql.connector 4 | 5 | PACKET_SIZE = 64 6 | context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) 7 | context.load_verify_locations('cert.pem') 8 | 9 | def show_history(history_file): 10 | with open(history_file, 'r') as f: 11 | history = f.read() 12 | history = history.replace(",", "\n").replace("[", "").replace("]", "").replace("\n ", "\n") 13 | print(history) 14 | 15 | def show_history_from_db(cursor): 16 | history_record = "SELECT * FROM history" 17 | cursor.execute(history_record) 18 | for (record) in cursor: 19 | print(record[1]) 20 | 21 | def find_open_ports(host, start, end): 22 | free_ports = [] 23 | for port in range(start, end): 24 | with socket() as tmp_sock: 25 | tmp_sock.settimeout(1) 26 | try: 27 | tmp_sock.connect((host, port)) 28 | free_ports.append(port) 29 | except: 30 | pass 31 | return free_ports 32 | 33 | def connect_to_db(): 34 | conn = mysql.connector.connect(user='root', password='', host='localhost', database='telnet') 35 | cursor = conn.cursor() 36 | return cursor, conn 37 | 38 | def add_to_db(data, cursor, conn): 39 | command = (data ,) 40 | add_record = "INSERT INTO history(command) VALUES(%s)" 41 | cursor.execute(add_record, command) 42 | conn.commit() 43 | 44 | def send_encrypted(data): 45 | hostname='localhost' 46 | ip = '127.0.0.1' 47 | port = 8443 48 | with create_connection((ip, port)) as client: 49 | print('data encrypt: ', type(data)) 50 | with context.wrap_socket(client, server_hostname=hostname) as ssock: 51 | ssock.sendall(data.encode()) 52 | print(f'Using {ssock.version()}\n') 53 | sys.stdout.flush() 54 | 55 | 56 | class Client(): 57 | def __init__(self, server_host, server_port): 58 | self.server_host = server_host 59 | self.server_port = server_port 60 | self.command_history = [] 61 | 62 | self.socket = socket(AF_INET, SOCK_STREAM) 63 | try: 64 | self.socket.connect((gethostbyname(self.server_host),self.server_port)) 65 | print('connected to ', gethostbyname(self.server_host)) 66 | except: 67 | print(f'not able to connect to {self.server_host}:{self.server_port}\n') 68 | exit() 69 | 70 | def send_message(self, data): 71 | # data += '\n' 72 | self.socket.sendall(data.encode()) 73 | sys.stdout.flush() 74 | 75 | def send_file(self, file_directory): 76 | try: 77 | file_size = os.stat(file_directory).st_size 78 | print('file size: ', file_size) 79 | self.socket.sendall(str(file_size).encode()) 80 | with open(file_directory, 'rb') as f: 81 | file = f.read() 82 | self.socket.sendall(file) 83 | sys.stdout.flush() 84 | 85 | except Exception as e: 86 | print('error: ', e) 87 | pass 88 | 89 | def receive_data(self): 90 | data = b'' 91 | while True: 92 | part = self.socket.recv(PACKET_SIZE) 93 | data += part 94 | if len(part) < PACKET_SIZE: # either 0 or end of data 95 | break 96 | return data.decode() 97 | 98 | def close_connection(self): 99 | if self.socket: 100 | self.socket.close() 101 | 102 | 103 | 104 | if __name__ == '__main__': 105 | 106 | if len(sys.argv) == 1: 107 | HOST = 'localhost' 108 | PORT = 1080 109 | elif len(sys.argv) == 2 and sys.argv[1] == 'find-open-ports': # find open ports 110 | HOST = input('Host: ') 111 | min_port = input('minimum port range: ') 112 | max_port = input('maximum port range: ') 113 | open_ports = find_open_ports(HOST, int(min_port), int(max_port)) 114 | print(f'open ports for host: {HOST} are: {open_ports} \n') 115 | exit() 116 | else: 117 | HOST = sys.argv[1] 118 | PORT = int(sys.argv[2]) 119 | 120 | print(f'host is {HOST}, port is {PORT}') 121 | myclient = Client(HOST, PORT) 122 | 123 | cursor, conn = connect_to_db() 124 | 125 | while True: 126 | data = input(">> ") 127 | myclient.command_history.append(data) 128 | # add to file 129 | with open('commands history.txt', 'w') as f: 130 | f.write(str(myclient.command_history)) 131 | 132 | # add to mysql database 133 | add_to_db(data, cursor, conn) 134 | 135 | if len(data.split(' '))>1 and data.split(' ')[1] == 'upload': 136 | myclient.send_message(data) 137 | myclient.send_file(data.split(' ')[2]) 138 | 139 | elif len(data.split(' '))>1 and data.split(' ')[1] == 'send' and data.split(' ')[2] == '-e': 140 | myclient.send_message(str(data.split(' ')[:3]).replace(",", "").replace("[", "").replace("]", "").replace("'", "")) 141 | send_encrypted(str(data.split(' ')[3:]).replace(",", "").replace("[", "").replace("]", "").replace("'", "")) 142 | 143 | elif len(data.split(' '))>1 and data.split(' ')[1] == 'history': 144 | # show_history('commands history.txt') 145 | show_history_from_db(cursor) 146 | myclient.send_message(data) 147 | 148 | else: 149 | myclient.send_message(data) 150 | 151 | 152 | received_data = myclient.receive_data() 153 | print('received from server: ', received_data) 154 | if received_data == 'closing the connection...': 155 | myclient.close_connection() 156 | break -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/commands history.txt: -------------------------------------------------------------------------------- 1 | ['telnet exec dir'] -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,ABDE7AD2E474F713 4 | 5 | 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 54 | -----END RSA PRIVATE KEY----- 55 | -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/dab51bd7e31eccae6db50b0d24b48f04d3bd0c55/CN_Proj2_Telnet Simulator/report.pdf -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/server files/sherek.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/dab51bd7e31eccae6db50b0d24b48f04d3bd0c55/CN_Proj2_Telnet Simulator/server files/sherek.png -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/server files/test.txt: -------------------------------------------------------------------------------- 1 | this is a text -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/server.py: -------------------------------------------------------------------------------- 1 | from socket import * 2 | import subprocess, threading, sys, ssl 3 | 4 | PACKET_SIZE = 64 5 | command_history = [] 6 | context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) 7 | context.load_cert_chain('cert.pem', 'key.pem') 8 | # PEM Phrase = 1 2 3 4 9 | 10 | def recv_encrypted(): 11 | ip = '127.0.0.1' 12 | port = 8443 13 | with socket(AF_INET, SOCK_STREAM) as server: 14 | server.bind((ip, port)) 15 | server.listen(1) 16 | with context.wrap_socket(server, server_side=True) as tls: 17 | connection, address = tls.accept() 18 | data = connection.recv(PACKET_SIZE) 19 | return data 20 | 21 | 22 | def main(): 23 | server_socket = socket(AF_INET, SOCK_STREAM) 24 | server_socket.bind(('', 1080)) 25 | server_socket.listen(10) 26 | 27 | while True: 28 | conn, addr = server_socket.accept() 29 | threading.Thread(target=handle_client, args=(conn,server_socket)).start() 30 | 31 | def handle_client(conn, server_socket): 32 | 33 | print('client connected!') 34 | while True: 35 | 36 | data = conn.recv(PACKET_SIZE) 37 | data = data.decode() 38 | sys.stdout.flush() 39 | print(f'from client: {data}') 40 | splitted_data = data.split(' ', 2) 41 | 42 | command_history.append(data) 43 | 44 | if splitted_data[1] == 'exec': 45 | command = splitted_data[2] 46 | print('command is:', command) 47 | response = subprocess.check_output(command, shell=True) 48 | print('response is:', response) 49 | conn.sendall(response) 50 | 51 | elif splitted_data[1] == 'send' and splitted_data[2] != '-e': 52 | message = splitted_data[2] 53 | print('message is:', message) 54 | response = "message received" 55 | print('response is:', response) 56 | conn.sendall(response.encode()) 57 | 58 | elif splitted_data[1] == 'send' and splitted_data[2] == '-e': 59 | print('encrypted mode') 60 | enc_data = recv_encrypted() 61 | print('encrypted data is: ', enc_data.decode()) 62 | response = "encrypted message received" 63 | print('response is:', response) 64 | conn.sendall(response.encode()) 65 | 66 | elif splitted_data[1] == 'upload': 67 | print('uploading...') 68 | file_size = conn.recv(PACKET_SIZE) 69 | file_size = int(file_size.decode()) 70 | print('file size: ', file_size) 71 | file = conn.recv(file_size) 72 | file_in_server = "server files\\" + splitted_data[2].split('\\')[-1] 73 | print('file in server dir: ', file_in_server) 74 | with open(file_in_server, "wb") as f: 75 | f.write(file) 76 | 77 | response = "file received" 78 | print('response is:', response) 79 | conn.sendall(response.encode()) 80 | 81 | elif splitted_data[1] == 'history': 82 | print('client history...') 83 | conn.sendall("show history".encode()) 84 | 85 | elif splitted_data[1] == 'exit': 86 | response = 'closing the connection...' 87 | conn.sendall(response.encode()) 88 | conn.close() 89 | break 90 | 91 | else: 92 | conn.sendall('wrong command!'.encode()) 93 | pass 94 | 95 | if __name__ == '__main__': 96 | main() -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/sherek.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/dab51bd7e31eccae6db50b0d24b48f04d3bd0c55/CN_Proj2_Telnet Simulator/sherek.png -------------------------------------------------------------------------------- /CN_Proj2_Telnet Simulator/test.txt: -------------------------------------------------------------------------------- 1 | this is a text -------------------------------------------------------------------------------- /CN_Proj3_DHCP/CN-P3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/dab51bd7e31eccae6db50b0d24b48f04d3bd0c55/CN_Proj3_DHCP/CN-P3.pdf -------------------------------------------------------------------------------- /CN_Proj3_DHCP/Client.py: -------------------------------------------------------------------------------- 1 | import random 2 | import threading 3 | import dhcppython 4 | import socket 5 | import ipaddress 6 | import time 7 | import math 8 | 9 | mac_address = 'DE:AD:BE:EF:C0:44' 10 | backoff_cutoff = 120 # in seconds 11 | initial_interval = 10 # in seconds 12 | ack_timeout = 10 # in seconds 13 | lease_time = 10 # in seconds 14 | ip = '' 15 | 16 | 17 | def countdown(t): 18 | while t: 19 | time.sleep(1) 20 | t -= 1 21 | 22 | 23 | def update_timeout(prev_interval): # Discover timeout in a thread 24 | new_interval = math.ceil(2 * prev_interval * random.random()) 25 | if new_interval < backoff_cutoff: 26 | return new_interval 27 | else: 28 | return backoff_cutoff 29 | 30 | 31 | def handle_discover_timeout(client, time_interval, state): 32 | countdown(time_interval) 33 | if ip == '' and state == 'from offer': 34 | send_discover(client, 'offer') 35 | print('time interval should be updated') 36 | time_interval = update_timeout(time_interval) 37 | print('new time interval: ', time_interval) 38 | handle_discover_timeout(client, time_interval, 'from offer') 39 | elif ip == '' and state == 'from ack': 40 | send_discover(client, 'ack') 41 | print('Ack is not received') 42 | handle_discover_timeout(client, time_interval, 'from ack') 43 | else: 44 | print('we have a valid ip :)') 45 | handle_discover_timeout(client, time_interval, 'from ack') 46 | 47 | 48 | def handle_ack_timeout(client, ack_timeout): 49 | if ip == '': 50 | handle_discover_timeout(client, ack_timeout, 'from ack') 51 | 52 | 53 | def lease_time_timeout(client, leas_time): 54 | countdown(leas_time) 55 | print('lease time is finished\n') 56 | send_discover(client, 'lease_time') 57 | 58 | 59 | def wait_for_ack(client): # listen for Ack from Server 60 | while True: 61 | data_ack, addr = client.recvfrom(1024) 62 | packet_ack = dhcppython.packet.DHCPPacket.from_bytes(data_ack) 63 | dhcp_type = packet_ack.options.as_dict()['dhcp_message_type'] 64 | if packet_ack.op == 'BOOTREPLY' and dhcp_type == 'DHCPACK': 65 | print("ack message:", packet_ack) 66 | ip = packet_ack.yiaddr 67 | print(f'ip: {ip} is assigned to this client\n') 68 | lease_time_t = threading.Thread(target=lease_time_timeout, args=(client, lease_time,)) 69 | lease_time_t.start() 70 | break 71 | 72 | 73 | def send_request(client, transaction_id, from_state, offered_ip): # Request packet 74 | request_packet = dhcppython.packet.DHCPPacket(op="BOOTREQUEST", htype="ETHERNET", hlen=6, hops=0, xid=transaction_id, secs=0, flags=0, ciaddr=ipaddress.IPv4Address(0), yiaddr=ipaddress.IPv4Address(offered_ip), siaddr=ipaddress.IPv4Address(0), giaddr=ipaddress.IPv4Address(0), chaddr=mac_address, sname=b'', file=b'', options=dhcppython.options.OptionList([dhcppython.options.options.short_value_to_object(53, "DHCPREQUEST")])) 75 | client.sendto(request_packet.asbytes, ('', 6666)) 76 | if from_state == 'start': 77 | wait_for_ack_t = threading.Thread(target=handle_ack_timeout, args=(client, ack_timeout,)) 78 | wait_for_ack_t.start() 79 | wait_for_ack(client) 80 | else: 81 | wait_for_ack(client) 82 | 83 | 84 | def wait_for_offer(client, transaction_id, from_state): # listen for Server Offer 85 | while True: 86 | data_offer, addr = client.recvfrom(1024) 87 | packet_offer = dhcppython.packet.DHCPPacket.from_bytes(data_offer) 88 | dhcp_type = packet_offer.options.as_dict()['dhcp_message_type'] 89 | if packet_offer.op == 'BOOTREPLY' and dhcp_type == 'DHCPOFFER': 90 | print("offer message:", packet_offer) 91 | offered_ip = packet_offer.yiaddr 92 | print(f'server offer is: {offered_ip}\n') 93 | send_request(client, transaction_id, from_state, offered_ip) 94 | break 95 | 96 | 97 | def send_discover(client, from_state): # Discovery packet 98 | discover_packet = dhcppython.packet.DHCPPacket.Discover(mac_address) 99 | client.sendto(discover_packet.asbytes, ('', 6666)) 100 | transaction_id = discover_packet.xid 101 | if from_state == 'start': 102 | wait_for_offer_t = threading.Thread(target=handle_discover_timeout, args=(client, initial_interval, 'from offer')) 103 | wait_for_offer_t.start() 104 | wait_for_offer(client, transaction_id, from_state) 105 | else: 106 | wait_for_offer(client, transaction_id, from_state) 107 | 108 | 109 | def main(): 110 | client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # UDP 111 | client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Enable port reusage 112 | client.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # Enable broadcasting mode 113 | client.bind(("", 4444)) 114 | while True: 115 | send_discover(client, 'start') 116 | 117 | 118 | if __name__ == '__main__': 119 | main() -------------------------------------------------------------------------------- /CN_Proj3_DHCP/Server.py: -------------------------------------------------------------------------------- 1 | import ipaddress 2 | import json 3 | import dhcppython 4 | import socket 5 | import threading 6 | import random 7 | import time 8 | 9 | mac_address = 'DE:AD:BE:EF:C0:88' 10 | assigned_IPs = {} # it's not the same as reservation_list! 11 | lease_mac = {} # record lease time for each client 12 | json_file = 'configs.json' 13 | 14 | 15 | def pool_maker(from_ip, to_ip): 16 | ip_pool = [] 17 | from_ip_splitted = from_ip.split('.') 18 | to_ip_splitted = to_ip.split('.') 19 | start = int(from_ip_splitted[3]) 20 | end = int(to_ip_splitted[3]) 21 | mutual_part = from_ip_splitted[0] + '.' + from_ip_splitted[1] + '.' + from_ip_splitted[2] + '.' 22 | 23 | for end_part in range(start, end+1): 24 | ip_pool.append(mutual_part + str(end_part)) 25 | return ip_pool 26 | 27 | 28 | def pool_maker_subnet(ip_block, subnet_mask): 29 | power = 8 - bin(int(subnet_mask.split('.')[-1])).count('1') 30 | if ip_block.split('.')[-1] == '0': 31 | from_ip = ip_block[:-1] + '1' 32 | print(from_ip) 33 | else: 34 | from_ip = ip_block 35 | to_ip = ip_block[:-1] + str((2 ** power) - 1) 36 | print('to ip is:', to_ip) 37 | return pool_maker(from_ip, to_ip) 38 | 39 | 40 | def load_server_config(json_file): 41 | f = open(json_file) 42 | config = json.load(f) 43 | ip_pool = [] 44 | pool_mode = config['pool_mode'] 45 | if pool_mode == 'range': 46 | from_ip = config['range']['from'] 47 | to_ip = config['range']['to'] 48 | ip_pool = pool_maker(from_ip, to_ip) 49 | elif pool_mode == 'subnet': 50 | ip_block = config['subnet']['ip_block'] 51 | subnet_mask = config['subnet']['subnet_mask'] 52 | ip_pool = pool_maker_subnet(ip_block, subnet_mask) 53 | 54 | lease_time = config['lease_time'] 55 | reservation_list = config['reservation_list'] 56 | black_list = config['black_list'] 57 | f.close() 58 | return ip_pool, lease_time, reservation_list, black_list 59 | 60 | 61 | def offer_ip(ip_pool, mac_address, reservation_list, black_list): 62 | if mac_address in reservation_list.keys(): 63 | print(f'IP {reservation_list[mac_address]} is reserved for mac address {mac_address}\n') 64 | return reservation_list[mac_address] 65 | elif mac_address in black_list: 66 | return 'BLOCK' 67 | elif mac_address in assigned_IPs.keys(): 68 | return assigned_IPs[mac_address] 69 | else: 70 | while True: 71 | ip_to_assign = random.choice(ip_pool) 72 | if ip_to_assign not in reservation_list.values() and ip_to_assign not in assigned_IPs.values(): 73 | return ip_to_assign 74 | 75 | 76 | def show_clients(assigned_IPs, lease_mac): 77 | for mac in assigned_IPs.keys(): 78 | print(f'mac:{mac}, time to expire:{lease_mac[mac]}, IP:{assigned_IPs[mac]}\n') 79 | 80 | 81 | def countdown(t, lease_time): 82 | while t: 83 | time.sleep(1) 84 | lease_time -= 1 85 | t -= 1 86 | 87 | 88 | def lease_time_timeout(server, ip_pool, reservation_list, black_list, lease_time, mac_addr): 89 | countdown(lease_time, lease_mac[mac_addr]) 90 | assigned_IPs.pop(mac_addr) 91 | lease_mac[mac_addr] = 0 92 | print(f'lease time for client {mac_addr} is finished') 93 | show_clients(assigned_IPs, lease_mac) 94 | manage_client(server, ip_pool, reservation_list, black_list, lease_time) 95 | 96 | 97 | def manage_client(server, ip_pool, reservation_list, black_list, lease_time): 98 | # listen for Discovery packet 99 | while True: 100 | data_discovery, addr = server.recvfrom(1024) 101 | packet_discovery = dhcppython.packet.DHCPPacket.from_bytes(data_discovery) 102 | print("discover message:", packet_discovery) 103 | dhcp_type = packet_discovery.options.as_dict()['dhcp_message_type'] 104 | if packet_discovery.op == 'BOOTREQUEST' and dhcp_type == 'DHCPDISCOVER': 105 | client_mac_address = packet_discovery.chaddr 106 | print('Discover packet received\n') 107 | transaction_id = packet_discovery.xid 108 | break 109 | 110 | 111 | # Offer packet 112 | offered_ip = offer_ip(ip_pool, client_mac_address, reservation_list, black_list) 113 | if offered_ip == 'BLOCK': 114 | print('This client is blocked!\n') 115 | else: 116 | offer_packet = dhcppython.packet.DHCPPacket.Offer(mac_address, seconds=0, tx_id=transaction_id, yiaddr=ipaddress.IPv4Address(offered_ip)) 117 | server.sendto(offer_packet.asbytes, ('', 4444)) 118 | 119 | # time.sleep(20) 120 | # print('offer sent') 121 | 122 | # listen for Client request packet 123 | while True: 124 | data_request, addr = server.recvfrom(1024) 125 | packet_request = dhcppython.packet.DHCPPacket.from_bytes(data_request) 126 | dhcp_type = packet_request.options.as_dict()['dhcp_message_type'] 127 | if packet_request.op == 'BOOTREQUEST' and dhcp_type == 'DHCPREQUEST': 128 | print("request message:", packet_request) 129 | print('Request packet received\n') 130 | break 131 | 132 | # time.sleep(15) 133 | 134 | # Ack packet 135 | client_mac_address = packet_request.chaddr 136 | assigned_IPs[client_mac_address] = offered_ip 137 | print(f'ip {offered_ip} is assigned to client') 138 | ack_packet = dhcppython.packet.DHCPPacket.Ack(mac_address, seconds=0, tx_id=transaction_id, yiaddr=ipaddress.IPv4Address(offered_ip)) 139 | server.sendto(ack_packet.asbytes, ('', 4444)) 140 | lease_mac[client_mac_address] = lease_time 141 | 142 | # print('ack sent') 143 | show_clients(assigned_IPs, lease_mac) 144 | # lease_time_t = threading.Thread(target=lease_time_timeout, args=(server, ip_pool, reservation_list, black_list, lease_time, client_mac_address)) 145 | # lease_time_t.start() 146 | return client_mac_address 147 | 148 | 149 | def main(): 150 | ip_pool, lease_time, reservation_list, black_list = load_server_config(json_file) 151 | server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) 152 | server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 153 | server.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) 154 | server.bind(("", 6666)) 155 | 156 | # while True: 157 | threading.Thread(target=handle_client, args=(server,ip_pool, lease_time, reservation_list, black_list)).start() 158 | 159 | def handle_client(server,ip_pool, lease_time, reservation_list, black_list): 160 | 161 | client_mac_address = manage_client(server, ip_pool, reservation_list, black_list, lease_time) 162 | 163 | # timer for handling client lease time 164 | # lease_time_t = threading.Thread(target=lease_time_timeout, args=(server, ip_pool, reservation_list, black_list, lease_time, client_mac_address)) 165 | # lease_time_t.start() 166 | 167 | 168 | if __name__ == '__main__': 169 | main() 170 | -------------------------------------------------------------------------------- /CN_Proj3_DHCP/backup/Client.py: -------------------------------------------------------------------------------- 1 | import random 2 | import dhcppython 3 | import socket 4 | import ipaddress 5 | mac_address = 'de:ad:be:ef:c0:de' 6 | 7 | # TODO Discover timeout in a thread (calculated by a formula: Prev_interval * 2 * Random(0,1)) 8 | backoff_cutoff = 120 # in seconds 9 | initial_interval = 10 # in seconds 10 | def calculate_timeout(prev_interval): 11 | new_interval = 2 * prev_interval * random.random() 12 | if new_interval < backoff_cutoff: 13 | return backoff_cutoff 14 | else: 15 | return new_interval 16 | 17 | 18 | client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # UDP 19 | client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Enable port reusage 20 | client.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # Enable broadcasting mode 21 | client.bind(("", 4444)) 22 | 23 | while True: 24 | 25 | # Discovery packet 26 | discover_packet = dhcppython.packet.DHCPPacket.Discover(mac_address) 27 | client.sendto(discover_packet.asbytes, ('', 6666)) 28 | transaction_id = discover_packet.xid 29 | 30 | # listen for Server Offer 31 | while True: 32 | data_offer, addr = client.recvfrom(1024) 33 | packet_offer = dhcppython.packet.DHCPPacket.from_bytes(data_offer) 34 | print("received message:", packet_offer) 35 | dhcp_type = packet_offer.options.as_dict()['dhcp_message_type'] 36 | if packet_offer.op == 'BOOTREPLY' and dhcp_type == 'DHCPOFFER': 37 | print(f'server offer is: {packet_offer.yiaddr}') 38 | break 39 | 40 | # print('offer received') 41 | 42 | # Request packet 43 | request_packet = dhcppython.packet.DHCPPacket.Request(mac_address, seconds=0, tx_id=transaction_id) 44 | print('request: ', request_packet) 45 | client.sendto(request_packet.asbytes, ('', 6666)) 46 | 47 | # print('request sent') 48 | 49 | # listen for Ack from Server 50 | while True: 51 | data_ack, addr = client.recvfrom(1024) 52 | packet_ack = dhcppython.packet.DHCPPacket.from_bytes(data_ack) 53 | print("received message:", packet_ack) 54 | dhcp_type = packet_ack.options.as_dict()['dhcp_message_type'] 55 | if packet_ack.op == 'BOOTREPLY' and dhcp_type == 'DHCPACK': 56 | print(f'ip: {packet_ack.yiaddr} is assigned to this client') 57 | break 58 | 59 | # print('ack received') 60 | 61 | 62 | # TODO implement timeout (arbitrary timeout) 63 | exit() -------------------------------------------------------------------------------- /CN_Proj3_DHCP/backup/Server.py: -------------------------------------------------------------------------------- 1 | import ipaddress 2 | import json 3 | import dhcppython 4 | import socket 5 | import threading 6 | import random 7 | mac_address = 'de:ad:be:ef:c0:de' 8 | assigned_IPs = {} # it's not the same as reservation_list! 9 | 10 | def pool_maker(from_ip, to_ip): 11 | from_ip_splitted = from_ip.split('.') 12 | to_ip_splitted = to_ip.split('.') 13 | ip_pool = [] 14 | 15 | if from_ip_splitted[0] != to_ip_splitted[0]: 16 | pass 17 | elif from_ip_splitted[1] != to_ip_splitted[1]: 18 | pass 19 | elif from_ip_splitted[2] != to_ip_splitted[2]: 20 | pass 21 | else: 22 | start = int(from_ip_splitted[3]) 23 | end = int(to_ip_splitted[3]) 24 | 25 | mutual_part = from_ip_splitted[0] + '.' + from_ip_splitted[1] + '.' + from_ip_splitted[2] + '.' 26 | for end_part in range(start, end+1): 27 | ip_pool.append(mutual_part + str(end_part)) 28 | return ip_pool 29 | 30 | 31 | json_file = 'configs.json' 32 | def load_server_config(json_file): 33 | f = open(json_file) 34 | config = json.load(f) 35 | ip_pool = [] 36 | pool_mode = config['pool_mode'] 37 | if pool_mode == 'range': 38 | from_ip = config['range']['from'] 39 | to_ip = config['range']['to'] 40 | ip_pool = pool_maker(from_ip, to_ip) 41 | elif pool_mode == 'subnet': 42 | ip_block = config['subnet']['ip_block'] 43 | subnet_mask = config['subnet']['subnet_mask'] 44 | 45 | lease_time = config['lease_time'] 46 | reservation_list = config['reservation_list'] 47 | black_list = config['black_list'] 48 | f.close() 49 | return ip_pool, lease_time, reservation_list, black_list 50 | 51 | 52 | def offer_ip(ip_pool, mac_address, reservation_list): 53 | if mac_address in reservation_list.keys(): 54 | return reservation_list[mac_address] 55 | else: 56 | while True: 57 | ip_to_assign = random.choice(ip_pool) 58 | if ip_to_assign not in reservation_list.values() and ip_to_assign not in assigned_IPs.values(): 59 | return ip_to_assign 60 | 61 | 62 | def show_clients(): 63 | pass 64 | 65 | def main(): 66 | ip_pool, lease_time, reservation_list, black_list = load_server_config(json_file) 67 | server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) 68 | server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 69 | server.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) 70 | server.bind(("", 6666)) 71 | 72 | # while True: 73 | threading.Thread(target=handle_client, args=(server,ip_pool, lease_time, reservation_list, black_list)).start() 74 | 75 | def handle_client(server,ip_pool, lease_time, reservation_list, black_list): 76 | 77 | 78 | 79 | # listen for Discovery packet (it should be multi-thread) 80 | while True: 81 | data_discovery, addr = server.recvfrom(1024) 82 | packet_discovery = dhcppython.packet.DHCPPacket.from_bytes(data_discovery) 83 | print("received message:", packet_discovery) 84 | dhcp_type = packet_discovery.options.as_dict()['dhcp_message_type'] 85 | if packet_discovery.op == 'BOOTREQUEST' and dhcp_type == 'DHCPDISCOVER': 86 | print('Discover packet received') 87 | transaction_id = packet_discovery.xid 88 | break 89 | 90 | 91 | # Offer packet 92 | offered_ip = offer_ip(ip_pool, mac_address, reservation_list) 93 | offer_packet = dhcppython.packet.DHCPPacket.Offer(mac_address, seconds=0, tx_id=transaction_id, yiaddr=ipaddress.IPv4Address(offered_ip)) 94 | server.sendto(offer_packet.asbytes, ('', 4444)) 95 | 96 | # print('offer sent') 97 | 98 | # listen for Client request packet (parse request) 99 | while True: 100 | data_request, addr = server.recvfrom(1024) 101 | packet_request = dhcppython.packet.DHCPPacket.from_bytes(data_request) 102 | print("request message:", packet_request) 103 | dhcp_type = packet_request.options.as_dict()['dhcp_message_type'] 104 | if packet_request.op == 'BOOTREQUEST' and dhcp_type == 'DHCPREQUEST': 105 | print('Request packet received') 106 | break 107 | 108 | # print('request received') 109 | 110 | # Ack packet 111 | assigned_IPs[packet_request.chaddr] = offered_ip 112 | print('ip:', offered_ip) 113 | ack_packet = dhcppython.packet.DHCPPacket.Ack(mac_address, seconds=0, tx_id=transaction_id, yiaddr=ipaddress.IPv4Address(offered_ip)) 114 | server.sendto(ack_packet.asbytes, ('', 4444)) 115 | 116 | # print('ack sent') 117 | 118 | # TODO handle lease-time (perhaps in a different thread for each client) 119 | 120 | if __name__ == '__main__': 121 | main() 122 | -------------------------------------------------------------------------------- /CN_Proj3_DHCP/configs.json: -------------------------------------------------------------------------------- 1 | { 2 | "pool_mode": "range", 3 | "range":{ 4 | "from": "192.168.1.2", 5 | "to": "192.168.1.10" 6 | }, 7 | "subnet":{ 8 | "ip_block": "192.168.1.0", 9 | "subnet_mask": "255.255.255.224" 10 | }, 11 | "lease_time": 10, 12 | "reservation_list": { 13 | "DE:AD:BE:EF:C0:11": "192.168.1.2", 14 | "DE:AD:BE:EF:C0:22": "192.168.1.3" 15 | }, 16 | "black_list": [ 17 | "DE:AD:BE:EF:C0:33", "DE:AD:BE:EF:C0:00" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /CN_Proj3_DHCP/report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/dab51bd7e31eccae6db50b0d24b48f04d3bd0c55/CN_Proj3_DHCP/report.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Computer Networks Course Projects 2 | ## [Project 1: DNS Resolver](https://github.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/tree/main/CN_Proj1_DNS%20Resolver) 3 | ## [Project 2: Telnet Simulator](https://github.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/tree/main/CN_Proj2_Telnet%20Simulator) 4 | ## [Project 3: DHCP](https://github.com/Amirhossein-Rajabpour/Computer-Networks-Course-Projects/tree/main/CN_Proj3_DHCP) 5 | --------------------------------------------------------------------------------