Debian / IPv6 / ip6tables / arno-iptables-firewall

Gandi turned IPv6 on, on my virtual host and I’ve been playing catch up ever since.  I’d not spent much time looking at IPv6 other than a cursory glance and I sort of knew the basics.  But once they’d switched it on I had to put in a little bit of reading time.

Did I want the same hostname to resolve to both the IPv4 and IPv6 address, or did I want to use a different hostname for each?  What was I going to do about firewalls?  And a few other things.

Because the iptables documentation makes my brain bleed, I use an out-of-the-box firewall tool (arno-iptables-firewall) which I’ve found extremely useful.  However, the Debian stable version doesn’t support IPv6 configurations.

That left me with three choices.  Try and work out an ip6tables setup for myself, grab a different firewall product, or backport the latest version of arno-iptables-firewall to Debian Squeeze.  Backporting seemed like the most interesting option – so I did that.

Surprisingly it wasn’t as hard as I expected, although I did have to learn a bunch of Debian Package Management terminology in very short notice.  This post helped a ton.  Up until this point, IPv6 access to the server had been working fine, because there was nothing in the way 😉 A couple of connections with other servers had started using the IPv6 and I wanted to retain those.

I checked the config for the firewall, and restarted it.  Everything seemed okay.  However a few days later, another sysadmin got in touch and told me they could no longer get to the server on it’s IPv6 address.  It turned out I could, but only from another server on the same network, and after a little digging and investigation it became clear the issue was routing.

Turning the firewall on and off didn’t fix it, but it seemed like rebooting got it working, and as soon as I started arno-iptables-firewall the problem came back.  So, I stopped using the firewall for IPv6 and everything was okay.  Until overnight the problem came back on it’s own.

One of the key things about IPv6 is that it relies on ICMPv6 far more than IPv4 did.  One of the most important things, is that ICMP is used to do Neighbor Discovery.

Although the arno-iptables-firewall setup was set to allow ICMP through, I had missed one critical setting.  Gandi uses IPv6 stateless autoconfiguration to provide IPv6 information to the host.  This means the host continues to check how to route traffic.  The missed config stopped this information from arriving at the host, and as a result, the essential route to the outside world expired from the routing table.

If you’re uisng arno-iptables-firewall v2.0.0a, and your server uses stateless autoconfiguration, make sure you set the following two options,

# Only disable this if you're NOT using forwarding (required for NAT etc.) for
# increased security.
# Note: If enabled and IPV6 enabled, local IPv6 autoconf will be disabled.
# -----------------------------------------------------------------------------
IP_FORWARDING=0
# (EXPERT SETTING!) Only disable this if IP_FORWARDING is disabled and
# you do not use autoconf to obtain your IPv6 address.
# Note: This is ignored if IP_FORWARDING is enabled. (IPv6 Only)
# -----------------------------------------------------------------------------
IPV6_AUTO_CONFIGURATION=1

By default, IP_FORWARDING will be set to 1, and that stops the IPV6_AUTO_CONFIGURATION setting from taking effect.  Once I switched IP_FORWARDING to 0, the route came back and everything has been fine since.

 

Soup!

I’ve blogged a couple of times about the soup I make (I think, although a quick search doesn’t reveal anything).  Anyway, it seems to be good for my blood sugar which I found out after I’d been making it a while, which is handy for my diabetes.  It took me a few years to get it right – my mum makes it (or used to) with a ham shank, which I could never get around to sorting out.

I eventually settled on a gammon joint as the base and it works quite well.  Since I’m about to put another batch on, I thought I’d write down how I make it.

I buy a gammon join, and some potatoes, carrots, swede, shallots, leeks and lentils.  I boil the gammon joint for some period of time, until it’s done.  Then I chop the various amounts of vegetables, and chuck them and the lentils into the stock. I know I should strain the stock and get the fat out, but I don’t.  I then chop some of the gammon joint and stick that in (I slice the rest and keep it).  I then simmer it for some period of time until the lentils have turned completely smooth.

See? Easy 🙂

I guess if you want numbers, just remember that I don’t look at this by quantity, I just buy whatever looks okay at the time and stick it all in.

  • Gammon Joint – today’s is around 1.7kg, un-smoked, good quality
  • 300g sweet shallots – quartered
  • 1kg potatoes (I tend to use British Charlotte potatoes, because they don’t turn to mush) – cut into chunks (halved, or quartered if they’re big)
  • 4-6 leeks – sliced roughly 1-2cm thick
  • 500g swede – cut into chunks
  • 500g carrots – cut into 1-2cm chunks
  • 500g red split lentils.
  • This gives 8-10 servings.

Half cover the gammon (in a big pan), simmer for an hour or so, and then while it’s cooling, chop the veg.  Take the gammon out (remove the fat from the gammon, and get the fat out of the stock if you want – easier if you make the gammon stock the day before, I don’t).  Stick the veg and lentils into the stock.  Chop gammon to taste, stick into the stock.  At this point, you need to judge if there’s enough water or if you need to add more.  I make this soup *thick*.  I’m serious, it’s slice-able when cold.  However, if you like it with more liquid you’ll need an even bigger pan.

Heat slowly, stir often to prevent sticking.  It’s done for me when the lentils are virtually a single homogeneous gloop.

Graphing INN2 stats through Munin

I run a news server (using INN2), and I graph the performance of the server on which it sits using Munin.  I used to use Cacti, but find Munin much, much easier to set up and get going, even if the interface isn’t quite as fancy.

Munin comes with a collection of regular plugins for graphing various linux services and system stats (such as Apache, MySQL, etc.) but it obviously can’t include everything.  I spent about 10 minutes seeing if anyone had written their own plugin for reporting on INN2 traffic stats, but couldn’t see anything.  So I rolled my own.  I tried this under Cacti and frankly, it was painful.  Not so much the script to gather the data, but getting the graphs actually up and running.

With Munin, it’s trivial.  You can read all about it here, which is where I worked out what I needed to do.

Disclaimer: My shell scripting is shockingly lazy, and my use of awk can be compared to someone playing an exquisite 400 year old violin with a hammer.  Sorry, but suck it up.

I use Munin on a Debian system installed, so the paths may vary depending on your setup.  You need to complete three steps.

1. Get your stats

Munin collects data every 300 seconds.  You need a script which can be run every 300 seconds to return data.  The output of your script should be,

datavariable.value actualvalue

where datavariable is the name you give your erm, data variable, value is the word value and actualvalue is the value you want to graph.  If you have several values, you just output them one line at a time,

datavariable.value actualvalue
datavariable_b.value actualvalue
datavariable_c.value actualvalue

Once you have a script which can output that, you’re most of the way there.

2. Describe your graph

What Munin actually graphs is based on what your script outputs when it is passed a command line parameter of config.  There are a bunch of values you should return which describe the graph, and then a bunch of values which describe the variables (i.e. the stuff above returned by your script), their format and how they should be put onto the graph.  Here’s a simple example,

[sourcecode language=”bash” gutter=”false”]
echo ‘graph_title CPU usage’
echo ‘graph_vlabel %’
echo ‘graph_scale no’
echo ‘graph_info This graph shows how CPU time is spent.’
echo ‘system.label system’
echo ‘system.draw AREA’
echo ‘system.min 0’
[/sourcecode]

That would tell Munin to create a graph with the relevant title, to label the vertical axis with a single %, add a little bit of text and graph a single variable called system.  The system variable is labelled on the graph as system, is an AREA plot and has a minimum value of 0.

There’s plenty more you can do, which you can read about on the Munin site, but that’s the basic stuff, and should be returned when your script is called with config on the command line.  (By the way, your script can be anything executable, perl, shell, etc.)

3. Tell Munin to use your script

You should place your script (executable) in /etc/munin/plugins or a link to it.  You should also add various config options to /etc/munin/plugin-conf.d/munin-node which control how your script behaves.  I’m not covering that in detail here but it’s fairly obvious.

You then restart the munin agent, and bingo your stuff turns up.  Like magic.

INN2 Graphs

So, if you want to graph INN2 data, set INN2 to output stats (inn.conf and innfeed.conf) every 300 seconds (or quicker).  Then use the following two scripts, and entries in the munin-node config file (as appropriate for your installation).

inn2_incoming

[sourcecode language=”bash”]
#!/bin/sh
#
# Plugin to monitor inn2 status file, and report incoming traffic
#
# Require read permissions on the appropriate status file, and INN2 to be configured
# to update the file at or quicker than every 5 minutes.
#
#
#
# Parameters:
#
#       config   (required)
#       autoconf (optional – used by munin-config)
#
# Magick markers (optional):
#%# family=auto
#%# capabilities=autoconf
#
# config example for /etc/munin/plugin-conf.d/munin-node
#[inn2_incoming]
#user news
#group news
#env.logfile /var/log/news/inn_status.html
#

LOG=${logfile:-/var/log/news/inn_status}
CATEGORY=${category:-inn2}

if [ "$1" = "autoconf" ]; then
if [ -r "$LOG" ]; then
echo yes
exit 0
else
echo no
exit 1
fi
fi

if [ "$1" = "config" ]; then

echo ‘graph_title INN2 incoming article stats’
echo ‘graph_args –base 1000 -l 0’
echo ‘graph_scale no’
echo ‘graph_vlabel article count’
echo ‘graph_category’ $CATEGORY
echo ‘graph_period minute’

echo ‘offered.label Total articles offered’
echo ‘offered.type DERIVE’
echo ‘offered.min 0’
echo ‘accepted.label Articles accepted’
echo ‘accepted.type DERIVE’
echo ‘accepted.min 0’
echo ‘refused.label Articles refused’
echo ‘refused.type DERIVE’
echo ‘refused.min 0’
echo ‘rejected.label Articles rejected’
echo ‘rejected.type DERIVE’
echo ‘rejected.min 0’
echo ‘dupe.label Duplicate articles’
echo ‘dupe.type DERIVE’
echo ‘dupe.min 0’

exit 0
fi

awk -v RS="" ‘/global/ {print $0}’ < $LOG | awk -v RS="" -F":" ‘{printf "offered.value %d\naccepted.value %d\nrefused.value %d\nrejected.value %d\ndupe.value %d\n",$5,$7,$10,$13,$16}’
[/sourcecode]

inn2_outgoing

[sourcecode language=”bash”]
#!/bin/sh
#
# Plugin to monitor inn2 status file, and report outgoing traffic
#
# Require read permissions on the appropriate status file, and INN2 to be configured
# to update the file at or quicker than every 5 minutes.
#
#
#
# Parameters:
#
# config (required)
# autoconf (optional – used by munin-config)
#
# Magick markers (optional):
#%# family=auto
#%# capabilities=autoconf
#
# config example for /etc/munin/plugin-conf.d/munin-node
#[inn2_incoming]
#user news
#group news
#env.logfile /var/log/news/innfeed.status
#

LOG=${logfile:-/var/log/news/innfeed.status}
CATEGORY=${category:-inn2}

if [ "$1" = "autoconf" ]; then
if [ -r "$LOG" ]; then
echo yes
exit 0
else
echo no
exit 1
fi
fi

if [ "$1" = "config" ]; then

echo ‘graph_title INN2 outgoing article stats’
echo ‘graph_args –base 1000 -l 0’
echo ‘graph_scale no’
echo ‘graph_vlabel article count’
echo ‘graph_category’ $CATEGORY
echo ‘graph_period minute’

echo ‘offered.label Total articles offered’
echo ‘offered.type DERIVE’
echo ‘offered.min 0’
echo ‘accepted.label Articles accepted’
echo ‘accepted.type DERIVE’
echo ‘accepted.min 0’
echo ‘refused.label Articles refused’
echo ‘refused.type DERIVE’
echo ‘refused.min 0’
echo ‘rejected.label Articles rejected’
echo ‘rejected.type DERIVE’
echo ‘rejected.min 0’
echo ‘missing.label Missing articles’
echo ‘missing.type DERIVE’
echo ‘missing.min 0’
echo ‘deferred.label Deferred articles’
echo ‘deferred.type DERIVE’
echo ‘deferred.min 0’

exit 0
fi

awk -v RS="" ‘/global \(process\)/ {print $0}’ < $LOG | awk -v RS="" -F":" ‘{printf "offered.value %d\naccepted.value %d\nrefused.value %d\nrejected.value %d\nmissing.value %d\ndeferred.value %d\n",$5,$7,$9,$11,$13,$15}’
[/sourcecode]

Obviously, depending on your version of INN2, you may have to tweak the awk entry to get the right values.

Lastly, put the following lines into /etc/munin/plugin-conf.d/munin-node

[sourcecode language=”plain” gutter=”false”]
[inn2_incoming]
user news
group news
env.logfile /var/log/news/inn_status.html

[inn2_outgoing]
user news
group news
env.logfile /var/log/news/innfeed.status
[/sourcecode]

And again, those values will need to change to match your distribution / INN2 setup.  Hope this helps someone.