Socks5Proxy

Налаштування проксі у Node.js: підключення HTTP та SOCKS5 до fetch та https

Цей посібник пояснює, як підключити HTTP-проксі Socks5Proxy через ProxyAgent у undici та SOCKS5-проксі через socks-proxy-agent у Node.js 18 і вище, а також як ротувати IP через API.

Що потрібно для використання проксі у Node.js?

Вбудований fetch у Node.js працює через бібліотеку undici та за замовчуванням не читає налаштування проксі. Тому HTTP-проксі використовується через передачу ProxyAgent як dispatcher, а SOCKS5-проксі - через передачу socks-proxy-agent як agent до модуля https Node.

У прикладі використовується IP 198.51.100.23, HTTP порт 8000, SOCKS5 порт 1080, ім'я користувача spx_user, пароль spx_pass. Весь код у форматі ES модулів (.mjs).

npm install undici socks-proxy-agent

Як підключити HTTP проксі до fetch?

Передайте адресу проксі до ProxyAgent, а ім'я користувача та пароль - у token-опції у вигляді Basic-автентифікації. Передача dispatcher до fetch з undici призведе до використання проксі. HTTPS-адреси передаються через CONNECT у зашифрованому вигляді.

Якщо повторно використовувати той самий ProxyAgent для кількох запитів, з’єднання повторно використовуватимуться, що прискорить роботу. Створіть окремий агент для кожного проксі та використовуйте їх по черзі.

import { fetch, ProxyAgent } from "undici";

const agent = new ProxyAgent({
  uri: "http://198.51.100.23:8000",
  token: "Basic " + Buffer.from("spx_user:spx_pass").toString("base64"),
});

const res = await fetch("https://api.ipify.org?format=json", { dispatcher: agent });
console.log(res.status, await res.json()); // "ip" should be the proxy IP

Як підключитися до проксі SOCKS5?

socks-proxy-agent - це агент для використання з модулями http та https у Node. Використання socks5h дозволяє виконувати DNS-запити через проксі. У прикладі нижче агент передається до https.get для отримання та виведення вмісту відповіді.

Бібліотеки, які працюють на http модулі (як axios), також можуть використовувати SOCKS5, якщо передати той самий агент до httpAgent та httpsAgent.

import https from "node:https";
import { SocksProxyAgent } from "socks-proxy-agent";

const agent = new SocksProxyAgent("socks5h://spx_user:spx_pass@198.51.100.23:1080");

https.get("https://api.ipify.org?format=json", { agent }, (res) => {
  let body = "";
  res.on("data", (chunk) => (body += chunk));
  res.on("end", () => console.log(res.statusCode, body));
}).on("error", (err) => console.error("request failed:", err.message));

Як отримати список через API та циклічно його використовувати?

При старті ви отримуєте список через API, створюєте агента для кожного проксі та використовуєте наступного агента для кожного запиту. Наведений нижче код отримує HTTP-список у форматі ip:port:user:pass, створює масив ProxyAgent і повторює спробу з наступним проксі у разі невдачі.

Обов'язково встановлюйте обмеження часу для запитів за допомогою AbortSignal.timeout. Невідповіді сповільнюють всю роботу.

import { fetch, ProxyAgent } from "undici";

const API = "https://socks5proxy.io/api/v1";
const KEY = "YOUR_API_KEY";

const text = await (await fetch(API + "/proxies/download?format=ip:port:user:pass&protocol=http", {
  headers: { Authorization: "Bearer " + KEY },
})).text();

const agents = text.trim().split("\n").map((line) => {
  const [ip, port, user, pass] = line.trim().split(":");
  return new ProxyAgent({
    uri: "http://" + ip + ":" + port,
    token: "Basic " + Buffer.from(user + ":" + pass).toString("base64"),
  });
});

let i = 0;
async function get(url, tries = 3) {
  for (let t = 0; t < tries; t++) {
    const dispatcher = agents[i++ % agents.length];
    try {
      const res = await fetch(url, { dispatcher, signal: AbortSignal.timeout(20000) });
      if (res.ok) return await res.text();
    } catch {
      // try the next proxy
    }
  }
  return null;
}

console.log((await get("https://example.com/"))?.length);

Як змінюється код при використанні IP-авторизації?

Якщо зареєструвати IPv4 сервера, де запущено Node.js, на панелі керування, можна використовувати ProxyAgent лише з адресою без токена. SOCKS5 також можна використовувати без логіна та пароля, наприклад socks5h://198.51.100.23:1080. Це полегшує розгортання на кількох серверах, оскільки пароль не потрібно зберігати в змінних середовища або коді.

Як підключити проксі при використанні axios?

axios працює на базі http/https модулів Node, тому ви можете використовувати проксі через агентів. Для SOCKS5 використовуйте socks-proxy-agent для httpAgent та httpsAgent, а параметр proxy в axios встановіть на false, щоб уникнути конфлікту.

Для HTTP проксі в axios можна використовувати опцію proxy з host, port, auth, але для HTTPS адрес стабільніше працює підхід з агентами. Пакет https-proxy-agent дозволяє підключати HTTP проксі у такій же структурі.

import axios from "axios";
import { SocksProxyAgent } from "socks-proxy-agent";

const agent = new SocksProxyAgent("socks5h://spx_user:spx_pass@198.51.100.23:1080");
const client = axios.create({ httpAgent: agent, httpsAgent: agent, proxy: false, timeout: 20000 });

const { data } = await client.get("https://api.ipify.org?format=json");
console.log(data);

Що слід враховувати при надсиланні кількох запитів одночасно?

Одночасний запуск тисячі запитів через Promise.all може перевантажити як проксі, так і цільовий сайт. Обмежте кількість одночасних запитів за допомогою черги завдань. Ви можете створити просту функцію або використати пакети, як-от p-limit.

Рівномірний розподіл запитів між проксі запобігає перевантаженню окремих IP. Спільні тарифи включають до 500 одночасних з'єднань - дотримуйтесь цього обмеження.

Чи можна застосувати проксі для всіх запитів через змінні середовища?

EnvHttpProxyAgent з undici читає змінні оточення HTTP_PROXY, HTTPS_PROXY та NO_PROXY для налаштування проксі. Використання setGlobalDispatcher застосовує проксі до всіх fetch у процесі, що зручно для бібліотек, які використовують fetch внутрішньо.

Глобальні налаштування використовують один IP для всіх запитів, що підходить для інструментів або тестів, які потребують доступу з однієї країни. Якщо потрібне циклічне використання, передавайте dispatcher для кожного запиту, як показано вище.

// HTTPS_PROXY=http://spx_user:spx_pass@198.51.100.23:8000 node app.mjs
import { EnvHttpProxyAgent, setGlobalDispatcher, fetch } from "undici";

setGlobalDispatcher(new EnvHttpProxyAgent());
const res = await fetch("https://api.ipify.org");
console.log(await res.text());

Як вирішити поширені проблеми?

Якщо dispatcher у вбудованому fetch Node.js ігнорується, перевірте, чи ви імпортували fetch з пакету undici. Якщо версії вбудованого fetch та undici відрізняються, агент може не працювати. Найнадійніший спосіб - імпортувати fetch та ProxyAgent з одного пакету.

Відповідь 407 означає помилку автентифікації. Перевірте, чи значення token містить base64-кодований рядок у форматі ім'я:пароль після Basic. ECONNREFUSED часто виникає через неправильний порт. Використовуйте HTTP-порт для HTTP-агентів і SOCKS5-порт для SOCKS-агентів.

  • fetch та ProxyAgent знаходяться в одному пакеті undici
  • 407: перевірте значення token та зареєстровані IP
  • ECONNREFUSED: Різниця між HTTP портом та SOCKS5 портом
  • Обмеження часу для всіх запитів
Налаштування проксі у Node.js: підключення undici та SOCKS5-агента | Socks5Proxy