Add mitmproxy to HAR conversion tools
- scripts/mitmproxy-to-har.py: Конвертер mitm → HAR - MITMPROXY.md: Инструкция по записи и конвертации - Два способа: mitmweb (GUI) и mitmdump + скрипт
This commit is contained in:
parent
90f465eedb
commit
7b01544802
156
MITMPROXY.md
Normal file
156
MITMPROXY.md
Normal file
@ -0,0 +1,156 @@
|
||||
# Mitmproxy → HAR
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
### Вариант 1: mitmweb (проще всего)
|
||||
|
||||
```bash
|
||||
# 1. Запустить mitmweb
|
||||
mitmweb --mode regular
|
||||
|
||||
# 2. Открыть в браузере
|
||||
http://127.0.0.1:8081
|
||||
|
||||
# 3. Настроить прокси в браузере
|
||||
# localhost:8081
|
||||
|
||||
# 4. Выполнить действия на Kwork
|
||||
|
||||
# 5. Экспорт: File → Export → HAR
|
||||
```
|
||||
|
||||
### Вариант 2: mitmdump + конвертация
|
||||
|
||||
```bash
|
||||
# 1. Записать трафик
|
||||
mitmdump -w kwork-dump.mitm
|
||||
|
||||
# 2. Конвертировать в HAR
|
||||
python3 scripts/mitmproxy-to-har.py kwork-dump.mitm kwork-dump.har
|
||||
|
||||
# 3. Анализировать
|
||||
jq '.log.entries | length' kwork-dump.har
|
||||
```
|
||||
|
||||
## Настройка прокси
|
||||
|
||||
### Системный прокси (Linux)
|
||||
|
||||
```bash
|
||||
export http_proxy=http://127.0.0.1:8081
|
||||
export https_proxy=http://127.0.0.1:8081
|
||||
```
|
||||
|
||||
### Firefox
|
||||
|
||||
1. Настройки → Прокси
|
||||
2. Manual proxy configuration
|
||||
3. HTTP Proxy: 127.0.0.1:8081
|
||||
4. ☑ Also use for HTTPS
|
||||
|
||||
### Chrome
|
||||
|
||||
```bash
|
||||
# Запустить с прокси
|
||||
google-chrome --proxy-server="127.0.0.1:8081"
|
||||
```
|
||||
|
||||
## Установка сертификата
|
||||
|
||||
```bash
|
||||
# 1. Открыть в браузере
|
||||
http://mitm.it
|
||||
|
||||
# 2. Скачать сертификат для вашей ОС
|
||||
|
||||
# 3. Установить в доверенные
|
||||
# Linux:
|
||||
sudo cp mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/
|
||||
sudo update-ca-certificates
|
||||
|
||||
# 4. Перезапустить браузер
|
||||
```
|
||||
|
||||
## Фильтрация трафика
|
||||
|
||||
```bash
|
||||
# Только Kwork
|
||||
mitmdump -w kwork.mitm --set 'filter=~u kwork\.ru'
|
||||
|
||||
# Только API
|
||||
mitmdump -w kwork-api.mitm --set 'filter=~u /api/'
|
||||
|
||||
# Исключить статику
|
||||
mitmdump -w kwork.mitm --set 'filter=!~u \.(css|js|png|jpg|gif|svg)'
|
||||
```
|
||||
|
||||
## Скрипт для записи Kwork
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# record-kwork.sh
|
||||
|
||||
echo "Starting mitmproxy recording for Kwork..."
|
||||
echo "Configure your browser to use proxy: localhost:8081"
|
||||
echo "Press Ctrl+C when done"
|
||||
|
||||
mitmdump \
|
||||
-w kwork-session.mitm \
|
||||
--set 'filter=~u kwork\.ru' \
|
||||
--set 'ignore_hosts=~u (cdn|counter|yandex|google)' \
|
||||
--set 'keep_host_headers=true'
|
||||
|
||||
echo "Converting to HAR..."
|
||||
python3 scripts/mitmproxy-to-har.py kwork-session.mitm kwork-session.har
|
||||
|
||||
echo "Done! File: kwork-session.har"
|
||||
echo "Analyze with: jq '.log.entries | length' kwork-session.har"
|
||||
```
|
||||
|
||||
## Анализ записанного HAR
|
||||
|
||||
```bash
|
||||
# Количество запросов
|
||||
jq '.log.entries | length' kwork-session.har
|
||||
|
||||
# JSON эндпоинты
|
||||
jq '[.log.entries[] | select(.response.content.mimeType | test("json"; "i")) | .request.url | split("?")[0]] | unique' kwork-session.har
|
||||
|
||||
# Самые большие ответы
|
||||
jq '[.log.entries[] | {url: .request.url, size: .response.bodySize}] | sort_by(.size) | reverse | .[0:10]' kwork-session.har
|
||||
|
||||
# Авторизация
|
||||
jq '[.log.entries[].request.headers[] | select(.name | ascii_downcase | test("authorization|cookie"; "i"))] | unique' kwork-session.har
|
||||
```
|
||||
|
||||
## Типичные проблемы
|
||||
|
||||
### SSL ошибки
|
||||
|
||||
```bash
|
||||
# Игнорировать SSL ошибки
|
||||
mitmdump --set 'ignore_hosts=.*'
|
||||
|
||||
# Или отключить проверку
|
||||
mitmdump --set 'ssl_insecure=true'
|
||||
```
|
||||
|
||||
### WebSocket
|
||||
|
||||
```bash
|
||||
# WebSocket не экспортируется в HAR
|
||||
# Используйте --show-websocket для отладки
|
||||
mitmdump --show-websocket
|
||||
```
|
||||
|
||||
### Сжатый трафик
|
||||
|
||||
```bash
|
||||
# mitmproxy автоматически распаковывает
|
||||
# Если нужно сырое:
|
||||
mitmdump --set 'rawtcp=true'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
_Updated: 2026-03-22_
|
||||
97
scripts/mitmproxy-to-har.py
Normal file
97
scripts/mitmproxy-to-har.py
Normal file
@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Convert mitmproxy flow dump to HAR format
|
||||
Usage: mitmproxy-to-har.py <input.mitm> <output.har>
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from mitmproxy import io
|
||||
from mitmproxy.http import HTTPFlow
|
||||
|
||||
|
||||
def flow_to_har_entry(flow: HTTPFlow) -> dict:
|
||||
"""Convert single flow to HAR entry."""
|
||||
if not flow.request or not flow.response:
|
||||
return None
|
||||
|
||||
entry = {
|
||||
"startedDateTime": datetime.fromtimestamp(flow.request.timestamp_start).isoformat() + "Z",
|
||||
"time": int((flow.response.timestamp_end - flow.request.timestamp_start) * 1000) if flow.response.timestamp_end else 0,
|
||||
"request": {
|
||||
"method": flow.request.method,
|
||||
"url": flow.request.url,
|
||||
"httpVersion": flow.request.http_version,
|
||||
"headers": [{"name": k, "value": v} for k, v in flow.request.headers.items()],
|
||||
"queryString": [{"name": k, "value": v} for k, v in flow.request.query.items()],
|
||||
"cookies": [{"name": k, "value": v} for k, v in flow.request.cookies.items()],
|
||||
"headersSize": -1,
|
||||
"bodySize": len(flow.request.content) if flow.request.content else 0,
|
||||
},
|
||||
"response": {
|
||||
"status": flow.response.status_code,
|
||||
"statusText": flow.response.reason,
|
||||
"httpVersion": flow.response.http_version,
|
||||
"headers": [{"name": k, "value": v} for k, v in flow.response.headers.items()],
|
||||
"cookies": [{"name": k, "value": v} for k, v in flow.response.cookies.items()],
|
||||
"content": {
|
||||
"size": len(flow.response.content) if flow.response.content else 0,
|
||||
"mimeType": flow.response.headers.get("Content-Type", "unknown").split(";")[0],
|
||||
"text": flow.response.get_text() if flow.response.content else ""
|
||||
},
|
||||
"redirectURL": flow.response.headers.get("Location", ""),
|
||||
"headersSize": -1,
|
||||
"bodySize": len(flow.response.content) if flow.response.content else 0,
|
||||
},
|
||||
"cache": {},
|
||||
"timings": {
|
||||
"send": 0,
|
||||
"wait": int((flow.response.timestamp_start - flow.request.timestamp_end) * 1000) if flow.response.timestamp_start and flow.request.timestamp_end else 0,
|
||||
"receive": int((flow.response.timestamp_end - flow.response.timestamp_start) * 1000) if flow.response.timestamp_end and flow.response.timestamp_start else 0,
|
||||
}
|
||||
}
|
||||
|
||||
# Add POST data if present
|
||||
if flow.request.method == "POST" and flow.request.content:
|
||||
entry["request"]["postData"] = {
|
||||
"mimeType": flow.request.headers.get("Content-Type", "application/octet-stream"),
|
||||
"text": flow.request.get_text() if flow.request.content else ""
|
||||
}
|
||||
|
||||
return entry
|
||||
|
||||
|
||||
def convert_mitm_to_har(input_file: str, output_file: str):
|
||||
"""Convert mitmproxy dump to HAR."""
|
||||
har = {
|
||||
"log": {
|
||||
"version": "1.2",
|
||||
"creator": {
|
||||
"name": "mitmproxy-to-har",
|
||||
"version": "1.0"
|
||||
},
|
||||
"entries": []
|
||||
}
|
||||
}
|
||||
|
||||
with open(input_file, 'rb') as f:
|
||||
reader = io.FlowReader(f)
|
||||
for flow in reader.read():
|
||||
if isinstance(flow, HTTPFlow):
|
||||
entry = flow_to_har_entry(flow)
|
||||
if entry:
|
||||
har["log"]["entries"].append(entry)
|
||||
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(har, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"Converted {len(har['log']['entries'])} flows to {output_file}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 3:
|
||||
print("Usage: mitmproxy-to-har.py <input.mitm> <output.har>")
|
||||
sys.exit(1)
|
||||
|
||||
convert_mitm_to_har(sys.argv[1], sys.argv[2])
|
||||
Loading…
Reference in New Issue
Block a user