Add TLS proxying

pull/5/head
Frank Denis 5 years ago
parent ec91355e74
commit a62b4a0cf7

@ -17,6 +17,7 @@ pub struct Globals {
pub listen_addr: SocketAddr, pub listen_addr: SocketAddr,
pub external_addr: SocketAddr, pub external_addr: SocketAddr,
pub upstream_addr: SocketAddr, pub upstream_addr: SocketAddr,
pub tls_upstream_addr: Option<SocketAddr>,
pub udp_timeout: Duration, pub udp_timeout: Duration,
pub tcp_timeout: Duration, pub tcp_timeout: Duration,
pub udp_concurrent_connections: Arc<AtomicU32>, pub udp_concurrent_connections: Arc<AtomicU32>,

@ -39,6 +39,7 @@ use byteorder::{BigEndian, ByteOrder};
use clap::Arg; use clap::Arg;
use dnsstamps::{InformalProperty, WithInformalProperty}; use dnsstamps::{InformalProperty, WithInformalProperty};
use failure::{bail, ensure}; use failure::{bail, ensure};
use futures::join;
use futures::prelude::*; use futures::prelude::*;
use parking_lot::Mutex; use parking_lot::Mutex;
use rand::prelude::*; use rand::prelude::*;
@ -52,6 +53,7 @@ use std::path::PathBuf;
use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener, TcpStream, UdpSocket}; use tokio::net::{TcpListener, TcpStream, UdpSocket};
use tokio::prelude::*; use tokio::prelude::*;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
@ -234,6 +236,32 @@ async fn handle_client_query(
.await .await
} }
async fn tls_proxy(
globals: Arc<Globals>,
binlen: [u8; 2],
client_connection: TcpStream,
) -> Result<(), Error> {
let tls_upstream_addr = match &globals.tls_upstream_addr {
None => return Ok(()),
Some(tls_upstream_addr) => tls_upstream_addr,
};
let std_socket = match globals.external_addr {
SocketAddr::V4(_) => net2::TcpBuilder::new_v4(),
SocketAddr::V6(_) => net2::TcpBuilder::new_v6(),
}?
.bind(&globals.external_addr)?
.to_tcp_stream()?;
let ext_socket =
TcpStream::connect_std(std_socket, tls_upstream_addr, &Handle::default()).await?;
let (mut erh, mut ewh) = ext_socket.split();
let (mut rh, mut wh) = client_connection.split();
ewh.write_all(&binlen).await?;
let fut_proxy_1 = rh.copy(&mut ewh);
let fut_proxy_2 = erh.copy(&mut wh);
let _ = join!(fut_proxy_1, fut_proxy_2);
Ok(())
}
async fn tcp_acceptor(globals: Arc<Globals>, tcp_listener: TcpListener) -> Result<(), Error> { async fn tcp_acceptor(globals: Arc<Globals>, tcp_listener: TcpListener) -> Result<(), Error> {
let runtime = globals.runtime.clone(); let runtime = globals.runtime.clone();
let mut tcp_listener = tcp_listener.incoming(); let mut tcp_listener = tcp_listener.incoming();
@ -262,7 +290,9 @@ async fn tcp_acceptor(globals: Arc<Globals>, tcp_listener: TcpListener) -> Resul
let mut binlen = [0u8, 0]; let mut binlen = [0u8, 0];
client_connection.read_exact(&mut binlen).await?; client_connection.read_exact(&mut binlen).await?;
let packet_len = BigEndian::read_u16(&binlen) as usize; let packet_len = BigEndian::read_u16(&binlen) as usize;
ensure!(packet_len != 0x1603, "TLS traffic"); if packet_len == 0x1603 {
return tls_proxy(globals, binlen, client_connection).await;
}
ensure!( ensure!(
(DNS_HEADER_SIZE..=DNSCRYPT_TCP_QUERY_MAX_SIZE).contains(&packet_len), (DNS_HEADER_SIZE..=DNSCRYPT_TCP_QUERY_MAX_SIZE).contains(&packet_len),
"Unexpected query size" "Unexpected query size"
@ -342,42 +372,49 @@ fn main() -> Result<(), Error> {
let matches = app_from_crate!() let matches = app_from_crate!()
.arg( .arg(
Arg::with_name("listen-addr") Arg::with_name("listen-addr")
.value_name("listen-addr") .long("listen-addr")
.value_name("addr:port")
.takes_value(true) .takes_value(true)
.default_value("127.0.0.1:4443") .default_value("127.0.0.1:4443")
.required(true)
.help("Address and port to listen to"), .help("Address and port to listen to"),
) )
.arg( .arg(
Arg::with_name("provider-name") Arg::with_name("provider-name")
.value_name("provider-name") .long("provider-name")
.value_name("string")
.takes_value(true) .takes_value(true)
.default_value("2.dnscrypt.test") .default_value("2.dnscrypt.test")
.required(true)
.help("Provider name"), .help("Provider name"),
) )
.arg( .arg(
Arg::with_name("upstream-addr") Arg::with_name("upstream-addr")
.value_name("upstream-addr") .long("upstream-addr")
.value_name("addr:port")
.takes_value(true) .takes_value(true)
.default_value("9.9.9.9:53") .default_value("9.9.9.9:53")
.required(true)
.help("Address and port of the upstream server"), .help("Address and port of the upstream server"),
) )
.arg(
Arg::with_name("tls-upstream-addr")
.long("tls-upstream-addr")
.value_name("addr:port")
.takes_value(true)
.help("Address and port of an optional upstream TLS (HTTPS / DoH) server"),
)
.arg( .arg(
Arg::with_name("external-addr") Arg::with_name("external-addr")
.value_name("external-addr") .long("external-addr")
.value_name("addr:port")
.takes_value(true) .takes_value(true)
.default_value("0.0.0.0:0") .default_value("0.0.0.0:0")
.required(true)
.help("Address and port to connect from"), .help("Address and port to connect from"),
) )
.arg( .arg(
Arg::with_name("state-file") Arg::with_name("state-file")
.value_name("state-file") .long("state-file")
.value_name("file")
.takes_value(true) .takes_value(true)
.default_value("dnscrypt-server.state") .default_value("dnscrypt-server.state")
.required(true)
.help("File to store the server state"), .help("File to store the server state"),
) )
.get_matches(); .get_matches();
@ -393,6 +430,11 @@ fn main() -> Result<(), Error> {
let upstream_addr_s = matches.value_of("upstream-addr").unwrap(); let upstream_addr_s = matches.value_of("upstream-addr").unwrap();
let upstream_addr: SocketAddr = upstream_addr_s.parse()?; let upstream_addr: SocketAddr = upstream_addr_s.parse()?;
let tls_upstream_addr_s = matches.value_of("tls-upstream-addr");
dbg!(tls_upstream_addr_s);
let tls_upstream_addr: Option<SocketAddr> =
tls_upstream_addr_s.map(|x| x.parse().expect("Invalid TLS upstream address"));
let external_addr_s = matches.value_of("external-addr").unwrap(); let external_addr_s = matches.value_of("external-addr").unwrap();
let external_addr: SocketAddr = external_addr_s.parse()?; let external_addr: SocketAddr = external_addr_s.parse()?;
@ -450,6 +492,7 @@ fn main() -> Result<(), Error> {
provider_name, provider_name,
listen_addr, listen_addr,
upstream_addr, upstream_addr,
tls_upstream_addr,
external_addr, external_addr,
tcp_timeout, tcp_timeout,
udp_timeout, udp_timeout,

Loading…
Cancel
Save