s2w / src /services /networkService.js
dvc890's picture
Upload 11 files
3c8ff75 verified
// 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
};