Initial commit

This commit is contained in:
Geoffrey Frogeye 2019-11-10 18:14:25 +01:00
commit 80b23e2d5c
7 changed files with 222 additions and 0 deletions

.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@

54 Normal file
View file

@ -0,0 +1,54 @@
# eulaurarien
Generates a host list of first-party trackers for ad-blocking.
**DISCLAIMER:** I'm by no way an expert on this subject so my vocabulary or other stuff might be wrong. Use at your own risk.
## What's a first-party tracker?
Traditionally, websites load trackers scripts directly.
For example, `` and `` both load `` to track their users.
In order to block those, one can simply block the host ``.
However, to circumvent this easy block, tracker companies made the website using them load trackers from ``.
The latter being a DNS redirection to ``, directly pointing to a server serving the tracking script.
Those are the first-party trackers.
Blocking `` doesn't work any more, and blocking `*` isn't really possible since:
1. Most ad-blocker don't support wildcards
2. It's a DNS redirection, meaning that most ad-blockers will only see ``
So the only solution is to block every ``-like subdomains known, which is a lot.
That's where this scripts comes in, to generate a list of such subdomains.
## How does this script work
It takes an input a list of websites with trackers included.
So far, this list is manually-generated from the list of clients of such first-party trackers
(latter we should use a general list of websites to be more exhaustive).
It open each ones of those websites (just the homepage) in a web browser, and record the domains of the network requests the page makes.
It then find the DNS redirections of those domains, and compare with regexes of known tracking domains.
It finally outputs the matching ones.
## Requirements
Just to build the list, you can find an already-built list in the releases.
- Bash
- Python 3.4+
- Firefox
- Selenium
- seleniumwire
- dnspython
## Contributing
### Adding websites
Just add them to `websites.list`.
### Adding first-party trackers regex
Just add them to ``.

47 Executable file
View file

@ -0,0 +1,47 @@
#!/usr/bin/env python3
From a list of URLs, output the subdomains
accessed by the websites.
import sys
import typing
import urllib.parse
import selenium.webdriver.firefox.options
import seleniumwire.webdriver
def subdomain_from_url(url: str) -> str:
Extract the domain part from an url.
parsed = urllib.parse.urlparse(url)
return parsed.netloc
def collect_subdomains(url: str) -> typing.Iterable[str]:
Load an URL into an headless browser and return all the domains
it tried to access.
options = selenium.webdriver.firefox.options.Options()
driver = seleniumwire.webdriver.Firefox(
executable_path='geckodriver', options=options)
for request in driver.requests:
if request.response:
yield subdomain_from_url(request.path)
if __name__ == '__main__':
for line in sys.stdin:
line = line.strip()
if not line:
for subdomain in collect_subdomains(line):

22 Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Main script for eulaurarien
# Get all subdomains accessed by each website in the website list
cat websites.list | ./ > subdomains.list
sort -u subdomains.list > subdomains.sorted.list
# Filter out the subdomains not pointing to a first-party tracker
cat subdomains.sorted.list | ./ > toblock.list
sort -u toblock.list > toblock.sorted.list
# Format the blocklist so it can be used as a hostlist
echo "# First party trackers"
echo "# List generated on $(date -Isec) by eulaurarian $(git describe --tags --dirty)"
cat toblock.sorted.list | while read host;
echo " $host"
) > toblock.hosts.list

35 Executable file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env python3
From a list of subdomains, output only
the ones resolving to a first-party tracker.
import re
import sys
import dns.resolver
import regexes
def is_subdomain_matching(subdomain: str) -> bool:
Indicates if the subdomain redirects to a first-party tracker.
# TODO Look at the whole chain rather than the last one
query = dns.resolver.query(subdomain, 'A')
canonical = query.canonical_name.to_text()
for regex in regexes.REGEXES:
if re.match(regex, canonical):
return True
return False
if __name__ == '__main__':
for line in sys.stdin:
line = line.strip()
if not line:
if is_subdomain_matching(line):

9 Normal file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env python3
List of regex matching first-party trackers.

websites.list Normal file
View file

@ -0,0 +1,52 @@