Runbook: Configure a BGP Neighbour
1 · Prerequisites
Confirm every item is in place before any state change.
- BGP configuration foundations
- BGP neighbour identity and source address
- BGP timers and advertisement intervals
- BGP authentication and GTSM
- eBGP multihop and peer groups
- BGP session troubleshooting
- Prefix-list configuration — sequence numbers, ge/le operators, descriptions, hit counters
- Maximum-prefix — bounding the number of prefixes a BGP peer can send
- commit-confirm — the rollback safety net for remote changes
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 protocolsshows the intendedsystem-asandparameters router-id - · The peer address is reachable from the source you intend to use:
show route PEER,show route SOURCE, andping -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-multihopwith a documented hop count, orttl-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-confirmis 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.
- 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. - 2Commit the policy objects first, on their own.
set policy prefix-listrules are inert until something references them, so this commit changes no forwarding and creates the objects the neighbour stanza will reference. - 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. - 4Build the neighbour stanza in the candidate:
remote-as,description,update-sourceif the source is not the outgoing interface address, the transport model, and the address family with the inbound prefix-list, the outbound prefix-list andmaximum-prefix. - 5For a peer whose policy you have not seen before, add
shutdownto the stanza in this commit. The configuration renders and validates without a session establishing, which separates a configuration fault from a peering fault. - 6Run
compareand read every line. Have it peer-reviewed against the written peer contract before committing. - 7Apply with
commit-confirm 5, leave configure mode, and verify from the operational shell. Do notconfirmuntil the verification ladder is complete. - 8Walk the ladder in order - configuration, transport, protocol, policy, forwarding.
show bgp summaryfor the state,show bgp neighbor PEERfor source, capabilities, timers and reset reason,show route PEERandss -tnp | grep 179for transport. - 9If the peer was committed shut, remove the
shutdownin a secondcommit-confirmand watch the prefix count as it establishes. This is the moment a wrong maximum-prefix or a missing inbound filter shows itself. - 10Compare the received and advertised prefix counts against the peer contract, not against zero:
show bgp summaryfor the totals,show ip bgp neighbors PEER advertised-routesfor what you are sending, andshow ip bgp neighbors PEER received-routesfor what arrived before local policy. - 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. - 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 summaryshows the neighbour in Established with the intended remote AS - ✓
show bgp neighbor PEERshows 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-routescontains exactly the prefixes the outbound policy is supposed to export, and nothing else - ✓A prefix learned from the peer appears in
show ip routewith 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-listconfirms the inbound and outbound lists are bound to the address family, andmaximum-prefixis set - ✓The change is confirmed and saved:
confirmwas run before the timer expired,saveafterwards, andshow log commit | last 5shows both
5 · Rollback
If verification fails, undo the procedure in reverse order.
- ↶While the
commit-confirmtimer 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-prefixvalue 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-idand the address family come first; seevyos-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.
| Fact | Why it decides something |
|---|---|
| Peer address | Providers frequently document a loopback while the router listens on the link address |
| Remote AS | remote-as is a validation constraint, not a label. FRR compares it with the AS in the peer OPEN |
| Local source | If the source is not the outgoing interface address, update-source is required and the source must be reachable from the peer |
| Address family | A neighbour with remote-as and no address family negotiates no AFI/SAFI at all |
| Expected prefix count, both directions | This is the input to maximum-prefix and the only way to judge the session after it comes up |
| Authentication | TCP-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
show configuration commands | match protocols
show bgp summary
show ip route summaryThe 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.
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
saveEach 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
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
compareThe 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
| Model | Configuration | Use when |
|---|---|---|
| Direct peer | nothing; eBGP defaults to TTL 1 | The peer address is on a directly connected subnet |
| Routed multihop | ebgp-multihop with the real hop count | Loopback peering or a genuinely routed path |
| GTSM | ttl-security hops | You 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:
set protocols bgp neighbor 203.0.113.2 update-source 192.0.2.1
set protocols bgp neighbor 203.0.113.2 ebgp-multihop 5ebgp-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
set protocols bgp neighbor 203.0.113.2 password CHANGE-ME-OUT-OF-BANDThe 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:
nstat -az | grep -i md5TcpExtTCPMD5Failure 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
compare
commit-confirm 5
exitFor 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.
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'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-routesIf 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.
show ip route 203.0.113.0/24
show ip route summaryEstablished 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
configure
confirm
save
exitRecord 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
| Symptom | Likely cause | Resolution |
|---|---|---|
Neighbour absent from show bgp summary | Not committed, in another VRF, or shutdown is set | show configuration commands | match neighbor |
| Stuck in Active, ping to the peer works | Wrong source, missing return route, or a peer ACL | Prove both directions with show route and ping source; do not add multihop |
| Stuck in Active, no NOTIFICATION either way | TCP-MD5 key mismatch - the kernel drops the segments | nstat -az | grep -i md5 |
| Stuck in OpenSent | Remote AS mismatch; the peer rejects the OPEN | Compare remote-as on both sides against the contract |
| Stuck in OpenConfirm | No address family in common | Add the address-family node to the neighbour |
| Established, zero prefixes received | Inbound filter denies everything, or the peer sends nothing | soft-reconfiguration inbound, then compare pre-policy against post-policy |
| Established, then Idle (shutdown) | maximum-prefix limit exceeded | Find out why the count moved before raising the limit |
| Prefixes in BGP, absent from the FIB | Policy, administrative distance, or unreachable next hop | show ip route for the prefix and for the next hop |
| Session flaps roughly every half the hold time | KEEPALIVE or UPDATE traffic is being lost | Fix 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.