Guest User

udp_relay_server.py

a guest
Nov 1st, 2021
42
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.78 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. droptimeout = 360 #seconds clients are to remain in packet target if no connection from them.
  31. droppedremind = 120 #seconds bethween reminding dropped clients.
  32. logfilename="logfile" #log for umatching connections (cannot be disabled) (you can provide file address here)
  33. logfileext=".txt"
  34. #NO MORE SETTINGS TO CONFIGURE AFTER THIS LINE
  35. macbroad=b'\xff\xff\xff\xff\xff\xff' #do not touch (broadcast mac address)
  36. clientamount=4 #does nothing (gets auto set by clientused)
  37. clienttime=[]
  38. logifile=open(logfilename + logfileext, 'a')
  39. prevpri=time.time() - 10.0
  40.  
  41. def listeshow():
  42.     global prevpri
  43.     while True:
  44.         if prevpri + 2.5 < time.time():
  45.             print ("[%03d] Waiting to receive message from client" % (math.floor(time.time())%1000) )
  46.             return
  47.         time.sleep(0.05)
  48.  
  49. def dropfollow():
  50.     global clienttime
  51.     global clientused
  52.     while True:
  53.         for x in clientused:
  54.             if clienttime[x*2] + droptimeout < time.time() and not clienttime[x*2+1]:
  55.                 print("[%03d] %s dropped from connection." % (math.floor(time.time())%1000,listen[x*2]))
  56.                 clienttime[x*2+1]=True
  57.                 clienttime[x*2]=time.time()
  58.             elif clienttime[x*2+1] and clienttime[x*2] + droppedremind < time.time():
  59.                 print("[%03d] %s still down..." % (math.floor(time.time())%1000,listen[x*2]))
  60.                 clienttime[x*2]=time.time()
  61.         time.sleep(1.0)
  62.  
  63. def mysendpacket(sock,data,target):
  64.     try:
  65.         return sock.sendto(data,target)
  66.     except Exception as e:
  67.         console.writeError(str(e))
  68.     return -1
  69.        
  70. def echo_server(port):
  71.     # Create a UDP socket
  72.     sock = socket.socket(socket.AF_INET,
  73.                          socket.SOCK_DGRAM)
  74.  
  75.     # Bind the socket to the port
  76.     server_address = (listen[0][0], port)
  77.     global logifile
  78.     global clienttime
  79.     global clientused
  80.     if exists(logfilename + logfileext):
  81.         if os.path.getsize(logfilename + logfileext) == 0:
  82.             pass
  83.         else:
  84.             if exists(logfilename + "9" + logfileext):
  85.                 os.remove(logfilename + "9" + logfileext)
  86.             for x in range(8,0,-1):
  87.                 if exists((logfilename + "%s" + logfileext) % x):
  88.                     os.rename((logfilename + "%s" + logfileext) % x,(logfilename + "%s" + logfileext) % (x+1))
  89.             logifile.close()
  90.             os.rename(logfilename + logfileext,(logfilename + "1" + logfileext))
  91.             logifile=open(logfilename + logfileext,"x")
  92.     else:
  93.         logifile=open(logfilename + logfileext,"x")
  94.     tmp=[]
  95.     for i in clientused:
  96.         if i not in tmp and i < math.floor(len(listen)/2):
  97.             tmp.append(i)
  98.             print("Allowed %d %s client." % (i,listen[i*2]))
  99.         else:
  100.             print("Unlisted %d (max id %d) client. (if already allowed it's still listed)" % (i,math.floor(len(listen)/2)-1))
  101.     clientused=tmp
  102.     del tmp
  103.     clientamount=len(clientused)
  104.     for i in range(0,math.floor(len(listen)/2)):
  105.         clienttime.append(time.time())
  106.         clienttime.append(defaultstate)
  107.     print ("Starting UDP RELAY SERVER on %s port %s" % server_address)
  108.     if clientamount < 1:
  109.         print("QUITING DUE NO CLIENTS ALLOWED")
  110.         return
  111.  
  112.     sock.bind(server_address)
  113.     #licount=0 #this line is related to notepad++ python console
  114.     strtoprint=""
  115.     global prevpri
  116.     global allclientsbroadcast
  117.     while True:
  118.         try:
  119.             dispwaiting
  120.             dispdrop
  121.         except NameError:
  122.             dispwaiting=threading.Thread(target=listeshow)
  123.             dispwaiting.start()
  124.             dispdrop=threading.Thread(target=dropfollow)
  125.             dispdrop.start()
  126.         else:
  127.             if not dispdrop.is_alive():
  128.                 dispdrop=threading.Thread(target=dropfollow)
  129.                 dispdrop.start()
  130.             if not dispwaiting.is_alive():
  131.                 dispwaiting=threading.Thread(target=listeshow)
  132.                 dispwaiting.start()
  133.  
  134.         try:
  135.             data, address = sock.recvfrom(data_payload)
  136.         except Exception as e:
  137.             console.writeError(str(e))
  138.    
  139.         strtoprint="%s%s\n" % (strtoprint,("[%03d] received %s bytes from %s" % (math.floor(time.time())%1000,len(data), address)))
  140.         #print ("Data: %s" %data)
  141.         ctest=[0,0,0,0]
  142.         cindex=-1
  143.         for x in clientused:
  144.             if listen[x*2][0] == address[0]:
  145.                 ctest[0]=2
  146.             if listen[x*2][1] == address[1]:
  147.                 ctest[1]=2
  148.             if data[6:12] == listen[x*2+1]:
  149.                 ctest[2]=2
  150.             if data and listen[x*2][0] == address[0] and listen[x*2][1] == address[1] and data[6:12] == listen[x*2+1]:
  151.                 ctest[0]=1
  152.                 ctest[1]=1
  153.                 ctest[2]=1
  154.                 clienttime[x*2]=time.time()
  155.                 clienttime[x*2+1]=False
  156.                 cindex=x
  157.                 break
  158.         if cindex != -1:
  159.             if data[:6] == macbroad:
  160.                 ctest[3]=1
  161.                 if allclientsbroadcast or cindex==0:
  162.                     for x in clientused:
  163.                         if x != cindex and (clienttime[x*2]+droptimeout > time.time() or not broadcastonlyactive):
  164.                             sent = mysendpacket(sock,data,listen[x*2])
  165.                             strtoprint="%s%s\n" % (strtoprint,("[%03d] broadcast %s bytes to %s" % (math.floor(time.time())%1000,sent, listen[x*2])))
  166.             else:
  167.                 for x in clientused:
  168.                     if data[:6] == listen[x*2+1]:
  169.                         ctest[3]=2
  170.                         if x != cindex and (clienttime[x*2]+droptimeout > time.time() or not broadcastonlyactive):
  171.                             ctest[3]=1
  172.                             sent = mysendpacket(sock,data,listen[x*2])
  173.                             strtoprint="%s%s\n" % (strtoprint,("[%03d] send %s bytes to %s %s" % (math.floor(time.time())%1000,sent, listen[x*2],data[:6].hex())))
  174.                             break
  175.         if not (ctest[0]==1 and ctest[1]==1 and ctest[2]==1 and ctest[3]==1):
  176.             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())
  177.             tmpbyt=bytearray(tmpstr,"ascii")
  178.             tmpbyt[0]="!" if (ctest[0] == 0) else ("?" if ctest[0] == 2 else " ")
  179.             tmpbyt[16]="!" if (ctest[0] == 0) else ("?" if ctest[0] == 2 else " ")
  180.             tmpbyt[18]="!" if (ctest[1] == 0) else ("?" if ctest[1] == 2 else " ")
  181.             tmpbyt[24]="!" if (ctest[1] == 0) else ("?" if ctest[1] == 2 else " ")
  182.             tmpbyt[26]="!" if (ctest[2] == 0) else ("?" if ctest[2] == 2 else " ")
  183.             tmpbyt[39]="!" if (ctest[2] == 0) else ("?" if ctest[2] == 2 else " ")
  184.             tmpbyt[41]="!" if (ctest[3] == 0) else ("?" if ctest[3] == 2 else " ")
  185.             tmpbyt[54]="!" if (ctest[3] == 0) else ("?" if ctest[3] == 2 else " ")
  186.             tmpstr=tmpbyt.decode("ascii")
  187.             logifile.write(tmpstr)
  188.             logifile.close()
  189.             logifile.open(logfilename + logfileext, 'a')
  190.         strtoprint="%s\n" % strtoprint
  191.         if (prevpri + 0.3 < time.time()):
  192.             prevpri=time.time()
  193.             print(strtoprint,end='')
  194.             strtoprint=""
  195. #        licount+=1 #these 5 lines are related to notepad++ python console
  196. #        if licount > 500:
  197. #            licount=0
  198. #            if console.editor.getCurrentPos() > 50000:
  199. #                console.clear()
  200.  
  201. #sys.stderr = console # remove first "#" to make standard log visible to notepad++ python console
  202. #sys.stdout = console # remove first "#" to make standard log visible to notepad++ python console
  203. try:
  204.     echo_server(serverport)
  205. finally:
  206.     pass
  207.     # logifile.close()
  208.     # if os.path.getsize(logfilename + logfileext) == 0:
  209.         # os.remove(logfilename + logfileext)
Advertisement
Add Comment
Please, Sign In to add comment