Mikrotik Hotspot Authentication for IPv6 dual-stacked clients

In preparation for some IPv6 testing of our hotspot systems, I’ve come up with the following temporary authentication method for dual-stacked users.

Seeing as the login redirect goes via an IPv4 webserver, if enabled IPv6 traffic passes by the hotspot unhindered. This is my work on enabling the IPv6 side of things when a user logs in or out of the hotspot with a dual stacked client.

This has been implemented on my demo v4.10 router and tested with both Mac OS X 10.6 and Windows 7 Ultimate x64

!!Please note this is an Alpha release an as such is not  recommended to be used on any production routers!!

Prerequisites

1. An IPv6 (public) address must be assigned to the hotspot interface

2. IPv6 transit must be working (can you reach ipv6 sites on the internet? try pinging 2404:6800:8004::68 aka ipv6.google.com … from Australia anyway)

3. ND (neighbour discovery) helps to be setup on the specific interface with the following options enabled:

reachable-time=30s retransmit-interval=1s managed-address-configuration=yes advertise-dns=yes

Admin note: as I’m not familiar with the reachable-time and retrans-time values I’ve copied default Cisco values, if anyone wants to correct me on this go ahead ^_^

4. The following firewall rules need to be added (where hotspot is the name of your hotspot interface):

/ipv6 firewall filter
add action=accept chain=forward comment="Accept local to local connections on link-local or public address range" disabled=no in-interface=hotspot out-interface=hotspot
add action=accept chain=forward comment="Allow outbound traffic from any IPv6 address on the \"hotspot-auth\" list" disabled=no in-interface=hotspot src-address-list=hotspot-auth
add action=reject chain=forward comment="Reject traffic not in \"active-hosts\" list" disabled=no in-interface=hotspot

5. Hotspot should not be using to-address mapping (hotspot server “address-pool” should be set to none).

Admin note: this is not something I like to use in general due to the proxy-arp etc. so I’ve done all my testing with it off however you’re welcome to do your own.

6. Scheduler entry can/should? be run every minute to add addresses that might be picked up after the user logs in.

/system scheduler
add comment="" disabled=no interval=30s name=run-ipv6-auth-check on-event="/system script run ipv6-auth-check" policy=read,write start-date=jan/01/1970 start-time=00:00:00

The auth-check Script

#IPv6 authentication script for RouterOS
#Tested on v4.10
#Last updated: 15/06/2010

:local line
:local linecomment
:local maccheck
:local mac
:local username
:local ipv6
:local mapping
:local localcheck

#Loop through each ipv6 address line in the hotspot-auth list
#  Set linecomment variable to the comment of the current line
#  Set maccheck variable by grabbing only the mac address from the comment
#  If an active hotspot listing doesn't exist for this mac address:
#    Remove the address-list line
#  End of if segement
#End of foreach segment

:foreach line in=[/ipv6 firewall address-list find list="hotspot-auth"] do={
  :set linecomment [/ipv6 firewall address-list get $line comment]
  :set maccheck [:pick $linecomment 0 17]
  :if ([/ip hotspot active find mac-address=$maccheck] ="") do={
    /ipv6 firewall address-list remove $line
  }
}

#Loop through active hotspot user lines
#  Set username variable to match currently selecte lines user value
#  Set mac varible to match currently selected lines mac-address value
#  For each listing in neighbour discovery table with the same mac address
#    Set ipv6 variable to match currently selected lines address value
#	 Set localcheck variable to first 4 digits of the current IPv6 address
#    If localcheck doesn't = "fe80" then do the following
#      If no listing exists in the "hotspot-auth" list with the same ip address:
#        Create a new "hotspot-auth" address list entry with the ipv6 address variable and comment set to the mac address and username
#      End of if segment
#    End of if segment
#  End of foreach segment
#End of foreach segment

:foreach line in=[/ip hotspot active find] do={
  :set username [/ip hotspot active get $line user]
  :set mac [/ip hotspot active get $line mac-address]
  :foreach mapping in=[/ipv6 neighbor find mac-address=$mac] do={
    :set ipv6 [/ipv6 neighbor get $mapping address]
    :set localcheck [:pick $ipv6 0 4]
    if ($localcheck != "fe80") do={
      if ([/ipv6 firewall address-list find list="hotspot-auth" address="$ipv6/128"]= "") do={
        /ipv6 firewall address-list add address=$ipv6 list=hotspot-auth comment="$mac $username"
      }
    }
  }
}

Full config example

/ipv6 nd
add advertise-dns=yes advertise-mac-address=yes disabled=no hop-limit=unspecified interface=hotspot managed-address-configuration=yes mtu=unspecified other-configuration=no ra-delay=3s ra-interval=3m20s-10m ra-lifetime=30m reachable-time=1m retransmit-interval=10s

/system scheduler
add comment="Check for any new addresses" disabled=no interval=30s name=run-ipv6-auth-check on-event="/system script run ipv6-auth-check" policy=read,write start-date=jan/01/1970 start-time=00:00:00

/system script
add name=ipv6-auth-check policy=ftp,read,write,winbox source="#IPv6 authentication script for RouterOS\r\
    \n#Tested on v4.10\r\
    \n#Last updated: 15/06/2010\r\
    \n\r\
    \n:local line\r\
    \n:local linecomment\r\
    \n:local maccheck\r\
    \n:local mac\r\
    \n:local username\r\
    \n:local ipv6\r\
    \n:local mapping\r\
    \n:local localcheck\r\
    \n\r\
    \n#Loop through each ipv6 address line in the hotspot-auth list\r\
    \n#  Set linecomment variable to the comment of the current line\r\
    \n#  Set maccheck variable by grabbing only the mac address from the comment\r\
    \n#  If an active hotspot listing doesn't exist for this mac address:\r\
    \n#    Remove the address-list line\r\
    \n#  End of if segement\r\
    \n#End of foreach segment\r\
    \n\r\
    \n:foreach line in=[/ipv6 firewall address-list find list=\"hotspot-auth\"] do={\r\
    \n  :set linecomment [/ipv6 firewall address-list get \$line comment]\r\
    \n  :set maccheck [:pick \$linecomment 0 17]\r\
    \n  :if ([/ip hotspot active find mac-address=\$maccheck] =\"\") do={\r\
    \n    /ipv6 firewall address-list remove \$line\r\
    \n  }\r\
    \n}\r\
    \n\r\
    \n#Loop through active hotspot user lines\r\
    \n#  Set username variable to match currently selecte lines user value\r\
    \n#  Set mac varible to match currently selected lines mac-address value\r\
    \n#  For each listing in neighbour discovery table with the same mac address\r\
    \n#    Set ipv6 variable to match currently selected lines address value\r\
    \n#\t Set localcheck variable to first 4 digits of the current IPv6 address\r\
    \n#    If localcheck doesn't = \"fe80\" then do the following\r\
    \n#      If no listing exists in the \"hotspot-auth\" list with the same ip address:\r\
    \n#        Create a new \"hotspot-auth\" address list entry with the ipv6 address variable and comment set to the mac address and username\r\
    \n#      End of if segment\r\
    \n#    End of if segment\r\
    \n#  End of foreach segment\r\
    \n#End of foreach segment\r\
    \n\r\
    \n:foreach line in=[/ip hotspot active find] do={\r\
    \n  :set username [/ip hotspot active get \$line user]\r\
    \n  :set mac [/ip hotspot active get \$line mac-address]\r\
    \n  :foreach mapping in=[/ipv6 neighbor find mac-address=\$mac] do={\r\
    \n    :set ipv6 [/ipv6 neighbor get \$mapping address]\r\
    \n    :set localcheck [:pick \$ipv6 0 4]\r\
    \n    if (\$localcheck != \"fe80\") do={\r\
    \n      if ([/ipv6 firewall address-list find list=\"hotspot-auth\" address=\"\$ipv6/128\"]= \"\") do={\r\
    \n        /ipv6 firewall address-list add address=\$ipv6 list=hotspot-auth comment=\"\$mac \$username\"\r\
    \n      }\r\
    \n    }\r\
    \n  }\r\
    \n}"

/ipv6 firewall filter
add action=accept chain=forward comment="Accept local to local connections on link-local or public address range" disabled=no in-interface=hotspot out-interface=hotspot
add action=accept chain=forward comment="Allow outbound traffic from any IPv6 address on the \"hotspot-auth\" list" disabled=no in-interface=hotspot src-address-list=hotspot-auth
add action=reject chain=forward comment="Reject traffic not in \"active-hosts\" list" disabled=no in-interface=hotspot

/ip hotspot user profile
set default idle-timeout=none keepalive-timeout=2m name=default on-login="/system script run ipv6-auth-check" on-logout="/system script run ipv6-auth-check" shared-users=1 status-autorefresh=1m transparent-proxy=no

Known Bugs

This won’t detect an IPv6 address until it shows up the in the router’s neighbour discovery table. Windows 7 seems to show up almost straight away as soon as it tries to send any ipv6 traffic whereas Mac OS X 10.6 didn’t appear for a couple of minutes each time.

Until the address has appeared it won’t be added, but as soon as it is added it’ll remain there and not be removed until the user logs out from the hotspot.

The scheduler runs every 30 seconds for this exact reason however I hope to be able to make it useless in the end and have all IPv6 addresses for the client added upon hotspot login

This won’t actually allow you to *account* traffic for the user, just allow them to gain IPv6 connectivity.

3 thoughts on “Mikrotik Hotspot Authentication for IPv6 dual-stacked clients

Leave a Reply