BGP TTL Security, Pt. 1

To explain the BGP TTL Security feature, we first need to look at how TTL works by default in BGP peering sessions.

You may already know that iBGP sessions can be multiple hops away, but eBGP sessions can only be one hop away. Let’s breifly explore how TTL actually works during iBGP and eBGP sessions.

Lab

The interface IPs in the diagram above are configured already, as well as a loopback of <R#>.<R#>.<R#>.<R#>/32 for each router. AS 65000 runs OSPF, and R3 and R4 have static routes to each other’s loopback.

iBGP

First we’ll enable iBGP between R1 and R3, take a pcap, and see what the TTL values are.

R1#
router bgp 65000
 neighbor 3.3.3.3 remote-as 65000
 neighbor 3.3.3.3 update-source lo0

R3#
router bgp 65000
 neighbor 1.1.1.1 remote-as 65000
 neighbor 1.1.1.1 update-source lo0

In a pcap taken at Gi1 on R1, we can see that packets sourced from R1 have a TTL of 255, and packets sourced from R3 have a TTL of 254. (They were initally 255 then decremented 1 by R2).

So we can clearly see that iBGP neighbors can be up to 255 hops away. BGP will use a TTL of 255 for packets sent to iBGP neighbors.

eBGP - directly connected

Now let’s enable eBGP between the loopbacks of R3 and R4

R3#
ip route 4.4.4.4 255.255.255.255 10.3.4.4
router bgp 65000
 neighbor 4.4.4.4 remote-as 65001
 neighbor 4.4.4.4 update-source lo0

R4#
ip route 3.3.3.3 255.255.255.255 10.3.4.3
router bgp 65001
 neighbor 3.3.3.3 remote-as 65000
 neighbor 3.3.3.3 update-source lo0

The BGP session does not come up. If we take a pcap on Gi1 of R3, we see no TCP SYNs even egress the interface. Why is this?

You may have come across books that state that you need to add ebgp-multihop when two directly connected eBGP neighbors peer over their loopback addresses. However, this is a huge pet peeve of mine. The neighbors are not two hops away when they peer over the loopbacks. They are still one hop away. However, when you issue the command ebgp-multihop, it also disables the connected-peer-check, which is actually the reason the two routers won’t peer.

In addition to eBGP neighbors needing to be one hop away, there is also a directly connected check, in which the router makes sure that the eBGP peer is reachable via a directly connected route. Currently in our lab, the peer is reachable via a static route. R3 will not even send a TCP SYN if the eBGP neighbor does not pass its directly connected check.

Let’s disable the directly-connected peer check on R3 and see what happens.

R3#
router bgp 65000
 neighbor 4.4.4.4 disable-connected-check

R3 starts to send TCP SYNs now, but R4 is still rejecting the connection due to its own connected peer check.

Also notice that R3’s TCP SYNs have a TTL of 1. The iBGP session used a TTL of 255, but eBGP sessions use a TTL of 1.

Let’s disable the connected peer check on R4.

R4#
router bgp 65001
 neighbor 3.3.3.3 disable-connected-check

Now the session comes up:

To recap, BGP uses a TTL value of 1 when the neighbor is an eBGP peer, but uses a TTL value of 255 when the neighbor is an iBGP peer. eBGP peers must be reachable on a directly connected route by default.

eBGP multihop

Let’s peer R1 and R4 now. First we’ll add a static route to R4, and redistribute the static route on R3 into OSPF.

R3#
router ospf 1
 redistribute static

R4#
ip route 1.1.1.1 255.255.255.255 10.3.4.3

R4#ping 1.1.1.1 source 4.4.4.4
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 1.1.1.1, timeout is 2 seconds:
Packet sent with a source address of 4.4.4.4 
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 3/5/10 ms

Because eBGP will use a TTL of 1 by default, we will need to use ebgp-multihop. By default, if you specify no hop count, it will use a hop count of 255. However, if we want to be accurate, what minimum hop count would we need to specify?

The answer is 3. TCP packets from R1 to R4 will have an initial TTL of 3. R2 decrements this to 2, and R3 decrements this to 1. R4 receives the packet with a TTL of 1.

R1#
router bgp 65000
 neighbor 4.4.4.4 remote-as 65001
 neighbor 4.4.4.4 ebgp-multihop 3
 neighbor 4.4.4.4 update-source lo0

R4#
router bgp 65001
 neighbor 1.1.1.1 remote-as 65000
 neighbor 1.1.1.1 ebgp-multihop 3
 neighbor 1.1.1.1 update-source lo0

This is a pcap taken at R1 on Gi1. Packets from R4 arrive with a TTL of 1, and packets from R1 have an initial TTL of 3.

If we instead set the ebgp-multihop count to 10, the neighborship still works just fine, it just has a larger TTL value than necessary. Practically there is no difference.

R1#
router bgp 65000
 neighbor 4.4.4.4 ebgp-multihop 10

R4#
router bgp 65001
 neighbor 1.1.1.1 ebgp-multihop 10

  • The TTL values are 10 and 8 now, instead of 3 and 1.

If we do not specify the hop count at all, the TTL values will be 255 and 253 in the pcap.

R1#
router bgp 65000
 neighbor 4.4.4.4 ebgp-multihop

R4#
router bgp 65001
 neighbor 1.1.1.1 ebgp-multihop

In fact, if you look at the running config, IOS will automatically add “255” when you don’t specify the hop count.

! The command "neighbor 4.4.4.4 ebgp-multihop" was entered, with no hop count specified.

R1#sho run | sec bgp
router bgp 65000
 bgp log-neighbor-changes
 neighbor 3.3.3.3 remote-as 65000
 neighbor 3.3.3.3 update-source Loopback0
 neighbor 4.4.4.4 remote-as 65001
 neighbor 4.4.4.4 ebgp-multihop 255
 neighbor 4.4.4.4 update-source Loopback0

The problem with eBGP multihop

The security flaw with this approach is that any router can “pretend” to be R1 and peer with R4. If a bad actor is able to hijack the 1.1.1.1 IP, they can bring up a peering session with R4, because R4 does not inspect the TTL. R4 doesn’t care what the TTL actually is, as long as the packet reaches R4 and it is from the correct peer IP, R4 will form a neighborship.

eBGP multihop simply enables you to form eBGP sessions up to 255 hops away. If we limit the hop count, such as we did when we set it to 3, we just prevent using a longer path if we had to re-route around a link or node failure. Otherwise, there is no security benefit to using a hop count of 3 or a hop count of 255. eBGP multihop does nothing for security. Any other router can be up to 255 hops away and still peer with R4, as long as their source IP is 1.1.1.1.

BGP TTL Security solves this issue by using the TTL value as a verification check. In the next article, we will peer R1 with R4 but use a TTL security “check” of 253. R1 and R4 will not accept the peering session unless the TTL value on the packets is 253 this time. This prevents any routers more than 3 hops away from spoofing the BGP session. An attacker 20 hops away cannot source a packet with a TTL larger than 255, so by the time the packet reaches R4, the TTL will be 235, and R4 will reject the packet based on its TTL value.

To restate this another way, eBGP multihop changes the TTL on outbound packets only. BGP TTL Security changes the TTL on outbound packets, and inspects the TTL value on inbound packets.

Futher Reading

https://packetlife.net/blog/2009/nov/23/understanding-bgp-ttl-security/

https://learningnetwork.cisco.com/s/question/0D53i00000KszCkCAJ/bgp-ttl-security-vs-ebgp-multihop

https://www.cisco.com/c/en/us/td/docs/ios/12_2sx/feature/guide/fsxebtsh.html

Last updated