FortiGate
FortiGate Next Generation Firewall utilizes purpose-built security processors and threat intelligence security services from FortiGuard labs to deliver top-rated protection and high performance, including encrypted traffic.
npaiva
Staff
Staff
Article Id 241807
Description

 

This article describes the challenges of Multicasting using PIM in an ADVPN environment.

In order to understand the behavior that is going to be demonstrated, we first need to have knowledge of how Protocol Independent Multicast works in general.

 

It is possible to start by saying that IP Multicast routes packets away from the source.

To explain the sentence above, it is first possible to think about unicast routing.

Unicast packet forwarding forwards a packet to a destination.

 

The router gets the packet, looks at the destination, checks the routing table for a match, and forwards the packet out the corresponding egress interface.

 

In Multicast, packets get forwarded away from the source.

The router receives the packet on an ingress interface and it will be forwarded to one or many egress interfaces but never on the same interface where the packet was received.

This is a loop prevention mechanism.

 

If the packet was sent back out the ingress interface, the upstream Router would route the packet again downstream, and we would have a loop until the TTL expired.

The easiest way to think about the methodology used by Multicast is that for each (Source,Group) entry in the MRIB (Multicast Routing Information Base), the Router will record the Upstream and Downstream interfaces.

An Upstream interface is one facing the source, and a Downstream interface is one facing a Multicast listener or another PIM participating Router.

 

Example of an (S,G) entry in the MFIB:

 

hub # get router info multicast pim dense-mode table
PIM-DM Multicast Routing Table
(10.254.15.1, 239.0.0.1)
MRT life time: 210
RPF Neighbor: 192.168.100.1, Nexthop: 192.168.100.1, advpn-hub
Upstream IF: advpn-hub
Upstream State: Forwarding
Assert State: Loser
Assert timer: 180 seconds
Asert winner (pref 0 metric 0): 192.168.100.1
Last SR 00:00:29
Downstream IF List:
port2, in 'olist':
Flag: LMEM_INC IN-OLIST
Downstream State: NoInfo
Assert State: NoInfo

 

This is the sample topology:

 

topo.png

 

Issue 1: In this topology, is that the Spokes cannot form a direct PIM neighborship, as PIM cannot bind to an ADVPN shortcut.

The HUB is a PIM neighbor with both spokes, but spokes only form an adjacency with the HUB:

 

hub # get router info multicast pim dense-mode neighbour
Neighbor-Address Interface Uptime/Expires Ver
192.168.100.1 advpn-hub 01:47:15/00:01:29 v2
192.168.100.2 advpn-hub 01:46:58/00:01:20 v2

 

Spoke1 # get router info multicast pim dense-mode neighbour
Neighbor-Address Interface Uptime/Expires Ver
192.168.100.254 spoke1 01:47:51/00:01:42 v2

 

Spoke2 # get router info multicast pim dense-mode neighbour
Neighbor-Address Interface Uptime/Expires Ver
192.168.100.254 spoke2 01:47:55/00:01:18 v2

 

Multicast routing will work properly if the Source is directly connected to, or upstream of the HUB on another interface other than the ADVPN tunnel, and the group members (listeners) are connected to the Spokes.

 

Example:

 

A server will be initiating a stream on the HUB, on the LAN connected to port2 and it will be multicasting to group 239.0.0.254:

 

hub # get router info multicast pim dense-mode table 239.0.0.254
PIM-DM Multicast Routing Table
(10.254.17.1, 239.0.0.254)
MRT life time: 210
Source directly connected on port2
State-Refresh Originator State: Originator
State Refresh Interval (received): 0
Upstream IF: port2
Upstream State: Forwarding
Assert State: NoInfo
Assert timer: 180 seconds
Downstream IF List:
advpn-hub, in 'olist':
Flag: IN-OLIST
Downstream State: NoInfo
Assert State: NoInfo

 

It is possible to see that it states that the Source is directly connected to port2.

 

Now on both Spokes, a device will be used on the LAN to join group 239.0.0.254, and  both Spokes have seen the group join from the hosts on its connected LAN (port2):

 

Spoke1 # get router info multicast igmp groups 239.0.0.254
IGMP Connected Group Membership
Group Address Interface Uptime Expires Last Reporter
239.0.0.254 port2 00:01:34 00:03:04 10.254.15.1

 

Spoke2 # get router info multicast igmp groups 239.0.0.254
IGMP Connected Group Membership
Group Address Interface Uptime Expires Last Reporter
239.0.0.254 port2 00:01:32 00:02:47 10.254.16.1

 

Both Spokes also have the (S,G) entry in the MRIB at this point, that was sent by the HUB:

 

Spoke1 # get router info multicast pim dense-mode table 239.0.0.254
PIM-DM Multicast Routing Table
(10.254.17.1, 239.0.0.254)
MRT life time: 210
RPF Neighbor: 192.168.100.254, Nexthop: 10.191.20.108, spoke1
Upstream IF: spoke1
Upstream State: Forwarding
Assert State: Loser
Assert timer: 180 seconds
Asert winner (pref 0 metric 0): 192.168.100.254
Last SR 00:00:38
Downstream IF List:
port2, in 'olist':
Flag: LMEM_INC IN-OLIST
Downstream State: NoInfo
Assert State: NoInfo

 

Spoke2 # get router info multicast pim dense-mode table 239.0.0.254
PIM-DM Multicast Routing Table
(10.254.17.1, 239.0.0.254)
MRT life time: 210
RPF Neighbor: 192.168.100.254, Nexthop: 10.191.20.108, spoke2
Upstream IF: spoke2
Upstream State: Forwarding
Assert State: Loser
Assert timer: 180 seconds
Asert winner (pref 0 metric 0): 192.168.100.254
Last SR 00:00:53
Downstream IF List:
port2, in 'olist':
Flag: LMEM_INC IN-OLIST
Downstream State: NoInfo
Assert State: NoInfo

 

Doing some packet captures, the traffic flowing correctly.

From HUB incoming on port2 and outgoing on IPSEC tunnel, and on the Spokes incoming on the IPSEC tunnel and outgoing to port2:

 

hub # diagnose sniffer packet any 'host 239.0.0.254' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[host 239.0.0.254]
4.499764 port2 in 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
4.499779 advpn-hub out 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
4.504304 port2 in 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
4.504320 advpn-hub out 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
4.511482 port2 in 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
4.511507 advpn-hub out 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328

 

Spoke1 # diagnose sniffer packet any 'host 239.0.0.254' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[host 239.0.0.254]
6.798215 spoke1 in 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
6.798278 port2 out 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
6.802153 spoke1 in 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
6.802204 port2 out 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
6.810191 spoke1 in 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
6.810264 port2 out 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328

 

Spoke2 # diagnose sniffer packet any 'host 239.0.0.254' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[host 239.0.0.254]
9.204459 spoke2 in 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
9.204496 port2 out 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
9.207703 spoke2 in 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
9.207746 port2 out 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
9.215718 spoke2 in 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328
9.215795 port2 out 10.254.17.1.50639 -> 239.0.0.254.5004: udp 1328

 

Issue 2:

 

Now let’s demonstrate what happens if the Server is in one of the Spokes.

For this example, a host on Spoke1 LAN will be the server and is transmitting to multicast group 230.0.0.1.

 

Both the HUB and the Spoke2 already have hosts on the LAN that have joined this group:

 

hub # get router info multicast igmp groups 239.0.0.1
IGMP Connected Group Membership
Group Address Interface Uptime Expires Last Reporter
239.0.0.1 port2 00:00:33 00:03:46 10.254.17.1

 

Spoke2 # get router info multicast igmp groups 239.0.0.1
IGMP Connected Group Membership
Group Address Interface Uptime Expires Last Reporter
239.0.0.1 port2 00:00:32 00:03:47 10.254.16.1

 

The server initiates the Stream and the source is directly connected to port2 on Spoke1:

 

Spoke1 # get router info multicast pim dense-mode table 239.0.0.1
PIM-DM Multicast Routing Table
(10.254.15.1, 239.0.0.1)
MRT life time: 210
Source directly connected on port2
State-Refresh Originator State: Originator
State Refresh Interval (received): 0
Upstream IF: port2
Upstream State: Forwarding
Assert State: NoInfo
Assert timer: 180 seconds
Downstream IF List:
spoke1, in 'olist':
Flag: IN-OLIST
Downstream State: NoInfo
Assert State: NoInfo

 

The HUB also gets the MRIB entry:

 

hub # get router info multicast pim dense-mode table 239.0.0.1
PIM-DM Multicast Routing Table
(10.254.15.1, 239.0.0.1)
MRT life time: 210
RPF Neighbor: 192.168.100.1, Nexthop: 192.168.100.1, advpn-hub
Upstream IF: advpn-hub
Upstream State: Forwarding
Assert State: Loser
Assert timer: 180 seconds
Asert winner (pref 0 metric 0): 192.168.100.1
Last SR 00:00:04
Downstream IF List:
port2, in 'olist':
Flag: LMEM_INC IN-OLIST
Downstream State: NoInfo
Assert State: NoInfo

 

But not Spoke2:

 

Spoke2 # get router info multicast pim dense-mode table 239.0.0.1
PIM-DM Multicast Routing Table

 

Doing a PCAP,it is possible to see that from Spoke1 to HUB everything looks fine, and the traffic is being delivered to port2 LAN at the HUB:

 

Spoke1 # diagnose sniffer packet any 'host 239.0.0.1' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[host 239.0.0.1]
7.583857 port2 in 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
7.583995 spoke1 out 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
7.649343 port2 in 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
7.649479 spoke1 out 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
7.716773 port2 in 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
7.716929 spoke1 out 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328

 

hub # diagnose sniffer packet any 'host 239.0.0.1' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[host 239.0.0.1]
13.323281 advpn-hub in 10.254.15.1.61359 -> 239.0.0.1.5005: udp 64
13.323371 port2 out 10.254.15.1.61359 -> 239.0.0.1.5005: udp 64
13.323408 advpn-hub in 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
13.323423 port2 out 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
13.914856 advpn-hub in 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
13.914887 port2 out 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328

 

Why it is not possible for Spoke2 to also get the Stream:

First, remember that as explained above the Spokes cannot form a PIM neighborship directly because PIM cannot bind to an ADVPN shortcut, so sending traffic directly is not a possibility.

Aside from that, the HUB is getting the Stream from Spoke1, and for the HUB the Upstream Interface for (10.254.15.1, 239.0.0.1) is the IPSEC tunnel. If the IPSEC tunnel is the upstream interface, and in Multicast routing, it is only possible to forward traffic away from the source, then the HUB cannot forward the traffic back into the tunnel for it to reach Spoke2 because it would create a loop to Spoke1.

 

Solution

 

It is still possible to implement multicast Spoke to Spoke in an ADVPN environment, but without using Multicast Routing, so without configuring PIM.

It is possible to use a technique called RPB .

Reverse Path Broadcasting. On the FortiGate this feature is called 'multicast-forward', and when it is enabled, the FortiGate forwards any multicast IP packets to all interfaces and VLAN interfaces, except the receiving interface.

Multicast policies still need to be configured to allow the traffic as with PIM. The configuration is very straightforward:

 

# config system settings

    set multicast-forward enable

end

 

For the next example, all PIM configuration was removed, and multicast-forward was enabled in the HUB and Spokes. The server in Spoke1 LAN will transmit to the same group as before:

 

Spoke1 # diagnose sniffer packet any 'host 239.0.0.1' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[host 239.0.0.1]
17.593847 port2 in 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
17.593981 spoke1 out 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
17.594103 spoke1_0 out 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
17.594159 port2 in 10.254.15.1.61359 -> 239.0.0.1.5005: udp 64
17.594168 spoke1 out 10.254.15.1.61359 -> 239.0.0.1.5005: udp 64
17.594190 spoke1_0 out 10.254.15.1.61359 -> 239.0.0.1.5005: udp 64

 

Spoke2 # diagnose sniffer packet any 'host 239.0.0.1' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[host 239.0.0.1]
5.870579 spoke2_0 in 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
5.870677 port2 out 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
5.870721 spoke2_0 in 10.254.15.1.61359 -> 239.0.0.1.5005: udp 64
5.870771 port2 out 10.254.15.1.61359 -> 239.0.0.1.5005: udp 64


hub # diagnose sniffer packet any 'host 239.0.0.1' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[host 239.0.0.1]
81.386872 advpn-hub in 10.254.15.1.61359 -> 239.0.0.1.5005: udp 64
81.386939 port2 out 10.254.15.1.61359 -> 239.0.0.1.5005: udp 64
81.386990 advpn-hub in 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
81.387005 port2 out 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
82.043590 advpn-hub in 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328
82.043616 port2 out 10.254.15.1.61358 -> 239.0.0.1.5004: udp 1328

 

Related Documents:

https://docs.fortinet.com/document/fortigate/6.2.12/cookbook/985659/advpn-and-shortcut-paths

https://community.fortinet.com/t5/FortiGate/Technical-Tip-Multicast-traffic-over-site-to-site-IPsec-...

https://community.fortinet.com/t5/FortiGate/Technical-Note-Multicast-traffic-over-site-to-site-IPsec...

Contributors