ivt / app.py
seawolf2357's picture
Update app.py
2ab28ff verified
"""
IVT 봇 트래픽 생성기
- 다양한 IVT 패턴 시뮬레이션
- 테스트 목적 전용
"""
import gradio as gr
import requests
import random
import string
import time
import threading
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor
import json
# ============================================
# 봇 User-Agent 목록
# ============================================
BOT_USER_AGENTS = {
"googlebot": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
"bingbot": "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)",
"yandex": "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)",
"baidu": "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
"curl": "curl/7.68.0",
"wget": "Wget/1.20.3 (linux-gnu)",
"python_requests": "python-requests/2.28.0",
"scrapy": "Scrapy/2.7.0 (+https://scrapy.org)",
"selenium": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Selenium",
"puppeteer": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/120.0.0.0 Safari/537.36",
"phantomjs": "Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1",
"java": "Java/17.0.1",
"go_http": "Go-http-client/1.1",
"node_fetch": "node-fetch/1.0 (+https://github.com/node-fetch/node-fetch)",
"axios": "axios/1.4.0",
"httpx": "python-httpx/0.24.0",
"postman": "PostmanRuntime/7.32.0",
}
NORMAL_USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (Linux; Android 14; SM-S918B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
]
SUSPICIOUS_REFERRERS = [
"https://traffic-exchange.com/surf",
"https://autosurf.pro/visit",
"https://free-traffic-bot.com/",
"https://paid-to-click.net/earn",
"https://hit-exchange.org/view",
"https://buy-cheap-traffic.com/",
"https://cashsurf.io/browse",
]
DATACENTER_IPS = [
"52.94.76.0", # AWS
"35.192.0.0", # GCP
"20.36.0.0", # Azure
"104.16.0.0", # Cloudflare
"159.89.0.0", # DigitalOcean
"172.104.0.0", # Linode
"45.32.0.0", # Vultr
]
# ============================================
# 트래픽 로그
# ============================================
traffic_log = []
log_lock = threading.Lock()
def add_log(message: str, status: str = "info"):
with log_lock:
timestamp = datetime.now().strftime("%H:%M:%S")
icon = {"success": "✅", "error": "❌", "warning": "⚠️", "info": "ℹ️"}.get(status, "📝")
traffic_log.append(f"[{timestamp}] {icon} {message}")
if len(traffic_log) > 100:
traffic_log.pop(0)
def get_logs():
with log_lock:
return "\n".join(traffic_log[-50:]) if traffic_log else "로그 없음"
# ============================================
# 핑거프린트 생성기
# ============================================
def generate_fingerprint(pattern_type: str, custom_settings: dict = None) -> dict:
"""IVT 패턴에 따른 핑거프린트 생성"""
fp = {
"timestamp": datetime.now().isoformat(),
"sessionToken": f"bot_{int(time.time())}_{random.randint(1000, 9999)}",
}
# 기본 설정
settings = custom_settings or {}
if pattern_type == "bot_ua":
# 봇 User-Agent 패턴
bot_type = settings.get("bot_type", random.choice(list(BOT_USER_AGENTS.keys())))
fp["userAgent"] = BOT_USER_AGENTS.get(bot_type, BOT_USER_AGENTS["curl"])
fp["platform"] = "Linux x86_64"
fp["webdriver"] = False
fp["pluginsCount"] = "0"
fp["hasMouseMove"] = False
fp["hasScroll"] = False
fp["hasClick"] = False
fp["dwellTime"] = random.uniform(0.1, 0.5)
elif pattern_type == "headless":
# Headless 브라우저 패턴
fp["userAgent"] = random.choice([
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36"
])
fp["webdriver"] = True
fp["webGLVendor"] = "Google Inc. (Google)"
fp["webGLRenderer"] = "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero)), SwiftShader driver)"
fp["platform"] = "Linux x86_64"
fp["pluginsCount"] = "0"
fp["hasMouseMove"] = False
fp["hasScroll"] = False
fp["dwellTime"] = random.uniform(0.05, 0.3)
elif pattern_type == "rapid_click":
# 빠른 반복 클릭 패턴
fp["userAgent"] = random.choice(NORMAL_USER_AGENTS)
fp["platform"] = random.choice(["Win32", "MacIntel", "Linux x86_64"])
fp["webdriver"] = False
fp["hasMouseMove"] = True
fp["hasScroll"] = False
fp["hasClick"] = True
fp["dwellTime"] = random.uniform(0.1, 0.8) # 매우 짧은 체류
fp["pluginsCount"] = str(random.randint(3, 10))
elif pattern_type == "no_interaction":
# 무상호작용 패턴
fp["userAgent"] = random.choice(NORMAL_USER_AGENTS)
fp["platform"] = random.choice(["Win32", "MacIntel"])
fp["webdriver"] = False
fp["hasMouseMove"] = False
fp["hasScroll"] = False
fp["hasClick"] = False
fp["hasKeypress"] = False
fp["dwellTime"] = random.uniform(0.5, 2.0)
fp["pluginsCount"] = str(random.randint(0, 2))
elif pattern_type == "datacenter_ip":
# 데이터센터 IP 패턴 (시뮬레이션)
fp["userAgent"] = random.choice(NORMAL_USER_AGENTS)
fp["platform"] = "Linux x86_64"
fp["webdriver"] = False
fp["hasMouseMove"] = random.choice([True, False])
fp["dwellTime"] = random.uniform(1, 5)
# IP는 실제로는 서버에서 감지되지만, 여기서는 플래그만 설정
fp["_simulated_datacenter"] = True
elif pattern_type == "suspicious_referrer":
# 의심스러운 Referrer 패턴
fp["userAgent"] = random.choice(NORMAL_USER_AGENTS)
fp["platform"] = random.choice(["Win32", "MacIntel"])
fp["referrer"] = random.choice(SUSPICIOUS_REFERRERS)
fp["webdriver"] = False
fp["hasMouseMove"] = True
fp["dwellTime"] = random.uniform(2, 10)
elif pattern_type == "device_mismatch":
# 디바이스 불일치 패턴 (모바일 UA + 데스크톱 플랫폼)
fp["userAgent"] = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 Mobile Safari/604.1"
fp["platform"] = "Win32" # 불일치!
fp["screenWidth"] = "1920"
fp["screenHeight"] = "1080"
fp["maxTouchPoints"] = "0" # 터치 없음 (모바일인데?)
fp["webdriver"] = False
fp["dwellTime"] = random.uniform(3, 10)
elif pattern_type == "geo_mismatch":
# 지역-언어 불일치 패턴
fp["userAgent"] = random.choice(NORMAL_USER_AGENTS)
fp["platform"] = random.choice(["Win32", "MacIntel"])
fp["languages"] = "zh-CN,zh" # 중국어인데
fp["timezone"] = "-540" # 한국 시간대 (불일치)
fp["webdriver"] = False
fp["dwellTime"] = random.uniform(5, 15)
elif pattern_type == "abnormal_screen":
# 비정상 해상도 패턴
fp["userAgent"] = random.choice(NORMAL_USER_AGENTS)
fp["platform"] = "Win32"
fp["screenWidth"] = random.choice(["0", "1", "100"])
fp["screenHeight"] = random.choice(["0", "1", "100"])
fp["webdriver"] = False
fp["dwellTime"] = random.uniform(1, 5)
elif pattern_type == "mixed_attack":
# 복합 공격 패턴 (여러 플래그 동시)
fp["userAgent"] = BOT_USER_AGENTS["selenium"]
fp["platform"] = "Linux x86_64"
fp["webdriver"] = True
fp["webGLRenderer"] = "SwiftShader"
fp["pluginsCount"] = "0"
fp["hasMouseMove"] = False
fp["hasScroll"] = False
fp["hasClick"] = False
fp["dwellTime"] = 0.1
fp["referrer"] = random.choice(SUSPICIOUS_REFERRERS)
fp["screenWidth"] = "800"
fp["screenHeight"] = "600"
else: # normal
# 정상 트래픽 패턴
fp["userAgent"] = random.choice(NORMAL_USER_AGENTS)
fp["platform"] = random.choice(["Win32", "MacIntel", "Linux x86_64"])
fp["webdriver"] = False
fp["hasMouseMove"] = True
fp["hasScroll"] = True
fp["hasClick"] = True
fp["hasKeypress"] = random.choice([True, False])
fp["dwellTime"] = random.uniform(10, 60)
fp["pluginsCount"] = str(random.randint(3, 15))
fp["languages"] = random.choice(["ko-KR,ko,en-US,en", "en-US,en", "ja-JP,ja,en"])
# 공통 필드 추가
fp.setdefault("platform", "Win32")
fp.setdefault("timezone", str(random.choice([-540, -480, -420, 0, 60, 120])))
fp.setdefault("deviceMemory", str(random.choice([2, 4, 8, 16])))
fp.setdefault("screenWidth", str(random.choice([1366, 1920, 2560, 1440])))
fp.setdefault("screenHeight", str(random.choice([768, 1080, 1440, 900])))
fp.setdefault("screenDepth", "24")
fp.setdefault("hardwareConcurrency", str(random.choice([2, 4, 8, 12, 16])))
fp.setdefault("languages", "en-US,en")
fp.setdefault("doNotTrack", random.choice(["1", "0", "NC"]))
fp.setdefault("maxTouchPoints", "0")
fp.setdefault("pluginsCount", str(random.randint(0, 10)))
fp.setdefault("referrer", "direct")
fp.setdefault("currentUrl", "https://test-site.com/page")
fp.setdefault("currentHost", "test-site.com")
fp.setdefault("webGLVendor", "Google Inc. (NVIDIA)")
fp.setdefault("webGLRenderer", "ANGLE (NVIDIA, NVIDIA GeForce RTX 3080)")
fp.setdefault("canvasHash", ''.join(random.choices(string.hexdigits, k=50)))
fp.setdefault("audioSampleRate", "48000")
fp.setdefault("videoFormats", '{"mp4":"probably","webm":"probably"}')
return fp
# ============================================
# 트래픽 전송
# ============================================
def send_single_request(target_url: str, fingerprint: dict, request_num: int) -> bool:
"""단일 요청 전송"""
try:
# API 엔드포인트 구성
if not target_url.endswith('/'):
target_url += '/'
# Gradio API 엔드포인트로 전송 시도
api_url = target_url.rstrip('/') + "/api/collect"
headers = {
"Content-Type": "application/json",
"User-Agent": fingerprint.get("userAgent", "python-requests/2.28.0"),
"Referer": fingerprint.get("referrer", ""),
}
response = requests.post(
api_url,
json=fingerprint,
headers=headers,
timeout=10
)
if response.status_code == 200:
add_log(f"요청 #{request_num} 성공 - {fingerprint.get('sessionToken', 'unknown')[:20]}", "success")
return True
else:
add_log(f"요청 #{request_num} 실패 (HTTP {response.status_code})", "warning")
return False
except requests.exceptions.Timeout:
add_log(f"요청 #{request_num} 타임아웃", "error")
return False
except requests.exceptions.ConnectionError:
add_log(f"요청 #{request_num} 연결 실패", "error")
return False
except Exception as e:
add_log(f"요청 #{request_num} 오류: {str(e)[:50]}", "error")
return False
def generate_traffic(
target_url: str,
pattern_type: str,
request_count: int,
delay_ms: int,
concurrent: int,
bot_type: str = "random",
progress=gr.Progress()
) -> tuple:
"""트래픽 생성 메인 함수"""
if not target_url:
return "❌ 대상 URL을 입력하세요", get_logs()
if not target_url.startswith("http"):
target_url = "https://" + target_url
add_log(f"트래픽 생성 시작: {target_url}", "info")
add_log(f"패턴: {pattern_type}, 요청 수: {request_count}, 딜레이: {delay_ms}ms", "info")
success_count = 0
fail_count = 0
custom_settings = {}
if bot_type != "random" and pattern_type == "bot_ua":
custom_settings["bot_type"] = bot_type
# 빠른 반복 클릭 테스트인 경우 딜레이 무시
if pattern_type == "rapid_click":
delay_ms = min(delay_ms, 100)
with ThreadPoolExecutor(max_workers=concurrent) as executor:
futures = []
for i in range(request_count):
progress((i + 1) / request_count, desc=f"요청 {i+1}/{request_count}")
fp = generate_fingerprint(pattern_type, custom_settings)
future = executor.submit(send_single_request, target_url, fp, i + 1)
futures.append(future)
if delay_ms > 0 and i < request_count - 1:
time.sleep(delay_ms / 1000)
for future in futures:
if future.result():
success_count += 1
else:
fail_count += 1
result = f"""## 📊 트래픽 생성 완료
| 항목 | 결과 |
|------|------|
| **대상 URL** | `{target_url}` |
| **패턴** | {pattern_type} |
| **총 요청** | {request_count}회 |
| **성공** | ✅ {success_count}회 |
| **실패** | ❌ {fail_count}회 |
| **성공률** | {success_count/request_count*100:.1f}% |
"""
add_log(f"완료: 성공 {success_count}, 실패 {fail_count}", "success" if fail_count == 0 else "warning")
return result, get_logs()
def clear_logs():
global traffic_log
with log_lock:
traffic_log = []
return "로그가 초기화되었습니다."
# ============================================
# Gradio UI
# ============================================
with gr.Blocks(title="IVT Bot Traffic Generator") as demo:
gr.Markdown("""# 🤖 IVT 봇 트래픽 생성기
**⚠️ 주의: 테스트 목적으로만 사용하세요. 본인 소유 서버에서만 테스트하세요.**
IVT 탐지 시스템 테스트를 위한 다양한 부정 트래픽 패턴을 생성합니다.
""")
with gr.Tabs():
# 탭 1: 트래픽 생성
with gr.TabItem("🚀 트래픽 생성"):
with gr.Row():
with gr.Column(scale=2):
target_url = gr.Textbox(
label="🎯 대상 URL",
placeholder="https://your-ivt-server.hf.space",
info="IVT 탐지 서버의 URL을 입력하세요"
)
pattern_type = gr.Dropdown(
label="📋 IVT 패턴 선택",
choices=[
("🤖 봇 User-Agent", "bot_ua"),
("👻 Headless 브라우저 (WebDriver)", "headless"),
("⚡ 빠른 반복 클릭", "rapid_click"),
("🚫 무상호작용 (No Interaction)", "no_interaction"),
("🏢 데이터센터 IP 시뮬레이션", "datacenter_ip"),
("🔗 의심스러운 Referrer", "suspicious_referrer"),
("📱 디바이스 불일치 (Mobile UA + Desktop)", "device_mismatch"),
("🗺️ 지역-언어 불일치", "geo_mismatch"),
("📐 비정상 해상도", "abnormal_screen"),
("💀 복합 공격 (다중 플래그)", "mixed_attack"),
("✅ 정상 트래픽", "normal"),
],
value="bot_ua",
info="생성할 IVT 패턴을 선택하세요"
)
with gr.Row():
request_count = gr.Slider(
label="요청 수",
minimum=1,
maximum=100,
value=5,
step=1,
info="생성할 요청 수"
)
delay_ms = gr.Slider(
label="딜레이 (ms)",
minimum=0,
maximum=5000,
value=500,
step=100,
info="요청 간 딜레이"
)
with gr.Row():
concurrent = gr.Slider(
label="동시 요청 수",
minimum=1,
maximum=10,
value=1,
step=1,
info="병렬 처리 수"
)
# 봇 UA 상세 선택 (패턴이 bot_ua일 때만 표시)
bot_type = gr.Dropdown(
label="🤖 봇 유형 (봇 UA 패턴 전용)",
choices=[
("랜덤", "random"),
("Googlebot", "googlebot"),
("Bingbot", "bingbot"),
("curl", "curl"),
("wget", "wget"),
("Python Requests", "python_requests"),
("Scrapy", "scrapy"),
("Selenium", "selenium"),
("Puppeteer", "puppeteer"),
("PhantomJS", "phantomjs"),
("Java", "java"),
("Go HTTP", "go_http"),
("Axios", "axios"),
("Postman", "postman"),
],
value="random",
visible=True
)
with gr.Row():
generate_btn = gr.Button("🚀 트래픽 생성", variant="primary", scale=2)
clear_btn = gr.Button("🗑️ 로그 초기화", scale=1)
with gr.Column(scale=1):
result_output = gr.Markdown(value="**설정 후 '트래픽 생성' 버튼을 클릭하세요**")
gr.Markdown("### 📜 실행 로그")
log_output = gr.Textbox(
label="",
value="로그 없음",
lines=15,
max_lines=20,
interactive=False
)
generate_btn.click(
fn=generate_traffic,
inputs=[target_url, pattern_type, request_count, delay_ms, concurrent, bot_type],
outputs=[result_output, log_output]
)
clear_btn.click(fn=clear_logs, outputs=log_output)
# 탭 2: 패턴 설명
with gr.TabItem("📖 패턴 설명"):
gr.Markdown("""
## 🛡️ IVT 패턴 상세 설명
각 패턴이 어떤 부정 트래픽을 시뮬레이션하는지 설명합니다.
---
### 🤖 봇 User-Agent (`bot_ua`)
**탐지 점수: 40점**
웹 크롤러, 스크레이퍼 등의 봇 UA를 사용합니다.
| 봇 유형 | User-Agent 예시 |
|---------|----------------|
| Googlebot | `compatible; Googlebot/2.1` |
| curl | `curl/7.68.0` |
| Python | `python-requests/2.28.0` |
| Scrapy | `Scrapy/2.7.0` |
---
### 👻 Headless 브라우저 (`headless`)
**탐지 점수: 50-85점**
Selenium, Puppeteer 등 자동화 도구를 탐지합니다.
- `navigator.webdriver = true`
- WebGL Renderer: `SwiftShader` (소프트웨어 렌더링)
- 플러그인 수: 0개
---
### ⚡ 빠른 반복 클릭 (`rapid_click`)
**탐지 점수: 25-45점**
클릭 팜, 자동 클릭 봇을 시뮬레이션합니다.
- 5초 내 2회 이상 클릭
- 1분 내 5회 이상 클릭
- 체류시간 1초 미만
---
### 🚫 무상호작용 (`no_interaction`)
**탐지 점수: 20점**
페이지 로드 후 아무 동작도 하지 않는 패턴입니다.
- 마우스 이동 없음
- 스크롤 없음
- 클릭 없음
- 키보드 입력 없음
---
### 🏢 데이터센터 IP (`datacenter_ip`)
**탐지 점수: 25-30점**
AWS, GCP, Azure 등 클라우드 서버에서 오는 트래픽입니다.
- ASN에 'amazon', 'google', 'microsoft' 포함
- 호스팅/서버 IP로 분류됨
---
### 🔗 의심스러운 Referrer (`suspicious_referrer`)
**탐지 점수: 35점**
트래픽 교환, PTC(Paid-to-Click) 사이트에서 오는 트래픽입니다.
- `traffic-exchange.com`
- `paid-to-click.net`
- `autosurf.pro`
---
### 📱 디바이스 불일치 (`device_mismatch`)
**탐지 점수: 20점**
UA와 실제 디바이스 정보가 맞지 않는 경우입니다.
- 모바일 UA + 데스크톱 플랫폼
- 모바일 UA + 터치 미지원
---
### 🗺️ 지역-언어 불일치 (`geo_mismatch`)
**탐지 점수: 15점**
IP 위치와 브라우저 언어 설정이 맞지 않습니다.
- 한국 IP + 중국어 언어
- 미국 IP + 일본어 언어
---
### 📐 비정상 해상도 (`abnormal_screen`)
**탐지 점수: 20-30점**
화면 해상도가 비정상적인 경우입니다.
- 0x0, 1x1 해상도
- 300 미만의 너비/높이
---
### 💀 복합 공격 (`mixed_attack`)
**탐지 점수: 70점 이상 (GIVT)**
여러 IVT 패턴을 동시에 포함합니다.
- WebDriver 감지
- 봇 UA
- SwiftShader
- 무상호작용
- 의심스러운 Referrer
---
### ✅ 정상 트래픽 (`normal`)
**탐지 점수: 0-10점**
일반 사용자 행동을 시뮬레이션합니다.
- 정상 브라우저 UA
- 마우스/스크롤/클릭 상호작용
- 10-60초 체류시간
- 정상 플러그인 수
""")
# 탭 3: 빠른 테스트
with gr.TabItem("⚡ 빠른 테스트"):
gr.Markdown("""
### 원클릭 테스트
각 버튼을 클릭하면 해당 패턴으로 5회 요청을 즉시 전송합니다.
""")
quick_url = gr.Textbox(
label="🎯 대상 URL",
placeholder="https://your-ivt-server.hf.space"
)
quick_result = gr.Markdown()
quick_log = gr.Textbox(label="로그", lines=10, interactive=False)
with gr.Row():
btn_bot = gr.Button("🤖 봇 UA", variant="secondary")
btn_headless = gr.Button("👻 Headless", variant="secondary")
btn_rapid = gr.Button("⚡ 반복클릭", variant="secondary")
btn_noact = gr.Button("🚫 무상호작용", variant="secondary")
with gr.Row():
btn_referrer = gr.Button("🔗 의심 Referrer", variant="secondary")
btn_device = gr.Button("📱 디바이스불일치", variant="secondary")
btn_mixed = gr.Button("💀 복합공격", variant="stop")
btn_normal = gr.Button("✅ 정상", variant="primary")
# 빠른 테스트 버튼 연결
btn_bot.click(
fn=lambda url: generate_traffic(url, "bot_ua", 5, 200, 1, "random"),
inputs=[quick_url],
outputs=[quick_result, quick_log]
)
btn_headless.click(
fn=lambda url: generate_traffic(url, "headless", 5, 200, 1, "random"),
inputs=[quick_url],
outputs=[quick_result, quick_log]
)
btn_rapid.click(
fn=lambda url: generate_traffic(url, "rapid_click", 10, 50, 2, "random"),
inputs=[quick_url],
outputs=[quick_result, quick_log]
)
btn_noact.click(
fn=lambda url: generate_traffic(url, "no_interaction", 5, 200, 1, "random"),
inputs=[quick_url],
outputs=[quick_result, quick_log]
)
btn_referrer.click(
fn=lambda url: generate_traffic(url, "suspicious_referrer", 5, 200, 1, "random"),
inputs=[quick_url],
outputs=[quick_result, quick_log]
)
btn_device.click(
fn=lambda url: generate_traffic(url, "device_mismatch", 5, 200, 1, "random"),
inputs=[quick_url],
outputs=[quick_result, quick_log]
)
btn_mixed.click(
fn=lambda url: generate_traffic(url, "mixed_attack", 5, 200, 1, "random"),
inputs=[quick_url],
outputs=[quick_result, quick_log]
)
btn_normal.click(
fn=lambda url: generate_traffic(url, "normal", 5, 500, 1, "random"),
inputs=[quick_url],
outputs=[quick_result, quick_log]
)
if __name__ == "__main__":
demo.launch()