Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -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)
8 changes: 8 additions & 0 deletions doc/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ <h3>Use Net::HTTP explicitly via SOCKS</h3>
explicitly or use <code>Net::HTTP</code> directly.
</p>

<p>
<code>Net::HTTP.SOCKSProxy</code> also supports SOCKS authentication:
</p>
<pre>
Net::HTTP.SOCKSProxy('127.0.0.1', 9050, 'username', 'p4ssw0rd')
</pre>


<h3>Resolve addresses via SOCKS</h3>
<pre>Socksify::resolve("spaceboyz.net")
# => "87.106.131.203"</pre>
Expand Down
15 changes: 12 additions & 3 deletions lib/socksify/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
14 changes: 7 additions & 7 deletions lib/socksify/socksproxyable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand Down
30 changes: 24 additions & 6 deletions lib/socksify/tcpsocket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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

Expand Down
Loading