File size: 4,601 Bytes
3c8ff75 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
// networkService.js
const net = require('net');
const dgram = require('dgram');
const { exec } = require('child_process');
const { promisify } = require('util');
const execAsync = promisify(exec);
/**
* 创建一个不会被TUN设备捕获的TCP连接
* @param {string} host - 目标主机
* @param {number} port - 目标端口
* @returns {net.Socket} TCP套接字
*/
function createProtectedTCPConnection(host, port) {
console.log(`创建受保护的TCP连接到 ${host}:${port}`);
// 创建TCP套接字
const socket = new net.Socket();
// 设置连接选项,尝试避免路由循环
socket.setNoDelay(true);
socket.setTimeout(10000); // 10秒超时
// 尝试设置SOCKET选项来避免路由循环
try {
// 在某些系统上,可以设置SOCK_NO_CHECK_V4来避免路由循环
// 注意:这个选项在Node.js中可能不可用
socket.setKeepAlive(true, 1000);
} catch (error) {
console.warn('设置TCP套接字选项时出错:', error.message);
}
// 连接到目标主机
socket.connect(port, host, () => {
console.log(`已连接到 ${host}:${port}`);
});
return socket;
}
/**
* 创建一个不会被TUN设备捕获的UDP套接字
* @returns {dgram.Socket} UDP套接字
*/
function createProtectedUDPSocket() {
console.log('创建受保护的UDP套接字');
// 创建UDP套接字
const socket = dgram.createSocket('udp4');
return socket;
}
/**
* 通过系统命令发送ICMP数据包(避免路由循环)
* @param {string} destinationIP - 目标IP地址
* @param {Buffer} packet - ICMP数据包
* @returns {Promise<void>}
*/
async function sendICMPPacketViaSystem(destinationIP, packet) {
console.log(`通过系统命令发送ICMP数据包到 ${destinationIP}`);
try {
// 将数据包保存到临时文件
const fs = require('fs');
const path = require('path');
const tempDir = '/tmp';
const tempFile = path.join(tempDir, `icmp_packet_${Date.now()}.bin`);
// 写入数据包到临时文件
fs.writeFileSync(tempFile, packet);
// 使用hping3或ping命令发送ICMP数据包
// 注意:这需要安装hping3工具
const command = `hping3 -0 -c 1 -d ${packet.length} -E ${tempFile} ${destinationIP}`;
console.log(`执行命令: ${command}`);
const { stdout, stderr } = await execAsync(command);
if (stderr) {
console.warn('发送ICMP数据包时的警告:', stderr);
}
console.log('ICMP数据包发送结果:', stdout);
// 清理临时文件
fs.unlinkSync(tempFile);
} catch (error) {
console.error('通过系统命令发送ICMP数据包时出错:', error.message);
// 回退到普通UDP发送
console.log('回退到普通UDP发送');
const client = dgram.createSocket('udp4');
client.send(packet, 0, packet.length, 7, destinationIP, (err) => {
if (err) {
console.error('发送ICMP数据包时出错:', err.message);
} else {
console.log(`ICMP数据包已发送到 ${destinationIP}:7`);
}
client.close();
});
}
}
/**
* 检查是否为本地地址
* @param {string} ip - IP地址
* @returns {boolean} 是否为本地地址
*/
function isLocalAddress(ip) {
// 检查是否为本地回环地址
if (ip.startsWith('127.') || ip === 'localhost') {
return true;
}
// 检查是否为私有地址范围
if (ip.startsWith('10.') ||
ip.startsWith('192.168.') ||
(ip.startsWith('172.') && parseInt(ip.split('.')[1]) >= 16 && parseInt(ip.split('.')[1]) <= 31)) {
return true;
}
return false;
}
/**
* 获取默认网关
* @returns {Promise<string>} 默认网关IP地址
*/
async function getDefaultGateway() {
return new Promise((resolve, reject) => {
require('child_process').exec('route get default | grep gateway | awk \'{print $2}\'', (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
const gateway = stdout.trim();
resolve(gateway);
}
});
});
}
/**
* 获取网络接口信息
* @returns {Promise<Array>} 网络接口列表
*/
async function getNetworkInterfaces() {
return new Promise((resolve, reject) => {
require('child_process').exec('ifconfig -l', (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
const interfaces = stdout.trim().split(' ');
resolve(interfaces);
}
});
});
}
module.exports = {
createProtectedTCPConnection,
createProtectedUDPSocket,
isLocalAddress,
getDefaultGateway,
getNetworkInterfaces
}; |