Deployment guide

ExaBGP

Overview

ExaBGP is the Python "BGP swiss army knife" from Exa Networks. Instead of being a traditional routing stack, it lets software talk BGP. It runs as a daemon driven by a plain text configuration, announces and withdraws routes on command through a named pipe CLI (exabgp cli), and streams every BGP event it receives as JSON to helper processes that you write in any language.

That makes it a good fit for injecting routes from scripts and controllers, steering or blackholing traffic during DDoS mitigation, announcing anycast service addresses with health checks, and prototyping BGP behaviour including FlowSpec.

A bare BGP daemon has nothing to show on its own, so this SecureAnyCloud image ships a complete, self-contained BGP reference deployment on a single VM. As soon as the VM boots, sudo exabgp cli show neighbor summary shows an established session. One announce route command later, you can watch your route arrive at the peer in real time, so you can see BGP working before you point the daemon at your own routers.

What you get:

  • ExaBGP 5.0.9 (exabgp and exabgp-cli) in a dedicated virtual environment at /opt/exabgp/venv, pinned to the official upstream release and verified by SHA-256
  • A primary ExaBGP (AS 65001), the daemon you drive with sudo exabgp cli. It dials out to the demo peer and listens nowhere.
  • Runtime control of the primary over the named pipe CLI: sudo exabgp cli <command>
  • A demo peer ExaBGP (AS 65002) listening on an internal loopback range address only (10.255.255.2:179), authenticated with a per-VM TCP-MD5 key
  • A real eBGP session between the two that reaches established, with static routes propagating in both directions and every BGP event the peer receives logged as JSON to /var/log/exabgp/peer-events.jsonl
  • JSON event logs of everything the daemons receive, at /var/log/exabgp/peer-events.jsonl and /var/log/exabgp/primary-events.jsonl
  • A per-VM TCP-MD5 key generated at first boot and stored at /root/exabgp-credentials.txt (root only)
  • Secure by default: no port is open on the public interface, and BGP listens only on the internal demo link
  • The unprivileged exabgp system account, with only the two capabilities it needs
  • 24/7 SecureAnyCloud support

Deploying on Azure

Launch the image from the Azure Marketplace on a Standard_B2s (or larger) VM. ExaBGP is a lightweight, pure Python daemon, and Standard_B2s (2 vCPU / 4 GB) is ample for the reference deployment and for a modest production route injector.

SSH in as azureuser with the key you selected at launch:

ssh azureuser@<vm-ip>

On first boot the appliance generates this VM's unique TCP-MD5 session key, renders both ExaBGP configurations, validates them with exabgp validate and brings the reference deployment up. It then proves that the session establishes, routes propagate both ways and a live CLI injection lands, before it writes its first-boot sentinel.

No two VMs share a key, and the image itself contains no key at all.

1

Confirm the authenticated eBGP session is established

show neighbor summary lists the primary daemon's peers and their session state. The demo peer (10.255.255.2, AS 65002) is established, and it gets there only because both ends share this VM's TCP-MD5 key:

sudo exabgp cli show neighbor summary

Expected output:

Peer AS up/down state | #sent #recvd 10.255.255.2 65002 0:00:51 established 26 22
2

Check that routes propagate in both directions

The Adjacency RIB In shows what the primary has received from the demo peer, its static route 192.0.2.0/24. The Adjacency RIB Out shows what the primary is advertising to the peer, its own static route 203.0.113.0/24:

sudo exabgp cli show adj-rib in
sudo exabgp cli show adj-rib out

Expected output:

10.255.255.2 ipv4 unicast 192.0.2.0/24 next-hop 10.255.255.2 10.255.255.2 ipv4 unicast 203.0.113.0/24 next-hop 10.255.255.1

You can verify the reverse direction from a file. The demo peer runs an ExaBGP API process that appends every BGP event it receives to a JSON log, and the arrival of the primary's route is recorded there:

sudo jq -c 'select(.type=="update") | .neighbor.message.update.announce // empty' /var/log/exabgp/peer-events.jsonl | head -3

Expected output:

{"ipv4 unicast":{"10.255.255.1":[{"nlri":"203.0.113.0/24"}]}}
3

Inject a route live from the CLI

Route injection is what ExaBGP is for. Announce a prefix on the primary and watch it arrive at the demo peer in real time:

sudo exabgp cli announce route 198.51.100.0/24 next-hop 10.255.255.1 sleep 3
sudo jq -c 'select(.type=="update") | .neighbor.message.update.announce // empty' /var/log/exabgp/peer-events.jsonl | tail -1

Expected output:

{"ipv4 unicast":{"10.255.255.1":[{"nlri":"198.51.100.0/24"}]}}

Withdraw the route just as easily. The peer logs the withdrawal too:

sudo exabgp cli withdraw route 198.51.100.0/24 next-hop 10.255.255.1 sleep 3
sudo jq -c 'select(.type=="update") | .neighbor.message.update.withdraw // empty' /var/log/exabgp/peer-events.jsonl | tail -1

Expected output:

{"ipv4 unicast":[{"nlri":"198.51.100.0/24"}]}
4

Confirm the secure defaults

Nothing is exposed on the VM's routable interface. The primary daemon listens nowhere because it dials out, and the demo peer's BGP listener is bound to the internal demo address 10.255.255.2 only. This VM's TCP-MD5 key lives only in /root/exabgp-credentials.txt, readable by root alone. Check the listeners:

sudo ss -lntH | awk '{print $1, $4}' | grep -E '10.255.255|:179'
sudo grep -v '^#' /root/exabgp-credentials.txt | head -2

Expected output. BGP listens on the internal demo link only, and nothing listens on eth0:

LISTEN 10.255.255.2:179

Peering with your own routers

The primary daemon's configuration is at /etc/exabgp/exabgp.conf. To peer with your own routers, add a neighbor block for each one. A minimal example:

neighbor <remote-peer-ip> { router-id <this-vm-private-ip>; local-address <this-vm-private-ip>; local-as 65001; peer-as <remote-as>; md5-password "<a-shared-md5-key>"; static { route <prefix-to-announce> next-hop self; } }

Open TCP 179 to those peers in your Azure Network Security Group, then apply the change with sudo systemctl restart exabgp.

You can drive everything at runtime without editing the config. Use sudo exabgp cli announce route <prefix> next-hop <ip> and sudo exabgp cli withdraw route <prefix> next-hop <ip>, and run sudo exabgp cli help for the full command set.

To feed received routes into your own automation, add an ExaBGP process block. The shipped /usr/local/sbin/exabgp-route-log.sh is a working example that streams every event as JSON to a file.

Managing the service

sudo systemctl status exabgp --no-pager sudo journalctl -u exabgp -n 50 --no-pager

The demo peer (exabgp-peer.service) exists only to make the shipped image a working reference deployment. Once you have configured your own peers, you can disable it for a clean single-daemon setup with sudo systemctl disable --now exabgp-peer.service.

Support

Every SecureAnyCloud deployment is patched at build time, ships with unattended security updates enabled, and includes 24/7 SecureAnyCloud support. For help with this image, contact support through the Azure Marketplace listing or at secureanycloud.com.

Deploy on Azure

Launch ExaBGP on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure