Advertisement
Guest User

Untitled

a guest
Mar 31st, 2015
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.12 KB | None | 0 0
  1. # -*- coding: binary -*-
  2. #
  3. # sf - Sept 2010
  4. #
  5. require 'thread'
  6. require 'rex/logging'
  7. require 'rex/socket'
  8.  
  9. module Rex
  10. module Proto
  11. module Proxy
  12.  
  13. #
  14. # A Socks4a proxy server.
  15. #
  16. class Socks5
  17.  
  18. #
  19. # A client connected to the Socks4a server.
  20. #
  21. class Client
  22.  
  23.  
  24.  
  25. REPLY_VERSION = 0
  26. REQUEST_VERSION = 5
  27.  
  28. ATYP_IP4 = 1
  29. ATYP_DOMAINNAME = 3
  30. ATYP_IP6 = 4
  31.  
  32. AUTH_NOT_REQUIRED = 0
  33. AUTH_GSSAPI = 1
  34. AUTH_USERNAME_PASSWORD = 2
  35. AUTH_NO_ACCEPTABLE_METHODS = 255
  36.  
  37. COMMAND_CONNECT = 1
  38. COMMAND_BIND = 2
  39. COMMAND_UDP_ASSOCIATE = 3
  40.  
  41. REQUEST_GRANTED = 0
  42. REQUEST_REJECT_GENERAL = 1
  43.  
  44. HOST = 1
  45. PORT = 2
  46.  
  47. #
  48. # A Socks4a packet.
  49. #
  50. class Packet
  51.  
  52. def initialize
  53. @version = REQUEST_VERSION
  54. @command = 0
  55. @dest_port = 0
  56. @dest_host = '0.0.0.0'
  57. @dest_atype = 0
  58. end
  59.  
  60. #
  61. # A helper function to recv in a Socks5 packet byte by byte.
  62. #
  63. # sf: we could just call raw = sock.get_once but some clients
  64. # seem to need reading this byte by byte instead.
  65. #
  66. def Packet.recv( sock, timeout=30 )
  67. raw = ''
  68. # read in the 4 byte header
  69. while raw.length < 4
  70. raw << sock.read(1)
  71. end
  72.  
  73. raw = raw.unpack("CCCC")
  74. return nil unless raw[0] == REQUEST_VERSION
  75. return nil unless [COMMAND_CONNECT, COMMAND_BIND, COMMAND_UDP_ASSOCIATE].include? raw[1]
  76. return nil unless raw[2] == 0
  77. return nil unless [ATYP_IP4, ATYP_DOMAINNAME, ATYP_IP6].include? raw[3]
  78.  
  79. # read in address
  80. case raw[3]
  81. when ATYP_IP4
  82. address_length = 4
  83. when ATYP_DOMAINNAME
  84. address_length = sock.read(1).unpack("C").first
  85. when ATYP_IP6
  86. address_length = 16
  87. end
  88. address = sock.read(address_length)
  89. return nil unless address.to_s.length == address_length
  90. if raw[3] != ATYP_DOMAINNAME
  91. address = Rex::Socket.addr_ntoa(address)
  92. end
  93. # read in 2 bytes ALSO have unpack as a 16-bit integer
  94.  
  95. dest_port = sock.read(2).unpack("n")
  96. pkt = {
  97. :version => raw[0],
  98. :command => raw[1],
  99. :dest_port => dest_port,
  100. :dest_host => address,
  101. :dest_atype => raw[3]
  102. }
  103.  
  104. # create a packet from this raw data...
  105. packet = Packet.new
  106. # packet.from_h(pkt) ? packet : nil
  107. packet.from_h(pkt) ? packet : nil
  108. end
  109.  
  110. #
  111. # Pack a packet into raw bytes for transmitting on the wire.
  112. #
  113. def to_r
  114. raw = [ @version, @command, 0, @dest_atype ].pack('CCCC')
  115.  
  116. if is_hostname?
  117. raw << [@dest_host.length].pack('C')
  118. end
  119. raw << @dest_host
  120. raw << [@dest_port].pack('n')
  121. raw
  122. end
  123.  
  124. #
  125. # Unpack a raw packet into its components.
  126. #
  127. def from_h(pkt)
  128. @version = pkt[:version]
  129. @command = pkt[:command]
  130. @dest_port = pkt[:dest_port]
  131. @dest_host = pkt[:dest_host]
  132. @dest_atype = pkt[:dest_atype]
  133. # if this is a socks4a request we can resolve the provided hostname
  134. if self.is_hostname?
  135. @dest_host = self.resolve(pkt[:dest_host])
  136. # fail if we couldnt resolve the hostname
  137. return false unless @dest_host
  138. end
  139. return true
  140. end
  141.  
  142. def is_connect?
  143. @command == COMMAND_CONNECT ? true : false
  144. end
  145.  
  146. def is_bind?
  147. @command == COMMAND_BIND ? true : false
  148. end
  149.  
  150. attr_accessor :version, :command, :dest_port, :dest_host, :dest_atype
  151.  
  152. protected
  153.  
  154. #
  155. # Resolve the given hostname into a dotted IP address.
  156. #
  157. def resolve( hostname )
  158. if( not hostname.empty? )
  159. begin
  160. return Rex::Socket.addr_itoa( Rex::Socket.gethostbyname( hostname )[3].unpack( 'N' ).first )
  161. rescue ::SocketError
  162. return nil
  163. end
  164. end
  165. return nil
  166. end
  167.  
  168. #
  169. # As per the Socks4a spec, check to see if the provided dest_ip is 0.0.0.XX
  170. # which indicates after the @userid field contains a hostname to resolve.
  171. #
  172. def is_hostname?
  173. return @dest_atype == ATYP_DOMAINNAME
  174. end
  175.  
  176. end
  177.  
  178. #
  179. # A mixin for a socket to perform a relay to another socket.
  180. #
  181. module Relay
  182.  
  183. #
  184. # Relay data coming in from relay_sock to this socket.
  185. #
  186. def relay( relay_client, relay_sock )
  187. @relay_client = relay_client
  188. @relay_sock = relay_sock
  189. # start the relay thread (modified from Rex::IO::StreamAbstraction)
  190. @relay_thread = Rex::ThreadFactory.spawn("SOCKS5ProxyServerRelay", false) do
  191. loop do
  192. closed = false
  193. buf = nil
  194.  
  195. begin
  196. s = Rex::ThreadSafe.select( [ @relay_sock ], nil, nil, 0.2 )
  197. if( s == nil || s[0] == nil )
  198. next
  199. end
  200. rescue
  201. closed = true
  202. end
  203.  
  204. if( closed == false )
  205. begin
  206. buf = @relay_sock.sysread( 32768 )
  207. closed = true if( buf == nil )
  208. rescue
  209. closed = true
  210. end
  211. end
  212.  
  213. if( closed == false )
  214. total_sent = 0
  215. total_length = buf.length
  216. while( total_sent < total_length )
  217. begin
  218. data = buf[total_sent, buf.length]
  219. sent = self.write( data )
  220. if( sent > 0 )
  221. total_sent += sent
  222. end
  223. rescue
  224. closed = true
  225. break
  226. end
  227. end
  228. end
  229.  
  230. if( closed )
  231. @relay_client.stop
  232. ::Thread.exit
  233. end
  234. end
  235. end
  236.  
  237. end
  238.  
  239. end
  240.  
  241. #
  242. # Create a new client connected to the server.
  243. #
  244. def initialize( server, sock )
  245. @server = server
  246. @lsock = sock
  247. @rsock = nil
  248. @client_thread = nil
  249. @mutex = ::Mutex.new
  250. end
  251.  
  252. #
  253. # Checks if the request supports Authentication methods.
  254. #
  255. def authenticate
  256. # reads two bytes of the request
  257. request = @lsock.read(2)
  258. # checks if the request is long enough
  259. return false unless request.to_s.length == 2
  260. # unpacks request from string to an array of two integers
  261. request = request.unpack('CC')
  262. # checks if the client in running the same version
  263. return false unless request[0] == REQUEST_VERSION
  264. # reads the rest of the request
  265. auth_methods = @lsock.read(request[1])
  266. # checks if auth_methods got the same amount as in the request
  267. return false unless auth_methods.to_s.length == request[1]
  268. # checks that there is something in the request
  269. return false unless auth_methods.to_s.length > 0
  270. # this unpacks everything from auth_methods instead of just 2
  271. auth_methods = auth_methods.unpack('C*')
  272. # checks if auth is required
  273. if auth_methods.include? AUTH_NOT_REQUIRED
  274. response = [REQUEST_VERSION, AUTH_NOT_REQUIRED].pack('CC')
  275. @lsock.write(response)
  276. wlog("-Socks5 Auth- Client was authenticated Auth was not required.")
  277. # returns true because the client was authenticated
  278. return true
  279. else
  280. response = [REQUEST_VERSION, AUTH_NO_ACCEPTABLE_METHODS].pack('CC')
  281. @lsock.write(response)
  282. wlog("-Sock5 Auth- Client was not authenicated because no acceptable methods were used.")
  283. end
  284. false
  285. end
  286.  
  287. #
  288. # Start handling the client connection.
  289. #
  290. def start
  291. # create a thread to handle this client request so as to not block the socks4a server
  292. @client_thread = Rex::ThreadFactory.spawn("SOCKS5ProxyClient", false) do
  293. begin
  294. @server.add_client( self )
  295. unless authenticate
  296. wlog("-Auth- Authentication Failed")
  297. self.stop
  298. return
  299. end
  300. # get the initial client request packet
  301. request = Packet.recv( @lsock )
  302. raise "Invalid Socks5 request packet received." if not request
  303. # handle the request
  304. begin
  305. # handle socks4a conenct requests
  306. if( request.is_connect? )
  307. # perform the connection request
  308. params = {
  309. 'PeerHost' => request.dest_host,
  310. 'PeerPort' => request.dest_port,
  311. }
  312. params['Context'] = @server.opts['Context'] if @server.opts.has_key?('Context')
  313. wlog('Marker 1')
  314. @rsock = Rex::Socket::Tcp.create(params)
  315. # and send back success to the client
  316. response = Packet.new
  317. response.version = REPLY_VERSION
  318. response.command = REQUEST_GRANTED
  319. response.dest_port = request.dest_port
  320. response.dest_host = request.dest_host
  321. response.dest_atype = request.dest_atype
  322. wlog('Marker 2')
  323. @lsock.put(response.to_r)
  324. # handle socks4a bind requests
  325. elsif(request.is_bind?)
  326. # create a server socket for this request
  327. params = {
  328. 'LocalHost' => '0.0.0.0',
  329. 'LocalPort' => 0,
  330. }
  331. params['Context'] = @server.opts['Context'] if @server.opts.has_key?('Context')
  332. bsock = Rex::Socket::TcpServer.create( params )
  333. # send back the bind success to the client
  334. response = Packet.new
  335. response.version = REPLY_VERSION
  336. response.command = REQUEST_GRANTED
  337. response.dest_ip = '0.0.0.0'
  338. response.dest_port = bsock.getlocalname()[PORT]
  339.  
  340. @lsock.put( response.to_r )
  341. # accept a client connection (2 minute timeout as per spec)
  342. begin
  343. ::Timeout.timeout( 120 ) do
  344. @rsock = bsock.accept
  345. end
  346. rescue ::Timeout::Error
  347. raise "Timeout reached on accept request."
  348. end
  349. # close the listening socket
  350. bsock.close
  351. # verify the connection is from the dest_ip origionally specified by the client
  352. rpeer = @rsock.getpeername
  353. raise "Got connection from an invalid peer." if( rpeer[HOST] != request.dest_ip )
  354. # send back the client connect success to the client
  355. #
  356. # sf: according to the spec we send this response back to the client, however
  357. # I have seen some clients who bawk if they get this second response.
  358. #
  359. response = Packet.new
  360. response.version = REPLY_VERSION
  361. response.command = REQUEST_GRANTED
  362. response.dest_ip = rpeer[HOST]
  363. response.dest_port = rpeer[PORT]
  364. @lsock.put( response.to_r )
  365. wlog('Marker 1')
  366. else
  367. raise "Unknown request command received #{request.command} received."
  368. end
  369. rescue
  370. # send back failure to the client
  371. response = Packet.new
  372. response.version = REPLY_VERSION
  373. response.command = REQUEST_REJECT_GENERAL
  374. @lsock.put( response.to_r )
  375. # raise an exception to close this client connection
  376. raise "Failed to handle the clients request."
  377. end
  378. # setup the two way relay for full duplex io
  379. @lsock.extend( Relay )
  380. @rsock.extend( Relay )
  381. # start the socket relays...
  382. @lsock.relay( self, @rsock )
  383. @rsock.relay( self, @lsock )
  384. rescue
  385. wlog( "Client.start - #{$!}" )
  386. self.stop
  387. end
  388. end
  389. end
  390.  
  391. #
  392. # Stop handling the client connection.
  393. #
  394. def stop
  395. @mutex.synchronize do
  396. if( not @closed )
  397.  
  398. begin
  399. @lsock.close if @lsock
  400. rescue
  401. end
  402.  
  403. begin
  404. @rsock.close if @rsock
  405. rescue
  406. end
  407.  
  408. @client_thread.kill if( @client_thread and @client_thread.alive? )
  409.  
  410. @server.remove_client( self )
  411.  
  412. @closed = true
  413. end
  414. end
  415. end
  416.  
  417. end
  418.  
  419. #
  420. # Create a new Socks4a server.
  421. #
  422. def initialize( opts={} )
  423. @opts = { 'ServerHost' => '0.0.0.0', 'ServerPort' => 1080 }
  424. @opts = @opts.merge( opts )
  425. @server = nil
  426. @clients = ::Array.new
  427. @running = false
  428. @server_thread = nil
  429. end
  430.  
  431. #
  432. # Check if the server is running.
  433. #
  434. def is_running?
  435. return @running
  436. end
  437.  
  438. #
  439. # Start the Socks4a server.
  440. #
  441. def start
  442. begin
  443. # create the servers main socket (ignore the context here because we don't want a remote bind)
  444. @server = Rex::Socket::TcpServer.create( 'LocalHost' => @opts['ServerHost'], 'LocalPort' => @opts['ServerPort'] )
  445. # signal we are now running
  446. @running = true
  447. # start the servers main thread to pick up new clients
  448. @server_thread = Rex::ThreadFactory.spawn("SOCKS5ProxyServer", false) do
  449. while( @running ) do
  450. begin
  451. # accept the client connection
  452. sock = @server.accept
  453. # and fire off a new client instance to handle it
  454. Client.new( self, sock ).start
  455. rescue
  456. wlog( "Socks5.start - server_thread - #{$!}" )
  457. end
  458. end
  459. end
  460. rescue
  461. wlog( "Socks5.start - #{$!}" )
  462. return false
  463. end
  464. return true
  465. end
  466.  
  467. #
  468. # Block while the server is running.
  469. #
  470. def join
  471. @server_thread.join if @server_thread
  472. end
  473.  
  474. #
  475. # Stop the Socks4a server.
  476. #
  477. def stop
  478. if( @running )
  479. # signal we are no longer running
  480. @running = false
  481. # stop any clients we have (create a new client array as client.stop will delete from @clients)
  482. clients = []
  483. clients.concat( @clients )
  484. clients.each do | client |
  485. client.stop
  486. end
  487. # close the server socket
  488. @server.close if @server
  489. # if the server thread did not terminate gracefully, kill it.
  490. @server_thread.kill if( @server_thread and @server_thread.alive? )
  491. end
  492. return !@running
  493. end
  494.  
  495. def add_client( client )
  496. @clients << client
  497. end
  498.  
  499. def remove_client( client )
  500. @clients.delete( client )
  501. end
  502.  
  503. attr_reader :opts
  504.  
  505. end
  506.  
  507. end; end; end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement