开发防火墙策略区分ipv4和ipv6。
This commit is contained in:
@@ -16,6 +16,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
|
|
||||||
public class GlobalConfig {
|
public class GlobalConfig {
|
||||||
|
|
||||||
|
public static String NETNAME = "";
|
||||||
/**
|
/**
|
||||||
* 服务启动时间
|
* 服务启动时间
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ public class NetVO implements Serializable {
|
|||||||
@Schema(description = "IPv4")
|
@Schema(description = "IPv4")
|
||||||
private String ipV4;
|
private String ipV4;
|
||||||
|
|
||||||
|
@Schema(description = "IPv6")
|
||||||
|
private String ipV6;
|
||||||
|
|
||||||
@Schema(description = "入站丢包")
|
@Schema(description = "入站丢包")
|
||||||
private long inDropped;
|
private long inDropped;
|
||||||
|
|
||||||
@@ -43,6 +46,18 @@ public class NetVO implements Serializable {
|
|||||||
@Schema(description = "接收流量(接收总字节)")
|
@Schema(description = "接收流量(接收总字节)")
|
||||||
private long inSpeed;
|
private long inSpeed;
|
||||||
|
|
||||||
|
@Schema(description = "IPv4接收流量")
|
||||||
|
private Long ipv4InSpeed;
|
||||||
|
|
||||||
|
@Schema(description = "IPv4发送流量")
|
||||||
|
private Long ipv4OutSpeed;
|
||||||
|
|
||||||
|
@Schema(description = "IPv6接收流量")
|
||||||
|
private Long ipv6InSpeed;
|
||||||
|
|
||||||
|
@Schema(description = "IPv6发送流量")
|
||||||
|
private Long ipv6OutSpeed;
|
||||||
|
|
||||||
@Schema(description = "协商速度")
|
@Schema(description = "协商速度")
|
||||||
private String speed;
|
private String speed;
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,14 @@ public class AgentEndpoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(object.containsKey("netName")){
|
||||||
|
String netName = object.getString("netName");;
|
||||||
|
AssertLog.info("注册成功,业务网卡={}",netName);
|
||||||
|
if(StringUtils.isNotBlank(netName)){
|
||||||
|
// 添加ipv4 ipv6防火墙策略
|
||||||
|
agentService.addFirewall(netName);
|
||||||
|
}
|
||||||
|
}
|
||||||
//检查外置目录是否存在
|
//检查外置目录是否存在
|
||||||
if(AdvancedAsyncDownloader.createSingleDirectoryIfNotExists(properties.getConfPath())){
|
if(AdvancedAsyncDownloader.createSingleDirectoryIfNotExists(properties.getConfPath())){
|
||||||
String[] lines = {
|
String[] lines = {
|
||||||
|
|||||||
@@ -92,6 +92,12 @@ public class AppInitializer implements CommandLineRunner {
|
|||||||
// 检测监控策略配置
|
// 检测监控策略配置
|
||||||
AssertLog.info("检测监控策略配置");
|
AssertLog.info("检测监控策略配置");
|
||||||
agentService.checkMonitor();
|
agentService.checkMonitor();
|
||||||
|
// 检测防火墙策略配置
|
||||||
|
AssertLog.info("检测防火墙策略配置");
|
||||||
|
agentService.checkFirewall();
|
||||||
|
AssertLog.info("启动检查防火墙策略定时任务 - 延迟: {}ms, 间隔: {}ms", milli, 600000);
|
||||||
|
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
//未注册,发送注册
|
//未注册,发送注册
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public class BusinessTasks {
|
|||||||
private final AtomicInteger registerTask = new AtomicInteger(0);
|
private final AtomicInteger registerTask = new AtomicInteger(0);
|
||||||
private final AtomicInteger connectionTask = new AtomicInteger(0);
|
private final AtomicInteger connectionTask = new AtomicInteger(0);
|
||||||
private final AtomicInteger networkDetectTask = new AtomicInteger(0);
|
private final AtomicInteger networkDetectTask = new AtomicInteger(0);
|
||||||
|
private final AtomicInteger checkFirewallTask = new AtomicInteger(0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -846,6 +847,11 @@ public class BusinessTasks {
|
|||||||
// 检测监控策略配置
|
// 检测监控策略配置
|
||||||
AssertLog.info("检测监控策略配置Retry");
|
AssertLog.info("检测监控策略配置Retry");
|
||||||
agentService.checkMonitor();
|
agentService.checkMonitor();
|
||||||
|
// 检测防火墙策略配置
|
||||||
|
AssertLog.info("检测防火墙策略配置");
|
||||||
|
agentService.checkFirewall();
|
||||||
|
AssertLog.info("启动检查防火墙策略定时任务 - 延迟: {}ms, 间隔: {}ms", milli, 600000);
|
||||||
|
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
||||||
}else{
|
}else{
|
||||||
//未注册,发送注册
|
//未注册,发送注册
|
||||||
try {
|
try {
|
||||||
@@ -906,6 +912,21 @@ public class BusinessTasks {
|
|||||||
}
|
}
|
||||||
AssertLog.info("发送多网IP探测定时任务执行 - task #{} completed", count);
|
AssertLog.info("发送多网IP探测定时任务执行 - task #{} completed", count);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 任务30:监测防火墙策略
|
||||||
|
*/
|
||||||
|
@Async("taskExecutor")
|
||||||
|
public void checkFirewallTask() {
|
||||||
|
int count = checkFirewallTask.incrementAndGet();
|
||||||
|
AssertLog.info("监测防火墙策略定时任务执行 - 时间: {},task #{}", LocalDateTime.now(), count);
|
||||||
|
// 判定客户端与服务端是否连接
|
||||||
|
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||||
|
// 检测防火墙策略是否存在
|
||||||
|
agentService.checkAndAddFirewallPeriodically();
|
||||||
|
}else{
|
||||||
|
AssertLog.info("断开连接--监测防火墙策略定时任务执行 - task #{} completed", count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,4 +30,10 @@ public interface AgentService {
|
|||||||
String getLogicalNode();
|
String getLogicalNode();
|
||||||
|
|
||||||
void checkMonitor();
|
void checkMonitor();
|
||||||
|
|
||||||
|
void addFirewall(String netName);
|
||||||
|
|
||||||
|
void checkFirewall();
|
||||||
|
|
||||||
|
void checkAndAddFirewallPeriodically();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import javax.annotation.Resource;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@@ -282,6 +283,11 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
// 检测监控策略配置
|
// 检测监控策略配置
|
||||||
AssertLog.info("检测监控策略配置");
|
AssertLog.info("检测监控策略配置");
|
||||||
checkMonitor();
|
checkMonitor();
|
||||||
|
// 检测防火墙策略配置
|
||||||
|
AssertLog.info("检测防火墙策略配置");
|
||||||
|
checkFirewall();
|
||||||
|
AssertLog.info("启动检查防火墙策略定时任务 - 延迟: {}ms, 间隔: {}ms", milli, 600000);
|
||||||
|
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -825,7 +831,11 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(jsonObject.containsKey("netName")){
|
||||||
|
String netName = jsonObject.getString("netName");
|
||||||
|
// 添加防火墙策略
|
||||||
|
addFirewall(netName);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1428,8 +1438,228 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addFirewall(String netName) {
|
||||||
|
String[] netNames = netName.split(";");
|
||||||
|
|
||||||
|
if (!netName.equals(GlobalConfig.NETNAME)) {
|
||||||
|
try {
|
||||||
|
// 1. 将网卡名称写入配置文件
|
||||||
|
String[] lines = {
|
||||||
|
"# 业务网卡防火墙策略配置文件",
|
||||||
|
"# 生成时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),
|
||||||
|
"# 业务网卡名称列表",
|
||||||
|
"businessNetNames=" + netName,
|
||||||
|
"",
|
||||||
|
"# 配置元信息",
|
||||||
|
"lastUpdateTime=" + System.currentTimeMillis(),
|
||||||
|
"totalInterfaces=" + netNames.length
|
||||||
|
};
|
||||||
|
|
||||||
|
// 检查目录并写入配置文件
|
||||||
|
if (AdvancedAsyncDownloader.createSingleDirectoryIfNotExists(properties.getConfPath())) {
|
||||||
|
AgentUtil.bufferedWriter(properties.getConfPath() + "/businessnetname.conf", lines);
|
||||||
|
}
|
||||||
|
// 更新全局变量
|
||||||
|
GlobalConfig.NETNAME = netName;
|
||||||
|
// 2. 为每个业务网卡执行iptables命令
|
||||||
|
for (String interfaceName : netNames) {
|
||||||
|
String iface = interfaceName.trim();
|
||||||
|
if (!iface.isEmpty()) {
|
||||||
|
// 执行IPv4防火墙命令
|
||||||
|
executeIptablesCommand("iptables", "-I", "INPUT", "1", "-i", iface, "-j", "ACCEPT");
|
||||||
|
executeIptablesCommand("iptables", "-I", "OUTPUT", "1", "-o", iface, "-j", "ACCEPT");
|
||||||
|
|
||||||
|
// 执行IPv6防火墙命令
|
||||||
|
executeIptablesCommand("ip6tables", "-I", "INPUT", "1", "-i", iface, "-j", "ACCEPT");
|
||||||
|
executeIptablesCommand("ip6tables", "-I", "OUTPUT", "1", "-o", iface, "-j", "ACCEPT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertLog.debug("防火墙策略配置完成,网卡列表: {}", netName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.error("配置防火墙策略时发生错误: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行iptables命令
|
||||||
|
*/
|
||||||
|
private void executeIptablesCommand(String... command) {
|
||||||
|
Process process = null;
|
||||||
|
try {
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||||
|
processBuilder.redirectErrorStream(true);
|
||||||
|
process = processBuilder.start();
|
||||||
|
|
||||||
|
// 等待命令执行完成
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
if (exitCode != 0) {
|
||||||
|
AssertLog.debug("命令执行失败: {} , 退出码: {}", String.join(" ", command), exitCode);
|
||||||
|
} else {
|
||||||
|
AssertLog.debug("命令执行成功: {}", String.join(" ", command));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.error("执行命令异常: {} , 错误: {}", String.join(" ", command), e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (process != null) {
|
||||||
|
process.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void checkFirewall() {
|
||||||
|
File businessNetFile = new File(properties.getConfPath() + "/businessnetname.conf");
|
||||||
|
if (businessNetFile.exists()) {
|
||||||
|
Properties props = new Properties();
|
||||||
|
try (InputStream input = Files.newInputStream(businessNetFile.toPath())) {
|
||||||
|
props.load(input);
|
||||||
|
|
||||||
|
String businessNetNames = props.getProperty("businessNetNames");
|
||||||
|
if (StringUtils.isNotBlank(businessNetNames)) {
|
||||||
|
// 直接调用 addFirewall 方法,传入配置文件中读取的 netName
|
||||||
|
addFirewall(businessNetNames);
|
||||||
|
AssertLog.info("应用启动时加载业务网卡配置成功: {}", businessNetNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.error("应用启动时加载业务网卡配置异常", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AssertLog.debug("业务网卡配置文件不存在: {}", businessNetFile.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void caseTypeBySystem(String type, int interval, boolean collect){
|
public void caseTypeBySystem(String type, int interval, boolean collect){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 检查业务端口防火墙策略,不存在则添加
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void checkAndAddFirewallPeriodically() {
|
||||||
|
try {
|
||||||
|
String netName = getBusinessNetNames();
|
||||||
|
if (StringUtils.isBlank(netName)) {
|
||||||
|
AssertLog.debug("没有配置业务网卡,跳过防火墙检查");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] netNames = netName.split(";");
|
||||||
|
StringBuilder missingNetNames = new StringBuilder();
|
||||||
|
|
||||||
|
for (String interfaceName : netNames) {
|
||||||
|
String iface = interfaceName.trim();
|
||||||
|
if (iface.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查该网卡是否缺少任何规则
|
||||||
|
if (!checkRuleExists("iptables", "INPUT", "-i", iface, "-j", "ACCEPT") ||
|
||||||
|
!checkRuleExists("iptables", "OUTPUT", "-o", iface, "-j", "ACCEPT") ||
|
||||||
|
!checkRuleExists("ip6tables", "INPUT", "-i", iface, "-j", "ACCEPT") ||
|
||||||
|
!checkRuleExists("ip6tables", "OUTPUT", "-o", iface, "-j", "ACCEPT")) {
|
||||||
|
|
||||||
|
if (missingNetNames.length() > 0) {
|
||||||
|
missingNetNames.append(";");
|
||||||
|
}
|
||||||
|
missingNetNames.append(iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingNetNames.length() > 0) {
|
||||||
|
AssertLog.info("检测到以下网卡防火墙策略缺失: {}", missingNetNames.toString());
|
||||||
|
// 只对缺失规则的网卡调用addFirewall
|
||||||
|
addFirewall(missingNetNames.toString());
|
||||||
|
} else {
|
||||||
|
AssertLog.debug("所有业务网卡防火墙策略检查正常,无需添加");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.error("检查防火墙策略时发生错误: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 iptables -S [chain] 检查特定链中的规则是否存在
|
||||||
|
*/
|
||||||
|
private boolean checkRuleExists(String command, String chain, String... ruleParts) {
|
||||||
|
Process process = null;
|
||||||
|
try {
|
||||||
|
// 执行 iptables -S [chain] 命令,只查看特定链
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder(command, "-S", chain);
|
||||||
|
processBuilder.redirectErrorStream(true);
|
||||||
|
process = processBuilder.start();
|
||||||
|
|
||||||
|
// 构建目标规则关键词(排除-A和链名)
|
||||||
|
List<String> targetKeywords = new ArrayList<>();
|
||||||
|
for (String part : ruleParts) {
|
||||||
|
if (!part.equals("-A") && !part.equals(chain)) {
|
||||||
|
targetKeywords.add(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取命令输出
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
// 检查行是否包含所有关键词
|
||||||
|
boolean containsAll = true;
|
||||||
|
for (String keyword : targetKeywords) {
|
||||||
|
if (!line.contains(keyword)) {
|
||||||
|
containsAll = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (containsAll) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
if (exitCode != 0) {
|
||||||
|
AssertLog.debug("命令执行失败: {} -S {}, 退出码: {}", command, chain, exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.debug("检查规则是否存在时发生异常: {}", e.getMessage());
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
if (process != null) {
|
||||||
|
process.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从配置文件或全局变量获取业务网卡名称
|
||||||
|
*/
|
||||||
|
private String getBusinessNetNames() {
|
||||||
|
if (StringUtils.isNotBlank(GlobalConfig.NETNAME)) {
|
||||||
|
return GlobalConfig.NETNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
File businessNetFile = new File(properties.getConfPath() + "/businessnetname.conf");
|
||||||
|
if (businessNetFile.exists()) {
|
||||||
|
Properties props = new Properties();
|
||||||
|
try (InputStream input = Files.newInputStream(businessNetFile.toPath())) {
|
||||||
|
props.load(input);
|
||||||
|
String businessNetNames = props.getProperty("businessNetNames");
|
||||||
|
if (StringUtils.isNotBlank(businessNetNames)) {
|
||||||
|
GlobalConfig.NETNAME = businessNetNames;
|
||||||
|
return businessNetNames;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.error("读取业务网卡配置文件异常", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.tongran.agent.client.service.impl;
|
package com.tongran.agent.client.service.impl;
|
||||||
|
|
||||||
|
import com.tongran.agent.client.core.config.GlobalConfig;
|
||||||
import com.tongran.agent.client.core.vo.NetVO;
|
import com.tongran.agent.client.core.vo.NetVO;
|
||||||
import com.tongran.agent.client.service.NetService;
|
import com.tongran.agent.client.service.NetService;
|
||||||
import com.tongran.agent.client.utils.AgentUtil;
|
import com.tongran.agent.client.utils.AgentUtil;
|
||||||
@@ -12,78 +13,112 @@ import oshi.util.FormatUtil;
|
|||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class NetServiceImpl implements NetService {
|
public class NetServiceImpl implements NetService {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<NetVO> netList(long timestamp) {
|
public List<NetVO> netList(long timestamp) {
|
||||||
List<NetVO> list = new ArrayList<>();
|
List<NetVO> list = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
SystemInfo si = new SystemInfo();
|
SystemInfo si = new SystemInfo();
|
||||||
HardwareAbstractionLayer hal = si.getHardware();
|
HardwareAbstractionLayer hal = si.getHardware();
|
||||||
// 获取所有网络接口
|
|
||||||
List<NetworkIF> networkIFs = hal.getNetworkIFs();
|
List<NetworkIF> networkIFs = hal.getNetworkIFs();
|
||||||
|
|
||||||
System.out.println("=========================================================");
|
System.out.println("=========================================================");
|
||||||
System.out.println("===== 网卡流量统计 =====");
|
System.out.println("===== 网卡流量统计(基于iptables统计) =====");
|
||||||
List<NetVO> temp = new ArrayList<>();
|
|
||||||
|
// 第一次采样 - 获取基本数据
|
||||||
for (NetworkIF net : networkIFs) {
|
for (NetworkIF net : networkIFs) {
|
||||||
System.out.println("接口名称: " + net.getName()+"("+net.getDisplayName()+")");
|
net.updateAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待1秒进行第二次采样
|
||||||
|
Thread.sleep(1000);
|
||||||
|
|
||||||
|
// 获取iptables统计信息
|
||||||
|
Map<String, Map<String, Long>> iptablesStats = getIptablesStatistics();
|
||||||
|
|
||||||
|
// 第二次采样并计算流量
|
||||||
|
for (NetworkIF net : networkIFs) {
|
||||||
|
net.updateAttributes();
|
||||||
|
|
||||||
|
String interfaceName = net.getName();
|
||||||
|
boolean isBusinessInterface = GlobalConfig.NETNAME.contains(interfaceName);
|
||||||
|
|
||||||
|
System.out.println("接口名称: " + interfaceName + "(" + net.getDisplayName() + ")");
|
||||||
System.out.println("MAC地址: " + net.getMacaddr());
|
System.out.println("MAC地址: " + net.getMacaddr());
|
||||||
System.out.print("运行状态: ");
|
System.out.println("运行状态: " + (net.isConnectorPresent() ? "已连接" : "未连接"));
|
||||||
System.out.println(net.isConnectorPresent() ? "已连接" : "未连接");
|
|
||||||
System.out.println("接口类型: " + AgentUtil.getInterfaceType(net));
|
System.out.println("接口类型: " + AgentUtil.getInterfaceType(net));
|
||||||
System.out.println("IPv4地址: " + String.join(", ", net.getIPv4addr()));
|
System.out.println("IPv4地址: " + String.join(", ", net.getIPv4addr()));
|
||||||
|
System.out.println("IPv6地址: " + String.join(", ", net.getIPv6addr()));
|
||||||
|
System.out.println("业务网卡: " + (isBusinessInterface ? "是" : "否"));
|
||||||
|
|
||||||
NetVO netVO = NetVO.builder().build();
|
// 获取总流量
|
||||||
netVO.setName(net.getName()+"("+net.getDisplayName()+")");//网卡名称
|
long totalBytesRecv = net.getBytesRecv();
|
||||||
netVO.setMac(net.getMacaddr());//MAC
|
long totalBytesSent = net.getBytesSent();
|
||||||
netVO.setStatus(net.isConnectorPresent() ? "已连接" : "未连接");//运行状态
|
|
||||||
netVO.setType(AgentUtil.getInterfaceType(net));//接口类型
|
Long ipv4BytesRecv = null, ipv4BytesSent = null;
|
||||||
netVO.setIpV4(String.join(", ", net.getIPv4addr()));//IPv4
|
Long ipv6BytesRecv = null, ipv6BytesSent = null;
|
||||||
Map<String, String> map = getNetworkMode(net.getName());
|
|
||||||
if (map != null && !map.isEmpty()) {
|
if (isBusinessInterface) {
|
||||||
netVO.setSpeed(map.get("speed"));
|
// 业务网卡:使用iptables统计区分IPv4/IPv6流量
|
||||||
netVO.setDuplex(map.get("duplex"));
|
Map<String, Long> interfaceStats = iptablesStats.get(interfaceName);
|
||||||
|
if (interfaceStats != null) {
|
||||||
|
ipv4BytesRecv = interfaceStats.get("ipv4Recv");
|
||||||
|
ipv4BytesSent = interfaceStats.get("ipv4Sent");
|
||||||
|
ipv6BytesRecv = interfaceStats.get("ipv6Recv");
|
||||||
|
ipv6BytesSent = interfaceStats.get("ipv6Sent");
|
||||||
|
|
||||||
|
System.out.println("iptables统计 - IPv4接收: " + (ipv4BytesRecv != null ? FormatUtil.formatBytes(ipv4BytesRecv) : "null") +
|
||||||
|
", IPv4发送: " + (ipv4BytesSent != null ? FormatUtil.formatBytes(ipv4BytesSent) : "null") +
|
||||||
|
", IPv6接收: " + (ipv6BytesRecv != null ? FormatUtil.formatBytes(ipv6BytesRecv) : "null") +
|
||||||
|
", IPv6发送: " + (ipv6BytesSent != null ? FormatUtil.formatBytes(ipv6BytesSent) : "null"));
|
||||||
|
} else {
|
||||||
|
System.out.println("警告: 未找到网卡 " + interfaceName + " 的iptables统计信息");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非业务网卡:IPv4/IPv6流量设为null
|
||||||
|
System.out.println("非业务网卡,IPv4/IPv6流量统计为null");
|
||||||
}
|
}
|
||||||
temp.add(netVO);
|
|
||||||
}
|
|
||||||
// 2. 实时带宽监控(需要两次采样)
|
|
||||||
System.out.println("\n=== 实时带宽监控 ===");
|
|
||||||
// 第一次采样
|
|
||||||
for (NetworkIF net : networkIFs) {
|
|
||||||
net.updateAttributes();
|
|
||||||
}
|
|
||||||
// 等待1秒
|
|
||||||
TimeUnit.SECONDS.sleep(1);
|
|
||||||
|
|
||||||
// 第二次采样并计算速率
|
System.out.println("总接收流量: " + FormatUtil.formatBytes(totalBytesRecv));
|
||||||
for (NetworkIF net : networkIFs) {
|
System.out.println("总发送流量: " + FormatUtil.formatBytes(totalBytesSent));
|
||||||
long prevBytesRecv = net.getBytesRecv();
|
System.out.println("IPv4接收流量: " + (ipv4BytesRecv != null ? FormatUtil.formatBytes(ipv4BytesRecv) : "null"));
|
||||||
long prevBytesSent = net.getBytesSent();
|
System.out.println("IPv4发送流量: " + (ipv4BytesSent != null ? FormatUtil.formatBytes(ipv4BytesSent) : "null"));
|
||||||
net.updateAttributes();
|
System.out.println("IPv6接收流量: " + (ipv6BytesRecv != null ? FormatUtil.formatBytes(ipv6BytesRecv) : "null"));
|
||||||
long bytesRecv = net.getBytesRecv();
|
System.out.println("IPv6发送流量: " + (ipv6BytesSent != null ? FormatUtil.formatBytes(ipv6BytesSent) : "null"));
|
||||||
long bytesSent = net.getBytesSent();
|
|
||||||
// long bytesRecv = net.getBytesRecv() - prevBytesRecv;
|
|
||||||
// long bytesSent = net.getBytesSent() - prevBytesSent;
|
|
||||||
System.out.println("接口: " + net.getName());
|
|
||||||
System.out.println("入站丢包: " + net.getInDrops());
|
System.out.println("入站丢包: " + net.getInDrops());
|
||||||
System.out.println("出站丢包: " + net.getCollisions());
|
System.out.println("出站丢包: " + net.getCollisions());
|
||||||
System.out.println("接收带宽: " + FormatUtil.formatBytes(bytesRecv) + "/s (" +
|
|
||||||
bytesToMbps(bytesRecv) + " Mbps)");
|
|
||||||
System.out.println("发送带宽: " + FormatUtil.formatBytes(bytesSent) + "/s (" +
|
|
||||||
bytesToMbps(bytesSent) + " Mbps)");
|
|
||||||
|
|
||||||
NetVO netVO = temp.stream().filter(n -> n.getIpV4().equals(String.join(", ", net.getIPv4addr()))
|
NetVO netVO = NetVO.builder()
|
||||||
&& n.getMac().equals(net.getMacaddr())).findFirst().orElse(null);
|
.name(net.getName() + "(" + net.getDisplayName() + ")")
|
||||||
if(Objects.nonNull(netVO)){
|
.mac(net.getMacaddr())
|
||||||
netVO.setInDropped(net.getInDrops());//入站丢包
|
.status(net.isConnectorPresent() ? "已连接" : "未连接")
|
||||||
netVO.setOutDropped(net.getCollisions());//出站丢包
|
.type(AgentUtil.getInterfaceType(net))
|
||||||
netVO.setInSpeed(bytesRecv);//接收流量
|
.ipV4(String.join(", ", net.getIPv4addr()))
|
||||||
netVO.setOutSpeed(bytesSent);//发送流量
|
.ipV6(String.join(", ", net.getIPv6addr()))
|
||||||
netVO.setTimestamp(timestamp);
|
.inDropped(net.getInDrops())
|
||||||
list.add(netVO);
|
.outDropped(net.getCollisions())
|
||||||
|
.inSpeed(totalBytesRecv)
|
||||||
|
.outSpeed(totalBytesSent)
|
||||||
|
.ipv4InSpeed(ipv4BytesRecv)
|
||||||
|
.ipv4OutSpeed(ipv4BytesSent)
|
||||||
|
.ipv6InSpeed(ipv6BytesRecv)
|
||||||
|
.ipv6OutSpeed(ipv6BytesSent)
|
||||||
|
.timestamp(timestamp)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 设置协商速度和工作模式
|
||||||
|
Map<String, String> ethtoolMap = getNetworkMode(net.getName());
|
||||||
|
if (ethtoolMap != null && !ethtoolMap.isEmpty()) {
|
||||||
|
netVO.setSpeed(ethtoolMap.get("speed"));
|
||||||
|
netVO.setDuplex(ethtoolMap.get("duplex"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list.add(netVO);
|
||||||
|
System.out.println("-----------------------------------------");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -91,8 +126,128 @@ public class NetServiceImpl implements NetService {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double bytesToMbps(long bytes) {
|
/**
|
||||||
return bytes * 8.0 / 1_000_000; // bytes to megabits
|
* 获取iptables统计信息
|
||||||
|
*/
|
||||||
|
private Map<String, Map<String, Long>> getIptablesStatistics() {
|
||||||
|
Map<String, Map<String, Long>> stats = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
System.out.println("开始获取iptables统计信息...");
|
||||||
|
|
||||||
|
// 获取IPv4 INPUT统计
|
||||||
|
System.out.println("获取IPv4 INPUT统计...");
|
||||||
|
ProcessBuilder pb = new ProcessBuilder("iptables", "-v", "-n", "-x", "-L", "INPUT");
|
||||||
|
Process process = pb.start();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
parseIptablesLine(line, stats, "ipv4Recv");
|
||||||
|
}
|
||||||
|
process.waitFor();
|
||||||
|
|
||||||
|
// 获取IPv4 OUTPUT统计
|
||||||
|
System.out.println("获取IPv4 OUTPUT统计...");
|
||||||
|
pb = new ProcessBuilder("iptables", "-v", "-n", "-x", "-L", "OUTPUT");
|
||||||
|
process = pb.start();
|
||||||
|
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
parseIptablesLine(line, stats, "ipv4Sent");
|
||||||
|
}
|
||||||
|
process.waitFor();
|
||||||
|
|
||||||
|
// 获取IPv6 INPUT统计
|
||||||
|
System.out.println("获取IPv6 INPUT统计...");
|
||||||
|
pb = new ProcessBuilder("ip6tables", "-v", "-n", "-x", "-L", "INPUT");
|
||||||
|
process = pb.start();
|
||||||
|
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
parseIptablesLine(line, stats, "ipv6Recv");
|
||||||
|
}
|
||||||
|
process.waitFor();
|
||||||
|
|
||||||
|
// 获取IPv6 OUTPUT统计
|
||||||
|
System.out.println("获取IPv6 OUTPUT统计...");
|
||||||
|
pb = new ProcessBuilder("ip6tables", "-v", "-n", "-x", "-L", "OUTPUT");
|
||||||
|
process = pb.start();
|
||||||
|
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
parseIptablesLine(line, stats, "ipv6Sent");
|
||||||
|
}
|
||||||
|
process.waitFor();
|
||||||
|
|
||||||
|
System.out.println("最终iptables统计信息: " + stats);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("获取iptables统计失败: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析iptables输出行 - 根据实际输出格式修复
|
||||||
|
*/
|
||||||
|
private void parseIptablesLine(String line, Map<String, Map<String, Long>> stats, String statType) {
|
||||||
|
line = line.trim();
|
||||||
|
|
||||||
|
if (line.isEmpty() || line.startsWith("Chain") || line.startsWith("pkts") || line.startsWith("target")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用空格分割,处理多个连续空格
|
||||||
|
String[] parts = line.split("\\s+");
|
||||||
|
System.out.println("解析行: " + line);
|
||||||
|
System.out.println("分割部分数量: " + parts.length + ", 内容: " + Arrays.toString(parts));
|
||||||
|
|
||||||
|
if (parts.length >= 7) {
|
||||||
|
try {
|
||||||
|
// 字节数在第二列(索引1)
|
||||||
|
long bytes = Long.parseLong(parts[1]);
|
||||||
|
String interfaceName = null;
|
||||||
|
|
||||||
|
// 根据statType确定是输入接口还是输出接口
|
||||||
|
if ("ipv4Recv".equals(statType) || "ipv6Recv".equals(statType)) {
|
||||||
|
// 接收流量:查看输入接口(第6列,索引5)
|
||||||
|
if (parts.length > 5 && !parts[5].equals("*")) {
|
||||||
|
interfaceName = parts[5];
|
||||||
|
System.out.println("接收流量 - 输入接口: " + interfaceName);
|
||||||
|
}
|
||||||
|
} else if ("ipv4Sent".equals(statType) || "ipv6Sent".equals(statType)) {
|
||||||
|
// 发送流量:查看输出接口(第7列,索引6)
|
||||||
|
if (parts.length > 6 && !parts[6].equals("*")) {
|
||||||
|
interfaceName = parts[6];
|
||||||
|
System.out.println("发送流量 - 输出接口: " + interfaceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interfaceName != null && GlobalConfig.NETNAME.contains(interfaceName)) {
|
||||||
|
Map<String, Long> interfaceStats = stats.getOrDefault(interfaceName, new HashMap<>());
|
||||||
|
|
||||||
|
// 累加相同接口的流量(处理多条规则匹配同一接口的情况)
|
||||||
|
long currentBytes = interfaceStats.getOrDefault(statType, 0L);
|
||||||
|
interfaceStats.put(statType, currentBytes + bytes);
|
||||||
|
stats.put(interfaceName, interfaceStats);
|
||||||
|
|
||||||
|
System.out.println("成功记录iptables统计: " + interfaceName + " - " + statType + " = " + bytes + " bytes (累计: " + (currentBytes + bytes) + ")");
|
||||||
|
} else if (interfaceName != null) {
|
||||||
|
System.out.println("接口 " + interfaceName + " 不是业务网卡,跳过");
|
||||||
|
} else {
|
||||||
|
System.out.println("未找到有效的接口名(可能是通配符*)");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
System.err.println("解析iptables行失败,无法解析数字: " + line);
|
||||||
|
System.err.println("错误部分: " + parts[1]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("行格式不符合预期,跳过: " + line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, String> getNetworkMode(String interfaceName) {
|
public static Map<String, String> getNetworkMode(String interfaceName) {
|
||||||
@@ -109,14 +264,9 @@ public class NetServiceImpl implements NetService {
|
|||||||
result.put("speed", line.split(":")[1].trim());
|
result.put("speed", line.split(":")[1].trim());
|
||||||
} else if (line.contains("Duplex:")) {
|
} else if (line.contains("Duplex:")) {
|
||||||
result.put("duplex", line.split(":")[1].trim());
|
result.put("duplex", line.split(":")[1].trim());
|
||||||
} else if (line.contains("Auto-negotiation:")) {
|
|
||||||
result.put("auto-negotiation", line.split(":")[1].trim());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int exitCode = process.waitFor();
|
process.waitFor();
|
||||||
if (exitCode != 0) {
|
|
||||||
result.put("error", "ethtool command failed with exit code " + exitCode);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result.put("error", e.getMessage());
|
result.put("error", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user