【问题标题】:NodeJS - Error: write EPIPE on SOCKS5 proxyNodeJS - 错误:在 SOCKS5 代理上写入 EPIPE
【发布时间】:2016-04-06 14:59:39
【问题描述】:

在尝试与 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 中提取了上面的代码。

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

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

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:~#

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

我还在套接字中添加了一个错误事件,只需将err 记录到控制台。这就是我得到的:

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

【问题讨论】:

    标签: node.js sockets proxy socks


    【解决方案1】:

    如果有人偶然发现这个问题,请在此处添加工作代码。

    正如@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();
        }
      });
    });
    

    【讨论】:

      【解决方案2】:

      你确定 socks 服务器真的可以工作吗?写入EPIPE 表示无法写入套接字,因为连接已被丢弃,希望被服务器关闭。尝试测试这个命令(在 Linux 系统上):

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

      此外,在发送该数据之前,您可能想向 socks 服务器说“你好”,例如发送这些字节:0x05 0x02 0x00 0x01

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

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

      【讨论】:

      • 我编辑了我的问题并添加了信息:) 感谢您的回复。
      猜你喜欢
      • 2015-08-17
      • 2014-12-26
      • 2016-04-25
      • 2017-08-10
      • 2020-10-06
      • 1970-01-01
      • 2012-02-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多