Archives For 30 November 1999

When you boot your Raspberry Pi with Raspbian, it will get its ip address from a DHCP server. Most tutorials I’ve seen, ask you to login to a ‘router’ (that serves as DHCP server as well) to find the assigned ip address. When you haven’t access to the DHCP server, how do you find the Pi’s ip address?
You should know the MAC address of a Raspberry Pi always has a ‘b8:27:eb’ prefix. Using a Linux utility called ‘arp-scan‘ you can discover MAC addresses and their corresponding ip addresses. Arp-scan sends ARP packets to hosts on the local network and displays any responses that are received.
First, install arp-scan:
apt-get install arp-scan
Then locate all Raspberry Pi’s on the local network using this command:
arp-scan --interface=eth0 --localnet | grep b8:27:eb
You will need to be root, or arp-scan must be SUID root, in order to run arp-scan, because the functions that it uses to read and write  packets require root privilege.
Result:
172.16.12.34 b8:27:eb:00:11:ab (Unknown)
Using the ip address, it is now possible to SSH into your Raspberry Pi:
ssh -l pi 172.16.12.34

Today I figured out how to automatically add new devices (in my case those are mostly virtual machines) to the Zenoss monitoring system. This used to be done by hand, but no more 🙂

To add a new device (for example a Linux server called server001), simply call:

curl -u apiUser:apiPass \
'http://zenoss-server:8080/zport/dmd/DeviceLoader? \
deviceName=server001&devicePath=/Server/Linux&\
loadDevice:method=1'

It’s wise to create a dedicated Zenoss user just for these API calls, but you may use any account that has sufficient permissions to perform the action you’re calling.

As an alternative you can also use the ‘zenbatchload‘ command. Although you can only add new devices, not edit existing ones.The RESTful API does have the possibility to edit an existing device.

Let’s set some properties to the server we’ve just added:

curl -u apiUser:apiPass \
'http://zenoss-server:8080/zport/dmd/Devices/Server/\
Linux/devices/server001/manage_editDevice?serialNumber=1234&\
tag=tagname&productionState=1000&\
groupPaths=Group1&groupPaths=Group2&priority=3&\
comments=Api%20Test%20Comment&systemPaths=/System\
&rackSlot=Virtual'

It took me some time to figure out all available attributes, although once I found some of them I was able to Google the full list with an explaination.

Attributes:

  • deviceName – the name or IP of the device. If its a name it must resolve in DNS
  • devicePath – the device class where the first “/” starts at “/Devices” like “/Server/Linux” the default is “/Discovered”
  • tag – the tag of the device@
  • serialNumber – the serial number of the device
  • zSnmpCommunity – snmp community to use during auto-discovery if none is given the list zSnmpCommunities will be used
  • zSnmpPort – snmp port to use default is 161
  • zSnmpVer – snmp version to use default v1 other valid values are v2
  • rackSlot – the rack slot of the device.
  • productionState – production state of the device default is 1000 (Production)
  • comments – any comments about the device
  • hwManufacturer – hardware manufacturer this must exist in the database before the device is added
  • hwProductName – hardware product this must exist in the manufacturer object specified
  • osManufacturer – OS manufacturer this must exist in the database before the device is added
  • osProductName – OS product this must exist in the manufacturer object specified
  • locationPath – path to the location of this device like “/Building/Floor” must exist before device is added
  • groupPaths – list of groups for this device multiple groups can be specified by repeating the attribute in the url
  • systemPaths – list of systems for this device multiple groups can be specified by repeating the attribute in the url
  • statusMonitors – list of status monitors (zenping) for this device default is “localhost”
  • performanceMonitor – performance monitor to use default is “localhost”
  • discoverProto – discovery protocol default is “snmp” other possible value is “none”

Finally, in case you wish to delete a device, that can be done as well:

curl -u apiUser:apiPass \
'http://zenoss-server:8080/zport/dmd/Devices/Server/Linux/\
devices/server001/deleteDevice'

Personally I prefer not to delete devices. I rather set the ‘productionState’ to ‘-1’ (Decommissioned) to keep the history in Zenoss.

These simple API calls make it possible to automatically add a new server to the monitoring, or sync information from another source. But you can use the API for gathering all sorts of data as well. For example the load-average:

curl -u apiUser:apiPass \
'http://zenoss-server:8080/zport/dmd/Devices/Server/Linux/\
devices/server001/getRRDValue?dsname=laLoadInt5_laLoadInt5'

Result:

2.0

If you want to start playing with it, have a look at the Zenoss API documentation.

Recently I was looking for a way to SSH from a network that blocked my outgoing SSH connection. I’d be nice to have a way around firewalls and be able to access your private Linux terminal. To be able to debug a problem from an remote location, for example.

A collegue suggested a tool called ‘Shell In A Box‘. Shell In A Box implements a web server that can export arbitrary command line tools to a web based terminal emulator using just JavaScript and CSS without any additional browser plugins. This means: connecting your browser via HTTPS to your own hosted Shell In A Box web site, and access a Linux terminal from there.

How cool is that? In this blog I’ll show you how to set it up in a secure way.

Building and installing Shell In A Box
I want to setup Shell In A Box on my Raspberry Pi. It’s a great device running Linux that has a very small energy consumption footprint. Ideal for an always-on device I’d say!

Since there is no package available, we’ve to compile our own. It’s best to get the sources from Github (original here), since the Github repository contains some patches and fixes for issues on Firefox.

These commands install the required dependencies, clone the Git repository and start building:

apt-get install git dpkg-dev debhelper autotools-dev libssl-dev libpam0g-dev zlib1g-dev libssl1.0.0 libpam0g openssl
git clone https://github.com/pythonanywhere/shellinabox_fork
cd shellinabox_fork
dpkg-buildpackage

During my first attempt, I ran into this problem:

dpkg-source -b shellinabox-2.14
dpkg-source: error: can't build with source format '3.0 (quilt)': no upstream tarball found at ../shellinabox_2.14.orig.tar.{bz2,gz,lzma,xz}
dpkg-buildpackage: error: dpkg-source -b shellinabox-2.14 gave error exit status 255

When grepping for ‘quilt’ I found a file called ‘/debian/source/format’. From what I can tell this does not do anything important, so I ended up deleting the file. Guess what, it now works.

rm ./debian/source/format

Build the package again, this should now succeed.

dpkg-buildpackage

This process will take some time (especially on the Raspberry Pi). Afterwards you’ll find the .deb file ready to be installed.

dpkg -i ../shellinabox_2.14-1_armhf.deb

I changed the configuration, to disallow the build-in SSL and to bind to localhost only. I did this because another web server will serve our terminal. I will explain in a minute.

vim /etc/default/shellinabox

And edit this line:

SHELLINABOX_ARGS="--no-beep -s /terminal:LOGIN --disable-ssl --localhost-only"

Finally, restart the deamon:

/etc/init.d/shellinabox restart

And check if all went well:

/etc/init.d/shellinabox status

You should see:

Shell In A Box Daemon is running

Another way to verify is to check the open ports:

netstat -ntl

You should see:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State 
tcp 0 0 127.0.0.1:4200 0.0.0.0:* LISTEN


Setting up Lighttpd as a proxy

Shell In A Box runs on port 4200 by default. Although this can be changed to a more common 80 or even 443, this is not what I want. I decided to integrate it with another webserver, to be able to combine other services and use just one url (and one SSL certificate). Since the Raspberry Pi isn’t that powerful, I choose Lighttpd.

apt-get instal lighttpd
cd /etc/lighttpd/conf-enabled
ln -s ../conf-available/10-proxy.conf

This installs Lighttpd and enables Proxy support. Now add the Proxy config:

vim /etc/lighttpd/lighttpd.conf

And add:

proxy.server = (
 "/terminal" =>
  ( (
    "host" => "127.0.0.1",
    "port" => 4200
  ) )
)

Save and restart Lighttpd:

/etc/init.d/lighttpd restart

Connect to http://pi.example.org/terminal and your Shell In A Box terminal should appear.

Although this is cool already, we’re not quite there. No one will SSH on an unencrypted web page, right? So, we’ll configure an SSL certificate to enable encryption. For double safety, we’ll also set a username/password on the web page. One then needs to know this password to access the login promt, and needs a valid local username/password to really use the terminal.

Adding encryption with SSL
By using a HTTPS-url, our traffic is encrypted. Let’s generate a private key (and remove the passphrase):

openssl genrsa -des3 -out pi.example.org.key 2048
cp -pr pi.example.org.key pi.example.org.key.passwd
openssl rsa -in pi.example.org.key.passwd -out pi.example.org.key

If you do not remove the passphrase, you will need to type it every time you start the web server. To request a SSL-certificate, you need to supply a CSR (Certificate Signing Request) and send that to a SSL provider such as Thawte or Verisign.

openssl req -new -key pi.example.org.key -out pi.example.org.csr

To be able to continue now, let’s self-sign the certificate:

openssl x509 -in pi.example.org.csr -out pi.example.org.pem -req -signkey pi.example.org.key -days 365
cat pi.example.org.key >> pi.example.org.pem

A self-signed certificate will display a warning in our browser, but that’s ok for now. Once the real certificate comes back from our SSL provider, it’s easy to replace it. The warning will then disappear.

Time to tell Lighttpd about our certificate:

vim /etc/lighttpd/lighttpd.conf

Add these lines:

$SERVER["socket"] == "10.0.0.10:443" {
  ssl.engine = "enable"
  ssl.pemfile = "/etc/lighttpd/ssl/pi.example.org/pi.example.org.pem"
  server.name = "pi.example.org"
  server.document-root = "/home/lighttpd/pi.example.org/https"
  server.errorlog = "/var/log/lighttpd/pi.example.org_serror.log"
  accesslog.filename = "/var/log/lighttpd/pi.example.org_saccess.log"
}

And restart Lighttpd:

/etc/init.d/lighttpd restart

Now Shell In A Box should be available on: https://pi.example.org/terminal

Enhancing security by adding HTTP-auth
Since the /terminal page now makes an actual terminal available to web users, I added an extra password for security. You can use the ‘HTTP Auth’ method for this. It will pop up a message box that requires an valid username/password before the /terminal page is shown.

First enable the module:

cd /etc/lighttpd/conf-enabled
ln -s ../conf-available/05-auth.conf

Then extend the config of the virtual host config you created above. The final result should be:

$SERVER["socket"] == "10.0.0.10:443" {
  ssl.engine = "enable"
  ssl.pemfile = "/etc/lighttpd/ssl/pi.example.org/pi.example.org.pem"

  server.name = "pi.example.org"
  server.document-root = "/home/lighttpd/pi.example.org/https"
  server.errorlog = "/var/log/lighttpd/pi.example.org_serror.log"
  accesslog.filename = "/var/log/lighttpd/pi.example.org_saccess.log"

  auth.debug = 2
  auth.backend = "htpasswd"
  auth.backend.htpasswd.userfile = "/etc/lighttpd/shellinabox-htpasswd"

  auth.require = ( "/terminal/" =>
    (
      "method" => "basic",
      "realm" => "Password protected area",
      "require" => "user=remibergsma"
    )
  )
}

Reload Lighttpd to make the changes active:

/etc/init.d/lighttpd reload

To set a password:

apt-get install apache2-utils
htpasswd -c -m /etc/lighttpd/shellinabox-htpasswd remibergsma

You can enter multiple users, just remember to remove the ‘-c’ flag when adding more users, as this overwrites the current file.

When you visit https://pi.example.org/terminal you will need to enter a valid username and password, before the page loads.

The final result: SSH in a browser window!
You should now be able to use a terminal via your own protected webpage. It’s mostly like a real terminal/SSH session but from a browser. Wow 🙂

Shell In A Box in action

Shell In A Box in action

 

I always use GNU Screen, so I know for sure my commands keep running whatever happens.

Using GNU Screen in a browser

Using GNU Screen in a browser

 

openvpnOpenVPN is great, it allows for easy access in a secure way. But how do you keep it secure? I mean, what if someone leaves your company? Do you disable access to the OpenVPN server? You should! In this blog I’ll show you how to do it.

A feature called revoking exists in OpenVPN. Revoking a certificate means to invalidate a previously signed certificate so that it can no longer be used for authentication purposes. For this to work, we need to tell the OpenVPN server which certificates are no longer valid.

All connecting clients will then have their client certificates verified against the so-called CRL (Certificate Revoking List). Any positive match will result in the connection being dropped. Your former employees will no longer have access, even if they still have their certificates.

Creating a certificate to test with
Before we start, let’s generate a dummy certificate for testing purposes:

cd /etc/openvpn/easy-rsa/2.0/
 . ./vars
./build-key unwanted-client-name

Verify you can connect to the OpenVPN server using this certificate. Refer to my earlier post for more info. Now that this works, I’ll show you how to revoke this certificate so you will no longer be able to connect.

Revoking a certificate
To revoke a certificate, we’ll use the ‘easy-rsa’ toolset.

cd /etc/openvpn/easy-rsa/2.0

If it’s not there, look at the OpenVPN examples and copy it:

cp -R /usr/share/doc/openvpn/examples/easy-rsa /etc/openvpn
cd /etc/openvpn/easy-rsa/2.0

Run this command to revoke the certificate called ‘unwanted-client-name’:

./revoke-all unwanted-client-name

You should see output similar to this:

Using configuration from /etc/openvpn/easy-rsa/2.0/openssl-1.0.0.cnf
Revoking Certificate 03.
Data Base Updated
Using configuration from /etc/openvpn/easy-rsa/2.0/openssl-1.0.0.cnf
unwanted-client-name.crt: C = NL, ST = ZH, L = City, O = Name, OU = pi.example.org, CN = unwanted-client-name, name = unwanted-client-name], emailAddress = [email protected]
error 23 at 0 depth lookup:certificate revoked

Note the “error 23” in the last line. That is what you want to see, as it indicates that a certificate verification of the revoked certificate failed.

The index.txt file on keys directory will be updated. You’ll see an ‘R’ (for Revoked) on the first column from the left for your user when you run this:

cat keys/index.txt

You can also examine the CRL to see what’s in there:

openssl crl -in keys/crl.pem -text

Now copy the crl.pem file to the OpenVPN config directory:

cp keys/crl.pem /etc/openvpn/

Whenever you revoke a certificate, you’ve to copy it to the OpenVPN server.
Note: The CRL file is not secret, and should be made world-readable so that the OpenVPN daemon can read it after root privileges have been dropped.

Enable revoking support
Before it works, we need to setup the OpenVPN server to add support for revoking certificates. You’ve to do this only once.

Add the folowing line to the OpenVPN server config:

vim /etc/openvpn/server.conf
crl-verify /etc/openvpn/crl.pem

Reload the OpenVPN server to activate the revoke setting:

/etc/init.d/openvpn reload

Testing the revoked certificate
The final test: try to login again using the ‘unwanted-client-name’ certificate. It will not work anymore!

By revoking users, you disallow access to your OpenVPN server for users that previously had access. This should be done as soon as an user no longer needs access, as it is an important security feature.

When you create firewall rules with iptables on Linux, you want to make them persistent over reboot, because they are not by default. Different Linux distributions have different methods of achieving this, although the basics are similar. I’ve been working with Debian, Red Hat Enterprise Linux and SUSE Linux Enterprise Server and in this blog I’ll describe how to configure each of them to save your iptables rules across reboots.

First the good news: the iptables package, the administration tool for packet filtering and NAT, always ships with Linux distributions. The package also includes the ‘iptables-save‘ and ‘iptables-restore‘ tools. These do what you might already expect from their names: save or restore iptables rules. ‘iptables-save‘ outputs to stdout, which you can save to a file:

iptables-save > /etc/iptables/rules

To load these again:

iptables-restore < /etc/iptables/rules

These really are the basics that work across Linux distributions and that you can use in your custom boot scripts. In addition to this, each Linux distribution has its own way to make this process easier.

Red Hat Enterprise Linux (RHEL):
redhat-logo

RHEL (and the same counts for CentOS and Fedora) has some built in mechanism to help automate this. First of all, there are some settings in ‘/etc/sysconfig/iptables-config‘:

IPTABLES_SAVE_ON_STOP=”yes”
IPTABLES_SAVE_ON_RESTART=”yes”

You can set them to “yes” to have persistent iptables rules. In fact, there are many more settings in that file that allow for finer control. That’s all, since the rest is handled automatically.

At any time it’s possible to save the current state. Just run:

service iptables save

And it will, like on reboot, save the rules to: ‘/etc/sysconfig/iptables‘. Pretty easy and pretty powerful!

SUSE Linux Enterprise Server (SLES 11):

suse-logo SLES (and the same counts for OpenSUSE) is yet another story. SLES 11 now ships with SUSE Firewall. Instead of defining the rules yourself, you tell Yast what you want to achieve and it generates the needed iptables rules for you. Although SUSE Firewall does allow you to add custom rules, it isn’t really designed for it. The tool is pretty nice though, because it integrates fully with Yast and allows for easy maintenance of rules. When you install a package, it automatically opens the associated port, for example.

This all might seems a bit scary for us sysadmins, right?! Don’t worry, it’s still possible to manage rules on your own by disabling SUSE Firewall. But have a look at it first, as you might as well like it.

To start the SUSE Firewall admin module, run:

yast2 firewall

The interface is pretty self-explaining. Afterwards, to activate the changes run:

SuSEfirewall2

It’s even possible to by-pass Yast, and edit the config file directly. It’s safe to combine the two methods, no problem.

vim /etc/sysconfig/SuSEfirewall2

For example, to open a port you’d edit the ‘FW_SERVICES_EXT_TCP’ variable. Just make a list (space separated) with protocols you want to allow. These protocols refer to files in ‘/etc/sysconfig/SuSEfirewall2.d’.

Like with using Yast, activate the changes when you’re done.

SuSEfirewall2

I’ve used it for some time and it’s actually pretty easy. It just depends on the project whether or not to use it, I guess.

Debian
debian-logoWhen I was using Debian (same counts for Ubuntu as well), I used to create a small shell script and place it in ‘/etc/network/if-pre-up.d’. Just before the network interface is brought up, the iptables rules will be restored. The idea is to do the same when the interface goes down (use the ‘/etc/network/if-post-down.d’ folder to place the script in). Using these thechniques, you can create something and have fine control over it.

Recently I heard about a tool called ‘iptables-persistent’ that can automate this out-of-the-box. Here’s the package description:

iptables-persistent - boot-time loader for iptables rules: Current iptables rules can be saved to the configuration file '/etc/iptables/rules.v4'. These rules will then be loaded automatically during system startup.

To install it:

sudo apt-get install iptables-persistent

During install, the program asks to save both ipv4 and ipv6 iptables rules. Please note this counts for Wheezy, the current stable release uses the file ‘/etc/iptables/rules’.

To manually save the iptables rules, run:

/etc/init.d/iptables-persistent save

Although this should be done automatically when you reboot. It looks like the Red Hat way of doing things, but just with an extra package installed.

Conclusion: 
iptables all over the place, just with different tooling to automate it 🙂