[c-nsp] Tunnel keepalive in NAT environment problem
Brett Frankenberger
rbf+cisco-nsp at panix.com
Tue Nov 18 13:48:51 EST 2008
On Tue, Nov 18, 2008 at 02:03:08PM +0100, Oliver Boehmer (oboehmer) wrote:
>
> Well, it looks like the linux NAT/firewall is not NAT'ing the
> keepalive GRE packets correctly, otherwise they would not arrive with
> the 172.16.1.1 src address on router2. Not sure what's happening
> there, but I would focus my attention on the NAT/firewall box.. I
> guess NAT for the "other" GRE packets work just fine? Maybe related
> to the different protocol type (0x0) or the lack of payload in the
> GRE keepalive packet?
>
> oli
The issue is that a GRE keepalive packet has the originating tunnel
endpoint IP address as the destination address of the encapsulated
packet. That is, consider the following:
interface tunnel1
tunnel source 10.0.0.1
tunnel destination 20.0.0.2
tunnel keepalive
(Not sure I've got the syntax right, but you get the idea.)
A keepalive packet generated by the router will look like the following:
IP header: Source=10.0.0.1 Destination=20.0.0.2 Protocol=GRE
GRE Header: Protocol=IP
Encapsulated Packet:
IP Header: Source=? (Not Inportant) Dest=10.0.0.1 Proto=GRE
GRE Header: 0x0000
The idea is that the router at the far end will received the packet,
remove the outer header, and transmit the encapsulated packet. (The
router at the far end will, then, not do any special processing all for
a keepalive packet originating from the near end.) THe issue with
keepalive is that the 10.0.0.1 appears in the encapsulated packet, so
if that's being NAT'd somewhere, for keepalive to work, the NAT needs
to translate the address on the encapsulated packet also.
AFAIK, essentially no NATs will do that.
So, anyway, suppose that 10.0.0.1 is being NAT'd to 30.0.0.1. The far
end router then receives:
IP header: Source=30.0.0.1 Destination=20.0.0.2 Protocol=GRE
GRE Header: Protocol=IP
Encapsulated Packet:
IP Header: Source=? (Not Inportant) Dest=10.0.0.1 Proto=GRE
GRE Header: 0x0000
The far end router's normal GRE processing then involves removing the
outer header, and attempting to send the following packer:
IP Header: Source=? (Not Important) Dest=10.0.0.1 Proto=GRE
GRE Header: 0x0000
This fails because the far end router has no path to get to 10.0.0.1,
because it should be sending to 30.0.0.1.
The reason that isn't a problem for "other" GRE packets is that, in
general, there's no requirement that the encapsulated packet be
translated by the NAT, because, in general, the tunnel endpoint IP
addresses don't appear as source or destination addresses on the
encapsulated packet.
More generally, GRE works fine through NAT as long as the expectation
is that one or both of the tunnel endpoint addresses will be
translated, but the packets flowing through the tunnel don't need NAT.
However, once you enable keepalive, you effectively create a
requirement that the encapsulated packets be translated, because Cisco
GRE keepalive depends on using the tunnel origin/destination address in
encapsulated packet.
This also, in general, breaks keepalives when a tunnel interface has
"ip forwarding vrf XXXX' and "tunnel vrf YYYY" where XXXX and YYYY
aren't the same. (This is because the keepalive processing on the far
end will result in a packet being send in vrf XXXX to a destination IP
address that is reallyin vrf YYYY.)
And, yes, I think this is horribly broken. A much better GRE keepalive
implementation would be to just send
IP header: Source=30.0.0.1 Destination=20.0.0.2 Protocol=GRE
GRE Header: Protocol=KeepaliveRequest
and have the far end router generate a
IP header: Source=20.0.0.2 Destination=30.0.0.1 Protocol=GRE
GRE Header: Protocol=KeepaliveResponse
This would work through NAT and through complicated VRF configurations.
But that's not what Cisco implemented.
-- Brett
More information about the cisco-nsp
mailing list