Skip to content

在web服务器上开一个隐藏的狗洞

我们现在有一个WEB服务器. 当然它工作在一个安全的内网集群中, 并通过一个安全的公网地址映射了一个唯一的端口. 我们仅能通过这个公网地址上的端口访问到内网服务器上提供的服务. 不过我现在想要在这个看起来像是只运行了HTTP服务的端口上藏一个悄悄工作的普通TCP服务!

我们现在有一个内网服务器, 假设它的ip是 10.175.106.101, 我们在其上部署了web服务, 监听其 8001端口. 我们称呼它为 Server_01好了.

同时, 我们有个既定的不可改变的映射关系. 比如 我们有一个公网ip 125.71.211.57. 其上的80端口被固定映射到了 Server_01的8001端口.

我们接下来要做的是, 改变Server_01上的服务, 让他监听8082, 随后用一个新的程序来代替它监听8001.

程序会无条件的接受TCP请求, 与对方建立套接字, 不过并不立刻将套接字与8002端口建立管道.

程序分析收到的第一份报文. 如果匹配报文确实是HTTP/1.1协议, 才建立与8002的管道, 否则, 将socket对接到另一个后端服务上.

 

const net = require('net');

function createPromiseClientBackHttp () {
  return new Promise(function (resolve, reject) {
    var client = new net.Socket();
    client.connect(2222, '10.176.104.84', function () {
      resolve(client);
    });
  });
}

function createPromiseClientBackTcp () {
  return new Promise(function (resolve, reject) {
    var client = new net.Socket();
    client.connect(22, '119.23.173.49', function () {
      resolve(client);
    });
  });
}

var server = net.createServer(
    function (socket) {
      var remoteAddress = socket.remoteAddress,
          remotePort    = socket.remotePort,
          localAddress  = socket.localAddress,
          localPort     = socket.localPort;
      Promise.all([createPromiseClientBackHttp(), createPromiseClientBackTcp()])
             .then(
                 function (ps) {
                   var clientHttp = ps[0], clientTcp = ps[1];
                   var isPiped                       = false;
            
                   socket.on('data', function (data) {
                     if (isPiped) {
                       return;
                     }
                     isPiped = true;
              
                     var lines  = data.toString('utf8')
                                      .split('\n');
                     var line   = lines[0] || '';
                     var client = null;
                     if (/http\/1\.1/i.test(line)) {
                       console.log(
                           '[HTTP] '
                           + remoteAddress + ':' + remotePort + '\t' + line
                       );
                       client = clientHttp;
                       clientTcp.destroy();
                     }
                     else if (/^ssh-/i.test(line)) {
                       console.log(
                           '[SSH] '
                           + remoteAddress + ':' + remotePort + '\t' + line
                       );
                     }
                     else {
                       console.log(
                           '[其它] '
                           + remoteAddress + ':' + remotePort
                       );
                       client = clientTcp;
                       clientHttp.destroy();
                     }
              
                     if (client && socket) {
                       socket.pipe(client);
                       client.pipe(socket);
                
                       client.write(data);
                       client.on('close', function () {
                         console.log(
                             '[关闭] '
                             + remoteAddress + ':' + remotePort
                         );
                         socket.destroy();
                       });
                
                       client.on('error', function (err) {
                         // console.log(err);
                         console.log(
                             '[关闭] '
                             + remoteAddress + ':' + remotePort
                         );
                         socket.destroy();
                       });
                
                       socket.on('close', function () {
                         console.log(
                             '[关闭] '
                             + remoteAddress + ':' + remotePort
                         );
                         client.destroy();
                       });
                
                       socket.on('error', function (err) {
                         // console.log(err);
                         console.log(
                             '[关闭] '
                             + remoteAddress + ':' + remotePort
                         );
                         client.destroy();
                       });
                     }
                   });
            
                 }
             ).catch(function (reason) { });
      
    }
);

server.listen(8092, '0.0.0.0');