first commit

This commit is contained in:
编码猿
2025-09-09 08:57:01 +08:00
commit 01c6885a2b
5 changed files with 186 additions and 0 deletions

20
Dockerfile Normal file
View File

@@ -0,0 +1,20 @@
# 使用基础镜像(根据需要选择合适的版本)
FROM debian:bullseye-slim # 或 ubuntu:22.04
# 设置非交互模式,避免安装过程中出现交互提示
ENV DEBIAN_FRONTEND=noninteractive
# 更新软件源并安装iproute2同时清理缓存减小镜像体积
RUN apt-get update && \
apt-get install -y --no-install-recommends \
iproute2 \ # 包含ip命令的工具包
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 可选:设置工作目录
WORKDIR /app
# 可选:添加启动命令
CMD ["bash"]

4
config/index.js Normal file
View File

@@ -0,0 +1,4 @@
module.exports = {
port: 9900,
command: 'ip -6 addr show enp3s0'
}

29
index.js Normal file
View File

@@ -0,0 +1,29 @@
const { execSync } = require('child_process');
const ip = require('./utils/ip');
const { port, command } = require('./config');
const express = require('express')
const app = express()
app.get('/ip', async (req, res) => {
// let output = execSync(command, { encoding: "utf8" });
let output = `2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
inet6 240e:362:2245:9b00::68c/128 scope global dynamic noprefixroute
valid_lft 24426sec preferred_lft 24426sec
inet6 240e:362:2245:9b00:2e0:4cff:fe09:1f7f/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 222142sec preferred_lft 135742sec
inet6 240e:362:223c:2800:2e0:4cff:fe09:1f7f/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 221829sec preferred_lft 135429sec
inet6 fe80::2e0:4cff:fe09:1f7f/64 scope link
valid_lft forever preferred_lft forever`
res.json(await ip.parseNetworkInfo(output))
})
app.listen(port, () => {
console.log(`app listening on port: http://127.0.0.1:${port}`)
})

16
package.json Normal file
View File

@@ -0,0 +1,16 @@
{
"name": "ipv6",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"express": "^5.1.0"
},
"devDependencies": {},
"scripts": {
"start": "node-dev index.js"
},
"keywords": [],
"author": "",
"license": "ISC"
}

117
utils/ip.js Normal file
View File

@@ -0,0 +1,117 @@
const net = require('net');
class Ip {
static async parseNetworkInfo(output) {
// 初始化结果对象
const result = {
interface: '',
flags: [],
mtu: '',
state: '',
ipv6Addresses: []
};
// 按行分割输入
const lines = output.split('\n').map(line => line.trim());
// 解析第一行的基本信息
if (lines.length > 0) {
const firstLineParts = lines[0].split(/\s+/);
// 提取接口名称
result.interface = firstLineParts[1].replace(':', '');
// 提取标志
if (firstLineParts[2] && firstLineParts[2].startsWith('<') && firstLineParts[2].endsWith('>')) {
result.flags = firstLineParts[2].slice(1, -1).split(',');
}
// 提取MTU
const mtuIndex = firstLineParts.indexOf('mtu');
if (mtuIndex !== -1 && mtuIndex + 1 < firstLineParts.length) {
result.mtu = firstLineParts[mtuIndex + 1];
}
// 提取状态
const stateIndex = firstLineParts.indexOf('state');
if (stateIndex !== -1 && stateIndex + 1 < firstLineParts.length) {
result.state = firstLineParts[stateIndex + 1];
}
}
// 解析IPv6地址信息
let currentIpv6 = null;
for (let i = 1; i < lines.length; i++) {
const line = lines[i];
if (line.startsWith('inet6')) {
// 如果有当前正在处理的IPv6地址先保存
if (currentIpv6) {
result.ipv6Addresses.push(currentIpv6);
}
// 开始解析新的IPv6地址
const parts = line.split(/\s+/);
const ipv6Address = parts[1].split("/")[0]
currentIpv6 = {
connect: await Ip.checkIPv6WithTcp(ipv6Address),
address: parts[1].split("/")[0],
scope: parts[2].replace('scope', ''),
properties: parts.slice(3),
validLft: '',
preferredLft: ''
};
} else if (currentIpv6 && line.includes('valid_lft')) {
// 解析有效期信息
const lftParts = line.split(/\s+/);
currentIpv6.validLft = lftParts[0].replace('valid_lft', '');
currentIpv6.preferredLft = lftParts[1].replace('preferred_lft', '');
}
}
// 添加最后一个IPv6地址
if (currentIpv6) {
result.ipv6Addresses.push(currentIpv6);
}
return result;
}
/**
* 检测IPv6地址是否可访问通过尝试建立TCP连接
* @param {string} ipv6 - 要检测的IPv6地址
* @param {number} port - 目标端口,默认 21100
* @param {number} timeout - 超时时间毫秒默认1000
* @returns {Promise<boolean>} - 是否可访问
*/
static checkIPv6WithTcp(ipv6, port = 21100, timeout = 1000) {
return new Promise((resolve) => {
// 验证IPv6格式
if (!net.isIPv6(ipv6)) {
resolve(false);
return;
}
const socket = new net.Socket({ family: 6 }); // 指定IPv6
// 设置超时
const timer = setTimeout(() => {
socket.destroy();
resolve(false);
}, timeout);
// 尝试连接
socket.connect(port, ipv6, () => {
clearTimeout(timer);
socket.destroy();
resolve(true);
});
// 错误处理
socket.on('error', () => {
clearTimeout(timer);
resolve(false);
});
});
}
}
module.exports = Ip