Guest User

udp_relay_server.py

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