Skip to content

Commit

Permalink
Revert deprecation of UDS local DNS
Browse files Browse the repository at this point in the history
- ref shadowsocks/shadowsocks-android#2650
- Server's builtin DNS will not use local-dns-addr
  • Loading branch information
zonyitoo committed Jan 4, 2021
1 parent 7bf6d32 commit d41404c
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 77 deletions.
7 changes: 7 additions & 0 deletions bin/common/validator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use std::net::SocketAddr;

#[cfg(feature = "local-dns")]
use shadowsocks_service::local::dns::NameServerAddr;
use shadowsocks_service::shadowsocks::{relay::socks5::Address, ManagerAddr, ServerAddr, ServerConfig};

macro_rules! validate_type {
Expand All @@ -29,6 +31,11 @@ validate_type!(
ManagerAddr,
"should be either ip:port, domain:port or /path/to/unix.sock"
);
validate_type!(
validate_name_server_addr,
NameServerAddr,
"should be either ip:port or a path to unix domain socket"
);
validate_type!(validate_u64, u64, "should be unsigned integer");
validate_type!(validate_u32, u32, "should be unsigned integer");

Expand Down
6 changes: 3 additions & 3 deletions bin/sslocal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ fn main() {
#[cfg(feature = "local-dns")]
{
app = clap_app!(@app (app)
(@arg LOCAL_DNS_ADDR: --("local-dns-addr") +takes_value required_if("PROTOCOL", "dns") {validator::validate_socket_addr} "Specify the address of local DNS server, send queries directly")
(@arg LOCAL_DNS_ADDR: --("local-dns-addr") +takes_value required_if("PROTOCOL", "dns") {validator::validate_name_server_addr} "Specify the address of local DNS server, send queries directly")
(@arg REMOTE_DNS_ADDR: --("remote-dns-addr") +takes_value required_if("PROTOCOL", "dns") {validator::validate_address} "Specify the address of remote DNS server, send queries through shadowsocks' tunnel")
(@arg DNS_LOCAL_ADDR: --("dns-addr") +takes_value requires_all(&["REMOTE_DNS_ADDR"]) {validator::validate_server_addr} "DNS address, listen to this address if specified")
);
Expand Down Expand Up @@ -247,10 +247,10 @@ fn main() {

#[cfg(feature = "local-dns")]
{
use std::net::SocketAddr;
use shadowsocks_service::local::dns::NameServerAddr;

if let Some(local_dns_addr) = matches.value_of("LOCAL_DNS_ADDR") {
let addr = local_dns_addr.parse::<SocketAddr>().expect("local dns address");
let addr = local_dns_addr.parse::<NameServerAddr>().expect("local dns address");
config.local_dns_addr = Some(addr);
}

Expand Down
4 changes: 3 additions & 1 deletion crates/shadowsocks-service/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ use shadowsocks::{
use trust_dns_resolver::config::{NameServerConfig, Protocol, ResolverConfig};

use crate::acl::AccessControl;
#[cfg(feature = "local-dns")]
use crate::local::dns::NameServerAddr;

#[cfg(feature = "trust-dns")]
#[derive(Serialize, Deserialize, Debug)]
Expand Down Expand Up @@ -574,7 +576,7 @@ pub struct Config {
///
/// Sending DNS query directly to this address
#[cfg(feature = "local-dns")]
pub local_dns_addr: Option<SocketAddr>,
pub local_dns_addr: Option<NameServerAddr>,
/// Remote DNS's address
///
/// Sending DNS query through proxy to this address
Expand Down
1 change: 0 additions & 1 deletion crates/shadowsocks-service/src/local/dns/client_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ impl DnsClientCache {
}

#[cfg(unix)]
#[allow(dead_code)]
pub async fn lookup_unix_stream<P: AsRef<Path>>(&self, ns: &P, msg: Message) -> Result<Message, ProtoError> {
let mut last_err = None;

Expand Down
52 changes: 52 additions & 0 deletions crates/shadowsocks-service/src/local/dns/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//! DNS configurations
#[cfg(unix)]
use std::{convert::Infallible, path::PathBuf};
use std::{
fmt::{self, Display},
net::SocketAddr,
str::FromStr,
};

/// DNS name server address
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum NameServerAddr {
/// IP address
SocketAddr(SocketAddr),
/// Unix Domain Socket address
///
/// Specifically used by Android, which served as a stream protocol based DNS server
#[cfg(unix)]
UnixSocketAddr(PathBuf),
}

/// Parse `NameServerAddr` error
#[cfg(unix)]
pub type NameServerAddrError = Infallible;
/// Parse `NameServerAddr` error
#[cfg(not(unix))]
pub type NameServerAddrError = <SocketAddr as FromStr>::Err;

impl FromStr for NameServerAddr {
type Err = NameServerAddrError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.parse::<SocketAddr>() {
Ok(addr) => Ok(NameServerAddr::SocketAddr(addr)),
#[cfg(unix)]
Err(..) => Ok(NameServerAddr::UnixSocketAddr(PathBuf::from(s))),
#[cfg(not(unix))]
Err(err) => Err(err),
}
}
}

impl Display for NameServerAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
NameServerAddr::SocketAddr(ref sa) => Display::fmt(sa, f),
#[cfg(unix)]
NameServerAddr::UnixSocketAddr(ref p) => write!(f, "{}", p.display()),
}
}
}
3 changes: 2 additions & 1 deletion crates/shadowsocks-service/src/local/dns/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Customized DNS resolver
pub use self::server::Dns;
pub use self::{config::NameServerAddr, server::Dns};

mod client_cache;
pub mod config;
pub mod server;
mod upstream;
81 changes: 48 additions & 33 deletions crates/shadowsocks-service/src/local/dns/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,29 +36,29 @@ use crate::{
local::{context::ServiceContext, loadbalancing::PingBalancer},
};

use super::client_cache::DnsClientCache;
use super::{client_cache::DnsClientCache, config::NameServerAddr};

/// DNS Relay server
pub struct Dns {
context: Arc<ServiceContext>,
mode: Mode,
local_addr: SocketAddr,
local_addr: Arc<NameServerAddr>,
remote_addr: Arc<Address>,
}

impl Dns {
/// Create a new DNS Relay server
pub fn new(local_addr: SocketAddr, remote_addr: Address) -> Dns {
pub fn new(local_addr: NameServerAddr, remote_addr: Address) -> Dns {
let context = ServiceContext::new();
Dns::with_context(Arc::new(context), local_addr, remote_addr)
}

/// Create with an existed `context`
pub fn with_context(context: Arc<ServiceContext>, local_addr: SocketAddr, remote_addr: Address) -> Dns {
pub fn with_context(context: Arc<ServiceContext>, local_addr: NameServerAddr, remote_addr: Address) -> Dns {
Dns {
context,
mode: Mode::UdpOnly,
local_addr: local_addr,
local_addr: Arc::new(local_addr),
remote_addr: Arc::new(remote_addr),
}
}
Expand Down Expand Up @@ -117,7 +117,7 @@ impl Dns {
client.clone(),
stream,
peer_addr,
self.local_addr,
self.local_addr.clone(),
self.remote_addr.clone(),
));
}
Expand All @@ -127,7 +127,7 @@ impl Dns {
client: Arc<DnsClient>,
mut stream: TcpStream,
peer_addr: SocketAddr,
local_addr: SocketAddr,
local_addr: Arc<NameServerAddr>,
remote_addr: Arc<Address>,
) -> io::Result<()> {
let mut length_buf = [0u8; 2];
Expand Down Expand Up @@ -168,7 +168,7 @@ impl Dns {
}
};

let respond_message = match client.resolve(message, local_addr, &remote_addr).await {
let respond_message = match client.resolve(message, &local_addr, &remote_addr).await {
Ok(m) => m,
Err(err) => {
error!("dns tcp {} lookup error: {}", peer_addr, err);
Expand Down Expand Up @@ -237,7 +237,7 @@ impl Dns {
listener.clone(),
peer_addr,
message,
self.local_addr,
self.local_addr.clone(),
self.remote_addr.clone(),
));
}
Expand All @@ -248,10 +248,10 @@ impl Dns {
listener: Arc<UdpSocket>,
peer_addr: SocketAddr,
message: Message,
local_addr: SocketAddr,
local_addr: Arc<NameServerAddr>,
remote_addr: Arc<Address>,
) -> io::Result<()> {
let respond_message = match client.resolve(message, local_addr, &remote_addr).await {
let respond_message = match client.resolve(message, &local_addr, &remote_addr).await {
Ok(m) => m,
Err(err) => {
error!("dns udp {} lookup failed, error: {}", peer_addr, err);
Expand Down Expand Up @@ -442,7 +442,12 @@ impl DnsClient {
}
}

async fn resolve(&self, request: Message, local_addr: SocketAddr, remote_addr: &Address) -> io::Result<Message> {
async fn resolve(
&self,
request: Message,
local_addr: &NameServerAddr,
remote_addr: &Address,
) -> io::Result<Message> {
let mut message = Message::new();
message.set_id(request.id());
message.set_recursion_desired(true);
Expand Down Expand Up @@ -476,7 +481,7 @@ impl DnsClient {
async fn acl_lookup(
&self,
query: &Query,
local_addr: SocketAddr,
local_addr: &NameServerAddr,
remote_addr: &Address,
) -> (io::Result<Message>, bool) {
// Start querying name servers
Expand Down Expand Up @@ -657,7 +662,7 @@ impl DnsClient {
}
}

async fn lookup_local(&self, query: &Query, local_addr: SocketAddr) -> io::Result<Message> {
async fn lookup_local(&self, query: &Query, local_addr: &NameServerAddr) -> io::Result<Message> {
let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty");

for _ in 0..self.attempts {
Expand All @@ -672,34 +677,44 @@ impl DnsClient {
Err(last_err)
}

async fn lookup_local_inner(&self, query: &Query, local_addr: SocketAddr) -> io::Result<Message> {
async fn lookup_local_inner(&self, query: &Query, local_addr: &NameServerAddr) -> io::Result<Message> {
let mut message = Message::new();
message.set_id(thread_rng().gen());
message.set_recursion_desired(true);
message.add_query(query.clone());

// Query UDP then TCP
match *local_addr {
NameServerAddr::SocketAddr(ns) => {
// Query UDP then TCP

let udp_query =
self.client_cache
.lookup_udp_local(local_addr, message.clone(), self.context.connect_opts_ref());
let tcp_query = async move {
// Send TCP query after 500ms, because UDP will always return faster than TCP, there is no need to send queries simutaneously
time::sleep(Duration::from_millis(500)).await;
let udp_query =
self.client_cache
.lookup_udp_local(ns, message.clone(), self.context.connect_opts_ref());
let tcp_query = async move {
// Send TCP query after 500ms, because UDP will always return faster than TCP, there is no need to send queries simutaneously
time::sleep(Duration::from_millis(500)).await;

self.client_cache
.lookup_tcp_local(local_addr, message, self.context.connect_opts_ref())
.await
};
self.client_cache
.lookup_tcp_local(ns, message, self.context.connect_opts_ref())
.await
};

tokio::pin!(udp_query);
tokio::pin!(tcp_query);
tokio::pin!(udp_query);
tokio::pin!(tcp_query);

match future::select(udp_query, tcp_query).await {
Either::Left((Ok(m), ..)) => Ok(m),
Either::Left((Err(..), next)) => next.await.map_err(From::from),
Either::Right((Ok(m), ..)) => Ok(m),
Either::Right((Err(..), next)) => next.await.map_err(From::from),
match future::select(udp_query, tcp_query).await {
Either::Left((Ok(m), ..)) => Ok(m),
Either::Left((Err(..), next)) => next.await.map_err(From::from),
Either::Right((Ok(m), ..)) => Ok(m),
Either::Right((Err(..), next)) => next.await.map_err(From::from),
}
}
#[cfg(unix)]
NameServerAddr::UnixSocketAddr(ref path) => self
.client_cache
.lookup_unix_stream(path, message)
.await
.map_err(From::from),
}
}
}
76 changes: 38 additions & 38 deletions crates/shadowsocks-service/src/local/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,44 +82,44 @@ pub async fn run(mut config: Config) -> io::Result<()> {
accept_opts.tcp.recv_buffer_size = config.inbound_recv_buffer_size;
accept_opts.tcp.nodelay = config.no_delay;

#[cfg(all(feature = "local-dns", feature = "trust-dns"))]
if let Some(socket_addr) = config.local_dns_addr {
use trust_dns_resolver::config::{NameServerConfig, Protocol, ResolverConfig};

trace!("initializing direct DNS resolver for {}", socket_addr);

let mut resolver_config = ResolverConfig::new();

resolver_config.add_name_server(NameServerConfig {
socket_addr,
protocol: Protocol::Udp,
tls_dns_name: None,
trust_nx_responses: false,
#[cfg(feature = "dns-over-tls")]
tls_config: None,
});
resolver_config.add_name_server(NameServerConfig {
socket_addr,
protocol: Protocol::Tcp,
tls_dns_name: None,
trust_nx_responses: false,
#[cfg(feature = "dns-over-tls")]
tls_config: None,
});

match DnsResolver::trust_dns_resolver(Some(resolver_config), config.ipv6_first).await {
Ok(r) => {
context.set_dns_resolver(Arc::new(r));
}
Err(err) => {
error!(
"initialize DNS resolver failed, nameserver: {}, error: {}",
socket_addr, err
);
return Err(err);
}
}
}
// #[cfg(all(feature = "local-dns", feature = "trust-dns"))]
// if let Some(socket_addr) = config.local_dns_addr {
// use trust_dns_resolver::config::{NameServerConfig, Protocol, ResolverConfig};
//
// trace!("initializing direct DNS resolver for {}", socket_addr);
//
// let mut resolver_config = ResolverConfig::new();
//
// resolver_config.add_name_server(NameServerConfig {
// socket_addr,
// protocol: Protocol::Udp,
// tls_dns_name: None,
// trust_nx_responses: false,
// #[cfg(feature = "dns-over-tls")]
// tls_config: None,
// });
// resolver_config.add_name_server(NameServerConfig {
// socket_addr,
// protocol: Protocol::Tcp,
// tls_dns_name: None,
// trust_nx_responses: false,
// #[cfg(feature = "dns-over-tls")]
// tls_config: None,
// });
//
// match DnsResolver::trust_dns_resolver(Some(resolver_config), config.ipv6_first).await {
// Ok(r) => {
// context.set_dns_resolver(Arc::new(r));
// }
// Err(err) => {
// error!(
// "initialize DNS resolver failed, nameserver: {}, error: {}",
// socket_addr, err
// );
// return Err(err);
// }
// }
// }

#[cfg(feature = "trust-dns")]
if context.dns_resolver().is_system_resolver() {
Expand Down

0 comments on commit d41404c

Please sign in to comment.