feat: v0.2.0-rc

This commit is contained in:
2024-03-30 16:32:59 +08:00
parent 9eb06c5135
commit 251f0e0483
4 changed files with 55 additions and 14 deletions

View File

@@ -1,7 +1,30 @@
# proxy-inspector # proxy-inspector
TODOs `proxy_config.json` sample config:
* Dynamic issue certificate ```json
{
"groups": [
{
"port": 443,
"lookup_dns": true,
"tls": {
"intermediate_cert": "intermediate_cert.pem",
"intermediate_key": "intermediate_pri_key.pem"
},
"proxy_map": {
"hatter.ink": {
"address": "101.132.122.240:443",
"tls": true
}
}
}
]
}
```
Important
* intermediate certificate only tested ECDSA(P384) with SHA384
* P384 with SHA256 is NOT supported
* P256 with SHA256 should be supported, but not tested

View File

@@ -1,7 +1,7 @@
{ {
"groups": [ "groups": [
{ {
"port": 4430, "port": 443,
"lookup_dns": true, "lookup_dns": true,
"tls": { "tls": {
"intermediate_cert": "__ignore_intermediate_cert.pem", "intermediate_cert": "__ignore_intermediate_cert.pem",

View File

@@ -1,3 +1,5 @@
use std::collections::HashMap;
use async_trait::async_trait; use async_trait::async_trait;
use base64::Engine; use base64::Engine;
use base64::engine::general_purpose::STANDARD; use base64::engine::general_purpose::STANDARD;
@@ -6,6 +8,7 @@ use http::{HeaderMap, HeaderName, HeaderValue};
use pingora::{Error, ErrorType}; use pingora::{Error, ErrorType};
use pingora::http::ResponseHeader; use pingora::http::ResponseHeader;
use pingora::prelude::{HttpPeer, ProxyHttp, Result, Session}; use pingora::prelude::{HttpPeer, ProxyHttp, Result, Session};
use tokio::sync::RwLock;
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts}; use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
use trust_dns_resolver::proto::rr::RData; use trust_dns_resolver::proto::rr::RData;
use trust_dns_resolver::TokioAsyncResolver; use trust_dns_resolver::TokioAsyncResolver;
@@ -17,6 +20,7 @@ pub struct ProxyApp {
lookup_dns: bool, lookup_dns: bool,
host_configs: Vec<HostConfig>, host_configs: Vec<HostConfig>,
tokio_async_resolver: TokioAsyncResolver, tokio_async_resolver: TokioAsyncResolver,
dns_resolver_cache_map: RwLock<HashMap<String, String>>,
} }
impl ProxyApp { impl ProxyApp {
@@ -30,29 +34,43 @@ impl ProxyApp {
lookup_dns, lookup_dns,
host_configs, host_configs,
tokio_async_resolver, tokio_async_resolver,
dns_resolver_cache_map: Default::default(),
} }
} }
// just only support IPv4 // just only support IPv4
async fn lookup_ipv4(&self, hostname: &str) -> Option<String> { async fn lookup_ipv4(&self, hostname: &str) -> Option<String> {
{
if let Some(ipv4_address) = self.dns_resolver_cache_map.read().await.get(hostname) {
log::info!("DNS cached {} --> {}", hostname, ipv4_address);
return Some(ipv4_address.to_string());
}
}
let ips = self.tokio_async_resolver.ipv4_lookup(hostname).await; let ips = self.tokio_async_resolver.ipv4_lookup(hostname).await;
log::debug!("lookup {} --> {:#?}", hostname, ips); log::debug!("DNS lookup {} --> {:#?}", hostname, ips);
match ips { match ips {
Ok(ips) => { Ok(ips) => {
let records = ips.as_lookup().records(); let records = ips.as_lookup().records();
if records.len() > 0 { for record in records {
let record = &records[0];
if let Some(rdata) = record.data() { if let Some(rdata) = record.data() {
match rdata { match rdata {
RData::A(a) => { RData::A(a) => {
return Some(a.0.to_string()); let ipv4_address = a.0.to_string();
{
self.dns_resolver_cache_map.write().await
.insert(hostname.to_string(), ipv4_address.clone());
}
log::info!("DNS found {} --> {}", hostname, ipv4_address);
return Some(ipv4_address);
} }
_ => {} _ => {}
} }
} }
} }
} }
Err(_) => {} Err(e) => {
log::error!("DNS lookup: {} failed: {}", hostname, e);
}
} }
None None
} }
@@ -103,7 +121,7 @@ impl ProxyHttp for ProxyApp {
host_config.proxy_tls, host_config.proxy_tls,
host_config.proxy_hostname.clone(), host_config.proxy_hostname.clone(),
); );
log::info!("Find peer: {} --> {:?}", hostname, host_config.proxy_addr); log::info!("Find peer: {} --> {}", hostname, host_config.proxy_addr);
return Ok(Box::new(peer)); return Ok(Box::new(peer));
} }
@@ -115,7 +133,7 @@ impl ProxyHttp for ProxyApp {
self.tls, self.tls,
hostname.to_string(), hostname.to_string(),
); );
log::info!("Find peer: {} --> {:?}", hostname, peer_addr); log::info!("Generate peer: {} --> {}", hostname, peer_addr);
return Ok(Box::new(peer)); return Ok(Box::new(peer));
} }
} }

View File

@@ -48,15 +48,15 @@ fn build_services(server: &Server, proxy_config: &ProxyConfig) -> Vec<Box<dyn Se
for group in &proxy_config.groups { for group in &proxy_config.groups {
let listen_address = format!("0.0.0.0:{}", group.port); let listen_address = format!("0.0.0.0:{}", group.port);
let host_configs = build_host_configs(group); let host_configs = build_host_configs(group);
let lookup_tls = group.lookup_dns.unwrap_or(false); let lookup_dns = group.lookup_dns.unwrap_or(false);
log::info!("Listen at: {}, tls: {}, lookup_tls: {}", listen_address, group.tls.is_some(), lookup_tls); log::info!("Listen at: {}, tls: {}, lookup_dns: {}", listen_address, group.tls.is_some(), lookup_dns);
match &group.tls { match &group.tls {
None => { None => {
services.push(Box::new(service::proxy_service_tcp( services.push(Box::new(service::proxy_service_tcp(
&server.configuration, &server.configuration,
&listen_address, &listen_address,
lookup_tls, lookup_dns,
host_configs, host_configs,
))); )));
} }
@@ -64,7 +64,7 @@ fn build_services(server: &Server, proxy_config: &ProxyConfig) -> Vec<Box<dyn Se
services.push(Box::new(service::proxy_service_tls( services.push(Box::new(service::proxy_service_tls(
&server.configuration, &server.configuration,
&listen_address, &listen_address,
lookup_tls, lookup_dns,
&proxy_tls, &proxy_tls,
host_configs, host_configs,
))); )));