Border Gateway Protocol (BGP) is the routing protocol that powers the internet, exchanging routing information between autonomous systems (AS). On RHEL 8, the BIRD Internet Routing Daemon provides a lightweight, production-grade BGP implementation available through the EPEL repository. This tutorial walks through installing BIRD, writing a BGP configuration with neighbor relationships and route filters, verifying adjacencies with the birdc shell, and opening the BGP port through firewalld. By the end you will have a working iBGP or eBGP session suitable for lab environments, home labs, or edge routing scenarios.

Prerequisites

  • Two RHEL 8 servers (or VMs) with static IP addresses on a shared network segment
  • Root or sudo access on both nodes
  • EPEL 8 repository enabled (dnf install -y epel-release)
  • Basic familiarity with IP routing concepts (AS numbers, prefixes, next-hop)
  • firewalld running and managing the active zone

Step 1 — Install BIRD from EPEL

BIRD is not in the default RHEL 8 BaseOS or AppStream repositories, so you must enable EPEL first. Once EPEL is active, install the bird package and enable its systemd service so it starts at boot.

dnf install -y epel-release
dnf install -y bird
systemctl enable --now bird
systemctl status bird

Step 2 — Write the Base BIRD Configuration

BIRD’s main configuration file is /etc/bird.conf. Replace the default file content with the skeleton below, substituting your own router ID and AS number. The router id is typically the primary loopback or management IP of the local node.

# /etc/bird.conf  — Node 1 (192.168.100.1, AS 65001)

router id 192.168.100.1;

# Kernel protocol — sync BIRD routes into the OS routing table
protocol kernel {
    ipv4 {
        export filter {
            accept;
        };
    };
}

# Device protocol — required to detect directly connected interfaces
protocol device {
    scan time 10;
}

# Connected protocol — redistribute directly connected prefixes into BIRD
protocol direct {
    ipv4;
}

# BGP peer — iBGP session to Node 2
protocol bgp ibgp_node2 {
    local 192.168.100.1 as 65001;
    neighbor 192.168.100.2 as 65001;   # same AS = iBGP

    ipv4 {
        import filter {
            accept;
        };
        export filter {
            accept;
        };
    };
}

Step 3 — Configure the Second Node

On Node 2 (192.168.100.2), create a mirrored configuration pointing back to Node 1. In an iBGP topology both nodes share the same AS number. For eBGP, assign a different AS to each node.

# /etc/bird.conf  — Node 2 (192.168.100.2, AS 65001)

router id 192.168.100.2;

protocol kernel {
    ipv4 { export filter { accept; }; };
}

protocol device {
    scan time 10;
}

protocol direct {
    ipv4;
}

protocol bgp ibgp_node1 {
    local 192.168.100.2 as 65001;
    neighbor 192.168.100.1 as 65001;

    ipv4 {
        import filter { accept; };
        export filter { accept; };
    };
}

# Reload configuration on both nodes after saving
birdc configure

Step 4 — Open the BGP Port in firewalld

BGP uses TCP port 179. Without this rule, the TCP handshake will be blocked and the session will stay in Active state indefinitely. Apply the rule to the zone that covers your BGP-facing interface — typically public or internal.

# Allow BGP (TCP 179) permanently
firewall-cmd --add-port=179/tcp --permanent
firewall-cmd --reload

# Verify the rule is present
firewall-cmd --list-ports

Step 5 — Verify BGP Sessions and Routes with birdc

The birdc command-line tool connects to the running BIRD daemon over a Unix socket. Use it to inspect protocol state, view the routing table, and confirm that prefixes are being exchanged correctly between peers.

# Enter the BIRD CLI
birdc

# Inside birdc — show all protocol states
show protocols

# Show only BGP protocols
show protocols all ibgp_node2

# Show the full routing table
show route

# Show routes exported to the kernel table
show route export kernel1

# Reload the config without restarting the daemon
configure

# Exit the BIRD CLI
exit

A healthy BGP session will display Established in the show protocols output. If you see Active or Idle, verify firewall rules, IP reachability (ping), and that both configuration files reference the correct neighbor IP addresses.

Step 6 — Add Import and Export Filters

Accepting all routes with a bare accept is fine for a lab but unsafe in production. The example below adds a simple prefix-list filter that only imports routes within 10.0.0.0/8 and only exports the node’s own loopback prefix.

# Add to /etc/bird.conf before the BGP protocol block

define MY_LOOPBACK = 192.168.100.1/32;

filter import_from_peer {
    if net ~ [ 10.0.0.0/8+ ] then accept;
    reject;
}

filter export_to_peer {
    if net = MY_LOOPBACK then accept;
    reject;
}

# Then update the BGP protocol block:
protocol bgp ibgp_node2 {
    local 192.168.100.1 as 65001;
    neighbor 192.168.100.2 as 65001;

    ipv4 {
        import filter import_from_peer;
        export filter export_to_peer;
    };
}

# Apply the updated config
birdc configure

Conclusion

You have installed the BIRD daemon on RHEL 8, written a working BGP configuration with router ID, AS numbers, connected/kernel/direct protocols, and a neighbor block, verified the session is Established using the birdc CLI, and hardened the setup with import/export prefix filters. The BGP TCP port is open in firewalld so sessions survive reboots. This foundation scales from a simple two-node iBGP lab to more complex topologies with route reflectors and multiple AS peers.

Next steps: Configuring OSPF with FRRouting on RHEL 8, Setting Up MPLS with Linux Traffic Control, and Building a Route Reflector with BIRD.