Guest User

udp_relay_server.py

a guest
Apr 17th, 2022
23
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 21.04 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. def autoip():
  12.     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  13.     try:
  14.         s.connect(('255.255.255.255', 65301))
  15.         IP = s.getsockname()[0]
  16.     except Exception:
  17.         IP = '127.0.0.1'
  18.     finally:
  19.         s.close()
  20.     print("auto get local ip : %s" % IP)
  21.     return IP
  22.  
  23. # virtual guest os:es set to
  24. # Generic Driver
  25. # Name=UDPTunnel
  26. # !check advanced
  27. # Generic Properties
  28. # dest=UDP RELAY SERVER HOST EXTERNAL IP (local ip on server host guest (0th client))
  29. # 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))
  30. # dport=RELAY SERVER ROUTED PORT (setting name serverport)
  31.  
  32. #without encryption data will be visible to middleman attacks
  33.  
  34. #UDP SERVER SERVER external ip in example 111.111.111.111
  35. 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.)
  36. serverport=27000 # port to host UDP RELAY SERVER/CLIENT(if client mode) (packet distributor)
  37. 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)
  38. 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. Here is place for your own local ip if autolocalip fails.
  39.          ('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
  40.          ('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
  41.          ('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
  42. 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))
  43. 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)
  44. broadcastonlyactive = True #if True, broadcast packets are only sent clients that have connected UDP RELAY SERVER (activates settings defaultstate,droptimeout and droppedremind)
  45. 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))
  46. displayfake = True #reports even if broadcastonlyactive is False on timeouts. (console output setting only)
  47. droptimeout = 360 #seconds clients are to remain in packet target if no connection from them.
  48. droppedremind = 120 #seconds bethween reminding dropped clients. (console output setting only)
  49. logfilename="logfile" #log for umatching connections (cannot be disabled) (you can provide file address here (example: "c:/logs/filename"))
  50. logfileext=".txt"
  51. #POSSIBLE MODES
  52. #star mode -> everyone connected to everyone
  53. #            -each of clients are running this script
  54. #            -each of clients known each of connected encryption keys,seeds, if using encryption
  55. #            -everyone must have allclientsbroadcast False, (othervice packets get reflected (duplicated) back to source from who has it on)
  56. #            -self is client 0 on each script
  57. #server - client mode -> everyone is connected to server
  58. #                       -each of clients are running this script, but in different settings look example bellow
  59. #                       -clients have allclientsbroadcast False (othervice packets get reflected (duplicated) back to source from who has it on)
  60. #                       -each client only knows it's own encryption keys,seeds, if using encryption
  61. #                       -self is client 0 on each script
  62. #server only mode -> everyone is connected to server (directly with guest os)
  63. #                   -only server is running this script
  64. #                   -each of clients is connect directly by their guest os
  65. #                   -therefore no encryption possible (if not encrypting directly from guest os)
  66. #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.))
  67. encryptingon=[False,True,True,True] #is encrypting turned on (reseprents client 0-3)
  68. 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)
  69. cryptseed=[123, #lan does not require enryption. client 0
  70.            1234567899876543210000000123, #use any, but high numbers recomended. client 1
  71.            1234567899876543210000000231, #use any, but high numbers recomended. client 2
  72.            1234567899876543210000000213] #use any, but high numbers recomended. client 3
  73. cryptpassword=["5341", #lan does not require enryption. client 0
  74.                "0123456789abcdeffedcba98765432100123", #use any, long key recomended & amount of hex divisable by 2. client 1
  75.                "0123456789abcdeffedcba98765432100231", #use any, long key recomended & amount of hex divisable by 2. client 2
  76.                "0123456789abcdeffedcba98765432100213"] #use any, long key recomended & amount of hex divisable by 2. client 3
  77. #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)
  78. #import secrets
  79. #print(secrets.randbelow(1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000))
  80. #print(secrets.token_hex(60))
  81. #CLIENTMODE DEFAULT SETTINGS (example client 1)
  82. #allclientsbroadcast = False #don't send broadcast recived back, so we don't stuck on infinite loop
  83. #broadcastonlyactive = False #always send packets even if normally would be disconnected so we can re-etablish
  84. #displayfake = True #helps determine wheter connection has been disconnected
  85. #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)
  86. #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
  87. #        ('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
  88. #        ('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
  89. #        ('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
  90. #encryptingon=[False,True,True,True] #is encrypting turned on (reseprents client 1,0,2,3) (use client 1 enc, except on first one)
  91. #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)
  92. #cryptseed=[123, #lan does not require enryption. client 1
  93. #           1234567899876543210000000123, #use any, but high numbers recomended. client 0 (use client 1 enc)
  94. #           1234567899876543210000000123, #use any, but high numbers recomended. client 2 (use client 1 enc)
  95. #           1234567899876543210000000123] #use any, but high numbers recomended. client 3 (use client 1 enc)
  96. #cryptpassword=["5341", #lan does not require enryption. client 1
  97. #               "0123456789abcdeffedcba98765432100123", #use any, long key recomended & amount of hex divisable by 2. client 0 (use client 1 enc)
  98. #               "0123456789abcdeffedcba98765432100123", #use any, long key recomended & amount of hex divisable by 2. client 2 (use client 1 enc)
  99. #               "0123456789abcdeffedcba98765432100123"] #use any, long key recomended & amount of hex divisable by 2. client 3 (use client 1 enc)
  100. #NO MORE SETTINGS TO CONFIGURE AFTER THIS LINE
  101. if len(cryptlvl) != len(cryptseed) or len(cryptseed) != len(cryptpassword) or len(cryptseed) != len(encryptingon):
  102.     raise ValueError("Error:encryption keys/seeds not same length.")
  103. cryptlevel=[0]*len(cryptlvl)
  104. cryptmask=["0"]*len(cryptlvl)
  105. for i in range(0,len(cryptlvl)):
  106.     cryptlevel[i]=2 ** cryptlvl[i] if cryptlvl[i] <= 3 else 8
  107.     cryptmask[i]=math.floor(256**(1/2**(cryptlvl[i] if cryptlvl[i] <= 3 else 3)))-1
  108. macbroad=b'\xff\xff\xff\xff\xff\xff' #do not touch (broadcast mac address)
  109. clientamount=4 #does nothing (gets auto set by clientused)
  110. clienttime=[]
  111. logifile=open(logfilename + logfileext, 'a')
  112. prevpri=time.time() - 10.0
  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.             myoutip=socket.gethostbyname_ex(listen[i*2][0])[2][0]
  243.             print("%s as resolved address." % myoutip)
  244.             listen[i*2]=(myoutip,listen[i*2][1])
  245.         else:
  246.             print("Unlisted %d (max id %d) client. (if already allowed it's still listed)" % (i,math.floor(len(listen)/2)-1))
  247.     clientused=tmp
  248.     del tmp
  249.     clientamount=len(clientused)
  250.     if clientamount > len(encryptingon):
  251.         raise ValueError("Error:Not enough encrypt states")
  252.     for i in range(0,math.floor(len(listen)/2)):
  253.         clienttime.append(time.time())
  254.         clienttime.append(defaultstate)
  255.     print ("Starting UDP RELAY SERVER on %s port %s" % server_address)
  256.     if clientamount < 1:
  257.         print("QUITING DUE NO CLIENTS ALLOWED")
  258.         return
  259.  
  260.     sock.bind(server_address)
  261.     #licount=0 #this line is related to notepad++ python console
  262.     strtoprint=""
  263.     global prevpri
  264.     global allclientsbroadcast
  265.     while True:
  266.         try:
  267.             dispwaiting
  268.         except NameError:
  269.             dispwaiting=threading.Thread(target=listeshow)
  270.             dispwaiting.start()
  271.             if broadcastonlyactive or displayfake:
  272.                 dispdrop=threading.Thread(target=dropfollow)
  273.                 dispdrop.start()
  274.         else:
  275.             if broadcastonlyactive or displayfake:
  276.                 if not dispdrop.is_alive():
  277.                     dispdrop=threading.Thread(target=dropfollow)
  278.                     dispdrop.start()
  279.             if not dispwaiting.is_alive():
  280.                 dispwaiting=threading.Thread(target=listeshow)
  281.                 dispwaiting.start()
  282.         ctest=[0,0,0,0]
  283.         try:
  284.             data, address = sock.recvfrom(data_payload)
  285.             tmp=-1
  286.             for x in clientused:
  287.                 if listen[x*2][0] == address[0]:
  288.                     ctest[0]=2
  289.                 if listen[x*2][1] == address[1]:
  290.                     ctest[1]=2
  291.                 if listen[x*2][0] == address[0] and listen[x*2][1] == address[1]:
  292.                     ctest[0]=2
  293.                     ctest[1]=2
  294.                     tmp=x
  295.                     break
  296.             if tmp != -1:
  297.                 if encryptingon[tmp]:
  298.                     data=crypt(data,cryptpassword[tmp],cryptseed[tmp],False,(cryptlvl[tmp],cryptlevel[tmp],cryptmask[tmp]))
  299.         except Exception as e:
  300.             print(str(e))
  301.         strtoprint="%s%s\n" % (strtoprint,("[%03d] received %s bytes from %s" % (math.floor(time.time())%1000,len(data), address)))
  302.         #print ("Data: %s" %data)
  303.         cindex=-1
  304.         deta=data
  305.         for x in clientused:
  306.             if data[6:12] == listen[x*2+1]:
  307.                 ctest[2]=2
  308.             if data and listen[x*2][0] == address[0] and listen[x*2][1] == address[1] and data[6:12] == listen[x*2+1]:
  309.                 ctest[0]=1
  310.                 ctest[1]=1
  311.                 ctest[2]=1
  312.                 clienttime[x*2]=time.time()
  313.                 clienttime[x*2+1]=False
  314.                 cindex=x
  315.                 break
  316.         if cindex != -1:
  317.             if data[:6] == macbroad:
  318.                 ctest[3]=1
  319.                 if allclientsbroadcast or cindex==0:
  320.                     for x in clientused:
  321.                         if x != cindex and (not clienttime[x*2+1] or not broadcastonlyactive):
  322.                             if encryptingon[x]:
  323.                                 deta=crypt(data,cryptpassword[x],cryptseed[x],True,(cryptlvl[x],cryptlevel[x],cryptmask[x]))
  324.                             else:
  325.                                 deta=data
  326.                             sent = mysendpacket(sock,deta,listen[x*2])
  327.                             strtoprint="%s%s\n" % (strtoprint,("[%03d] broadcast %s bytes to %s" % (math.floor(time.time())%1000,sent, listen[x*2])))
  328.                 else:
  329.                     if encryptingon[0]:
  330.                         deta=crypt(data,cryptpassword[0],cryptseed[0],True,(cryptlvl[0],cryptlevel[0],cryptmask[0]))
  331.                     else:
  332.                         deta=data
  333.                     sent = mysendpacket(sock,deta,listen[0*2])
  334.                     strtoprint="%s%s\n" % (strtoprint,("[%03d] handled localbroadcast %s bytes to %s" % (math.floor(time.time())%1000,len(deta), listen[0*2])))
  335.             else:
  336.                 for x in clientused:
  337.                     if data[:6] == listen[x*2+1]:
  338.                         ctest[3]=2
  339.                         if x != cindex and (not clienttime[x*2+1] or not broadcastonlyactive):
  340.                             if encryptingon[x]:
  341.                                 deta=crypt(data,cryptpassword[x],cryptseed[x],True,(cryptlvl[x],cryptlevel[x],cryptmask[x]))
  342.                             else:
  343.                                 deta=data
  344.                             ctest[3]=1
  345.                             sent = mysendpacket(sock,deta,listen[x*2])
  346.                             strtoprint="%s%s\n" % (strtoprint,("[%03d] send %s bytes to %s %s" % (math.floor(time.time())%1000,sent, listen[x*2],data[:6].hex())))
  347.                             break
  348.         if not (ctest[0]==1 and ctest[1]==1 and ctest[2]==1 and ctest[3]==1):
  349.             if cindex == -1:
  350.                 tmpstr=" %15s   %05i   %s   %s  %s\n" % (address[0],address[1],deta[:6].hex(),deta[6:12].hex(),deta[12:].hex())
  351.             else:
  352.                 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())
  353.             tmpbyt=bytearray(tmpstr,"ascii") #33 -> "!" 63 -> "?" 32 -> " "
  354.             tmpbyt[0]=33 if (ctest[0] == 0) else (63 if ctest[0] == 2 else 32)
  355.             tmpbyt[16]=33 if (ctest[0] == 0) else (63 if ctest[0] == 2 else 32)
  356.            
  357.             tmpbyt[18]=33 if (ctest[1] == 0) else (63 if ctest[1] == 2 else 32)
  358.             tmpbyt[24]=33 if (ctest[1] == 0) else (63 if ctest[1] == 2 else 32)
  359.            
  360.             tmpbyt[26]=33 if (ctest[3] == 0) else (63 if ctest[3] == 2 else 32)
  361.             tmpbyt[39]=33 if (ctest[3] == 0) else (63 if ctest[3] == 2 else 32)
  362.            
  363.             tmpbyt[41]=33 if (ctest[2] == 0) else (63 if ctest[2] == 2 else 32)
  364.             tmpbyt[54]=33 if (ctest[2] == 0) else (63 if ctest[2] == 2 else 32)
  365.             tmpstr=tmpbyt.decode("ascii")
  366.             try:
  367.                 logifile.write(tmpstr)
  368.                 logifile.close()
  369.                 logifile=open(logfilename + logfileext, 'a')
  370.             except Exception as e:
  371.                 print("Logfile failure.")
  372.                 print(str(e))
  373.         strtoprint="%s\n" % strtoprint
  374.         if (prevpri + 0.3 < time.time()):
  375.             prevpri=time.time()
  376.             print(strtoprint,end='')
  377.             strtoprint=""
  378. #        licount+=1 #these 5 lines are related to notepad++ python console
  379. #        if licount > 500:
  380. #            licount=0
  381. #            if console.editor.getCurrentPos() > 50000:
  382. #                console.clear()
  383.  
  384. #sys.stderr = console # remove first "#" to make standard log visible to notepad++ python console
  385. #sys.stdout = console # remove first "#" to make standard log visible to notepad++ python console
  386. try:
  387.     echo_server(serverport)
  388. finally:
  389.     pass
  390.     # logifile.close()
  391.     # if os.path.getsize(logfilename + logfileext) == 0:
  392.         # os.remove(logfilename + logfileext)
Add Comment
Please, Sign In to add comment