feat: v0.2.0-rc, optimize code
This commit is contained in:
@@ -2,7 +2,10 @@
|
|||||||
"groups": [
|
"groups": [
|
||||||
{
|
{
|
||||||
"port": 443,
|
"port": 443,
|
||||||
"lookup_dns": true,
|
"lookup_dns": false,
|
||||||
|
"dns_domains": [
|
||||||
|
"*baidu*"
|
||||||
|
],
|
||||||
"tls": {
|
"tls": {
|
||||||
"issuer_cert": "cert.pem",
|
"issuer_cert": "cert.pem",
|
||||||
"issuer_key": "cert.key"
|
"issuer_key": "cert.key"
|
||||||
|
|||||||
59
src/app.rs
59
src/app.rs
@@ -19,13 +19,14 @@ use super::service::HostConfig;
|
|||||||
pub struct ProxyApp {
|
pub struct ProxyApp {
|
||||||
tls: bool,
|
tls: bool,
|
||||||
lookup_dns: bool,
|
lookup_dns: bool,
|
||||||
|
dns_domains: Option<Vec<String>>,
|
||||||
host_config_map: HashMap<String, HostConfig>,
|
host_config_map: HashMap<String, HostConfig>,
|
||||||
dns_resolver: TokioAsyncResolver,
|
dns_resolver: TokioAsyncResolver,
|
||||||
dns_resolver_cache: RwLock<HashMap<String, String>>,
|
dns_resolver_cache: RwLock<HashMap<String, String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProxyApp {
|
impl ProxyApp {
|
||||||
pub fn new(tls: bool, lookup_dns: bool, host_config_map: HashMap<String, HostConfig>) -> Self {
|
pub fn new(tls: bool, lookup_dns: bool, dns_domains: Option<Vec<String>>, host_config_map: HashMap<String, HostConfig>) -> Self {
|
||||||
let dns_resolver = TokioAsyncResolver::tokio(
|
let dns_resolver = TokioAsyncResolver::tokio(
|
||||||
ResolverConfig::default(),
|
ResolverConfig::default(),
|
||||||
ResolverOpts::default(),
|
ResolverOpts::default(),
|
||||||
@@ -33,12 +34,32 @@ impl ProxyApp {
|
|||||||
ProxyApp {
|
ProxyApp {
|
||||||
tls,
|
tls,
|
||||||
lookup_dns,
|
lookup_dns,
|
||||||
|
dns_domains,
|
||||||
host_config_map,
|
host_config_map,
|
||||||
dns_resolver,
|
dns_resolver,
|
||||||
dns_resolver_cache: Default::default(),
|
dns_resolver_cache: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lookup_dns(&self, hostname: &str) -> bool {
|
||||||
|
if self.lookup_dns {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if let Some(dns_names) = &self.dns_domains {
|
||||||
|
for domain_pattern in dns_names {
|
||||||
|
// Only support below patterns:
|
||||||
|
// - example.com
|
||||||
|
// - google.*
|
||||||
|
// - *.google.com
|
||||||
|
// - *google*
|
||||||
|
if domain_match(hostname, domain_pattern) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
// 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> {
|
||||||
{
|
{
|
||||||
@@ -119,7 +140,7 @@ impl ProxyHttp for ProxyApp {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.lookup_dns {
|
if self.lookup_dns(&hostname) {
|
||||||
if let Some(address) = self.lookup_ipv4(&hostname).await {
|
if let Some(address) = self.lookup_ipv4(&hostname).await {
|
||||||
let peer_addr = format!("{}:{}", address, if self.tls { 443 } else { 80 });
|
let peer_addr = format!("{}:{}", address, if self.tls { 443 } else { 80 });
|
||||||
log::info!("DNS peer: {} --> {}", hostname, peer_addr);
|
log::info!("DNS peer: {} --> {}", hostname, peer_addr);
|
||||||
@@ -188,4 +209,38 @@ impl ProxyHttp for ProxyApp {
|
|||||||
).unwrap_or_else(|| "<none>".into())
|
).unwrap_or_else(|| "<none>".into())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn domain_match(domain: &str, domain_pattern: &str) -> bool {
|
||||||
|
if domain == domain_pattern {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let domain_pattern_chars = domain_pattern.chars();
|
||||||
|
if domain_pattern.starts_with('*') && domain_pattern.ends_with('*') {
|
||||||
|
let domain_pattern_len = domain_pattern.chars().collect::<Vec<_>>().len();
|
||||||
|
let sub_domain = domain_pattern_chars.skip(1).take(domain_pattern_len - 2).collect::<String>();
|
||||||
|
return domain.contains(&sub_domain);
|
||||||
|
}
|
||||||
|
if domain_pattern.starts_with('*') {
|
||||||
|
let sub_domain = domain_pattern_chars.skip(1).collect::<String>();
|
||||||
|
return domain.ends_with(&sub_domain);
|
||||||
|
}
|
||||||
|
if domain_pattern.ends_with('*') {
|
||||||
|
let domain_pattern_len = domain_pattern.chars().collect::<Vec<_>>().len();
|
||||||
|
let sub_domain = domain_pattern_chars.take(domain_pattern_len - 1).collect::<String>();
|
||||||
|
return domain.starts_with(&sub_domain);
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_domain_match() {
|
||||||
|
assert!(domain_match("example.com", "example.com"));
|
||||||
|
assert!(!domain_match("www.example.com", "example.com"));
|
||||||
|
assert!(domain_match("www.example.com", "*example.com"));
|
||||||
|
assert!(domain_match("www.example.com", "*example.*"));
|
||||||
|
assert!(domain_match("example.com", "example.*"));
|
||||||
|
assert!(domain_match("example.com", "example*"));
|
||||||
|
assert!(domain_match("example.com", "*ample*"));
|
||||||
}
|
}
|
||||||
@@ -26,6 +26,7 @@ impl ProxyConfig {
|
|||||||
pub struct ProxyGroup {
|
pub struct ProxyGroup {
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub lookup_dns: Option<bool>,
|
pub lookup_dns: Option<bool>,
|
||||||
|
pub dns_domains: Option<Vec<String>>,
|
||||||
pub tls: Option<ProxyTls>,
|
pub tls: Option<ProxyTls>,
|
||||||
pub proxy_map: Option<HashMap<String, ProxyItem>>,
|
pub proxy_map: Option<HashMap<String, ProxyItem>>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,8 +56,10 @@ fn build_services(server: &Server, proxy_config: &ProxyConfig) -> Vec<Box<dyn Se
|
|||||||
let listen_address = format!("0.0.0.0:{}", group.port);
|
let listen_address = format!("0.0.0.0:{}", group.port);
|
||||||
let host_config_map = build_host_config_map(group);
|
let host_config_map = build_host_config_map(group);
|
||||||
let lookup_dns = group.lookup_dns.unwrap_or(false);
|
let lookup_dns = group.lookup_dns.unwrap_or(false);
|
||||||
|
let dns_domains = group.dns_domains.clone();
|
||||||
|
|
||||||
log::info!("Listen at: {}, tls: {}, lookup_dns: {}", listen_address, group.tls.is_some(), lookup_dns);
|
log::info!("Listen at: {}, tls: {}, lookup_dns: {}", listen_address, group.tls.is_some(), lookup_dns);
|
||||||
|
log::debug!("Dns domains: {:#?}", dns_domains);
|
||||||
|
|
||||||
match &group.tls {
|
match &group.tls {
|
||||||
None => {
|
None => {
|
||||||
@@ -65,6 +67,7 @@ fn build_services(server: &Server, proxy_config: &ProxyConfig) -> Vec<Box<dyn Se
|
|||||||
&server.configuration,
|
&server.configuration,
|
||||||
&listen_address,
|
&listen_address,
|
||||||
lookup_dns,
|
lookup_dns,
|
||||||
|
dns_domains,
|
||||||
host_config_map,
|
host_config_map,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@@ -73,6 +76,7 @@ fn build_services(server: &Server, proxy_config: &ProxyConfig) -> Vec<Box<dyn Se
|
|||||||
&server.configuration,
|
&server.configuration,
|
||||||
&listen_address,
|
&listen_address,
|
||||||
lookup_dns,
|
lookup_dns,
|
||||||
|
dns_domains,
|
||||||
proxy_tls,
|
proxy_tls,
|
||||||
host_config_map,
|
host_config_map,
|
||||||
)));
|
)));
|
||||||
|
|||||||
@@ -83,9 +83,10 @@ pub fn proxy_service_tcp(
|
|||||||
server_conf: &Arc<ServerConf>,
|
server_conf: &Arc<ServerConf>,
|
||||||
listen_addr: &str,
|
listen_addr: &str,
|
||||||
lookup_dns: bool,
|
lookup_dns: bool,
|
||||||
|
dns_domains: Option<Vec<String>>,
|
||||||
host_config_map: HashMap<String, HostConfig>,
|
host_config_map: HashMap<String, HostConfig>,
|
||||||
) -> impl pingora::services::Service {
|
) -> impl pingora::services::Service {
|
||||||
let proxy_app = ProxyApp::new(false, lookup_dns, host_config_map);
|
let proxy_app = ProxyApp::new(false, lookup_dns, dns_domains, host_config_map);
|
||||||
let mut service = http_proxy_service(server_conf, proxy_app);
|
let mut service = http_proxy_service(server_conf, proxy_app);
|
||||||
|
|
||||||
service.add_tcp(listen_addr);
|
service.add_tcp(listen_addr);
|
||||||
@@ -97,10 +98,11 @@ pub fn proxy_service_tls(
|
|||||||
server_conf: &Arc<ServerConf>,
|
server_conf: &Arc<ServerConf>,
|
||||||
listen_addr: &str,
|
listen_addr: &str,
|
||||||
lookup_dns: bool,
|
lookup_dns: bool,
|
||||||
|
dns_domains: Option<Vec<String>>,
|
||||||
proxy_tls: &ProxyTls,
|
proxy_tls: &ProxyTls,
|
||||||
host_config_map: HashMap<String, HostConfig>,
|
host_config_map: HashMap<String, HostConfig>,
|
||||||
) -> impl pingora::services::Service {
|
) -> impl pingora::services::Service {
|
||||||
let proxy_app = ProxyApp::new(true, lookup_dns, host_config_map);
|
let proxy_app = ProxyApp::new(true, lookup_dns, dns_domains, host_config_map);
|
||||||
let mut service = http_proxy_service(server_conf, proxy_app);
|
let mut service = http_proxy_service(server_conf, proxy_app);
|
||||||
|
|
||||||
let callback = Box::new(Callback::new(proxy_tls).unwrap_or_else(|e| {
|
let callback = Box::new(Callback::new(proxy_tls).unwrap_or_else(|e| {
|
||||||
|
|||||||
Reference in New Issue
Block a user