Add: verbose flag to show logs in detail
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -2851,6 +2851,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tokio-socks",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
@@ -2871,6 +2872,7 @@ dependencies = [
|
||||
"serde",
|
||||
"thiserror 2.0.17",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
@@ -2927,6 +2929,7 @@ dependencies = [
|
||||
"thiserror 2.0.17",
|
||||
"tokio",
|
||||
"tokio-socks",
|
||||
"tracing",
|
||||
"url",
|
||||
"wtfnet-geoip",
|
||||
]
|
||||
@@ -2942,6 +2945,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tokio-socks",
|
||||
"tracing",
|
||||
"url",
|
||||
"x509-parser",
|
||||
]
|
||||
|
||||
@@ -70,7 +70,7 @@ wtfn calc summarize 10.0.0.0/24 10.0.1.0/24
|
||||
Global flags:
|
||||
- `--json` / `--pretty`
|
||||
- `--no-color` / `--quiet`
|
||||
- `-v` / `-vv`
|
||||
- `-v` / `-vv` / `--verbose`
|
||||
- `--log-level <error|warn|info|debug|trace>`
|
||||
- `--log-format <text|json>`
|
||||
- `--log-file <path>`
|
||||
|
||||
@@ -24,7 +24,7 @@ struct Cli {
|
||||
no_color: bool,
|
||||
#[arg(long)]
|
||||
quiet: bool,
|
||||
#[arg(short = 'v', action = clap::ArgAction::Count)]
|
||||
#[arg(short = 'v', long = "verbose", action = clap::ArgAction::Count)]
|
||||
verbose: u8,
|
||||
#[arg(long)]
|
||||
log_level: Option<String>,
|
||||
|
||||
@@ -16,6 +16,7 @@ tokio-rustls = "0.24"
|
||||
tokio-socks = "0.5"
|
||||
url = "2"
|
||||
pnet = { version = "0.34", optional = true }
|
||||
tracing = "0.1"
|
||||
|
||||
[features]
|
||||
pcap = ["dep:pnet"]
|
||||
|
||||
@@ -19,6 +19,7 @@ use thiserror::Error;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio_rustls::TlsConnector;
|
||||
use tokio_socks::tcp::Socks5Stream;
|
||||
use tracing::debug;
|
||||
use url::Url;
|
||||
|
||||
#[cfg(feature = "pcap")]
|
||||
@@ -169,6 +170,15 @@ pub async fn query(
|
||||
timeout_ms: u64,
|
||||
) -> Result<DnsQueryReport, DnsError> {
|
||||
let record_type = parse_record_type(record_type)?;
|
||||
debug!(
|
||||
domain,
|
||||
record_type = %record_type,
|
||||
transport = %transport,
|
||||
server = ?server.as_ref().map(|value| value.addr),
|
||||
proxy = ?proxy.as_deref(),
|
||||
timeout_ms,
|
||||
"dns query start"
|
||||
);
|
||||
if let Some(proxy) = proxy {
|
||||
let server = server.ok_or_else(|| DnsError::MissingServer(transport.to_string()))?;
|
||||
return match transport {
|
||||
@@ -245,6 +255,15 @@ pub async fn detect(
|
||||
repeat: u32,
|
||||
timeout_ms: u64,
|
||||
) -> Result<DnsDetectResult, DnsError> {
|
||||
debug!(
|
||||
domain,
|
||||
transport = %transport,
|
||||
servers = servers.len(),
|
||||
proxy = ?proxy.as_deref(),
|
||||
repeat,
|
||||
timeout_ms,
|
||||
"dns detect start"
|
||||
);
|
||||
let mut results = Vec::new();
|
||||
for server in servers {
|
||||
for _ in 0..repeat.max(1) {
|
||||
@@ -311,6 +330,12 @@ pub async fn watch(_options: DnsWatchOptions) -> Result<DnsWatchReport, DnsError
|
||||
|
||||
#[cfg(feature = "pcap")]
|
||||
pub async fn watch(options: DnsWatchOptions) -> Result<DnsWatchReport, DnsError> {
|
||||
debug!(
|
||||
iface = ?options.iface,
|
||||
duration_ms = options.duration_ms,
|
||||
filter = ?options.filter,
|
||||
"dns watch start"
|
||||
);
|
||||
let iface = match select_interface(options.iface.as_deref()) {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
@@ -341,6 +366,15 @@ pub async fn watch(options: DnsWatchOptions) -> Result<DnsWatchReport, DnsError>
|
||||
match rx.next() {
|
||||
Ok(frame) => {
|
||||
if let Some(event) = parse_dns_frame(frame, start, &filter) {
|
||||
debug!(
|
||||
src = %event.src,
|
||||
dst = %event.dst,
|
||||
query_name = %event.query_name,
|
||||
query_type = %event.query_type,
|
||||
rcode = %event.rcode,
|
||||
is_response = event.is_response,
|
||||
"dns watch event"
|
||||
);
|
||||
events.push(event);
|
||||
}
|
||||
}
|
||||
@@ -435,6 +469,13 @@ async fn doh_query_via_proxy(
|
||||
timeout_ms: u64,
|
||||
proxy: String,
|
||||
) -> Result<DnsQueryReport, DnsError> {
|
||||
debug!(
|
||||
domain,
|
||||
record_type = %record_type,
|
||||
server = %server.addr,
|
||||
proxy = %proxy,
|
||||
"dns doh via proxy"
|
||||
);
|
||||
let tls_name = server
|
||||
.name
|
||||
.clone()
|
||||
@@ -530,6 +571,13 @@ async fn dot_query_via_proxy(
|
||||
timeout_ms: u64,
|
||||
proxy: String,
|
||||
) -> Result<DnsQueryReport, DnsError> {
|
||||
debug!(
|
||||
domain,
|
||||
record_type = %record_type,
|
||||
server = %server.addr,
|
||||
proxy = %proxy,
|
||||
"dns dot via proxy"
|
||||
);
|
||||
let tls_name = server
|
||||
.name
|
||||
.clone()
|
||||
|
||||
@@ -9,3 +9,4 @@ serde = { version = "1", features = ["derive"] }
|
||||
thiserror = "2"
|
||||
tokio = { version = "1", features = ["net", "time"] }
|
||||
url = "2"
|
||||
tracing = "0.1"
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::net::{IpAddr, SocketAddr};
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::net::lookup_host;
|
||||
use thiserror::Error;
|
||||
use tracing::debug;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@@ -67,6 +68,16 @@ pub struct HttpRequestOptions {
|
||||
}
|
||||
|
||||
pub async fn request(url: &str, opts: HttpRequestOptions) -> Result<HttpReport, HttpError> {
|
||||
debug!(
|
||||
url,
|
||||
method = ?opts.method,
|
||||
timeout_ms = opts.timeout_ms,
|
||||
follow_redirects = ?opts.follow_redirects,
|
||||
http1_only = opts.http1_only,
|
||||
http2_only = opts.http2_only,
|
||||
proxy = ?opts.proxy,
|
||||
"http request start"
|
||||
);
|
||||
let parsed = Url::parse(url).map_err(|err| HttpError::Url(err.to_string()))?;
|
||||
let host = parsed
|
||||
.host_str()
|
||||
|
||||
@@ -14,3 +14,4 @@ wtfnet-geoip = { path = "../wtfnet-geoip" }
|
||||
libc = "0.2"
|
||||
tokio-socks = "0.5"
|
||||
url = "2"
|
||||
tracing = "0.1"
|
||||
|
||||
@@ -21,6 +21,7 @@ use thiserror::Error;
|
||||
use tokio::net::{TcpStream, lookup_host};
|
||||
use tokio::time::timeout;
|
||||
use tokio_socks::tcp::Socks5Stream;
|
||||
use tracing::debug;
|
||||
use url::Url;
|
||||
use wtfnet_geoip::GeoIpRecord;
|
||||
|
||||
@@ -114,7 +115,15 @@ pub async fn ping(
|
||||
timeout_ms: u64,
|
||||
interval_ms: u64,
|
||||
) -> Result<PingReport, ProbeError> {
|
||||
debug!(
|
||||
target,
|
||||
count,
|
||||
timeout_ms,
|
||||
interval_ms,
|
||||
"probe ping start"
|
||||
);
|
||||
let addr = resolve_one(target).await?;
|
||||
debug!(ip = %addr, "probe ping resolved");
|
||||
let mut results = Vec::new();
|
||||
let mut received = 0u32;
|
||||
let mut min = None;
|
||||
@@ -193,6 +202,15 @@ pub async fn tcp_ping(
|
||||
proxy: Option<&str>,
|
||||
prefer_ipv4: bool,
|
||||
) -> Result<TcpPingReport, ProbeError> {
|
||||
debug!(
|
||||
target,
|
||||
port,
|
||||
count,
|
||||
timeout_ms,
|
||||
proxy = ?proxy,
|
||||
prefer_ipv4,
|
||||
"probe tcp ping start"
|
||||
);
|
||||
let (report_ip, target_host, proxy_addr) = if let Some(proxy) = proxy {
|
||||
let proxy = parse_socks5_proxy(proxy)?;
|
||||
if proxy.remote_dns {
|
||||
@@ -214,6 +232,12 @@ pub async fn tcp_ping(
|
||||
(Some(addr), addr.to_string(), String::new())
|
||||
};
|
||||
let socket_addr = report_ip.map(|addr| SocketAddr::new(addr, port));
|
||||
debug!(
|
||||
report_ip = ?report_ip,
|
||||
target_host = %target_host,
|
||||
proxy_addr = %proxy_addr,
|
||||
"probe tcp ping resolved"
|
||||
);
|
||||
let timeout_dur = Duration::from_millis(timeout_ms);
|
||||
let mut results = Vec::new();
|
||||
let mut received = 0u32;
|
||||
@@ -285,7 +309,15 @@ pub async fn tcp_trace(
|
||||
max_hops: u8,
|
||||
timeout_ms: u64,
|
||||
) -> Result<TraceReport, ProbeError> {
|
||||
debug!(
|
||||
target,
|
||||
port,
|
||||
max_hops,
|
||||
timeout_ms,
|
||||
"probe tcp trace start"
|
||||
);
|
||||
let addr = resolve_one(target).await?;
|
||||
debug!(ip = %addr, "probe tcp trace resolved");
|
||||
let socket_addr = SocketAddr::new(addr, port);
|
||||
let timeout_dur = Duration::from_millis(timeout_ms);
|
||||
let mut hops = Vec::new();
|
||||
@@ -341,7 +373,15 @@ pub async fn udp_trace(
|
||||
max_hops: u8,
|
||||
timeout_ms: u64,
|
||||
) -> Result<TraceReport, ProbeError> {
|
||||
debug!(
|
||||
target,
|
||||
port,
|
||||
max_hops,
|
||||
timeout_ms,
|
||||
"probe udp trace start"
|
||||
);
|
||||
let addr = resolve_one(target).await?;
|
||||
debug!(ip = %addr, "probe udp trace resolved");
|
||||
|
||||
let timeout_dur = Duration::from_millis(timeout_ms);
|
||||
let mut hops = Vec::new();
|
||||
|
||||
@@ -13,3 +13,4 @@ tokio-rustls = "0.24"
|
||||
x509-parser = "0.16"
|
||||
tokio-socks = "0.5"
|
||||
url = "2"
|
||||
tracing = "0.1"
|
||||
|
||||
@@ -8,6 +8,7 @@ use tokio::net::TcpStream;
|
||||
use tokio::time::timeout;
|
||||
use tokio_rustls::TlsConnector;
|
||||
use tokio_socks::tcp::Socks5Stream;
|
||||
use tracing::debug;
|
||||
use url::Url;
|
||||
use x509_parser::prelude::{FromDer, X509Certificate};
|
||||
|
||||
@@ -85,6 +86,15 @@ pub struct TlsOptions {
|
||||
}
|
||||
|
||||
pub async fn handshake(target: &str, options: TlsOptions) -> Result<TlsHandshakeReport, TlsError> {
|
||||
debug!(
|
||||
target,
|
||||
sni = ?options.sni,
|
||||
alpn = ?options.alpn,
|
||||
proxy = ?options.socks5,
|
||||
timeout_ms = options.timeout_ms,
|
||||
prefer_ipv4 = options.prefer_ipv4,
|
||||
"tls handshake start"
|
||||
);
|
||||
let (host, port, server_name) = parse_target(target, options.sni.as_deref())?;
|
||||
let connector = build_connector(options.insecure, &options.alpn)?;
|
||||
let stream = connect(
|
||||
@@ -115,6 +125,15 @@ pub async fn handshake(target: &str, options: TlsOptions) -> Result<TlsHandshake
|
||||
}
|
||||
|
||||
pub async fn verify(target: &str, options: TlsOptions) -> Result<TlsVerifyReport, TlsError> {
|
||||
debug!(
|
||||
target,
|
||||
sni = ?options.sni,
|
||||
alpn = ?options.alpn,
|
||||
proxy = ?options.socks5,
|
||||
timeout_ms = options.timeout_ms,
|
||||
prefer_ipv4 = options.prefer_ipv4,
|
||||
"tls verify start"
|
||||
);
|
||||
let (host, port, server_name) = parse_target(target, options.sni.as_deref())?;
|
||||
let connector = build_connector(false, &options.alpn)?;
|
||||
match connect(
|
||||
@@ -159,6 +178,15 @@ pub async fn verify(target: &str, options: TlsOptions) -> Result<TlsVerifyReport
|
||||
}
|
||||
|
||||
pub async fn certs(target: &str, options: TlsOptions) -> Result<TlsCertReport, TlsError> {
|
||||
debug!(
|
||||
target,
|
||||
sni = ?options.sni,
|
||||
alpn = ?options.alpn,
|
||||
proxy = ?options.socks5,
|
||||
timeout_ms = options.timeout_ms,
|
||||
prefer_ipv4 = options.prefer_ipv4,
|
||||
"tls certs start"
|
||||
);
|
||||
let (host, port, server_name) = parse_target(target, options.sni.as_deref())?;
|
||||
let connector = build_connector(options.insecure, &options.alpn)?;
|
||||
let stream = connect(
|
||||
@@ -180,6 +208,15 @@ pub async fn certs(target: &str, options: TlsOptions) -> Result<TlsCertReport, T
|
||||
}
|
||||
|
||||
pub async fn alpn(target: &str, options: TlsOptions) -> Result<TlsAlpnReport, TlsError> {
|
||||
debug!(
|
||||
target,
|
||||
sni = ?options.sni,
|
||||
alpn = ?options.alpn,
|
||||
proxy = ?options.socks5,
|
||||
timeout_ms = options.timeout_ms,
|
||||
prefer_ipv4 = options.prefer_ipv4,
|
||||
"tls alpn start"
|
||||
);
|
||||
let (host, port, server_name) = parse_target(target, options.sni.as_deref())?;
|
||||
let connector = build_connector(options.insecure, &options.alpn)?;
|
||||
let stream = connect(
|
||||
|
||||
Reference in New Issue
Block a user