From 5e94a0f31e9ec6421593c179674fc196b05ad146 Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Wed, 22 Jun 2022 23:06:16 -0600 Subject: [PATCH 1/8] Add host address binding option --- src/config.rs | 13 +++++++++++++ src/wg.rs | 14 +++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/config.rs b/src/config.rs index eb48510..3292673 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,6 +19,7 @@ pub struct Config { pub(crate) private_key: Arc, pub(crate) endpoint_public_key: Arc, pub(crate) endpoint_addr: SocketAddr, + pub(crate) host_addr: Option, pub(crate) source_peer_ip: IpAddr, pub(crate) keepalive_seconds: Option, pub(crate) max_transmission_unit: usize, @@ -76,6 +77,12 @@ impl Config { .long("endpoint-addr") .env("ONETUN_ENDPOINT_ADDR") .help("The address (IP + port) of the WireGuard endpoint (remote). Example: 1.2.3.4:51820"), + Arg::with_name("host-addr") + .required(false) + .takes_value(true) + .long("host-addr") + .env("ONETUN_HOST_ADDR") + .help("The address (IP + port) for the tunnel to bind to. Example: 1.2.4:51820"), Arg::with_name("source-peer-ip") .required(true) .takes_value(true) @@ -237,6 +244,12 @@ impl Config { ), endpoint_addr: parse_addr(matches.value_of("endpoint-addr")) .with_context(|| "Invalid endpoint address")?, + host_addr: match matches.value_of("host-addr") { + Some(host_addr) => { + Some(parse_addr(Some(host_addr)).with_context(|| "Invalid host address")?) + } + None => None, + }, source_peer_ip, keepalive_seconds: parse_keep_alive(matches.value_of("keep-alive")) .with_context(|| "Invalid keep-alive value")?, diff --git a/src/wg.rs b/src/wg.rs index 1d06444..a55fd99 100644 --- a/src/wg.rs +++ b/src/wg.rs @@ -36,11 +36,15 @@ impl WireGuardTunnel { let source_peer_ip = config.source_peer_ip; let peer = Self::create_tunnel(config)?; let endpoint = config.endpoint_addr; - let udp = UdpSocket::bind(match endpoint { - SocketAddr::V4(_) => "0.0.0.0:0", - SocketAddr::V6(_) => "[::]:0", - }) - .await + let udp = if let Some(host) = config.host_addr { + UdpSocket::bind(host).await + } else { + UdpSocket::bind(match endpoint { + SocketAddr::V4(_) => "0.0.0.0:0", + SocketAddr::V6(_) => "[::]:0", + }) + .await + } .with_context(|| "Failed to create UDP socket for WireGuard connection")?; Ok(Self { From b108b5f404ff0f8024a3ade3a5182e1f97f36a11 Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Thu, 23 Jun 2022 22:47:33 -0600 Subject: [PATCH 2/8] Clarify help instructions for host binding --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.rs b/src/config.rs index 3292673..5629b02 100644 --- a/src/config.rs +++ b/src/config.rs @@ -82,7 +82,7 @@ impl Config { .takes_value(true) .long("host-addr") .env("ONETUN_HOST_ADDR") - .help("The address (IP + port) for the tunnel to bind to. Example: 1.2.4:51820"), + .help("The address (IP + port) used to bind the local UDP socket for the WireGuard tunnel. Example: 1.2.3.4:30000. Defaults to 0.0.0.0:0 for IPv4 endpoints, or [::]:0 for IPv6 endpoints."), Arg::with_name("source-peer-ip") .required(true) .takes_value(true) From 3ab108ad041e3fb95355ad4e485a00c3df7011ed Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Thu, 23 Jun 2022 22:59:19 -0600 Subject: [PATCH 3/8] Move host address resolution logic to config --- src/config.rs | 34 +++++++++++++++++++++++++--------- src/wg.rs | 11 ++--------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/config.rs b/src/config.rs index 5629b02..499ea3b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,7 +19,7 @@ pub struct Config { pub(crate) private_key: Arc, pub(crate) endpoint_public_key: Arc, pub(crate) endpoint_addr: SocketAddr, - pub(crate) host_addr: Option, + pub(crate) host_addr: SocketAddr, pub(crate) source_peer_ip: IpAddr, pub(crate) keepalive_seconds: Option, pub(crate) max_transmission_unit: usize, @@ -232,6 +232,28 @@ impl Config { .with_context(|| "Missing private key") }?; + let endpoint_addr = parse_addr(matches.value_of("endpoint-addr")) + .with_context(|| "Invalid endpoint address")?; + + let host_addr = if let Some(addr) = matches.value_of("host-addr") { + let addr = parse_addr(Some(addr)).with_context(|| "Invalid host address")?; + // Make sure the host address and endpoint address are the same IP version + if addr.ip().is_ipv6() && endpoint_addr.ip().is_ipv6() + || (addr.ip().is_ipv4() && endpoint_addr.ip().is_ipv4()) + { + return Err(anyhow::anyhow!( + "Host address and endpoint address must be the same IP version" + )); + } + addr + } else { + // Return the IP version of the endpoint address + match endpoint_addr { + SocketAddr::V4(_) => parse_addr(Some("0.0.0.0:0"))?, + SocketAddr::V6(_) => parse_addr(Some("[::]:0"))?, + } + }; + Ok(Self { port_forwards, remote_port_forwards, @@ -242,14 +264,8 @@ impl Config { parse_public_key(matches.value_of("endpoint-public-key")) .with_context(|| "Invalid endpoint public key")?, ), - endpoint_addr: parse_addr(matches.value_of("endpoint-addr")) - .with_context(|| "Invalid endpoint address")?, - host_addr: match matches.value_of("host-addr") { - Some(host_addr) => { - Some(parse_addr(Some(host_addr)).with_context(|| "Invalid host address")?) - } - None => None, - }, + endpoint_addr, + host_addr, source_peer_ip, keepalive_seconds: parse_keep_alive(matches.value_of("keep-alive")) .with_context(|| "Invalid keep-alive value")?, diff --git a/src/wg.rs b/src/wg.rs index a55fd99..3ee8ca7 100644 --- a/src/wg.rs +++ b/src/wg.rs @@ -36,16 +36,9 @@ impl WireGuardTunnel { let source_peer_ip = config.source_peer_ip; let peer = Self::create_tunnel(config)?; let endpoint = config.endpoint_addr; - let udp = if let Some(host) = config.host_addr { - UdpSocket::bind(host).await - } else { - UdpSocket::bind(match endpoint { - SocketAddr::V4(_) => "0.0.0.0:0", - SocketAddr::V6(_) => "[::]:0", - }) + let udp = UdpSocket::bind(config.host_addr) .await - } - .with_context(|| "Failed to create UDP socket for WireGuard connection")?; + .with_context(|| "Failed to create UDP socket for WireGuard connection")?; Ok(Self { source_peer_ip, From c647bc9a96b51e6e44998dfcc5dd376a0342c26f Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Thu, 23 Jun 2022 23:01:32 -0600 Subject: [PATCH 4/8] Rename host_addr to endpoint_bind_addr --- src/config.rs | 12 ++++++------ src/wg.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/config.rs b/src/config.rs index 499ea3b..490d90c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,7 +19,7 @@ pub struct Config { pub(crate) private_key: Arc, pub(crate) endpoint_public_key: Arc, pub(crate) endpoint_addr: SocketAddr, - pub(crate) host_addr: SocketAddr, + pub(crate) endpoint_bind_addr: SocketAddr, pub(crate) source_peer_ip: IpAddr, pub(crate) keepalive_seconds: Option, pub(crate) max_transmission_unit: usize, @@ -77,11 +77,11 @@ impl Config { .long("endpoint-addr") .env("ONETUN_ENDPOINT_ADDR") .help("The address (IP + port) of the WireGuard endpoint (remote). Example: 1.2.3.4:51820"), - Arg::with_name("host-addr") + Arg::with_name("endpoint-bind-addr") .required(false) .takes_value(true) - .long("host-addr") - .env("ONETUN_HOST_ADDR") + .long("endpoint-bind-addr") + .env("ONETUN_ENDPOINT_BIND_ADDR") .help("The address (IP + port) used to bind the local UDP socket for the WireGuard tunnel. Example: 1.2.3.4:30000. Defaults to 0.0.0.0:0 for IPv4 endpoints, or [::]:0 for IPv6 endpoints."), Arg::with_name("source-peer-ip") .required(true) @@ -235,7 +235,7 @@ impl Config { let endpoint_addr = parse_addr(matches.value_of("endpoint-addr")) .with_context(|| "Invalid endpoint address")?; - let host_addr = if let Some(addr) = matches.value_of("host-addr") { + let endpoint_bind_addr = if let Some(addr) = matches.value_of("endpoint-bind-addr") { let addr = parse_addr(Some(addr)).with_context(|| "Invalid host address")?; // Make sure the host address and endpoint address are the same IP version if addr.ip().is_ipv6() && endpoint_addr.ip().is_ipv6() @@ -265,7 +265,7 @@ impl Config { .with_context(|| "Invalid endpoint public key")?, ), endpoint_addr, - host_addr, + endpoint_bind_addr, source_peer_ip, keepalive_seconds: parse_keep_alive(matches.value_of("keep-alive")) .with_context(|| "Invalid keep-alive value")?, diff --git a/src/wg.rs b/src/wg.rs index 3ee8ca7..2bacc22 100644 --- a/src/wg.rs +++ b/src/wg.rs @@ -36,7 +36,7 @@ impl WireGuardTunnel { let source_peer_ip = config.source_peer_ip; let peer = Self::create_tunnel(config)?; let endpoint = config.endpoint_addr; - let udp = UdpSocket::bind(config.host_addr) + let udp = UdpSocket::bind(config.endpoint_bind_addr) .await .with_context(|| "Failed to create UDP socket for WireGuard connection")?; From 96e18edd190bcbd8072536d2e71fadab850a70e2 Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Thu, 23 Jun 2022 23:10:11 -0600 Subject: [PATCH 5/8] Invert logic for IP version mismatch --- src/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.rs b/src/config.rs index 490d90c..3a22e5d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -238,8 +238,8 @@ impl Config { let endpoint_bind_addr = if let Some(addr) = matches.value_of("endpoint-bind-addr") { let addr = parse_addr(Some(addr)).with_context(|| "Invalid host address")?; // Make sure the host address and endpoint address are the same IP version - if addr.ip().is_ipv6() && endpoint_addr.ip().is_ipv6() - || (addr.ip().is_ipv4() && endpoint_addr.ip().is_ipv4()) + if addr.ip().is_ipv6() != endpoint_addr.ip().is_ipv6() + || (addr.ip().is_ipv4() != endpoint_addr.ip().is_ipv4()) { return Err(anyhow::anyhow!( "Host address and endpoint address must be the same IP version" From 1680b17c4715d4153a60f7f8ce678a5c1d5c67ae Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Thu, 23 Jun 2022 23:10:48 -0600 Subject: [PATCH 6/8] Correct binding terminoligy IP version detection --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.rs b/src/config.rs index 3a22e5d..baf8b1d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -242,7 +242,7 @@ impl Config { || (addr.ip().is_ipv4() != endpoint_addr.ip().is_ipv4()) { return Err(anyhow::anyhow!( - "Host address and endpoint address must be the same IP version" + "Endpoint and bind addresses must be the same IP version" )); } addr From 9bd7ec2cca784cb0ebc46763c91d9a71f446cae7 Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Thu, 23 Jun 2022 23:11:45 -0600 Subject: [PATCH 7/8] Simplify IP version detection --- src/config.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/config.rs b/src/config.rs index baf8b1d..6b86428 100644 --- a/src/config.rs +++ b/src/config.rs @@ -238,9 +238,7 @@ impl Config { let endpoint_bind_addr = if let Some(addr) = matches.value_of("endpoint-bind-addr") { let addr = parse_addr(Some(addr)).with_context(|| "Invalid host address")?; // Make sure the host address and endpoint address are the same IP version - if addr.ip().is_ipv6() != endpoint_addr.ip().is_ipv6() - || (addr.ip().is_ipv4() != endpoint_addr.ip().is_ipv4()) - { + if addr.ip().is_ipv4() != endpoint_addr.ip().is_ipv4() { return Err(anyhow::anyhow!( "Endpoint and bind addresses must be the same IP version" )); From 4162f62ae67fde6887e8fdd375c8b650bbdae8f6 Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Thu, 23 Jun 2022 23:14:57 -0600 Subject: [PATCH 8/8] Change the error message from host to bind --- src/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.rs b/src/config.rs index 6b86428..ccae551 100644 --- a/src/config.rs +++ b/src/config.rs @@ -236,8 +236,8 @@ impl Config { .with_context(|| "Invalid endpoint address")?; let endpoint_bind_addr = if let Some(addr) = matches.value_of("endpoint-bind-addr") { - let addr = parse_addr(Some(addr)).with_context(|| "Invalid host address")?; - // Make sure the host address and endpoint address are the same IP version + let addr = parse_addr(Some(addr)).with_context(|| "Invalid bind address")?; + // Make sure the bind address and endpoint address are the same IP version if addr.ip().is_ipv4() != endpoint_addr.ip().is_ipv4() { return Err(anyhow::anyhow!( "Endpoint and bind addresses must be the same IP version"