87 lines
4.1 KiB
Python
87 lines
4.1 KiB
Python
"""生成复杂 TLS 合成测试数据(含经纬度、MAC地址、大量空值)"""
|
|
import polars as pl
|
|
import numpy as np
|
|
from pathlib import Path
|
|
|
|
RNG = np.random.RandomState(42)
|
|
|
|
CLIENTS = [f'192.168.{RNG.randint(1,255)}.{RNG.randint(1,255)}' for _ in range(80)]
|
|
SERVERS = (
|
|
[f'10.0.{RNG.randint(1,255)}.{RNG.randint(1,255)}' for _ in range(80)]
|
|
+ [f'203.0.113.{RNG.randint(1,255)}' for _ in range(30)]
|
|
)
|
|
DOMAINS = ['mail.example.com', 'api.example.org', 'cdn.example.net', 'login.example.org',
|
|
'storage.example.net', 'video.example.com', 'auth.example.com', 'pay.example.org']
|
|
TLS_VERSIONS = ['TLSv1.2', 'TLSv1.3', 'TLSv1.2', 'TLSv1.3', 'TLSv1.1', None]
|
|
CIPHERS = ['TLS_AES_128_GCM_SHA256', 'TLS_AES_256_GCM_SHA384',
|
|
'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', None]
|
|
CERT_STATUS = ['valid', 'valid', 'valid', 'expired', 'self_signed', None]
|
|
|
|
def gen_mac():
|
|
return ':'.join(f'{RNG.randint(0,255):02x}' for _ in range(6))
|
|
|
|
CITIES = [
|
|
('Beijing', 39.9, 116.4), ('Shanghai', 31.2, 121.5), ('Tokyo', 35.7, 139.7),
|
|
('Singapore', 1.35, 103.8), ('London', 51.5, -0.13), ('Frankfurt', 50.1, 8.68),
|
|
('NewYork', 40.7, -74.0), ('SanFrancisco', 37.8, -122.4),
|
|
('Sydney', -33.9, 151.2), ('Mumbai', 19.1, 72.9),
|
|
]
|
|
|
|
def gen_flows(n_rows=5000):
|
|
from datetime import datetime, timedelta
|
|
base_ts = datetime(2025, 1, 1)
|
|
rows = []
|
|
for _ in range(n_rows):
|
|
src_ip = RNG.choice(CLIENTS)
|
|
dst_ip = RNG.choice(SERVERS)
|
|
si = RNG.randint(0, len(CITIES))
|
|
di = RNG.randint(0, len(CITIES))
|
|
src_city, src_lat, src_lon = CITIES[si]
|
|
dst_city, dst_lat, dst_lon = CITIES[di]
|
|
same_city = src_city == dst_city
|
|
|
|
bs = int(max(0, RNG.lognormal(8, 2))) if RNG.random() > 0.05 else None
|
|
br = int(max(0, bs * RNG.uniform(0.1, 2))) if bs and RNG.random() > 0.05 else None
|
|
dur = round(RNG.exponential(20), 2) if RNG.random() > 0.08 else None
|
|
hok = RNG.choice([True, True, True, False, None])
|
|
trusted = hok and RNG.choice([True, True, False, None]) if hok else None
|
|
tmo = int(RNG.exponential(500)) + 100 if hok else RNG.choice([None, RNG.randint(5000, 30000)])
|
|
|
|
rows.append({
|
|
'timestamp': (base_ts + timedelta(seconds=RNG.randint(0, 31536000))).strftime('%Y-%m-%d %H:%M:%S'),
|
|
'src_ip': src_ip, 'dst_ip': dst_ip,
|
|
'src_mac': gen_mac(), 'dst_mac': gen_mac(),
|
|
'src_url': f'https://{RNG.choice(DOMAINS)}{RNG.choice(["/","/login","/api/v1/users","/api/v1/data","/favicon.ico"])}',
|
|
'dst_url': f'https://{RNG.choice(DOMAINS)}{RNG.choice(["/","/login","/api/v1/users","/api/v1/data"])}',
|
|
'sni': RNG.choice(DOMAINS + [None, None]),
|
|
'src_city': src_city, 'src_latitude': src_lat, 'src_longitude': src_lon,
|
|
'dst_city': dst_city if not same_city else None,
|
|
'dst_latitude': dst_lat if not same_city else None,
|
|
'dst_longitude': dst_lon if not same_city else None,
|
|
'bytes_sent': bs, 'bytes_rev': br, 'duration': dur,
|
|
'tls_version': RNG.choice(TLS_VERSIONS),
|
|
'cipher': RNG.choice(CIPHERS),
|
|
'dst_port': RNG.choice([80, 443, 8080, 8443, 53, 993, 5223, None]),
|
|
'cert_status': RNG.choice(CERT_STATUS),
|
|
'handshake_ok': hok, 'trusted': trusted, 'timeout_ms': tmo,
|
|
})
|
|
df = pl.DataFrame(rows)
|
|
nulls = df.null_count()
|
|
for col in df.columns:
|
|
n = int(nulls[col].item())
|
|
if n > 0:
|
|
print(f' {col}: {n}/{len(df)} 缺失 ({n*100//len(df)}%)')
|
|
print(f'总行数: {len(df)}, 列数: {len(df.columns)}')
|
|
return df
|
|
|
|
if __name__ == '__main__':
|
|
import argparse
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--rows', type=int, default=5000)
|
|
parser.add_argument('--output', type=str, default='data/complex_test.csv')
|
|
args = parser.parse_args()
|
|
df = gen_flows(args.rows)
|
|
Path(args.output).parent.mkdir(parents=True, exist_ok=True)
|
|
df.write_csv(args.output, null_value='')
|
|
print(f'已生成: {args.output} ({Path(args.output).stat().st_size/1024/1024:.1f} MB)')
|