From 6483d3d4d7677496cd0e6fe0d545fc24b490a466 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Thu, 17 Oct 2019 11:10:25 +0200 Subject: [PATCH] Set IPV6_ONLY on IPv6 sockets Fixes #9 --- Cargo.toml | 2 +- src/main.rs | 35 ++++++++++++++++++++++++++--------- src/metrics.rs | 12 +++++++++++- src/resolver.rs | 21 +++++++++++++++------ 4 files changed, 53 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bd4a3f9..092f2d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ coarsetime = "0.1.11" daemonize-simple = "0.1.2" derivative = "1.0.3" dnsstamps = "0.1.2" -env_logger = { version="0.7.0", default-features = false, features = ["humantime"]} +env_logger = { version="0.7.1", default-features = false, features = ["humantime"]} failure = "0.1.6" futures-preview = { version = "=0.3.0-alpha.19", features = ["async-await"] } jemallocator = "0.3.2" diff --git a/src/main.rs b/src/main.rs index 0b1331b..8da4ef2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -237,11 +237,14 @@ async fn tls_proxy( 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()?; + SocketAddr::V4(_) => net2::TcpBuilder::new_v4()? + .bind(&globals.external_addr)? + .to_tcp_stream()?, + SocketAddr::V6(_) => net2::TcpBuilder::new_v6()? + .only_v6(true)? + .bind(&globals.external_addr)? + .to_tcp_stream()?, + }; let mut ext_socket = TcpStream::connect_std(std_socket, tls_upstream_addr, &Default::default()).await?; let (mut erh, mut ewh) = ext_socket.split(); @@ -384,15 +387,29 @@ async fn start( fn bind_listeners( listen_addrs: &[SocketAddr], - runtime: Arc, ) -> Result, Error> { let mut sockets = Vec::with_capacity(listen_addrs.len()); for listen_addr in listen_addrs { - let tcp_listener = match runtime.block_on(TcpListener::bind(&listen_addr)) { + let std_socket = match listen_addr { + SocketAddr::V4(_) => net2::TcpBuilder::new_v4()? + .bind(&listen_addr)? + .to_tcp_listener()?, + SocketAddr::V6(_) => net2::TcpBuilder::new_v6()? + .only_v6(true)? + .bind(&listen_addr)? + .to_tcp_listener()?, + }; + let tcp_listener = match TcpListener::from_std(std_socket, &Default::default()) { Ok(tcp_listener) => tcp_listener, Err(e) => bail!(format_err!("{}/TCP: {}", listen_addr, e)), }; - let udp_socket = match std::net::UdpSocket::bind(&listen_addr) { + let std_socket = match listen_addr { + SocketAddr::V4(_) => net2::UdpBuilder::new_v4()?.bind(&listen_addr), + SocketAddr::V6(_) => net2::UdpBuilder::new_v6()? + .only_v6(true)? + .bind(&listen_addr), + }; + let udp_socket = match std_socket { Ok(udp_socket) => udp_socket, Err(e) => bail!(format_err!("{}/UDP: {}", listen_addr, e)), }; @@ -486,7 +503,7 @@ fn main() -> Result<(), Error> { let runtime = Arc::new(runtime_builder.build()?); let listen_addrs: Vec<_> = config.listen_addrs.iter().map(|x| x.local).collect(); - let listeners = bind_listeners(&listen_addrs, runtime.clone()) + let listeners = bind_listeners(&listen_addrs) .map_err(|e| { error!("Unable to listen to the requested IPs and ports: [{}]", e); std::process::exit(1); diff --git a/src/metrics.rs b/src/metrics.rs index 290cfbf..ae3cf47 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -10,6 +10,7 @@ use hyper::service::service_fn; use hyper::{Body, Request, Response, StatusCode}; use prometheus::{self, Encoder, TextEncoder}; use std::mem; +use std::net::SocketAddr; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; use tokio::net::TcpListener; @@ -52,7 +53,16 @@ pub async fn prometheus_service( runtime: Arc, ) -> Result<(), Error> { let path = Arc::new(metrics_config.path); - let mut stream = TcpListener::bind(metrics_config.listen_addr).await?; + let std_socket = match metrics_config.listen_addr { + SocketAddr::V4(_) => net2::TcpBuilder::new_v4()? + .bind(&metrics_config.listen_addr)? + .to_tcp_listener()?, + SocketAddr::V6(_) => net2::TcpBuilder::new_v6()? + .only_v6(true)? + .bind(&metrics_config.listen_addr)? + .to_tcp_listener()?, + }; + let mut stream = TcpListener::from_std(std_socket, &Default::default())?; let concurrent_connections = Arc::new(AtomicU32::new(0)); loop { let (client, _client_addr) = stream.accept().await?; diff --git a/src/resolver.rs b/src/resolver.rs index a935009..e5b0778 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -18,7 +18,13 @@ pub async fn resolve_udp( tid: u16, has_cached_response: bool, ) -> Result, Error> { - let mut ext_socket = UdpSocket::bind(&globals.external_addr).await?; + let std_socket = match globals.external_addr { + SocketAddr::V4(_) => net2::UdpBuilder::new_v4()?.bind(&globals.external_addr)?, + SocketAddr::V6(_) => net2::UdpBuilder::new_v6()? + .only_v6(true)? + .bind(&globals.external_addr)?, + }; + let mut ext_socket = UdpSocket::from_std(std_socket, &Default::default())?; ext_socket.connect(&globals.upstream_addr).await?; dns::set_edns_max_payload_size(&mut packet, DNS_MAX_PACKET_SIZE as u16)?; let mut response; @@ -60,11 +66,14 @@ pub async fn resolve_tcp( tid: u16, ) -> Result, Error> { 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()?; + SocketAddr::V4(_) => net2::TcpBuilder::new_v4()? + .bind(&globals.external_addr)? + .to_tcp_stream()?, + SocketAddr::V6(_) => net2::TcpBuilder::new_v6()? + .only_v6(true)? + .bind(&globals.external_addr)? + .to_tcp_stream()?, + }; let mut ext_socket = TcpStream::connect_std(std_socket, &globals.upstream_addr, &Default::default()).await?; ext_socket.set_nodelay(true)?;