Skip to content

Commit

Permalink
support specifying dns for resolving the server address
Browse files Browse the repository at this point in the history
  • Loading branch information
neevek committed Oct 14, 2024
1 parent df43ac0 commit 0a20c46
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rstun"
version = "0.6.0"
version = "0.6.1"
edition = "2021"

[lib]
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ Options:
Wait time in milliseconds before trying [default: 5000]
-i, --max-idle-timeout-ms <MAX_IDLE_TIMEOUT_MS>
Max idle timeout in milliseconds for the connection [default: 30000]
--dot <DOT>
Comma separated DoT servers (domains) used to resolve the server address (domain)
e.g. "dns.google,one.one.one.one"
Note that DoT servers will be resolved using any available system DNS [default: ]
--dns <DNS>
Comma separated DNS' (IPs) used to resolve the server address (domain)
Note that the --dot option if not empty takes precedence over this option
e.g. "1.1.1.1,8.8.8.8" [default: ]
-l, --loglevel <LOGLEVEL>
Log level [default: I] [possible values: T, D, I, W, E]
-h, --help
Expand Down
14 changes: 14 additions & 0 deletions src/bin/rstunc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ fn main() {
&args.cipher,
&args.tcp_mapping,
&args.udp_mapping,
&args.dot,
&args.dns,
args.workers,
args.wait_before_retry_ms,
args.max_idle_timeout_ms,
Expand Down Expand Up @@ -91,6 +93,18 @@ struct RstuncArgs {
#[arg(short = 'i', long, default_value_t = 30000)]
max_idle_timeout_ms: u64,

/// Comma separated DoT servers (domains) used to resolve the server address (domain)
/// e.g. "dns.google,one.one.one.one"
/// Note that DoT servers will be resolved using any available system DNS
#[arg(long, verbatim_doc_comment, default_value = "")]
dot: String,

/// Comma separated DNS' (IPs) used to resolve the server address (domain)
/// Note that the --dot option if not empty takes precedence over this option
/// e.g. "1.1.1.1,8.8.8.8"
#[arg(long, verbatim_doc_comment, default_value = "")]
dns: String,

/// Log level
#[arg(short = 'l', long, default_value_t = String::from("I"),
value_parser = PossibleValuesParser::new(["T", "D", "I", "W", "E"]).map(|v| match v.as_str() {
Expand Down
28 changes: 8 additions & 20 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ impl Client {
let mut quinn_client_cfg = quinn::ClientConfig::new(quic_client_cfg);
quinn_client_cfg.transport_config(Arc::new(transport_cfg));

let remote_addr = Self::parse_server_addr(&self.config.server_addr).await?;
let remote_addr = self.parse_server_addr().await?;
let local_addr: SocketAddr = socket_addr_with_unspecified_ip_port(remote_addr.is_ipv6());

let mut endpoint = quinn::Endpoint::client(local_addr)?;
Expand Down Expand Up @@ -571,7 +571,8 @@ impl Client {
addr.parse::<SocketAddr>().is_ok()
}

async fn parse_server_addr(addr: &str) -> Result<SocketAddr> {
async fn parse_server_addr(&self) -> Result<SocketAddr> {
let addr = self.config.server_addr.as_str();
let sock_addr: Result<SocketAddr> = addr.parse().context("error will be ignored");

if sock_addr.is_ok() {
Expand All @@ -588,26 +589,13 @@ impl Client {
domain = &addr[..pos];
}

if let Ok(ip) = Self::lookup_server_ip(domain, "dns.alidns.com", vec![]).await {
return Ok(SocketAddr::new(ip, port));
}

if let Ok(ip) = Self::lookup_server_ip(domain, "dot.pub", vec![]).await {
return Ok(SocketAddr::new(ip, port));
for dot in &self.config.dot_servers {
if let Ok(ip) = Self::lookup_server_ip(domain, dot, vec![]).await {
return Ok(SocketAddr::new(ip, port));
}
}

if let Ok(ip) = Self::lookup_server_ip(
domain,
"",
vec![
"1.12.12.12".to_string(),
"120.53.53.53".to_string(),
"223.5.5.5".to_string(),
"223.6.6.6".to_string(),
],
)
.await
{
if let Ok(ip) = Self::lookup_server_ip(domain, "", self.config.dns_servers.clone()).await {
return Ok(SocketAddr::new(ip, port));
}

Expand Down
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ pub struct ClientConfig {
pub max_idle_timeout_ms: u64,
pub tcp_upstream: Option<Upstream>,
pub udp_upstream: Option<Upstream>,
pub dot_servers: Vec<String>,
pub dns_servers: Vec<String>,
pub threads: usize,
pub mode: &'static str,
}
Expand Down Expand Up @@ -197,6 +199,8 @@ impl ClientConfig {
cipher: &str,
tcp_addr_mapping: &str,
udp_addr_mapping: &str,
dot: &str,
dns: &str,
workers: usize,
wait_before_retry_ms: u64,
max_idle_timeout_ms: u64,
Expand All @@ -222,6 +226,8 @@ impl ClientConfig {
config.max_idle_timeout_ms = max_idle_timeout_ms;
config.tcp_upstream = parse_as_upstream(mode, &tcp_sock_mapping)?;
config.udp_upstream = parse_as_upstream(mode, &udp_sock_mapping)?;
config.dot_servers = dot.split(',').map(|s| s.to_string()).collect();
config.dns_servers = dns.split(',').map(|s| s.to_string()).collect();
config.mode = if mode == TUNNEL_MODE_IN {
config.local_tcp_server_addr = *tcp_sock_mapping.get(1).unwrap_or(&None);
config.local_udp_server_addr = *udp_sock_mapping.get(1).unwrap_or(&None);
Expand Down

0 comments on commit 0a20c46

Please sign in to comment.