Skip to content

Commit 378141b

Browse files
author
xerik
committed
write dns client
1 parent 1dc4715 commit 378141b

File tree

15 files changed

+123
-226
lines changed

15 files changed

+123
-226
lines changed

Cargo.lock

Lines changed: 15 additions & 145 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ tokio-net = "0.2.0-alpha.6"
2727
radix_trie = "0.1.*"
2828
structopt = "^0"
2929
treebitmap = "0.3.1"
30-
trust-dns = "0.14.0"
31-
trust-dns-resolver = "*"
32-
futures01 = { package = "futures", version = "0.1" }
30+
trust-dns = { version = "^0.17", default-features = false }
3331
futures-preview = { version = "0.3.0-alpha.16", features = ["compat"] }
3432
tokio = "0.2.0-alpha.6"

asocks5/src/client/udp.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,7 @@ pub struct Socks5Datagram {
2626
impl Socks5Datagram {
2727
/// Creates a UDP socket bound to the specified address which will have its
2828
/// traffic routed through the specified proxy.
29-
pub async fn bind_with_timeout(
30-
proxy: SocketAddr,
31-
local: SocketAddr,
32-
time: Option<Duration>,
33-
) -> Result<Socks5Datagram, SocksError> {
29+
pub async fn bind(proxy: SocketAddr, local: SocketAddr) -> Result<Socks5Datagram, SocksError> {
3430
// we don't know what our IP is from the perspective of the proxy, so
3531
// don't try to pass `addr` in here.
3632
let dst = Address::SocketAddress(SocketAddr::V4(SocketAddrV4::new(
@@ -51,10 +47,6 @@ impl Socks5Datagram {
5147
}
5248
};
5349
let socket = net::UdpSocket::bind(&local)?;
54-
if time.is_some() {
55-
socket.set_read_timeout(time)?;
56-
}
57-
5850
let socket = UdpSocket::from_std(socket, &Handle::default())?;
5951

6052
Ok(Socks5Datagram {

src/conf/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mod decision_tree;
2-
mod main;
2+
pub(crate) mod main;
33
mod prefix_match;
44
mod util;
55

src/lib.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ extern crate byteorder;
22
extern crate bytes;
33
#[macro_use]
44
extern crate failure;
5-
extern crate futures01;
65
extern crate httparse;
76
#[macro_use]
87
extern crate log;
@@ -15,8 +14,6 @@ extern crate env_logger;
1514
extern crate tokio;
1615
extern crate tokio_io;
1716
extern crate treebitmap;
18-
extern crate trust_dns;
19-
extern crate trust_dns_resolver;
2017

2118
use structopt::StructOpt;
2219

@@ -31,7 +28,6 @@ use crate::relay::run_with_conf;
3128

3229
use futures::task::Context;
3330

34-
3531
use futures::Future;
3632
use std::pin::Pin;
3733
use std::task::Poll;
@@ -61,11 +57,7 @@ pub fn run() -> Result<(), i32> {
6157
for r in conf.relays {
6258
info!("Starting {}", r);
6359

64-
if let Err(e) = run_with_conf(
65-
r,
66-
conf.domain_matcher.clone(),
67-
conf.ip_matcher.clone(),
68-
) {
60+
if let Err(e) = run_with_conf(r, conf.domain_matcher.clone(), conf.ip_matcher.clone()) {
6961
error!("Relay error: {:?}", e);
7062
}
7163
}

src/relay/forwarding/tcp/copy/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::io;
22
use std::time;
33

4-
54
use futures::task::Context;
65
use futures::{Future, Poll as Poll1};
76
use futures_timer::Delay;

src/relay/forwarding/tcp/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ async fn carry_out(
9191
.map_err(|e| format_err!("Error sending {:?} header bytes to {:?}: {}", &pr, a, e))?;
9292
let (ur, uw) = split(s);
9393
let (cr, cw) = split(client_stream);
94-
run_copy(ur, cw, a, pr.clone(), r.clone(), true, );
94+
run_copy(ur, cw, a, pr.clone(), r.clone(), true);
9595
run_copy(cr, uw, a, pr, r, false);
9696
Ok(())
9797
}

src/relay/inspect/codec.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ use bytes::BytesMut;
44
use failure::Error;
55
use tokio::net::TcpStream;
66

7-
8-
97
use super::InspectedTcp;
108
use crate::relay::inspect::parse::guess_bytes;
119
use tokio::prelude::*;

src/relay/listen/socks.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use failure::Error;
2-
use futures::compat::Future01CompatExt;
2+
33
use std::net::SocketAddr;
44
use std::sync::Arc;
55
use tokio;
6-
use trust_dns_resolver::AsyncResolver;
76

87
use crate::relay::forwarding::handle_incoming_tcp;
98
use crate::relay::TcpRouter;
@@ -14,11 +13,9 @@ use asocks5::socks::TcpRequestHeader;
1413
use asocks5::Command;
1514
use tokio::net::TcpStream;
1615

17-
1816
use futures::future::ready;
1917

20-
use futures::task::SpawnExt;
21-
18+
use crate::resolver::AsyncResolver;
2219
use tokio::prelude::*;
2320

2421
pub async fn listen_socks(
@@ -68,13 +65,12 @@ async fn read_address(
6865
match head.address {
6966
Address::SocketAddress(a) => Ok(a),
7067
Address::DomainNameAddress(domain, port) => {
71-
let lookup = resolver
72-
.lookup_ip(&*domain)
73-
.compat()
68+
let ips = resolver
69+
.resolve(&*domain)
7470
.await
7571
.map_err(|e| format_err!("Error resolving {}: {}", domain, e))?;
76-
let ip = lookup
77-
.iter()
72+
let ip = ips
73+
.into_iter()
7874
.next()
7975
.ok_or_else(|| format_err!("No address found for domain {}", domain))?;
8076
Ok(SocketAddr::new(ip, port))

src/relay/mod.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,17 @@ pub use self::route::TcpRouter;
1111
use crate::conf::Relay;
1212
use crate::conf::RelayProto;
1313
use crate::conf::{DomainMatcher, IpMatcher};
14-
use crate::resolver::create_resolver;
15-
16-
14+
use crate::resolver::AsyncResolver;
1715

1816
/// Start a relay
19-
pub fn run_with_conf(
20-
conf: Relay,
21-
d: Arc<DomainMatcher>,
22-
i: Arc<IpMatcher>,
23-
) -> Result<(), Error> {
17+
pub fn run_with_conf(conf: Relay, d: Arc<DomainMatcher>, i: Arc<IpMatcher>) -> Result<(), Error> {
2418
let rule = conf.rule.val().clone();
2519
// FIXME support proxy
2620
let ns = conf.nameserver_or_default();
2721
if ns.egress.is_some() {
2822
error!("Resolver config in relay doesn't support proxy yet");
2923
}
30-
let resolver = Arc::new(create_resolver(ns.remote));
24+
let resolver = Arc::new(AsyncResolver::new(&ns));
3125
let router = TcpRouter::new(d, i, rule);
3226
match conf.listen {
3327
RelayProto::Socks5(a) => {

src/resolver/client/socks/mod.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ use std::io;
33
use std::net::SocketAddr;
44

55
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
6-
use std::time::Duration;
7-
use tokio::net::TcpStream;
86

9-
use super::TIMEOUT;
7+
use tokio::net::TcpStream;
108

119
use crate::conf::NameServerRemote;
1210
use asocks5::socks::Address;
@@ -44,9 +42,7 @@ impl SockGetterAsync {
4442
pub async fn get_udp(&self, data: Vec<u8>) -> Result<Vec<u8>, SocksError> {
4543
use std::str::FromStr;
4644
let la = SocketAddr::from_str("0.0.0.0:0").unwrap();
47-
let socks5 =
48-
Socks5Datagram::bind_with_timeout(self.proxy, la, Some(Duration::from_secs(TIMEOUT)))
49-
.await?;
45+
let socks5 = Socks5Datagram::bind(self.proxy, la).await?;
5046
let addr = ns_sock_addr(&self.addr);
5147
let socks5 = socks5.send_to(&data, Address::SocketAddress(addr)).await?;
5248

src/resolver/client/udp.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
use std::io;
32
use std::net::SocketAddr;
43
use std::net::UdpSocket as UdpSocketStd;

src/resolver/lookup.rs

Lines changed: 90 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,93 @@
1-
use crate::conf::NameServerRemote;
2-
use futures::compat::Future01CompatExt;
1+
use super::dnsclient::DnsClient;
2+
use crate::conf::NameServer;
33

4-
use futures::task::SpawnExt;
5-
use trust_dns_resolver::config::{NameServerConfig, Protocol};
6-
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
7-
use trust_dns_resolver::AsyncResolver;
4+
use failure::Error;
5+
use std::net::IpAddr;
6+
use std::str::FromStr;
7+
use trust_dns::op::Message;
8+
use trust_dns::op::Query;
9+
use trust_dns::proto::rr::Name;
10+
use trust_dns::rr::RecordType;
11+
use trust_dns::serialize::binary::{BinDecodable, BinDecoder};
812

9-
pub fn create_resolver(rm: NameServerRemote) -> AsyncResolver {
10-
let (addr, p) = match rm {
11-
NameServerRemote::Udp(a) => (a, Protocol::Udp),
12-
NameServerRemote::Tcp(a) => (a, Protocol::Tcp),
13-
};
14-
let nc = NameServerConfig {
15-
socket_addr: addr,
16-
protocol: p,
17-
tls_dns_name: None,
18-
};
19-
let conf = ResolverConfig::from_parts(None, vec![], vec![nc]);
20-
let (resolver, fut) = AsyncResolver::new(conf, ResolverOpts::default());
21-
tokio::spawn(async move {
22-
fut.compat().await.expect("AsyncResolver");
23-
});
24-
resolver
13+
use failure::_core::time::Duration;
14+
use tokio::future::FutureExt;
15+
16+
pub struct AsyncResolver {
17+
client: DnsClient,
18+
}
19+
impl AsyncResolver {
20+
pub fn new(rm: &NameServer) -> AsyncResolver {
21+
let client = DnsClient::new(rm);
22+
AsyncResolver { client }
23+
}
24+
25+
pub async fn resolve(&self, name: &str) -> Result<Vec<IpAddr>, Error> {
26+
let result = self
27+
.resolve_eternal(name)
28+
.timeout(Duration::from_secs(10))
29+
.await?;
30+
result
31+
}
32+
async fn resolve_eternal(&self, name: &str) -> Result<Vec<IpAddr>, Error> {
33+
let mut msg = Message::new();
34+
let name = Name::from_str(name).unwrap();
35+
let query = Query::query(name, RecordType::A);
36+
msg.add_query(query);
37+
let res = self.client.resolve(msg.to_vec()?).await?;
38+
let mut decoder = BinDecoder::new(&res);
39+
let message = Message::read(&mut decoder).expect("msg deco err");
40+
let ips = message
41+
.answers()
42+
.into_iter()
43+
.filter_map(|rec| {
44+
let rd = rec.rdata();
45+
let ip = rd.to_ip_addr();
46+
ip
47+
})
48+
.collect();
49+
Ok(ips)
50+
}
51+
}
52+
53+
#[cfg(test)]
54+
mod tests {
55+
use crate::conf::{main::RefVal, Egress, EgressAddr};
56+
use crate::conf::{NameServer, NameServerRemote};
57+
use crate::resolver::AsyncResolver;
58+
use bytes::Bytes;
59+
use std::net::IpAddr;
60+
use std::net::SocketAddr;
61+
use std::str::FromStr;
62+
63+
#[test]
64+
fn udp_test() {
65+
let ip = [127, 8, 8, 8];
66+
let remote = NameServerRemote::Udp(SocketAddr::new(IpAddr::from(ip), 53001));
67+
let ns = NameServer {
68+
remote,
69+
egress: None,
70+
};
71+
let resolver = AsyncResolver::new(&ns);
72+
let rt = tokio::runtime::Runtime::new().unwrap();
73+
let response = rt.block_on(async move { resolver.resolve("www.example.com.").await });
74+
assert!(response.is_err());
75+
}
76+
77+
#[test]
78+
fn socks_test() {
79+
let ip = [8, 8, 8, 8];
80+
let remote = NameServerRemote::Tcp(SocketAddr::new(IpAddr::from(ip), 53));
81+
let ns = NameServer {
82+
remote,
83+
egress: Some(RefVal::Val(Egress {
84+
name: Bytes::new(),
85+
addr: EgressAddr::Socks5(SocketAddr::from_str("1.1.1.1:3128").unwrap()),
86+
})),
87+
};
88+
let resolver = AsyncResolver::new(&ns);
89+
let rt = tokio::runtime::Runtime::new().unwrap();
90+
let response = rt.block_on(async move { resolver.resolve("www.example.com").await });
91+
assert!(response.is_err());
92+
}
2593
}

src/resolver/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ mod handler;
66
mod lookup;
77
mod serve;
88

9-
pub use self::lookup::create_resolver;
9+
pub use self::lookup::AsyncResolver;
1010
pub use self::serve::serve;

src/resolver/serve/mod.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,11 @@ use crate::conf::DomainMatcher;
1010
use crate::resolver::handler;
1111
use crate::resolver::handler::SmartResolver;
1212

13-
14-
1513
use std::net::UdpSocket as UdpSocketStd;
1614
use tokio::net::UdpSocket;
1715
use tokio_net::driver::Handle;
1816

19-
pub fn serve(
20-
conf: DnsProxy,
21-
matcher: Arc<DomainMatcher>,
22-
) -> Result<(), Error> {
17+
pub fn serve(conf: DnsProxy, matcher: Arc<DomainMatcher>) -> Result<(), Error> {
2318
let handler = handler::SmartResolver::new(matcher, &conf)?;
2419
let handler = Arc::new(handler);
2520
let addr = conf.listen;

0 commit comments

Comments
 (0)