Archive for March 2013

SSHing efficiently   6 comments

I personally have a numerous number of hosts which I sometimes have to SSH to. It can get rather confusing and inefficient if you get lost among them.

I’m going to show you here how you can get your SSHing to be heaps more efficient with just 5 minutes of your time.


In $HOME/.ssh/config I usually store all my hosts in such a way:

Host host1
    Port 1234
    User root

Host host2
    Port 5678
    User root

Host host3
    Port 9012
    User root

You obviously got the idea. So if I’d like to ssh to host2, all I have to do is:

ssh host2

That will ssh to – saves a bit of time.

I usually manage all of my hosts in that file. Makes life simpler, even use git if you feel like it…

Auto complete

I’ve added to my .bashrc the following:

_ssh_hosts() {
    local cur="${COMP_WORDS[COMP_CWORD]}"
    local ssh_hosts=`grep ^Host ~/.ssh/config | cut -d' ' -f2 | xargs`
    [[ ! ${cur} == -* ]] && COMPREPLY=( $(compgen -W "${ssh_hosts}" -- ${cur}) )

complete -o bashdefault -o default -o nospace -F _ssh_hosts ssh 2>/dev/null \
    || complete -o default -o nospace -F _ssh_hosts ssh
complete -o bashdefault -o default -o nospace -F _ssh_hosts scp 2>/dev/null \
    || complete -o default -o nospace -F _ssh_hosts scp

Sweet. All that you have to do now is:

$ ssh TAB TAB
host1 host2 host3

We are a bit more efficient today.

Posted March 31, 2013 by malkodan in Bash, Linux, System Administration

Tagged with , , ,

NetworkManager-ssh   3 comments

SSH is amazing

Show me one unix machine today without SSH. It’s everywhere, for a reason.
OpenSSH specifically allows you to do so much with it. What would we have done without SSH?

OpenSSH Tunnelling and full VPN

Tunnelling with SSH is really cool, utilizing the secure SSH connection you can virtually secure any TCP/IP connection using port forwarding (-R and -L):

However for full VPN support, you can use -w which opens a tun/tap device on both ends of connection, allowing you potentially to have all of your network passing via your SSH connection. In other words – full VPN support for free!!!

Server configuration

On the server, the configuration would be minimal:

  • Allow tunnelling in sshd configuration
  • echo 'PermitTunnel=yes' >> /etc/ssh/sshd_config
    service sshd reload
  • Allow forwarding
  • -I FORWARD -i tun+ -j ACCEPT
    -I FORWARD -o tun+ -j ACCEPT
    -I INPUT -i tun+ -j ACCEPT
    echo 1 > /proc/sys/net/ipv4/ip_forward

That’s all!! Congratulations on your new VPN server!!

Client configuration (your personal linux machine)

These 2 commands will configure you with a very simple VPN (run as root!!!):

ssh -f -v -o Tunnel=point-to-point \
  -o ServerAliveInterval=10 \
  -o TCPKeepAlive=yes \
  -w 100:100 root@YOUR_SSH_SERVER \
  '/sbin/ifconfig tun100 netmask pointopoint' && \
/sbin/ifconfig tun100 netmask pointopoint

The only downside of this awesome VPN is that you have to be root on both ends.
But this whole setup is rather clumsy, lets use some UI for that, no?


Somewhere in time, after intensively working in a company dealing with VPNs (but no SSH VPNs at all) I was looking at my taskbar at NetworkManager and thinking “Hey! There’s an OpenVPN, PPTP and IPSEC plugin for NetworkManager, why not build a SSH VPN plugin?”
And hell, why not?
I started searching the Internet frantically, believing that someone already implemented that ingenious idea (like most good ideas), but except for one mailing list post from a few years ago where someone suggested to implement it – nada.

Guess it’s my prime time. Within a week of forking the code of NetworkManager-openvpn (the NetworkManager OpenVPN plugin) I managed to get something that actually works (ssh-agent authentication only). I was surprised because I’ve never dealt with glib/gtk infrastructure not to mention UI programming (I’m a pure backend/infrastructure developer for the most of it).

And today?

I’m writing this post perhaps 2 months after I started development and committed my first alpha release. While writing this post I’m trying to submit NetworkManager-ssh to fedora (fedora-extras to be precise).

Getting into the bits and bytes behind it is redundant, all that you have to know is that the source is available here:
It compiles easily into a RPM or DEB for your convenience. I urge you to give it a shot and please open me issues on github if you find any.

Posted March 23, 2013 by malkodan in C++, Linux

Tagged with , , , , , , , , ,

Creating a puppet ready image (CentOS/Fedora)   10 comments

Cloud computing and being lazy

The need to create template images in our cloud environment is obvious. Especially with Amazon EC2 offering an amazing API and spot instances in ridiculously low prices.
In the following post I’ll show what I am doing in order to prepare a “puppet-ready” image.

Puppet for the rescue

In my environment I have puppet configured and provisioning any of my machines. With puppet I can deploy anything I need – “if it’s not in puppet – it doesn’t exist”.
Coupled with Puppet dashboard the interface is rather simple for manually adding nodes. But doing stuff manually is slow. I assume that given the right base image I (and you) can deploy and configure that machine with puppet.
In other words, the ability to convert a bare machine to a usable machine is taken for granted (although it is heaps of work on its own).

Handling the “bare” image

Most cloud computing providers today provide you (usually) with an interface for starting/stopping/provisioning machines on its cloud.
The images the cloud providers are usually supplying are bare, such as CentOS 6.3 with nothing. Configuring an image like that will require some manual labour as you can’t even auto-login to it without some random password or something similar.

Create a “puppet ready” image

So if I boot up a simple CentOS 6.x image, these are the steps I’m taking in order to configure it to be “puppet ready” (and I’ll do it only once per cloud computing provider):

# install EPEL, because it's really useful
rpm -q epel-release-6-8 || rpm -Uvh`uname -i`/epel-release-6-8.noarch.rpm

# install puppet labs repository
rpm -q puppetlabs-release-6-6 || rpm -ivh

# i usually disable selinux, because it's mostly a pain
setenforce 0
sed -i -e 's!^SELINUX=.*!SELINUX=disabled!' /etc/selinux/config

# install puppet
yum -y install puppet

# basic puppet configuration
echo '[agent]' > /etc/puppet/puppet.conf
echo '  pluginsync = true' >> /etc/puppet/puppet.conf
echo '  report = true' >> /etc/puppet/puppet.conf
echo '  server = YOUR_PUPPETMASTER_ADDRESS' >> /etc/puppet/puppet.conf
echo '  rundir = /var/run/puppet' >> /etc/puppet/puppet.conf

# run an update
yum update -y

# highly recommended is to install any package you might deploy later on
# the reason behind it is that it will save a lot of precious time if you
# install 'httpd' just once, instead of 300 times, if you deploy 300 machines
# also recommended is to run any 'baseline' configuration you have for your nodes here
# such as changing SSH port or applying common firewall configuration for instance

# and now comes the cleanup phase, where we actually make the machine "bare", removing
# any identity it could have

# set machine hostname to 'changeme'
hostname changeme
sed -i -e "s/^HOSTNAME=.*/HOSTNAME=changeme" /etc/sysconfig/network

# remove puppet generated certificates (they should be recreated)
rm -rf /etc/puppet/ssl

# stop puppet, as you should change the hostname before it will be permitted to run again
service puppet stop; chkconfig puppet off

# remove SSH keys - they should be recreated with the new machine identity
rm -f /etc/ssh/ssh_host_*

# finally add your key to authorized_keys
mkdir -p /root/.ssh; echo "YOUR_SSH_PUBLIC_KEY" > /root/.ssh/authorized_keys

Power off the machine and create an image. This is your “puppet-ready” image.

Using the image

Now you’re good to go, create a new image from that machine and any machine you’re going to create in the future should be based on that image.

When creating a new machine the steps you should follow are:

  • Start the machine with the “puppet-ready” image
  • Set the machine’s hostname
    hostname $hostname
    sed -i -e "s/^HOSTNAME=.*/HOSTNAME=$hostname/" /etc/sysconfig/network
  • Run ‘puppet agent –test’ to generate a new certificate request
  • Add the puppet configuration for the machine, for puppet dashboard it’ll be something similar to:
    sudo -u puppet-dashboard RAILS_ENV=production rake -f /usr/share/puppet-dashboard/Rakefile node:add name=$hostname
    sudo -u puppet-dashboard RAILS_ENV=production rake -f /usr/share/puppet-dashboard/Rakefile node:groups name=$hostname groups=group1,group2
    sudo -u puppet-dashboard RAILS_ENV=production rake -f /usr/share/puppet-dashboard/Rakefile node:parameters name=$hostname parameters=parameter1=value1,parameter2=value2
  • Authorize the machine in puppetmaster (if autosign is disabled)
  • Run puppet:
    # initial run, might actually change stuff
    puppet agent --test
    service puppet start; chkconfig puppet on

This is 90% of the work if you want to quickly create usable machines on the fly, it shortens the process significantly and can be easily implemented to support virtually any cloud computing provider!

I personally have it all scripted and a new instance on EC2 takes me 2-3 minutes to load + configure. It even notifies me politely via email when it’s done.

I’m such a lazy bastard.

Posted March 23, 2013 by malkodan in Bash, Linux, System Administration

Tagged with , , , , , , , , , , ,