How to use a routed network for a VPS

This article is about how to configure a VPS host and VPS guests to use a routed network without spoiling IP addresses. Also a section is included to use BGP to announce the IP you have to the routers you use. A configuration like this is also used for the server where this site is located (in the Coloclue network). I do not include how to install a VPS host, only the network part is covered.

Note 1: All examples are based on Debian, but should also work on other Linux distributions.
Note 2: The examples are based on IPv4, but should also apply to IPv6 with small changes.


Configuring the VPS host

Install packages if you want to use vlans:

apt-get install vlan

Now create a new interface in /etc/network/interfaces, this interface is used for all virtual machines to connect to. The used IP will be the gateway for your virtual machines.

auto vlanbr

iface vlanbr inet static

bridge_ports none
bridge_stp off
bridge_fd 0
bridge_maxwait 0

Prepare your VPS host for forwarding and NAT for outgoing connections:

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf

echo 1 > /proc/sys/net/ipv4/ip_forward

iptables -A INPUT -d -i vlanbr -j ACCEPT
iptables -A INPUT -s -i vlanbr -j ACCEPT
iptables -A INPUT -s -i eth0 -j ACCEPT
iptables -A FORWARD -s -i vlanbr -o eth0 -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -d -o eth0 -j LOG
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -d -o vlanbr -j ACCEPT
iptables -A OUTPUT -d -o vlanbr -j ACCEPT
iptables -A OUTPUT -d -o eth0 -j ACCEPT

iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE

Per IP that should point to your VPS you will do something like:

/sbin/route add -net netmask gw

In this example should be replaced with your public ip you want to route to your VPS. is the internal IP for your VPS.

Per VPS you also want a line like this if you want outgoing connections from that VPS to use the public IP:

iptables -t nat -I POSTROUTING -s -o eth0 -j SNAT --to-source

In this example the IP addresses have the same meaning as the previous example. eth0 is the interface used for all outgoing connections.

This is everything that is needed for routing IP addresses to your VPS guests from the VPS host. Now we will first at BGP on the VPS host and after that we will configure the important sections on the VPS guest.

BGP on the VPS host

Install required package (bird6 is used for IPv6, not covered besides the installation):

apt-get install bird bird6

Configure bird. You can base it on the example below, comment lines start with # and are used to explain the line just above it.

log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug };
router id;
# Replace with your public IPv4 address for the VPS host. If only a private IP is available check that it is uniq in your environment.

function is_owned_by_me()
prefix set owned_by_me_space;
owned_by_me_space = [{30,32},{31,32} ];
# Replace and with the prefixes that should be routed to you. Also mention the largest and biggest announcements that are allowed within { and }. The first example allows a /30, /31 and /32 to be announced for this range. In the last example only /31 and /32 are allowed.
if net ~ owned_by_me_space then return true;
return false;

filter ebgp_import {
if ( is_owned_by_me () ) then accept;

template bgp ebgp {
local as 65151;
# Define a local as, if you don't have an AS from a RIR use something that is uniq in your network. If needed ask what you need to use at your network supplier/network admin.
import all;
export filter ebgp_import;
source address;
# Replace with your public IPv4 address for the VPS host. If only a private IP is available check that it is uniq in your environment. This should be the address used for communication between the host and the routers.
next hop self;

protocol bgp dcg1 from ebgp {
neighbor as 8283;
# Replace with the IP of the first router that is your uplink
protocol bgp dcg2 from ebgp {
neighbor as 8283;
# Replace with the IP of the second router that is your uplink

protocol kernel {
learn; # Learn all alien routes from the kernel
persist; # Don't remove routes on bird shutdown
scan time 20; # Scan kernel routing table every 20 seconds
import all; # Default is import all
export all; # Default is export none, changed to all
# This pseudo-protocol watches all interface up/down events.
protocol device {
scan time 10; # Scan interfaces every 10 seconds
protocol direct {
interface "eth0";

After this restart bird (/etc/init.d/bird restart).

The host is now configured. Now go to the VPS guests.

The VPS guests network configuration

For the installation configure everything to use the internal IP ( in the example). After that add the following to /etc/network/interfaces and bring up the new interface.

auto lo:0
iface lo:0 inet static

Per public/external IP add an interface with the IP.

Now run the following commands and it should work:

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf

echo 1 > /proc/sys/net/ipv4/ip_forward

Now everything should be configured.