文章目录
- @[TOC](文章目录) Java 将 wireshark 语法转换为sql 语法
- 前言
- 一、wireshark 是什么?
- 二、代码转换
- 正则解析表达式
Java 将 wireshark 语法转换为sql 语法
文章目录
- @[TOC](文章目录) Java 将 wireshark 语法转换为sql 语法
- 前言
- 一、wireshark 是什么?
- 二、代码转换
- 正则解析表达式
前言
需求:需要将 wireshark 语法转换为 clickhouse查询语句,一个wireshark 查询条件可能涉及到多表问题。
一、wireshark 是什么?
Wireshark的过滤语法有两种:BPF(Berkeley Packet Filter)语法和Wireshark语法。
Wireshark语法
基本格式:字段 运算符 值
字段:表示数据包的字段,可以是协议名、字段名或别名。
运算符:表示比较运算符,可以是==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)、contains(包含)、matches(匹配)等。
值:表示字段的值,可以是数字、字符串、布尔值等。
示例:
ip.addr == 192.168.1.1:过滤所有IP地址等于192.168.1.1的数据包,无论是源地址还是目的地址。
tcp.port == 80:过滤所有TCP端口等于80的数据包,无论是源端口还是目的端口。
udp.srcport == 53 and dns.flags.response == 0:过滤所有源端口为53,且DNS标志位为请求的UDP数据包。
http.request.method == “GET”:过滤所有HTTP请求方法为GET的数据包。
ssl.handshake.type == 1:过滤所有SSL握手类型为Client Hello的数据包。
ip.addr matches “10.0.\d+.\d+”:过滤所有IP地址符合正则表达式10.0.\d+.\d+的数据包。
二、代码转换
正则解析表达式
代码如下(示例):
private String parseWiresharkSql(){
String sql = "select * from flow_log as flow ";
String whereStr = " where 1=1 and ";
String filterStr = "src_ip == 192.168.0.5 && dst_port != 443 && dst_ip == 192.168.0.0 && app_proto == \"http\" && (http.url==\"xxx.ss\" || app_proto == \"dns\") ";
String orderStr = " order by xxx asc ";
//字段与表的对应关系
Map<String,String> tableMap = new HashMap<>();
tableMap.put("http","http_log");
tableMap.put("ssh","ssh_log");
tableMap.put("ssl","ssl_log");
//基础逻辑字符串转换
filterStr = filterStr.replaceAll("&&"," and ").replaceAll("\\|\\|"," or ").replaceAll("\"","'");
filterStr += " and";
//组合需要join的关联表
String joinStr = "";
String table_key = "";
String field_key = "";
String field_type = "";
String value = "";
//2.通过正则将过滤条件的每个字段都获取到
StringBuffer filterBuffer = new StringBuffer();
Pattern tablePatten = Pattern.compile("(.*?)\\s*(!=|==|>=|<=|>|<)\\s*(.*?)\\s*(and|or)\\s*");
Matcher matcherTable = tablePatten.matcher(filterStr);
while (matcherTable.find()){
field_key = matcherTable.group(1);
//1.group1中出现 协议表. 则 join 相关表。
if (field_key.contains(".")){
table_key = field_key.split("\\.")[0].replaceAll("\\(","");
field_key = field_key.split("\\.")[1];
joinStr += " join "+tableMap.get(table_key) + " as " +
table_key + " on flow.id = "+table_key+".id ";
//queryFiledType 方法是去数据库查字段的类型与value类型比较
field_type = queryFiledType(field_key, table_key);
}else {
field_type = queryFiledType(field_key.replaceAll("\\(",""), "");
}
//2.根据group1核对group3的字段类型
//string类型的数据转换为'',数值类的转换为数值
value = matcherTable.group(3);
if ("string".equals(field_type)){
if (!value.startsWith("\'") || !value.endsWith("\'")){
value = "'"+value+"'";
}
}else if ("number".equals(field_type)){
if (value.startsWith("\'") || value.endsWith("\'")){
value = value.replaceAll("'","");
}
}
filterBuffer.append(matcherTable.group(1)+" "+matcherTable.group(2)+" "+value+" "+matcherTable.group(4)+" ");
}
if (filterBuffer.length()>4){
filterBuffer.delete(filterBuffer.length()-4,filterBuffer.length());
}
sql+=joinStr+whereStr + " and "+filterBuffer +orderStr;
return sql;
}
总结:核心是使用正则原子化的取出,然后对字段和值进行处理。逻辑符号和()等顺序不变,从而进行转换。