mirror of
https://github.com/DNSCrypt/doh-server.git
synced 2025-04-06 06:27:37 +03:00
parent
de99e6a8b2
commit
217bb90320
1 changed files with 78 additions and 17 deletions
95
src/main.rs
95
src/main.rs
|
@ -13,6 +13,7 @@ use hyper;
|
||||||
use hyper::server::conn::Http;
|
use hyper::server::conn::Http;
|
||||||
use hyper::service::Service;
|
use hyper::service::Service;
|
||||||
use hyper::{Body, Method, Request, Response, StatusCode};
|
use hyper::{Body, Method, Request, Response, StatusCode};
|
||||||
|
use std::io;
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
use native_tls::{self, Identity};
|
use native_tls::{self, Identity};
|
||||||
|
@ -103,20 +104,41 @@ struct DoH {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Error {
|
enum Error {
|
||||||
Incomplete,
|
Incomplete,
|
||||||
|
InvalidData,
|
||||||
TooLarge,
|
TooLarge,
|
||||||
|
UpstreamIssue,
|
||||||
Hyper(hyper::Error),
|
Hyper(hyper::Error),
|
||||||
|
Io(io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Error {
|
impl std::fmt::Display for Error {
|
||||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
std::fmt::Debug::fmt(self, fmt)
|
std::fmt::Debug::fmt(self, fmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for Error {
|
impl std::error::Error for Error {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
Error::Incomplete => "Incomplete",
|
Error::Incomplete => "Incomplete",
|
||||||
Error::TooLarge => "TooLarge",
|
Error::InvalidData => "Invalid data",
|
||||||
|
Error::TooLarge => "Too large",
|
||||||
|
Error::UpstreamIssue => "Upstream error",
|
||||||
Error::Hyper(_) => self.description(),
|
Error::Hyper(_) => self.description(),
|
||||||
|
Error::Io(_) => self.description(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Error> for StatusCode {
|
||||||
|
fn from(e: Error) -> StatusCode {
|
||||||
|
match e {
|
||||||
|
Error::Incomplete => StatusCode::UNPROCESSABLE_ENTITY,
|
||||||
|
Error::InvalidData => StatusCode::BAD_REQUEST,
|
||||||
|
Error::TooLarge => StatusCode::PAYLOAD_TOO_LARGE,
|
||||||
|
Error::UpstreamIssue => StatusCode::BAD_GATEWAY,
|
||||||
|
Error::Hyper(_) => StatusCode::SERVICE_UNAVAILABLE,
|
||||||
|
Error::Io(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +179,38 @@ impl DoH {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
return Box::new(future::ok(response));
|
return Box::new(future::ok(response));
|
||||||
}
|
}
|
||||||
|
let headers = req.headers();
|
||||||
|
let accept = match headers.get("accept") {
|
||||||
|
None => {
|
||||||
|
let response = Response::builder()
|
||||||
|
.status(StatusCode::NOT_ACCEPTABLE)
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap();
|
||||||
|
return Box::new(future::ok(response));
|
||||||
|
}
|
||||||
|
Some(accept) => accept.to_str(),
|
||||||
|
};
|
||||||
|
let accept = match accept {
|
||||||
|
Err(_) => {
|
||||||
|
let response = Response::builder()
|
||||||
|
.status(StatusCode::BAD_REQUEST)
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap();
|
||||||
|
return Box::new(future::ok(response));
|
||||||
|
}
|
||||||
|
Ok(accept) => accept.to_lowercase(),
|
||||||
|
};
|
||||||
|
let found = accept
|
||||||
|
.split(',')
|
||||||
|
.take(10)
|
||||||
|
.any(|part| part.trim() == "application/dns-message");
|
||||||
|
if !found {
|
||||||
|
let response = Response::builder()
|
||||||
|
.status(StatusCode::UNSUPPORTED_MEDIA_TYPE)
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap();
|
||||||
|
return Box::new(future::ok(response));
|
||||||
|
}
|
||||||
match *req.method() {
|
match *req.method() {
|
||||||
Method::POST => {
|
Method::POST => {
|
||||||
if self.inner.disable_post {
|
if self.inner.disable_post {
|
||||||
|
@ -166,8 +220,14 @@ impl DoH {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
return Box::new(future::ok(response));
|
return Box::new(future::ok(response));
|
||||||
}
|
}
|
||||||
let fut = self.read_body_and_proxy(req.into_body());
|
let fut = self.read_body_and_proxy(req.into_body()).or_else(|e| {
|
||||||
Box::new(fut.map_err(|_| Error::Incomplete))
|
let response = Response::builder()
|
||||||
|
.status(StatusCode::from(e))
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap();
|
||||||
|
future::ok(response)
|
||||||
|
});
|
||||||
|
Box::new(fut)
|
||||||
}
|
}
|
||||||
Method::GET => {
|
Method::GET => {
|
||||||
let query = req.uri().query().unwrap_or("");
|
let query = req.uri().query().unwrap_or("");
|
||||||
|
@ -192,8 +252,14 @@ impl DoH {
|
||||||
return Box::new(future::ok(response));
|
return Box::new(future::ok(response));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let fut = self.proxy(question);
|
let fut = self.proxy(question).or_else(|e| {
|
||||||
Box::new(fut.map_err(|_| Error::Incomplete))
|
let response = Response::builder()
|
||||||
|
.status(StatusCode::from(e))
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap();
|
||||||
|
future::ok(response)
|
||||||
|
});
|
||||||
|
Box::new(fut)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let response = Response::builder()
|
let response = Response::builder()
|
||||||
|
@ -208,13 +274,9 @@ impl DoH {
|
||||||
fn proxy(
|
fn proxy(
|
||||||
&self,
|
&self,
|
||||||
mut query: Vec<u8>,
|
mut query: Vec<u8>,
|
||||||
) -> Box<dyn Future<Item = Response<Body>, Error = ()> + Send> {
|
) -> Box<dyn Future<Item = Response<Body>, Error = Error> + Send> {
|
||||||
if query.len() < MIN_DNS_PACKET_LEN {
|
if query.len() < MIN_DNS_PACKET_LEN {
|
||||||
let response = Response::builder()
|
return Box::new(future::err(Error::Incomplete));
|
||||||
.status(StatusCode::BAD_REQUEST)
|
|
||||||
.body(Body::empty())
|
|
||||||
.unwrap();
|
|
||||||
return Box::new(future::ok(response));
|
|
||||||
}
|
}
|
||||||
let _ = dns::set_edns_max_payload_size(&mut query, MAX_DNS_RESPONSE_LEN as u16);
|
let _ = dns::set_edns_max_payload_size(&mut query, MAX_DNS_RESPONSE_LEN as u16);
|
||||||
let inner = &self.inner;
|
let inner = &self.inner;
|
||||||
|
@ -223,18 +285,18 @@ impl DoH {
|
||||||
let (min_ttl, max_ttl, err_ttl) = (inner.min_ttl, inner.max_ttl, inner.err_ttl);
|
let (min_ttl, max_ttl, err_ttl) = (inner.min_ttl, inner.max_ttl, inner.err_ttl);
|
||||||
let fut = socket
|
let fut = socket
|
||||||
.send_dgram(query, &inner.server_address)
|
.send_dgram(query, &inner.server_address)
|
||||||
.map_err(|_| ())
|
.map_err(Error::Io)
|
||||||
.and_then(move |(socket, _)| {
|
.and_then(move |(socket, _)| {
|
||||||
let packet = vec![0; MAX_DNS_RESPONSE_LEN];
|
let packet = vec![0; MAX_DNS_RESPONSE_LEN];
|
||||||
socket.recv_dgram(packet).map_err(|_| {})
|
socket.recv_dgram(packet).map_err(Error::Io)
|
||||||
})
|
})
|
||||||
.and_then(move |(_socket, mut packet, len, response_server_address)| {
|
.and_then(move |(_socket, mut packet, len, response_server_address)| {
|
||||||
if len < MIN_DNS_PACKET_LEN || expected_server_address != response_server_address {
|
if len < MIN_DNS_PACKET_LEN || expected_server_address != response_server_address {
|
||||||
return future::err(());
|
return future::err(Error::UpstreamIssue);
|
||||||
}
|
}
|
||||||
packet.truncate(len);
|
packet.truncate(len);
|
||||||
let ttl = match dns::min_ttl(&packet, min_ttl, max_ttl, err_ttl) {
|
let ttl = match dns::min_ttl(&packet, min_ttl, max_ttl, err_ttl) {
|
||||||
Err(_) => return future::err(()),
|
Err(_) => return future::err(Error::UpstreamIssue),
|
||||||
Ok(ttl) => ttl,
|
Ok(ttl) => ttl,
|
||||||
};
|
};
|
||||||
let packet_len = packet.len();
|
let packet_len = packet.len();
|
||||||
|
@ -256,7 +318,7 @@ impl DoH {
|
||||||
fn read_body_and_proxy(
|
fn read_body_and_proxy(
|
||||||
&self,
|
&self,
|
||||||
body: Body,
|
body: Body,
|
||||||
) -> Box<dyn Future<Item = Response<Body>, Error = ()> + Send> {
|
) -> Box<dyn Future<Item = Response<Body>, Error = Error> + Send> {
|
||||||
let mut sum_size = 0;
|
let mut sum_size = 0;
|
||||||
let inner = self.clone();
|
let inner = self.clone();
|
||||||
let fut = body
|
let fut = body
|
||||||
|
@ -270,7 +332,6 @@ impl DoH {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.concat2()
|
.concat2()
|
||||||
.map_err(move |_err| ())
|
|
||||||
.map(move |chunk| chunk.to_vec())
|
.map(move |chunk| chunk.to_vec())
|
||||||
.and_then(move |query| inner.proxy(query));
|
.and_then(move |query| inner.proxy(query));
|
||||||
Box::new(fut)
|
Box::new(fut)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue