Birdseye
A Simple Secure Micro Service for Querying Bird (JSON API)
Install / Use
/learn @inex/BirdseyeREADME
Bird's Eye - A Simple Secure Micro Service for Querying BIRD
A simple secure PHP micro service to provide some BIRD protocol / routing information via a HTTP API as JSON, with an optional built-in looking-glass implementation.
This is the winning project from the RIPE IXP Tools Hackaton just prior to RIPE73 in Madrid, Spain. Since the hackathon, substantial improvements have been made.
The end of workshop presentation can be found here: [Keynote] [PDF]. A more detailed presentation to the Open Source Working Group at RIPE73, delivered by @nickhilliard, can be found here: [VIDEO]
Author: Barry O'Donovan, INEX, Dublin, Ireland
Live Examples
INEX runs a number of BIRD instances and many of them have a public looking glass powered by Bird's Eye as a standalone live example and also integrated with IXP Manager as a frontend consumer.
- INEX Cork IPv4 Router Collector: https://www.inex.ie/rc1-cork-ipv4/
- INEX Cork IPv6 Router Collector: https://www.inex.ie/rc1-cork-ipv6/
The landing pages for the above also document the API calls available.
You can see the IXP Manager integration for ~30 BIRD daemons at INEX at https://www.inex.ie/ixp/lg. GR-IX have also a public IXP Manager integration at: https://portal.gr-ix.gr/lg.
Complementary Projects
At the hackathon, the team also produced consumers of this API:
- https://github.com/dfkbg/birdseye - Python CLI consumer by Daniel Karrenberg
- https://github.com/ecix/birdseye - Python based web consumer by Annika Hannig
Rationale
Historically, IXPs made route collector and route server information available via looking-glasses. Over the past few years, many IXPs have selected BIRD as their route server / collector BGP daemon for a number of good reasons.
BIRD lacks an API to allow IXPs to provide these looking glass type tools. Moreover, this also affects an IXP's ability to monitor these routing daemons and peering participant sessions to them.
In a typical IXP, there will be six daemons per peering LAN:
- two route servers and one route collector
- separate daemon for ipv4 and ipv6
Having looked at existing BIRD LG implementations, INEX could not identify one that was designed with security in mind. Bird's Eye was written with security as a primary consideration.
Security
As this is intended to be deployed on an IXP's route server / route collector, security is vital. In that regard, the following considerations have been made:
- Natural rate limiting via caching by default. All queries are cached for a (configurable) period of at least one minute. This means the most you can hit the BIRD daemon for a specific request is once per minute.
- Built in rate limiter for queries that take variable parameters (e.g. route lookup).
- Strict parameter parsing and checking.
- Bundled
birdcbash script for safe use via sudo - the web process will require this to access the BIRD socket. birdcexecuted in restricted mode, to allow ''show'' commands only.
This API was not designed with the notion of making it publicly available. Ideally it would be run on an internal private network and fronted by one of the looking glass frontends above that consume this API, thereby providing multiple levels of API parameter validation.
Outlook
In an ideal world, this micro-service will be deprecated once the BIRD developers release a version with a built-in HTTP JSON API. This is a (hopefully) temporary solution to plug a gap.
Installation
This is a basic Lumen PHP application and the requirements are:
- PHP >= 8.1
- Mbstring PHP Extension
Download the release package (ensure you get the latest version rather than the example version listed below!) and install on your server. E.g.:
# E.g. Ubuntu 20.04 / 22.04 / 24.04 LTS
apt-get install php-cgi php-mbstring php-xml unzip
cd /srv
wget https://github.com/inex/birdseye/releases/download/vx.y.z/birdseye-vx.y.z.tar.bz2
tar jxf birdseye-vx.y.z.tar.bz2
cd birdseye-vx.y.z
chown -R www-data: storage # or the appropriate web user on your system
You'll need a web server to front it. Apache or Lighttpd are good choices. As the requirements are small and you most likely don't have any other use for a web server on the route server / collector boxes, Lighttpd has a small footprint:
apt-get install lighttpd
lighty-enable-mod fastcgi
lighty-enable-mod fastcgi-php
And configure Lighttpd - see data/configs/lighttpd.conf for an example.
Install from Source with Composer
If you prefer to install from source with composer:
git clone https://github.com/inex/birdseye.git
cd birdseye
composer install --prefer-dist --no-dev
chown -R www-data: storage # or the appropriate web user on your system
Configuration
We have tried to make configuration as easy as possible while allowing for the fact that there will typically be at least two BIRD processes to query on the same server. An explanation is easiest with an example:
Let's say there is a route server called rs1.inex.ie which provides both IPv4 and IPv6 services to two separate peering LANs.
To query the individual four daemons, we create DNS aliases as follows:
rs1-lan1-ipv4.inex.ie IN CNAME rs1.inex.ie
rs1-lan1-ipv6.inex.ie IN CNAME rs1.inex.ie
rs1-lan2-ipv4.inex.ie IN CNAME rs1.inex.ie
rs1-lan2-ipv6.inex.ie IN CNAME rs1.inex.ie
The micro-service will extract the first element of the hostname (e.g. rs1-lan1-ipv4, see beginning of bootstrap/app.php) and look for an environment file in the applications root directory (e.g. /srv/birdseye) named as follows for the above examples:
rs1-lan1-ipv4.inex.ie -> /srv/birdseye/birdseye-rs1-lan1-ipv4.env
rs1-lan1-ipv6.inex.ie -> /srv/birdseye/birdseye-rs1-lan1-ipv6.env
rs1-lan2-ipv4.inex.ie -> /srv/birdseye/birdseye-rs1-lan2-ipv4.env
rs1-lan2-ipv6.inex.ie -> /srv/birdseye/birdseye-rs1-lan2-ipv6.env
To create your env file, just (following the above naming convention):
cd /srv/birdseye
cp .env.example birdseye-rs1-lan1-ipv4.env
If you do not want to use hostnames and your Bird's Eye installation is behind a proxy, you can set the same element as above in the HTTP request header: X-BIRDSEYE. See the Varnish example below in the Serving Behind a Proxy section.
This example file has sane defaults but you need to edit it and fix the BIRDC parameter. In our naming case above (and for rs1-lan1-ipv4.inex.ie) and with Bird v1.x.y we'd set it to:
BIRDC="/usr/bin/sudo /srv/birdseye/bin/birdc -4 -s /var/run/bird/rs1-lan1-ipv4.ctl"
with the assumption that we've named and located the BIRD socket at that location. If you are using Bird v1.x.y with the IPv6 daemon, change the -4 switch to -6. From Bird's Eye v1.2.0 onwards, we now also support Bird v2; in this case use the -2 switch.
If you have a single BIRD daemon, you can skip DNS and just do:
cp .env.example .env
The last thing you need to do is give the www-data (or the appropriate web server user) user permission to run the birdc script. Edit /etc/sudoers and add (example):
www-data ALL=(ALL) NOPASSWD: /srv/birdseye/bin/birdc
Built in Looking Glass
This API has an optional built-in looking glass which utilises the API internally. This is mildly inefficient as it means a json_encode/json_decode of the same data but it proves the API, keeps us honest and the performance overhead is not excessive.
To enable it, set the following parameter to true in your configuration file:
LOOKING_GLASS_ENABLED=true
This will activate the looking glass routes, add a link to the header and make the looking glass available under the base URL /lg.
Disabling Caching on a Per-Request Basis
Caching was implemented to provide a natural rate-limiting mechanism for security and to reduce the load on BIRD.
In environments where you already have security in place (e.g. authenticated users on IXP Manager), you may want to disable caching for those requests. You can whitelist a set of IP addresses for this purpose by:
cp skipcache_ips.php.dist skipcache_ips.php
and then editing skipcache_ips.php to add your (for example) IXP Manager server's IP address.
If you then tag ?use_cache=0 to API requests, the cache will be avoided. Note that the results from BIRD will still be added to the cache so standard requests will still benefit with the freshest data.
Serving Behind a Proxy
The API requires prefixes (e.g. 192.0.2.0/24) to be submitted as GET requests and so they need to be URL encoded. Some web servers such as Apache squash these. A sample Apache configuration for proxying Bird's Eye requests is:
<VirtualHost 192.0.2.17:80 [2001:db8::17]:80>
ServerName rc1-lan1-ipv4.example.com
ServerAlias rc1-lan1-ipv6.example.com
AllowEncodedSlashes NoDecode
ProxyPass / http://10.8.5.126/ nocanon
ProxyPassReverse / http://10.8.5.126/
</VirtualHost>
The code to work out what URL should be used in links can be seen here. In essence:
- if the server is configured for HTTPS, then
https://is forced.- otherwise if
$_SERVER['HTTP_X_FORWARDED_PROTO'](X-Forwarded-Protoin the HTTP request header) ishttps, thenhttps://is forced. - otherwise it is
http://
- otherwise if
- i
