# Small SOCKSv4-implementation - comments / feedback appreciat

**URL:** <https://www.ruby-forum.com/t/small-socksv4-implementation-comments-feedback-appreciat/71060>\
**Category:** Ruby\
**Created:** [October 5, 2006, 1:43am UTC](https://www.ruby-forum.com/t/small-socksv4-implementation-comments-feedback-appreciat/71060 "2006-10-05T01:43:31Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![SSJSSSSrgen\_PSTjern](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e47774/32.png) [@SSJSSSSrgen\_PSTjern](https://www.ruby-forum.com/u/SSJSSSSrgen_PSTjern)\
**Post date:** [October 5, 2006, 1:43am UTC](https://www.ruby-forum.com/t/small-socksv4-implementation-comments-feedback-appreciat/71060/1 "2006-10-05T01:43:31Z")

</div>

After having struggeled with libsock/ruby-sockets+socks, etc, and not  
getting any way, I decided to try another approach. The whole  
ruby-builting-socks / libsock idea is to make it as transparent / global  
as possible, seemingly never meant to be controlled directly by the  
application.

So, I implemented my own little TCPSocket-“wrapper”-class, which just  
speaks the one command from SOCKSv4 and which only understands the one  
reply. After that, it lets go of the socket. (SOCKS protocol information  
found on [SOCKS - Wikipedia](http://en.wikipedia.org/wiki/SOCKS))

Then I just overrode Net::FTP#open\_socket, so if ENV[‘SOCKS\_SERVER’] is  
set, it uses this my little class to set up a socks-connection. This can  
of course be used for anything, not just Net::FTP - any other  
Net::-module, or a custom creation of yours. Net::FTP just happens to be  
what I wanted it for. 😉

Now, I’m curious what you think of the code as a whole (coding style,  
language use, approach, how to “hook into” Net::FTP, etc), and if you  
have any suggestions. I’m thinking I should release this as public  
domain, so anyone else in my situation won’t have to bark up all the  
wrong trees for as long as I did. 😉

Thanks in advance!

Kindest regards, Jørgen P.  
Tjernø.

- code follows:

require ‘socket’  
require ‘resolv’

require ‘net/ftp’

class SocksProxying  
REQUEST\_GRANTED = 0x5A  
REQUEST\_FAILED = 0x5B  
REQUEST\_FAILED\_NOIDENT = 0x5C  
REQUEST\_FAILED\_IDENTINVALID = 0x5D

```
 SOCKS_VERSION_4 = 0x04
 SOCKS_CMD_CONNECTION = 0x01
 SOCKS_CMD_BINDING = 0x02

 SOCKS_REPLY_LENGTH = 8

 def initialize
     @socket = nil
 end

 def connect_via(proxy, proxy_port = 1080)
     @socket = TCPSocket.open(proxy, proxy_port)
 end

 def connect(host, port, user = ENV['USER'])
     if @socket.nil?
         raise "Error: Must connect_via first, then connect."
     end

     ip = Resolv.getaddress(host).split(/\./).collect {|part| 

```

part.to\_i}  
port = port.to\_i

```
     data = [SOCKS_VERSION_4, SOCKS_CMD_CONNECTION, port, ip,

```

user].flatten.pack(‘CCnC4a’ + (user.length + 1).to\_s)  
@socket.write data  
dud, statuscode, port, ip =  
@socket.recv(SOCKS\_REPLY\_LENGTH).unpack(‘CCnC4’)  
if statuscode != REQUEST\_GRANTED  
if statuscode == REQUEST\_FAILED  
raise “Error: SOCKS-access not granted by  
SOCKS-server.”  
elsif statuscode == REQUEST\_FAILED\_NOIDENT  
raise “Error: SOCKS-connection failed; server could not  
reach our ident server.”  
elsif statuscode == REQUEST\_FAILED\_IDENTINVALID  
raise “Error: SOCKS-connection failed; server could not  
match our ident reply to the one sent.”  
else  
raise “Error: SOCKS-connection failed; unknown  
error-code.”  
end  
end

```
     @socket
 end

```

end

# Here is where we override Net::FTP’s internal socket creation.

class Net::FTP  
def open\_socket(host, port)  
if ENV[“SOCKS\_SERVER”]  
@passive = true  
proxy\_host, proxy\_port = ENV[“SOCKS\_SERVER”].split /😕  
sp = SocksProxying.new  
sp.connect\_via(proxy\_host, proxy\_port)  
return sp.connect(host, port)  
else  
return TCPSocket.open(host, port)  
end  
end  
end

---

<div class="post-metadata">

**Author:** ![SSJSSSSrgen\_PSTjern](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e47774/32.png) [@SSJSSSSrgen\_PSTjern](https://www.ruby-forum.com/u/SSJSSSSrgen_PSTjern)\
**Post date:** [October 5, 2006, 1:53am UTC](https://www.ruby-forum.com/t/small-socksv4-implementation-comments-feedback-appreciat/71060/2 "2006-10-05T01:53:33Z")

</div>

Jørgen P. Tjernø wrote:

> […]
> 
> So, I implemented my own little TCPSocket-“wrapper”-class, which just  
> speaks the one command from SOCKSv4 and which only understands the  
> one  
> reply. After that, it lets go of the socket. (SOCKS protocol  
> information  
> found on [SOCKS - Wikipedia](http://en.wikipedia.org/wiki/SOCKS))  
> […]

I should of course mention that I plan on implementing SOCKSv4A (it’s a  
simple and useful addition), but not SOCKSv5 - someone else is of course  
free to do so if they please. 🙂

Kindest regards, Jørgen P.  
Tjernø.
