Accountability with IPv6
Latest commit 25ec8b2 Jun 13, 2016 @jimdigriz added README
Failed to load latest commit information.
sql initial upload Apr 10, 2011
syslog broke out ipv4 syslog dhcp configlet to it's own file Apr 11, 2011
.gitignore initial upload Apr 10, 2011 added README Jun 13, 2016
slaacer initial upload Apr 10, 2011

SLAACer - Accountability with IPv6

SLAACer primary objective is to place a second option on the table for network sysadmin's when they deploy IPv6 in their organisation. So far the mass consenus generally has bee that you must roll out DHCPv6 if you want to be able to map your IPv6 addresses back to MAC addresses; and do not wish to poll via SNMP/CLI all your routers.

SLAACer embraces that in the IPv6 world, unlike the IPv4 world, multiple IP assignment to a node should be encouraged if not actually be considered the norm:

Much like NAT, I have the opinion that DHCP has become one of those 'latent' efforts that sysadmins have become use to deploying in the IPv4 world when in actual fact they do require some degree of effort (especially to make highly available) which can be completely engineered away in the IPv6 world. Some might argue that DHCP can also be used to give TFTP, NTP, LDAP, etc servers in their payload, I personally feel that using DNS SRV records and multicast SLP are far more appropriate methods.

Either way and whatever your view, SLAACer now permits network sysadmin's to choose to use either DHCPv6 or SLAAC depending on their needs. A situation with options should always be considered preferable over a sitation where you are forced to embrace one method/vendor.

N.B. SLAACer is not the solution but should tie us all over until something better comes along (lets hope vendors give us something like SNMP traps for changes to the IPv6 to MAC mapping events).


Do contact me if you want to contribute patches, send feedback or just generally have a chat about SLAACer. Currently on the roadmap are the following changes that I can think of:

  • improve Perl POD documentation for the daemon
  • improvements to filtering port-mirroring to mirror only the traffic we are interested in (including developments into SPF loopback approaches)
  • schemas for SQLite, MySQL, MS-SQL and others
  • configuration examples for other syslog servers such as rsyslog
  • record and process ICMPv6 RA packets to track down mis-configured hosts

Related Links


In it's ugliest form, SLAACer requires that you port-mirror every workstation edge switch port in your network into it. This is actually not as bad as it sounds as to stop things getting out of control you can use filters on the port-mirror'ing to capture only the traffic SLAACer is interested in (ICMPv6 NS/NA traffic), ingress only traffic and a number of other tricks discussed later.

All this traffic is sent to a dedicated Ethernet interface that the 'slaacer' daemon listens on (using libpcap). 'slaacer' digests the traffic and sends out syslog messages depending on what it sees. A syslog server collects these messages (additionally you can process the syslog traffic from your IPv4 ISC DHCP server too) to write to a text file as well as parsing the contents and creating an SQL query calling an function that records the information in an easy to use format.



Once deployed and you have all your data trickling into your SQL server, data is recorded as the column 'start' indicating when the IP address (either IPv4 or IPv6) was first seen and 'last' when it was last recorded((warning: especially in the case of DHCP leases, 'last' and when the host was last using that address is only accurate to the last timestamp a DHCP renew request, or IPv6 NA packet, was sent)).

You can now start to make queries such as "what addresses has the MAC address 00-17-42-87-ce-f7 used since the beginning of March 2011?":

user@host:~$ echo "SELECT * FROM mac2addr WHERE mac = '00-17-42-87-ce-f7' AND last > '2011-03-01' ORDER BY last DESC" | psql --host=%SQL-SERVER% %DATABASE% %USERNAME%
Password for user %USERNAME%:
  id   |        mac        |                 addr                 |         start          |          last
  6609 | 00-17-42-87-ce-f7 | fe80::217:42ff:fe87:cef7             | 2011-02-23 10:06:23+00 | 2011-04-08 14:55:33+01
 31403 | 00-17-42-87-ce-f7 | 2001:630:1b:8000:c4b:c8fa:d360:5b3   | 2011-04-07 08:32:43+01 | 2011-04-08 14:44:06+01
 10185 | 00-17-42-87-ce-f7 |                         | 2011-03-07 08:23:02+00 | 2011-04-08 07:41:30+01
 30027 | 00-17-42-87-ce-f7 | 2001:630:1b:8000:c161:3cde:da18:9caa | 2011-04-04 08:28:22+01 | 2011-04-06 15:58:03+01
 29489 | 00-17-42-87-ce-f7 | 2001:630:1b:8000:51bc:41fe:62de:99da | 2011-04-01 08:23:21+01 | 2011-04-01 20:11:08+01
(5 rows)

The most useful request is, in the case of abuse reports, to ask "who was using the IP address 2001:630:1b:8000:c4b:c8fa:d360:5b3 at 2011-04-07 22:00?":

user@host:~$ echo "SELECT * FROM mac2addr WHERE addr = '2001:630:1b:8000:c4b:c8fa:d360:5b3' AND start `<= '2011-04-07 22:00' AND last >`= '2011-04-07 22:00'" | psql --host=%SQL-SERVER% %DATABASE% %USERNAME%
Password for user ac56:
  id   |        mac        |                addr                |         start          |          last
 31403 | 00-17-42-87-ce-f7 | 2001:630:1b:8000:c4b:c8fa:d360:5b3 | 2011-04-07 08:32:43+01 | 2011-04-08 14:44:06+01
(1 row)

All the IPv6 information ((the IPv4 DHCP entries come from the regular ISC DHCP syslog messages)) is obtained from the syslog messages that are generated by 'slaacer':

Apr 11 08:25:26: 00-17-42-87-ce-f7 2001:630:1b:8000:7c1a:d241:3902:b982 [SOLICIT,dad]
Apr 11 08:25:27: 00-17-42-87-ce-f7 2001:630:1b:8000:217:42ff:fe87:cef7 [SOLICIT,dad]
Apr 11 08:26:12: 00-17-42-87-ce-f7 2001:630:1b:8000:7c1a:d241:3902:b982 [ADVERT,solicited,override]
Apr 11 08:56:10: 00-17-42-87-ce-f7 fe80::217:42ff:fe87:cef7 [ADVERT,solicited]
Apr 11 08:56:11: 00-17-42-87-ce-f7 2001:630:1b:8000:7c1a:d241:3902:b982 [ADVERT,solicited]
Apr 11 08:57:10: 00-17-42-87-ce-f7 fe80::217:42ff:fe87:cef7 [ADVERT,solicited]


'slaacer' supports a number of parameters when being called (in addition to '--help, -h' and '--man'):

  • --interface, -i: listen for IPv6 ICMP packets on a particular interface (//required//)
  • --debug, -d: enable verbose debugging
  • --nofork, -n: do not fork into background
  • --record=path, -R path: path to place recordings in (default: /tmp)
  • --playback=filename, -P filename: playback a former recording and exit (implies 'nofork' but does no syslog'ing)

Whilst running, 'slaacer' supports receiving and acting on the following signals (ie. 'pkill -USR1 -x slaacer'):

  • SIGTERM/SIGINT: cleanly shutdown
  • SIGUSR1: write out traffic being received by the daemon to a PCAP compatible file ('/path/specified/for/record/slaacer.%Y-%m-%dT%TZ') and when signaled when already recording, stop recording and close the file


The git tree for hopefully everything you need can be found at

For those unfamiliar with git, if you have installed it, all you need to type is:

user@host:~$ git clone git://
user@host:~$ cd slaacer
user@host:~/slaacer$ ls -l
total 16
-rwxr-xr-x 1 user group 12882 Apr 10 15:09 slaacer
drwxr-xr-x 2 user group    18 Apr 10 15:09 sql
drwxr-xr-x 2 user group    22 Apr 10 15:09 syslog


There are four components that need to be configured:

  • SQL server
  • central syslog server
  • port mirroring
  • the SLAACer daemon

Throughout, we will assume that:

  • your central syslog server you administrate lives at ''
  • the SQL server is at ''

N.B. make sure you are careful to replace all the placeholders ('%...%')


This should be just a simple case of just replacing the place holders '%DATABASE%', '%USERNAME%' and '%PASSWORD%' in the included 'sql' directory for your particular SQL server and loading it in.


sql:~# cat `<<'EOF' >`> /etc/postgresql/8.3/main/pg_hba.conf
host    %DATABASE%    mac2addr     md5

sql:~# /etc/init.d/postgresql-8.3 reload

sql:~# su - postgres
postgres@sql:~$ psql -f /path/to/slaacer/sql/pqsql %DATABASE%


Like for the SQL case, it should be just a simple case of replacing the place holders '%SQL-SERVER%', '%DATABASE%', '%USERNAME%' and '%PASSWORD%' in the included 'syslog' directory.


Make sure you have the 'psql' (Debian package 'postgresql-client') tool installed and that you insert the 'syslog/syslog-ng' file into your syslog-ng configuration (additionally you might wish to add 'syslog/syslog-ng.ipv4-dhcp-hook' to record you IPv4 allocations too).

syslog:~# cat `<<'EOF' >`> /etc/syslog-ng/pgpass

syslog:~# chown root:root /etc/syslog-ng/pgpass
syslog:~# chmod 600 /etc/syslog-ng/pgpass

syslog:~# /etc/init.d/syslog-ng reload

Port Mirror

This section is more than likely the most difficult part and so to try and help out I have broken it up into two chunks. The "quick'n'dirty" approach that gets you going without any thought about the quantity of traffic flooding your LAN but should just work, the second part lists constraints and approaches to make you feel less dirty in regards to the deployment.

N.B. as a helpful aid to track bandwidth usage on your LAN, I strongly recommend Torrus. It is trivial to set up and it gives you RRD graphs for every switchport on your network.


You need to create a single global VLAN than spans your entire LAN (in our example we shall use VLAN ID '300'). The VLAN should be trunked up to every switch stack and you will need to type the following on either your VTP master, or each of your switch stacks:

vlan 300
  name v6span-nd

At all your L3 router source(s)((If you have your IP addresses assigned at your core routers ('L2 to the edge'), then you RSPAN source on those core routers. If you have your IP addressing at your access layer ('L3 to the edge') then you need to RSPAN source from there, yes 48 ports per switch is what we have to do, but it works)), assuming all your IPv6 traffic comes off VLAN 33, we want to only capture ingress (received) traffic:

monitor session 8 source vlan 33 rx
monitor session 8 destination remote vlan 300

N.B. if you are fortunate enough to have 3750X/3560X's at your access layer, then you can use FRSPAN (Filter RSPAN) to capture just then neighbour discovery traffic. If you be a simple case of just adding 'monitor session 8 filter ipv6 ...' and the necessary access list.

On the switch that the SLAACer server connects to (assuming it's monitoring port, 'eth1' is on 'Gi1/0/1'), type:

monitor session 8 source remote vlan 300
monitor session 8 destination interface Gi1/0/1


Remote SPAN'ing functions by creating a VLAN that has MAC learning disabled, this unfortunately means that every packet is turned into a broadcast packet, this becomes a nasty problem as the number of edge switch stacks increase. You can control the problem by creating a unique RSPAN VLAN for each edge switchstack which would effectively uni-directionalise the traffic.

The most powerful feature you need to look into is VACL's which enable you to apply filters to the RSPAN VLAN to control what traffic is actually passed around. There are a number of unfortunate appliable constraints when dealing with VACL's and IPv6 traffic:

  • C3750 will not VACL RSPAN sources

  • C3750/C6500 will not VACL with IPv6 ACLs

  • C3750 will not VACL IPv6 Ethernet frames with MAC ACLs

  • C6500 with even a single DFC3A will not VACL Ethernet frames with MAC ACLs (no 'mac classify-packet' command)

  • IOS versions pre-12.2(55) on a C3750 are affected by CSCtd72626 where an RSPAN does not include multicast IPv6 traffic (MAC address destination '33:33:ww:xx:yy:zz') that prevents catching NS-DAD packets

My organisation's network is made up of C3750's at the edge (configured in L3 'at the edge') feeding back to two C6500's (with DFC3A modules) using port-channels. The SLAACer daemon sits on a Linux box hanging off a C3750E that pipes back to the C6500 core. With this topology some of those contraints are a royal pain...fortunately at peak most of those port-channels peak at around 5% utilisation.

So far, what I am currently using is the following (the C6500 will prune all IPv4 traffic whilst the C3750E prunes off the ARP traffic):

6500#show ip access-lists slaacer-v4
Extended IP access list slaacer-v4
    10 permit ip any any

6500#show vlan access-map slaacer
Vlan access-map "slaacer"  10
        match: ip address slaacer-v4
        action: drop

6500#show vlan filter
VLAN Map slaacer:
        Configured on VLANs:  300
            Active on VLANs:  300

3750E#show access-lists slaacer

Extended MAC access list slaacer
    permit any any lsap 0xAAAA 0x0
    permit any any lsap 0x4242 0x0

3750E#show vlan access-map slaacer
Vlan access-map "slaacer"  10
  Match clauses:
    mac address: slaacer
Vlan access-map "slaacer"  20
  Match clauses:

3750E#show vlan filter
VLAN Map slaacer is filtering VLANs:

Possible IPv6/MAC VACL Version

no vlan filter slaacer vlan-list 902
no vlan access-map slaacer
no mac access-list extended slaacer

mac access-list extended slaacer
        deny any any 0x4242 0x0
        deny any any 0xaaaa 0x0
        deny any 3333.0000.0000 0000.ffff.ffff 0x86dd 0x0
        permit any any
vlan access-map slaacer 10
        match mac address slaccer
        action drop
vlan access-map slaacer 20
        action forward

vlan filter slaacer vlan-list 902
ipv6 access-list slaacer-v6
        permit icmp FF80::/64 host FF02::2 sequence 10
        permit icmp host :: FF02::1:0:0/96 sequence 20
ip access-list extended slaacer-v4
        permit ip any any

vlan access-map slaacer 10
        match ip address slaacer-v4
        action drop

vlan filter slaacer vlan-list 902


'slaacer' is placed on the system that is the destination for all the port mirror'ed traffic you are collecting (lets assume the interface is 'eth1'). We first need to configure the system to send the 'slaacer' generated syslog traffic to your central syslog server. We do this, assuming you run 'rsyslog' on the system, by adding the following to send the traffic over TCP (if you want UDP, replace '@@' with '@'):

root@slaacer:~# cat `<<'EOF' >` /etc/rsyslog.d/local-slaacer.conf
if $programname == 'slaacer' then @@
& ~

root@slaacer:~# /etc/init.d/rsyslog reload

For now, initially call 'slaacer' in a screen session:

# slaacer -i eth1 -n

'slaacer' will now parse traffic coming in over 'eth1' and print to stderr (as well as syslog) a message describing the traffic it sees. The syslog messages will be processed by your central syslog server and the SQL table 'mac2addr' will be updated with this live information.