NodeJS – 错误:在SOCKS5代理上写入EPIPE

尝试使net.Socket()连接到SOCKS5服务器时,我得到以下net.Socket()

 events.js:141 throw er; // Unhandled 'error' event ^ Error: write EPIPE at exports._errnoException (util.js:870:11) at WriteWrap.afterWrite (net.js:769:14) 

我的代码如下:

 var net = require('net'); var proxy = { host: '115.159.155.96', port: 1080, dstHost: 'www.google.com', dstPort: 80 }; var socket = new net.connect({ host: proxy.host, port: proxy.port }, function() { console.log('connected!'); var addrlen = Buffer.byteLength(proxy.dstHost); var reqbuf = new Buffer(7 + addrlen); var p; reqbuf[0] = 0x05; reqbuf[1] = 0x01; reqbuf[2] = 0x00; reqbuf[3] = 0x03; reqbuf[4] = addrlen; reqbuf.write(proxy.dstHost, 5, addrlen); p = 5 + addrlen; reqbuf.writeUInt16BE(proxy.dstPort, p, true); socket.write(reqbuf); socket.on('data', function(data) { if(data.toString('hex') == '0500') { // This means 0x05 for version 5 and 0x00 for 'succeeded', right? var bfr = new Buffer('GET / HTTP/1.1\r\nHost: www.google.com'); socket.write(bfr); // I also tried "socket.write('GET / HTTP/1.1\r\nHost: www.google.com');", // but I got the same error. } console.log(data.toString()); }); }); 

我相信这是不正确的方式来连接到套接字。 什么是正确的方法来做到这一点?

我从socksv5包中的lib/client.js中取出了上面的代码。

顺便说一句,我不想​​使用现有的包(我知道有很多SOCKS-Client包的NodeJS),因为我想学习SOCKS。

编辑:这是curl -vv --socks5-hostname 115.159.155.96:1080 http://api.ipify.org?format=json的输出curl -vv --socks5-hostname 115.159.155.96:1080 http://api.ipify.org?format=json ,就像Quedarobuild议如下:

 root@mymachine:~# curl -vv --socks5-hostname 115.159.155.96:1080 http://api.ipify.org?format=json * Rebuilt URL to: http://api.ipify.org/?format=json * Hostname was NOT found in DNS cache * Trying 115.159.155.96... * Connected to 115.159.155.96 (115.159.155.96) port 1080 (#0) > GET /?format=json HTTP/1.1 > User-Agent: curl/7.38.0 > Host: api.ipify.org > Accept: */* > < HTTP/1.1 200 OK * Server Cowboy is not blacklisted < Server: Cowboy < Connection: keep-alive < Content-Type: application/json < Date: Wed, 06 Apr 2016 18:15:59 GMT < Content-Length: 23 < Via: 1.1 vegur < * Connection #0 to host api.ipify.org left intact {"ip":"115.159.155.96"} root@mymachine:~# 

这意味着代理人应该可以正常工作,不是吗?

我还向套接字添加了一个错误事件,只需将errlogging到控制台即可。 这是,我得到:

 { [Error: write EPIPE] code: 'EPIPE', errno: 'EPIPE', syscall: 'write' } 

如果有人绊倒这个问题,在这里添加工作代码。

就像@Quedaro所说的那样,socks5握手不见了。

 var net = require('net'); var proxy = { host: 'localhost', // You can create a socks5 server by running `ssh -D 8001 xyz.com` port: 8001, destinationHost: 'www.google.com', destinationPort: 80, destinationPath: '/' }; var socks5Handshake = new Buffer(3); socks5Handshake[0] = 0x05; // SOCKS version number (must be 0x05 for this version) socks5Handshake[1] = 0x01; // Number of authentication methods supported. socks5Handshake[2] = 0x00; // 0x00: No authentication var serverHandshakeResponse = "0500"; // SOCKS version number followed by chosen authentication method, 1 byte, or 0xFF if no acceptable methods were offered. var serverConnectionResponse = "05000001000000000000"; var socket = new net.connect({ host: proxy.host, port: proxy.port }, function() { // Socket connect done. Initiating Socks5 handshake socket.write(socks5Handshake); // Error event handler to handle error in case of ECONNRESET, ECONNREFUSED etc. socket.on('error', function(err){ console.log('error!', err); }); socket.once('data', function(data) { if(data.toString('hex') == serverHandshakeResponse) { var addressLength = Buffer.byteLength(proxy.destinationHost); var requestBuffer = new Buffer(7 + addressLength); var portOffset; requestBuffer[0] = 0x05; // SOCKS version number (must be 0x05 for this version) requestBuffer[1] = 0x01; // establish a TCP/IP stream connection requestBuffer[2] = 0x00; // reserved, must be 0x00 requestBuffer[3] = 0x03; // address type, 1 byte. 0x03 = Domain name requestBuffer[4] = addressLength; // 1 byte of name length followed by the name for domain name requestBuffer.write(proxy.destinationHost, 5, addressLength); portOffset = 5 + addressLength; requestBuffer.writeUInt16BE(proxy.destinationPort, portOffset, true); socket.write(requestBuffer); socket.once('data', function(data){ if(data.toString('hex') == serverConnectionResponse) { var requestBuffer = new Buffer("GET " + proxy.destinationPath + " HTTP/1.1\r\nHost: " + proxy.destinationHost + ":" + proxy.destinationPort + "\r\n\r\n"); socket.write(requestBuffer); socket.once('data', function(data){ console.log("Response for the url:", proxy.destinationHost + ":" + proxy.destinationPort, "=>", data.toString().match(/^HTTP\/1\.. \d+/i)[0]); socket.end(); }); } else { console.log("Socks5 connection request failed. Closing the socket"); socket.end(); } }); } else { console.log("Socks5 handshake failed. Closing the socket"); socket.end(); } }); }); 

你确定袜子服务器真的有效吗? 写EPIPE意味着套接字不能被写入,因为连接已经被丢弃,希望被服务器closures。 尝试testing这个命令(在Linux系统上):

 curl -vv --socks5-hostname 115.159.155.96:1080 http://api.ipify.org?format=json 

另外,在发送这些数据之前,你可能想对袜子服务器说'hello',就像发送这些字节一样: 0x05 0x02 0x00 0x01

为了不引发任何套接字exception,请尝试捕获'error'事件,如下所示:

 socket.on('error', function(err){ console.log('error!', err); });