VyOS BGP Configuration on a VPS: Dual-Stack Tutorial
Configure BGP on a VyOS instance running on a VPS to announce your own IPv4 and IPv6 prefixes. Covers prefix-lists, route-maps, session security, and external verification.
Network engineers who work with Junos or IOS daily know the pain of editing flat config files for BIRD2 or FRR. VyOS gives you a proper router CLI on a VPS: hierarchical config, commit/rollback, tab completion. This tutorial walks through a full BGP setup on a Virtua Cloud VPS running VyOS, from interface config to verified dual-stack prefix announcement.
By the end, you will have IPv4 and IPv6 prefixes announced via BGP with prefix-lists, route-maps, MD5 authentication, GTSM, and max-prefix limits in place.
BGP and Bring Your Own IP on a VPS: The Complete Guide
Prerequisites
Before starting, you need:
- An ASN registered with a RIR (RIPE NCC, ARIN, APNIC). How to Register an ASN with RIPE NCC
- At least one IPv4 /24 and/or IPv6 /48 prefix assigned to your ASN.
- Valid ROA objects published in RPKI for each prefix. RPKI ROA Setup for BGP: Create ROAs, Validate Routes in BIRD2 and FRR
- A Virtua Cloud VPS with VyOS installed. Order a VPS with the ISO image option, mount the VyOS ISO, and complete the install (
install imagefrom the live system). Reboot, unmount the ISO, and you have a persistent VyOS instance. - A BGP session provisioned by your upstream provider. You need: their ASN, the peering IPv4/IPv6 addresses, and the MD5 password (if set).
Throughout this tutorial, we use these placeholder values. Replace them with your own:
| Parameter | Placeholder | Description |
|---|---|---|
| Your ASN | 64512 |
Your autonomous system number |
| Router ID | 198.51.100.10 |
Usually your primary IPv4 address |
| Upstream ASN | 64501 |
Your provider's AS number |
| Upstream IPv4 | 198.51.100.1 |
Provider's peering IPv4 |
| Your peering IPv4 | 198.51.100.10 |
Your side of the point-to-point link |
| Upstream IPv6 | 2001:db8::1 |
Provider's peering IPv6 |
| Your peering IPv6 | 2001:db8::10 |
Your side of the IPv6 peering link |
| Your IPv4 prefix | 203.0.113.0/24 |
The prefix you will announce |
| Your IPv6 prefix | 2001:db8:1000::/48 |
The IPv6 prefix you will announce |
| MD5 password | (from provider) | Shared secret for TCP MD5 |
How do I access and prepare VyOS on a VPS?
After provisioning, SSH into the VyOS instance. VyOS drops you into an operational mode shell. To make configuration changes, enter configuration mode:
ssh vyos@198.51.100.10
configure
The prompt changes from $ to #, indicating you are in configuration mode. Every set command stages a change. Nothing takes effect until you run commit.
Verify the interface
Check that your network interface has the correct addresses assigned. On a Virtua VPS, the primary interface is typically eth0:
show interfaces ethernet eth0
If your peering addresses are not yet configured (some providers use a separate /30 or /31 for the point-to-point link), add them:
set interfaces ethernet eth0 address 198.51.100.10/24
set interfaces ethernet eth0 address 2001:db8::10/64
How do I set up a BGP session on VyOS?
VyOS BGP configuration starts with set protocols bgp. In VyOS 1.4+ (Sagitta), the AS number is set with system-as, not the deprecated set protocols bgp <ASN> format from older releases.
Set your AS number and router ID:
set protocols bgp system-as 64512
set protocols bgp parameters router-id 198.51.100.10
Configure the IPv4 neighbor
set protocols bgp neighbor 198.51.100.1 remote-as 64501
set protocols bgp neighbor 198.51.100.1 description 'Upstream-v4'
set protocols bgp neighbor 198.51.100.1 update-source 198.51.100.10
Configure the IPv6 neighbor
If your provider peers IPv6 over a separate address (common), add a second neighbor block:
set protocols bgp neighbor 2001:db8::1 remote-as 64501
set protocols bgp neighbor 2001:db8::1 description 'Upstream-v6'
set protocols bgp neighbor 2001:db8::1 update-source 2001:db8::10
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast
For the IPv4 neighbor, enable the ipv4-unicast address family explicitly:
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast
How do I announce IPv4 and IPv6 prefixes on VyOS?
To announce a prefix via BGP, two things are required: a network statement under the correct address family, and the prefix must exist in the routing table. The standard approach is to create a static blackhole route (null route) for each prefix.
Create blackhole routes
set protocols static route 203.0.113.0/24 blackhole
set protocols static route6 2001:db8:1000::/48 blackhole
These routes ensure the prefix is always present in the routing table, even when no more-specific routes exist.
Add network statements
set protocols bgp address-family ipv4-unicast network 203.0.113.0/24
set protocols bgp address-family ipv6-unicast network 2001:db8:1000::/48
The network command tells BGP to originate these prefixes. Without the matching blackhole route, BGP will not advertise the prefix.
How do I filter BGP routes with prefix-lists and route-maps on VyOS?
Running BGP without filters is negligent. You should filter both outbound (only announce what you own) and inbound (limit what you accept from the upstream). VyOS uses prefix-list for IPv4 and prefix-list6 for IPv6. This is a common pitfall: using prefix-list with an IPv6 prefix silently fails.
Outbound prefix-lists
Create a prefix-list that permits only your prefixes:
set policy prefix-list EXPORT4 rule 10 action permit
set policy prefix-list EXPORT4 rule 10 prefix 203.0.113.0/24
set policy prefix-list6 EXPORT6 rule 10 action permit
set policy prefix-list6 EXPORT6 rule 10 prefix 2001:db8:1000::/48
An implicit deny-all exists at the end of every prefix-list. Only explicitly permitted prefixes pass.
Inbound prefix-lists
Limit inbound routes to prevent your upstream from flooding your table with a full feed (if you did not request one) or leaking garbage:
set policy prefix-list IMPORT4 rule 10 action permit
set policy prefix-list IMPORT4 rule 10 prefix 0.0.0.0/0
set policy prefix-list IMPORT4 rule 10 le 24
set policy prefix-list6 IMPORT6 rule 10 action permit
set policy prefix-list6 IMPORT6 rule 10 prefix ::/0
set policy prefix-list6 IMPORT6 rule 10 le 48
This accepts any IPv4 prefix up to /24 and any IPv6 prefix up to /48. Adjust le values based on your needs. If you only want a default route, remove the le line and set the prefix to 0.0.0.0/0 or ::/0 with exact match.
Route-maps
Route-maps tie prefix-lists to neighbor sessions:
set policy route-map UPSTREAM-OUT4 rule 10 action permit
set policy route-map UPSTREAM-OUT4 rule 10 match ip address prefix-list EXPORT4
set policy route-map UPSTREAM-OUT6 rule 10 action permit
set policy route-map UPSTREAM-OUT6 rule 10 match ipv6 address prefix-list EXPORT6
set policy route-map UPSTREAM-IN4 rule 10 action permit
set policy route-map UPSTREAM-IN4 rule 10 match ip address prefix-list IMPORT4
set policy route-map UPSTREAM-IN6 rule 10 action permit
set policy route-map UPSTREAM-IN6 rule 10 match ipv6 address prefix-list IMPORT6
Apply route-maps to neighbors
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map export UPSTREAM-OUT4
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map import UPSTREAM-IN4
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast route-map export UPSTREAM-OUT6
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast route-map import UPSTREAM-IN6
How do I secure a VyOS BGP session?
Four mechanisms harden a BGP session: TCP MD5 authentication, GTSM (TTL security), maximum prefix limits, and the ebgp-requires-policy setting. Most competitors cover zero of these. All four should be on by default.
MD5 authentication
MD5 (RFC 2385) signs each TCP segment. It does not encrypt traffic but prevents spoofed TCP resets and session hijacks:
set protocols bgp neighbor 198.51.100.1 password 'your-md5-secret'
set protocols bgp neighbor 2001:db8::1 password 'your-md5-secret'
Both sides must use the same password. Get it from your upstream provider during session provisioning.
GTSM (Generalized TTL Security Mechanism)
GTSM (RFC 5082) rejects BGP packets with a TTL lower than expected. For directly connected eBGP peers, set hops to 1:
set protocols bgp neighbor 198.51.100.1 ttl-security hops 1
set protocols bgp neighbor 2001:db8::1 ttl-security hops 1
This drops any BGP packet that traversed more than 1 hop, blocking remote spoofing attempts. GTSM is mutually exclusive with ebgp-multihop. Do not use both on the same neighbor.
Maximum prefix limits
Protect your routing table from a peer accidentally sending a full table (900k+ IPv4 prefixes) or a route leak:
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast maximum-prefix 10000
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast maximum-prefix 5000
The session tears down if the peer exceeds this limit. Set values based on what you expect to receive. For a single upstream with a default route, 10 is enough. For a full table, 1000000.
Enforce eBGP policy
VyOS disables RFC 8212 enforcement by default for backward compatibility. Enable it so BGP refuses to send or accept routes without an explicit policy:
set protocols bgp parameters ebgp-requires-policy
With this enabled, a neighbor without a route-map applied will not exchange any routes. This prevents accidental route leaks if you add a new peer and forget filters.
How do I configure the VyOS firewall for BGP?
BGP runs on TCP port 179. If you run a VyOS firewall (and you should), allow BGP traffic from your upstream's peering addresses only.
IPv4 firewall rules
set firewall ipv4 input filter rule 20 action accept
set firewall ipv4 input filter rule 20 protocol tcp
set firewall ipv4 input filter rule 20 destination port 179
set firewall ipv4 input filter rule 20 source address 198.51.100.1
set firewall ipv4 input filter rule 20 description 'BGP from upstream v4'
set firewall ipv4 input filter rule 21 action accept
set firewall ipv4 input filter rule 21 protocol tcp
set firewall ipv4 input filter rule 21 source port 179
set firewall ipv4 input filter rule 21 source address 198.51.100.1
set firewall ipv4 input filter rule 21 description 'BGP return from upstream v4'
IPv6 firewall rules
set firewall ipv6 input filter rule 20 action accept
set firewall ipv6 input filter rule 20 protocol tcp
set firewall ipv6 input filter rule 20 destination port 179
set firewall ipv6 input filter rule 20 source address 2001:db8::1
set firewall ipv6 input filter rule 20 description 'BGP from upstream v6'
set firewall ipv6 input filter rule 21 action accept
set firewall ipv6 input filter rule 21 protocol tcp
set firewall ipv6 input filter rule 21 source port 179
set firewall ipv6 input filter rule 21 source address 2001:db8::1
set firewall ipv6 input filter rule 21 description 'BGP return from upstream v6'
Rule 21 handles return traffic when the remote side initiates the TCP connection on source port 179. If you have established/related connection tracking enabled in your firewall, rule 21 may be unnecessary. Include it to be safe.
Commit, save, and the VyOS config workflow
VyOS uses a two-stage workflow. commit activates the staged changes in the running config. save writes the running config to disk so it persists across reboots. Forgetting save means a reboot wipes your changes.
commit
If commit succeeds with no errors, save:
save
Expected output:
Saving configuration to '/config/config.boot'...
Done
If commit fails, VyOS shows the error and rolls back. Read the error. Common causes: typos in IP addresses, conflicting options (like ttl-security and ebgp-multihop on the same neighbor), or referencing a prefix-list that does not exist.
To review your staged changes before committing:
compare
This shows a diff between the running config and your pending changes. To discard uncommitted changes:
discard
To roll back to a previous commit:
rollback 1
commit
save
How do I verify my BGP announcements are visible?
Verification happens in two stages: local (on the VyOS instance) and external (from the internet). Exit configuration mode first:
exit
Local verification
Check session status for both address families:
show bgp ipv4 summary
Expected output:
IPv4 Unicast Summary:
BGP router identifier 198.51.100.10, local AS number 64512 vrf-id 0
BGP table version 3
RIB entries 5, using 960 bytes of memory
Peers 1, using 725 KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
198.51.100.1 4 64501 142 138 0 0 0 01:15:23 2
The State/PfxRcd column shows a number (prefixes received) when the session is established. If it shows Active, Connect, or OpenSent, the session is not up. See the troubleshooting section.
show bgp ipv6 summary
Verify you are advertising the correct prefixes:
show bgp ipv4 neighbors 198.51.100.1 advertised-routes
Expected output includes your 203.0.113.0/24 prefix. If it is missing, check your network statement and outbound route-map.
show bgp ipv6 neighbors 2001:db8::1 advertised-routes
Verification commands reference
| Command | What it shows |
|---|---|
show bgp ipv4 summary |
Session state, prefixes received per peer |
show bgp ipv6 summary |
Same for IPv6 |
show bgp ipv4 neighbors <ip> advertised-routes |
Prefixes you are sending |
show bgp ipv4 neighbors <ip> received-routes |
Prefixes received from peer |
show bgp ipv4 neighbors <ip> |
Full neighbor detail (timers, capabilities, counters) |
show ip route bgp |
BGP routes installed in the routing table |
show bgp ipv4 |
Full IPv4 BGP table |
External verification
Local checks only confirm what your router thinks. Verify from the internet that your prefixes are actually propagating.
bgp.tools: Open https://bgp.tools/prefix/203.0.113.0/24 in a browser. It shows which ASes see the prefix, the AS path, and any RPKI validation status. If the prefix does not appear, wait 5-10 minutes for propagation and recheck.
RIPE Stat: Open https://stat.ripe.net/203.0.113.0/24 for routing status, visibility across route collectors, and RPKI validation state.
Looking glass: Many transit providers offer looking glass tools. Query your upstream's looking glass to confirm they see your announcement.
If your prefix shows RPKI-invalid on bgp.tools, your ROA is wrong. Fix it in the RIPE portal before continuing. RPKI ROA Setup for BGP: Create ROAs, Validate Routes in BIRD2 and FRR
VyOS CLI vs BIRD2 vs FRR: quick comparison
All three can run BGP on a Linux VPS. The choice depends on your workflow preference.
| Task | VyOS CLI | BIRD2 config file | FRR vtysh |
|---|---|---|---|
| Set AS number | set protocols bgp system-as 64512 |
protocol bgp { local 64512 as 64512; } |
router bgp 64512 |
| Add neighbor | set protocols bgp neighbor 1.2.3.4 remote-as 64501 |
neighbor 1.2.3.4 as 64501; inside protocol block |
neighbor 1.2.3.4 remote-as 64501 |
| Announce prefix | set protocols bgp address-family ipv4-unicast network 203.0.113.0/24 |
protocol static { route 203.0.113.0/24 blackhole; } + export filter |
network 203.0.113.0/24 |
| Prefix-list | set policy prefix-list NAME rule 10 ... |
define PFXLIST = [ 203.0.113.0/24 ]; |
ip prefix-list NAME permit ... |
| Apply changes | commit / save |
birdc configure |
write memory |
| Rollback | rollback N + commit |
Restore backup config file | No built-in rollback |
| Config format | Hierarchical CLI | Custom DSL (C-like) | IOS-like CLI |
| Underlying daemon | FRR (bundled) | BIRD | FRR |
VyOS bundles FRR internally but wraps it in a commit/rollback workflow. If you want atomic config changes and rollback without writing scripts, VyOS is the right choice. If you want maximum control over filter logic, BIRD2 gives you a full programming language. BIRD2 BGP Configuration on a Linux VPS FRRouting BGP Configuration on a Linux VPS
What are common VyOS BGP troubleshooting steps?
When a session does not come up or prefixes are not visible, work through these checks systematically.
| Symptom | Likely cause | Fix |
|---|---|---|
State stuck on Active |
TCP connection failing. Firewall blocking port 179, wrong neighbor IP, or the remote side is not configured. | Check firewall rules. Verify neighbor IP matches what the upstream configured. Try ping to the peer address. |
State stuck on OpenSent |
TCP connects but BGP OPEN is rejected. AS number mismatch or capability negotiation failure. | Verify system-as matches what the upstream expects. Check show bgp ipv4 neighbors <ip> for "Notification received". |
State stuck on OpenConfirm |
MD5 password mismatch. TCP connects (SYN/ACK works without MD5 check) but BGP messages fail authentication. | Confirm the password matches on both sides. MD5 is case-sensitive. |
| Session established but 0 prefixes received | Upstream is not sending routes, or your inbound route-map is denying everything. | Check show bgp ipv4 neighbors <ip> received-routes. If empty, ask your upstream. If routes show there but not in the table, check your import route-map. |
| Your prefix not visible externally | Outbound route-map blocking, missing network statement, or no blackhole route. | Run show bgp ipv4 neighbors <ip> advertised-routes. If the prefix is missing, check the outbound route-map and network statement. Verify the blackhole route exists with show ip route 203.0.113.0/24. |
| RPKI Invalid on bgp.tools | ROA mismatch. The origin AS or max-length in the ROA does not match your announcement. | Fix the ROA in the RIPE portal. Ensure the origin AS matches system-as and max-length covers /24. |
| Session flapping | MTU issues, unstable link, or max-prefix limit hit. | Check show log for BGP messages. If max-prefix triggered, increase the limit or investigate why the peer is sending excess routes. |
Read the logs
VyOS logs BGP events through the system journal:
show log | match bgp
For real-time monitoring:
monitor log | match bgp
On the underlying system (if you need more detail):
journalctl -u frr -f
This tails the FRR daemon logs directly. Look for NOTIFICATION messages, which contain the BGP error code and subcode.
Complete configuration reference
Here is the full configuration block for reference. Copy, replace placeholder values, paste into configuration mode, commit, and save:
# Enter configuration mode
configure
# BGP core
set protocols bgp system-as 64512
set protocols bgp parameters router-id 198.51.100.10
set protocols bgp parameters ebgp-requires-policy
# Blackhole routes for prefix origination
set protocols static route 203.0.113.0/24 blackhole
set protocols static route6 2001:db8:1000::/48 blackhole
# Network statements
set protocols bgp address-family ipv4-unicast network 203.0.113.0/24
set protocols bgp address-family ipv6-unicast network 2001:db8:1000::/48
# IPv4 neighbor
set protocols bgp neighbor 198.51.100.1 remote-as 64501
set protocols bgp neighbor 198.51.100.1 description 'Upstream-v4'
set protocols bgp neighbor 198.51.100.1 update-source 198.51.100.10
set protocols bgp neighbor 198.51.100.1 password 'your-md5-secret'
set protocols bgp neighbor 198.51.100.1 ttl-security hops 1
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast maximum-prefix 10000
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map export UPSTREAM-OUT4
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast route-map import UPSTREAM-IN4
# IPv6 neighbor
set protocols bgp neighbor 2001:db8::1 remote-as 64501
set protocols bgp neighbor 2001:db8::1 description 'Upstream-v6'
set protocols bgp neighbor 2001:db8::1 update-source 2001:db8::10
set protocols bgp neighbor 2001:db8::1 password 'your-md5-secret'
set protocols bgp neighbor 2001:db8::1 ttl-security hops 1
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast maximum-prefix 5000
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast route-map export UPSTREAM-OUT6
set protocols bgp neighbor 2001:db8::1 address-family ipv6-unicast route-map import UPSTREAM-IN6
# Outbound prefix-lists (only announce what you own)
set policy prefix-list EXPORT4 rule 10 action permit
set policy prefix-list EXPORT4 rule 10 prefix 203.0.113.0/24
set policy prefix-list6 EXPORT6 rule 10 action permit
set policy prefix-list6 EXPORT6 rule 10 prefix 2001:db8:1000::/48
# Inbound prefix-lists
set policy prefix-list IMPORT4 rule 10 action permit
set policy prefix-list IMPORT4 rule 10 prefix 0.0.0.0/0
set policy prefix-list IMPORT4 rule 10 le 24
set policy prefix-list6 IMPORT6 rule 10 action permit
set policy prefix-list6 IMPORT6 rule 10 prefix ::/0
set policy prefix-list6 IMPORT6 rule 10 le 48
# Route-maps
set policy route-map UPSTREAM-OUT4 rule 10 action permit
set policy route-map UPSTREAM-OUT4 rule 10 match ip address prefix-list EXPORT4
set policy route-map UPSTREAM-OUT6 rule 10 action permit
set policy route-map UPSTREAM-OUT6 rule 10 match ipv6 address prefix-list EXPORT6
set policy route-map UPSTREAM-IN4 rule 10 action permit
set policy route-map UPSTREAM-IN4 rule 10 match ip address prefix-list IMPORT4
set policy route-map UPSTREAM-IN6 rule 10 action permit
set policy route-map UPSTREAM-IN6 rule 10 match ipv6 address prefix-list IMPORT6
# Firewall - allow BGP from upstream only
set firewall ipv4 input filter rule 20 action accept
set firewall ipv4 input filter rule 20 protocol tcp
set firewall ipv4 input filter rule 20 destination port 179
set firewall ipv4 input filter rule 20 source address 198.51.100.1
set firewall ipv4 input filter rule 20 description 'BGP from upstream v4'
set firewall ipv6 input filter rule 20 action accept
set firewall ipv6 input filter rule 20 protocol tcp
set firewall ipv6 input filter rule 20 destination port 179
set firewall ipv6 input filter rule 20 source address 2001:db8::1
set firewall ipv6 input filter rule 20 description 'BGP from upstream v6'
# Apply
commit
save
Further reading
- BGP and Bring Your Own IP on a VPS: The Complete Guide Parent guide covering the full BYOIP workflow
- BIRD2 BGP Configuration on a Linux VPS -- Same goal, different tool: BIRD2 on bare Linux
- FRRouting BGP Configuration on a Linux VPS -- FRR approach for those who prefer vtysh without VyOS
- RPKI ROA Setup for BGP: Create ROAs, Validate Routes in BIRD2 and FRR -- Setting up ROA objects before announcing prefixes
- BGP Route Filtering: Prefix Lists, AS-Path Filters, Bogon Rejection, and GTSM -- Deep dive on route filtering strategies
- How to Register an ASN with RIPE NCC Getting your own ASN from RIPE NCC
- VyOS BGP documentation -- Official reference for all BGP options
- bgp.tools -- External BGP route visibility checker
Copyright 2026 Virtua.Cloud. All rights reserved. This content is original work by the Virtua.Cloud team. Reproduction, republication, or redistribution without written permission is prohibited.
Ready to try it yourself?
Run BGP sessions on your own IP space with Virtua.Cloud VPS. →