Code Monkey home page Code Monkey logo

rosenpass's Issues

Rosenpass 1.0.0 release

To create a 1.0.0 release, we should create a blog post as well as a section for blog posts on the website explaining the recent developments and breaking changes we introduce.

Breaking changes:

  • Deprecation of ip command style interface (the interface is supported for now but will be removed in the future)

Features:

  • Configuration file support
  • BSD support

News:

  • TBD, needs discussions with each party about what can be publicly said

We should reintroduce the keygen command but mark it as deprecated and point out that we are going to remove it in a future release.

In the name of a smooth transition we should also rename the exchange-config command to exchange, detecting automatically which variant is called for.

This will allow us to deprecate the exchange command we currently have in favor of the new one using a configuration file.

OSKs written to outfile have no delimiter

Maybe it has been a design choice, but the OSKs written to the outfile are currently not delimited by something which we could easily parse (e.g. newline or \0-byte):

b64_writer(fopen_w(of)?).write_all(key.secret())?;

I've just finished building my testing code for performing handshakes in go-rosenpass:

https://github.com/stv0g/go-rosenpass/blob/f36f8421fbbacb57a05a78531af594d2708ebe76/interop_test.go#L28

Unfortunately this test is half broken, as I fail to parse the OSKs from outfile:

https://github.com/stv0g/go-rosenpass/actions/runs/5054666362/jobs/9069861180#step:11:30

As we can see, I fail to parse the key of the second handshake.

IPv6 cloning support: Gitlab mirror

We should provide an official gitlab mirror to support IPv6-only deployments.

See #64:

Why GitHub? What about IPv6-only nodes? Rosenpass is FLOSS. Is there a specific reason why GitHub, which is proprietary, is used then? Some FLOSS projects host Git instances themselves or use free ones like codeberg.org. I had several times in the past on IPv6-only nodes the problem to install Rust packages since Rust fetched the packages from GitHub. Does this problem exist with Rosenpass as well? Building rosenpass locally on an IPv6-only node is also impossible, as the source code would have to be downloaded from GitHub. If not switching from GitHub, is the plan to do a mirror on an IPv6 Git instance?

documentation: readability of getting started section

The Getting Started section on your website looks awesome but it could be easier to read for the typical ADHD programmer recipient:

  1. The section starts with an explanation which is rather distracting from the "getting started" part than contributing to it. --> Maybe put it further down on the page for the more interested reader?
  2. Each command is either executed on the "server" or the "client" and you mention this information in the text. --> Maybe put this information to the beginning of each command line like user@server:~$ or user@client:~$, potentially even in different colors.
  3. Some steps are documented as commands and some steps are documented in running text. --> Maybe use bullet points or any other method of itemization to visualize where one step ends and another one starts.

This is probably all not very urgent but I have witnessed time and time again how an "ADHD-friendly" README or "Getting Started" decides the game which tool gets used in the end and which one is ignored despite being a good tool.

Fix AUR `rosenpass-git` pkgbuild

  • Needed to adjust ulimit to have the tests succeed
  • Needed to adjust the package version filter to deal with the naming of release candidate versions
  • Needed to adjust the rust stack size
# Maintainer: Sven Friedrich (sven At autumnal Dot de) 
pkgname=rosenpass-git
_pkgname=rosenpass
pkgver=0.1.1
pkgrel=4
pkgdesc="formally verified and post-quantum secure VPN over WireGuard"
url="https://rosenpass.eu"
_git="https://github.com/rosenpass/${_pkgname}.git"
arch=(any)
license=(MIT APACHE)
makedepends=('cargo' 'git' 'cmake' 'pkg-config' 'rust-bindgen')
depends=('libsodium' 'gawk' 'wireguard-tools' 'findutils')
provides=('rp' 'rosenpass')
conflicts=()
source=("${_pkgname}::git+${_git}")
sha256sums=('SKIP')
options=(!lto)

_bin=rosenpass
_script=rp

pkgver() {
    cd "${_pkgname}"
    cargo pkgid rosenpass | grep -oE "[^#]+$" | tr -d '-'
}

prepare() {
    cd "${_pkgname}"
    cargo fetch --locked --target $CARCH-unknown-linux-gnu
    ulimit -s 8192000
    export RUST_MIN_STACK=33554432000
    export RUST_BACKTRACE=1
}

build() {
    cd "${_pkgname}"
    cargo build --release --frozen
}

check() {
    cd "${_pkgname}"
    cargo test --frozen
}

package() {
    cd "${_pkgname}"
    install -Dm 0755 "target/release/${_bin}" "${pkgdir}/usr/bin/${_bin}"
    install -Dm 0755 "${_script}" "${pkgdir}/usr/bin/${_script}"
    install -Dm 0644 LICENSE-MIT "${pkgdir}/usr/share/licenses/${_pkgname}/LICENSE-MIT"
    install -Dm 0644 LICENSE-APACHE "${pkgdir}/usr/share/licenses/${_pkgname}/LICENSE-APACHE"
}

(homepage) Redirect from http:// to https://

(not sure, whether this is the correct place to report this, but since it's the only repository, I'll do it nonetheless.)

A recent toot from the official Rosenpass account links to http://rosenpass.eu, likely by accident. And even though Firefox and other browsers do have a "use HTTPS by default" mode, not every browser has that as of today.

For example, I've opened the toot on my iPhone which opened the page using only HTTP. For a basic web page I wouldn't care. But Rosenpass is quite different and I think it would be beneficial to redirect all HTTP requests to the HTTPS version.

Furthermore, I'd recommend to enable the preload directive in the Strict-Transport-Security header, so that Rosenpass can be submitted do the HSTS Preload list.

(and thanks again for the nice talk at the #eh20, really enjoyed it! ☺️)

Should support unbundling liboqs and others

For packaging this project in distributions, dependencies on C and C++ libraries should have the option to unbundle them. This enables distributions to find and fix bugs in these dependencies.

Questions / Why should you use rosenpass?

Hello,

I have some questions. Since I was reluctant to write an email, but I have not found another place, I thought I open an issue. If this is the wrong place for it, I apologize.
My questions would be as follows:

  1. Questions outside of issues and direct emails Is there some sort of forum or space where people can exchange ideas and ask questions about the Rosenpass? (Mailling List, Forum, IRC, Matrix, XMPP).

  2. Rosenpass PSK vs. WireGuard PSK As far as I know WireGuard, WireGuard already has a PSK feature. Why should one use Rosenpass? As far as I understand, the only advantage would be that Rosenpass renews the PSK every two minutes. Is that correct? As a cryptograhie dummy: Does this bring anything?

  3. How does it works? How does Rosenpass negotiate the PSK? As I understand it, Rosenpass also uses asymmetric keys like WireGuard, right? And then negotiates this accordingly securely using a separate UDP port? Do the asymmetric keys that Rosenpass uses have the same format as the asymmetric keys of WireGuard?

  4. wg-quick and Post Statments Is it possible to integrate Rosenpass with wg-quick? Is it possible to create configuration files (like for wg-quick) for Rosenpass in which you can also enter PostUp and PostDown statements?

  5. Why GitHub? What about IPv6-only nodes? Rosenpass is FLOSS. Is there a specific reason why GitHub, which is proprietary, is used then? Some FLOSS projects host Git instances themselves or use free ones like codeberg.org. I had several times in the past on IPv6-only nodes the problem to install Rust packages since Rust fetched the packages from GitHub. Does this problem exist with Rosenpass as well? Building rosenpass locally on an IPv6-only node is also impossible, as the source code would have to be downloaded from GitHub. If not switching from GitHub, is the plan to do a mirror on an IPv6 Git instance?

$ git clone https://github.com/rosenpass/rosenpass.git
Cloning into 'rosenpass'...
fatal: unable to access 'https://github.com/rosenpass/rosenpass.git/': Couldn't connect to server

Simplify deployment of Rosenpass by providing unit files and other things

I am using the following configuration files in my own Rosenpass VPN setup; we should provide the unit files as part of the installation and a template of the script to get a setup running. @wucke13 what is the best way to do this?

Client script -- /etc/rosenpass//start.sh

#! /usr/bin/env bash

set -e
cd "$(dirname "$0")"

(
  # Wait until the interface becomes available
  until ip l show rp0 >/dev/null 2>/dev/null; do sleep 0.1; done

  # Configure IP addresses
  ip a add <client-ipv4>/<ipv4-net> dev rp0
  ip a add <client-ipv6>/<ipv6-net> dev rp0
  ip route add <some-random-ipv4-route-I-use> via <server-ipv4>
  ip route add <some-random-ipv6-route-I-use> via <server-ipv6>

  # Wait until the network becomes available
  until ping -c 3 <server-ipv6> do sleep 1; done

  # Configure DNS
  resolvectl flush-caches
  resolvectl dns rp0 <server-dns>
  resolvectl domain rp0 '~<server>'
  #resolvectl dnssec rp0 
  resolvectl dnsovertls rp0 false
  resolvectl cache rp0 false
  #resolvectl default-route rp0 true
) &

exec rp \
  verbose explain \
  exchange <client>.rpsecret dev rp0 \
    peer <server>.rppub \
      endpoint <server>:26581 \
      allowed-ips fe80::/64,<ipv4-prefix>/<subnet>,<ipv4-prefix>/<subnet>

Server script -- /etc/rosenpass//start.sh

#! /usr/bin/env bash

set -e
cd "$(dirname "$0")"

# Config
(
  # Wait until the interface becomes available
  until ip l show rp0 >/dev/null 2>/dev/null; do sleep 0.1; done

  # Configure IP address
  ip a add <server-ipv4>/<subnet> dev rp0
  ip a add <server-ipv6>/<subnet> dev rp0
) &

exec rp \
  verbose explain \
  exchange <server>.rpsecret dev rp0 listen '[::]:26581' \
    peer <client>.rppub/ \
      allowed-ips fe80::/64,<client-ipv4>/32,<client-ipv6>/128

Group unit -- /etc/systemd/system/rosenpass.service

[Unit]
Description=Rosenpass VPN
After=network.target
Wants=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecReload=/bin/true
WorkingDirectory=/etc/rosenpass

[Install]
WantedBy=multi-user.target

Template unit -- /etc/systemd/system/[email protected]

[Unit]
PartOf=rosenpass.service
ReloadPropagatedFrom=rosenpass.service

[Service]
Type=simple
WorkingDirectory=/etc/rosenpass/%i
ExecStart=/etc/rosenpass/%i/start.sh
KillMode=mixed
Restart=on-failure
RestartSec=5
TimeoutStopSec=5

[Install]
WantedBy=rosenpass.service

Whitepaper proof read

I've started to work on a Golang implementation of the Rosenpass key exchange1.
While implementing it, I stumbled over some confusing parts in the whitepaper:

Variables / message fields mac, cookie, ini_enc & res_enc

Figure 3 shows the output variables mac and cookie which apparently should be included in a message envelope (Figure 2).
But I find no mention about use of the mac and cookie variable elsewhere in the whitepaper.

Apart from the osk two more output variables are generated after the completion of the handshake: ini_enc & res_enc
What is their purpose?

Message types: Data & CookieReply

Figure 2 shows these two message types. But they are nowhere described or used?

Live session state

Section 2.4.4 covers some variables which are not described and used in the handshake?

  • txkm – Our transmission key
  • txnm – Our transmission nonce
  • sidt – Peer’s session ID (“theirs”)
  • txkt – Peer’s transmission key
  • txnt – Peer’s transmission nonce

Enter live helper

What is the purpose of the enter_live helper function mentioned in section 2.5?
It appears also not to be used?

How are the roles of initiator / responder assigned?

WireGuard has no designated server/client as both sides are treated equal.
How does Rosenpass decide which side initiates the key exchange?

Status

Footnotes

  1. https://github.com/stv0g/go-rosenpass

CI is failing on main due to nix issues

I don't think these problems have anything with the recently merged documentation change

Failed to load /nix/store/7habp8pc2jwvv17v6kx8wlidndxskqpb-dotnet-runtime-6.0.15/shared/Microsoft.NETCore.App/6.0.15/libcoreclr.so, error: /nix/store/5lp5v0sa76mhvc42bdc4z8vxwysp18r9-gcc-11.3.0-lib/lib/libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by /nix/store/vl893j5kphwcnqyf3qrxcmmjc8zrfa5q-icu4c-72.1/lib/libicuuc.so)

Online version of the manual page

Manual pages in the mdoc(7) format can be rendered by various tools, such as groff(1) and (my favorite) mandoc(1). Example

I personally think, that we should provide such a thing as well.

Integration tests calling the `rp` script

Ensuring that any changes to the rosenpass command remain compatible with the rp script is paramount to ensure the software.

Please add an integration test that calls the rp command and checks whether a VPN can be created.

The integration tests should also cover triggering the cookie reply mechanism (#142 )

FreeBSD CI environment

We should have a FreeBSD integration test as part of our CI setup to fully support FreeBSD.

ability to use ports for wireguard that aren't N+1

there should be a possibility to use non N+1 ports for the created wireguard tunnel.
This should then be configurable in via the command line (or in a config file once a config format will get specified)

(it is possible to manually set the wireguard listen-port /peer port after creating the interface, but that requires an additional command )

Reliable dual stack setups

My server has two public ips; I might use the following specification to listen on both public facing ips on port 5555: listen '95.216.24.30:55555' listen '[2a01:4f9:2a:1861::2]:55555'

If instead I wanted to listen on all IPs, I might use to specify the port: listen '0.0.0.0:55555' listen '[::]:55555'.

The latter would raise an error on linux systems since listen '[::]:55555' will have rosenpass listen on both IPv4 and IPv6 addresses, port 55555 due to the dual-stack feature on those systems.

We should introduce a listen-all 55555 option that will listen on any available address, port 55555. Additionally, we should automatically detect any-interface listen specifications for both ipv4 and ipv6 bind-all addresses and automatically handle dual-stack setups on all platforms (in this case rosenpass should behave as if listen-all was given.

CI is failing

The nix runners on the CI are failing for some reason; I think these might be false positives but they do make us look bad. Running for prolonged times with a read CI also establishes a culture of disregarding the CI output which can lead to real bugs being introduced. Please make sure that the CI is green if the code on main is acceptable as it is.

Allow multiple endpoints

We should allow the ability to configure multiple endpoints for a peer, probing them sequentially.
We should also add the ability to probe those addresses again in case the connection fails so we can recover from some errors.

We should also add the ability, to remember past addresses used by a peer and try those again in case of failure.

@wucke13 This is a UX feature :)

Support for absolute paths in rp

The rp shell script parses directories using skdir="${1/\//}", likely to make sure the directory name does not contain a trailing slash.

It evades me how I overlooked, that this would prohibit the use of actual paths.

Windows support

We do not wish to support GUI windows based setups; we do wish to support command line based ones.

Port for rp script to support FreeBSD and OpenBSD

The rp script requires the Linux-only ip command and seems to be very specific to the Linux implementation of Wireguard. It will not work on FreeBSD and others. For the FreeBSD port, I'll probably have to rewrite it somewhat.

Use internal man page

While reviewing #53 , I noticed that the man invocation feature would fail to use the man command since I did not have the man page installed on my system. The feature would also show the system man page even if the system RP is different from the version I just compiled.

Both issues could be solved by including the man page source in the binary and doing the equivalent of:

cat doc/rosenpass.1 | man /dev/stdin

Support for multiple listen sockets

I tried following this setup: https://rosenpass.eu/#start

Server: 192.168.2.107/24

rp exchange 192.168.2.107-sec dev rosenpass0 listen 192.168.2.107:9999 peer 192.168.2.106-pub allowed-ips 192.168.123.0/24

Client: 192.168.2.106/24

rp exchange 192.168.2.106-sec dev rosenpass0 peer 192.168.2.107-pub endpoint 192.168.2.107:9999 allowed-ips 192.168.123.0/24

However, I am getting this output from the client:

[2023-03-14T20:59:57Z ERROR rosenpass] unexpected error after processing 0 messages: Address family not supported by protocol family (os error 47) disabled backtrace
[2023-03-14T20:59:57Z ERROR rosenpass] reinitializing networking in 0.01! 10 tries left.
[2023-03-14T20:59:57Z ERROR rosenpass] unexpected error after processing 0 messages: Address family not supported by protocol family (os error 47) disabled backtrace
[2023-03-14T20:59:57Z ERROR rosenpass] reinitializing networking in 0.02! 9 tries left.
[2023-03-14T20:59:58Z ERROR rosenpass] unexpected error after processing 0 messages: Address family not supported by protocol family (os error 47) disabled backtrace
[2023-03-14T20:59:58Z ERROR rosenpass] reinitializing networking in 0.04! 8 tries left.
[2023-03-14T20:59:59Z ERROR rosenpass] unexpected error after processing 0 messages: Address family not supported by protocol family (os error 47) disabled backtrace
[2023-03-14T20:59:59Z ERROR rosenpass] reinitializing networking in 0.08! 7 tries left.
...

To my understanding this is because the socket the rosenpass binary is using for sendig is somehow bound for IPv6:

 98150 rosenpass CALL  socket(AF_INET6,0x8002,0)
 98150 rosenpass RET   socket 3
 98150 rosenpass CALL  bind(3,0x7f7ffffd19a8,28)
 98150 rosenpass STRU  struct sockaddr { AF_INET6, [::]:0 }
 98150 rosenpass RET   bind 0
...
 98150 rosenpass CALL  sendto(3,0x7f7ffffd24b0,0x444,0x400,0x7f7ffffd1a30,0x10)
 98150 rosenpass STRU  struct sockaddr { AF_INET, 192.168.2.107:9999 }
 98150 rosenpass RET   sendto -1 errno 47 Address family not supported by protocol family
 98150 rosenpass CALL  write(2,0x878b524c500,0xd9)
 98150 rosenpass GIO   fd 2 wrote 217 bytes
       "\^[[0m\^[[38;5;8m[\^[[0m2023-03-14T20:59:57Z \^[[0m\^[[1m\^[[31mERROR\
        \^[[0m rosenpass\^[[0m\^[[38;5;8m]\^[[0m unexpected error after proces\
        sing 0 messages: Address family not supported by protocol family (os e\
        rror 47) disabled backtrace
       "
 98150 rosenpass RET   write 217/0xd9
 98150 rosenpass CALL  write(2,0x878b524c500,0x8c)
 98150 rosenpass GIO   fd 2 wrote 140 bytes
       "\^[[0m\^[[38;5;8m[\^[[0m2023-03-14T20:59:57Z \^[[0m\^[[1m\^[[31mERROR\
        \^[[0m rosenpass\^[[0m\^[[38;5;8m]\^[[0m reinitializing networking in \
        0.01! 10 tries left.
       "
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:

rp exchange 192.168.2.107-sec dev rosenpass0 listen fe80::fce1:bbff:fed1:3a06%vio0:9999 peer 192.168.2.106-pub allowed-ips 192.168.123.0/24

Client:

rp exchange 192.168.2.106-sec dev rosenpass0 peer 192.168.2.107-pub endpoint fe80::fce1:bbff:fed1:3a06%vio0:9999 allowed-ips 192.168.123.0/24

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

Exchanged key deviates after few minutes

Steps to reproduce:

user@device /t/xx> sudo rp exchange private-key ./priv public-key ./pub listen 127.0.0.1:11000 verbose peer public-key ./server.rosenpass-secret/pqpk endpoint localhost:9999 outfile z
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
[2023-04-10T13:23:10Z ERROR rosenpass] unexpected error after processing 0 messages: Operation not permitted (os error 1) disabled backtrace
[2023-04-10T13:23:10Z ERROR rosenpass] reinitializing networking in 0.01! 10 tries left.
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
[2023-04-10T13:25:10Z ERROR rosenpass] unexpected error after processing 0 messages: Operation not permitted (os error 1) disabled backtrace
[2023-04-10T13:25:10Z ERROR rosenpass] reinitializing networking in 0.02! 9 tries left.
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
[ Starting from here the exchange keys are different ]
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
output-key peer n/LOYinpheqmIs0IjwSXmof+3n8FBWx+GYcaVcjm4xI= key-file z exchanged
  • Peer 2:
user@device /t/xx> sudo rp exchange private-key ./server.rosenpass-secret/pqsk public-key ./server.rosenpass-secret/pqpk listen 127.0.0.1:9999 verbose peer public-key pub endpoint 127.0.0.1:11000 outfile f
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged
output-key peer 9b23kJf7Rf1OzFJTgoZEqxCrFQgz2aYUzd5GbrZXiwE= key-file f exchanged

Observing exchanged key written to file f and z in third terminal:

after few minutes the keys are different

Every 2,0s: sha256sum f z          device: Mon Apr 10 15:27:53 2023

098eecd8eaa2785135ea4b69301e44caca0f6913520cb3bd300c9fb616c3980e  f
90508b25177c8ee528b45cfa9de7c0a9533e9788f1b8245626da70cca9184842  z

I think it is because both peers know the endpoint of the other and initiate the key exchange at the same time, which would also explain the error messages and that the first 2 exchanges run within 3 seconds.
If i remove the endpoint argument one side of the peers, it seems to work durable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.