首頁 什麼是代理IP? NodeJS搭建簡單Socks5代理

NodeJS搭建簡單Socks5代理

user profile
Pandada 文章於 2023-10-19 發佈
0

本代碼是一個簡單的 SOCKS5 代理服務器實現,使用 Node.js 的 net 模塊。SOCKS5 代理服務器用於轉發客戶端的網絡請求到目標服務器。它支持多種地址類型,包括 IPv4、IPv6 和域名地址。在本實現中,支持的操作是 CONNECT,即建立 TCP 連接。

代碼功能詳解

  • 引入模塊:
    const net = require('net');
    引入 Node.js 的 net 模塊,用於創建 TCP 服務器和客戶端。
  • 創建服務器:
    let server = net.createServer(function (socket) {
        // 服務器邏輯
    });
    使用 net.createServer 方法創建一個 TCP 服務器。每當有新的客戶端連接時,會執行回調函數,其中 socket 對象代表與客戶端的連接。
  • 處理客戶端數據:
    socket.once('data', function (data) {
                    // 處理客戶端發送的數據
    });
    使用 socket.once 監聽客戶端發送的第一段數據。這通常是 SOCKS5 協議的握手請求。
  • 驗證 SOCKS5 協議:
    if (!data || data[0] !== 0x05) return socket.destroy();
    驗證客戶端發送的數據是否符合 SOCKS5 協議。如果不是,則銷毀該連接。
  • 發送響應:
    socket.write(Buffer.from([5, 0]), function (err) {
                    // 發送響應後的邏輯
    });
    向客戶端發送響應,表示無需認證即可繼續。
  • 處理連接請求:
    socket.once('data', (data) => {
                    // 解析目標地址和端口,並建立連接
    });
    再次監聽客戶端發送的數據,這次是連接請求。解析目標地址和端口,然後嘗試建立到目標服務器的連接。
  • 建立連接到目標服務器:
    let remote = net.connect(remotePort, remoteAddr, function () {
                     // 連接成功後的邏輯
    });
    使用 net.connect 方法嘗試連接到目標服務器。成功後,會執行回調函數。
  • 數據轉發:
    remote.pipe(socket);
    socket.pipe(remote);
    使用 pipe 方法實現數據在客戶端和目標服務器之間的雙向轉發。
  • 錯誤處理:
    remote.on('error', function (err) {
                    // 處理連接到目標服務器的錯誤
    });
    socket.on('error', function (err) {
        // 處理客戶端連接的錯誤
    });
    監聽錯誤事件,並在發生錯誤時銷毀相應的連接。
  • 啟動服務器:
    server.listen(11100);
    服務器監聽端口 11100,等待客戶端連接。
  • 完整代碼

    const net = require('net');
                const net = require('net');
                let server = net.createServer(function (socket) {
                    socket.once('data', function (data) {
                        if (!data || data[0] !== 0x05) return socket.destroy();
                        let addrLen = 0, remoteAddr = null, remotePort = null;
                        socket.write(Buffer.from([5, 0]), function (err) {
                            if (err) socket.destroy();
                            socket.once('data', (data) => {
                                if (data.length < 7 || data[1] !== 0x01) return socket.destroy();  // 只支持 CONNECT 
                                try {
                                    addrtype = data[3];// ADDRESS_TYPE 目標服務器地址類型
                                    if (addrtype === 3) {  //0x03 域名地址(沒有打錯,就是沒有0x02),
                                        addrLen = data[4];  //域名地址的第1個字節為域名長度,剩下字節為域名名稱字節數組
                                    } else if (addrtype !== 1 && addrtype !== 4) {
                                        return socket.destroy();
                                    }
                                    remotePort = data.readUInt16BE(data.length - 2); //最後兩位為端口值
                                    if (addrtype === 1) {  // 0x01 IP V4地址
                                        remoteAddr = data.slice(3, 7).join('.');
                                    } else if (addrtype === 4) {  //0x04 IP V6地址
                                        // remoteAddr = data.slice(3, 19);//IP V6長度為 16
                                        return socket.write(Buffer.from([0x05, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));  //不支持IP V6
                                    } else {  //0x03 域名地址(沒有打錯,就是沒有0x02),域名地址的第1個字節為域名長度,剩下字節為域名名稱字節數組
                                        remoteAddr = data.slice(5, 5 + addrLen).toString("binary");
                                    }
                                    let remote = net.connect(remotePort, remoteAddr, function () {
                                        console.log(`connecting : ${remoteAddr}:${remotePort}`);
                                        socket.write(Buffer.from([0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), function (err) {
                                            if (err) {
                                                console.error(`error:${err.message}`);
                                                return socket.destroy();
                                            }
                                            remote.pipe(socket);
                                            socket.pipe(remote);
                                        });
                                    });
                                    remote.on('error', function (err) {
                                        console.error(`連接到遠程服務器 ${remoteAddr}:${remoteAddr} 失敗,失敗信息:${err.message}`);
                                        remote.destroy();
                                        socket.destroy();
                                    });
                                } catch (e) {
                                    console.error(e);
                                }
                            });
                        });
                    });
                    socket.on('error', function (err) { console.error(`error:${err.message}`); });
                });
                server.listen(11100);
            
        

    使用方法

  • 將上述代碼保存為 socks5.js
  • 在命令行中運行 node socks5.js 啟動 SOCKS5 代理服務器。
  • 配置客戶端使用 SOCKS5 代理,代理地址設置為服務器的 IP 和端口 11100
  • 注意事項

    • 本代碼僅為簡單實現,不包含認證等高級功能。
    • 在生產環境中使用時,需要考慮安全性和性能優化。
    • 如果需要支持更多 SOCKS5 協議的功能,需要進一步擴展代碼。

    NodeJS搭建簡單Socks5代理測評常見問答

    SOCKS5(Socket Secure 5)是一種網絡傳輸協議,用於代理服務。它允許用戶將其網絡連接路由到代理服務器,以繞過地理位置限制或提高隱私性。與Shadowsocks等代理工具一樣,SOCKS5代理可以用於保護用戶的隱私和訪問受限網站。

    您可以在瀏覽器的設置中配置代理服務器信息。在配置中,您需要指定SOCKS5代理服務器的IP地址和端口號。一旦配置完成,瀏覽器的所有網絡請求將通過指定的代理服務器進行路由。
    上一篇 24款指紋瀏覽器(匯總) 瀏覽器指紋技術通常用於網站分析、廣告定向、反欺詐檢測和用戶識...
    下一篇 代理IP的分類與用途詳解 代理IP是跨境出海的重要工具,它為企業提供了許多途徑,可以更...
    blog
    20款常用的socks5代理IP連接工具

    代理IP連接工具是一種強大的工具,可以保護您的隱私和安全,同...

    blog
    如何通過curl命令測試代理IP

    在進行網絡開發或管理時,經常需要驗證代理服務器的有效性和性能...

    blog
    NodeJS搭建簡單Socks5代理

    本代碼是一個簡單的 SOCKS5 代理服務器實現,使用 No...

    blog
    如何解決代理IP速度慢的問題?

    在使用代理IP的過程中,速度慢是一個常見但令人頭疼的問題。它...

    請直接通過電子郵件聯系我們 [email protected]

    推薦商家