Где взять бесплатные прокси? Часть 1: Сканируем интернет с помощью nodejs

17.01.2020 13:45

Давайте за пару минут напишем приложуньку на nodejs, которая будет сканировать интернеты в поисках открытых прокси серверов.

После беглого гугления по npmjs.org, я нашел пакетик с подходящим функционалом: portscanner. Из него нам понадобится только функция portscanner.checkPortStatus, и которую нам нужно обернуть в промис:

function Pscan(addr, port) {  
  return new Promise( function(resolve) {
    portscanner.checkPortStatus(port, addr, function(error, status) {
      resolve(status);
    });
  });  
}

Наша Pscan будет использоваться в более расширенной функции, которая будет перебирать порты для сканирования и в случае нахождения открытого порта, возвращать его:

async function scan(addr, ports) {
  let strAddr = addr.join('.');

  let testStart = new Date();
  for (let port of ports) {
    let status = await Pscan(strAddr, port);    
    if ( status === 'open' ) {
      let testTime = new Date() - testStart;
      console.log(colors.green(`${strAddr}:${port} time: ${testTime}`));
      return {
        addr: strAddr,
        port: port,
        type: 'HTTP',
        time: testTime
      };
    }
  }
  
  let testTime = new Date() - testStart;
  console.log(colors.red(`${strAddr} time: ${testTime}`));
  
  return null;
}

Далее нам потребуется немного магии по работе с ИП адресами. Нужны функции: увеличения ип адреса на 1, преобразования строкового адреса в массив байт и из массива байт в инт, для сравнения.

function parseIPv4(str) {
  let result = [];
  
  let parts = str.trim().split('.');
  if ( parts.length != 4 ) {
    return null;
  }
  
  for (let part of parts) {
    let byte = parseInt(part);
    if ( byte < 0 ) {
      return null;
    }
    
    if ( byte > 255 ) {
      return null;
    }
    
    result.push(byte);
  }
  
  return result;
}

function incIPv4(addr) {
  addr[ 3 ]++;
  
  for (let index=3; index>0; index--) {
    if ( addr[ index ] > 255 ) {
      addr[ index - 1 ]++;
      addr[ index ] = 0;
    }
  }
  
  if ( addr[ 0 ] > 255 ) {
    return null;
  }
  
  return addr;
}

function Ipv4IntValue(addr) {
  return addr[ 3 ] + ( addr[ 2 ] * 255 ) + ( addr[ 1 ] * 255 * 255 ) + +( addr[ 1 ] * 255 * 255 * 255 );
}

И нам остаётся собрать этот пазл воедино, не забыв о псевдопараллелизме, чтобы не приходилось проверять адреса один за другим, а условно, сразу N адресов:


async function main() {
  
  if ( process.argv.length < 5 ) {
    console.error(colors.red('Not enough arguments, usage:'));
    console.log('node scanner.js ipv4_start_add ipv4_stop_addr out_file.csv [ optional pseudo_threads_count ]');
    console.log('Example:');
    console.log('node scanner.js 127.0.0.0 127.0.0.1 ./out_file.csv 5');
    process.exit(1);
  }
  
  const startADDR = parseIPv4(process.argv[ 2 ]);
  const stopADDR = parseIPv4(process.argv[ 3 ]);
  const dstFile = process.argv[ 4 ];
  let pseudoThreads = 1;
  
  if ( process.argv[ 5 ] ) {
    pseudoThreads = parseInt(process.argv[ 5 ]);
  }
  
  if ( startADDR === null ) {
    console.error(colors.red('Wrong start addr: ' + process.argv[ 2 ]));
    process.exit(1);
  }
  
  if ( stopADDR === null ) {
    console.error(colors.red('Wrong stop addr: ' + process.argv[ 3 ]));
    process.exit(1);
  }
  
  // prepare output file
  if ( !fs.existsSync(dstFile) ) {
    fs.writeFileSync(dstFile, outHeaders.join(',') + '
', { encoding: 'utf8' });
  }
  
  let curAddr = startADDR.map( item => item);
  let eof = false;
  let addrScanned = 0;
  let scanStart = new Date();
  
  while ( !eof ) {
    let promises = [];
    
    for (let tc=0; tc<pseudoThreads; tc++) {
      addrScanned++;
      if ( curAddr === null ) {// The end of IPv4 network
        eof = true;
        break;
      }
      
      if ( Ipv4IntValue(curAddr) > Ipv4IntValue(stopADDR) ) {
        eof = true;
        break;
      }
      
      promises.push(scan(curAddr, defaultPorts));
      
      curAddr = incIPv4(curAddr);
    }
    
    let results = await Promise.all(promises);
    let outString = '';
    
    for (let result of results) {
      if ( result !== null ) {
        let cols = [];
        
        for (let header of outHeaders) {
          cols.push( result[ header ] );
        }
          
        outString += cols.join(',') + '
';
      }
    }
    
    if ( outString !== '' ) {
      fs.writeFileSync(dstFile, outString, { encoding: 'utf8', flag: 'a' });
    }
  }
  
  console.log('Done!');
  console.log('Addressess scaned:', addrScanned, 'scan time:', new Date() - scanStart, 'ms');
  process.exit();  
}

main();

Ещё чтобы увеличить скорость проверки, мы не будем сканировать все 65к портов на каждом хосте, а просканируем только самые распространённые порты указанные в константе: const defaultPorts = [ 8000, 8080, 8888, 3128 ]

Результаты сканирования выведутся в консоль, а успешные сканы запишутся в .csv файл.

Давайте запустим эту хреновину:

node scanner.js 5.135.100.0 5.135.255.255 ./result.csv 100

За тестовое сканирование было опрошено 39937 адресов, было найдено 2173 открытых порта, и потрачено 647183 ms (~10 минут) времени.

Но это не значит, что на всех этих 2173 хостах работают именно прокси, это всего лиш найденные открытые порты, и даже если часть из них действительно прокси сервера, то они почти со 100% вероятностью закрыты авторизацией. По этому поиск открытых анонимных прокси дело долгое.

Что бы ускорить поиск, можно разбивать диапазоны ИП адресов на блоки и одновременно запускать несколько сканеров.

Готовый проект на гитлабе: https://gitlab.com/hololoev/http_proxy_scanner

Смотрите так же

Проверяем список прокси серверов на доступность, с помощью nodejs

Где взять бесплатные прокси? Часть 2: Парсим бесплатные прокси листы



Проверяем список прокси серверов на доступность, с помощью nodejs

Допустим у нас есть список проси серверов в овер 9999 строк, и как обычно большая часть из них не работает. Нам же нужно выбрать только работоспособные, да ещё которые позволяют достучаться до конкретного сайта.

Где взять бесплатные прокси? Часть 2: Парсим бесплатные прокси листы

Тут проблем меньше, чем со сканированием всего интернета, нужно лишь скравлить несколько разных сайтов и слить списки проксей в 1 итоговый файл.


(0) Комментариев