-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for multiple listen sockets #27
Comments
Hi, I have a couple of questions for you (since you surely are more experienced with OpenBSD than I am):
use std::net::UdpSocket;
fn main() {
let ipv4 = "0.0.0.0:1024";
let ipv6 = ":::1024";
let v4socket = UdpSocket::bind(ipv4).unwrap();
let v6socket = UdpSocket::bind(ipv6).unwrap();
} /cc @emilengler @koraa |
Windows apparently also defaults to not being dual stack. So I see two options: either we introduce dynamic detection of dual-stack and on-demand adding of a second socket, or we just default to either IPv4 or IPv6 all-interface listening, while informing the user on how to change the default with an explicit |
|
We're currently not testing under openbsd; we should start to add the BSDs and Mac as supported platforms. The |
Ah, this might also explain why I couldn't get a tunnel to work on FreeBSD. It likely has the same behaviour. Treating this as a blocking issue for finishing the port. |
I think the following makes it work for me but I am not familiar with rust and as discussed it should break Linux. Index: src/main.rs
--- src/main.rs.orig
+++ src/main.rs
@@ -211,6 +211,7 @@ pub enum Verbosity {
pub struct AppServer {
pub crypt: CryptoServer,
pub sock: UdpSocket,
+ pub sock4: UdpSocket,
pub peers: Vec<AppPeer>,
pub verbosity: Verbosity,
}
@@ -449,6 +450,7 @@ impl AppServer {
Ok(Self {
crypt: CryptoServer::new(sk, pk),
sock: UdpSocket::bind(addr)?,
+ sock4: UdpSocket::bind("0.0.0.0:0")?,
peers: Vec::new(),
verbosity,
})
@@ -520,7 +522,10 @@ impl AppServer {
let p = $peer.get_app(self);
if let Some(addr) = p.tx_addr {
let len = $fn()?;
- self.sock.send_to(&tx[..len], addr)?;
+ match self.sock.send_to(&tx[..len], addr) {
+ Ok(x) => { x },
+ Err(_) => { self.sock4.send_to(&tx[..len], addr)? },
+ };
}
Ok(())
})
@@ -547,7 +552,10 @@ impl AppServer {
info!("error processing incoming message from {:?}: {:?} {}", addr, e, e.backtrace())),
Ok(HandleMsgResult { resp: Some(len), .. }) => {
- self.sock.send_to(&tx[0..len], addr)?
+ match self.sock.send_to(&tx[..len], addr) {
+ Ok(x) => { x },
+ Err(_) => { self.sock4.send_to(&tx[..len], addr)? },
+ };
},
Ok(HandleMsgResult { exchanged_with: Some(p), .. }) => {
@@ -634,7 +642,17 @@ impl AppServer {
}
self.sock
.set_read_timeout(Some(Duration::from_secs_f64(timeout)))?;
+ self.sock4
+ .set_read_timeout(Some(Duration::from_secs_f64(timeout)))?;
match self.sock.recv_from(buf) {
+ Ok(x) => return Ok(Some(x)),
+ Err(e) => match e.kind() {
+ ErrorKind::WouldBlock => {},
+ ErrorKind::TimedOut => {},
+ _ => return Err(anyhow::Error::new(e)),
+ },
+ };
+ match self.sock4.recv_from(buf) {
Ok(x) => Ok(Some(x)),
Err(e) => match e.kind() {
ErrorKind::WouldBlock => Ok(None), |
@moritzbuhl Thank you for your code contribution! Would you mind opening a PR? I don't think that code is what we will arrive, but it is a starting point for development. I think the correct thing to do is to have support for multiple I will also create a "BSD Support" meta ticket to track what needs to be done to fully support BSD. |
Hello, long-term OpenBSD Desktop user here. I have been learning network development on OpenBSD, so I am quite familiar with that issue :D The problem lies within the fact, that OpenBSDs IPv6 sockets ONLY support IPv6, not the IPv4 backwards compatibility. Unfortunately, most applications use the latter approach to do a dual stack. The OpenBSD way would be to create two sockets and set the IPv6 socket to Years ago, I was working on an OpenBSD-exclusive privilege-separated POP3-Daemon using dual-stack. The code looked like this: static void
net_sockets_init(uint16_t port)
{
struct sockaddr_in sa4;
struct sockaddr_in6 sa6;
if ((net_in4 = socket(AF_INET, SOCK_STREAM, 0)) == -1)
fatal("socket AF_INET");
if ((net_in6 = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
fatal("socket AF_INET6");
/* Portable code would require a setsockopt(2) here */
if (net_fd_nonblock(net_in4) == -1)
fatal("net_fd_nonblock AF_INET");
if (net_fd_nonblock(net_in6) == -1)
fatal("net_fd_nonblock AF_INET6");
/* Steps related for bind(2). */
memset(&sa4, 0, sizeof(sa4));
sa4.sin_family = AF_INET;
sa4.sin_port = htons(port);
sa4.sin_addr.s_addr = INADDR_ANY;
memset(&sa6, 0, sizeof(sa6));
sa6.sin6_family = AF_INET6;
sa6.sin6_port = htons(port);
sa6.sin6_addr = in6addr_any;
if (bind(net_in4, (struct sockaddr *)&sa4, sizeof(sa4)) == -1)
fatal("bind AF_INET");
if (bind(net_in6, (struct sockaddr *)&sa6, sizeof(sa6)) == -1)
fatal("bind AF_INET6");
if (listen(net_in4, 128) == -1)
fatal("listen AF_INET");
if (listen(net_in6, 128) == -1)
fatal("listen AF_INET6");
}
Yes
Yes, but in order to achieve compatibility with other systems, you have to make the IPv6 socket IPv6 only (default on OpenBSD). It requires a
I would not introduce conditional compilation. The dual socket approach that OpenBSD uses (one V6-only and one V4-only socket) works cross platform. Sure, it might add a tiny overhead, but having a common codebase across architectures is probably better. |
I see some problems with the multi-socket approach, foremost that we use
@koraa what is your call on this? The way I see it, our best option is either platform-dependent code (clean, but a high maintenance burden), async for the frontend or just a single listen address per rosenpass process and no happy non-v4-v6-dualstack users. |
There are |
I agree with @clausecker. |
I looked a little more into this. The correct way IMHO would be usin |
- adds TOML based configuation files - with example configuratios in config-examples - reimplments arcane CLI argument parser as automaton - adds a new CLI focused arround configuration files - moves all file utility stuff from `main.rs` to `util.rs` - moves all AppServer stuff to dedicated `app_server.rs` - add mio for multi-listen-socket support (should fix #27) - consistency: rename private to secret
- adds TOML based configuation files - with example configuratios in config-examples - reimplments arcane CLI argument parser as automaton - adds a new CLI focused arround configuration files - moves all file utility stuff from `main.rs` to `util.rs` - moves all AppServer stuff to dedicated `app_server.rs` - add mio for multi-listen-socket support (should fix #27) - consistency: rename private to secret
- adds TOML based configuation files - with example configuratios in config-examples - reimplments arcane CLI argument parser as automaton - adds a new CLI focused arround configuration files - moves all file utility stuff from `main.rs` to `util.rs` - moves all AppServer stuff to dedicated `app_server.rs` - add mio for multi-listen-socket support (should fix #27) - consistency: rename private to secret
- adds TOML based configuation files - with example configuratios in config-examples - reimplments arcane CLI argument parser as automaton - adds a new CLI focused arround configuration files - moves all file utility stuff from `main.rs` to `util.rs` - moves all AppServer stuff to dedicated `app_server.rs` - add mio for multi-listen-socket support (should fix #27) - consistency: rename private to secret
- adds TOML based configuation files - with example configuratios in config-examples - reimplments arcane CLI argument parser as automaton - adds a new CLI focused arround configuration files - moves all file utility stuff from `main.rs` to `util.rs` - moves all AppServer stuff to dedicated `app_server.rs` - add mio for multi-listen-socket support (should fix #27) - consistency: rename private to secret
- adds TOML based configuation files - with example configuratios in config-examples - reimplments arcane CLI argument parser as automaton - adds a new CLI focused arround configuration files - moves all file utility stuff from `main.rs` to `util.rs` - moves all AppServer stuff to dedicated `app_server.rs` - add mio for multi-listen-socket support (should fix #27) - consistency: rename private to secret
- adds TOML based configuation files - with example configuratios in config-examples - reimplments arcane CLI argument parser as automaton - adds a new CLI focused arround configuration files - moves all file utility stuff from `main.rs` to `util.rs` - moves all AppServer stuff to dedicated `app_server.rs` - add mio for multi-listen-socket support (should fix #27) - consistency: rename private to secret
Looking forwards to the next release! Will try another attempt at packaging then. |
I tried following this setup: https://rosenpass.eu/#start
Server: 192.168.2.107/24
Client: 192.168.2.106/24
However, I am getting this output from the client:
To my understanding this is because the socket the rosenpass binary is using for sendig is somehow bound for IPv6:
This unwrap_or makes the socket IPv6 since `listen` is not set for the client.To fix this, the client should bind a v4 socket too and depending on endpoint it should use that socket for sending.
Alternatively it could just try the v4 socket in case the v6 one failed.
I will look into implementing that but I have little knowledge on rust.
https://github.com/rosenpass/rosenpass/blob/main/src/main.rs#L356
Adding
listen
for the client makes it work with IPv4.Because the client is trying to send via an IPv6 socket, I tried just using IPv6 to connect to the server:
Server:
Client:
Now everything works, I can assign IP addresses to the wg/rosenpass interfaces and ping through them.
I had to adjust the rp script sligthly to make it work with OpenBSD, but I did not add any changes to the rosenpass binary:
https://github.com/moritzbuhl/mystuff/tree/master/net/rosenpass
The text was updated successfully, but these errors were encountered: