Add my_ip feature

pull/34/head
Frank Denis 4 years ago
parent 2a96c5f985
commit 75166216b9

@ -114,6 +114,11 @@ daemonize = false
# chroot = "/var/empty" # chroot = "/var/empty"
## Queries sent to that name will return the client IP address.
## This can be very useful for debugging, or to check that relaying works.
my_ip = "my.ip"
#################################### ####################################
# DNSCrypt settings # # DNSCrypt settings #

@ -43,7 +43,7 @@ impl BlackList {
while line.ends_with('.') { while line.ends_with('.') {
line = &line[..line.len() - 1]; line = &line[..line.len() - 1];
} }
let qname = line.as_bytes().to_vec().to_ascii_lowercase(); let qname = line.as_bytes().to_ascii_lowercase();
if qname.is_empty() { if qname.is_empty() {
bail!("Unexpected blacklist rule at line {}", line_nb) bail!("Unexpected blacklist rule at line {}", line_nb)
} }
@ -53,7 +53,7 @@ impl BlackList {
} }
pub fn find(&self, qname: &[u8]) -> bool { pub fn find(&self, qname: &[u8]) -> bool {
let qname = qname.to_vec().to_ascii_lowercase(); let qname = qname.to_ascii_lowercase();
let mut qname = qname.as_slice(); let mut qname = qname.as_slice();
let map = &self.inner.map; let map = &self.inner.map;
let mut iterations = self.max_iterations; let mut iterations = self.max_iterations;

@ -81,6 +81,7 @@ pub struct Config {
pub daemonize: bool, pub daemonize: bool,
pub pid_file: Option<PathBuf>, pub pid_file: Option<PathBuf>,
pub log_file: Option<PathBuf>, pub log_file: Option<PathBuf>,
pub my_ip: Option<String>,
#[cfg(feature = "metrics")] #[cfg(feature = "metrics")]
pub metrics: Option<MetricsConfig>, pub metrics: Option<MetricsConfig>,
pub anonymized_dns: Option<AnonymizedDNSConfig>, pub anonymized_dns: Option<AnonymizedDNSConfig>,

@ -2,7 +2,7 @@ use crate::dnscrypt_certs::*;
use crate::errors::*; use crate::errors::*;
use byteorder::{BigEndian, ByteOrder, WriteBytesExt}; use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::IpAddr;
use std::sync::Arc; use std::sync::Arc;
pub const DNS_MAX_HOSTNAME_SIZE: usize = 256; pub const DNS_MAX_HOSTNAME_SIZE: usize = 256;
@ -622,7 +622,7 @@ pub fn serve_blocked_response(client_packet: Vec<u8>) -> Result<Vec<u8>, Error>
Ok(packet) Ok(packet)
} }
pub fn serve_a_response(client_packet: Vec<u8>, ip: Ipv4Addr) -> Result<Vec<u8>, Error> { pub fn serve_ip_response(client_packet: Vec<u8>, ip: IpAddr, ttl: u32) -> Result<Vec<u8>, Error> {
ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet"); ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet");
ensure!(qdcount(&client_packet) == 1, "No question"); ensure!(qdcount(&client_packet) == 1, "No question");
ensure!( ensure!(
@ -637,31 +637,21 @@ pub fn serve_a_response(client_packet: Vec<u8>, ip: Ipv4Addr) -> Result<Vec<u8>,
authoritative_response(&mut packet); authoritative_response(&mut packet);
ancount_inc(&mut packet)?; ancount_inc(&mut packet)?;
packet.write_u16::<BigEndian>(0xc000 + DNS_HEADER_SIZE as u16)?; packet.write_u16::<BigEndian>(0xc000 + DNS_HEADER_SIZE as u16)?;
packet.write_u16::<BigEndian>(DNS_TYPE_A)?; match ip {
packet.write_u16::<BigEndian>(DNS_CLASS_INET)?; IpAddr::V4(ip) => {
packet.write_u32::<BigEndian>(60)?; packet.write_u16::<BigEndian>(DNS_TYPE_A)?;
packet.extend_from_slice(&ip.octets()); packet.write_u16::<BigEndian>(DNS_CLASS_INET)?;
Ok(packet) packet.write_u32::<BigEndian>(ttl)?;
} packet.write_u16::<BigEndian>(4)?;
packet.extend_from_slice(&ip.octets());
pub fn serve_aaaa_response(client_packet: Vec<u8>, ip: Ipv6Addr) -> Result<Vec<u8>, Error> { }
ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet"); IpAddr::V6(ip) => {
ensure!(qdcount(&client_packet) == 1, "No question"); packet.write_u16::<BigEndian>(DNS_TYPE_AAAA)?;
ensure!( packet.write_u16::<BigEndian>(DNS_CLASS_INET)?;
!is_response(&client_packet), packet.write_u32::<BigEndian>(ttl)?;
"Question expected, but got a response instead" packet.write_u16::<BigEndian>(16)?;
); packet.extend_from_slice(&ip.octets());
let offset = skip_name(&client_packet, DNS_HEADER_SIZE)?; }
let mut packet = client_packet; };
ensure!(packet.len() - offset >= 4, "Short packet");
packet.truncate(offset + 4);
an_ns_ar_count_clear(&mut packet);
authoritative_response(&mut packet);
ancount_inc(&mut packet)?;
packet.write_u16::<BigEndian>(0xc000 + DNS_HEADER_SIZE as u16)?;
packet.write_u16::<BigEndian>(DNS_TYPE_AAAA)?;
packet.write_u16::<BigEndian>(DNS_CLASS_INET)?;
packet.write_u32::<BigEndian>(60)?;
packet.extend_from_slice(&ip.octets());
Ok(packet) Ok(packet)
} }

@ -49,6 +49,7 @@ pub struct Globals {
pub anonymized_dns_allow_non_reserved_ports: bool, pub anonymized_dns_allow_non_reserved_ports: bool,
pub anonymized_dns_blacklisted_ips: Vec<IpAddr>, pub anonymized_dns_blacklisted_ips: Vec<IpAddr>,
pub access_control_tokens: Option<Vec<String>>, pub access_control_tokens: Option<Vec<String>>,
pub my_ip: Option<Vec<u8>>,
#[cfg(feature = "metrics")] #[cfg(feature = "metrics")]
#[derivative(Debug = "ignore")] #[derivative(Debug = "ignore")]
pub varz: Varz, pub varz: Varz,

@ -704,6 +704,7 @@ fn main() -> Result<(), Error> {
anonymized_dns_allow_non_reserved_ports, anonymized_dns_allow_non_reserved_ports,
anonymized_dns_blacklisted_ips, anonymized_dns_blacklisted_ips,
access_control_tokens, access_control_tokens,
my_ip: config.my_ip.map(|ip| ip.as_bytes().to_ascii_lowercase()),
#[cfg(feature = "metrics")] #[cfg(feature = "metrics")]
varz: Varz::default(), varz: Varz::default(),
}); });

@ -8,7 +8,7 @@ use byteorder::{BigEndian, ByteOrder};
use rand::prelude::*; use rand::prelude::*;
use siphasher::sip128::Hasher128; use siphasher::sip128::Hasher128;
use std::hash::Hasher; use std::hash::Hasher;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use tokio::net::{TcpStream, UdpSocket}; use tokio::net::{TcpStream, UdpSocket};
use tokio::prelude::*; use tokio::prelude::*;
@ -169,16 +169,15 @@ pub async fn get_cached_response_or_resolve(
mut packet: &mut Vec<u8>, mut packet: &mut Vec<u8>,
) -> Result<Vec<u8>, Error> { ) -> Result<Vec<u8>, Error> {
let packet_qname = dns::qname(&packet)?; let packet_qname = dns::qname(&packet)?;
if &packet_qname == b"my.ip" { if let Some(my_ip) = &globals.my_ip {
let client_ip = match client_ctx { if &packet_qname.to_ascii_lowercase() == my_ip {
ClientCtx::Udp(u) => u.client_addr, let client_ip = match client_ctx {
ClientCtx::Tcp(t) => t.client_connection.peer_addr()?, ClientCtx::Udp(u) => u.client_addr,
ClientCtx::Tcp(t) => t.client_connection.peer_addr()?,
}
.ip();
return serve_ip_response(packet.to_vec(), client_ip, 1);
} }
.ip();
return match client_ip {
IpAddr::V4(ip) => serve_a_response(packet.to_vec(), ip),
IpAddr::V6(ip) => serve_aaaa_response(packet.to_vec(), ip),
};
} }
if let Some(blacklist) = &globals.blacklist { if let Some(blacklist) = &globals.blacklist {
if blacklist.find(&packet_qname) { if blacklist.find(&packet_qname) {

Loading…
Cancel
Save