Advertisement
Guest User

Untitled

a guest
May 25th, 2018
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.11 KB | None | 0 0
  1. # Author: Nicolas VERDIER (contact@n1nj4.eu)
  2. # This file is part of pr0cks.
  3. #
  4. # pr0cks is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # pr0cks is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with pr0cks. If not, see <http://www.gnu.org/licenses/>.
  16.  
  17. import sys
  18. import StringIO
  19. import time
  20. import struct
  21. import os
  22. import asyncore
  23. import socket
  24. import socks
  25. import argparse
  26. import traceback
  27. import logging
  28. logging.basicConfig(stream=sys.stderr, level=logging.WARNING)
  29. import binascii
  30. from collections import OrderedDict
  31.  
  32. dnslib_imported=False
  33. dns_cache=OrderedDict()
  34. DNS_CACHE_SIZE=1000
  35.  
  36. def display(msg):
  37. msg=msg.strip()
  38. if msg.startswith("[-]"):
  39. print "\033[31m[-]\033[0m"+msg[3:]
  40. elif msg.startswith("[+]"):
  41. print "\033[32m[+]\033[0m"+msg[3:]
  42. elif msg.startswith("[i]"):
  43. print "\033[1;30m[i]\033[0m"+msg[3:]
  44. else:
  45. print msg
  46.  
  47. try:
  48. from dnslib import DNSRecord, QTYPE
  49. from dnslib.server import DNSServer,DNSHandler,BaseResolver,DNSLogger
  50. class ProxyResolver(BaseResolver):
  51. def __init__(self,address,port):
  52. self.address = address
  53. self.port = port
  54.  
  55. def resolve(self,request,handler):
  56. if handler.protocol == 'udp':
  57. proxy_r = request.send(self.address,self.port)
  58. else:
  59. proxy_r = request.send(self.address,self.port,tcp=True)
  60. reply = DNSRecord.parse(proxy_r)
  61. return reply
  62.  
  63. class PassthroughDNSHandler(DNSHandler):
  64. def get_reply(self,data):
  65. global dns_cache
  66. global args
  67. host,port = self.server.resolver.address,self.server.resolver.port
  68. request = DNSRecord.parse(data)
  69.  
  70.  
  71. domain=str(request.q.qname)
  72. qtype=str(QTYPE.get(request.q.qtype))
  73. index=domain+"/"+qtype
  74. if not args.no_cache and index in dns_cache:
  75. if time.time()<dns_cache[index][0]:
  76. if args is not None and args.verbose:
  77. try:
  78. display("[i] %s served value from cache: %s"%(index, ', '.join([x.rdata for x in dns_cache[index][1]])))
  79. except:
  80. pass
  81. rep=request.reply()
  82. rep.add_answer(*dns_cache[index][1])
  83. return rep.pack()
  84. if args is not None and args.verbose:
  85. display("[i] domain %s requested using TCP server %s"%(domain, args.dns_server))
  86.  
  87. # CubeKirito's Code
  88. result_domain = ""
  89. if domain.split(".")[0] == "www":
  90. for val in domain.split("."):
  91. if val != "www": result_domain = result_domain + val
  92. result_domain = "http://" + result_domain + ":80"
  93. display("[i] result domain: %s"%(result_domain))
  94.  
  95. data = struct.pack("!H",len(data)) + data
  96. response = send_tcp(data,host,port)
  97. response = response[2:]
  98. reply = DNSRecord.parse(response)
  99. if args.verbose:
  100. try:
  101. display("[i] %s %s resolve to %s"%(domain, qtype, ', '.join([x.rdata for x in reply.rr])))
  102. except:
  103. pass
  104. ttl=3600
  105. try:
  106. ttl=reply.rr[0].ttl
  107. except Exception:
  108. try:
  109. ttl=reply.rr.ttl
  110. except Exception:
  111. pass
  112. dns_cache[index]=(int(time.time())+ttl, reply.rr)
  113. if len(dns_cache)>DNS_CACHE_SIZE:
  114. dns_cache.popitem(last=False)
  115. return response
  116.  
  117. def send_tcp(data,host,port):
  118. """
  119. Helper function to send/receive DNS TCP request
  120. (in/out packets will have prepended TCP length header)
  121. """
  122. sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  123. sock.settimeout(5)
  124. sock.connect((host,port))
  125. sock.sendall(data)
  126. response = sock.recv(8192)
  127. length = struct.unpack("!H",bytes(response[:2]))[0]
  128. while len(response) - 2 < length:
  129. response += sock.recv(8192)
  130. sock.close()
  131. return response
  132. dnslib_imported=True
  133. except ImportError:
  134. display("[-] WARNING: The following dependency is needed to proxify DNS through tcp: pip install dnslib")
  135.  
  136.  
  137. #Python socket module does not have this constant
  138. SO_ORIGINAL_DST = 80
  139. class Socks5Conn(asyncore.dispatcher):
  140. def __init__(self, sock=None, map=None, conn=True, verbose=False):
  141. self.out_buffer=b""
  142. self.verbose=verbose
  143. self.allsent=False
  144. if conn is True:
  145. #get the original dst address and port
  146. odestdata = sock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
  147. _, port, a1, a2, a3, a4 = struct.unpack("!HHBBBBxxxxxxxx", odestdata)
  148. address = "%d.%d.%d.%d" % (a1, a2, a3, a4)
  149. if self.verbose:
  150. display('[+] Forwarding incoming connection from %s to %s through the proxy' % (repr(sock.getpeername()), (address, port)))
  151. #connect to the original dst :
  152. self.conn_sock = socks.socksocket()
  153. #self.conn_sock.settimeout(15)
  154. self.conn_sock.connect((address, port))
  155.  
  156. self.sock_class=Socks5Conn(sock=self.conn_sock, conn=self) #add a dispatcher to handle the other side
  157. else:
  158. self.sock_class=conn
  159. self.conn_sock=None
  160. asyncore.dispatcher.__init__(self, sock, map)
  161.  
  162. def initiate_send(self):
  163. num_sent = 0
  164. num_sent = asyncore.dispatcher.send(self, self.out_buffer[:4096])
  165. self.out_buffer = self.out_buffer[num_sent:]
  166.  
  167. def handle_write(self):
  168. self.initiate_send()
  169.  
  170. def writable(self):
  171. return (self.allsent or len(self.out_buffer)>0)
  172.  
  173. def send(self, data):
  174. #if self.debug:
  175. # self.log_info('sending %s' % repr(data))
  176. if data:
  177. self.out_buffer += data
  178. else:
  179. self.allsent=True
  180. #self.initiate_send()
  181.  
  182. def handle_read(self):
  183. data = self.recv(8192)
  184. self.sock_class.send(data)
  185.  
  186. def handle_close(self):
  187. leftover_size=len(self.sock_class.out_buffer)
  188. while leftover_size>0 :
  189. logging.debug("sending %s leftover data"%leftover_size)
  190. self.sock_class.initiate_send()
  191. leftover_size=len(self.sock_class.out_buffer)
  192.  
  193. self.sock_class.close()
  194. self.close()
  195.  
  196. def handle_error(self):
  197. t, v, tb = sys.exc_info()
  198. display("[-] Socks5conn Error: %s : %s\n%s"%(t,v, tb))
  199.  
  200.  
  201.  
  202. class Pr0cks5Server(asyncore.dispatcher):
  203. verbose=False
  204. def __init__(self, host, port):
  205. asyncore.dispatcher.__init__(self)
  206. self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  207. self.set_reuse_addr()
  208. self.bind((host, port))
  209. self.listen(20)
  210.  
  211. def handle_accept(self):
  212. pair = self.accept()
  213. if pair is not None:
  214. sock, addr = pair
  215. self.sock=sock
  216. handler = Socks5Conn(sock, verbose=self.verbose)
  217. def handle_close(self):
  218. self.sock.close()
  219. self.close()
  220. def handle_error(self):
  221. t, v, tb = sys.exc_info()
  222. display("[-] %s : %s"%(t,v))
  223.  
  224.  
  225.  
  226. args=None
  227. if __name__=='__main__':
  228. parser = argparse.ArgumentParser(prog='procks', description="Transparent SOCKS5/SOCKS4/HTTP_CONNECT Proxy")
  229. parser.add_argument('--proxy', default="SOCKS5:127.0.0.1:1080", help="proxytype:ip:port to forward our connections through. proxytype can be SOCKS5, SOCKS4 or HTTP")
  230. parser.add_argument('-p', '--port', type=int, default=10080, help="port to bind the transparent proxy on the local socket (default 10080)")
  231. parser.add_argument('-n', '--nat', action='store_true', help="set bind address to 0.0.0.0 to make pr0cks work from a netfilter FORWARD rule instead of OUTPUT")
  232. parser.add_argument('--enjoysoft', action='store_true', help="set bind address to 192.168.0.31")
  233. parser.add_argument('-v', '--verbose', action="store_true", help="print all the connections requested through the proxy")
  234. parser.add_argument('-c', '--no-cache', action="store_true", help="don't cache dns requests")
  235. parser.add_argument('--username', default=None, help="Username to authenticate with to the server. The default is no authentication.")
  236. parser.add_argument('--password', default=None, help="Only relevant when a username has been provided")
  237. parser.add_argument('--dns-port', default=1053, type=int, help="dns port to listen on (default 1053)")
  238. parser.add_argument('--dns-server', default="8.8.8.8:53", help="ip:port of the DNS server to forward all DNS requests to using TCP through the proxy (default 8.8.8.8:53)")#208.67.222.222:53
  239. args=parser.parse_args()
  240.  
  241. bind_address="127.0.0.1"
  242. if args.nat:
  243. bind_address="0.0.0.0"
  244. if args.enjoysoft:
  245. bind_address="192.168.0.31"
  246. if dnslib_imported:
  247. try:
  248. dns_srv, dns_port=args.dns_server.split(':',1)
  249. dns_port=int(dns_port)
  250. except Exception as e:
  251. display("[-] %s"%e)
  252. display("[-] Invalid dns server : %s"%args.dns_server)
  253. exit(1)
  254. resolver = ProxyResolver(dns_srv,dns_port)
  255. handler = PassthroughDNSHandler # if args.passthrough else DNSHandler
  256. logger = DNSLogger("request,reply,truncated,error", False)
  257. udp_server = DNSServer(resolver,
  258. port=args.dns_port,
  259. address=bind_address,
  260. logger=logger,
  261. handler=handler)
  262. udp_server.start_thread()
  263. display("[+] DNS server started on %s:%s forwarding all DNS trafic to %s:%s using TCP"%(bind_address, args.dns_port, dns_srv, dns_port))
  264.  
  265. ptype,proxy_addr,proxy_port=args.proxy.split(":",2)
  266. t=None
  267. if ptype.upper()=="SOCKS5":
  268. t=socks.PROXY_TYPE_SOCKS5
  269. elif ptype.upper()=="SOCKS4":
  270. t=socks.PROXY_TYPE_SOCKS4
  271. elif ptype.upper()=="HTTP":
  272. t=socks.PROXY_TYPE_HTTP
  273. else:
  274. display("[-] --proxy : unknown proxy type %s"%ptype)
  275. exit(1)
  276. try:
  277. proxy_port=int(proxy_port)
  278. except Exception:
  279. display("[-] --proxy : invalid port %s"%proxy_port)
  280. exit(1)
  281.  
  282. if args.username:
  283. if not args.password:
  284. exit("username provided but without password !")
  285. display("[+] Provided credentials are %s:%s"%(args.username, args.password[0:3]+"*"*(len(args.password)-3)))
  286. socks.setdefaultproxy(proxytype=t, addr=proxy_addr, port=proxy_port, username=args.username, password=args.password)
  287.  
  288. display("[+] Forwarding all TCP traffic received on %s:%s through the %s proxy on %s:%s"%(bind_address, args.port, ptype, proxy_addr, proxy_port))
  289. display("[i] example of rule you need to have:")
  290. display("iptables -t nat -A OUTPUT -o eth0 -p tcp -m tcp !-d <proxy_server> -j REDIRECT --to-ports %s"%args.port)
  291. display("iptables -t nat -A OUTPUT -o eth0 -p udp -m udp --dport 53 -j REDIRECT --to-ports %s"%args.dns_port)
  292. display("[i] Tip to avoid leaks : Block IPv6. For ipv4 put a DROP policy on OUTPUT and only allow TCP to your socks proxy. cf. the iptables.rules example file")
  293.  
  294.  
  295. try:
  296. server = Pr0cks5Server(bind_address, args.port)
  297. if args.verbose:
  298. server.verbose=True
  299. asyncore.loop()
  300. except KeyboardInterrupt:
  301. sys.stdout.write("\n")
  302. sys.exit(0)
  303. except Exception as e:
  304. sys.stderr.write(traceback.format_exc())
  305. sys.exit(1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement