SimpleTunnel/client.py

153 lines
3.8 KiB
Python

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()