Port Forwarding with gobetween

As other blog posts on our site have mentioned, IPv4 addresses are becoming increasingly difficult to obtain. To make the situation more difficult, most communications on the internet is done through IPv4.

Cybera's Rapid Access Cloud provides each project with one public IPv4 address, known as a “Floating IP”. We call them this  because they're not tied to a single resource — they can float from one to another. However, it's sometimes helpful to be able to access multiple resources at once, instead of constantly moving the Floating IP around.

One way of doing this is to configure a virtual machine to act as a proxy or port forwarding server. You use this port forwarding server as a gateway to access other resources in the cloud which do not have a public IPv4 address. Illustratively, the setup looks like this:

We detail one way of doing this in our Advanced Guide, but this blog post will show an alternative way, using a tool called gobetween.

gobetween is a simple, but powerful, load balancing tool. It's written in Go, so it has the benefit of being packaged as a single binary executable — you don't have to install any packages or dependencies on your virtual machine to use it.

Building the Virtual Machines

Note: If you already have one or more virtual machines you would like to use for this, feel free to skip to the Installing and Configuring gobetween section.

To demo gobetween, we'll create three virtual machines and configure them in the setup illustrated above. One will host a Floating IP and act as the port forwarding server, providing access to the other two virtual machines.

To create these virtual machines, we'll use a tool called Terraform. To get started with Terraform, either check out the docs on its homepage or Cybera's ongoing series on Using Terraform.

To begin, create a directory on your desktop called "terraform-gob". Inside that directory, create a file called "main.tf". I have laid out below the code that you will use in this file.

The first step is to create a security group. This security group will allow traffic to ports 22, 2201, and 2202. Port 22 will provide access to SSH on the port forwarding server. 2201 and 2202 will provide SSH access to the other two virtual machines:

resource "openstack_networking_secgroup_v2" "pf" {
  name        = "pf"
  description = "pf"
}
 
resource "openstack_networking_secgroup_rule_v2" "allow-ssh" {
  direction = "ingress"
  ethertype = "IPv4"
  protocol = "tcp"
  port_range_min = 22
  port_range_max = 22
  remote_ip_prefix = "0.0.0.0/0"
  security_group_id = "${openstack_networking_secgroup_v2.sg_1.id}"
}
 
resource "openstack_networking_secgroup_rule_v2" "allow-2201" {
  direction = "ingress"
  ethertype = "IPv4"
  protocol = "tcp"
  port_range_min = 2201
  port_range_max = 2201
  remote_ip_prefix = "0.0.0.0/0"
  security_group_id = "${openstack_networking_secgroup_v2.sg_1.id}"
}
 
resource "openstack_networking_secgroup_rule_v2" "allow-2202" {
  direction = "ingress"
  ethertype = "IPv4"
  protocol = "tcp"
  port_range_min = 2202
  port_range_max = 2202
  remote_ip_prefix = "0.0.0.0/0"
  security_group_id = "${openstack_networking_secgroup_v2.sg_1.id}"
}

Next, create the port forwarding virtual machine:

resource "openstack_compute_instance_v2" "pf" {
  name = "pf"
  image_name = "Ubuntu 16.04"
  flavor_name = "m1.small"
  key_pair = "CHANGE"
  security_groups = ["${openstack_networking_secgroup_v2.pf.id}"]
 
  network {
    name = "default"
  }
}

Make sure to change the "key_pair" to a key pair you have configured in the Rapid Access Cloud.

Next, create a Floating IP address and associate it with the port forwarding virtual machine:

resource "openstack_networking_floatingip_v2" "pf" {
  pool = "public"
}
 
resource "openstack_compute_floatingip_associate_v2" "pf" {
  instance_id = "${openstack_compute_instance_v2.pf.id}"
  floating_ip = "${openstack_networking_floatingip_v2.pf.address}"
}

Now you'll need two more virtual machines:

resource "openstack_compute_instance_v2" "instance" {
  count = 2
  name = "${format("instance_%d", count.index+1)}"
  image_name = "Ubuntu 16.04"
  flavor_name = "m1.small"
  key_pair = "CHANGEME"
  security_groups = ["${openstack_networking_secgroup_v2.pf.id}"]
 
  network {
    name = "default"
  }
}

Instead of creating two explicit "openstack_compute_instance_v2" resources, the "count" parameter here will create two copies of this resource. Everything will be the same, except for their names.

Finally, add some "output" resources to display the information needed to continue with this exercise:

output "pf" {
  value = "${openstack_networking_floatingip_v2.pf.address}"
}
 
output "instances" {
  value = ["${openstack_compute_instance_v2.instance.*.access_ip_v4}"]
}

With all of the above in place, run the following:

$ cd terraform-gob
$ terraform apply

Once it's done running, you should see something similar to the following:

Outputs:

pf = 162.246.157.142
instances = [
    10.2.10.184,
    10.2.10.183
]

Installing and Configuring gobetween

Start by connecting to the port forwarding instance via SSH:

$ ssh ubuntu@162.246.157.142

Next, locate the download link for gobetween. Do that by first visiting the Downloads page and look for the "Linux x64" link. Rather than downloading the file to your workstation, copy the link location to your clipboard and run the following in your SSH session:

$ wget https://github.com/yyyar/gobetween/releases/download/0.4.0/gobetween_0.4.0_linux_amd64.tar.gz
$ tar xzvf gobetween*

Install the gobetween binary to /usr/sbin running the following command:

$ sudo cp gobetween_0.4.0_linux_amd64/gobetween /usr/sbin

To begin configuring gobetween, make a copy of the "gobetween.toml" configuration file:

$ sudo cp gobetween_0.4.0_linux_amd64/config/gobetween.toml /etc/

Next, open the file with a terminal-based editor, such as "vi"

$ sudo vi /etc/gobetween.toml

Locate the section called "[servers]". Delete the "servers.sample" and "servers.udpsample" entries in the file. Add the following:

[servers.ssh-1]
protocol = "tcp"
bind = "0.0.0.0:2201"
[servers.ssh-1.discovery]
  interval = "0s"
  kind = "static"
  static_list = [
      "10.2.10.183:22"
  ]
 
[servers.ssh-2]
protocol = "tcp"
bind = "0.0.0.0:2202"
[servers.ssh-2.discovery]
  interval = "0s"
  kind = "static"
  static_list = [
      "10.2.10.184:22"
  ]

Note the IP addresses in the "static_list" of each entry. You'll want to replace these IPs with the IP addresses which were in the Terraform output.

Once you've added the above, save the contents of the file and exit. Next, run the following:

$ sudo gobetween -c /etc/gobetween.toml

You should see an output similar to the following:

2017-06-05 21:24:15 [INFO ] (manager): Initializing...
2017-06-05 21:24:15 [INFO ] (server): Creating 'ssh-1': 0.0.0.0:2201 weight static none
2017-06-05 21:24:15 [INFO ] (scheduler): Starting scheduler
2017-06-05 21:24:15 [INFO ] (api): Starting up API
2017-06-05 21:24:15 [INFO ] (api): Starting HTTP server :8888
2017-06-05 21:24:15 [INFO ] (server): Creating 'ssh-2': 0.0.0.0:2202 weight static none
2017-06-05 21:24:15 [INFO ] (scheduler): Starting scheduler
2017-06-05 21:24:15 [INFO ] (manager): Initialized

Once it's up and running, open a new terminal and connect to the internal virtual machines:

$ ssh  -p 2201
$ ssh  -p 2202

And there you have it! You’re now able to connect to multiple resources in the Rapid Access Cloud while only using one public IP address.

And you're not limited to just two virtual machines. You can continue adding entries to the gobetween.toml configuration file to suit your requirements.

Installing gobetween as a Service

Return to the terminal session that has gobetween running and press ctrl-c. You'll notice this stops gobetween and you're no longer able to reach your internal instances. Running gobetween on the command-line like this certainly works, but it's not a permanent solution.

If you'd like to run gobetween as an actual service on your virtual machine, run the following commands:

$ sudo wget -O /etc/systemd/system/gobetween.service https://raw.githubusercontent.com/yyyar/gobetween/master/config/systemd/gobetween.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable gobetween.service
$ sudo systemctl start gobetween

gobetween will now run as a permanent service in your virtual machine. If you make changes to the configuration file, you must restart the gobetween service by doing:

$ sudo systemctl restart gobetween

Conclusion

This blog post showed how to create a port forwarding service in the Rapid Access Cloud using a tool called gobetween. By creating a service such as this, you can gain access to more than one resource in the Rapid Access Cloud via the public internet while still only using only one public IPv4 address.