Guest User

udp_relay_server.py

a guest
Dec 8th, 2021
29
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 20.82 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. import random
  10.  
  11. # virtual guest os:es set to
  12. # Generic Driver
  13. # Name=UDPTunnel
  14. # !check advanced
  15. # Generic Properties
  16. # dest=UDP RELAY SERVER HOST EXTERNAL IP (local ip on server host guest (0th client))
  17. # 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))
  18. # dport=RELAY SERVER ROUTED PORT (setting name serverport)
  19.  
  20. #without encryption data will be visible to middleman attacks
  21.  
  22. #UDP SERVER SERVER external ip in example 111.111.111.111
  23. autolocalip=autoip() # DO NOT EDIT, this for autoconfiguring local ip (example ip 192.168.100.20 if we got 127.0.0.1 something failed, if we got external address looking address then you probably have bridging internet connection don't worry it still works.)
  24. serverport=27000 # port to host UDP RELAY SERVER/CLIENT(if client mode) (packet distributor)
  25. 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)
  26. listen= ((autolocalip, 26000)     ,b'\x08\x00\x27\xff\xff\x00', # 0th enter here your server local ip + sport of virtual machine + your guest os virtual network card mac
  27.          ('123.123.123.123',26000),b'\x08\x00\x27\xff\xff\x01', # 1st client ip of his/her host + sport value + 1st client guest os virtual network card mac
  28.          ('231.231.231.231',26000),b'\x08\x00\x27\xff\xff\x02', # 2nd client ip of his/her host + sport value + 2nd client guest os virtual network card mac
  29.          ('213.213.213.213',26000),b'\x08\x00\x27\xff\xff\x03') # 3rd client ip of his/her host + sport value + 3rd client guest os virtual network card mac
  30. 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))
  31. 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 True if server is running without guest os)
  32. broadcastonlyactive = True #if True, broadcast packets are only sent clients that have connected UDP RELAY SERVER (activates settings defaultstate,droptimeout and droppedremind)
  33. 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 (UDP RELAY SERVER))
  34. displayfake = True #reports even if broadcastonlyactive is False on timeouts. (console output setting only)
  35. droptimeout = 360 #seconds clients are to remain in packet target if no connection from them.
  36. droppedremind = 120 #seconds bethween reminding dropped clients. (console output setting only)
  37. logfilename="logfile" #log for umatching connections (cannot be disabled) (you can provide file address here (example: "c:/logs/filename"))
  38. logfileext=".txt"
  39. #POSSIBLE MODES
  40. #star mode -> everyone connected to everyone
  41. #            -each of clients are running this script
  42. #            -each of clients known each of connected encryption keys,seeds, if using encryption
  43. #            -everyone must have allclientsbroadcast False, (othervice packets get reflected (duplicated) back to source from who has it on)
  44. #            -self is client 0 on each script
  45. #server - client mode -> everyone is connected to server
  46. #                       -each of clients are running this script, but in different settings look example bellow
  47. #                       -clients have allclientsbroadcast False (othervice packets get reflected (duplicated) back to source from who has it on)
  48. #                       -each client only knows it's own encryption keys,seeds, if using encryption
  49. #                       -self is client 0 on each script
  50. #server only mode -> everyone is connected to server (directly with guest os)
  51. #                   -only server is running this script
  52. #                   -each of clients is connect directly by their guest os
  53. #                   -therefore no encryption possible (if not encrypting directly from guest os)
  54. #encrypting settings (only possible on client mode system, where each client runs this script as client to communicate bethween UDP RELAY SERVER and from there to others (unless you manage encrypt network traffic at base level at guest os:es.))
  55. encryptingon=[False,True,True,True] #is encrypting turned on (reseprents client 0-3)
  56. cryptlvl=[0,1,1,1] #encryption level 0 byte at time, 1 half byte at time, 2 quarter byte at time, 3 bit at time (higher number better encryption but slower encrypting)(reseprents client 0-3)
  57. cryptseed=[123, #lan does not require enryption. client 0
  58.            1234567899876543210000000123, #use any, but high numbers recomended. client 1
  59.            1234567899876543210000000231, #use any, but high numbers recomended. client 2
  60.            1234567899876543210000000213] #use any, but high numbers recomended. client 3
  61. cryptpassword=["5341", #lan does not require enryption. client 0
  62.                "0123456789abcdeffedcba98765432100123", #use any, long key recomended & amount of hex divisable by 2. client 1
  63.                "0123456789abcdeffedcba98765432100231", #use any, long key recomended & amount of hex divisable by 2. client 2
  64.                "0123456789abcdeffedcba98765432100213"] #use any, long key recomended & amount of hex divisable by 2. client 3
  65. #use this on python to get safe codes (next 3 lines)(you still have to check that it is divisable for 2 hex when mentioned)
  66. #import secrets
  67. #print(secrets.randbelow(1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000))
  68. #print(secrets.token_hex(60))
  69. #CLIENTMODE DEFAULT SETTINGS (example client 1)
  70. #allclientsbroadcast = False #don't send broadcast recived back, so we don't stuck on infinite loop
  71. #broadcastonlyactive = False #always send packets even if normally would be disconnected so we can re-etablish
  72. #displayfake = True #helps determine wheter connection has been disconnected
  73. #clientused=[0,1,2,3] #list all used client slots (client side server is client 1 and client 0 is client 1 in UDP REALAY SERVER list(tuple)
  74. #listen=(('192.168.100.20', 26000),b'\x08\x00\x27\xff\xff\x01', #local ip of the client connecting to UDP RELAY SERVER,sport of that user (client 1) guest os, that user (client 1) guest os mac
  75. #        ('111.111.111.111',27000),b'\x08\x00\x27\xff\xff\x00', #UDP RELAY SERVER external ip, serverport setting of the UDP RELAY SERVER, client 0 server host guest os mac
  76. #        ('111.111.111.111',27000),b'\x08\x00\x27\xff\xff\x02', #UDP RELAY SERVER external ip, serverport setting of the UDP RELAY SERVER, client 2 host guest os mac
  77. #        ('111.111.111.111',27000),b'\x08\x00\x27\xff\xff\x03') #UDP RELAY SERVER external ip, serverport setting of the UDP RELAY SERVER, client 3 host guest os mac
  78. #encryptingon=[False,True,True,True] #is encrypting turned on (reseprents client 1,0,2,3) (use client 1 enc, except on first one)
  79. #cryptlvl=[0,1,1,1] #encryption level 0 byte at time, 1 half byte at time, 2 quarter byte at time, 3 bit at time (higher number better encryption but slower encrypting)(reseprents client 1,0,2,3) (use client 1 enc, except on first one)
  80. #cryptseed=[123, #lan does not require enryption. client 1
  81. #           1234567899876543210000000123, #use any, but high numbers recomended. client 0 (use client 1 enc)
  82. #           1234567899876543210000000123, #use any, but high numbers recomended. client 2 (use client 1 enc)
  83. #           1234567899876543210000000123] #use any, but high numbers recomended. client 3 (use client 1 enc)
  84. #cryptpassword=["5341", #lan does not require enryption. client 1
  85. #               "0123456789abcdeffedcba98765432100123", #use any, long key recomended & amount of hex divisable by 2. client 0 (use client 1 enc)
  86. #               "0123456789abcdeffedcba98765432100123", #use any, long key recomended & amount of hex divisable by 2. client 2 (use client 1 enc)
  87. #               "0123456789abcdeffedcba98765432100123"] #use any, long key recomended & amount of hex divisable by 2. client 3 (use client 1 enc)
  88. #NO MORE SETTINGS TO CONFIGURE AFTER THIS LINE
  89. if len(cryptlvl) != len(cryptseed) or len(cryptseed) != len(cryptpassword) or len(cryptseed) != len(encryptingon):
  90.     raise ValueError("Error:encryption keys/seeds not same length.")
  91. cryptlevel=[0]*len(cryptlvl)
  92. cryptmask=["0"]*len(cryptlvl)
  93. for i in range(0,len(cryptlvl)):
  94.     cryptlevel[i]=2 ** cryptlvl[i] if cryptlvl[i] <= 3 else 8
  95.     cryptmask[i]=math.floor(256**(1/2**(cryptlvl[i] if cryptlvl[i] <= 3 else 3)))-1
  96. macbroad=b'\xff\xff\xff\xff\xff\xff' #do not touch (broadcast mac address)
  97. clientamount=4 #does nothing (gets auto set by clientused)
  98. clienttime=[]
  99. logifile=open(logfilename + logfileext, 'a')
  100. prevpri=time.time() - 10.0
  101.  
  102. def autoip():
  103.     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  104.     try:
  105.         s.connect(('255.255.255.255', 65301))
  106.         IP = s.getsockname()[0]
  107.     except Exception:
  108.         IP = '127.0.0.1'
  109.     finally:
  110.         s.close()
  111.     print("auto get local ip : %s" % IP)
  112.     return IP
  113.  
  114. def listeshow():
  115.     global prevpri
  116.     while True:
  117.         if prevpri + 2.5 < time.time():
  118.             print ("[%03d] Waiting to receive message from client" % (math.floor(time.time())%1000) )
  119.             return
  120.         time.sleep(0.05)
  121.  
  122. def quitdetect():
  123.     infod=[False,False]
  124.     while msvcrt.kbhit():
  125.         if msvcrt.getch()==b'\x1b':
  126.             infod[1]=True
  127.         else:
  128.             infod[0]=True
  129.     if infod[1]:
  130.         print("Quiting...")
  131.         os.abort()
  132.     elif infod[0]:
  133.         print("Key press detected. Kill process with Escape")
  134.  
  135. def dropfollow():
  136.     global clienttime
  137.     global clientused
  138.     while True:
  139.         for x in clientused:
  140.             if clienttime[x*2] + droptimeout < time.time() and not clienttime[x*2+1]:
  141.                 print("[%03d] %s dropped from connection.%s" % (math.floor(time.time())%1000,listen[x*2],"fake" if not broadcastonlyactive else ""))
  142.                 clienttime[x*2+1]=True
  143.                 clienttime[x*2]=time.time()
  144.             elif clienttime[x*2+1] and clienttime[x*2] + droppedremind < time.time():
  145.                 print("[%03d] %s still down...%s" % (math.floor(time.time())%1000,listen[x*2],"fake" if not broadcastonlyactive else ""))
  146.                 clienttime[x*2]=time.time()
  147.         quitdetect()
  148.         time.sleep(1.0)
  149.  
  150. def mysendpacket(sock,data,target):
  151.     try:
  152.         return sock.sendto(data,target)
  153.     except Exception as e:
  154.         print(str(e))
  155.     return -1
  156.  
  157. def getpartbyte(mybytes,part,info):
  158.     cryptlvl=info[0]
  159.     cryptlevel=info[1]
  160.     cryptmask=info[2]
  161.     if cryptlvl == 0:
  162.         return mybytes[part]
  163.     return (mybytes[part//cryptlevel] >> ((8 // cryptlevel)*(part % cryptlevel))) & cryptmask
  164.  
  165. def setpartbyte(mybytes,part,what,info):
  166.     cryptlvl=info[0]
  167.     cryptlevel=info[1]
  168.     cryptmask=info[2]
  169.     if cryptlvl == 0:
  170.         mybytes[part]=what
  171.         return
  172.     drop=(8 // cryptlevel)*(part % cryptlevel)
  173.     mask=255 - (cryptmask << drop)
  174.     mybytes[part//cryptlevel]=mybytes[part//cryptlevel] & mask | what << drop
  175.  
  176. def crypt(data,password,seed,encrypt,info):
  177.     datalen=len(data)
  178.     pdata=bytearray(data)
  179.     passlen=len(password)
  180.     random.seed(seed,2)
  181.     if encrypt:
  182.         curbyte=0
  183.         while curbyte < datalen:
  184.             pdata[curbyte]=(pdata[curbyte] + password[curbyte%passlen])%256
  185.             curbyte+=1
  186.         curbyte=0
  187.         while curbyte < datalen*info[1]-1:
  188.             swap=getpartbyte(pdata,curbyte,info)
  189.             num=random.randrange(curbyte,datalen*info[1])
  190.             setpartbyte(pdata,curbyte,getpartbyte(pdata,num,info),info)
  191.             setpartbyte(pdata,num,swap,info)
  192.             curbyte+=1
  193.     else:
  194.         randomnums=[0] * (datalen*info[1]-1)
  195.         for i in range(0,datalen*info[1]-1):
  196.             randomnums[i]=random.randrange(i,datalen*info[1])
  197.         curbyte=datalen*info[1]-2
  198.         while curbyte >= 0:
  199.             num=randomnums[curbyte]
  200.             swap=getpartbyte(pdata,num,info)
  201.             setpartbyte(pdata,num,getpartbyte(pdata,curbyte,info),info)
  202.             setpartbyte(pdata,curbyte,swap,info)
  203.             curbyte-=1
  204.         curbyte=0
  205.         while curbyte < datalen:
  206.             pdata[curbyte]=(pdata[curbyte] - password[curbyte%passlen])%256
  207.             curbyte+=1
  208.     return pdata
  209.  
  210. def echo_server(port):
  211.     global cryptpassword
  212.     for x in range(0,len(cryptpassword)):
  213.         cryptpassword[x]=bytearray.fromhex(cryptpassword[x])
  214.     # Create a UDP socket
  215.     sock = socket.socket(socket.AF_INET,
  216.                          socket.SOCK_DGRAM)
  217.  
  218.     # Bind the socket to the port
  219.     server_address = (listen[0][0], port)
  220.     global logifile
  221.     global clienttime
  222.     global clientused
  223.     if exists(logfilename + logfileext):
  224.         if os.path.getsize(logfilename + logfileext) == 0:
  225.             pass
  226.         else:
  227.             if exists(logfilename + "9" + logfileext):
  228.                 os.remove(logfilename + "9" + logfileext)
  229.             for x in range(8,0,-1):
  230.                 if exists((logfilename + "%s" + logfileext) % x):
  231.                     os.rename((logfilename + "%s" + logfileext) % x,(logfilename + "%s" + logfileext) % (x+1))
  232.             logifile.close()
  233.             os.rename(logfilename + logfileext,(logfilename + "1" + logfileext))
  234.             logifile=open(logfilename + logfileext,"x")
  235.     else:
  236.         logifile=open(logfilename + logfileext,"x")
  237.     tmp=[]
  238.     for i in clientused:
  239.         if i not in tmp and i < math.floor(len(listen)/2):
  240.             tmp.append(i)
  241.             print("Allowed %d %s client." % (i,listen[i*2]))
  242.         else:
  243.             print("Unlisted %d (max id %d) client. (if already allowed it's still listed)" % (i,math.floor(len(listen)/2)-1))
  244.     clientused=tmp
  245.     del tmp
  246.     clientamount=len(clientused)
  247.     if clientamount > len(encryptingon):
  248.         raise ValueError("Error:Not enough encrypt states")
  249.     for i in range(0,math.floor(len(listen)/2)):
  250.         clienttime.append(time.time())
  251.         clienttime.append(defaultstate)
  252.     print ("Starting UDP RELAY SERVER on %s port %s" % server_address)
  253.     if clientamount < 1:
  254.         print("QUITING DUE NO CLIENTS ALLOWED")
  255.         return
  256.  
  257.     sock.bind(server_address)
  258.     #licount=0 #this line is related to notepad++ python console
  259.     strtoprint=""
  260.     global prevpri
  261.     global allclientsbroadcast
  262.     while True:
  263.         try:
  264.             dispwaiting
  265.         except NameError:
  266.             dispwaiting=threading.Thread(target=listeshow)
  267.             dispwaiting.start()
  268.             if broadcastonlyactive or displayfake:
  269.                 dispdrop=threading.Thread(target=dropfollow)
  270.                 dispdrop.start()
  271.         else:
  272.             if broadcastonlyactive or displayfake:
  273.                 if not dispdrop.is_alive():
  274.                     dispdrop=threading.Thread(target=dropfollow)
  275.                     dispdrop.start()
  276.             if not dispwaiting.is_alive():
  277.                 dispwaiting=threading.Thread(target=listeshow)
  278.                 dispwaiting.start()
  279.         ctest=[0,0,0,0]
  280.         try:
  281.             data, address = sock.recvfrom(data_payload)
  282.             tmp=-1
  283.             for x in clientused:
  284.                 if listen[x*2][0] == address[0]:
  285.                     ctest[0]=2
  286.                 if listen[x*2][1] == address[1]:
  287.                     ctest[1]=2
  288.                 if listen[x*2][0] == address[0] and listen[x*2][1] == address[1]:
  289.                     ctest[0]=2
  290.                     ctest[1]=2
  291.                     tmp=x
  292.                     break
  293.             if tmp != -1:
  294.                 if encryptingon[tmp]:
  295.                     data=crypt(data,cryptpassword[tmp],cryptseed[tmp],False,(cryptlvl[tmp],cryptlevel[tmp],cryptmask[tmp]))
  296.         except Exception as e:
  297.             print(str(e))
  298.         strtoprint="%s%s\n" % (strtoprint,("[%03d] received %s bytes from %s" % (math.floor(time.time())%1000,len(data), address)))
  299.         #print ("Data: %s" %data)
  300.         cindex=-1
  301.         deta=data
  302.         for x in clientused:
  303.             if data[6:12] == listen[x*2+1]:
  304.                 ctest[2]=2
  305.             if data and listen[x*2][0] == address[0] and listen[x*2][1] == address[1] and data[6:12] == listen[x*2+1]:
  306.                 ctest[0]=1
  307.                 ctest[1]=1
  308.                 ctest[2]=1
  309.                 clienttime[x*2]=time.time()
  310.                 clienttime[x*2+1]=False
  311.                 cindex=x
  312.                 break
  313.         if cindex != -1:
  314.             if data[:6] == macbroad:
  315.                 ctest[3]=1
  316.                 if allclientsbroadcast or cindex==0:
  317.                     for x in clientused:
  318.                         if x != cindex and (not clienttime[x*2+1] or not broadcastonlyactive):
  319.                             if encryptingon[x]:
  320.                                 deta=crypt(data,cryptpassword[x],cryptseed[x],True,(cryptlvl[x],cryptlevel[x],cryptmask[x]))
  321.                             else:
  322.                                 deta=data
  323.                             sent = mysendpacket(sock,deta,listen[x*2])
  324.                             strtoprint="%s%s\n" % (strtoprint,("[%03d] broadcast %s bytes to %s" % (math.floor(time.time())%1000,sent, listen[x*2])))
  325.                 else:
  326.                     if encryptingon[0]:
  327.                         deta=crypt(data,cryptpassword[0],cryptseed[0],True,(cryptlvl[0],cryptlevel[0],cryptmask[0]))
  328.                     else:
  329.                         deta=data
  330.                     sent = mysendpacket(sock,deta,listen[0*2])
  331.                     strtoprint="%s%s\n" % (strtoprint,("[%03d] handled localbroadcast %s bytes to %s" % (math.floor(time.time())%1000,len(deta), listen[0*2])))
  332.             else:
  333.                 for x in clientused:
  334.                     if data[:6] == listen[x*2+1]:
  335.                         ctest[3]=2
  336.                         if x != cindex and (not clienttime[x*2+1] or not broadcastonlyactive):
  337.                             if encryptingon[x]:
  338.                                 deta=crypt(data,cryptpassword[x],cryptseed[x],True,(cryptlvl[x],cryptlevel[x],cryptmask[x]))
  339.                             else:
  340.                                 deta=data
  341.                             ctest[3]=1
  342.                             sent = mysendpacket(sock,deta,listen[x*2])
  343.                             strtoprint="%s%s\n" % (strtoprint,("[%03d] send %s bytes to %s %s" % (math.floor(time.time())%1000,sent, listen[x*2],data[:6].hex())))
  344.                             break
  345.         if not (ctest[0]==1 and ctest[1]==1 and ctest[2]==1 and ctest[3]==1):
  346.             if cindex == -1:
  347.                 tmpstr=" %15s   %05i   %s   %s  %s\n" % (address[0],address[1],deta[:6].hex(),deta[6:12].hex(),deta[12:].hex())
  348.             else:
  349.                 tmpstr=" %15s   %05i   %s   %s  %s\n" % (listen[cindex*2][0],listen[cindex*2][1],deta[:6].hex(),deta[6:12].hex(),deta[12:].hex())
  350.             tmpbyt=bytearray(tmpstr,"ascii") #33 -> "!" 63 -> "?" 32 -> " "
  351.             tmpbyt[0]=33 if (ctest[0] == 0) else (63 if ctest[0] == 2 else 32)
  352.             tmpbyt[16]=33 if (ctest[0] == 0) else (63 if ctest[0] == 2 else 32)
  353.            
  354.             tmpbyt[18]=33 if (ctest[1] == 0) else (63 if ctest[1] == 2 else 32)
  355.             tmpbyt[24]=33 if (ctest[1] == 0) else (63 if ctest[1] == 2 else 32)
  356.            
  357.             tmpbyt[26]=33 if (ctest[3] == 0) else (63 if ctest[3] == 2 else 32)
  358.             tmpbyt[39]=33 if (ctest[3] == 0) else (63 if ctest[3] == 2 else 32)
  359.            
  360.             tmpbyt[41]=33 if (ctest[2] == 0) else (63 if ctest[2] == 2 else 32)
  361.             tmpbyt[54]=33 if (ctest[2] == 0) else (63 if ctest[2] == 2 else 32)
  362.             tmpstr=tmpbyt.decode("ascii")
  363.             try:
  364.                 logifile.write(tmpstr)
  365.                 logifile.close()
  366.                 logifile=open(logfilename + logfileext, 'a')
  367.             except Exception as e:
  368.                 print("Logfile failure.")
  369.                 print(str(e))
  370.         strtoprint="%s\n" % strtoprint
  371.         if (prevpri + 0.3 < time.time()):
  372.             prevpri=time.time()
  373.             print(strtoprint,end='')
  374.             strtoprint=""
  375. #        licount+=1 #these 5 lines are related to notepad++ python console
  376. #        if licount > 500:
  377. #            licount=0
  378. #            if console.editor.getCurrentPos() > 50000:
  379. #                console.clear()
  380.  
  381. #sys.stderr = console # remove first "#" to make standard log visible to notepad++ python console
  382. #sys.stdout = console # remove first "#" to make standard log visible to notepad++ python console
  383. try:
  384.     echo_server(serverport)
  385. finally:
  386.     pass
  387.     # logifile.close()
  388.     # if os.path.getsize(logfilename + logfileext) == 0:
  389.         # os.remove(logfilename + logfileext)
Add Comment
Please, Sign In to add comment