I discovered earlier today that through my trial ipv6 access I am using mostly ipv6 to access Google services. This made me wonder: just how much of my home network's communication with the outside world is through ipv6 compared with ipv4?
I don't have any results yet, but this is how I'm measuring it using Debian Linux.
Network traffic in the Linux kernel is managed through the tool iptables. Conveniently there are completely separate tables for ipv4 and ipv6 so I don't have to do anything to separate those. There are several chains which packets traverse depending on where they came from, where they're going and whether or not they're being routed on behalf another computer.
The chains of interest are INPUT, FORWARD and OUTPUT on the default table. INPUT receives all packets destined for this particular computer, FORWARD receives all packets which are being ferried on behalf of other computers (in my case, sharing Internet access with NAT) and OUTPUT receives all packets being sent from this particular computer, not on behalf of anyone else. By default all of these will simply allow the packets to pass unmolested.
What I've done is create four custom chains: ipv4_input_ppp0, ipv4_forward_in, ipv4_forward_out and ipv4_output_ppp0. They don't actually do anything, which permits the packets to continue onward, but iptables will keep track of how much traffic travels through each rule, both as a number of packets and in bytes.
Here is some output from "iptables -x -n -v -L" with these chains set up:
Chain INPUT (policy ACCEPT 617 packets, 92499 bytes)
pkts bytes target prot opt in out source destination
41 5511 ipv4_input_ppp0 all -- ppp0 * 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT 46173 packets, 28090499 bytes)
pkts bytes target prot opt in out source destination
21742 10919366 ipv4_forward_out all -- * ppp0 0.0.0.0/0 0.0.0.0/0
24431 17171133 ipv4_forward_in all -- * eth0 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 487 packets, 113453 bytes)
pkts bytes target prot opt in out source destination
61 4783 ipv4_output_ppp0 all -- * ppp0 0.0.0.0/0 0.0.0.0/0
The rules are set up to use iptables' built in filtering capability. The ipv4_input_ppp0 rule will only collect packets which have an "in" interface of "ppp0". This means that packets from me sshing to my router from my LAN will not be counted. ipv4_output_ppp0 is handled the same way.
Similarly the destination interface is used to differentiate between incoming and outgoing traffic which is being forwarded by my router doing its router job, leading to counts in ipv4_forward_in and ipv4_forward_out.
This means we have direct byte counts which we can pull out of iptables and add together to get total incoming and outgoing ipv4 traffic. To make the information easier to process the counts can be zeroed at any time by running "iptables -Z".
The ipv6 setup is exactly the same except you use the tool ip6tables instead.
Here's my configuration for datalogging. I use the following in my firewall script which is run on boot to set up the chains and rules:
iptables -F
iptables -X
iptables -N ipv4_input_ppp0
iptables -N ipv4_forward_in
iptables -N ipv4_forward_out
iptables -N ipv4_output_ppp0
iptables -A INPUT -i ppp0 -j ipv4_input_ppp0
iptables -A FORWARD -o ppp0 -j ipv4_forward_out
iptables -A FORWARD -o eth0 -j ipv4_forward_in
iptables -A OUTPUT -o ppp0 -j ipv4_output_ppp0
iptables -Z
ip6tables -F
ip6tables -X
ip6tables -N ipv6_input_ppp0
ip6tables -N ipv6_forward_out
ip6tables -N ipv6_forward_in
ip6tables -N ipv6_output_ppp0
ip6tables -A INPUT -i ppp0 -j ipv6_input_ppp0
ip6tables -A FORWARD -o eth0 -j ipv6_forward_in
ip6tables -A FORWARD -o ppp0 -j ipv6_forward_out
ip6tables -A OUTPUT -o ppp0 -j ipv6_output_ppp0
ip6tables -Z
Then I run this script every day at midnight from root's crontab:
#!/bin/bash
ipv4_input_ppp0=`iptables -x -n -v -L | grep 'ipv4_input_ppp0' | grep all | sed -e "s/\s\+/\t/g" | cut -f 3`
ipv4_forward_in=`iptables -x -n -v -L | grep 'ipv4_forward_in' | grep all | sed -e "s/\s\+/\t/g" | cut -f 3`
ipv4_forward_out=`iptables -x -n -v -L | grep 'ipv4_forward_out' | grep all | sed -e "s/\s\+/\t/g" | cut -f 3`
ipv4_output_ppp0=`iptables -x -n -v -L | grep 'ipv4_output_ppp0' | grep all | sed -e "s/\s\+/\t/g" | cut -f 3`
iptables -Z
ipv6_input_ppp0=`ip6tables -x -n -v -L | grep 'ipv6_input_ppp0' | grep all | sed -e "s/\s\+/\t/g" | cut -f 3`
ipv6_forward_in=`ip6tables -x -n -v -L | grep 'ipv6_forward_in' | grep all | sed -e "s/\s\+/\t/g" | cut -f 3`
ipv6_forward_out=`ip6tables -x -n -v -L | grep 'ipv6_forward_out' | grep all | sed -e "s/\s\+/\t/g" | cut -f 3`
ipv6_output_ppp0=`ip6tables -x -n -v -L | grep 'ipv6_output_ppp0' | grep all | sed -e "s/\s\+/\t/g" | cut -f 3`
ip6tables -Z
ipv4_in=`echo "$ipv4_input_ppp0 + $ipv4_forward_in" | bc`
ipv4_out=`echo "$ipv4_forward_out + $ipv4_output_ppp0" | bc`
ipv6_in=`echo "$ipv6_input_ppp0 + $ipv6_forward_in" | bc`
ipv6_out=`echo "$ipv6_forward_out + $ipv6_output_ppp0" | bc`
echo "$ipv4_in $ipv4_out $ipv6_in $ipv6_out" >> /var/log/traffic/ip