import socket import struct import logging import threading from pytun import TunTapDevice, IFF_TAP ########################## Defining global variables ADDRESS = "127.0.0.1"; # Address to connect to PORT = 9999; # Port to connect to NIC_NAME = "client"; # Name for the TAP interface that gonna be created CONFIGURE_NIC = True; # If you prefer to set up the interface manualy set it to False NIC_IP = "10.0.0.2"; # IP to be set for the interface NIC_NETMASK = "255.255.255.0"; # Netmask to be used with the interface MTU = 1500; # MTU that gonna be set for the interface, please don't change it if you don't know what you are doing logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s %(message)s\n') # Sets logging level and format. Possible levels: DEBUG, INFO, WARNING, ERROR, CRITICAL Read python logging module documentation for more detailes # Don't change if you don't know what are you doing connected = False # Stores the connection status FRAME_SIZE = MTU + 42 # MTU is the size of payload, frame itself take 42 more bytes ########################## Defining global variables (END) ########################## Defining functions def recive(socket, NIC): # A function that reads socket for new data and writes this data to the NIC global FRAME_SIZE # Read what they are used for in "Defining global variables" section above global connected buffer_ = " " # Setting buffer to " " so it's not empty and the loop can start while buffer_ != b'': # If buffer_ is b'' that meas the server closed the socket buffer_ = socket.recv(FRAME_SIZE) # reciving data from the server if buffer_ != b'': # If buffer_ is still not empty, write it to the NIC NIC.write(buffer_) logging.debug(f'Recived: {buffer_}') logging.info("Connection with the server lost. Reconnecting...") connection = False def send(socket, NIC): # The function reads the NIC for new frames and send them to the server global FRAME_SIZE # Read what they are used for in "Defining global variables" section above global connected while connected == True: buffer_ = NIC.read(FRAME_SIZE) # Reads outgoing frames socket.send(buffer_) # Sends the frames logging.debug(f'Sent: {buffer_}') def main(): global NIC_NAME # Read what they are used for in "Defining global variables" section above global MTU global CONFIGURE_NIC global NIC_IP global NIC_NETMASK global ADDRESS global PORT global connected # Setting up a TAP interface NIC = TunTapDevice(flags=IFF_TAP, name=NIC_NAME) NIC.mtu = MTU if CONFIGURE_NIC: NIC.addr = NIC_IP NIC.netmask = NIC_NETMASK NIC.up() # Setting up a socket client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) logging.info(f'Connecting to {ADDRESS}:{PORT}') while True: try: client_socket.connect((ADDRESS, PORT)) connected = True logging.info(f'Connected {ADDRESS}:{PORT}') sending_thread = threading.Thread(target=send, args=(client_socket, NIC)) sending_thread.start() recive(client_socket, NIC) except Exception: # If there is an error execute the code below logging.debug("An error occurred during connection. Reconnecting") client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Recreating socket except KeyboardInterrupt: # if there is a keyboard interrupt (CTRL + C) it gonna close the socket and the NIC and break the loop NIC.close() client_socket.close() break ########################## Defining functions (END) if __name__ == '__main__': # Starting the main function main()