抓包过滤有如下两个格式:
- ✅主机
tshark -i any -f 'host 192.168.1.1/32' -w $path/timestamp-$host.pcapng
- ✅网络号
tshark -i any -f 'net 192.168.1.0/24' -w $path/timestamp-$host.pcapng
貌似可用带掩码的方式,直接使用net参数过滤,不区分是主机还是网络号,例如:
tshark -i any -f 'net 192.168.1.1/32' -w $path/timestamp-$host.pcapng
tshark -i any -f 'net 192.168.1.0/24' -w $path/timestamp-$host.pcapng
快速抓单目标
#!/bin/bash
iface="enp1s0"
path="/data"
# 创建目录(如果不存在)
mkdir -p "$path"
# 获取当前时间戳
timestamp=$(date +%Y-%m-%d-%H:%M:%S)
# 读取用户输入
read -p "请输入要抓包的主机或网段 (如 192.168.1.1 或 192.168.0.0/24): " host
# 判断输入是否为空
if [ -z "$host" ]; then
echo "抓包目标不能为空"
exit 1
fi
# 构建过滤器
if [[ "$host" =~ / ]]; then
filter="net $host"
else
filter="host $host"
fi
# 将斜杠替换为下划线防止文件名出错
safe_host="${host//\//_}"
file="$path/${timestamp}-${safe_host}.pcapng"
echo "开始抓包,使用接口 $iface,过滤条件: $filter"
tshark -i "$iface" -f "$filter" -w "$file"
echo "抓包完成,文件已保存为:$file"
# 是否转换为可阅读文本
read -p "是否转换为txt文本便于AI分析?(y/n, 默认 y): " answer
answer=${answer:-y}
if [[ "$answer" == "y" || "$answer" == "Y" ]]; then
txt_file="$path/${timestamp}-${safe_host}.txt"
echo "正在转换格式,请不要操作!"
tshark -r "$file" \
-T fields \
-E header=y \
-e frame.number \
-e frame.time_relative \
-e ip.src \
-e ip.dst \
-e tcp.srcport \
-e tcp.dstport \
-e _ws.col.Info > "$txt_file"
echo "已转换为文本:$txt_file"
fi
交互抓包
#!/bin/bash
# 抓包输出目录
output_dir="/data"
mkdir -p "$output_dir"
# 显示可用网卡
echo "=== 可用网卡列表 ==="
tshark -D
echo "==================="
# 选择网卡
read -p "请输入要抓包的网卡编号(例如 1): " iface_num
iface=$(tshark -D | sed -n "${iface_num}p" | cut -d. -f2- | sed 's/^[[:space:]]*//')
if [ -z "$iface" ]; then
echo "❌ 无效的网卡编号,退出。"
exit 1
fi
# 输入主机或网段
read -p "请输入抓包目标(IP或CIDR网段,例如 192.168.1.1 或 192.168.0.0/24): " target
if [ -z "$target" ]; then
echo "❌ 抓包目标不能为空"
exit 1
fi
# 判断过滤器类型
if [[ "$target" =~ / ]]; then
filter="net $target"
else
filter="host $target"
fi
# 选填:抓包持续时间
read -p "是否限制抓包时长?输入秒数(如 30),留空表示手动 Ctrl+C 停止: " duration
# 安全命名(去掉斜线)
timestamp=$(date +%Y-%m-%d-%H-%M-%S)
safe_target="${target//\//_}"
pcap_file="${output_dir}/${timestamp}-${safe_target}.pcapng"
echo "✅ 开始抓包,接口: $iface,过滤: $filter"
if [ -n "$duration" ]; then
tshark -i "$iface" -f "$filter" -a duration:$duration -w "$pcap_file"
else
tshark -i "$iface" -f "$filter" -w "$pcap_file"
fi
echo "✅ 抓包完成,文件保存为: $pcap_file"
# 是否导出为 txt
read -p "是否转换为txt文本供AI分析?(y/n, 默认 y): " convert
convert=${convert:-y}
if [[ "$convert" =~ ^[Yy]$ ]]; then
txt_file="${output_dir}/${timestamp}-${safe_target}.txt"
tshark -r "$pcap_file" \
-T fields \
-E header=y \
-e frame.number \
-e frame.time_relative \
-e ip.src \
-e ip.dst \
-e tcp.srcport \
-e tcp.dstport \
-e _ws.col.Info > "$txt_file"
echo "✅ 转换完成,文本保存为: $txt_file"
fi
交互同时抓多目标
#!/bin/bash
output_dir="/data"
mkdir -p "$output_dir"
# 显示网卡
echo "=== 可用网卡列表 ==="
tshark -D
echo "==================="
read -p "请输入要抓包的网卡编号: " iface_num
iface=$(tshark -D | sed -n "${iface_num}p" | cut -d. -f2- | sed 's/^[[:space:]]*//')
[ -z "$iface" ] && echo "无效网卡编号" && exit 1
read -p "请输入多个抓包目标(用空格分隔,如 192.168.1.1 192.168.0.0/24): " -a targets
[ ${#targets[@]} -eq 0 ] && echo "目标不能为空" && exit 1
read -p "是否限制抓包时长?输入秒数(默认无限制): " duration
for target in "${targets[@]}"; do
if [[ "$target" =~ / ]]; then
filter="net $target"
else
filter="host $target"
fi
timestamp=$(date +%Y-%m-%d-%H-%M-%S)
safe_target="${target//\//_}"
pcap_file="${output_dir}/${timestamp}-${safe_target}.pcapng"
echo "▶ 正在抓包 $target"
if [ -n "$duration" ]; then
tshark -i "$iface" -f "$filter" -a duration:$duration -w "$pcap_file"
else
tshark -i "$iface" -f "$filter" -w "$pcap_file"
fi
echo "✅ 已保存到 $pcap_file"
done
web控制抓单目标
from flask import Flask, render_template_string, request
import subprocess
import os
from datetime import datetime
app = Flask(__name__)
OUTPUT_DIR = "/data"
os.makedirs(OUTPUT_DIR, exist_ok=True)
TEMPLATE = """
<!doctype html>
<title>抓包控制台</title>
<h2>Web 抓包控制台</h2>
<form method="post">
网卡名: <input name="iface" value="enp1s0"><br><br>
抓包目标(IP 或 网段): <input name="target"><br><br>
抓包时长(秒,可选): <input name="duration"><br><br>
<input type="submit" value="开始抓包">
</form>
{% if msg %}<p style="color:green">{{ msg }}</p>{% endif %}
"""
@app.route("/", methods=["GET", "POST"])
def index():
msg = ""
if request.method == "POST":
iface = request.form["iface"]
target = request.form["target"]
duration = request.form.get("duration")
if "/" in target:
f = f"net {target}"
else:
f = f"host {target}"
timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
safe_target = target.replace("/", "_")
pcap_path = os.path.join(OUTPUT_DIR, f"{timestamp}-{safe_target}.pcapng")
cmd = ["tshark", "-i", iface, "-f", f, "-w", pcap_path]
if duration:
cmd += ["-a", f"duration:{duration}"]
subprocess.Popen(cmd)
msg = f"抓包已启动,保存为:{pcap_path}"
return render_template_string(TEMPLATE, msg=msg)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8888)
web控制抓多目标
from flask import Flask, render_template_string, request
import subprocess
import os
from datetime import datetime
app = Flask(__name__)
OUTPUT_DIR = "/data"
os.makedirs(OUTPUT_DIR, exist_ok=True)
TEMPLATE = """
<!doctype html>
<title>多目标抓包平台</title>
<h2>Web 多目标抓包平台</h2>
<form method="post">
网卡名: <input name="iface" value="enp1s0"><br><br>
抓包目标(可多个,用空格分隔): <input name="targets"><br><br>
抓包时长(秒,可选): <input name="duration"><br><br>
<input type="submit" value="开始抓包">
</form>
{% if msg %}<p style="color:green;white-space:pre-line;">{{ msg }}</p>{% endif %}
"""
@app.route("/", methods=["GET", "POST"])
def index():
msg = ""
if request.method == "POST":
iface = request.form["iface"]
targets = request.form["targets"].split()
duration = request.form.get("duration")
for target in targets:
if "/" in target:
f = f"net {target}"
else:
f = f"host {target}"
timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
safe_target = target.replace("/", "_")
pcap_path = os.path.join(OUTPUT_DIR, f"{timestamp}-{safe_target}.pcapng")
cmd = ["tshark", "-i", iface, "-f", f, "-w", pcap_path]
if duration:
cmd += ["-a", f"duration:{duration}"]
subprocess.Popen(cmd)
msg += f"✅ {target} 抓包启动,保存为 {pcap_path}\n"
return render_template_string(TEMPLATE, msg=msg)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8888)
web优化(终极版,推荐)
from flask import Flask, render_template_string, request, redirect, url_for, send_from_directory, Response
import subprocess
import os
from datetime import datetime
import threading
app = Flask(__name__)
OUTPUT_DIR = "/data"
os.makedirs(OUTPUT_DIR, exist_ok=True)
tasks = {}
history = []
task_id_counter = 1
log_buffers = {}
#--- 转换 TXT ---
def convert_to_txt(pcap_path, txt_path):
cmd = [
"tshark", "-r", pcap_path,
"-T", "fields", "-E", "header=y",
"-e", "frame.number", "-e", "frame.time_relative",
"-e", "ip.src", "-e", "ip.dst",
"-e", "tcp.srcport", "-e", "tcp.dstport",
"-e", "_ws.col.Info"
]
with open(txt_path, "w") as f:
proc = subprocess.Popen(cmd, stdout=f)
proc.wait() # 避免产生僵尸进程
def async_convert(task):
pcap_file = task["file"]
txt_file = task["txt"]
convert_to_txt(pcap_file, txt_file)
for h in history:
if h["pcap"] == os.path.basename(pcap_file):
h["txt"] = os.path.basename(txt_file)
#--- 实时输出 tshark ---
def stream_output(tid, proc):
log_buffers[tid] = []
for line in iter(proc.stdout.readline, b''):
log_buffers[tid].append(line.decode())
@app.route("/")
def index():
return render_template_string(TEMPLATE, tasks=tasks, history=history, default_ip=request.remote_addr)
@app.route("/start", methods=["POST"])
def start_capture():
global task_id_counter
iface = request.form["iface"]
targets = request.form["targets"].split()
duration = request.form.get("duration") or "3600"
snaplen = request.form.get("snaplen") or "400"
auto_txt = "auto_txt" in request.form
for target in targets:
capture_filter = f"net {target}" if "/" in target else f"host {target}"
timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
safe_target = target.replace("/", "_")
pcap = f"{timestamp}-{safe_target}.pcapng"
txt = f"{timestamp}-{safe_target}.txt"
pcap_path = os.path.join(OUTPUT_DIR, pcap)
txt_path = os.path.join(OUTPUT_DIR, txt)
cmd = ["tshark", "-i", iface, "-f", capture_filter, "-s", snaplen, "-w", pcap_path, "-l"]
if duration:
cmd += ["-a", f"duration:{duration}"]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
tid = task_id_counter
task_id_counter += 1
tasks[tid] = {
"target": target,
"file": pcap_path,
"txt": txt_path if auto_txt else None,
"pid": proc.pid,
"proc": proc,
"timestamp": timestamp,
"auto_txt": auto_txt
}
threading.Thread(target=stream_output, args=(tid, proc), daemon=True).start()
return redirect(url_for("index"))
@app.route("/stop/<int:tid>", methods=["POST"])
def stop_capture(tid):
task = tasks.pop(tid, None)
if task:
proc = task["proc"]
proc.terminate()
try:
proc.wait(timeout=3)
except subprocess.TimeoutExpired:
proc.kill()
history.append({
"target": task["target"],
"timestamp": task["timestamp"],
"pcap": os.path.basename(task["file"]),
"txt": None
})
if task.get("auto_txt"):
threading.Thread(target=async_convert, args=(task,), daemon=True).start()
return redirect(url_for("index"))
@app.route("/convert/<pcap>", methods=["POST"])
def manual_convert(pcap):
txt = pcap.replace(".pcapng", ".txt")
convert_to_txt(os.path.join(OUTPUT_DIR, pcap), os.path.join(OUTPUT_DIR, txt))
for h in history:
if h["pcap"] == pcap:
h["txt"] = txt
return redirect(url_for("index"))
@app.route("/logs/<int:tid>")
def show_logs(tid):
lines = log_buffers.get(tid, ["暂无日志"])
content = "".join(lines)
html = f"""
<html><head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="1">
<title>实时日志</title>
<style>body {{ background:black; color:lime; padding:10px; }}</style>
</head><body>
<pre>{content}</pre>
</body></html>
"""
return Response(html, mimetype="text/html")
@app.route("/download/<filename>")
def download(filename):
return send_from_directory(OUTPUT_DIR, filename, as_attachment=True)
#--- 前端模板 ---
TEMPLATE = """
<!doctype html>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>WEB抓包控制台</title>
<!--<link href="http://10.0.1.200/bootstrap.min.css" rel="stylesheet">-->
<link href="http://192.168.20.100:8080/bootstrap.min.css" rel="stylesheet">
<style>
body { padding: 2rem; background-color: #f8f9fa; }
.card { margin-bottom: 2rem; }
.table thead th { background-color: #e9ecef; }
.form-control, .btn { margin-bottom: 1rem; }
pre { max-height: 300px; overflow-y: scroll; background: #000; color: #0f0; padding: 1rem; }
</style>
</head>
<body>
<div class="container">
<h2 class="mb-4 text-primary">WEB抓包控制台</h2>
<div class="card shadow-sm">
<div class="card-header">发起新抓包任务</div>
<div class="card-body">
<form method="post" action="/start">
<div class="row">
<div class="col-md-3">
<label>网卡名</label>
<input class="form-control" name="iface" value="enp1s0">
</div>
<div class="col-md-3">
<label>抓包目标(空格分隔)</label>
<input class="form-control" name="targets" value="{{ default_ip }}">
</div>
<div class="col-md-2">
<label>时长(秒)</label>
<input class="form-control" name="duration" value="3600">
</div>
<div class="col-md-2">
<label>每包最大字节</label>
<input class="form-control" name="snaplen" value="400">
</div>
<div class="col-md-2">
<label>选项</label><br>
<input type="checkbox" name="auto_txt"> 自动转为TXT
</div>
</div>
<button type="submit" class="btn btn-success mt-2">开始抓包</button>
</form>
</div>
</div>
<div class="card shadow-sm">
<div class="card-header">当前抓包任务</div>
<div class="card-body">
{% if tasks %}
<div class="table-responsive">
<table class="table table-bordered table-hover align-middle">
<thead>
<tr><th>ID</th><th>目标</th><th>PID</th><th>操作</th><th>日志</th></tr>
</thead>
<tbody>
{% for tid, t in tasks.items() %}
<tr>
<td>{{ tid }}</td>
<td>{{ t['target'] }}</td>
<td>{{ t['pid'] }}</td>
<td>
<form method="post" action="/stop/{{ tid }}">
<button class="btn btn-danger btn-sm">停止</button>
</form>
</td>
<td><a href="/logs/{{ tid }}" target="_blank" class="btn btn-secondary btn-sm">查看日志</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p class="text-muted">暂无运行中任务</p>
{% endif %}
</div>
</div>
<div class="card shadow-sm">
<div class="card-header">抓包历史记录</div>
<div class="card-body">
{% if history %}
<div class="table-responsive">
<table class="table table-striped table-bordered align-middle">
<thead>
<tr><th>时间</th><th>目标</th><th>PCAP 文件</th><th>TXT 文件</th></tr>
</thead>
<tbody>
{% for h in history %}
<tr>
<td>{{ h['timestamp'] }}</td>
<td>{{ h['target'] }}</td>
<td><a href="/download/{{ h['pcap'] }}" class="btn btn-outline-primary btn-sm">{{ h['pcap'] }}</a></td>
<td>
{% if h['txt'] %}
<a href="/download/{{ h['txt'] }}" class="btn btn-outline-secondary btn-sm">{{ h['txt'] }}</a>
{% else %}
<form method="post" action="/convert/{{ h['pcap'] }}">
<button class="btn btn-warning btn-sm">手动转换</button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p class="text-muted">暂无历史记录</p>
{% endif %}
</div>
</div>
</div>
</body>
</html>
"""
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8888)
Comments | NOTHING
该文章已经关闭评论