Skip to main content
RunBook Academy

← All runbooks in VyOS

high riskservice affecting~45 min

Runbook: Configure a BGP Neighbour

1 · Prerequisites

Confirm every item is in place before any state change.

2 · Pre-checks

Read-only diagnostic commands. If any of these don't match expected output, stop and investigate further.

  • · The peer contract is written down before anything is typed: peer address, remote AS, local source address, address family, expected prefix count in each direction, and the authentication mechanism
  • · The local process identity is what you expect: show configuration commands | match protocols shows the intended system-as and parameters router-id
  • · The peer address is reachable from the source you intend to use: show route PEER, show route SOURCE, and ping -c 3 PEER source SOURCE
  • · The inbound prefix-list, the outbound prefix-list and the maximum-prefix value exist as decisions, not intentions. A neighbour committed without them accepts and advertises everything
  • · The transport model is chosen and is one of three: direct peer at TTL 1, ebgp-multihop with a documented hop count, or ttl-security hops. Multihop and GTSM are mutually exclusive
  • · Any TCP-MD5 secret has been exchanged through the approved secret store, not through the ticket or a chat message, and only a key identifier appears in the change record
  • · Out-of-band access is confirmed, and commit-confirm is the agreed apply method for a change on a router reached over the network being changed

3 · Procedure

Execute each step in order. Verify the expected output of a step before moving to the next.

  1. 1Capture the pre-change state: show configuration commands | match protocols, show bgp summary, show ip route summary. You need the prefix counts from BEFORE to judge the counts after.
  2. 2Commit the policy objects first, on their own. set policy prefix-list rules are inert until something references them, so this commit changes no forwarding and creates the objects the neighbour stanza will reference.
  3. 3Verify the policy objects exist and read as intended: show configuration commands | match prefix-list. A neighbour that references a list which does not exist either fails validation or, worse, passes with a permissive list.
  4. 4Build the neighbour stanza in the candidate: remote-as, description, update-source if the source is not the outgoing interface address, the transport model, and the address family with the inbound prefix-list, the outbound prefix-list and maximum-prefix.
  5. 5For a peer whose policy you have not seen before, add shutdown to the stanza in this commit. The configuration renders and validates without a session establishing, which separates a configuration fault from a peering fault.
  6. 6Run compare and read every line. Have it peer-reviewed against the written peer contract before committing.
  7. 7Apply with commit-confirm 5, leave configure mode, and verify from the operational shell. Do not confirm until the verification ladder is complete.
  8. 8Walk the ladder in order - configuration, transport, protocol, policy, forwarding. show bgp summary for the state, show bgp neighbor PEER for source, capabilities, timers and reset reason, show route PEER and ss -tnp | grep 179 for transport.
  9. 9If the peer was committed shut, remove the shutdown in a second commit-confirm and watch the prefix count as it establishes. This is the moment a wrong maximum-prefix or a missing inbound filter shows itself.
  10. 10Compare the received and advertised prefix counts against the peer contract, not against zero: show bgp summary for the totals, show ip bgp neighbors PEER advertised-routes for what you are sending, and show ip bgp neighbors PEER received-routes for what arrived before local policy.
  11. 11Verify forwarding, not just the BGP table: pick a prefix the peer should be giving you and confirm it in show ip route, then test traffic through it.
  12. 12Re-enter configure mode, confirm, save, and record the archive entry, the prefix counts in both directions and the key identifier in the change record.

4 · Verification

Confirm the procedure actually fixed the problem.

  • show bgp summary shows the neighbour in Established with the intended remote AS
  • show bgp neighbor PEER shows the intended source address, the intended address family, the negotiated hold time, and no recent reset reason
  • The received prefix count is inside the band the peer contract predicted - not zero, and not a full table where a customer cone was agreed
  • show ip bgp neighbors PEER advertised-routes contains exactly the prefixes the outbound policy is supposed to export, and nothing else
  • A prefix learned from the peer appears in show ip route with a usable next hop, not only in the BGP table
  • Traffic through the new path works end to end, tested rather than assumed
  • show configuration commands | match prefix-list confirms the inbound and outbound lists are bound to the address family, and maximum-prefix is set
  • The change is confirmed and saved: confirm was run before the timer expired, save afterwards, and show log commit | last 5 shows both

5 · Rollback

If verification fails, undo the procedure in reverse order.

  • While the commit-confirm timer is running, doing nothing is the rollback. The router restores the previous configuration without a second decision from an operator who has just been surprised
  • To take the session down without losing the configuration or the evidence: set protocols bgp neighbor PEER shutdown, compare, commit. This is faster and more surgical than deleting the peer, and it leaves the stanza intact for the post-incident review
  • To remove the peer entirely: delete protocols bgp neighbor PEER, compare, commit, save. Verify the withdrawal on the neighbour side, not just the absence of a local command
  • If only the policy is wrong, revert the policy rather than the session: correct the prefix-list or the maximum-prefix value and re-commit. Tearing down a session to fix a filter costs a reconvergence you did not need
  • POINT OF NO RETURN: prefixes you advertised that the peer accepted and propagated. Withdrawing re-converges the path; it does not undo what downstream systems did with the announcement, including route-flap dampening applied by the neighbour
  • POINT OF NO RETURN: a TCP-MD5 secret that has appeared in a ticket, a chat message or a shell history. Rotate it through the approved process; removing the message does not un-disclose it
  • POINT OF NO RETURN: a session that flapped repeatedly during the change. Whether it comes back promptly is the neighbour policy decision, not yours

6 · Escalation

When the runbook isn't enough, contact:

  • · Escalate to the peer or provider owner before any change that alters the session parameters they configured - remote AS, source address, authentication, timers. A BGP change has two ends and only one of them is yours
  • · Escalate to security if a session password has to be exchanged, rotated, or has been exposed. The saved configuration containing it is a credential artefact
  • · Escalate to network engineering before enabling a peer whose expected prefix count is a full table on a router that has never carried one - this is a memory and control-plane capacity question, not a configuration question
  • · Escalate immediately if the received prefix count is materially outside the contracted band. That is a route leak or a hijack until proven otherwise: vyos-rb-respond-bgp-route-leak
  • · Escalate to the change owner if the session will not leave Active and the transport evidence is clean - the peer side may not be configured, may point at a different address, or may be filtering the source
  • · Escalate to network engineering if this router is one of a redundant pair and the new session changes which half attracts traffic

A BGP neighbour is not a line of configuration. It is a contract with another organisation, and most of the risk in this runbook is not in the commands - it is in the part of the contract nobody wrote down before the change window opened.

The counter-intuitive thing about the change is which outcome is dangerous. A session that fails to establish is loud, harmless and easy to diagnose: the router is doing exactly what it was doing an hour ago. A session that establishes with no inbound filter and no prefix limit is quiet, looks like success, and has just made somebody else’s configuration mistake into your outage. So the order of this runbook is policy first, session second.

When to use this runbook

  • A new transit, peering or customer session on an existing BGP process.
  • A new iBGP session inside the local AS.
  • Re-pointing an existing peer at a different address or source.

When not to use it

  • The BGP process does not exist yet - system-as, router-id and the address family come first; see vyos-rb-deploy-router.
  • A session that used to work has stopped - that is vyos-rb-troubleshoot-bgp-session, and the evidence ladder starts from the session state rather than from the configuration.
  • You are changing what the router exports rather than who it talks to - that is vyos-rb-modify-route-policy-safely.

Blast radius

Everything the new peer can send you and everything it can be given. On a router with an existing table, a new session changes best-path selection for prefixes that were previously single-sourced, which moves traffic that has nothing to do with the new peer.

Step 0: the contract, before the configuration

Six facts. If any of them is a guess, stop and get it from the other side.

FactWhy it decides something
Peer addressProviders frequently document a loopback while the router listens on the link address
Remote ASremote-as is a validation constraint, not a label. FRR compares it with the AS in the peer OPEN
Local sourceIf the source is not the outgoing interface address, update-source is required and the source must be reachable from the peer
Address familyA neighbour with remote-as and no address family negotiates no AFI/SAFI at all
Expected prefix count, both directionsThis is the input to maximum-prefix and the only way to judge the session after it comes up
AuthenticationTCP-MD5, GTSM, both, or neither - and the key identifier, never the key, in the change record

Step 1: capture the numbers you will be judged against

Read-only / Safethe before, without which the after means nothing
show configuration commands | match protocols
show bgp summary
show ip route summary

The prefix counts from before the change are what turn “the session is up” into “the session is carrying what it was supposed to carry”. Without them you have a number with nothing to compare it to.

Step 2: commit the policy objects on their own

A set policy prefix-list rule changes nothing until something references it. That makes it the safest possible first commit: it creates the objects the neighbour stanza will reference, and it fails - if it fails - before any session exists.

Configuration changeinbound and outbound, as a separate change
configure
set policy prefix-list FROM-CUST-A rule 10 action 'permit'
set policy prefix-list FROM-CUST-A rule 10 prefix '203.0.113.0/24'
set policy prefix-list FROM-CUST-A rule 10 le '32'
set policy prefix-list FROM-CUST-A rule 10 description 'CUST-A cone: the /24 and more-specific'

set policy prefix-list TO-CUST-A rule 10 action 'permit'
set policy prefix-list TO-CUST-A rule 10 prefix '198.51.100.0/24'
set policy prefix-list TO-CUST-A rule 10 description 'our allocation, exact match only'

compare
commit
save

Each list ends in an implicit deny, which is the property that makes it a filter rather than a preference. Sparse sequence numbers leave room to insert a rule later without renumbering the list during an incident.

Step 3: build the neighbour stanza

Configuration changethe peer, with its policy already attached
configure
set protocols bgp neighbor 203.0.113.2 remote-as 65100
set protocols bgp neighbor 203.0.113.2 description 'CUST-A downstream, ticket 1842'
set protocols bgp neighbor 203.0.113.2 address-family ipv4-unicast
set protocols bgp neighbor 203.0.113.2 address-family ipv4-unicast prefix-list 'FROM-CUST-A' in
set protocols bgp neighbor 203.0.113.2 address-family ipv4-unicast prefix-list 'TO-CUST-A' out
set protocols bgp neighbor 203.0.113.2 address-family ipv4-unicast maximum-prefix '500'
set protocols bgp neighbor 203.0.113.2 address-family ipv4-unicast soft-reconfiguration inbound
compare

The address-family node is not decoration. A neighbour configured with remote-as alone negotiates no address family, and the session reaches OpenConfirm and stops there with a capability error - which reads like a protocol problem and is a configuration one.

soft-reconfiguration inbound retains the routes the peer sent before local policy was applied. It costs memory, and it is what lets you answer “did the peer send it and I filtered it, or did the peer never send it” without asking the peer to re-advertise.

Step 4: choose the transport model, and only one

ModelConfigurationUse when
Direct peernothing; eBGP defaults to TTL 1The peer address is on a directly connected subnet
Routed multihopebgp-multihop with the real hop countLoopback peering or a genuinely routed path
GTSMttl-security hopsYou want to reject packets arriving from further away than expected

The example above is a direct peer, so it needs none of this. The routed variant of the same session - peering loopback to loopback rather than across the link - replaces the default with an explicit source and hop count:

Configuration changethe routed alternative: a stable source and a real hop count
set protocols bgp neighbor 203.0.113.2 update-source 192.0.2.1
set protocols bgp neighbor 203.0.113.2 ebgp-multihop 5

ebgp-multihop and ttl-security are mutually exclusive; configuring both is a contradictory contract and will fail. Set the hop count to the path the design actually has, not to a large number that makes a session appear - a peer that is two hops away today and three after the next IGP change will keep working until it does not, and nothing in the configuration will explain why.

Step 5: authentication, if the contract calls for it

Configuration changethe secret comes from the store, not from the ticket
set protocols bgp neighbor 203.0.113.2 password CHANGE-ME-OUT-OF-BAND

The VyOS password option is TCP-MD5: a signature over each TCP segment using a shared key. It protects the transport of the session. It does not make a route valid and it does not replace the prefix filters from Step 2.

Its failure mode is unusually confusing and worth knowing before you enable it. A key mismatch is handled by the kernel, which discards the mis-signed segments before BGP ever sees them. The handshake never completes, no OPEN is exchanged, and no BGP NOTIFICATION is sent by either side - so the session oscillates between Connect and Active exactly as it would for a blocked port. The discriminator is not in BGP at all:

Read-only / Safethe kernel counters name the authentication case
nstat -az | grep -i md5

TcpExtTCPMD5Failure means the two keys differ. TcpExtTCPMD5NotFound means only the local side has a key configured. TcpExtTCPMD5Unexpected means only the remote side has one. All three at zero means authentication is not the problem and you should go back to routing and filtering.

Step 6: apply, with the option to have been wrong

Service impact possiblecommit-confirm, then leave configure mode to test
compare
commit-confirm 5
exit

For a peer whose policy you have not seen before, add shutdown to the stanza in this commit and remove it in a second commit-confirm. The first commit proves the configuration renders and validates; the second is the only one that can hurt, and it is the one you watch the prefix count during.

Do not confirm until the ladder below is complete. Doing nothing is a valid outcome: the timer restores the previous configuration.

Step 7: the verification ladder

Five layers, in order, because each one is only meaningful if the one below it is sound.

Read-only / Safe1 configuration, 2 transport
show configuration commands | match 'bgp|neighbor'
show route 203.0.113.2
show route 192.0.2.1
ping -c 3 203.0.113.2 source 192.0.2.1
ss -tnp | grep ':179'
Read-only / Safe3 protocol, 4 policy and tables
show bgp summary
show bgp neighbor 203.0.113.2
show ip bgp neighbors 203.0.113.2 received-routes
show ip bgp neighbors 203.0.113.2 advertised-routes

If the neighbour is absent from the summary, the local configuration is not committed, is in another VRF, or carries shutdown - do not debug timers. If it is present but not Established, the state names the boundary that failed: Active is transport, OpenSent is the OPEN parameters, OpenConfirm is the capability or hold-time negotiation, and a cycling Established is something that happens after the session is up.

Read-only / Safe5 forwarding - the layer people skip
show ip route 203.0.113.0/24
show ip route summary

Established with prefixes is not the same as forwarding. A route can be in the BGP table and absent from the FIB because of policy, administrative distance or an unreachable next hop. Pick a prefix the peer should be giving you, find it in show ip route, and then put traffic through it.

Step 8: confirm, save, record

Configuration changekeep the change and persist it
configure
confirm
save
exit

Record the archive entry number, the received and advertised prefix counts, the key identifier if authentication was used, and the peer contact. During the next incident on this session, the person paged will want the counts from the day it was healthy.

Common patterns

SymptomLikely causeResolution
Neighbour absent from show bgp summaryNot committed, in another VRF, or shutdown is setshow configuration commands | match neighbor
Stuck in Active, ping to the peer worksWrong source, missing return route, or a peer ACLProve both directions with show route and ping source; do not add multihop
Stuck in Active, no NOTIFICATION either wayTCP-MD5 key mismatch - the kernel drops the segmentsnstat -az | grep -i md5
Stuck in OpenSentRemote AS mismatch; the peer rejects the OPENCompare remote-as on both sides against the contract
Stuck in OpenConfirmNo address family in commonAdd the address-family node to the neighbour
Established, zero prefixes receivedInbound filter denies everything, or the peer sends nothingsoft-reconfiguration inbound, then compare pre-policy against post-policy
Established, then Idle (shutdown)maximum-prefix limit exceededFind out why the count moved before raising the limit
Prefixes in BGP, absent from the FIBPolicy, administrative distance, or unreachable next hopshow ip route for the prefix and for the next hop
Session flaps roughly every half the hold timeKEEPALIVE or UPDATE traffic is being lostFix the path; shortening timers hides the symptom

Escalation

Escalate when:

  • The session parameters the peer configured need to change.
  • A session password has to be exchanged, rotated, or has leaked.
  • The expected prefix count is a full table on a router that has never held one.
  • The received count is materially outside the contracted band.
  • The session will not leave Active and the transport evidence is clean.
  • This router is one half of a redundant pair.

References

  1. VyOS 1.5 LTS BGP documentation
  2. FRRouting BGP documentation
  3. RFC 4271 - A Border Gateway Protocol 4 (BGP-4)
  4. RFC 2385 - Protection of BGP sessions via the TCP MD5 signature option
  5. RFC 5082 - The Generalized TTL Security Mechanism (GTSM)
  6. RFC 7454 - BGP Operations and Security