From 07119fa8471235a3a167dbce5a497fd9a9d67911 Mon Sep 17 00:00:00 2001 From: Jake Mack Date: Tue, 26 May 2015 23:46:44 -0700 Subject: [PATCH 1/2] Use thread local variables instead of class variables --- lib/socksify.rb | 101 ++++++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/lib/socksify.rb b/lib/socksify.rb index 2923f4c..617f3ac 100644 --- a/lib/socksify.rb +++ b/lib/socksify.rb @@ -92,43 +92,60 @@ def self.for_response_code(code) end class TCPSocket - @@socks_version ||= "5" - + class << self + %w[socks_server socks_port socks_username socks_password].each do |new_method_name| + define_method new_method_name do + if Thread.current.respond_to? :thread_variable_get + Thread.current.thread_variable_get(new_method_name) + else + Thread.current[new_method_name] + end + end + end + + %w[socks_server socks_port socks_username socks_password socks_ignores].each do |new_method_name| + define_method "#{new_method_name}=" do |val| + if Thread.current.respond_to? :thread_variable_set + Thread.current.thread_variable_set(new_method_name, val) + else + Thread.current[new_method_name] = val + end + end + end + end + def self.socks_version - (@@socks_version == "4a" or @@socks_version == "4") ? "\004" : "\005" + default = '5' + if Thread.current.respond_to?(:thread_variable_get) + version = Thread.current.thread_variable_get('socks_version') + + version.nil? ? Thread.current.thread_variable_set('socks_version', default) : version + else + version = Thread.current['socks_version'] + + version.nil? ? Thread.current['socks_version'] = default : version + end end + def self.socks_version=(version) - @@socks_version = version.to_s - end - def self.socks_server - @@socks_server ||= nil - end - def self.socks_server=(host) - @@socks_server = host + Thread.current.respond_to?(:thread_variable_get) ? Thread.current.thread_variable_set('socks_version', version.to_s) : Thread.current['socks_version'] end - def self.socks_port - @@socks_port ||= nil - end - def self.socks_port=(port) - @@socks_port = port - end - def self.socks_username - @@socks_username ||= nil - end - def self.socks_username=(username) - @@socks_username = username - end - def self.socks_password - @@socks_password ||= nil - end - def self.socks_password=(password) - @@socks_password = password + + def self.encoded_socks_version + (socks_version == "4a" or socks_version == "4") ? "\004" : "\005" end + def self.socks_ignores - @@socks_ignores ||= %w(localhost) - end - def self.socks_ignores=(ignores) - @@socks_ignores = ignores + default = %w(localhost) + if Thread.current.respond_to?(:thread_variable_get) + version = Thread.current.thread_variable_get('socks_ignores') + + version.nil? ? Thread.current.thread_variable_set('socks_ignores', default) : version + else + version = Thread.current['socks_ignores'] + + version.nil? ? Thread.current['socks_ignores'] = default : version + end end class SOCKSConnectionPeerAddress < String @@ -168,7 +185,7 @@ def initialize(host=nil, port=0, local_host=nil, local_port=nil) Socksify::debug_notice "Connecting to SOCKS server #{socks_server}:#{socks_port}" initialize_tcp socks_server, socks_port - socks_authenticate unless @@socks_version =~ /^4/ + socks_authenticate unless TCPSocket::socks_version =~ /^4/ if host socks_connect(host, port) @@ -222,18 +239,18 @@ def socks_authenticate def socks_connect(host, port) port = Socket.getservbyname(port) if port.is_a?(String) Socksify::debug_debug "Sending destination address" - write TCPSocket.socks_version - Socksify::debug_debug TCPSocket.socks_version.unpack "H*" + write TCPSocket::encoded_socks_version + Socksify::debug_debug TCPSocket::encoded_socks_version.unpack "H*" write "\001" - write "\000" if @@socks_version == "5" - write [port].pack('n') if @@socks_version =~ /^4/ + write "\000" if TCPSocket::socks_version == "5" + write [port].pack('n') if TCPSocket::socks_version =~ /^4/ - if @@socks_version == "4" + if TCPSocket::socks_version == "4" host = Resolv::DNS.new.getaddress(host).to_s end Socksify::debug_debug host if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ # to IPv4 address - write "\001" if @@socks_version == "5" + write "\001" if TCPSocket::socks_version == "5" _ip = [$1.to_i, $2.to_i, $3.to_i, @@ -244,7 +261,7 @@ def socks_connect(host, port) raise "TCP/IPv6 over SOCKS is not yet supported (inet_pton missing in Ruby & not supported by Tor" write "\004" else # to hostname - if @@socks_version == "5" + if TCPSocket::socks_version == "5" write "\003" + [host.size].pack('C') + host else write "\000\000\000\001" @@ -254,7 +271,7 @@ def socks_connect(host, port) write "\000" end end - write [port].pack('n') if @@socks_version == "5" + write [port].pack('n') if TCPSocket::socks_version == "5" socks_receive_reply Socksify::debug_notice "Connected to #{host}:#{port} over SOCKS" @@ -263,7 +280,7 @@ def socks_connect(host, port) # returns [bind_addr: String, bind_port: Fixnum] def socks_receive_reply Socksify::debug_debug "Waiting for SOCKS reply" - if @@socks_version == "5" + if TCPSocket::socks_version == "5" connect_reply = recv(4) if connect_reply.empty? raise SOCKSError.new("Server doesn't reply") @@ -336,7 +353,7 @@ def self.resolve(host) s.write "\xF0\000\003" + [host.size].pack('C') + host end s.write [0].pack('n') # Port - + addr, _port = s.socks_receive_reply Socksify::debug_notice "Resolved #{host} as #{addr} over SOCKS" addr From def09293769e9245ad6c0e40382b54e23bdfbaec Mon Sep 17 00:00:00 2001 From: ojab Date: Tue, 8 Dec 2015 10:55:29 +0000 Subject: [PATCH 2/2] Add authentication support to Net::HTTP.SOCKSProxy --- lib/socksify/http.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/socksify/http.rb b/lib/socksify/http.rb index 25b63d7..cc5fb93 100644 --- a/lib/socksify/http.rb +++ b/lib/socksify/http.rb @@ -21,7 +21,7 @@ module Net class HTTP - def self.SOCKSProxy(p_host, p_port) + def self.SOCKSProxy(p_host, p_port, p_username = nil, p_password = nil) delta = SOCKSProxyDelta proxyclass = Class.new(self) proxyclass.send(:include, delta) @@ -31,6 +31,8 @@ def self.SOCKSProxy(p_host, p_port) @socks_server = p_host @socks_port = p_port } + TCPSocket.socks_username = p_username + TCPSocket.socks_password = p_password proxyclass end