diff --git a/Cargo.toml b/Cargo.toml index e0c7787..da692a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ rand-old = { package = "rand", version = "0.7.0" } # For ed25519-dalek sqlite = "0.26.0" uuid = { version = "0.8.2", features = ["serde", "v4"] } mio = { version = "0.7.13", features = ["os-poll", "net"] } -ureq = "2.2" +ureq = { version = "2.2", optional = true } lru = "0.6" derive_more = "0.99.16" lazy_static = "1.4.0" @@ -79,4 +79,5 @@ FileDescription="Alternative Free Identity System" [features] webgui = ["web-view", "tinyfiledialogs", "open"] edge = ["webgui", "web-view/edge"] -default = ["webgui"] \ No newline at end of file +doh = ["ureq"] +default = ["webgui", "doh"] \ No newline at end of file diff --git a/contrib/deb/generate.sh b/contrib/deb/generate.sh index 4854c90..8585db7 100755 --- a/contrib/deb/generate.sh +++ b/contrib/deb/generate.sh @@ -23,6 +23,11 @@ PKGREPLACES=alfis mkdir -p bin +FEATURES = "doh" +if [ $PKGARCH = "mipsel" ]; then FEATURES='' +elif [ $PKGARCH = "mips" ]; then FEATURES='' +fi + TARGET="" # Building nogui versions only if [ $PKGARCH = "amd64" ]; then TARGET='x86_64-unknown-linux-musl' @@ -36,7 +41,7 @@ else exit 1 fi -cross build --release --no-default-features --target $TARGET +cross build --release --no-default-features --features=$FEATURES --target $TARGET upx target/$TARGET/release/alfis cp target/$TARGET/release/alfis ./alfis cp target/$TARGET/release/alfis ./bin/alfis-linux-$PKGARCH-v$PKGVERSION-nogui diff --git a/src/dns/client.rs b/src/dns/client.rs index 4c5f032..1959b47 100644 --- a/src/dns/client.rs +++ b/src/dns/client.rs @@ -1,11 +1,17 @@ //! client for sending DNS queries to other servers -use std::io::{Write, Read}; +use std::io::Write; +#[cfg(feature = "doh")] +use std::io::Read; use std::marker::{Send, Sync}; -use std::net::{SocketAddr, TcpStream, ToSocketAddrs, UdpSocket, IpAddr}; +use std::net::{SocketAddr, TcpStream, ToSocketAddrs, UdpSocket}; +#[cfg(feature = "doh")] +use std::net::IpAddr; use std::sync::atomic::{AtomicUsize, Ordering, AtomicBool}; use std::sync::mpsc::{channel, Sender}; -use std::sync::{Arc, Mutex, RwLock}; +use std::sync::{Arc, Mutex}; +#[cfg(feature = "doh")] +use std::sync::RwLock; use std::thread::{sleep, Builder}; use std::time::Duration as SleepDuration; @@ -15,9 +21,14 @@ use derive_more::{Display, Error, From}; #[allow(unused_imports)] use log::{debug, error, info, trace, warn}; -use crate::dns::buffer::{BytePacketBuffer, PacketBuffer, StreamPacketBuffer, VectorPacketBuffer}; +use crate::dns::buffer::{BytePacketBuffer, PacketBuffer, StreamPacketBuffer}; +#[cfg(feature = "doh")] +use crate::dns::buffer::VectorPacketBuffer; use crate::dns::netutil::{read_packet_length, write_packet_length}; -use crate::dns::protocol::{DnsPacket, DnsQuestion, QueryType, DnsRecord}; +use crate::dns::protocol::{DnsPacket, DnsQuestion, QueryType}; +#[cfg(feature = "doh")] +use crate::dns::protocol::DnsRecord; +#[cfg(feature = "doh")] use lru::LruCache; #[derive(Debug, Display, From, Error)] @@ -372,12 +383,14 @@ impl DnsClient for DnsNetworkClient { } } +#[cfg(feature = "doh")] pub struct HttpsDnsClient { agent: ureq::Agent, /// Counter for assigning packet ids seq: AtomicUsize, } +#[cfg(feature = "doh")] impl HttpsDnsClient { pub fn new(bootstraps: Vec) -> Self { let client_name = format!("ALFIS/{}", env!("CARGO_PKG_VERSION")); @@ -444,6 +457,7 @@ impl HttpsDnsClient { } } +#[cfg(feature = "doh")] impl DnsClient for HttpsDnsClient { fn get_sent_count(&self) -> usize { // No statistics for now diff --git a/src/dns/context.rs b/src/dns/context.rs index f7fdd85..c0c6383 100644 --- a/src/dns/context.rs +++ b/src/dns/context.rs @@ -7,7 +7,9 @@ use derive_more::{Display, Error, From}; use crate::dns::authority::Authority; use crate::dns::cache::SynchronizedCache; -use crate::dns::client::{DnsClient, DnsNetworkClient, HttpsDnsClient}; +use crate::dns::client::{DnsClient, DnsNetworkClient}; +#[cfg(feature = "doh")] +use crate::dns::client::HttpsDnsClient; use crate::dns::filter::DnsFilter; use crate::dns::resolve::{DnsResolver, ForwardingDnsResolver, RecursiveDnsResolver}; @@ -45,7 +47,7 @@ pub struct ServerContext { pub cache: SynchronizedCache, pub filters: Vec>, pub old_client: Box, - pub doh_client: Box, + pub doh_client: Option>, pub dns_listen: String, pub api_port: u16, pub resolve_strategy: ResolveStrategy, @@ -64,13 +66,19 @@ impl Default for ServerContext { } impl ServerContext { + #[allow(unused_variables)] pub fn new(dns_listen: String, bootstraps: Vec) -> ServerContext { + #[cfg(not(feature = "doh"))] + let doh_client = None; + #[cfg(feature = "doh")] + let doh_client: Option> = Some(Box::new(HttpsDnsClient::new(bootstraps))); + ServerContext { authority: Authority::new(), cache: SynchronizedCache::new(), filters: Vec::new(), - old_client: Box::new(DnsNetworkClient::new(10000 + (rand::random::() % 20000))), - doh_client: Box::new(HttpsDnsClient::new(bootstraps)), + old_client: Box::new(DnsNetworkClient::new(10000 + (rand::random::() % 50000))), + doh_client, dns_listen, api_port: 5380, resolve_strategy: ResolveStrategy::Recursive, @@ -87,7 +95,9 @@ impl ServerContext { // Start UDP client thread self.old_client.run()?; // Start DoH client - self.doh_client.run()?; + if let Some(client) = &self.doh_client { + client.run()?; + } // Load authority data self.authority.load()?; @@ -122,7 +132,7 @@ pub mod tests { cache: SynchronizedCache::new(), filters: Vec::new(), old_client: Box::new(DnsStubClient::new(callback)), - doh_client: Box::new(HttpsDnsClient::new(Vec::new())), + doh_client: Some(Box::new(HttpsDnsClient::new(Vec::new()))), dns_listen: String::from("0.0.0.0:53"), api_port: 5380, resolve_strategy: ResolveStrategy::Recursive, diff --git a/src/dns/resolve.rs b/src/dns/resolve.rs index 4444560..044ef2f 100644 --- a/src/dns/resolve.rs +++ b/src/dns/resolve.rs @@ -89,7 +89,12 @@ impl DnsResolver for ForwardingDnsResolver { let result = match self.context.cache.lookup(qname, qtype) { None => { if is_url(upstream) { - self.context.doh_client.send_query(qname, qtype, upstream, true)? + if let Some(client) = &self.context.doh_client { + client.send_query(qname, qtype, upstream, true)? + } else { + log::error!("This build doesn't support DoH"); + return Err(ResolveError::NoServerFound); + } } else { self.context.old_client.send_query(qname, qtype, upstream, true)? }