Guest User

udp_relay_server.py

a guest
Nov 1st, 2021
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.02 KB | None | 0 0
  1. import socket
  2. import sys
  3. from os.path import exists,getsize
  4. import os
  5. import time
  6. import threading
  7. import math
  8.  
  9. # virtual guest os:es set to
  10. # Generic Driver
  11. # Name=UDPTunnel
  12. # !check advanced
  13. # Generic Properties
  14. # dest=UDP RELAY SERVER HOST EXTERNAL IP (local ip on server host guest (0th client))
  15. # sport=ROUTED PORT INTERNET (port to send packets from SERVER(udp_relay_server) (setting name listen (tuple(tuple(ip,port),mac,tuple(ip,port),mac))) (client shouldn't need to routed if packets are sent before server is running (server still routed))
  16. # dport=RELAY SERVER ROUTED PORT (setting name serverport)
  17.  
  18. #encryption support missing (data will be visible to middleman attacks)
  19.  
  20. serverport=27000 # port to host UDP RELAY SERVER (packet distributor)
  21. clientused=[0,1,2,3]
  22. listen= (('192.168.100.20',26000),b'\x08\x00\x27\xff\xff\xff', # 0th enter here your own local ip + sport of virtual machine + your guest os virtual network card mac
  23.          ('123.123.123.123',26000),b'\x08\x00\x27\xff\xff\xff', # 1st client ip of his/her host + sport value + 1st client guest os virtual network card mac
  24.          ('231.231.231.231',26000),b'\x08\x00\x27\xff\xff\xff', # 2nd client ip of his/her host + sport value + 2nd client guest os virtual network card mac
  25.          ('213.213.213.213',26000),b'\x08\x00\x27\xff\xff\xff') # 3rd client ip of his/her host + sport value + 3rd client guest os virtual network card mac
  26. data_payload = 2048 #max packet size (shouldn't need to be on mtu, preferably over it (low value will split packets and UDP RELAY SERVER cannot handle split packets))
  27. allclientsbroadcast = True #if false, only server host (0) packets broadcast packets are transmitted to all. this may cause some NOT seeing on other hosts hosted games.
  28. broadcastonlyactive = True #if true, broadcast packets are only sent clients that have connected UDP RELAY SERVER (activates settings defaultstate,droptimeout and droppedremind)
  29. defaultstate= True #starting state of client DROPPED status
  30. displayfake = True #reports even if broadcastonlyactive is false on timeouts.
  31. droptimeout = 360 #seconds clients are to remain in packet target if no connection from them.
  32. droppedremind = 120 #seconds bethween reminding dropped clients.
  33. logfilename="logfile" #log for umatching connections (cannot be disabled) (you can provide file address here)
  34. logfileext=".txt"
  35. #NO MORE SETTINGS TO CONFIGURE AFTER THIS LINE
  36. macbroad=b'\xff\xff\xff\xff\xff\xff' #do not touch (broadcast mac address)
  37. clientamount=4 #does nothing (gets auto set by clientused)
  38. clienttime=[]
  39. logifile=open(logfilename + logfileext, 'a')
  40. prevpri=time.time() - 10.0
  41.  
  42. def listeshow():
  43.     global prevpri
  44.     while True:
  45.         if prevpri + 2.5 < time.time():
  46.             print ("[%03d] Waiting to receive message from client" % (math.floor(time.time())%1000) )
  47.             return
  48.         time.sleep(0.05)
  49.  
  50. def dropfollow():
  51.     global clienttime
  52.     global clientused
  53.     while True:
  54.         for x in clientused:
  55.             if clienttime[x*2] + droptimeout < time.time() and not clienttime[x*2+1]:
  56.                 print("[%03d] %s dropped from connection.%s" % (math.floor(time.time())%1000,listen[x*2],"fake" if not broadcastonlyactive else ""))
  57.                 clienttime[x*2+1]=True
  58.                 clienttime[x*2]=time.time()
  59.             elif clienttime[x*2+1] and clienttime[x*2] + droppedremind < time.time():
  60.                 print("[%03d] %s still down...%s" % (math.floor(time.time())%1000,listen[x*2],"fake" if not broadcastonlyactive else ""))
  61.                 clienttime[x*2]=time.time()
  62.         time.sleep(1.0)
  63.  
  64. def mysendpacket(sock,data,target):
  65.     try:
  66.         return sock.sendto(data,target)
  67.     except Exception as e:
  68.         console.writeError(str(e))
  69.     return -1
  70.        
  71. def echo_server(port):
  72.     # Create a UDP socket
  73.     sock = socket.socket(socket.AF_INET,
  74.                          socket.SOCK_DGRAM)
  75.  
  76.     # Bind the socket to the port
  77.     server_address = (listen[0][0], port)
  78.     global logifile
  79.     global clienttime
  80.     global clientused
  81.     if exists(logfilename + logfileext):
  82.         if os.path.getsize(logfilename + logfileext) == 0:
  83.             pass
  84.         else:
  85.             if exists(logfilename + "9" + logfileext):
  86.                 os.remove(logfilename + "9" + logfileext)
  87.             for x in range(8,0,-1):
  88.                 if exists((logfilename + "%s" + logfileext) % x):
  89.                     os.rename((logfilename + "%s" + logfileext) % x,(logfilename + "%s" + logfileext) % (x+1))
  90.             logifile.close()
  91.             os.rename(logfilename + logfileext,(logfilename + "1" + logfileext))
  92.             logifile=open(logfilename + logfileext,"x")
  93.     else:
  94.         logifile=open(logfilename + logfileext,"x")
  95.     tmp=[]
  96.     for i in clientused:
  97.         if i not in tmp and i < math.floor(len(listen)/2):
  98.             tmp.append(i)
  99.             print("Allowed %d %s client." % (i,listen[i*2]))
  100.         else:
  101.             print("Unlisted %d (max id %d) client. (if already allowed it's still listed)" % (i,math.floor(len(listen)/2)-1))
  102.     clientused=tmp
  103.     del tmp
  104.     clientamount=len(clientused)
  105.     for i in range(0,math.floor(len(listen)/2)):
  106.         clienttime.append(time.time())
  107.         clienttime.append(defaultstate)
  108.     print ("Starting UDP RELAY SERVER on %s port %s" % server_address)
  109.     if clientamount < 1:
  110.         print("QUITING DUE NO CLIENTS ALLOWED")
  111.         return
  112.  
  113.     sock.bind(server_address)
  114.     #licount=0 #this line is related to notepad++ python console
  115.     strtoprint=""
  116.     global prevpri
  117.     global allclientsbroadcast
  118.     while True:
  119.         try:
  120.             dispwaiting
  121.         except NameError:
  122.             dispwaiting=threading.Thread(target=listeshow)
  123.             dispwaiting.start()
  124.             if broadcastonlyactive or displayfake:
  125.                 dispdrop=threading.Thread(target=dropfollow)
  126.                 dispdrop.start()
  127.         else:
  128.             if broadcastonlyactive or displayfake:
  129.                 if not dispdrop.is_alive():
  130.                     dispdrop=threading.Thread(target=dropfollow)
  131.                     dispdrop.start()
  132.             if not dispwaiting.is_alive():
  133.                 dispwaiting=threading.Thread(target=listeshow)
  134.                 dispwaiting.start()
  135.  
  136.         try:
  137.             data, address = sock.recvfrom(data_payload)
  138.         except Exception as e:
  139.             console.writeError(str(e))
  140.    
  141.         strtoprint="%s%s\n" % (strtoprint,("[%03d] received %s bytes from %s" % (math.floor(time.time())%1000,len(data), address)))
  142.         #print ("Data: %s" %data)
  143.         ctest=[0,0,0,0]
  144.         cindex=-1
  145.         for x in clientused:
  146.             if listen[x*2][0] == address[0]:
  147.                 ctest[0]=2
  148.             if listen[x*2][1] == address[1]:
  149.                 ctest[1]=2
  150.             if data[6:12] == listen[x*2+1]:
  151.                 ctest[2]=2
  152.             if data and listen[x*2][0] == address[0] and listen[x*2][1] == address[1] and data[6:12] == listen[x*2+1]:
  153.                 ctest[0]=1
  154.                 ctest[1]=1
  155.                 ctest[2]=1
  156.                 clienttime[x*2]=time.time()
  157.                 clienttime[x*2+1]=False
  158.                 cindex=x
  159.                 break
  160.         if cindex != -1:
  161.             if data[:6] == macbroad:
  162.                 ctest[3]=1
  163.                 if allclientsbroadcast or cindex==0:
  164.                     for x in clientused:
  165.                         if x != cindex and (clienttime[x*2]+droptimeout > time.time() or not broadcastonlyactive):
  166.                             sent = mysendpacket(sock,data,listen[x*2])
  167.                             strtoprint="%s%s\n" % (strtoprint,("[%03d] broadcast %s bytes to %s" % (math.floor(time.time())%1000,sent, listen[x*2])))
  168.             else:
  169.                 for x in clientused:
  170.                     if data[:6] == listen[x*2+1]:
  171.                         ctest[3]=2
  172.                         if x != cindex and (clienttime[x*2]+droptimeout > time.time() or not broadcastonlyactive):
  173.                             ctest[3]=1
  174.                             sent = mysendpacket(sock,data,listen[x*2])
  175.                             strtoprint="%s%s\n" % (strtoprint,("[%03d] send %s bytes to %s %s" % (math.floor(time.time())%1000,sent, listen[x*2],data[:6].hex())))
  176.                             break
  177.         if not (ctest[0]==1 and ctest[1]==1 and ctest[2]==1 and ctest[3]==1):
  178.             tmpstr=" %15s   %05i   %s   %s  %s\n" % (listen[cindex*2][0],listen[cindex*2][1],data[:6].hex(),data[6:12].hex(),data[12:].hex())
  179.             tmpbyt=bytearray(tmpstr,"ascii")
  180.             tmpbyt[0]=33 if (ctest[0] == 0) else (63 if ctest[0] == 2 else 32)
  181.             tmpbyt[16]=33 if (ctest[0] == 0) else (63 if ctest[0] == 2 else 32)
  182.             tmpbyt[18]=33 if (ctest[1] == 0) else (63 if ctest[1] == 2 else 32)
  183.             tmpbyt[24]=33 if (ctest[1] == 0) else (63 if ctest[1] == 2 else 32)
  184.             tmpbyt[26]=33 if (ctest[2] == 0) else (63 if ctest[2] == 2 else 32)
  185.             tmpbyt[39]=33 if (ctest[2] == 0) else (63 if ctest[2] == 2 else 32)
  186.             tmpbyt[41]=33 if (ctest[3] == 0) else (63 if ctest[3] == 2 else 32)
  187.             tmpbyt[54]=33 if (ctest[3] == 0) else (63 if ctest[3] == 2 else 32)
  188.             tmpstr=tmpbyt.decode("ascii")
  189.             logifile.write(tmpstr)
  190.             logifile.close()
  191.             logifile.open(logfilename + logfileext, 'a')
  192.         strtoprint="%s\n" % strtoprint
  193.         if (prevpri + 0.3 < time.time()):
  194.             prevpri=time.time()
  195.             print(strtoprint,end='')
  196.             strtoprint=""
  197. #        licount+=1 #these 5 lines are related to notepad++ python console
  198. #        if licount > 500:
  199. #            licount=0
  200. #            if console.editor.getCurrentPos() > 50000:
  201. #                console.clear()
  202.  
  203. #sys.stderr = console # remove first "#" to make standard log visible to notepad++ python console
  204. #sys.stdout = console # remove first "#" to make standard log visible to notepad++ python console
  205. try:
  206.     echo_server(serverport)
  207. finally:
  208.     pass
  209.     # logifile.close()
  210.     # if os.path.getsize(logfilename + logfileext) == 0:
  211.         # os.remove(logfilename + logfileext)
Advertisement
Add Comment
Please, Sign In to add comment