Permalink
Browse files

Merge branch 'dev'

  • Loading branch information...
Andrew Moffat
Andrew Moffat committed May 16, 2012
2 parents 0bbeaf3 + 86c8a89 commit a30d78e20dd699bd87ceb86dca532b6c4621a364
Showing with 42 additions and 15 deletions.
  1. +24 −10 README.md
  2. +18 −5 focus.py
View
@@ -1,7 +1,10 @@
-Focus.py is a simple DNS-based firewall for Linux that helps you stop
-procrastinating. Just give it a list of sites you spend too much time on and
-enjoy not being to access them (easily :)
+Focus.py helps you keep focused by applying schedulable firewall rules
+to distracting websites. An example firewall rule looks like this:
+``` python
+def domain_reddit_com(dt):
+ return dt.hour == 21 # allow from 9-10pm
+```
Starting
========
@@ -16,14 +19,14 @@ Now start Focus:
sudo python focus.py &
-Blocking Domains
-================
+Filtering Domains
+=================
Firewall rules involving schedules and timeframes can get complicated fast.
For this reason, the scheduling specification is pure Python, so you can make
-your blacklist schedules as simple or as complex as you want.
+your filtering rules as simple or as complex as you want.
-The default scheduler is created on first startup in `/etc/focus_blacklist.py`:
+The default filter rules is created on first startup in `/etc/focus_blacklist.py`:
```python
import re
@@ -33,7 +36,7 @@ def domain_ycombinator_com(dt):
return False
def domain_reddit_com(dt):
- # return dt.hour in (12, 21, 22) # at noon, or from 9-10pm
+ # return dt.hour in (12, 21) # at noon-1pm, or from 9-10pm
return False
def domain_facebook_com(dt):
@@ -49,7 +52,7 @@ want to block, preceeded by "domain_". Have it take a single datetime object
and have it return True or False. In the body, you can write whatever logic
makes the most sense for
you. Maybe you want to write your own Pomodoro routine, or maybe you want to
-scrape your google calendar for exam dates.
+scrape your google calendar for exam dates, and block certain websites on those dates.
For sites without their own scheduler function, the default() function is called.
@@ -63,6 +66,17 @@ Focus.py tries to start with a sensible configuration, but if you need to change
it, edit `/etc/focus.json.conf`
+How it works
+============
+
+Focus.py is, at its core, a DNS server. By making it your primary nameserver,
+it receives all DNS lookup requests. Based on the domain name being requested,
+it either responds with a "fail ip" address (blocked), or passes the request
+on to your other nameservers (not blocked). In both cases, Focus adjusts the TTL of each
+DNS response so that the service requesting the DNS lookup will do minimal
+caching on the IP, allowing Focus's filtering rules to be more immediate.
+
+
FAQ
===
@@ -74,4 +88,4 @@ FAQ
- Q: How do I stop Focus?
- A: You'll need to find the process id. Try `sudo netstat --inet -anpu | grep :53`.
-After you identify the process listening on port 53, run `sudo kill -9` with the process id.
+After you identify the process listening on port 53, run `sudo kill -9` with the process id.
View
@@ -34,7 +34,8 @@
import sys
import select
from imp import reload
-
+import atexit
+from optparse import OptionParser
IS_PY3 = sys.version_info[0] == 3
@@ -63,6 +64,7 @@
resolv_conf = "/etc/resolv.conf"
config_file = "/etc/focus.json.conf"
blacklist_file = "/etc/focus_blacklist.py"
+pid_file = "/var/run/focus.py.pid"
_default_config = {
"bind_ip": "127.0.0.1",
"fail_ip": "127.0.0.1",
@@ -80,7 +82,7 @@ def domain_news_ycombinator_com(dt):
return False
def domain_reddit_com(dt):
- # return dt.hour in (12, 21, 22) # at noon, or from 9-10pm
+ # return dt.hour in (12, 21) # at noon-1pm, or from 9-10pm
return False
def domain_facebook_com(dt):
@@ -323,15 +325,26 @@ def adjust_ttl_in_reply(self, reply, ttl):
return reply
+def clean_up_pid():
+ if exists(pid_file):
+ logging.info("cleaning up pid file")
+ os.remove(pid_file)
if __name__ == "__main__":
+ cli_parser = OptionParser()
+ cli_parser.add_option("-l", "--log", dest="log", default=None)
+ cli_options, cli_args = cli_parser.parse_args()
+
logging.basicConfig(
format="(%(process)d) %(asctime)s - %(name)s - %(levelname)s - %(message)s",
- level=logging.INFO
+ level=logging.INFO,
+ filename=cli_options.log
)
log = logging.getLogger("server")
-
+
+ with open(pid_file, "w") as f: f.write(str(os.getpid()))
+ atexit.register(clean_up_pid)
config.update(load_config())
nameservers = load_nameservers(resolv_conf)
@@ -422,4 +435,4 @@ def adjust_ttl_in_reply(self, reply, ttl):
last_cleaned_readers = now
- server.close()
+ server.close()

0 comments on commit a30d78e

Please sign in to comment.