Daily WPA passphrase changer

Post new topic   Reply to topic    DD-WRT Forum Index -> Contributions Upload
Author Message
kalfusisagod
DD-WRT Novice


Joined: 29 Mar 2012
Posts: 13

PostPosted: Mon Jul 02, 2012 1:15    Post subject: Daily WPA passphrase changer Reply with quote
I've posted this tutorial under general questions forum not realizing there was a contributions upload forum, I have removed the other post as this forum is much more suitable.

This document will help you set up a wireless hot spot with a daily rotating WPA password on a Netgear WNDR3700 running DD-WRT v24-sp2 (08/07/10) std. This is a great method for your business if you don't want to mess with expensive portal pages (like Starbucks or McDonalds style) and don't want to mess with complicated credit card services. This can be run solely from your DD-WRT router. You may use this method on other routers but with varying results. The WNDR3700 is a good dual band 2.4/5GHz ABGN wireless router with the ability to broadcast up to 4 SSIDs. It also has a good amount of memory where you can enable JFFS for your scripts, web page, and WPA passwords. It can be found brand new for about 100 bucks. Lets say you run a hookah bar and want to give out free wireless to paying customers. You can use this method to provide this service without giving them a WPA password valid for more than 24 hours. Another scenario is places like Germany where laws require you to secure your wireless access points, this will overcome that, especially if you live downtown and don't want to give out one WPA password and have people leach off your Internet for the rest of the year. This article assumes you have DD-WRT installed on a WNDR3700. This also assumes you have some sort of networking experience and know what a IP address is, how to SSH/SCP into your router etc. If these terms are foreign to you, then do some reading on these topics, and remember you won't learn everything overnight. This article will not go into petty details like "click this, then scroll here and click that" so it'll be a intermediate level article.

1) First ensure the correct time zone and time is set in your router under Setup>Basic Setup tab

2) Set up and secure your SSIDs. Depending on how you set this up remember that the WNDR3700 has up to 4 SSID. I suggest setting up the primary Access Point (AP) interface (ath0) with the wireless G option to ensure compatibility with older MacBooks, iPhones etc. Plus the G 2.4Ghz band has better range. The SSID should be something business oriented like "joes_hookah_bar". You can set this up under the Wireless>Basic Settings tab. Once this is done you can set up a virtual SSID on the same interface to run a un-secure version of your hot spot without Internet access. Set the SSID to something like "joes_hookah_barFREE". This last step is optional but is a good idea to broadcast your free wifi service detailed in the next step. Next, secure your ath0 interface under Wireless>Wireless Security tab. Your passphrase won't matter on the ath0 interface as this will get changed once the script runs. The main thing is to ensure WPA Personal and AES is selected for this otherwise the script won't work without modification.

3) OPTIONAL: Set up nocatspash. This is a recommended step, usually when customers see a secure access point, they don't even bother asking for the password. This method will allow customers to connect to your unsecure access point which will not provide them with access to the Internet, but a simple webpage announcing anything the owner wants; menu, hours, events, and a message telling customers to ask to waitress for the wifi password. Nocatsplash is a hotspot manager where when a user clicks a "I agree" button it will allot so many minutes of access to the Internet. As long as the "I agree" button is deleted out of the HTML code, the user can't access the Intenet (unless they really know what they're doing). The limitations of nocatsplash is that it uses only one simple HTML file, with no pictures, no external CSS files. But with a bit of hard core old school HTML hand coding and a good embedded CSS style, you can make a pretty legit web page. Read the nocatspash wiki and tutorials on how to modify this page and set it up correctly. You can even use a webserver on the Internet to host your page (without the pictures) so you won't have to modify to writable partition on the router with a constantly changing landing page. Ensure you set nocatsplash to run on the correct interface, in this case ath0.1, the unsecure wireless interface.

4) This next script will make 366 WPA passwords for each day of the year. It can be ran on a recent Linux distro. I've tried to run this script on a Mac, but got an "Illegal Byte Sequence" on the tr (translate) command and forget about running this on a windows machine. The script is commented fairly well, so no need to explaining it here. One thing to mention is that a Julian Date is a number assigned to everyday of the year starting with January 1st as being 1 (or in this case 001) and Jan 2nd being 002 and so on all the way up to 365 for December 31st (non leap year). To people new to the Linux command line, just copy and paste the below code into a text file. Once done, rename the file to "WPA_Keys_Script.sh" and run the file from your desktop. You may have to change permissions to execute the file. To do this, right click on the file, and enable the execute option. Once ran, you will see a new file on your desktop named "wpa_keys.txt"

Code:

#!/bin/bash
# This script creates a text file of 366
# WPA keys for your DD-WRT Router preceded
# by a 3 digit Julian Date ie 001, 002 to 366
# Followed by 10 uppercase letters
# Created by Joseph Kalfus MARCH2012
clear
sleep 1
echo "This script will start in a few seconds
It will place a file in the current directory named wpa_keys.txt
You will need to print this file out, and upload it to
your DD-WRT enabled router via SSH or other methods with a writable JFFS partition."
sleep 1
for ((num=1;num<=366;num+=1)); do echo `printf "%03d" $num` `cat /dev/urandom | tr -dc [:upper:] | fold -w 10 | head -1` >> wpa_keys.txt ; done
echo Done.


And the output should look like this in the current directory with the filename of wpa_keys.txt:

Code:

001 ERPHMYDPZE
002 VCYQHOVNZE
003 LBNVORZQOH
004 QQHKFYMKFM
005 UMKAOJSNDB
006 ZBKOOKGYJV
...
362 UGIWJGIPBS
363 SCXRFWSYJG
364 KGHMRDJVTS
365 YVCTFYVXCS
366 KAHAXWXZFS


Now take to outputted file, and print it out for your reference. This file lists your daily WPA keys till the end of the year. Notice the format; The first 3 characters are the Julian date, followed by a space, and then a 10 character uppercase WPA password. Reason I used all uppercase letters was to not have any issues with the Linux GREP command finding a Julian date within the WPA key; this would cause issues. Plus that provides enough possible combinations to deter a bruteforce attack on the WPA handshake, especially if it changes every 24 hours (26^10th= over 141 trillion possibilities) If you don't have a Linux box, download VirtualBox and a current Linux Distro iso to run the above code. Or if you can't do that, PM me, and I'll run it for you and send you back fresh WPA keys. Once you have your text file with your WPA passwords, you will need to put this file onto your router. You can do this several ways, but I prefer SCPing (secure copying) into your router and placing this text file into your *writable* JFFS partition

5) Enable JFFS on your router (if supported). On the WNDR3700, I get over a meg of the writable partition. To enable JFFS, I copy and pasted from the JFFS wiki

-----
The steps to enable JFFS through the router web page are very specific. To avoid having to reset and reprogram your router, it's smart to make a backup here of your settings. If you follow these steps exactly, it should not lock up.
On the router web page click on Administration.
Scroll down until you see JFFS2 Support section.
Click Enable JFFS.
Click Save.
Wait couple seconds, then click Apply.
Wait again. Go back to the Enable JFFS section, and enable Clean JFFS.
Do not click "Save". Click Apply instead.

The router formats the available space.

Wait till you get the web-GUI back, then disable "Clean JFFS" again.
Click "Save".
It may be wise to Reboot the router, just to make sure
-----

The one drawback to the JFFS partition is that you can write to this file system only so many times (a common drawback with any flash based media). In this situation, if you are using nocatspash and want to change your unsecure landing page daily, this would not be a viable solution. If so, plug a USB drive into your router and mount that to your router, which is not a topic for discussion for this post, just read the wikis on this topic.

6) Now that you have a writable JFFS partition and your wpa_keys text file, you need to SSH using SCP (secure copy- a SSH version of the copy command) into your router and place that text file into /jffs folder. To do this, use WinSCP, or on the mac box open up terminal and run the command (should work on Linux, haven't tried)

Code:

scp ~/Desktop/wpa_keys.txt root@192.168.5.1:/jffs


where root will always be root when SSHing/SCPing into your router, and YOUR router's IP address. It'll ask for the password, enter your web GUI password. To verify that the file has transfered, SSH into the router, and run...

Code:

cat /jffs/wpa_keys.txt


... and you will see a list of your WPA keys.



7) Now that you have your daily WPA keys written to the JFFS partition, you need to add a startup script that will run on your router daily. This took a bit of research on these forums so I will not take all the credit on this. I will give credit to kingsmill's post http://www.dd-wrt.com/phpBB2/viewtopic.php?p=654409 as it gave me some guidance on how to approach this, and the NVRAM variables. Also a bit of google research on some Linux commands helped (sed).

Code:

#!/bin/sh
# sleep 10 makes the router wait 10 seconds so it can aquire it's time
sleep 10
# stores the 3 digit julian date into a variable
julian=`date +"%j"`
# runs the grep cmd from the wpa_keys.txt and stores
# the entire line into passphrase variable
passphrase=`grep $julian /jffs/wpa_keys.txt`
# the grep cmd from the previous line stores the ENTIRE line
# so the next cmd will use the sed cmd to cut off the first
# four characters to store ONLY the WPA passphrase into a variable
wpa_password=`echo $passphrase | sed 's/^....//'`
# the next few lines change the NVRAM variable of your wireless
# interface and commit it to memory
nvram unset ath0_wpa_psk
sleep 5
nvram set ath0_wpa_psk=$wpa_password
nvram commit
# the next few lines will restart the ath0 interface
# which simulates the save and apply buttons in the webGUI
sleep 5
stopservice wan
sleep 5
startservice wan


Log into the webGUI portion of your router and click the Administration>Commands tab on top. Now copy and paste the above code into the text box and click the Save Startup button. Now in order to not lock yourself out of your router, you have several options:

a) Use your printed wpa_keys.txt document, google julian date to figure out your julian date and that will be your new WPA passphrase

b) Run the command
Code:

grep `date +"%j"` /jffs/wpa_keys.txt

for some reason, the above code works in terminal on OSX but not in Linux. I think this has to do with the encoding of the tick mark (` with the ~ key) and the double quotes if someone could help me out.

c) or run the command
Code:

date +"%j"

#and then grep that julian date with

grep NNN /jffs/wpa_keys.txt


d) or if you want to play it safe, have an Ethernet cable handy and hardwire to your router if all else fails

8 ) Now reboot your router TWICE with the Administration>Management>Reboot tabs. Test to ensure that the correct WPA passphrase is being used on that interface (in this case ath0)

9) Now your final step is to have your router reboot at a certain time. It could be at any time like midnight, 2am etc. Put some thought into this; if your hookah bar's hours are til 2am every night, I'd have it reboot at 2am. Do accomplish the reboot, click Administration>Keep Alive tab, and then set your reboot time to 00:01 Everyday for example, then save and apply settings. Finally, you will need to set up a cron script to reboot your router again. The reason being is that even though the nvram commit command commits the new WPA password to memory, it doesn't take effect until the router reboots after the script is run. You can not put a restart command in the above script otherwise you'll router will just go into a infinite reboot cycle. The below cron script (under Administration>Management tab, enable cron, copy paste below code in box) reboots the router every night 3 minutes after midnight. Reason being is that my router is set to reboot 1 minute after midnight, allowing it to run it's script and boot and then reboot again

Code:

3 0 * * * root /sbin/reboot


10) OPTIONAL: Lets say you have wireless clients that don't want to mess with a constantly changing passphrase. If you set up nocatsplash in the earlier steps, you can add that MAC address to it's whitelist to allow them unrestricted access to the Internet. Note that this is not a very secure method as someone can sniff packets on this interface and do a MAC Address clone. Another option is that if you do have Wireless N clients, (most new computers, MacBooks that have supported wireless cards) then you can set up a STRONG non-changing WPA passphrase on your ath1 interface. Note that some older mobile devices and laptops don't have wireless N compatibility. Another option is to hardwire if feasible.

11) Final step, print out your WPA keys stored in the JFFS partition and figure out the julian date by going to http://www.fs.fed.us/fire/partners/fepp/juliandate.htm Once you have this, you can even make a word document with the corresponding WPA key for the date like this:

Code:

JAN 01 ERPHMYDPZE
JAN 02 VCYQHOVNZE
JAN 03 LBNVORZQOH
JAN 04 QQHKFYMKFM
JAN 05 UMKAOJSNDB
JAN 06 ZBKOOKGYJV
...
DEC 27 UGIWJGIPBS
DEC 28 SCXRFWSYJG
DEC 29 KGHMRDJVTS
DEC 30 YVCTFYVXCS
DEC 31 KAHAXWXZFS


Remember to make note of any leap years and that FEB 29th will throw off your entire year by one if not noted. Also, your new passphrase will not take effect until your router is rebooted after midnight. For example, if your hookah bar's router reboots at 2am, and a customer wants to gain Internet access at 12:10am, then you would need to use the same WPA passphrase you used before midnight.

I have tested this set up for the last 30 or so days. It didn't work as planned at first but corrected the directions above after much troubleshooting (restarting after nvram commit). Hopefully these directions above help someone out. I would like to thank all the folks that code, post, contribute to the dd-wrt project that made this awesome firmware possible. I'd also like to thank google, and all the contributions to linux and mac made by awesome people. If you have any issues or questions, post them below.

-Joseph Kalfus
Sponsor
TheShanMan
DD-WRT User


Joined: 23 Jul 2007
Posts: 101

PostPosted: Sat Feb 08, 2014 1:25    Post subject: Reply with quote
I wanted to express appreciation for this post as well as provide an alternative. Daily key changing is overkill for me to provide a guest ssid at my house so I modified it to change automatically on the first of every month and I created 24 keys from a password generation site so that the keys recycle every two years instead of every year. Then I printed the months and keys and taped it inside one of my kitchen cabinets for easy access for visitors. Instead of rebooting the router, I have the script run as a cron job directly.

Here's my script, which is a modified version of kalfusisagod's script:

Code:
#!/bin/sh
# get a month number from 1 to 24 (covers a 2 year span)
month=$((`date +"%m"`+12*(`date +"%y"`%2)))
month=`printf "%02d" $month`
# runs the grep cmd from the wpa_keys.txt and stores
# the entire line into passphrase variable
passphrase=`grep $month /jffs/wpa_keys.txt`
# the grep cmd from the previous line stores the ENTIRE line
# so the next cmd will use the sed cmd to cut off the first
# three characters to store ONLY the WPA passphrase into a variable
wpa_password=`echo $passphrase | sed 's/^...//'`
#echo Setting password to $wpa_password
# the next few lines change the NVRAM variable of your wireless
# interface and commit it to memory
nvram unset wl0.1_wpa_psk
sleep 5
nvram set wl0.1_wpa_psk=$wpa_password
nvram commit
# the next few lines will restart the wl0.1 interface
# which simulates the save and apply buttons in the webGUI
sleep 5
stopservice wan
sleep 5
startservice wan


And here's my cron job definition to run it at 3AM on the first of every month:

Code:
0 3 1 * * root /jffs/rotatingkeys.sh > /var/log/rotatingkeys 2>&1


The one thing I'd be curious to get explanation on is the script spits out the message "vlan2: No such process".

Hope someone finds this helpful.
kalfusisagod
DD-WRT Novice


Joined: 29 Mar 2012
Posts: 13

PostPosted: Sat Feb 08, 2014 2:28    Post subject: Reply with quote
TheShanMan,

Hey thanks for taking interest in my article, it was a real pain to get this set up and I appreciate your kind words. As far as the "no such process" not sure what is wrong here. I have since then upgraded to a newer version of dd-wrt and haven't used this script since. But I also like your idea of changing the passphrase less often as this is a good option.

-Joseph
TheShanMan
DD-WRT User


Joined: 23 Jul 2007
Posts: 101

PostPosted: Sat Feb 08, 2014 2:35    Post subject: Reply with quote
Well I appreciate the work you put into it. You made my job easy comparatively. I probably wouldn't have tried to do this if it weren't for coming across this thread in a search. So thank you for sharing your work. Sharing my changes was the least I could do in return.
TheShanMan
DD-WRT User


Joined: 23 Jul 2007
Posts: 101

PostPosted: Sat Feb 08, 2014 23:03    Post subject: Reply with quote
Here's rev 2 of my script. I set up my router to run the script on startup too and found that sometimes ntp can take as much as a few minutes to set the clock (anyone know why???) so I made this more robust by checking to see if the year is at least 2014. I also put a sleep command of a few minutes prior to calling this script to hopefully avoid that problem (didn't include in the script itself so I can run it directly without having to wait a long time).

It now also compares to the old key and only tries to change it if it needs to (as a result, I changed my cron job to run daily instead of monthly - no harm in running it often and if anything goes haywire, hopefully it'll get corrected the next day).

It handles logging itself and still outputs to the console.

It now emails the results (unless it hasn't changed), so you can easily monitor the changes over time.

Code:
#!/bin/sh
tmplogfile=/tmp/rotatingkeyslog
logfile=/var/log/rotatingkeys

{
   routername=`nvram get router_name`
   SMTP="1.2.3.4"
   FROM="my@router.com"
   FROM_NAME="My $routername Router"
   DOMAIN="mydomain.com"
   USER=""
   PASSWORD=""
   SUBJECT="$routername guest key change"
   TO="me@mydomain.com"

   date
   if [ `date +"%Y"` -ge 2014 ]
   then
      # get a month number from 1 to 24 (covers a 2 year span)
      month=$((`date +"%m"`+12*(`date +"%y"`%2)))
      month=`printf "%02d" $month`
      # runs the grep cmd from the wpa_keys.txt and stores
      # the entire line into passphrase variable
      passphrase=`grep $month /jffs/wpa_keys.txt`
      # the grep cmd from the previous line stores the ENTIRE line
      # so the next cmd will use the sed cmd to cut off the first
      # three characters to store ONLY the WPA passphrase into a variable
      wpa_password=`echo $passphrase | sed 's/^...//'`
      #echo Setting password to $wpa_password
      # the next few lines change the NVRAM variable of your wireless
      # interface and commit it to memory
      old=`nvram get wl0.1_wpa_psk`
      if [ "$old" != "$wpa_password" ]
      then
         nvram unset wl0.1_wpa_psk
         sleep 5
         nvram set wl0.1_wpa_psk=$wpa_password
         nvram commit
         # the next few lines will restart the wl0.1 interface
         # which simulates the save and apply buttons in the webGUI
         sleep 5
         stopservice wan
         sleep 5
         startservice wan

         MESSAGE="Key changed from $old to $wpa_password for $month/"`date +"%y"`"."
         /usr/sbin/sendmail -S"$SMTP" -f"$FROM" -F"$FROM_NAME" -d"$DOMAIN" -u"$USER" -p"$PASSWORD" -s"$SUBJECT" -m"$MESSAGE" $TO

         echo "Password updated for $month/"`date +"%y"`"."
      else
         echo "Password already up to date for $month/"`date +"%y"`"."
      fi
   else
      MESSAGE="Clock isn't properly set ("`date`"). Can't determine which password to use. Password not updated."
      /usr/sbin/sendmail -S"$SMTP" -f"$FROM" -F"$FROM_NAME" -d"$DOMAIN" -u"$USER" -p"$PASSWORD" -s"$SUBJECT" -m"$MESSAGE" $TO
      echo $MESSAGE
   fi
} > $tmplogfile 2>&1
cat $tmplogfile >> $logfile

cat $tmplogfile
rm $tmplogfile
SubZeroWISP
DD-WRT Novice


Joined: 15 Feb 2017
Posts: 1

PostPosted: Wed Feb 15, 2017 8:13    Post subject: Thank You. . . . But? Reply with quote
Awesome. Well described directions and good code. But I am running into a problem, that my inexperience is preventing me from solving. I see this is an older post, so I am praying that someone is out there listening still. . .

I am guessing My problems lie in the fact that I have a different router, with (most likely,) different firmware. I am running an
ASUS RT-N16 with
DD-WRT v24-sp2 (12/24/10) mini - build 15962

I had to alter the ath0 to wl0 and raise the sleep command at the begining to 30 secs, otherwise I wouldnt get the right julian date passphrase. I load the script as a startup script, apply and then reboot. After the reboot, I can not associate ANY devices wirelessly. Neither the old passphrase or the new passphrase from the JFFS partition works. I can cable into the router and the GUI shows that the correct passphrase (per the corresponding julian date) is set. The Start/Stopservice wan doesnt fix the problem. I have also tried (by replacing stopservice/startservice wan):
Code:
ifconfig eth1 down (and then up)
wl -i eth1 down (and then up)
stopservice wlan (followed by startservice wlan)
and
rc restart

all with NO avail. The ONLY way it will work is if i hit APPLY from in the GUI. I can not find any command or section of script that mimic pressing "APPLY" in the GUI on the internet. The following is my startup script (any input at all will be appreciated!!):
Code:
#!/bin/sh
# sleep 30 makes the router wait 30seconds so it can aquire it's time
sleep 30
# stores the 3 digit julian date into a variable
julian=`date +"%j"`
# runs the grep cmd from the wpa_keys.txt and stores
# the entire line into passphrase variable
passphrase=`grep $julian /jffs/wpa_keys.txt`
# the grep cmd from the previous line stores the ENTIRE line
# so the next cmd will use the sed cmd to cut off the first
# four characters to store ONLY the WPA passphrase into a variable
wpa_password=`echo $passphrase | sed 's/^....//'`
# the next few lines change the NVRAM variable of your wireless
# interface and commit it to memory
nvram unset wl0_wpa_psk
sleep 5
nvram set wl0_wpa_psk=$wpa_password
nvram commit
# the next few lines will restart the wl0 interface
# which simulates the save and apply buttons in the webGUI
sleep 5
stopservice wan
sleep 5
startservice wan

I hope someone will come to the rescue! Thanks ahead of time for any input!

-CodeCrossEyed
TheShanMan
DD-WRT User


Joined: 23 Jul 2007
Posts: 101

PostPosted: Thu Feb 23, 2017 16:51    Post subject: Reply with quote
Glad it's helping you out. I had the same experience actually. I was frustrated not to find any way to mimic the Apply button. I ended up forcing a reboot in the script if the password is changed. The cron job is at like 3am so not too big of a deal in my case but it seems so unnecessary and overkill.
LrdThndr
DD-WRT Novice


Joined: 30 Apr 2024
Posts: 1

PostPosted: Tue Apr 30, 2024 19:20    Post subject: Re: Daily WPA passphrase changer Reply with quote
kalfusisagod wrote:
I've tried to run this script on a Mac, but got an "Illegal Byte Sequence" on the tr (translate) command


You can make it work on Mac by adding a few configurations to the top of the script:

Code:

#!/bin/bash

export LC_CTYPE=C
export LC_ALL=C

... the rest of your generator script
icantremember
DD-WRT Novice


Joined: 25 Sep 2024
Posts: 1

PostPosted: Wed Sep 25, 2024 18:21    Post subject: Reply with quote
this is amazing
kernel-panic69
DD-WRT Guru


Joined: 08 May 2018
Posts: 14961
Location: Texas, USA

PostPosted: Wed Sep 25, 2024 21:55    Post subject: Reply with quote
You can also use attached USB storage instead of internal flash for JFFS.
_________________
"Life is but a fleeting moment, a vapor that vanishes quickly; All is vanity"
Contribute To DD-WRT
Pogo - A minimal level of ability is expected and needed...
DD-WRT Releases 2023 (PolitePol)
DD-WRT Releases 2023 (RSS Everything)

----------------------
Linux User #377467 counter.li.org / linuxcounter.net
Display posts from previous:    Page 1 of 1
Post new topic   Reply to topic    DD-WRT Forum Index -> Contributions Upload All times are GMT

Navigation

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum