Recently I got myself in a situation where I was working on an OpenStack cluster where my tenant had only a single floating IP available.

I viewed this as a good opportunity to play with bastions and proxies. In this post I'll only deal with the bastion part.

All hosts had internal IPs but only one had a public IP.

I recreated this scenario on Atlantic.net - here's how I did it.

Environment:

You only need 2 instances to try this - one I'm going to call the " bastion", the other one " private1" as it will be cut off from the internet and only accessible through SSH from the bastion.

Part 1 - Set private IPs and test redir:

On private1 test your network settings first (we'll make them permanent later)

ifconfig eth1 10.42.226.2 netmask 255.255.255.0

try pinging your private ip to make sure it works:

[root@private1 ~]# ping 10.42.226.2 -c1
PING 10.42.226.2 (10.42.226.2) 56(84) bytes of data.
64 bytes from 10.42.226.2: icmp_seq=1 ttl=64 time=0.019 ms

--- 10.42.226.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.019/0.019/0.019/0.000 ms

now make those permanent by editing /etc/sysconfig/network-scripts/ifcfg-eth1 (second interface)

add the lines:

IPADDR=10.42.226.2
NETMASK=255.255.255.0

The file should now look like this:

# Virtio Network Device Private Interface
DEVICE=eth1
BOOTPROTO=static
HWADDR=00:00:0a:3a:26:e3
ONBOOT=yes

IPADDR=10.42.226.2
NETMASK=255.255.255.0

reboot your instance to make sure everything worked.

now on the bastion do the same:

ifconfig eth1 10.42.226.1 netmask 255.255.255.0

and add the following lines to the file /etc/sysconfig/network-scripts/ifcfg-eth1

IPADDR=10.42.226.1
NETMASK=255.255.255.0

and ping private1

ping 10.42.226.2
PING 10.42.226.2 (10.42.226.2) 56(84) bytes of data.
64 bytes from 10.42.226.2: icmp_seq=1 ttl=64 time=1.57 ms
^C
--- 10.42.226.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 605ms
rtt min/avg/max/mdev = 1.577/1.577/1.577/0.000 ms

excellent.

Now on private1, kill all public networking by bringing down interface eth0:

ifdown eth0

also to make sure it's not coming back up edit the file /etc/sysconfig/network-scripts/ifcfg-eth0

and change the line:

ONBOOT=yes

to:

ONBOOT=no

You'll notice that networking died! perfect!!!!

Now let's use redir on bastion to redirect connections to private1

yum install epel-release -y
yum install redir -y

With redir now in place let's create a forwarder:

redir --lport 2201 --cport=22 --caddr=10.42.226.2 --debug

Confirm that redir created listening port 2201 by running netstat -ntlp | grep redir, you should get something like:

tcp 0 0 0.0.0.0:2201 0.0.0.0:* LISTEN 1123/redir

Sweet! Now you should be able to connect to port 2201 over SSH and that will take you to private1.

ssh 69.87.216.89 -p 2201

Part 2 - Daemonize redir...using daemonize and create a control script:

First install the daemonize package:

yum install daemonize -y

Now test daemonize using the redir command above:

daemonize -a -e /var/log/redir-ssh-2201 -o /var/log/redir-ssh-2201 -p /var/run/redir-ssh-2201.pid -l /var/lock/subsys/redir-ssh-2201 /usr/sbin/redir --lport 2201 --cport=22 --caddr=10.42.226.2

Explanation of the above options (stolen from daemonize's help)

-a Append to, instead of overwriting, output files. Ignored 
 unless -e and/or -o are specified.
-e <stderr> Send daemon's stderr to file <stderr>, instead of /dev/null.
-o <stdout> Send daemon's stdout to file <stdout>, instead of /dev/null.
-p <pidfile> Save PID to <pidfile>.
-l <lockfile> Single-instance checking using lockfile <lockfile>.now that we have confirmed that this worked, let's set up monit to make sure our process keeps on running:

Let's add a start/stop script for our redir script: /usr/local/bin/redir-ssh-2201

#!/bin/bash

daemonize=/usr/sbin/daemonize
redir=/usr/sbin/redir
local_port=2201
lockfile=/var/lock/subsys/redir-ssh-$local_port.lock
logfile=/var/log/redir-ssh-$local_port.log
pid=/var/run/redir-ssh-$local_port.pid
forward_port=22
forward_ip=10.42.226.2

start() {
    echo -n "Starting redir for local port $local_port, forward port $forward_port and forward_ip $forward_ip "
    daemonize -a -e $logfile -o $logfile -p $pid -l $lockfile $redir --lport=$local_port --cport=$forward_port --caddr=$forward_ip
        if [ $? -eq 0 ]; then
        echo -e '\t\t\t[  OK  ]'
    fi
}

    echo -n "Stopping redir for local port $local_port, forward port $forward_port and forward_ip $forward_ip "
    kill `cat $pid`
        if [ $? -eq 0 ]; then
                echo -e '\t\t\t[  OK  ]'
        fi
}

# See how we were called.
case "$1" in
start)
    start
    ;;
    ;;
    start
    ;;
*)
    exit 2
esac

Part 3 - Install and setup Monit to monitor the daemonized redir

Install Monit in the usual way:

yum install monit -y

Make sure it's set to start along with the host:

chkconfig monit on

Add the following Monit configuration in /etc/monit.d/redir-2201

# Check redir-ssh-2201
check process redir-ssh-2201 pidfile /var/run/redir-ssh-2201.pid
 start program = "/usr/local/bin/redir-ssh-2201 start"
 stop program = "/usr/local/bin/redir-ssh-2201 stop"

Now start Monit with:

/etc/init.d/monit start

Done!