would eventually notice that the other half of the CHILD_SA pair has
not been deleted. Section 1.4 describes this case and notes that "a
node SHOULD regard half-closed connections as anomalous and audit
their existence should they persist", and continues that "if
connection state becomes sufficiently messed up, a node MAY close the
IKE_SA".
Another solution that has been proposed is to reply with an
INVALID_SPI notification that contains SPIb. This would explicitly
tell host B that the SA was not deleted, so host B could try deleting
it again later. However, this usage is not part of the IKEv2
specification and would not be in line with normal use of the
INVALID_SPI notification where the data field contains the SPI the
recipient of the notification would put in outbound packets.
Yet another solution would be to ignore req2 at this time and wait
until we have received resp1. However, this alternative has not been
fully analyzed at this time; in general, ignoring valid requests is
always a bit dangerous, because both endpoints could do it, leading
to a deadlock.
This document recommends the first alternative.
5.11.7. Rekeying a New CHILD_SA
Yet another case occurs when a CHILD_SA is rekeyed soon after it has
been created:
Host A Host B
-------- --------
send req1: [N(REKEY_SA,SPIa1)],
SA(..,SPIa2,..),.. -->
(lost) <-- send resp1: SA(..,SPIb2,..),..
<-- send req2: N(REKEY_SA,SPIb2),
SA(..,SPIb3,..),..
recv req2 <--
To host A, this looks like a request to rekey an SA that does not
exist. Like in the simultaneous rekeying case, replying with
NO_PROPOSAL_CHOSEN is probably reasonable:
send resp2: N(NO_PROPOSAL_CHOSEN) -->
recv resp1
5.11.8. Collisions with IKE_SA Rekeying
Another set of cases occurs when one peer starts rekeying the IKE_SA
at the same time the other peer starts creating, rekeying, or closing
a CHILD_SA. Suppose that host B starts creating a CHILD_SA, and soon
after, host A starts rekeying the IKE_SA:
Host A Host B
-------- --------
<-- send req1: SA,Ni1,TSi,TSr
send req2: SA,Ni2,.. -->
--> recv req2
What should host B do at this point? Replying as usual would seem
like a reasonable choice:
<-- send resp2: SA,Ni2,..
recv resp2 <--
send req3: D() -->
--> recv req3
Now, a problem arises: If host B now replies normally with an empty
Informational response, this will cause host A to delete state
associated with the IKE_SA. This means host B should stop
retransmitting req1. However, host B cannot know whether or not host
A has received req1. If host A did receive it, it will move the
CHILD_SA to the new IKE_SA as usual, and the state information will
then be out of sync.
It seems this situation is tricky to handle correctly. Our proposal
is as follows: if a host receives a request to rekey the IKE_SA when
it has CHILD_SAs in "half-open" state (currently being created or
rekeyed), it should reply with NO_PROPOSAL_CHOSEN. If a host
receives a request to create or rekey a CHILD_SA after it has started
rekeying the IKE_SA, it should reply with NO_ADDITIONAL_SAS.
The case where CHILD_SAs are being closed is even worse. Our
recommendation is that if a host receives a request to rekey the
IKE_SA when it has CHILD_SAs in "half-closed" state (currently being
closed), it should reply with NO_PROPOSAL_CHOSEN. And if a host
receives a request to close a CHILD_SA after it has started rekeying
the IKE_SA, it should reply with an empty Informational response.
This ensures that at least the other peer will eventually notice that
the CHILD_SA is still in "half-closed" state and will start a new
IKE_SA from scratch.
5.11.9. Closing and Rekeying the IKE_SA
The final case considered in this section occurs if one peer decides
to close the IKE_SA while the other peer tries to rekey it.
Host A Host B
-------- --------
send req1: SA(..,SPIa1,..),Ni1 -->
<-- send req2: D()
--> recv req1
recv req2 <--
At this point, host B should probably reply with NO_PROPOSAL_CHOSEN,
and host A should reply as usual, close the IKE_SA, and stop
retransmitting req1.
<-- send resp1: N(NO_PROPOSAL_CHOSEN)
send resp2: ()
If host A wants to continue communication with B, it can now start a
new IKE_SA.
5.11.10. Summary
If a host receives a request to rekey:
o a CHILD_SA pair that the host is currently trying to close: reply
with NO_PROPOSAL_CHOSEN.
o a CHILD_SA pair that the host is currently rekeying: reply as
usual, but prepare to close redundant SAs later based on the
nonces.
o a CHILD_SA pair that does not exist: reply with
NO_PROPOSAL_CHOSEN.
o the IKE_SA, and the host is currently rekeying the IKE_SA: reply
as usual, but prepare to close redundant SAs and move inherited
CHILD_SAs later based on the nonces.
o the IKE_SA, and the host is currently creating, rekeying, or
closing a CHILD_SA: reply with NO_PROPOSAL_CHOSEN.
o the IKE_SA, and the host is currently trying to close the IKE_SA:
reply with NO_PROPOSAL_CHOSEN.
If a host receives a request to close:
o a CHILD_SA pair that the host is currently trying to close: reply
without Delete payloads.
o a CHILD_SA pair that the host is currently rekeying: reply as
usual, with Delete payload.
o a CHILD_SA pair that does not exist: reply without Delete
payloads.
o the IKE_SA, and the host is currently rekeying the IKE_SA: reply
as usual, and forget about our own rekeying request.
o the IKE_SA, and the host is currently trying to close the IKE_SA:
reply as usual, and forget about our own close request.
If a host receives a request to create or rekey a CHILD_SA when it is
currently rekeying the IKE_SA: reply with NO_ADDITIONAL_SAS.
If a host receives a request to delete a CHILD_SA when it is
currently rekeying the IKE_SA: reply without Delete payloads.
5.12. Diffie-Hellman and Rekeying the IKE_SA
There has been some confusion whether doing a new Diffie-Hellman
exchange is mandatory when the IKE_SA is rekeyed.
It seems that this case is allowed by the IKEv2 specification.
Section 2.18 shows the Diffie-Hellman term (g^ir) in brackets.
Section 3.3.3 does not contradict this when it says that including
the D-H transform is mandatory: although including the transform is
mandatory, it can contain the value "NONE".
However, having the option to skip the Diffie-Hellman exchange when
rekeying the IKE_SA does not add useful functionality to the
protocol. The main purpose of rekeying the IKE_SA is to ensure that
the compromise of old keying material does not provide information
about the current keys, or vice versa. This requires performing the
Diffie-Hellman exchange when rekeying. Furthermore, it is likely
that this option would have been removed from the protocol as
unnecessary complexity had it been discussed earlier.
Given this, we recommend that implementations should have a hard-
coded policy that requires performing a new Diffie-Hellman exchange
when rekeying the IKE_SA. In other words, the initiator should not
propose the value "NONE" for the D-H transform, and the responder
should not accept such a proposal. This policy also implies that a
successful exchange rekeying the IKE_SA always includes the KEi/KEr
payloads.
(References: "Rekeying IKE_SAs with the CREATE_CHILD_SA exhange"
thread, Oct 2005. "Comments of
draft-eronen-ipsec-ikev2-clarifications-02.txt" thread, Apr 2005.)
6. Configuration Payloads
6.1. Assigning IP Addresses
Section 2.9 talks about traffic selector negotiation and mentions
that "In support of the scenario described in section 1.1.3, an
initiator may request that the responder assign an IP address and
tell the initiator what it is."
This sentence is correct, but its placement is slightly confusing.
IKEv2 does allow the initiator to request assignment of an IP address
from the responder, but this is done using configuration payloads,
not traffic selector payloads. An address in a TSi payload in a
response does not mean that the responder has assigned that address
to the initiator; it only means that if packets matching these
traffic selectors are sent by the initiator, IPsec processing can be
performed as agreed for this SA. The TSi payload itself does not
give the initiator permission to configure the initiator’s TCP/IP
stack with the address and use it as its source address.
In other words, IKEv2 does not have two different mechanisms for
assigning addresses, but only one: configuration payloads. In the
scenario described in Section 1.1.3, both configuration and traffic
selector payloads are usually included in the same message, and they
often contain the same information in the response message (see
Section 6.3 of this document for some examples). However, their
semantics are still different.
6.2. Requesting any INTERNAL_IP4/IP6_ADDRESS
When describing the INTERNAL_IP4/IP6_ADDRESS attributes, Section
3.15.1 says that "In a request message, the address specified is a
requested address (or zero if no specific address is requested)".
The question here is whether "zero" means an address "0.0.0.0" or a
zero-length string.
Earlier, the same section also says that "If an attribute in the
CFG_REQUEST Configuration Payload is not zero-length, it is taken as
a suggestion for that attribute". Also, the table of configuration
attributes shows that the length of INTERNAL_IP4_ADDRESS is either "0
or 4 octets", and likewise, INTERNAL_IP6_ADDRESS is either "0 or 17
octets".
Thus, if the client does not request a specific address, it includes
a zero-length INTERNAL_IP4/IP6_ADDRESS attribute, not an attribute
containing an all-zeroes address. The example in 2.19 is thus
incorrect, since it shows the attribute as
"INTERNAL_ADDRESS(0.0.0.0)".
However, since the value is only a suggestion, implementations are
recommended to ignore suggestions they do not accept; or in other
words, to treat the same way a zero-length INTERNAL_IP4_ADDRESS,
"0.0.0.0", and any other addresses the implementation does not
recognize as a reasonable suggestion.
6.3. INTERNAL_IP4_SUBNET/INTERNAL_IP6_SUBNET
Section 3.15.1 describes the INTERNAL_IP4_SUBNET as "The protected
sub-networks that this edge-device protects. This attribute is made
up of two fields: the first is an IP address and the second is a
netmask. Multiple sub-networks MAY be requested. The responder MAY
respond with zero or more sub-network attributes."
INTERNAL_IP6_SUBNET is defined in a similar manner.
This raises two questions: first, since this information is usually
included in the TSr payload, what functionality does this attribute
add? And second, what does this attribute mean in CFG_REQUESTs?
For the first question, there seem to be two sensible
interpretations. Clearly TSr (in IKE_AUTH or CREATE_CHILD_SA
response) indicates which subnets are accessible through the SA that
was just created.
The first interpretation of the INTERNAL_IP4/6_SUBNET attributes is
that they indicate additional subnets that can be reached through
this gateway, but need a separate SA. According to this
interpretation, the INTERNAL_IP4/6_SUBNET attributes are useful
mainly when they contain addresses not included in TSr.
The second interpretation is that the INTERNAL_IP4/6_SUBNET
attributes express the gateway’s policy about what traffic should be
sent through the gateway. The client can choose whether other
traffic (covered by TSr, but not in INTERNAL_IP4/6_SUBNET) is sent
through the gateway or directly to the destination. According to
this interpretation, the attributes are useful mainly when TSr
contains addresses not included in the INTERNAL_IP4/6_SUBNET
attributes.
It turns out that these two interpretations are not incompatible, but
rather two sides of the same principle: traffic to the addresses
listed in the INTERNAL_IP4/6_SUBNET attributes should be sent via
this gateway. If there are no existing IPsec SAs whose traffic
selectors cover the address in question, new SAs have to be created.
A couple of examples are given below. For instance, if there are two
subnets, 192.0.1.0/26 and 192.0.2.0/24, and the client’s request
contains the following:
CP(CFG_REQUEST) =
INTERNAL_IP4_ADDRESS()
TSi = (0, 0-65535, 0.0.0.0-255.255.255.255)
TSr = (0, 0-65535, 0.0.0.0-255.255.255.255)
Then a valid response could be the following (in which TSr and
INTERNAL_IP4_SUBNET contain the same information):
CP(CFG_REPLY) =
INTERNAL_IP4_ADDRESS(192.0.1.234)
INTERNAL_IP4_SUBNET(192.0.1.0/255.255.255.192)
INTERNAL_IP4_SUBNET(192.0.2.0/255.255.255.0)
TSi = (0, 0-65535, 192.0.1.234-192.0.1.234)
TSr = ((0, 0-65535, 192.0.1.0-192.0.1.63),
(0, 0-65535, 192.0.2.0-192.0.2.255))
In these cases, the INTERNAL_IP4_SUBNET does not really carry any
useful information. Another possible reply would have been this:
CP(CFG_REPLY) =
INTERNAL_IP4_ADDRESS(192.0.1.234)
INTERNAL_IP4_SUBNET(192.0.1.0/255.255.255.192)
INTERNAL_IP4_SUBNET(192.0.2.0/255.255.255.0)
TSi = (0, 0-65535, 192.0.1.234-192.0.1.234)
TSr = (0, 0-65535, 0.0.0.0-255.255.255.255)
This would mean that the client can send all its traffic through the
gateway, but the gateway does not mind if the client sends traffic
not included by INTERNAL_IP4_SUBNET directly to the destination
(without going through the gateway).
A different situation arises if the gateway has a policy that
requires the traffic for the two subnets to be carried in separate
SAs. Then a response like this would indicate to the client that if
it wants access to the second subnet, it needs to create a separate
SA:
CP(CFG_REPLY) =
INTERNAL_IP4_ADDRESS(192.0.1.234)
INTERNAL_IP4_SUBNET(192.0.1.0/255.255.255.192)
INTERNAL_IP4_SUBNET(192.0.2.0/255.255.255.0)
TSi = (0, 0-65535, 192.0.1.234-192.0.1.234)
TSr = (0, 0-65535, 192.0.1.0-192.0.1.63)
INTERNAL_IP4_SUBNET can also be useful if the client’s TSr included
only part of the address space. For instance, if the client requests
the following:
CP(CFG_REQUEST) =
INTERNAL_IP4_ADDRESS()
TSi = (0, 0-65535, 0.0.0.0-255.255.255.255)
TSr = (0, 0-65535, 192.0.2.155-192.0.2.155)
Then the gateway’s reply could be this:
CP(CFG_REPLY) =
INTERNAL_IP4_ADDRESS(192.0.1.234)
INTERNAL_IP4_SUBNET(192.0.1.0/255.255.255.192)
INTERNAL_IP4_SUBNET(192.0.2.0/255.255.255.0)
TSi = (0, 0-65535, 192.0.1.234-192.0.1.234)
TSr = (0, 0-65535, 192.0.2.155-192.0.2.155)
It is less clear what the attributes mean in CFG_REQUESTs, and
whether other lengths than zero make sense in this situation (but for
INTERNAL_IP6_SUBNET, zero length is not allowed at all!). This
document recommends that implementations should not include
INTERNAL_IP4_SUBNET or INTERNAL_IP6_SUBNET attributes in
CFG_REQUESTs.
For the IPv4 case, this document recommends using only netmasks
consisting of some amount of "1" bits followed by "0" bits; for
instance, "255.0.255.0" would not be a valid netmask for
INTERNAL_IP4_SUBNET.
It is also worthwhile to note that the contents of the INTERNAL_IP4/
6_SUBNET attributes do not imply link boundaries. For instance, a
gateway providing access to a large company intranet using addresses
from the 10.0.0.0/8 block can send a single INTERNAL_IP4_SUBNET
attribute (10.0.0.0/255.0.0.0) even if the intranet has hundreds of
routers and separate links.
(References: Tero Kivinen’s mail "Intent of couple of attributes in
Configuration Payload in IKEv2?", 2004-11-19. Srinivasa Rao
Addepalli’s mail "INTERNAL_IP4_SUBNET and INTERNAL_IP6_SUBNET in
IKEv2", 2004-09-10. Yoav Nir’s mail "Re: New I-D: IKEv2
Clarifications and Implementation Guidelines", 2005-02-07.
"Clarifications open issue: INTERNAL_IP4_SUBNET/NETMASK" thread,
April 2005.)
6.4. INTERNAL_IP4_NETMASK
Section 3.15.1 defines the INTERNAL_IP4_NETMASK attribute and says
that "The internal network’s netmask. Only one netmask is allowed in
the request and reply messages (e.g., 255.255.255.0) and it MUST be
used only with an INTERNAL_IP4_ADDRESS attribute".
However, it is not clear what exactly this attribute means, as the
concept of "netmask" is not very well defined for point-to-point
links (unlike multi-access links, where it means "you can reach hosts
inside this netmask directly using layer 2, instead of sending
packets via a router"). Even if the operating system’s TCP/IP stack
requires a netmask to be configured, for point-to-point links it
could be just set to 255.255.255.255. So, why is this information
sent in IKEv2?
One possible interpretation would be that the host is given a whole
block of IP addresses instead of a single address. This is also what
Framed-IP-Netmask does in [RADIUS], the IPCP "subnet mask" extension
does in PPP [IPCPSubnet], and the prefix length in the IPv6 Framed-
IPv6-Prefix attribute does in [RADIUS6]. However, nothing in the
specification supports this interpretation, and discussions on the
IPsec WG mailing list have confirmed it was not intended. Section
3.15.1 also says that multiple addresses are assigned using multiple
INTERNAL_IP4/6_ADDRESS attributes.
Currently, this document’s interpretation is the following:
INTERNAL_IP4_NETMASK in a CFG_REPLY means roughly the same thing as
INTERNAL_IP4_SUBNET containing the same information ("send traffic to
these addresses through me"), but also implies a link boundary. For
instance, the client could use its own address and the netmask to
calculate the broadcast address of the link. (Whether the gateway
will actually deliver broadcast packets to other VPN clients and/or
other nodes connected to this link is another matter.)
An empty INTERNAL_IP4_NETMASK attribute can be included in a
CFG_REQUEST to request this information (although the gateway can
send the information even when not requested). However, it seems
that non-empty values for this attribute do not make sense in
CFG_REQUESTs.
Fortunately, Section 4 clearly says that a minimal implementation
does not need to include or understand the INTERNAL_IP4_NETMASK
attribute, and thus this document recommends that implementations
should not use the INTERNAL_IP4_NETMASK attribute or assume that the
other peer supports it.
(References: Charlie Kaufman’s mail "RE: Proposed Last Call based
revisions to IKEv2", 2004-05-27. Email discussion with Tero Kivinen,
Jan 2005. Yoav Nir’s mail "Re: New I-D: IKEv2 Clarifications and
Implementation Guidelines", 2005-02-07. "Clarifications open issue:
INTERNAL_IP4_SUBNET/NETMASK" thread, April 2005.)
6.5. Configuration Payloads for IPv6
IKEv2 also defines configuration payloads for IPv6. However, they
are based on the corresponding IPv4 payloads and do not fully follow
the "normal IPv6 way of doing things".
A client can be assigned an IPv6 address using the
INTERNAL_IP6_ADDRESS configuration payload. A minimal exchange could
look like this:
CP(CFG_REQUEST) =
INTERNAL_IP6_ADDRESS()
INTERNAL_IP6_DNS()
TSi = (0, 0-65535, :: - FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF)
TSr = (0, 0-65535, :: - FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF)
CP(CFG_REPLY) =
INTERNAL_IP6_ADDRESS(2001:DB8:0:1:2:3:4:5/64)
INTERNAL_IP6_DNS(2001:DB8:99:88:77:66:55:44)
TSi = (0, 0-65535, 2001:DB8:0:1:2:3:4:5 - 2001:DB8:0:1:2:3:4:5)
TSr = (0, 0-65535, :: - FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF)
In particular, IPv6 stateless autoconfiguration or router
advertisement messages are not used; neither is neighbor discovery.
The client can also send a non-empty INTERNAL_IP6_ADDRESS attribute
in the CFG_REQUEST to request a specific address or interface
identifier. The gateway first checks if the specified address is
acceptable, and if it is, returns that one. If the address was not
acceptable, the gateway will attempt to use the interface identifier
with some other prefix; if even that fails, the gateway will select
another interface identifier.
The INTERNAL_IP6_ADDRESS attribute also contains a prefix length
field. When used in a CFG_REPLY, this corresponds to the
INTERNAL_IP4_NETMASK attribute in the IPv4 case (and indeed, was
called INTERNAL_IP6_NETMASK in earlier versions of the IKEv2 draft).
See the previous section for more details.
While this approach to configuring IPv6 addresses is reasonably
simple, it has some limitations: IPsec tunnels configured using IKEv2
are not fully-featured "interfaces" in the IPv6 addressing
architecture [IPv6Addr] sense. In particular, they do not
necessarily have link-local addresses, and this may complicate the
use of protocols that assume them, such as [MLDv2]. (Whether they
are called "interfaces" in some particular operating system is a
different issue.)
(References: "VPN remote host configuration IPv6 ?" thread, May 2004.
"Clarifications open issue: INTERNAL_IP4_SUBNET/NETMASK" thread,
April 2005.)
6.6. INTERNAL_IP6_NBNS
Section 3.15.1 defines the INTERNAL_IP6_NBNS attribute for sending
the IPv6 address of NetBIOS name servers.
However, NetBIOS is not defined for IPv6 and probably never will be.
Thus, this attribute most likely does not make much sense.
(Pointed out by Bernard Aboba in the IP Configuration Security (ICOS)
BoF at IETF62.)
6.7. INTERNAL_ADDRESS_EXPIRY
Section 3.15.1 defines the INTERNAL_ADDRESS_EXPIRY attribute as
"Specifies the number of seconds that the host can use the internal
IP address. The host MUST renew the IP address before this expiry
time. Only one of these attributes MAY be present in the reply."
Expiry times and explicit renewals are primarily useful in
environments like DHCP, where the server cannot reliably know when
the client has gone away. However, in IKEv2 this is known, and the
gateway can simply free the address when the IKE_SA is deleted.
Also, Section 4 says that supporting renewals is not mandatory.
Given that this functionality is usually not needed, we recommend
that gateways should not send the INTERNAL_ADDRESS_EXPIRY attribute.
(And since this attribute does not seem to make much sense for
CFG_REQUESTs, clients should not send it either.)
Note that according to Section 4, clients are required to understand
INTERNAL_ADDRESS_EXPIRY if they receive it. A minimum implementation
would use the value to limit the lifetime of the IKE_SA.
(References: Tero Kivinen’s mail "Comments of
draft-eronen-ipsec-ikev2-clarifications-02.txt", 2005-04-05.
"Questions about internal address" thread, April 2005.)
6.8. Address Assignment Failures
If the responder encounters an error while attempting to assign an IP
address to the initiator, it responds with an
INTERNAL_ADDRESS_FAILURE notification as described in Section 3.10.1.
However, there are some more complex error cases.
First, if the responder does not support configuration payloads at
all, it can simply ignore all configuration payloads. This type of
implementation never sends INTERNAL_ADDRESS_FAILURE notifications.