All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] Handling multiple endpoints for a single peer
@ 2017-01-08 22:41 Baptiste Jonglez
  2017-01-08 22:49 ` Jason A. Donenfeld
  2017-01-09  8:46 ` Ameretat Reith
  0 siblings, 2 replies; 11+ messages in thread
From: Baptiste Jonglez @ 2017-01-08 22:41 UTC (permalink / raw)
  To: wireguard

[-- Attachment #1: Type: text/plain, Size: 10274 bytes --]

Hi,

Here is a proposal for handling multiple endpoints for a single Wireguard
peer.  This includes handling dual-stack peers (IPv4 and IPv6) but is more
general.

This is something I had discussed with Jason at the beginning of the
project, but we agreed at the time that it was too early for the added
complexity.  It has since been requested several times on the mailing
list, and properly handling dual-stack is an important feature to have.

There is no code yet, the goal is to brainstorm possible methods.  Please
read and provide feedback on the specification, the use-cases and the
implementation suggestions (especially "Select new endpoint during each
handshake").  Sorry for the long email.


Problem
=======

Currently, Wireguard only allows a single Endpoint for a given peer,
where:

- Peer: remote computer implementing Wireguard, identified by its cryptographic public key.

- Endpoint: IP address and UDP port (written "IP:port") at which a Wireguard peer can be reached on the public Internet.

The big advantage of the current method is simplicity, because when
Wireguard needs to send an encrypted packet to a peer, it just sends the
packet to the (unique) endpoint of the peer.


Specification
=============

Allow multiple endpoints for the same Wireguard peer.  With the "wg
setconf" syntax [WG], it would look like this:

    [Peer]
    PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
    Endpoint = 192.95.5.67:1234, [2607:5300:60:6b0::c05f:543]:1234, myserver.dyndns.tld:1234, 192.168.1.42:1234
    AllowedIPs = 10.192.122.3/32, 10.192.124.1/24

Here, this peer (identified by its public key) has four different
endpoints:

- one public IPv4 address
- one public IPv6 address
- one hostname, which may resolve to multiple IPv4 and IPv6 addresses
- one private IPv4 address

When configuring the Wireguard kernel module itself, this information
would be translated to a list of IP:port entries.  To achieve this, each
hostname would be resolved to a list of IPv4 and IPv6 addresses by `wg`,
while IP addresses would be passed directly.


The decision of which endpoint to use for a given peer should be made
continuously during the entire lifetime of the Wireguard connection, and
not just when performing the initial connection.  This would allow to
handle events such as transient connectivity issues, performance
anomalies, mobility, etc.  It is also more consistent with the current
roaming functionality.

This decision could be based on either:

- simple connectivity: for instance, when an endpoint stops working, try
  another one;

- a performance metric: for instance, always use the endpoint with the
  lowest measured latency.

Moreover, the current roaming functionality should be preserved, at least
partially.  Currently, when a peer sends us a valid packet from a new
IP:port endpoint, we use this endpoint for all our subsequent outgoing
packets.


Use-cases
=========

## IPv4 and IPv6 cohabitation

In this case, one peer ("the server") is reachable via both IPv4 and IPv6.
Clients, on their physical network, may have IPv4-only connectivity,
IPv6-only connectivity, or dual-stack connectivity, and may move from one
such physical network to another.

For clients, it should be enough to use:

    Endpoint=myserver.tld:4242

where myserver.tld has both A and AAAA records.


## Server multi-homing

A peer may have multiple IPv4 or IPv6 addresses if it is multi-homed to
several networks (several ISPs).

In this case, clients could configure multiple endpoints for the peer:

    Endpoint=myserver.firstisp.tld:4242, myserver.secondisp.tld:4242

It is expected that Wireguard can always communicate with the peer even if
either one of the network path is broken (using fail-over to increase
reliability).  Also, it would be nice to select the endpoint based on a
performance metric (lowest RTT).

This also covers a use-case exposed on the mailing list [DYNDNS].


## Local and scope-dependent addressing

Let's assume my Wireguard server is at home, behind an IPv4 NAT or an IPv6
tunnel.  From the Internet, I want to use the public IPv4 or tunneled IPv6
as endpoint, but when I move to my local network, I want to use the
private IPv4 address.  This avoids connection failure if my home router
does not implement hairpinning (for IPv4) and avoids a potential
round-trip to the Internet (for tunneled IPv6).

In that case, I should be able to use:

    Endpoint=myserver.tld:4242, 192.168.1.100:4242

The connection to the private IP would not work while I am on a random
network, but once I connect to my home network, I expect Wireguard to
switch to the private IP endpoint.


Challenges
==========

The main problem to solve is that Wireguard would now have a choice to
make: when an encrypted packet needs to be sent towards a peer, what
destination address and UDP port should be used?  Currently, this task is
trivial since there is a 1-to-1 mapping between peer and endpoint.

This decision-making is difficult because Wireguard has access to very few
connectivity- or performance-related information.  For instance, Wireguard
currently cannot measure the RTT towards a given peer, except during the
handshake.  Even worse, Wireguard has no way to check that encrypted
packets are indeed received by the peer.  There is no acknowledgement
system at the level of Wireguard.  This means that dropped packets will
not be detected until the next handshake, which could create a temporary
blackhole.

It means that Wireguard is not in position to make informed decisions: it
needs to either delegate the decision to someone else, for instance a
user-space process, or find a way to have enough information to make
informed decisions itself.


Implementation suggestions
==========================

## Existing strategies

Choosing between IPv4 and IPv6 in a dual-stack environment is not new.
When IPv6 was not working very well, some people designed an algorithm
called "happy eyeballs" [HAPPYEYEBALLS].  A program basically tries to
connect over IPv4 and IPv6 quasi-simultaneously (with a small timing
advantage for IPv6), and chooses the address family based on the first
answer it receives.  If IPv6 works reasonably well, it will be used,
because it had a head-start of a few tens of milliseconds.  If IPv6 is
completely broken, then the connection will quickly fallback to IPv4.

The same idea could be used here to choose one of the multiple endpoints.
However, happy eyeballs is only used during connection establishment,
because the main use-case are short-lived connections like HTTP.  Here, we
would like Wireguard to switch to a new endpoint at any time, so that it
can react to changing network conditions.


## Select new endpoint during each handshake

This is perhaps the most clean and simple trade-off, and exploits the fact
that Wireguard regularly performs a new handshake with a peer:

- during the handshake, select the "best" endpoint
- while the symmetric key is in use (a few minutes), keep the same endpoint
- the roaming functionality can still update the current endpoint between two handshakes
- during the next handshake, repeat the procedure, potentially selecting a new endpoint

Selection of the "best" endpoint can be quite simple: send a handshake
packets to all endpoints simultaneously, and select the endpoint for which
the answer arrives the first.  This would select the endpoint with the
lowest RTT at this point in time.  To avoid switching endpoint too often,
the current endpoint can be given a slight advantage, similarly to happy
eyeballs: first send the handshake packet to the current endpoint, wait
e.g. 10 ms, and then send the handshake packet to all other endpoints.
This way, we switch to a new endpoint only if that would improve the RTT
by 10 ms.

It looks quite simple, but I am sure there would be a lot of
implementation difficulties:

- What if the remote peer always performs key exchange just before us?  We
  would never be able to try other endpoints.

- What should be the behaviour of the peer when it receives several
  handshake packets?  Should it reply to all of them? (probably, because
  of asymmetric RTT on Internet paths).  How would the peer select its own
  endpoint towards us?


Since Wireguard performs handshakes at relatively short intervals, this
method provides some amount of liveliness: if connectivity with the
current endpoint breaks (blackhole), it will be detected and corrected
within a few minutes.

Of course, there can be optimisations for cases with obvious lack of
connectivity.  For instance, if the current endpoint is an IPv6 address
and we are moving to a network with no IPv6 connectivity, trying to send
an IPv6 packet will result in an immediate error.  In this case, we would
immediately initiate a new handshake and use the IPv4 endpoint.
Similarly, if sending an encrypted packet elicits an ICMP error in
response (host or port unreachable), then we can initiate a new handshake
to test other endpoints.


## Extend Wireguard to perform measurements

Currently, Wireguard can already send traffic to a peer: persistent
keepalives.

There could be a new type of message ("ping" or "hearbeat" messages),
where Wireguard regularly solicits its peers through the encrypted
channel.  Wireguard could then use these messages to detect a connectivity
problem (packet loss) or a performance degradation (high RTT) towards a
peer, and try to use a new endpoint.


## Decision-making in userspace

An alternate solution is to use a userspace program to monitor
connectivity, and ask Wireguard to use a new endpoint if needed.  For
instance, a script could ping through the tunnel, and ask Wireguard to use
another random endpoint when it detects a problem.

A more elaborate solution would allow a userspace program to choose which
endpoint is used when sending a packet through Wireguard.  A daemon could
then use this feature to periodically ping the remote peer through the
tunnel using different endpoints, and based on the result, tell Wireguard
which endpoint it should use for the "regular" traffic.


References
==========

[WG] https://git.zx2c4.com/WireGuard/about/src/tools/wg.8
[HAPPYEYEBALLS] https://tools.ietf.org/html/rfc6555
[DYNDNS] https://lists.zx2c4.com/pipermail/wireguard/2017-January/000903.html

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] Handling multiple endpoints for a single peer
  2017-01-08 22:41 [RFC] Handling multiple endpoints for a single peer Baptiste Jonglez
@ 2017-01-08 22:49 ` Jason A. Donenfeld
  2017-01-09  2:37   ` Samuel Holland
                     ` (3 more replies)
  2017-01-09  8:46 ` Ameretat Reith
  1 sibling, 4 replies; 11+ messages in thread
From: Jason A. Donenfeld @ 2017-01-08 22:49 UTC (permalink / raw)
  To: Baptiste Jonglez; +Cc: WireGuard mailing list

Thanks for the proposal. Obviously the easiest solution is a userspace
decoupled one, but this might not necessarily be the most desirable.
However, it's possible the upcoming userspace event notification fd
support (epoll on an fd to learn when handshakes happen) and userspace
peer-message support (send an encrypted out of band non-IP packet
directly to a peer, for things like autoconfig) could play a nice role
in this.

But if it is in the kernel, the decision logic boils down essentially
to: there's a list of endpoints in a given order. Based on differing
metrics of success at differing points in time, the list gets
reordered, and packets are always sent to the top of the list. For
example, the list could be rotated or permutated on every handshake
retry. Or the various other RTT or routing metrics you mentioned
earlier.

However, this doesn't shine any light on the hardest problem: how to
update the list of addresses in a memory-bounded fashion. Right now,
if you receive an encrypted packet, the endpoint of that peer is
updated to the src address of that packet. With multi-endpoint, which
endpoint is updated? Is it simply appended to an ever-growing list of
recent endpoints? How to keep this clean and manageable?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] Handling multiple endpoints for a single peer
  2017-01-08 22:49 ` Jason A. Donenfeld
@ 2017-01-09  2:37   ` Samuel Holland
  2017-01-09  9:26     ` Baptiste Jonglez
  2017-01-15 10:12     ` Jason A. Donenfeld
  2017-01-09  7:00   ` Dave Taht
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 11+ messages in thread
From: Samuel Holland @ 2017-01-09  2:37 UTC (permalink / raw)
  To: Jason A. Donenfeld, Baptiste Jonglez; +Cc: WireGuard mailing list

Hello,

On 01/08/17 16:49, Jason A. Donenfeld wrote:
> However, this doesn't shine any light on the hardest problem: how to
> update the list of addresses in a memory-bounded fashion. Right now,
> if you receive an encrypted packet, the endpoint of that peer is
> updated to the src address of that packet. With multi-endpoint,
> which endpoint is updated? Is it simply appended to an ever-growing
> list of recent endpoints? How to keep this clean and manageable?

I think there should be a distinction between endpoint addresses
provided in explicit configuration and those discovered through roaming.
Presumably, users put those addresses in the configuration file because
they expect them to be relatively stable. So I think those endpoints
should always be remembered.

As for addresses learned from roaming, a simple solution is some form of
aging. If the endpoint is changing because the machine is physically
moving (e.g. to a different wireless network), it's not likely that
previous address:port combinations will work again in the future, except
for a few common locations (home, work). So there's not much reason to
remember more than the last few. On the other hand, consider a
fixed-location user whose IP only changes when the router reboots every
few months. In that case, there's no chance of even the last one or two
endpoints being reused. So a time-based aging seems more appropriate.
Assuming (for illustration) you pick an endpoint every handshake, then
"this endpoint hasn't been chosen in the last 50 handshakes" means it's
okay to forget about.

So: 1) always keep manually added endpoints, and 2) only keep a few
roaming endpoints, and drop them when they are unused for a while.


As a separate point, I have a use case that I haven't seen discussed
yet. I have a WireGuard peer at Site A with a public IP. I have two
peers, a desktop and a laptop, at Site B, both behind NAT. Both of them
are configured with the machine at Site A as their only peer. Often I
take the laptop offsite, and then traffic between the desktop and laptop
goes through Site A. Good. However, when I have them on the same local
network, I'd like them to communicate directly (avoiding the round trip
to Site A).

The problem is that, if I add the desktop and laptop as peers to each
other, they stop sending traffic through Site A at all. Thus, when they
are _not_ on the same network (so behind two different NATs, as opposed
to no NAT) they cannot communicate at all.

It would be nice to get the desktop and laptop able to directly
communicate (which is what we're discussing mostly in this thread), but,
as a fallback, it would be nice to be able to say "if you can't
handshake with the peer for this internal IP, send their traffic through
the peer with the next larger enclosing subnet of allowed IPs. Then the
peer with the public IP and the allowed IPs of 0.0.0.0/0 could act as a
hub for peers behind stricter NATs.


Thanks,
Samuel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] Handling multiple endpoints for a single peer
  2017-01-08 22:49 ` Jason A. Donenfeld
  2017-01-09  2:37   ` Samuel Holland
@ 2017-01-09  7:00   ` Dave Taht
  2017-01-09  9:47   ` Baptiste Jonglez
  2017-01-16 15:01   ` Dan Lüdtke
  3 siblings, 0 replies; 11+ messages in thread
From: Dave Taht @ 2017-01-09  7:00 UTC (permalink / raw)
  To: Jason A. Donenfeld; +Cc: WireGuard mailing list

As I mentioned on an earlier thread, a daydream of mine is to use up extra
ipv6 /64s to improve "fair queued" latency and eliminate head of line
blocking for individual flows.

So being able to dedicate an entire /64 as an endpoint

Endpoint=3Dmyserver.tld/64:4242

would lead to a major advance over conventional vpn technologies.



On Sun, Jan 8, 2017 at 2:49 PM, Jason A. Donenfeld <Jason@zx2c4.com> wrote:
> Thanks for the proposal. Obviously the easiest solution is a userspace
> decoupled one, but this might not necessarily be the most desirable.
> However, it's possible the upcoming userspace event notification fd
> support (epoll on an fd to learn when handshakes happen) and userspace
> peer-message support (send an encrypted out of band non-IP packet
> directly to a peer, for things like autoconfig) could play a nice role
> in this.
>
> But if it is in the kernel, the decision logic boils down essentially
> to: there's a list of endpoints in a given order. Based on differing
> metrics of success at differing points in time, the list gets
> reordered, and packets are always sent to the top of the list. For
> example, the list could be rotated or permutated on every handshake
> retry. Or the various other RTT or routing metrics you mentioned
> earlier.
>
> However, this doesn't shine any light on the hardest problem: how to
> update the list of addresses in a memory-bounded fashion. Right now,
> if you receive an encrypted packet, the endpoint of that peer is
> updated to the src address of that packet. With multi-endpoint, which
> endpoint is updated? Is it simply appended to an ever-growing list of
> recent endpoints? How to keep this clean and manageable?
> _______________________________________________
> WireGuard mailing list
> WireGuard@lists.zx2c4.com
> https://lists.zx2c4.com/mailman/listinfo/wireguard



--=20
Dave T=C3=A4ht
Let's go make home routers and wifi faster! With better software!
http://blog.cerowrt.org

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] Handling multiple endpoints for a single peer
  2017-01-08 22:41 [RFC] Handling multiple endpoints for a single peer Baptiste Jonglez
  2017-01-08 22:49 ` Jason A. Donenfeld
@ 2017-01-09  8:46 ` Ameretat Reith
  2017-01-15 10:17   ` Jason A. Donenfeld
  1 sibling, 1 reply; 11+ messages in thread
From: Ameretat Reith @ 2017-01-09  8:46 UTC (permalink / raw)
  To: wireguard

Another use case would be circumventing some crazy state backed firewalls
that drop or throttle -mostly UDP- connections having high bandwidths.  If
peer is being used as gateway and nameserver resolver, it can be used to
rotate server IPs too; yet another method to bypass kind of blockages.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] Handling multiple endpoints for a single peer
  2017-01-09  2:37   ` Samuel Holland
@ 2017-01-09  9:26     ` Baptiste Jonglez
  2017-01-15 10:12     ` Jason A. Donenfeld
  1 sibling, 0 replies; 11+ messages in thread
From: Baptiste Jonglez @ 2017-01-09  9:26 UTC (permalink / raw)
  To: Samuel Holland; +Cc: WireGuard mailing list

[-- Attachment #1: Type: text/plain, Size: 2075 bytes --]

On Sun, Jan 08, 2017 at 08:37:55PM -0600, Samuel Holland wrote:
> Hello,
> 
> On 01/08/17 16:49, Jason A. Donenfeld wrote:
> >However, this doesn't shine any light on the hardest problem: how to
> >update the list of addresses in a memory-bounded fashion. Right now,
> >if you receive an encrypted packet, the endpoint of that peer is
> >updated to the src address of that packet. With multi-endpoint,
> >which endpoint is updated? Is it simply appended to an ever-growing
> >list of recent endpoints? How to keep this clean and manageable?
> 
> I think there should be a distinction between endpoint addresses
> provided in explicit configuration and those discovered through roaming.
> Presumably, users put those addresses in the configuration file because
> they expect them to be relatively stable. So I think those endpoints
> should always be remembered.

I agree, it's not a hard problem.  Always keep explicitely configured
addresses, and keep at most X addresses discovered through roaming (where
X does not need to be much more than 1, 2 or 3).

> As a separate point, I have a use case that I haven't seen discussed
> yet. I have a WireGuard peer at Site A with a public IP. I have two
> peers, a desktop and a laptop, at Site B, both behind NAT. Both of them
> are configured with the machine at Site A as their only peer. Often I
> take the laptop offsite, and then traffic between the desktop and laptop
> goes through Site A. Good. However, when I have them on the same local
> network, I'd like them to communicate directly (avoiding the round trip
> to Site A).
> 
> The problem is that, if I add the desktop and laptop as peers to each
> other, they stop sending traffic through Site A at all. Thus, when they
> are _not_ on the same network (so behind two different NATs, as opposed
> to no NAT) they cannot communicate at all.

See the "## Local and scope-dependent addressing" point in my first email,
which unfortunately Jason forgot to quote.  Unless I'm mistaken, this is
exactly the use-case you describe here.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] Handling multiple endpoints for a single peer
  2017-01-08 22:49 ` Jason A. Donenfeld
  2017-01-09  2:37   ` Samuel Holland
  2017-01-09  7:00   ` Dave Taht
@ 2017-01-09  9:47   ` Baptiste Jonglez
  2017-01-15 10:06     ` Jason A. Donenfeld
  2017-01-16 15:01   ` Dan Lüdtke
  3 siblings, 1 reply; 11+ messages in thread
From: Baptiste Jonglez @ 2017-01-09  9:47 UTC (permalink / raw)
  To: Jason A. Donenfeld; +Cc: WireGuard mailing list

[-- Attachment #1: Type: text/plain, Size: 3351 bytes --]

On Sun, Jan 08, 2017 at 11:49:18PM +0100, Jason A. Donenfeld wrote:
> But if it is in the kernel, the decision logic boils down essentially
> to: there's a list of endpoints in a given order. Based on differing
> metrics of success at differing points in time, the list gets
> reordered, and packets are always sent to the top of the list.

This is not what I proposed.  Endpoints do not need to be ordered, and you
do not need to keep statistics about the past.  This path is precarious
because you will always have to balance between being overly conservative
(which means you won't react fast enough to new situations) and being
overly enthusiastic (which means that you will react to the slightest
insignificant change of your metric, impacting stability).

What I proposed is based on happy eyeballs, see an excerpt of my first
mail below:

On Sun, Jan 08, 2017 at 11:41:17PM +0100, Baptiste Jonglez wrote:
> ## Select new endpoint during each handshake
> 
> This is perhaps the most clean and simple trade-off, and exploits the fact
> that Wireguard regularly performs a new handshake with a peer:
> 
> - during the handshake, select the "best" endpoint
> - while the symmetric key is in use (a few minutes), keep the same endpoint
> - the roaming functionality can still update the current endpoint between two handshakes
> - during the next handshake, repeat the procedure, potentially selecting a new endpoint
> 
> Selection of the "best" endpoint can be quite simple: send a handshake
> packets to all endpoints simultaneously, and select the endpoint for which
> the answer arrives the first.  This would select the endpoint with the
> lowest RTT at this point in time.  To avoid switching endpoint too often,
> the current endpoint can be given a slight advantage, similarly to happy
> eyeballs: first send the handshake packet to the current endpoint, wait
> e.g. 10 ms, and then send the handshake packet to all other endpoints.
> This way, we switch to a new endpoint only if that would improve the RTT
> by 10 ms.
> 
> It looks quite simple, but I am sure there would be a lot of
> implementation difficulties:
> 
> - What if the remote peer always performs key exchange just before us?  We
>   would never be able to try other endpoints.
> 
> - What should be the behaviour of the peer when it receives several
>   handshake packets?  Should it reply to all of them? (probably, because
>   of asymmetric RTT on Internet paths).  How would the peer select its own
>   endpoint towards us?
> 
> 
> Since Wireguard performs handshakes at relatively short intervals, this
> method provides some amount of liveliness: if connectivity with the
> current endpoint breaks (blackhole), it will be detected and corrected
> within a few minutes.
> 
> Of course, there can be optimisations for cases with obvious lack of
> connectivity.  For instance, if the current endpoint is an IPv6 address
> and we are moving to a network with no IPv6 connectivity, trying to send
> an IPv6 packet will result in an immediate error.  In this case, we would
> immediately initiate a new handshake and use the IPv4 endpoint.
> Similarly, if sending an encrypted packet elicits an ICMP error in
> response (host or port unreachable), then we can initiate a new handshake
> to test other endpoints.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] Handling multiple endpoints for a single peer
  2017-01-09  9:47   ` Baptiste Jonglez
@ 2017-01-15 10:06     ` Jason A. Donenfeld
  0 siblings, 0 replies; 11+ messages in thread
From: Jason A. Donenfeld @ 2017-01-15 10:06 UTC (permalink / raw)
  To: Baptiste Jonglez; +Cc: WireGuard mailing list

On Mon, Jan 9, 2017 at 10:47 AM, Baptiste Jonglez
<baptiste@bitsofnetworks.org> wrote:
> This is not what I proposed.  Endpoints do not need to be ordered, and you

Sorry, I read too fast evidently. That's a nice suggestion, indeed, of
sending multiple handshakes and seeing which one arrives first. If the
same exact handshake packet is sent to multiple IP, only the first one
to arrive will actually be replied to, due to the anti-replay attack
prevention rejecting the ones that arrive later. This, then, makes
implementation quite simple. Wonderful. So then, as you wrote, the
symmetric session would use the IP from the handshake for the
duration.

I'm still struggling to come up with a satisfactory solution for how
to manage "learned" new IPs from the roaming, to prevent the list from
getting too large. Fixed size LRU cycling perhaps?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] Handling multiple endpoints for a single peer
  2017-01-09  2:37   ` Samuel Holland
  2017-01-09  9:26     ` Baptiste Jonglez
@ 2017-01-15 10:12     ` Jason A. Donenfeld
  1 sibling, 0 replies; 11+ messages in thread
From: Jason A. Donenfeld @ 2017-01-15 10:12 UTC (permalink / raw)
  To: Samuel Holland; +Cc: WireGuard mailing list

On Mon, Jan 9, 2017 at 3:37 AM, Samuel Holland <samuel@sholland.org> wrote:
> I think there should be a distinction between endpoint addresses
> provided in explicit configuration and those discovered through roaming.
> Presumably, users put those addresses in the configuration file because
> they expect them to be relatively stable. So I think those endpoints
> should always be remembered.
>
> As for addresses learned from roaming, a simple solution is some form of
> aging. If the endpoint is changing because the machine is physically
> moving (e.g. to a different wireless network), it's not likely that
> previous address:port combinations will work again in the future, except
> for a few common locations (home, work). So there's not much reason to
> remember more than the last few. On the other hand, consider a
> fixed-location user whose IP only changes when the router reboots every
> few months. In that case, there's no chance of even the last one or two
> endpoints being reused. So a time-based aging seems more appropriate.
> Assuming (for illustration) you pick an endpoint every handshake, then
> "this endpoint hasn't been chosen in the last 50 handshakes" means it's
> okay to forget about.
>
> So: 1) always keep manually added endpoints, and 2) only keep a few
> roaming endpoints, and drop them when they are unused for a while.

I don't like the complexity of adding that kind of distinction,
between explicit and learned addresses. I think in the end that will
prove to be confusing. But I like the idea of keeping track of metrics
and cycling out based on that.

> As a separate point, I have a use case that I haven't seen discussed
> yet. I have a WireGuard peer at Site A with a public IP. I have two
> peers, a desktop and a laptop, at Site B, both behind NAT. Both of them
> are configured with the machine at Site A as their only peer. Often I
> take the laptop offsite, and then traffic between the desktop and laptop
> goes through Site A. Good. However, when I have them on the same local
> network, I'd like them to communicate directly (avoiding the round trip
> to Site A).
>
> The problem is that, if I add the desktop and laptop as peers to each
> other, they stop sending traffic through Site A at all. Thus, when they
> are _not_ on the same network (so behind two different NATs, as opposed
> to no NAT) they cannot communicate at all.
>
> It would be nice to get the desktop and laptop able to directly
> communicate (which is what we're discussing mostly in this thread), but,
> as a fallback, it would be nice to be able to say "if you can't
> handshake with the peer for this internal IP, send their traffic through
> the peer with the next larger enclosing subnet of allowed IPs. Then the
> peer with the public IP and the allowed IPs of 0.0.0.0/0 could act as a
> hub for peers behind stricter NATs.

Right now the cryptokey routing is very strict. All entries must work
one-to-one, and they're always enforced and active when present. What
you're suggesting here is that the cryptokey routing table entries
would sort of "disappear" when there isn't a current handshake. That's
interesting; I'll give it some thought.

One thing that comes to mind is how to detect when the local LAN peer
comes back online there. Should wireguard just be trying to initiate a
new handshake _always_, and eventually it will succeed and promote the
cryptokey routing table entry to "active"?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] Handling multiple endpoints for a single peer
  2017-01-09  8:46 ` Ameretat Reith
@ 2017-01-15 10:17   ` Jason A. Donenfeld
  0 siblings, 0 replies; 11+ messages in thread
From: Jason A. Donenfeld @ 2017-01-15 10:17 UTC (permalink / raw)
  To: Ameretat Reith; +Cc: WireGuard mailing list

On Mon, Jan 9, 2017 at 9:46 AM, Ameretat Reith <ameretat.reith@gmail.com> wrote:
> Another use case would be circumventing some crazy state backed firewalls
> that drop or throttle -mostly UDP- connections having high bandwidths.  If
> peer is being used as gateway and nameserver resolver, it can be used to
> rotate server IPs too; yet another method to bypass kind of blockages.

That's another neat use case indeed. Baptiste's auto RTT-sensing idea
would automatically figure out which IPs the firewall has throttled.

(I suspect, however, that WireGuard isn't designed long term to deal
with state sponsored firewalls and such; it's fingerprintable, as
discussed earlier on the mailing list. Good approaches to building
"unblockable VPNs" probably include something like symmetric crypto
only, so that there's no protocol or handshake, with large random
nonces (XChaPoly), forming messages that are indistinguishable from
random, which are then massaged into resembling valid gzip'd data, and
then placed below a valid HTTP header on port 80... or something wild
like this.)

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] Handling multiple endpoints for a single peer
  2017-01-08 22:49 ` Jason A. Donenfeld
                     ` (2 preceding siblings ...)
  2017-01-09  9:47   ` Baptiste Jonglez
@ 2017-01-16 15:01   ` Dan Lüdtke
  3 siblings, 0 replies; 11+ messages in thread
From: Dan Lüdtke @ 2017-01-16 15:01 UTC (permalink / raw)
  To: Jason A. Donenfeld; +Cc: WireGuard mailing list

Hi,


> On 8 Jan 2017, at 23:49, Jason A. Donenfeld <Jason@zx2c4.com> wrote:
>=20
> (send an encrypted out of band non-IP packet
> directly to a peer, for things like autoconfig) could play a nice role
> in this.


This is highly interesting! I should undust my gcc probably.


> One thing that comes to mind is how to detect when the local LAN peer
> comes back online there. Should wireguard just be trying to initiate a
> new handshake _always_, and eventually it will succeed and promote the
> cryptokey routing table entry to "active"?

Something like RetryTimeout=3DX comes to mind. And immediately raises =
the question how it is different from PersistentKeepalive? The latter =
one is misused to achieve exactly this sometimes.

The concrete problem Samuel described is one that could be solved by =
scoped addressing. This may be too theoretical for the actual scenario =
and circumstances.


Cheers,

Dan=

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2017-01-16 14:51 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-08 22:41 [RFC] Handling multiple endpoints for a single peer Baptiste Jonglez
2017-01-08 22:49 ` Jason A. Donenfeld
2017-01-09  2:37   ` Samuel Holland
2017-01-09  9:26     ` Baptiste Jonglez
2017-01-15 10:12     ` Jason A. Donenfeld
2017-01-09  7:00   ` Dave Taht
2017-01-09  9:47   ` Baptiste Jonglez
2017-01-15 10:06     ` Jason A. Donenfeld
2017-01-16 15:01   ` Dan Lüdtke
2017-01-09  8:46 ` Ameretat Reith
2017-01-15 10:17   ` Jason A. Donenfeld

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.