Introduction

This page will explain step by step, how to remove advertisements from your surfing experience on every browser\computer on your network without the need to change anything on them.

We will accomplish this by installing the "pixelserv" program on a DD-WRT router and some DNS "magic".

Update: New walk-through movie is now up on youtube.




Overview

Essentially this works by deliberately poisoning our DNS to return a specific IP for domains in the an unapproved list. This unapproved list will contain domain names of sites that are responsible exclusively for delivering advertisement content, so we won't miss them much.

We will setup an additional HTTP server on the router to serve a transparent one pixel image, as the answer for any URL request. In conjunction with the DNS "wrong" resolve, this will cause the network clients to request the content from our internal pixelserver and get a blank image in response.
That way all the clients (with no additional software on them) won't know that the advertisement content was blocked and the page loads correctly despite the fact that its missing the content of the advertisement.

To generate the unapproved list, we will create one personal list in conjunction to two dynamically downloaded lists. the dynamic lists are the MVPS host file and the Yoyo domain list, together they hold a very extensive list of advertisement sites. By taking advantage of them, we are left with the responsibility of just adding the delta of sites that are not already in one of them, in our personal list.

Prerequisites

  1. This procedure was created and tested on DD-WRT (v24pre-sp2 build 3.6.10 mini), this means that you should already have it installed on your router to use it. You can find more information here.
  2. You have Telnet or SSH access into the router.
  3. The client computer is using the router as the DNS server (this is the default).
  4. Space for JFFS (when in doubt, I recommend using the mini version of DD-WRT).
  5. You know how to use the vi editor.

Credits

I have not "invented" anything here, just collected it into a representable simple to follow procedure.
The sources for this page are:

  1. https://secure.dd-wrt.com/phpBB2/viewtopic.php?p=434120&highlight=&sid=f9c90a3539cb6c2ae0f6e124877d909b
  2. http://www.dd-wrt.com/phpBB2/viewtopic.php?t=47515&postdays=0&postorder=asc&start=0
  3. http://wiki.flexion.org/SettingUpDNSMasq.html

Router setup

Enable JFFS

I have decided that the best way to get this done, make it stable and reproducible in addition to being a good internet citizen (as in not strain the servers holding the lists and executable every time the script is run) is to use JFFS to store as much of the configurations as possible. there are other ways to do this without enabling JFFS, if you cant due to space limitations, but they are not covered here.

FWI: There is an alternate version of the script here, which is better suited for cases of super extreme low space on JFFS, because it is designed to handle them in addition to it being more compact by consolidating a lot of clutter into functions. With that said, while i'm very proud of it, it is less thoroughly tested then this version and depends on the "general script" for some of the functions that are self contained in this version.

Using JFFS enables you to:
  • Upgrade the firmware and keep the ads-filter in place as long as the new firmware isn't bigger then the last one you used, because the JFFS content, will remain untouched.
  • Backup the router settings without tons of custom scripts information for a more streamline backup file.
  • Backup the work you have done in this guide, by simply copying three files, the pixelserv executable, your personal domains list and the startup script.

Enable JFFS on your router, by going to the "Administration" tab. find the JFFS section and click Enable like in the picture.
dd-jffs02.png
*If its the first time that you have enabled JFFS, also enable the "clean" option, save and reboot for it to take affect.

Once you have enabled JFFS and you see that you have some free space like in the picture above, create the directory that will hold our script by issuing this command in a terminal:
mkdir -p /jffs/etc/config
Note: this directory location has a special meaning for the DD-WRT firmware , so putting the startup script in this directory will cause it to be run automatically at startup.

Download pixelserv to JFFS

In a terminal issue these commands to grab the executable from my site:
cd /jffs/
wget http://hotfortech.wikispaces.com/file/view/pixelserv
I'm not taking credit for the program, just avoiding hot linking.

Make the file executable:
chmod +x /jffs/pixelserv

Setting up the Personal blocked domains list

This list enables you to add domains to the unapproved lists, if you find that the two dynamic lists don't catch something.
There are two ways of injecting the configuration with your own list of domains to block:

  1. Put the list into the DNSMasq configuration box in the wegGUI:
    Go to the "Administration" tab, in the "DNSMasq" section, find the "Additional DNSMasq Options" text-box.
    In this text-box enter the lists of domains that you want to be blocked with the syntax shown below:
    dnsmasq03.png
    Where 192.168.1.254 is the IP we will set up for the pixelserv.
    Note 1: This approach has the distinct disadvantage that you will need to remember not to delete it by mistake and possibly enter it manually again and again. This is because you have to delete the configurations every time you upgrade the firmware at the very least, and you are not allowed to use "saved configurations" from one version of DD-WRT to another (even with the same version the results are "iffy" sometimes).
    note 2: I do recommend enabling "Local DNS" even though its not necessary for this procedure.


  2. Create the personal-ads-list.conf file on our jffs mount:
    vi /jffs/personal-ads-list.conf

    Feel free to copy my file, it looks like this:
    address=/sharefoco.com/192.168.1.254
    address=/dclk.haaretz.co.il/192.168.1.254
    address=/gemius.pl/192.168.1.254
    address=/neto.co.il/192.168.1.254
    address=/outbrain.com/192.168.1.254
    address=/addthis.com/192.168.1.254
    address=/imrworldwide.com/192.168.1.254
    address=/clickon.co.il/192.168.1.254
    address=/cpxinteractive.com/192.168.1.254
    address=/xtendmedia.com/192.168.1.254
    address=/yieldmanager.com/192.168.1.254
    address=/z5x.net/192.168.1.254
    address=/adbrite.com/192.168.1.254
    address=/cltomedia.info/192.168.1.254
    address=/cltomedia.info/192.168.1.254
    address=/openx.net/192.168.1.254
    address=/clicktorrent.info/192.168.1.254
    address=/zedo.com/192.168.1.254
    address=/ad.foxnetworks.com/192.168.1.254
    address=/adnxs.com/192.168.1.254
    address=/ad.yieldmanager.com/192.168.1.254
    address=/adperium.com/192.168.1.254
    address=/livejasmin.com/192.168.1.254
    address=/googleads.g.doubleclick.net/192.168.1.254
    address=/doubleclick.net/192.168.1.254
    address=/doubleclick.com/192.168.1.254
    address=/infra-ad.com/192.168.1.254
    address=/2mdn.net/192.168.1.254
    address=/total-media.net/192.168.1.254
    address=/ds.serving-sys.com/192.168.1.254
    address=/reali-tech.com/192.168.1.254
    address=/2.gns.co.il/192.168.1.254
    address=/checkm8.com/192.168.1.254
    address=/e-dologic.co.il/192.168.1.254
    address=/wee.co.il/192.168.1.254
    address=/gorni.co.il/192.168.1.254
    address=/ustream.tv/192.168.1.254
    address=/quantserve.com/192.168.1.254
    address=/conviva.com/192.168.1.254
    address=/tdmt.com/192.168.1.254
    address=/smartadserver.com/192.168.1.254
    address=/google-analytics.com/192.168.1.254
    address=/fmpub.net/192.168.1.254
    address=/gravatar.com/192.168.1.254
    address=/mediaplex.com/192.168.1.254
    address=/dynamitedata.com/192.168.1.254
    address=/dynamic1.anandtech.com/192.168.1.254
    address=/vox-static.liverail.com/192.168.1.254
    address=/googlesyndication.com/192.168.1.254
    address=/tracker.thepiratebay.org/192.168.1.254

    Where 192.168.1.254 is the IP we will set up for the pixelserv.

Schedule the lists to be refreshed automatically (Optional)

The two dynamic lists are updated from time to time by there respective owners, so we will make the router grab the lists on a schedule in addition to the startup file. we will accomplish this by invoking the built in cron mechanism via the web interface.
Under the "Administration" tab, make sure that Cron is enabled.
In the additional Cron Jobs text-box add:
* 0 * * * root /jffs/etc/config/disable_adds.startup
As in the picture below.
cron-startup.png
Just "Save" for now, don't apply so we won't lose our connection to the shell. this will take affect later anyhow so it doesn't matter if its not applied right a way.

This will make the router perform an update to the lists everyday at midnight (0:00).

The Engine of the ads blocker

We will create a startup script that will perform all the necessary configurations for us. Don't get alarmed by its length, it is just robust enough to perform its duty's while not stepping on anyones toes and keeping the routers' usability as undisturbed and it's erosion down to a minimum as possible.
The script, IMHO, is very well documented below (under the troubleshooting section), so anyone can examine it for errors of syntax or design (suggestions are always welcomed).

Create the new startup script:
vi /jffs/etc/config/disable_adds.startup
note: you can do this under the "Administration" -> "Commands" tab -> "Save "Startup", in the web-GUI, but i have not tested this, and it has the same disadvantage as putting the personal list in the web-GUI explained above.

Make this its content:
#!/bin/sh
pixel=192.168.1.254
 
logger -s -p local0.notice -t ad_blocker_startup_script "###########abs blocker started and waiting for router boot to finish###########"
sleep 30
logger -s -p local0.notice -t ad_blocker_startup_script "###########New IP and ports setup###########"
changed_nvram=0
/sbin/ifconfig br0:1 $pixel netmask 255.255.255.0 broadcast 192.168.1.255 up
if [[ -z "`ps | grep -v grep | grep "httpd -p 81"`" && `nvram get http_lanport` -ne 81 ]]
then
logger -s -p local0.notice -t ad_blocker_startup_script "it seems that the web-GUI is not setup yet"
stopservice httpd
nvram set http_lanport=81
nvram commit
startservice httpd
else
logger -s -p local0.notice -t ad_blocker_startup_script  "The web-GUI is already setup"
fi
 
logger -s -p local0.notice -t ad_blocker_startup_script  "###########Redirect setup###########"
if [[ -z "`iptables -L -n -t nat | grep $(nvram get lan_ipaddr) | grep 81`" ]]
then
logger -s -p local0.notice -t ad_blocker_startup_script "did NOT find an active redirect rule with the iptable command, injecting it now."
/usr/sbin/iptables -t nat -I PREROUTING 1 -d $(nvram get lan_ipaddr) -p tcp --dport 80 -j DNAT --to $(nvram get lan_ipaddr):81
fi
 
logger -s -p local0.notice -t ad_blocker_startup_script "###########Appending to the FW script###########"
nvram get rc_firewall > /tmp/fw.tmp
if [[ -z "`cat /tmp/fw.tmp | grep "/usr/sbin/iptables -t nat -I PREROUTING 1 -d $(nvram get lan_ipaddr) -p tcp --dport 80 -j DNAT --to $(nvram get lan_ipaddr):81"`" ]]
then
echo "/usr/sbin/iptables -t nat -I PREROUTING 1 -d $(nvram get lan_ipaddr) -p tcp --dport 80 -j DNAT --to $(nvram get lan_ipaddr):81" >> /tmp/fw.tmp
nvram set rc_firewall="`cat /tmp/fw.tmp`"
logger -s -p local0.notice -t ad_blocker_startup_script "DONE appending to FW script"
changed_nvram=1
else
logger -s -p local0.notice -t ad_blocker_startup_script "the FW script is already in place"
fi
rm /tmp/fw.tmp
 
logger -s -p local0.notice -t ad_blocker_startup_script "###########Starting pixelsrv###########"
if [[ -n "`ps | grep -v grep | grep /jffs/pixelserv`" ]]
then
logger -s -p local0.notice -t ad_blocker_startup_script "the pixelserv is already up"
else
logger -s -p local0.notice -t ad_blocker_startup_script "it seems that the pixelserv isnt up. starting it now"
/jffs/pixelserv $pixel -p 80
fi
 
logger -s -p local0.notice -t ad_blocker_startup_script "###########Get the online lists###########"
tmp2="`find /jffs/dlhosts -mtime +3`"
tmp3="`find /jffs/dnsmasq.adblock.conf -mtime +3`"
 
if [[ -n "`echo $tmp2 | grep "/jffs"`" || -n "`echo $tmp3 | grep "/jffs"`" || ! -e /jffs/dlhosts || ! -e /jffs/dnsmasq.adblock.conf ]]
then
logger -s -p local0.notice -t ad_blocker_startup_script "The lists are not setup at all yet, or more then a 3 days old. will now retrive them from the web"
logger -s -p local0.notice -t ad_blocker_startup_script "Waiting for the Internet connection to come up (5 pings)"
while ! ping -c 5 www.d.co.il; do
  logger -s -p local0.notice -t ad_blocker_startup_script "ping of www.d.co.il failed sleeping for 30 seconds"
  sleep 30
done
logger -s -p local0.notice -t ad_blocker_startup_script "Connection to the Internet verified, retrieving the MVPS hosts list"
wget -q -O - http://www.mvps.org/winhelp2002/hosts.txt | grep "^127.0.0.1" | grep -v localhost | tr -d '\015' >/tmp/dlhosts.tmp
logger -s -p local0.notice -t ad_blocker_startup_script "adjusting the MVPS hosts list for our use"
cat /tmp/dlhosts.tmp | sed s/127.0.0.1/$pixel/g > /tmp/dlhosts
logger -s -p local0.notice -t ad_blocker_startup_script "done adjusting the MVPS hosts list use"
logger -s -p local0.notice -t ad_blocker_startup_script "retrieving the Yoyo domain list"
wget -q "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=dnsmasq&showintro=0&mimetype=plaintext" -O /tmp/adblock.tmp
logger -s -p local0.notice -t ad_blocker_startup_script "adjusting the Yoyo domain list for our use"
cat /tmp/adblock.tmp | sed s/127.0.0.1/$pixel/g > /tmp/dnsmasq.adblock.conf
logger -s -p local0.notice -t ad_blocker_startup_script "Moving the MVPS hosts list to JFFS"
mv /tmp/dlhosts /jffs/dlhosts
logger -s -p local0.notice -t ad_blocker_startup_script "Moving the Yoyo list to JFFS"
mv /tmp/dnsmasq.adblock.conf /jffs/dnsmasq.adblock.conf
rm /tmp/adblock.tmp
rm /tmp/dlhosts.tmp
else
logger -s -p local0.notice -t ad_blocker_startup_script "The lists are less then 3 days old, saving on flash erosion and NOT refreshing them"
fi
 
 
logger -s -p local0.notice -t ad_blocker_startup_script "###########Injecting the DNSmasq nvram options with the dynamic block lists###########"
nvram get dnsmasq_options > /tmp/dns-options.tmp
    if [[ -z "`cat /tmp/dns-options.tmp | grep "/jffs/dnsmasq.adblock.conf"`" || -z "`cat /tmp/dns-options.tmp | grep "/jffs/dlhosts"`" && -e /jffs/dnsmasq.adblock.conf && -e /jffs/dnsmasq.conf ]]
    then
    logger -s -p local0.notice -t ad_blocker_startup_script "Did not find DNSMaq options in nvram and adding them now"
    echo "conf-file=/jffs/dnsmasq.adblock.conf" >> /tmp/dns-options.tmp
    echo "addn-hosts=/jffs/dlhosts" >> /tmp/dns-options.tmp
    changed_nvram=1
    logger -s -p local0.notice -t ad_blocker_startup_script "Added options to nvram DNSMasq options"
        else
    logger -s -p local0.notice -t ad_blocker_startup_script "The DNSMaq options are already in place"
    fi
 
 
logger -s -p local0.notice -t ad_blocker_startup_script "###########Checking if the personal list is a file###########"
if [[ -z "`cat /tmp/dnsmasq.conf | grep conf-file=/jffs/personal-ads-list.conf`" && -z "`nvram get dnsmasq_options | grep "/jffs/personal-ads-list.conf"`" &&  -e /jffs/personal-ads-list.conf ]]
then
logger -s -p local0.notice -t ad_blocker_startup_script "Yes the personal list is in the form of a file"
echo "conf-file=/jffs/personal-ads-list.conf" >> /tmp/dns-options.tmp
changed_nvram=1
else
[ ! -e /jffs/personal-ads-list.conf ] && logger -s -p local0.notice -t ad_blocker_startup_script "The personal list (assuming there is one) is not in a file"
[ -n "`nvram get dnsmasq_options | grep "/jffs/personal-ads-list.conf"`" ] && logger -s -p local0.notice -t ad_blocker_startup_script "the personal list is a file, and... it is already in place acording to the NVRAM options readout"
fi
 
logger -s -p local0.notice -t ad_blocker_startup_script "###########Collective NVRAM changes to Commit###########"
if [ "$changed_nvram" -eq 1 ]
then
nvram set dnsmasq_options="`cat /tmp/dns-options.tmp`"
logger -s -p local0.notice -t ad_blocker_startup_script "Found that NVRAM was changed and committing changes now"
nvram commit
else
logger -s -p local0.notice -t ad_blocker_startup_script "Nothing to commit"
fi
rm /tmp/dns-options.tmp
 
logger -s -p local0.notice -t ad_blocker_startup_script "###########Refreshing DNS settings###########"
stopservice dnsmasq && logger -s -p local0.notice -t ad_blocker_startup_script "stopped the dnsmasq service"
startservice dnsmasq && logger -s -p local0.notice -t ad_blocker_startup_script "started the dnsmasq service"
 
logger -s -p local0.notice -t ad_blocker_startup_script "###########Blink the SES Leds###########"
tmp=50
while [ $tmp -ge 0 ]
do
   /sbin/gpio enable 3
   /sbin/gpio disable 2
   /sbin/gpio enable 2
   /sbin/gpio disable 3
   tmp=`expr $tmp - 1`
done
 
/sbin/gpio enable 2
/sbin/gpio disable 3
 
logger -s -p local0.notice -t ad_blocker_startup_script "The Ads blocker script has finished its run and you should up and running"

Make the script executable:
chmod +x /jffs/etc/config/disable_adds.startup
Run it by calling it or rebooting the router:
/jffs/etc/config/disable_adds.startup

Thats it, you should see a lot of sites "missing" their ads... :)



Troubleshooting

If you run into problems there are a couple of things that you can do to check what went wrong.

  • Test that the advertisement domain is resolved to the pixelserv IP - you can do this by issuing the nslookup command against the "offending" domain.
    For example:
    nslookup ad-emea.dubleclick.com

    Should look like:
    nslookup01a.png
    Where a normal unblocked answer would look like:
    nslookup02.png

  • Make sure your client is using the router as the DNS.
    Especially when using a VPN or a network that is more complex then the normal router to computer setup, it is possible that your client computer is simply not using the router as its DNS.
    It is very easy to see in the command above what is the DNS server the client is using, If the IP is not the same as the router, you have found the problem.

  • Clear your personal machines DNS cache - This is because otherwise you may still see the ads to the site your testing with, simply because your computer already knows how to get the advertisement content on its own without consulting the DNS for it.
    On windows this would be:
    ipconfig /flushdns

  • Close the browser - sometimes the browser holds the information cached, so clearing the DNS cache as shown above doesn't help because of it.

  • When in doubt reboot.

  • Use syslog.
    You can activate the routers syslog daemon and then look at the messages to see it the script encounters any problems by examining its messages.
    To do this go to the "Services" tab and enable the syslog daemon as in the picture below:
    syslog-enable.png
    Note: the "Remote Server" is used when you have a listening syslog server on another machine (like with kiwi ) if you don't have one, simply leave it blank.
    Once enabled, you can see the debug messages by looking at the /var/logs/messages file.
    To see all the messages from boot-up you can use:
    more /var/log/messages

    You can use the "tail" command to see the messages as they come in, in real time:
    tail -f /var/log/messages


Lets examine the scripts segment by segment:

The first three lines are:
  • #!/bin/sh - tells the router that this is an "sh" type of a script.
  • pixel=192.168.1.254 - set the new IP that we will dedicate for the pixelserver (it can be anything else in the subnet that you'd like, but this is a relatively safe option).
  • The logger command, with the parameters it was given, make it act like "echo" and in addition the messages go to the syslog. I used it so if need be, we can activate syslog in the Troubleshooting segment below and see what happened during startup (when we cant connect to the router yet).
  • "sleep 30" - Wait for 30 seconds before trying to do anything, to give the other processes the router preforms at boot, time to finish.
  • "change_nvram=0" - Set the variable that we use later to tell if we need to commit changes to the NVRAM to 0.

New IP and ports setup

There are two limitations to our setup:
  1. The pixelserv executable cant bind to another port as long as 80 is occupied (yes i tried). as i'm not going to hunt the source code, fix the problem and cross compile it for the router... I used the workaround of moving the management port.
  2. The management HTTP daemon automatically binds to its defined port on all the IPs addresses on the router. That is why we need to move it from port 80 so that the pixel server can bind to 80 with the additional IP we will setup for it.

So we will move the HTTP daemon and once it is moved, we will redirect the traffic destined for the management IP on port 80 to the alternate port we bound it to (81) automatically using an iptables rule. this will keep the access to the management interface "unchanged", while also freeing port 80 on the secondary IP.

  • First we setup an additional IP using the ifconfig command:
    • "br0:1" - Is a new sub-interface of the bridge interface (a logical interface that connects the wired and wireless ports ). By using this new undefined interface we can be sure that nothing else will try to use it somewhere down the line.
    • $pixel - Takes the new IP we want to dedicate for the pixelserver from the variable "pixel" we defined in the beginning of the script.
  • IF - Tests two conditions: 1. is the management HTTP daemon already working on port 81? 2. is the NVRAM (Non-volatile ram) variable set to tell the HTTP daemon to bind to port 81?
    True:
    • "stopservice httpd" - Kill the currently running management HTTP daemon.
    • "nvram set http_lanport=81" - Set the management bind port to 81 in the non-volatile ram.
    • "nvram commit" - Commit the change we just made so that it will survive a reboot. (as not losing the web-GUI is so important, I have not delayed the change for the collective commit later. this only happens once anyhow).
    • "startservice httpd" - Start the management HTTP daemon, it will now see that the bind port is 81 and will use it instead of 80.
    False:
    • Note that there is nothing that needs to be done and move on.

Redirect setup

Now that we moved the management web-GUI to port 81, we need to address the fact that currently we cant connect to it without specifying the port in the web browser (annoying). this iptable rule will take the communication that comes to port 80 and automatically throw it into port 81 for us, and we can stay oblivious to the change we made in the previous step.

  • IF - Tests for one condition: "Is the iptable rule missing from currently running configuration?"
    True:
    • Note to syslog
    • iptable:
      • " -t nat" - Use the NAT portion of the iptables.
      • "-I PREROUTING 1" - Insert (I) into the Pre-routing chain at place number one (1) from the top.
      • "-d $(nvram get lan_ipaddr)" - When the destination (-d) is the readout from the nvram variable of "lan_ipaddr". this enables the router's IP to be anything you want instead of forcing you to change a "hard coded" address in the script.
      • "-p tcp --dport 80" - Only for the TCP protocol (-p tcp), communication with the destination port (--dport) of 80.
      • "-j DNAT" - Perform "Destination NATing"
      • "--to $(nvram get lan_ipaddr):81" - Direct the traffic to the nvram variable of "lan_ipaddr" with port 81.
    False:
    • Do nothing but continue to the next segment.

Appending to the FW script

There is a "problem" that the iptable rules get erased and rebuilt every time there is a change to the routers' configurations by the firewall script.
This means that without this segment, every time you apply changes to the router, you either have to connect to it on port 81 or reboot it.

To over come this, the startup script assumes the responsibility of injecting the necessary iptable rule to the firewall script. It appends the same iptable rule we used in the "Redirect setup" segment to the firewall script.
That way you are spared from needing to manually enter the rule in the web-GUI, and also if you had anything else in the firewall script it will not get overwritten, while insuring that your access to the web-GUI will persist without the need to reboot every time you change a setting on the router.

  • nvram get rc_firewall > /tmp/fw.tmp" - Write the current firewall script content from NVRAM to a temporary file
  • IF - Tests for one condition: "Is the iptable rule missing from the firewall script?"
    True:
    • "echo iptab.... >> /tmp/fw.tmp" - Use the bash "append redirector" (>>) to add the iptables rule, to the file that holds the currently active firewall script.
    • "nvram set rc_firewall="`cat /tmp/fw.tmp`" "- Read the contents of the modified fw.tmp file (cat) and make it the firewall script in nvram (nvram set).
    • note to syslog
    • "changed_nvram=1" - Set the variable to 1 so we know that there was a change when we get to the commit segment.
    False:
    • Note to syslog and continue to the next segment
  • "rm /tmp/fw.tmp" - Delete the temporary file we used to perform the append operation.

Starting pixelsrv

Now that the stage is set, we can start the pixelserv to have it serve our clients.

  • IF - Tests for one condition: "Is the pixelsrv already running?"
    True:
    • Note to syslog and continue to the next segment
    False:
    • "/jffs/pixelserv $pixel -p 80" - Start the pixel server with the IP we set in the "pixel" variable at the beginning of the script, on port 80.

Get the online lists

This segment is responsible for a couple of things:
  1. Getting the online list as the name suggest
  2. Adjusting the online lists for our needs.
  3. Save the flash on the router from over use and subsequent *erosion.

*The erosion problem is the fact that the flash chip that is used for JFFS has a limited amount of cycles before it dies, so writing to it should be done as sparingly as possible.

  • tmp2="`find /jffs/dlhosts -mtime +3`" - This sets the variable "tmp2" to the returned string of the "Find" command that only returnes names of files that are more then 3 days old. This is a work around so we can test against the find command results because the busybox version of "find" doesnt return normal exit statuses.
  • tmp3="`find /jffs/dnsmasq.adblock.conf -mtime +3`" - same as above, only for the yoyo list file
  • IF - Test for these conditions: 1. "Did the find commands return file names, meaning that they are more then tree days old?" 2. "Are the dynamic files missing?"
    True:
    • Perform the sections below.
    False:
    • Note to syslog and skip retrieving the lists.

Waiting for the Internet connection to come up

At boot time, the script could be run when the connection to the internet isn't available yet.
To over come this we will ask it to check if it is able to ping the www.d.co.il domain 5 times, if not wait for 30 seconds.
This will give time for the internet connection to come up and when it does, the script will move on to the next section.

Setting up the MVPS and YoYo blocked sites lists

This segments' code, with a few slight additions to make it use the "pixel" variable and logging of the various stages, was taken almost "as is" from the sources sites. what it will do is:
  • Get the hosts list from the MVPS site and store it in the /jffs/dlhosts file.
  • Get the server list from the Yoyo site and store it in the /jffs/dnsmasq.adblock.conf file.
  • Substitute the references to "127.0.0.1" to the IP of the pixelserv as set by the "pixel" variable in both the MVPS host file and Yoyo list.
  • Delete the temporary files used to perform this operation.

Injecting the DNS conf file with our block lists


This is because if the additional "conf" files are missing at boot, the DNS service fails to come up and the router will not be able to grab the dynamic lists, leaving you in an infinite loop of WTF is going on here.

  • IF - Tests for these conditions: 1. "Does the dns-conf file missing the personal list?" 2. "Does the dns-conf file missing the Yoyo list?" 3. "Do the respective files exist?"
    True:
    • Add the file names to the DNSMasq configuration file
    False:
    • Note to syslog and continue to the next segment

Injecting the DNSmasq nvram options with our block lists

In order to reduce setup complexity for the user, i have made the script take the responsibility of injecting the configuration to the DNS service, when it sees that everything is ready and in place.
I have done this because there is a dual limitation that on one hand, if we put the domains lists in the DNSMasq configuration, before they are downloaded, the DNSMasq service will fail to load because it can not handle the missing files exception (for the .conf files, it doesn't care about hosts), and if that happens the router will never be able to get the lists because it won't be able to download them due to the missing resolve function. On the other hand we need these settings in place to achieve our ultimate goal of eliminating the ads.

To over come this, once the startup script knows that all the files are in place, It will insert the additional configurations into the NVRAM "DNSMasq options" for us.

  • "nvram get dnsmasq_options > /tmp/dns-options.tmp" - This command gets the content of the DNSMasq options that are already in place and stores them in a temporary file, so we will be able to concatenate our settings to the existing ones. For example, I have setup the PXE server option set as explained here , I wouldn't want to lose my PXE booting ability because of a "random" script, now would I?
  • IF - Test for these conditions: 1." Are the two dynamic lists missing from the DNS options?" 2. "Do the respective files exist?"
    True:
    • Note to syslog and append the lists to the DNSMasq options like we did in the firewall segment.
    • "change_nvram=1" - Set the variable to one(1) so that the script will know that we want to perform a commit to the changes in the appropriate segment below.
    False:
    • Note to syslog and continue to the next segment

Checking if the personal list is a file

As explained above, there are two ways of adding our own list of domains to the unapproved list. The first being to add it manually to the DNSMasq options in the web-GUI and the second being to create an additional configuration file that the DNSMasq will take into consideration. Because of this, the script needs to check if the file exists and NOT add it to the configuration if it doesn't. again, this is because if the DNSMasq configuration encounters a directive to a missing configuration file, it will fail to load and we will have a router that doesn't do DNS (not unlike the cleaning lady that doesn't do windows l0l).

  • IF - Test the following conditions: 1. "Does the already in use dnsmasq configuration file contain an entry for the personal list file?" 2."Does the current NVRAM configuration contain an entry for the personal list file?" 3. "Does the personal list file exist?"
  • True:
    • Note to syslog
    • "echo "conf-file=/jffs/personal-ads-list.conf" >> /tmp/dns-options.tmp" - Add the name of the file to the temporary dns-options file.
    • "change_nvram=1" - Set the variable to one(1) so that the script will know that we want to perform a commit to the changes in the appropriate segment below.
    False:
    • "[ ! -e /jffs/personal-ads-list.conf ] && logger" - A mini IF that will test if the personal list is NOT a file and only if its true will log a message indicating it.
    • "[ -n "`nvram get dnsmasq_options | grep "/jffs/personal-ads-list.conf"`" ] && logger" - A mini IF that will test if the NVRAM already contains the personal list file and only if its true will log a message indicating it.

Collective NVRAM changes to Commit

The NVRAM is a section of the flash chip on the router (the same one that holds the firmware) that is used to hold configurations so that they survive reboots.
This flash rom memory has a limited amount of write cycles before it dies, so the actual writes to it, should be performed very sparingly.
That is why the segments above did not immediately commit the changes, but noted that there are changes to be committed by this segment.

  • IF - Test for one condition: 1. "Is the "there were changes to NVRAM" variable (changed_nvram) equal to one(1)?"
    True:
    • Note to syslog
    • "nvram set dnsmasq_options="`cat /tmp/dns-options.tmp`"" - Dump the content of the dns-options.tmp file into NVRAM. This is done only here because it allows for the option that there is a personal list file to be added to the options before they are committed.
    • "nvram commit" - perform the write to NVRAM now that we know that it is necessary.
    False:
    • Just note to syslog that there was nothing to commit.
  • Delete the dns-options temporary file.

Refreshing DNS settings

Now that everything is in place, it is time to tell the DNS to take in the new configurations by restarting its control service. Thanks to the developers, using the control service causes the settings to be taken from NVRAM and regenerate the configuration file (its just too bad i didn't know this from the get go).

  • "stopservice dnsmasq && logger" - Stops the DNS service and if successfully executed log to syslog.
  • "startservice dnsmasq && logger" - Does the same only for starting it.

Blink the SES Leds

The SES LEDs are the orange and white lights behind the Cisco button on the router's front.
As this procedure can take anywhere from several seconds to several minutes (depending on your setup), blinking the LEDs visually informs us when the procedure has completed.

This is accomplished by invoking the "/sbin/gpio" command with the enable & disable parameters, wrapped in side a while loop.

Once the LEDs have been blinked you should see that the ads domain resolve to the pixel server IP.
End of the script


Thats' it... good luck and have a good one.


Subject Author Replies Views Last Message
best wireless router phanajan phanajan 0 3 Apr 9, 2014 by phanajan phanajan
Cron k8tek k8tek 9 567 Jan 24, 2011 by Hotfortech Hotfortech
Pixelserv syntax error kfuglsang kfuglsang 4 710 Jan 1, 2011 by Hotfortech Hotfortech
whitelist support? craftyguy craftyguy 1 463 Oct 10, 2010 by Hotfortech Hotfortech
pixelserv läuft nicht mit meinem Prozessor stephantest stephantest 3 416 Aug 18, 2010 by Hotfortech Hotfortech