diff --git a/ChangeLog b/ChangeLog index 27bc164..0ae2e87 100644 --- a/ChangeLog +++ b/ChangeLog @@ -81,3 +81,5 @@ SOCKSify Ruby 1.7.3 =================== * add Rakefile * fix missing :timeout kwarg in TCPSocket class (thanks @lizzypy) +* Authentication support added to Net::HTTP.SOCKSProxy + (thanks to @ojab) diff --git a/doc/index.html b/doc/index.html index 5d68607..86711d5 100644 --- a/doc/index.html +++ b/doc/index.html @@ -105,6 +105,14 @@
Net::HTTP directly.
+
+ Net::HTTP.SOCKSProxy also supports SOCKS authentication:
+
+Net::HTTP.SOCKSProxy('127.0.0.1', 9050, 'username', 'p4ssw0rd')
+
+
+
Socksify::resolve("spaceboyz.net")
# => "87.106.131.203"
diff --git a/lib/socksify/http.rb b/lib/socksify/http.rb
index 73eea48..a0629dd 100644
--- a/lib/socksify/http.rb
+++ b/lib/socksify/http.rb
@@ -21,16 +21,20 @@
module Net
# patched class
class HTTP
- def self.socks_proxy(p_host, p_port)
+ def self.socks_proxy(p_host, p_port, p_username = nil, p_password = nil)
proxyclass = Class.new(self)
proxyclass.send(:include, SOCKSProxyDelta)
proxyclass.module_eval do
include Ruby3NetHTTPConnectable if RUBY_VERSION.to_f > 3.0 # patch #connect method
include SOCKSProxyDelta::InstanceMethods
extend SOCKSProxyDelta::ClassMethods
+
@socks_server = p_host
@socks_port = p_port
+ @socks_username = p_username
+ @socks_password = p_password
end
+
proxyclass
end
@@ -41,13 +45,18 @@ class << self
module SOCKSProxyDelta
# class methods
module ClassMethods
- attr_reader :socks_server, :socks_port
+ attr_reader :socks_server, :socks_port,
+ :socks_username, :socks_password
end
# instance methods - no long supports Ruby < 2
module InstanceMethods
def address
- TCPSocket::SOCKSConnectionPeerAddress.new(self.class.socks_server, self.class.socks_port, @address)
+ TCPSocket::SOCKSConnectionPeerAddress.new(
+ self.class.socks_server, self.class.socks_port,
+ @address,
+ self.class.socks_username, self.class.socks_password
+ )
end
end
end
diff --git a/lib/socksify/socksproxyable.rb b/lib/socksify/socksproxyable.rb
index d79f54f..4a5c26f 100644
--- a/lib/socksify/socksproxyable.rb
+++ b/lib/socksify/socksproxyable.rb
@@ -26,8 +26,8 @@ def socks_version_hex
# instance method #socks_authenticate
module InstanceMethodsAuthenticate
# rubocop:disable Metrics
- def socks_authenticate
- if self.class.socks_username || self.class.socks_password
+ def socks_authenticate(socks_username, socks_password)
+ if socks_username || socks_password
Socksify.debug_debug 'Sending username/password authentication'
write "\005\001\002"
else
@@ -42,16 +42,16 @@ def socks_authenticate
raise SOCKSError, "SOCKS version #{auth_reply[0..0]} not supported"
end
- if self.class.socks_username || self.class.socks_password
+ if socks_username || socks_password
if auth_reply[1..1] != "\002"
raise SOCKSError, "SOCKS authentication method #{auth_reply[1..1]} neither requested nor supported"
end
auth = "\001"
- auth += self.class.socks_username.to_s.length.chr
- auth += self.class.socks_username.to_s
- auth += self.class.socks_password.to_s.length.chr
- auth += self.class.socks_password.to_s
+ auth += username.to_s.length.chr
+ auth += socks_username.to_s
+ auth += socks_password.to_s.length.chr
+ auth += socks_password.to_s
write auth
auth_reply = recv(2)
raise SOCKSError, 'SOCKS authentication failed' if auth_reply[1..1] != "\000"
diff --git a/lib/socksify/tcpsocket.rb b/lib/socksify/tcpsocket.rb
index 84ec288..0b7e1fe 100644
--- a/lib/socksify/tcpsocket.rb
+++ b/lib/socksify/tcpsocket.rb
@@ -10,14 +10,19 @@ class TCPSocket
# See http://tools.ietf.org/html/rfc1928
# rubocop:disable Metrics/ParameterLists
- def initialize(host = nil, port = nil, local_host = nil, local_port = nil, **kwargs)
+ def initialize(host = nil, port = nil,
+ local_host = nil, local_port = nil,
+ **kwargs)
socks_peer = host if host.is_a?(SOCKSConnectionPeerAddress)
socks_server = set_socks_server(socks_peer)
socks_port = set_socks_port(socks_peer)
+ socks_username = set_socks_username(socks_peer)
+ socks_password = set_socks_password(socks_peer)
socks_ignores = set_socks_ignores(socks_peer)
host = socks_peer.peer_host if socks_peer
+
if socks_server && socks_port && !socks_ignores.include?(host)
- make_socks_connection(host, port, socks_server, socks_port, **kwargs)
+ make_socks_connection(host, port, socks_server, socks_port, socks_username, socks_password, **kwargs)
else
make_direct_connection(host, port, local_host, local_port, **kwargs)
end
@@ -26,11 +31,13 @@ def initialize(host = nil, port = nil, local_host = nil, local_port = nil, **kwa
# string representation of the peer host address
class SOCKSConnectionPeerAddress < String
- attr_reader :socks_server, :socks_port
+ attr_reader :socks_server, :socks_port, :socks_username, :socks_password
- def initialize(socks_server, socks_port, peer_host)
+ def initialize(socks_server, socks_port, peer_host, socks_username = nil, socks_password = nil)
@socks_server = socks_server
@socks_port = socks_port
+ @socks_username = socks_username
+ @socks_password = socks_password
super(peer_host)
end
@@ -53,14 +60,25 @@ def set_socks_port(socks_peer = nil)
socks_peer ? socks_peer.socks_port : self.class.socks_port
end
+ def set_socks_username(socks_peer = nil)
+ socks_peer ? socks_peer.socks_username : self.class.socks_username
+ end
+
+ def set_socks_password(socks_peer = nil)
+ socks_peer ? socks_peer.socks_password : self.class.socks_password
+ end
+
def set_socks_ignores(socks_peer = nil)
socks_peer ? [] : self.class.socks_ignores
end
- def make_socks_connection(host, port, socks_server, socks_port, **kwargs)
+ def make_socks_connection(host, port,
+ socks_server, socks_port,
+ socks_username, socks_password,
+ **kwargs)
Socksify.debug_notice "Connecting to SOCKS server #{socks_server}:#{socks_port}"
initialize_tcp socks_server, socks_port, **kwargs
- socks_authenticate unless @socks_version =~ /^4/
+ socks_authenticate(socks_username, socks_password) unless @socks_version =~ /^4/
socks_connect(host, port) if host
end