Subject: [Mobike] Thoughts about issues 10/19: changing address vs. paths, and so on...

From: <[email-masked]>
Date: Thu, 3 Mar 2005 21:12:36 +0200

Hi all,

The recent discussions about issue #19 (same addresses for both
directions?) lead me to do some thinking about different ways
the tunnel header addresses for IPsec SAs can be chosen.

It seems that there are a couple of quite different approaches
to this (and some variations of those)... and I also have the
feeling that some of the text in the design draft and protocol
proposals has implicitly assumed one of these without really
making the assumption explicit.

Below I've gone through some of the approaches I've identified
so far, but there probably are others that make sense as well.

These aspects are also related to issue #17 (partial/full
connectivity)

-----

Option 1: "MOBIKE just informs the peer of our addresses; how 
they get used is a matter of local policy beyond our scope."

This would be the approach closest to SCTP, I think (and quite
close to the approach in Francis's and Tero's protocol
proposals, I think). The basic operation here would be as
follows: Host A sends a list of its addresses to B (and when the
list changes, sends either a new list or diffs to the previous
one).  And vice versa for B.

Host A selects the (tunnel header) src/dst addresses for its
IPsec SAs from its own list and the list it received from B in
any manner it wants. (Most likely this would somehow take into
account local policies and preferences, the order of addresses
in B's list, knowledge about connectivity or lack of it, etc.) 
And vice versa for B.

Or in other words, the situation looks something like this:

   Host A                           Host B
   ------                           -------

   List_A = (decided by A) -->

                                <-- List_B = (decided by B)

   src,dst = f_A(List_A, List_B,    src,dst = f_B(List_B, List_A,
                 local preferences,               local preferences,
                 local info about                 local info about
                 connectivity,                    connectivity,
                 whatever)                        whatever)

Where f_A() and f_B() can be basically anything.

Pros and cons:
+ Similar to SCTP
+ Symmetric behavior may make sense when the situation is 
  otherwise reasonably symmetric (such as site-to-site VPNs)
+ Handling partial connectivity and failures is reasonably clear: 
  if an address (interface) goes down, it is removed from the address 
  list. If the failure is in the "middle" (no connectivity, dpd fails), 
  the address lists don't change, but both parties choose address pairs 
  that work based on their own information.
- Failure detection and recovery has to be done by both parties, 
  possibly increasing complexity
- No guarantee that f_A() and f_B() choose the same address pair;
  this might not be desirable in e.g. "mobile client" case. 
  In particular, Host A can't move the "downstream" traffic
  (from B) to some particular interface (address) without
  deleting all the other addresses from List_A (unless we make 
  restrictions about f_A/f_B).
  
-----

Option 2: "Use the preferred/primary address"

It seems that at least some text in previous versions of the
design draft assumed that the address listed first in
List_A/List_B is the "primary" or "preferred" address that will
get used. We get this alternative by defining a very simple
f_A() and f_B() for option 1.

   Host A                           Host B
   ------                           -------

   List_A = (decided by A) -->

                                <-- List_B = (decided by B)

   src,dst = List_A[1],List_B[1]    src,dst = List_B[1],List_A[1]

Pros and cons:
+ Simple
+ Really simple for hosts that have a single static IP address
+ Symmetric behavior may make sense when the situation is 
  otherwise reasonably symmetric (such as site-to-site VPNs)
+ Same address pair used in both direction
- Connectivity information can be taken into account only
  when determining List_A/List_B: traffic can be on a path 
  that both ends know to be unworkable
- For instance, if both A and B have one IPv4 address and one 
  IPv6 address (and there's no v4/v6 translation), it's not clear 
  how traffic would be moved from one to the another. It seems that 
  the order of List_B has to depend on order of List_A which depends 
  on the order of List_B and so on: unless the protocol specifies 
  some tie-breaking mechanism (limits how the parties can choose 
  the order of List_A/List_B), we could even get a ping-pong effect.

-----

Option 3: "Initiator decides"

This is the approach chosen in MOPO-IKE.

   Host A                           Host B
   ------                           -------

   List_A = (decided by A) -->

                                <-- List_B = (decided by B)
  
   src,dst = f_A(List_A, List_B,      
                 local preferences,         
                 local info about
                 connectivity,
                 whatever) -->
                      
                                    src,dst = received from A

(BTW, in this approach Host B does not use List_A for updating
IPsec SAs at all; it's only used when List_B changes.)

Pros and cons:
+ Simple to handle partial connectivity and IPv4/v6 cases, without
  the danger of ping-pong or other unspecified aspects
+ Very simple for B (VPN gateway in "mobile client" case)
+ In mobile client case, the client probably has a better
  information about which addresses should be used. 
+ Same address pair used in both directions
+ Easier to work with NATs and stateful firewalls
- Asymmetric behavior, less elegant perhaps
- A's preferences win even in symmetric situations (site-to-site)

-----

Option 4: "Use the preferred/primary address if possible"

We can clearly refine the approach of option 2 by including
slightly more complicated f_A() and f_B(). For instance,

   Host A                           Host B
   ------                           -------

   List_A = (decided by A) -->

                                <-- List_B = (decided by B)

   src,dst =                        src,dst=
   if (List_A[1],List_B[1] works)   if(List_B[1],List_A[1] works)
     List_A[1],List_B[1]              List_B[1],List_A[1]
   else                             else
     f_A2(List_A, List_B,             f_B2(List_B, List_A,
          local preferences,               local preferences,
          local info about                 local info about
          connectivity,                    connectivity,
          whatever)                        whatever)

Pros and cons:
+ Often uses the same address pair in both directions 
- Almost as complex as option 1
- List_B still depends on List_A and vice versa in some
  unspecified way, just like option 2

-----

There are of course many other variations of option 1 that place
more or less restrictions of what f_A/f_B do and/or place
restrictions on how List_A/List_B are chosen.

But it seems that all the options involve some trade-offs and
none of them is clearly superior in all circumstances.  But
according to my understand, options 2 and 4 have important
missing pieces (how A and B choose the order of List_A/List_B
based on the other) that are needed before their merits can be
fully assessed. On the other hand, options 1 and 3 both seem to
be working alternatives, since in them the hosts don't have to
agree on f_A/f_B or choosing the order of List_A/List_B.

(BTW, most of the differences between the approaches occur only
when both parties have several addresses: otherwise, they're
pretty similar.)

These were just some initial thoughts, and comments are very 
welcome (as are variants of options 2 and 4 that fill in the 
missing pieces, and other variants).

Best regards,
Pasi
_______________________________________________
Mobike mailing list
[email-masked]
https://www.machshav.com/mailman/listinfo.cgi/mobike

---

From: Jari Arkko <[email-masked]>
Date: Thu, 03 Mar 2005 21:25:50 +0200

>Or in other words, the situation looks something like this:
If they are decoupled, it could also mean less complexity...
but they probably need to be coupled at least in some sense.
At least the "working pair" discovery protocol in
draft-ietf-multi6-failure-detection-00.txt needs a fairly close
sync between the operations on both sides.

>  restrictions about f_A/f_B).
Could this be a problem for firewall traversal?

>f_A() and f_B() for option 1.
Yes. To put it in other words, the working pair discovery
protocol needs to run first, and only then we can send
the lists.

>This is the approach chosen in MOPO-IKE.
This could be important.

>slightly more complicated f_A() and f_B(). For instance,
I would agree with this. Do people have a strong
preference between 1 and 3? I don't...

--Jari

---

From: Jari Arkko <[email-masked]>
Date: Fri, 04 Mar 2005 20:20:25 +0200

Thinking some more about this, I would actually like
to go for approach #3. This would simplify our protocol,
and would ensure an arhitecture where NAT and
firewall traversal can happen easily.

If make this decision, it seems that the following other
open issues would also be solved:

1 (direct or indirect indicators): Because one side is
responsible for the whole thing, we would have to
support failure detection using DPD at the initiator
side. Note that responder may still need to update its
own list of addresses now and then, say if an interface
goes down.

unassigned issue # (the list complaint that large SGWs
should not be forced to check the connectivity to clients):
The client would be doing all the work.

--Jari