High Availability on Vultr with Floating IP and BGP using BIRD 2.0

Updated on August 26, 2024
High Availability on Vultr with Floating IP and BGP using BIRD 2.0 header image

BIRD 2.0 was out with the first experimental version in 2016. Currently, BIRD 2.0 is stable and has a lot of improvement in BGP performance and security enhancement. Let's see how you can enable high availability for your application on Vultr using Floating IP and BGP in BIRD 2.0. If you still need BIRD version 1, check out the High Availability on Vultr with Floating IP and BGP article.

What is Floating IP

A floating IP is an IP that can act as a load-balancing address. It can route to any server in the same network system.

Why Floating IP

With floating IP, if the primary server that the IP routes to is down, the IP can route to another server in the same network. The user traffic comes to another server instead of waiting for the primary server to be up again. Using floating IP brings a smooth user experience to your application and helps your app to achieve high availability.

Note
High availability IP routing with Floating IPs is only supported when the servers are located within the same datacenter. Floating IPs will not function if the servers are in different datacenter locations.

What is BGP

BGP stands for Border Gateway Protocol, which is a routing protocol that enables network stability in your system. With BGP, the routers can quickly initiate another connection with another server and send data packets to the new server immediately.

What is Vultr reserved IP

Vultr Reserved IP is the static and permanent IP that you can use. You can use Vultr reserved IP as a floating IP to achieve high availability for your system.

Prerequisites

To follow the steps in this guide, you need the following:

  • A Vultr account with BGP usage is ready. Please complete this form to enable BGP for your account.
  • One reserved IP v4 address and one reserved IP v6 address. Check out this guide for how to reserve IP addresses with Vultr. Note that the reserved IPs must be in the same region as your Vultr servers.
  • Four Ubuntu version 20.04 server instances that are ready to use in Vultr platform. Three servers for applying Floating IP with IP v4 and one server for IP v6. Following this guide, you can use other Linux distros, but the commands and configuration files might differ.

Example values

Replace these example values with the ones you own throughout the doc.

  • Server 1 (IP v4 address): 45.76.146.91
  • Server 2 (IP v4 address): 139.180.213.161
  • Server 3 (IP v4 address): 139.180.186.3
  • ASN for the Vultr account: 4288000203
  • BGP password: q9BWVUCaiV1v8F2y
  • Reserved IP v4: 207.148.65.177
  • Reserved IP v6: 2401:c080:1400:54af::/64
  • Server 4 (IP v6 address): 2401:c080:1400:6398:5400:04ff:fe40:5b7e

Vultr's BGP Info

  • ASN for Vultr side: 64515 (This is the value for Vultr cloud, change it with 20473 if you're using Vultr bare metal).
  • IP v4 address for Vultr side: 169.254.169.254 (This is the value for Vultr cloud, change it with 169.254.1.1 if you're using Vultr bare metal).

1. Configure a dummy network

  1. Accessing your server one as root, then run the below commands to create a dummy network interface:

     # ip link add dev dummy1 type dummy
  2. Bring up the interface:

     # ip link set dummy1 up
  3. Bind the dummy interface to the Reserved IP address. Replace the example 45.76.146.91 with your reserved IP:

     # ip addr add dev dummy1 45.76.146.91/32
  4. Confirm the network configuration:

     # ip addr show dev dummy1
     3: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
     link/ether 06:75:41:99:bd:ff brd ff:ff:ff:ff:ff:ff
     inet 207.148.65.177/32 scope global dummy1
          valid_lft forever preferred_lft forever
     inet6 fe80::475:41ff:fe99:bdff/64 scope link 
          valid_lft forever preferred_lft forever

2. Configure BIRD 2.0

  1. Enable your firewall to permit traffic on TCP port 179:

     # ufw allow 179
     # ufw status verbose

    You should see the following output in the console:

     Status: active
     Logging: on (low)
     Default: deny (incoming), allow (outgoing), disabled (routed)
     New profiles: skip
    
     To                         Action      From
     --                         ------      ----
     22                         ALLOW IN    Anywhere                  
     179                        ALLOW IN    Anywhere                  
     22 (v6)                    ALLOW IN    Anywhere (v6)             
     179 (v6)                   ALLOW IN    Anywhere (v6)
  2. Install BIRD 2.0 into your Ubuntu server instance:

     # apt update
     # apt install bird2
     # bird --version

    You should see similar output:

      BIRD version 2.0.7
  3. Update BIRD 2.0 configuration for your Ubuntu server instance:

     # nano /etc/bird/bird.conf

    Replace your current bird.conf with the one below(Note that you need to change the example values with your values):

     log syslog all;
    
     router id 45.76.146.91;
    
    
     protocol device {
     }
    
     protocol direct {
     # Disable by default
     ipv4;     # Connect to default IPv4 table
     #ipv6;      # ... and to default IPv6 table
     interface "dummy1";
     }
    
     protocol kernel {
     ipv4 {      # Connect protocol to IPv4 table by channel
     export all; # Export to protocol. default is export none
     };
     }
    
     protocol kernel {
     ipv6 { export all; };
     }
    
    
     protocol static {
     ipv4;     # Again, IPv4 channel with default options
     }
    
     protocol bgp vultr
     {
     local as 4288000203;
     source address 45.76.146.91;
     ipv4 {
     import none;
     export all;
     };
     graceful restart on;
     multihop 2;
     neighbor 169.254.169.254 as 64515;
     password "q9BWVUCaiV1v8F2y";
     }

Here router id and source address values are the IP v4 address of your server one. The local as value is the ASN for your Vultr account. The password value is the BGP password of your Vultr account.

3. Verify BGP connectivity

  1. Start BIRD 2.0 service:

     # systemctl start bird
  2. Check that you successfully established the BGP session:

     # birdc show proto all vultr

    You should see the following output:

     BIRD 2.0.7 ready.
     Name       Proto      Table      State  Since         Info
     vultr      BGP        ---        up     00:00:28.089  Established   
     BGP state:          Established
     Neighbor address: 169.254.169.254
     Neighbor AS:      64515
     Local AS:         4288000203
     Neighbor ID:      45.32.98.8
     Local capabilities
       Multiprotocol
         AF announced: ipv4
       Route refresh
       Graceful restart
         Restart time: 120
         AF supported: ipv4
         AF preserved:
       4-octet AS numbers
       Enhanced refresh
       Long-lived graceful restart
     Neighbor capabilities
       Multiprotocol
         AF announced: ipv4
       Route refresh
       Extended message
       Graceful restart
       4-octet AS numbers
       ADD-PATH
         RX: ipv4
         TX:
       Enhanced refresh
       Long-lived graceful restart
         LL stale time: 0
         AF supported:
         AF preserved: ipv4
     Session:          external multihop AS4
     Source address:   45.76.146.91
     Hold timer:       100.101/180
     Keepalive timer:  4.679/60
     Channel ipv4
     State:          UP
     Table:          master4
     Preference:     100
     Input filter:   REJECT
     Output filter:  ACCEPT
     Routes:         0 imported, 1 exported, 0 preferred
     Route change stats:     received   rejected   filtered    ignored   accepted
       Import updates:              1          0          1          0          0
       Import withdraws:            0          0        ---          1          0
       Export updates:              1          0          0        ---          1
       Export withdraws:            0        ---        ---        ---          0
     BGP Next hop:   45.76.146.91
     IGP IPv4 table: master4

4. Test the Floating IP

  1. Verify BIRD 2.0 is advertising the route to your floating IP:

     # birdc show route

    You should see the following output:

     BIRD 2.0.7 ready.
     Table master4:
     207.148.65.177/32    unicast [direct1 2022-12-22] * (240)
     dev dummy1
  2. Open another terminal in your local environment to test the connection to the reserved IP:

     # ping 207.148.65.177

    You should see a similar output:

     PING 207.148.65.177 (207.148.65.177) 56(84) bytes of data.
     64 bytes from 207.148.65.177: icmp_seq=26 ttl=54 time=47.6 ms
     64 bytes from 207.148.65.177: icmp_seq=27 ttl=54 time=48.4 ms
     64 bytes from 207.148.65.177: icmp_seq=28 ttl=54 time=48.7 ms
     64 bytes from 207.148.65.177: icmp_seq=29 ttl=54 time=46.5 ms
     64 bytes from 207.148.65.177: icmp_seq=30 ttl=54 time=48.2 ms
     64 bytes from 207.148.65.177: icmp_seq=31 ttl=54 time=48.9 ms
  3. Bring the dummy service down from your server 1 terminal:

     # ip link set dummy1 down

    The ping process fails to capture data packets at the other terminal.

  4. Enable the dummy service again.

     # ip link set dummy1 up

    The ping process successfully capture data packets again.

  5. Similarly, install and configure BIRD 2.0 for servers two and three.

  6. Enable/Disable the dummy service in your servers two and three. You should see a similar result as with server one.

Now you successfully set up the three servers with the reserved IP address. If one or even two of your servers are down, user traffic going through the reserved IP will come to the remaining servers.

Use BGP Prepends to Assign Traffic Priority

What if you want to control the distribution traffic of user requests to your servers? In that case, you can use BGP prepends. Let's say you want:

  • Your server one is the primary instance that receives all traffic
  • Your server two is the second instance that receives all traffic if server 1 is down
  • Your server three is the third instance that receives all traffic if both server one and server 2 are down
  1. Update the BIRD 2.0 configuration for your server two:

     # nano /etc/bird/bird.conf

    Add the below content to protocol bgp vultr block (Update the BGP 4288000203 value with your BGP value for your Vultr account):

     export filter {
    
     # Artificially increase path length
    
     # by prepending the local AS number.
    
     bgp_path.prepend(4288000203);
    
     accept;
    
     };
  2. Your protocol bgp vultr configuration for server two should look like the following now:

     protocol bgp vultr
     {
     local as 4288000203;
     source address 139.180.213.161;
     ipv4 {
     import none;
     export all;
     export filter {
    
         # Artificially increase path length
    
         # by prepending the local AS number.
    
         bgp_path.prepend(4288000203);
    
         accept;
    
       };
       };
     graceful restart on;
     multihop 2;
     neighbor 169.254.169.254 as 64515;
     password "q9BWVUCaiV1v8F2y";
    }
  3. For server three, add two lines of bgp_path.prepend(4288000203) instead of one line. Your protocol bgp vultr configuration for server three should look like the following:

     protocol bgp vultr
     {
     local as 4288000203;
     source address 139.180.186.3;
     ipv4 {
     import none;
     export all;
     export filter {
    
         # Artificially increase path length
    
         # by prepending the local AS number.
    
         bgp_path.prepend(4288000203);
         bgp_path.prepend(4288000203);
    
         accept;
    
     };
     };
     graceful restart on;
     multihop 2;
     neighbor 169.254.169.254 as 64515;
     password "q9BWVUCaiV1v8F2y";
    }

And that's how you apply BGP prepends for BIRD 2.0 version for your servers.

Using Floating IPs with IPv6

Applying Floating IPs with IPv6 is similar to using IPv4. On your server four, you need to:

  1. Create a dummy network interface:

     # ip link add dev dummy1 type dummy
  2. Bring the interface up:

     # ip link set dummy1 up
  3. Bind the dummy interface to the number of IP v6 addresses you want. Refer to Vultr IPv6 calculator to see the available address for your IPv6 value. Let's bind the dummy interface to two IPv6 addresses, then.

     # ip addr add dev dummy1 2401:c080:1400:54af::1/64
     # ip addr add dev dummy1 2401:c080:1400:54af::2/64
  4. Verify the interface:

     # ip addr show dev dummy1

    You should see a similar output:

     4: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen  1000
     link/ether ce:f6:df:be:b6:4f brd ff:ff:ff:ff:ff:ff
     inet6 2401:c080:1400:54af::2/64 scope global 
     valid_lft forever preferred_lft forever
     inet6 2401:c080:1400:54af::1/64 scope global 
     valid_lft forever preferred_lft forever
     inet6 fe80::ccf6:dfff:febe:b64f/64 scope link 
     valid_lft forever preferred_lft forever

BIRD 2.0 configuration with IPv6

  1. Open up the BIRD 2.0 configuration file for server 4:

     # nano /etc/bird/bird.conf
  2. Replace your existing content with the below:

     log syslog all;
     router id 45.76.189.34;
    
     protocol device {
     }
    
     protocol direct {
       # Disable by default
     #ipv4;      # Connect to default IPv4 table
     ipv6;
     # ... and to default IPv6 table
     interface "dummy1";
     }
    
     protocol kernel {
     ipv4 {      # Connect protocol to IPv4 table by channel
         export all; # Export to protocol. default is export none
      };
      }
    
      protocol kernel {
      ipv6 { export all; };
      }
    
      protocol static {
      ipv4;     # Again, IPv4 channel with default options
      }
    
      protocol bgp vultr
      {
      local as 4288000203;
      source address 2401:c080:1400:6398:5400:04ff:fe40:5b7e;
      ipv6 {
      import none;
      export all;
      };
      graceful restart on;
      multihop 2;
      neighbor 2001:19f0:ffff::1 as 64515;
      password "q9BWVUCaiV1v8F2y";
      }

    Note that you need to change the example values with your values. The router id value is the IP v4 address of server four. The local as value is the ASN value for your Vultr account. The source address value is the IP v6 address of your server four. The password value is your Vultr BGP password.

  3. Start the BIRD 2.0 service:

     # systemctl start bird
  4. Check the BIRD 2.0 route:

     # birdc show route

    You should see a similar output below, which shows the configured IPv6 address:

     BIRD 2.0.7 ready.
     Table master6:
     2401:c080:1400:54af::/64 unicast [direct1 2022-12-22] * (240)
     dev dummy1
  5. Check whether the configuration of Vultr protocol for IPv6 is successful:

     # birdc show proto all vultr

    You should see a similar output:

     BIRD 2.0.7 ready.
     Name       Proto      Table      State  Since         Info
     vultr      BGP        ---        up     2022-12-22    Established   
     BGP state:          Established
     Neighbor address: 2001:19f0:ffff::1
     Neighbor AS:      64515
     Local AS:         4288000203
     Neighbor ID:      45.32.98.19
     Local capabilities
       Multiprotocol
         AF announced: ipv6
       Route refresh
       Graceful restart
         Restart time: 120
         AF supported: ipv6
         AF preserved:
       4-octet AS numbers
       Enhanced refresh
       Long-lived graceful restart
     Neighbor capabilities
       Multiprotocol
         AF announced: ipv6
       Route refresh
       Extended message
       Graceful restart
       4-octet AS numbers
       ADD-PATH
         RX: ipv6
         TX:
       Enhanced refresh
       Long-lived graceful restart
         LL stale time: 0
         AF supported:
         AF preserved: ipv6
     Session:          external multihop AS4
     Source address:   2401:c080:1400:6398:5400:4ff:fe40:5b7e
     Hold timer:       149.640/180
     Keepalive timer:  34.947/60
     Channel ipv6
     State:          UP
     Table:          master6
     Preference:     100
     Input filter:   REJECT
     Output filter:  ACCEPT
     Routes:         0 imported, 1 exported, 0 preferred
     Route change stats:     received   rejected   filtered    ignored   accepted
       Import updates:              1          0          1          0          0
       Import withdraws:            0          0        ---          1          0
       Export updates:              1          0          0        ---          1
       Export withdraws:            0        ---        ---        ---          0
     BGP Next hop:   2401:c080:1400:6398:5400:4ff:fe40:5b7e
     IGP IPv6 table: master6
  6. Open a new terminal from your local environment, then run the below command to test the connection to the IPv6 reserved IP.

      # ping6 2401:c080:1400:54af::1

    You should see the output below:

      64 bytes from 2401:c080:1400:54af::1: icmp_seq=2 ttl=59 time=0.548 ms
      64 bytes from 2401:c080:1400:54af::1: icmp_seq=3 ttl=59 time=0.528 ms
      64 bytes from 2401:c080:1400:54af::1: icmp_seq=4 ttl=59 time=0.483 ms
      64 bytes from 2401:c080:1400:54af::1: icmp_seq=5 ttl=59 time=0.467 ms
      64 bytes from 2401:c080:1400:54af::1: icmp_seq=6 ttl=59 time=0.528 ms
      64 bytes from 2401:c080:1400:54af::1: icmp_seq=7 ttl=59 time=0.551 ms
      64 bytes from 2401:c080:1400:54af::1: icmp_seq=8 ttl=59 time=0.468 ms
      64 bytes from 2401:c080:1400:54af::1: icmp_seq=9 ttl=59 time=0.535 ms

    Checking with the other ipv6 address:

      # ping6 2401:c080:1400:54af::2

    You should see a similar result:

      64 bytes from 2401:c080:1400:54af::2: icmp_seq=1 ttl=59 time=0.500 ms
      64 bytes from 2401:c080:1400:54af::2: icmp_seq=2 ttl=59 time=0.480 ms
      64 bytes from 2401:c080:1400:54af::2: icmp_seq=3 ttl=59 time=0.689 ms
      64 bytes from 2401:c080:1400:54af::2: icmp_seq=4 ttl=59 time=0.442 ms

Now you have successfully applied floating IP IPv4 and IPv6 using BIRD 2.0 with Vultr reserved IPs. Vultr also provides APIs to help you manage your reserved IPs. You can:

  • Create a new reserved IP.

  • List all reserved IPs in your account.

  • Get information about a reserved IP.

  • Convert the IP address on an instance into a reserved IP.

  • Delete a reserved IP.