PUT request just quits
Hi, I'm proxying a PUT request via Tor using socks and unfortunately it always fails if the content is larger than a 100-200 kilobytes, without any message or error. I just get the first part of the request back and then it quits. It works like it should if i don't proxy. What could be the cause of this?
Hi @patrikhermansson, thanks for reporting this. What version of node are you on and would it be possible for you provide the code that fails or a test case?
Hi! I've tested on node 6.0.0 as well as 4.4.4 and with different kind of proxy set ups so I don't think the problem lies there.
I'm also experiencing something similar. This is likely a combination of server and socks5-https-client issue because I can at the same time test:
- PUTting to server x with nodejs http.request works,
- PUTting to my mockup server with http.request and socks5-https-client/lib/Agent through local socks5 proxy works
- PUTting to server x via local socks5 proxy using curl works like a charm
- PUTting to server x with http.request and socks5-https-client/lib/Agent through local socks5 proxy always fails. I even tried sending some tiny files, but it still failed.
-> from socks5 proxy logs i can see that it always fails due to
administratively prohibited, however like I said using the exact same proxy I'm able to do connect to the sever using curl, but not using nodejs..
4:29:14 PM web.1 | debug2: fd 7 setting TCP_NODELAY
4:29:14 PM web.1 | socksserver: debug3: fd 7 is O_NONBLOCK
4:29:14 PM web.1 | debug3: fd 7 is O_NONBLOCK
4:29:14 PM web.1 | debug1: channel 2: new [dynamic-tcpip]
4:29:14 PM web.1 | socksserver: debug2: channel 2: pre_dynamic: have 0
4:29:14 PM web.1 | socksserver: debug2: channel 2: pre_dynamic: have 3
4:29:14 PM web.1 | debug2: channel 2: decode socks5
4:29:14 PM web.1 | debug2: channel 2: socks5 auth done
4:29:14 PM web.1 | debug2: channel 2: pre_dynamic: need more
4:29:14 PM web.1 | socksserver: debug2: channel 2: pre_dynamic: have 0
4:29:14 PM web.1 | socksserver: debug2: channel 2: pre_dynamic: have 28
4:29:14 PM web.1 | debug2: channel 2: decode socks5
4:29:14 PM web.1 | debug2: channel 2: socks5 post auth
4:29:14 PM web.1 | socksserver: debug2: channel 2: dynamic request: socks5 host server-x:PORT port PORT command 1
4:29:14 PM web.1 | socksserver: channel 2: open failed: administratively prohibited: open failed
4:29:14 PM web.1 | socksserver: debug2: channel 2: zombie
4:29:14 PM web.1 | debug2: channel 2: garbage collecting
4:29:14 PM web.1 | debug1: channel 2: free: direct-tcpip: listening port SOCKS_PORT for server-x:PORT port PORT, connect from 127.0.0.1 port 62684 to 127.0.0.1 port SOCKS_PORT, nchannels 3
4:29:14 PM web.1 | debug3: channel 2: status: The following connections are open:
P.S. The difficult part here is that I do not have access to the server-x...
Found the problem, maybe it's a different thing. Doesn't seem to be PUT request specific. It seems to be related to the way host/ports are encoded in the socks client. More specifically you can see here how they are passed on from the options like this: https://github.com/mattcg/socks5-client/blob/master/index.js#L9 And later here they are expected to be distinct: https://github.com/mattcg/socks5-client/blob/master/lib/Socket.js#L206
However it is quite idiomatic to use url parse to create opts for requests, but as of currently something like this would fail..:
opts = require('url').parse("protocol://hostname.com:34634/path")
//And as you can see from here too https://www.npmjs.com/package/url-parse#usage
//I guess nodejs idea here is that host == host header, which is required to contain both if not the default 80/443
//https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23
`${opts.hostname}:${opts.port}` == opts.host
//-> true
//Then you are quite likely to use this parsed opts as the basis for requests.. something like this..
var Agent = require('socks5-https-client/lib/Agent');
opts.agent = new Agent(opts);
request(opts, function(res){ /*...*/ });
I would propose that SocksClient#createConnection should default to using opts.hostname and if that's not set then use opts.host, but in that case split it with ":" and only take first part to be sure it really is just the host. This is easy to fix, but should it be handled in the socks5-https-client and socks5-http-client: https://github.com/mattcg/socks5-https-client/blob/master/lib/Agent.js#L21 https://github.com/mattcg/socks5-http-client/blob/master/lib/Agent.js#L19 or on the socks5-client side https://github.com/mattcg/socks5-client/blob/master/index.js#L9
I created this pr about it in socks5-client: https://github.com/mattcg/socks5-client/pull/15
Thank you for your work on this, @timolehto. I've improved the handling of options.host in socks5-client.
You should be able to run an npm update and re-test.