nodereality

node c0re

munin plugin for djbdns' DNS cache

written by Ghirai, on Sep 17, 2009 10:47:00 AM.

If you run a DNS cache with djbdns, you might want to see pretty graphs of the number of requests your cache received (queries/second).

Here's a very simple munin plugin that does just that:

#!/usr/local/bin/python
import sys

logfile = '/etc/dnscache/log/main/current'

if len(sys.argv) == 2 and sys.argv[1] == "autoconf":

  print "yes"

elif len(sys.argv) == 2 and sys.argv[1] == "config":

  print 'graph_title djbdns dnscache queries'
  print 'graph_vlabel Queries/s'
  print 'graph_category DNS'
  print 'queries.label Queries/s'
  print 'queries.type COUNTER'
  print 'graph_args --base 1000 -l 0'

else:

  f = open(logfile)

  for line in f:

    txt = line.split(' ')
    try:
      if txt[1] == 'query':
        query_count = txt[2]
    except IndexError: continue

  f.close()

  print 'queries.value %s' % query_count

Adjust the "logfile" on line 4 to fit your installation.

Python 3.x users will probably need to make slight adjustments to the code.

Install it like any other munin plugin, then restart munin_node. It doesn't require any additional configuration.

EDIT: Here's how it looks: queries/s graph

What's a browser?

written by Ghirai, on Sep 3, 2009 9:27:00 AM.

The answer is, obviously, it depends - on your operating system, on what features you need/expect from a browser, religion, and so forth.

Ruling out the people who use IE (because they have no choice, or don't know any better), you're left with a couple of options.

Do you care if it's 'free' and 'opensource'? Do you need a rich plugin ecosystem? Does it have to integrate seamlessly with your operating system/window manager/etc?

As far as i'm concerned, bloat starts to creep in when your browser can do more than browse the web (properly), has some sort of adblock and some sort of download manager (by that i mean a way of doing simultaneous downloads, and showing progress). If you feel you need something more, maybe you should start looking at a dedicated application. Or perhaps the web page/web app you're using is missing something.

Because most people spend quite a lot of time using the browser, it needs to be fast and hassle-free. Every time the browser takes its time, it steals time from you; this gets multiplied in the long run, and it adds up.

Personally, i never liked Firefox much. It always felt heavy somehow. Like trying to juggle watermelons. You might succeed, but it's exhausting.

Sure, some of the plugins are nice, some are even pretty useful (although i suspect the bulk of them are not).

Opera is a bit better, if they'd ditch the bittorrent and email stuff. And provide a more decent GUI experience on non-windows platforms.

Next we have Konqeror, which is quite fast, despite the bloat. Too bad i always found it crashing a bit too often. And it doesn't work on Windows. Otherwise it's perfect.

Safari is ok (if you ignore the bloat), and if Apple would patch the security holes more often.

Chrome is nice and all, but there's no decent *nix version yet. Oh, and you might want to think about the major privacy issues.

If you agree with this, then you might want to give Arora a shot.

It's free (a compelling argument these days), webkit-based, and platform independent. And it does one thing only. Fast.

Actually, try it even if you think this post is total bullshit.

FTP vs. FTPS vs. SFTP vs. FISH vs. SCP vs. WTF

written by Ghirai, on Aug 13, 2009 10:49:00 AM.

What's the difference between all these?

FTP stands for File Transfer Protocol. It's been around since the '80 or so, it's insecure, and it's a hassle to make it work through a firewall.

It as two modes of operation: active and passive.

In active mode, the client sends the server a port number that it will listen on (which will be the data connection), over the control connection.

In passive mode, the server sends the client a port number that it will listen on, over the control connection.

Files will get transferred over the data connection, and either way, the client or the server needs to open up some random port in his firewall, apart from the port for the control connection (usually 21).

Most servers (clients) have a way of specifying a port range, but it still sucks. To do it properly, you would need some sort of proxy on the server, and have everyone use passive mode.

Even if the clients have no firewall, most have NAT, which breaks active mode. A real hassle.

FTPS is just like FTP, but the control connection goes over SSL, and so does the data connection (sometimes). So it poses the same issues as plain FTP, but it supports TLS/SSL.

SFTP stands for SSH File Transfer protocol, and is something else entirely. As the name suggests, it uses SSH, and you don't need to do some wizardry to make it works through firewalls.

FISH is basically a wrap around SSH, where the server and client exchange predefined FISH commands, which get translated to standard UNIX shell commands by the server. It was first used in Midnight Commander.

SCP is the predecessor of SFTP. It also uses SSH as the underlying transport and authentication mechanism. Unlike SFTP, it can only transfer files, and does not offer FTP-like features.

Obviously you should stay a way of FTP variants if you have a choice (you should try even if you don't).

Basic RRDTool usage with Python

written by Ghirai, on Aug 9, 2009 2:48:00 AM.

If you're reading this, you probably know about RRDTool. It's a collection of applications that allow you to store just about any sort of time series data, perform various calculations on it, and most importantly, print pretty graphs based on that data.

In order to test the code in this article, you will need to install/compile RRDTool with Python bindings. You can get more info on that, as well as binary packages here.

For the purpose of this exercise, we will be storing and plotting temperature-related information, but you should get an idea on how to process other kind of information as well.

Assume we have two values - temperature and dew point, and we want to plot both on the same graph. We measure these values from some sensors (or from your local weather station's website) every 300 seconds.

The code to create the RRD file is:

rrdtool.create('test.rrd' ,
        '--step','300',
        'DS:temp:GAUGE:600:-50:50' ,
        'DS:dewpoint:GAUGE:600:-50:50',
        'RRA:AVERAGE:0.5:1:576',   #day
        'RRA:AVERAGE:0.5:6:672',   #week
        'RRA:AVERAGE:0.5:24:732',  #month
        'RRA:AVERAGE:0.5:144:1460' #year)

The parameters are identical to what is described in the official rrdcreate documentation. You can use the same values if you want to invoke the command line application, as opposed to doing it programatically.

The first one is obviously the filename (you can have any name/extension).

The second one is the interval at which we will be measuring our data. If you don't explicitly set this, it will default to 300 seconds. Following are the two data sources (DS) we will be using, their names (temp and dewpoint), GAUGE is to be used for temperature (there are other types as well, which are described in more detail in the documentation).

600 is the heartbeat, which specifies how many seconds need to pass before two consecutive updates, before the value is assumed to be unknown. Twice the measure interval seems reasonable in this case.

Finally, -50:50 is the interval between which the measured values are expected to be found.

The next thing to do is to define the round robin archives (RRA).

AVERAGE is our CF (consolidation function), which does exactly what the name says. Again, there are others, which you can learn about in the documentation. 0.5 is ratio of unknown measurements (PDPs, or primary data point; we get a new one every 300 seconds in this case) to the total number of measurements in the specified interval.

For the "day" RRA, 1 means the number of PDPs that build a consolidated datapoint (CDP), and 576 means how many of these get stored in the RRA before being overwritten. This is actually easier than it sounds - 1 PDP means we just store the data directly, every 300 seconds (5 minutes). We store 576 of these CDPs (576*300 seconds=2 days) in the "day" RRA, which means we will be able to plot data for the last 2 days with a 5 minutes resolution. The exact same applies for the week, month and year RRAs: for "week" we have 2 weeks worth of data, with averages of every half hour (6 means 6*300 seconds, which is 30 minutes; we store 672 of these, which means 672*30 minutes = 14 days), for "month" there will be 2 months worth of data, containing 2 hours averages, and finally "year" stores 2 years worth of data, containing 12 hours averages.

In order to have some data to test things out (and not having to wait say one month to see if the code works), we'll just generate some random values.

Note that RRDTool will refuse to insert data that is timestamped (seconds since epoch) before the creation of the database.

Let's add some data:

for i in xrange(nr_samples):
    now = random.randint(12 , 17)
    fake_time = fake_time + 300
    rrdtool.update(rrd_file , '%d:%d:%d' % (fake_time,now,now - \
    10 + random.randint(1,8)))

fake_time gets the current time.

Then we loop nr_samples time, produce a random temperature between 12 and 17C, while making sure to increment the time offset by 300 seconds.

The actual update operation is simple; the parameters are the database filename, following by the "current" time (which we fake here by incrementing fake_time after each update; in a real situation you would just want to get the current time here) and the measured values, how many there may be.

Our fake dew point, which is the second value, is adjusted by a random delta from the temperature, to make the graph a little more realistic.

Finally, it's time to generate the picture, along with the legend:

rrdtool.graph(pic_file ,
  '--start' , str(fake_time - 60*60*24*2) ,
  '--end' , str(fake_time) ,
  #'--slope-mode',
  '--vertical-label' , 'Degrees Celsius' ,
  '--imgformat' , 'PNG' ,
  '--title' , 'Temperature Data (by DAY)' ,
  '-w 500', '-h 200',
  'DEF:temp=%s:temp:AVERAGE' % rrd_file,
  'DEF:dewpoint=%s:dewpoint:AVERAGE' % rrd_file,

  'AREA:temp#ccedff:Temperature',
  'LINE1:temp#aaaaaa',

  'GPRINT:temp:LAST:CUR\: %2.1lf',
  'GPRINT:temp:AVERAGE:AVG\: %2.1lf',
  'GPRINT:temp:MIN:MIN\: %2.1lf',
  'GPRINT:temp:MAX:MAX\: %2.1lf\\n',

  'LINE1:dewpoint#007000:Dewpoint',
  'GPRINT:dewpoint:LAST:   CUR\: %2.1lf',
  'GPRINT:dewpoint:AVERAGE:AVG\: %2.1lf',
  'GPRINT:dewpoint:MIN:MIN\:%2.1lf',
  'GPRINT:dewpoint:MAX:MAX\:%2.1lf\\n')

Graph generation is pretty easy, you just have to pay attention to the start and end points. In a real world situation, you could use --start -2day, or calculate the UNIX time for 2 days ago yourself.

The rest of the parameters, as well as many others are described in more detail in the rrdgraph documentation.

The picture should look like this.

Complete source file for this demo is rrdtool_example.py.

While we're on the subject of temperature, here is some code to calculate the dewpoint, if you have the temperature (in degrees Celsius) and the relative humidity:

def dewpoint(temp,hum):

  f = 17.271 * temp / float(237.7 + temp) + log(H / float(100))
  return 237.7 * f / (17.271 - f)

If you're using Python 3 and up, you don't need the float(100), you can just use 100, and the result will still be a float.

Finally, here is another function that calculates the heat index, along with helper functions to covert around between Fahrenheit and Celsius:

def c2f(t):
  return 9/float(5) * t + 32


def f2c(t):
  return 5/float(9)*(t-32)


def heatindex(temp,hum):

# temperature needs to be in Fahrenheit
# return value is degrees Fahrenheit as well

  if temp < 80: return 0

  return -42.379 + (2.04901523 * temp) + (10.14333127 * hum) - \
    (0.22475541 * temp * hum) - (6.83783 * pow(10,-3) * \
    pow(temp,2)) - (5.481717 * pow(10,-2) * pow(hum,2)) + \
    (1.22874 * pow(10,-3) * pow(temp,2) * hum) + (8.5282 * \
    pow(10,-4) * temp * pow(hum,2)) - (1.99 * pow(10,-6) * \
    pow(temp,2) * pow(hum,2))
The calculations above are from Wikipedia and US NOAA, and i also tested them against known values, so they should be good.

A Comparison of Local Privilege Escalation Kernel Exploits on FreeBSD and Linux

written by abstorted, on Aug 5, 2009 1:45:00 AM.

There is a direct correlation between the popularity of an operating system and its vulnerabilities, especially the available exploits for those vulnerabilities. We can see this trend with the available exploits in Linux based distributions. Other factors are definitely involved like quality assurance. Since FreeBSD and Linux are open source and free software, the people who contribute code and time are for the most part, doing so because they are passionate about what they do. This is one of the possible reasons why these type of exploits are not so frequent, in fact there is only one kernel exploit for FreeBSD. The other factor that seems to be a main contributer to quality of code, is the way the organization works or communicates.

The Linux development environment is a loosely organized group of enthusiasts around the world who communicate solely by email lists and message boards. While this has been the reason for so much success and innovation, it has also caused problems, problems that the FreeBSD development community does not face because of their strict guidelines and assigned hierarchical structure. While this typically impedes innovation, it is one of the key reasons why FreeBSD is one of the most stable operating systems that runs the backbones of the Internet (http://en.wikipedia.org/wiki/FreeBSD) as well as topping the lists with the highest uptimes (http://news.netcraft.com).

The code running the operating system should be one of the most important decisions one can make when building a server or network with the intent of mitigating attacks. Choosing one with a minimal, hardened system (no bloat), scrutinized open source code (ability to see in detail what everything is doing) and years of reliability (ISP's and Government agencies can testify to this) is paramount for security. With that in mind, let us take a look at the differences between local privilege escalation kernel exploits available for both operating systems, and then examine how they can be used to put a system into an incorrect state.

A local privilege escalation kernel exploit may seem like a long word. Let's break it down. Local means that the attack can only be instigated from inside the machine. This means that the attacker can either be 1) physically sitting in front of the machine or 2) logged in remotely, typically on a shell like SSH, telnet or a PHP shell. Privilege escalation means just that, exploiting a process by executing a binary with malicious intent to gain more privileges. This typically involves memory access violations (in other words, exploits) to change from one users privileges to another users privileges to gain more access to files on the targeted system. A kernel is the core of the operating system. By itself it does nothing. In an operating system it is like the traffic controller, police man and plumber to the userland processes. When a kernel is exploited, the attacker will get root access if it is successful.

Putting it all together, what would happen is a remote attacker logs into the machine, downloads his or her exploits and tools and runs them, exploiting the kernel and giving him or her root privileges on the system.

FreeBSD 7.0/7.1 (ktimer) Local Kernel Root Exploit (http://www.securityfocus.com/bid/34196) and Linux Kernel SCSI IOCTL Integer Overflow Vulnerability (http://www.securityfocus.com/bid/12198/info) are two examples from different operating systems that display a similar type of vulnerability classification. SCSI IOCTL is used by the Linux kernel to control SCSI hardware devices such as hard disks. When it is given an out of range integer it may crash. When the input is supplied in a certain way, the crash can be controlled by an attacker to gain root privileges on the machine. The ktimer function in the FreeBSD kernel is used to control how many timers each process may have. When one of those timers reaches 0, certain actions are to be taken by the kernel. When a user passes an integer to ktimer, the timer is supposed to act on a specific timer labeled by the supplied integer. The problem with this is that the ktimer function was not bounds checked on the supplied integer causing a similar problem as the Linux kernels IOCTL vulnerability. The classification of these two exploits is called an Access Validation Error and a Boundary Condition Error, respectively.

Some of the built in protections on Unix based systems are the use of canaries (security cookies) and randomized stack address space. These, however, are not used in kernels generally speaking, so kernels are not protected against these types of attacks.

Thus it is very important to have the code scrutinized to the very last detail by as many trained eyes as possible. Black box testing methods like fuzzing could possibly aide in discovery of kernel vulnerabilities. These methods can work to help find other vulnerabilities in the kernel, but the best way to correct situations like these is through thorough communication and collaboration within the programming and security communities.