hackney icon indicating copy to clipboard operation
hackney copied to clipboard

Is Hackney able to connect to multiple SOCKS5 circuits at a time?

Open miskolc opened this issue 8 years ago • 3 comments

I'm using Hackney in an Elixir Project where I try to connect to multiple Tor circuits at a time via SOCKS5. I'm making this requests to a site that simply return the IP address in the response body and nothing else.

The problem is that when I make a request via one of the Tor processes and then immediately another one via another Tor process, I get the same IP address( so almost cetainly both requests go through the same circuit).

 > {:ok, status, headers, c1} = :hackney.request(:get ,url, [], "", [{:proxy, {:socks5, :localhost, 9062}}])
 > :hackney.body(c1) 
 {:ok, "one.ip.add.ress\n"}
 > {:ok, status, headers, c2} = :hackney.request(:get ,url, [], "", [{:proxy, {:socks5, :localhost, 9063}}])
 > :hackney.body(c2) 
 {:ok, "one.ip.add.ress\n"}

If I wait about 1 minute and make the same request with the other process first I get his IP for both:

 > {:ok, status, headers, c2} = :hackney.request(:get ,url, [], "", [{:proxy, {:socks5, :localhost, 9063}}])
 > :hackney.body(c2)     
 {:ok, "two.ip.add.ress\n"}
 > {:ok, status, headers, c1} = :hackney.request(:get ,url, [], "", [{:proxy, {:socks5, :localhost, 9062}}])
 > :hackney.body(c1)          
 {:ok, "two.ip.add.ress\n"}

and if I wait another 1 minute or so I get the IP of the first one for both again.

 > {:ok, status, headers, c1} = :hackney.request(:get ,url, [], "", [{:proxy, {:socks5, :localhost, 9062}}])
 > :hackney.body(c1)        
 {:ok, "one.ip.add.ress\n"}
 > {:ok, status, headers, c2} = :hackney.request(:get ,url, [], "", [{:proxy, {:socks5, :localhost, 9063}}])
 > :hackney.body(c2)         
 {:ok, "one.ip.add.ress\n"}

If I wait for a longer period both IP's change but again If I make a request through both processes within a short time interval I will get the same IP for both( the IP of the first TOR process I used):

 > {:ok, status, headers, c1} = :hackney.request(:get ,url, [], "", [{:proxy, {:socks5, :localhost, 9062}}])
 > :hackney.body(c1)        
 {:ok, "new.ip.add.ress\n"}
 > {:ok, status, headers, c2} = :hackney.request(:get ,url, [], "", [{:proxy, {:socks5, :localhost, 9063}}])
 > :hackney.body(c2)         
 {:ok, "new.ip.add.ress\n"}

Is there a way to avoid this in Hackney?

miskolc avatar Feb 13 '16 07:02 miskolc

It's probably because you get the socket from the pool. Bypassing the pool (by setting it topool in the request options would do the trick).

If you want to reuse the connection you can also use the following: https://github.com/benoitc/hackney#reuse-a-connection

Let me know if it works for you :)

benoitc avatar Feb 13 '16 08:02 benoitc

If by setting it to pool in the options you mean doing something like this

 > {:ok, status, headers, c1} = :hackney.request(:get ,url, [], "", [:pool, {:proxy, {:socks5, :localhost, 9062}}])
 > :hackney.body(c1) 
 {:ok, "one.ip.add.ress\n"}
 > {:ok, status, headers, c2} = :hackney.request(:get ,url, [], "", [:pool, {:proxy, {:socks5, :localhost, 9063}}])
 > :hackney.body(c2) 
 {:ok, "one.ip.add.ress\n"}

or like this

 > {:ok, status, headers, c1} = :hackney.request(:get ,url, [], "", [{:pool, :default}, {:proxy, {:socks5, :localhost, 9062}}])
 > :hackney.body(c1) 
 {:ok, "one.ip.add.ress\n"}
 > {:ok, status, headers, c2} = :hackney.request(:get ,url, [], "", [{:pool, :default}, {:proxy, {:socks5, :localhost, 9063}}])
 > :hackney.body(c2) 
 {:ok, "one.ip.add.ress\n"}

then it doesn't work.

However I also tried to create one pool for each of my tor ports and then it seems to work:

 > poolname = :port9062
 > options = [{:timeout, 150000},{:max_connections, 100}]
 > :hackney_pool.start_pool(poolname, options) 
 > poolname = :port9063
 > options = [{:timeout, 150000},{:max_connections, 100}]
 > :hackney_pool.start_pool(poolname, options) 
 >  {:ok, status, headers, c1} = :hackney.request(:get ,url, [], "", [{:pool, :port9062},{:proxy, {:socks5, :localhost, 9062}}])
 > :hackney.body(c1)  
 {:ok, "first.ip.add.ress\n"}
 >  {:ok, status, headers, c1} = :hackney.request(:get ,url, [], "", [{:pool, :port9063},{:proxy, {:socks5, :localhost, 9063}}])
 > :hackney.body(c1)  
 {:ok, "second.ip.add.ress\n"}

Is this what you suggested in the first place?

miskolc avatar Feb 14 '16 14:02 miskolc

I meant settings the pool to none so it's not used :)

benoitc avatar Feb 24 '16 15:02 benoitc