feat: v0.2.0-rc
This commit is contained in:
27
README.md
27
README.md
@@ -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
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
32
src/app.rs
32
src/app.rs
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
)));
|
)));
|
||||||
|
|||||||
Reference in New Issue
Block a user