Skip to content
This repository was archived by the owner on Sep 17, 2019. It is now read-only.

Commit 438a474

Browse files
committed
Releasing sources on GitHub
Signed-off-by: Sébastien Mériot <[email protected]>
0 parents  commit 438a474

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+7195
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*.pyc
2+
.*.sw*
3+
doc/build
4+
doc/.*
5+
.coverage

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Changelog
2+
3+
## 1.0.0 (2016-02-08)
4+
- Publishing sources on GitHub.

CONTRIBUTING.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
Every contribution are welcomed as long as few rules are followed.
2+
3+
# TL;DR
4+
5+
- Branch off `devel`.
6+
- Only one feature per commit.
7+
- In case of changes request, amend your commit to avoid multiple commits.
8+
- Run `make lint` before and after coding and take care not to lower the rating.
9+
- Write unit tests as much as possible so we can easily check your code.
10+
- Run unit tests using `make test` before commiting.
11+
12+
# How to contribute
13+
14+
- If you're thinking about a new feature, see if there's already an issue open
15+
about it or please open one otherwise.
16+
- One commit per feature.
17+
- Branch off the `devel` branch.
18+
- Test your code with unit tests and use `make test` to run them all.
19+
- Run `make lint` before and after coding and take care not to lower the rating.
20+
It worth mentioning you can freely improve the rating !
21+
- If we ask for a few changes, please amend your commit rather than creting new
22+
commits.
23+
- Remember to be `Python 2.7` compliant.
24+
25+
# How to start coding ?
26+
27+
First thing to do is to install dev requirements by running `make install-dev-deps`.
28+
Everything you need to start coding should be setup.
29+
To be sure everything went ok, run unit tests using command `make test`.
30+
31+
If needed, edit the `config/settings.py` so you can change logger level to
32+
debug (`LOGGER['level']` and `API['debug']` properties).
33+
34+
# Branches
35+
36+
- `master` still contains a stable version of the code. Releases are tagged
37+
from this branch.
38+
- `devel` contains all changes in the current development version. Don't use
39+
this code in production since it might break it.
40+
41+
# Licensing for new files
42+
43+
`ip-reputation-monitoring` is licensed under GNU GPL v3 license. Anything
44+
contributed to `ip-reputation-monitoring` must be released under this license.
45+
46+
When introducing a new file into the project, please make sur it has a
47+
copyright header making clear under which licenses it's being released.

LICENSE

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

Makefile

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
CD=cd
2+
FIND=find
3+
DEL=rm
4+
PYTHON=python
5+
PIP=pip
6+
COVERAGE=coverage
7+
PYLINT=pylint
8+
SPHINX=sphinx-build
9+
10+
MODULE_DIR=reputation
11+
DOC_DIR=doc/build
12+
13+
clean: clean-doc
14+
$(FIND) . -name *.pyc | xargs $(DEL)
15+
16+
clean-doc:
17+
$(DEL) -rf $(DOC_DIR)
18+
19+
install-deps:
20+
$(PIP) install -r requirements.txt
21+
22+
install-dev-deps:
23+
$(PIP) install -r requirements/dev.txt
24+
25+
test:
26+
cd $(MODULE_DIR) && \
27+
$(COVERAGE) > /dev/null 2>&1 && \
28+
$(COVERAGE) run --source='.' -m unittest discover && \
29+
$(COVERAGE) report \
30+
|| \
31+
$(PYTHON) -m unittest discover
32+
33+
lint:
34+
cd $(MODULE_DIR) && \
35+
$(PYLINT) --disable=W0141 --max-line-length=150 adapters/ api/ archive/ config/ default/ factory/ main.py mongo/ parsing/ reporting/ run_api.py tests/ spamhaus_monitor.py tools/ utils/
36+
37+
doc: clean-doc
38+
$(SPHINX) -b html doc/source doc/build

README.md

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
# ip-reputation-monitoring #
2+
3+
## Summary ##
4+
5+
This tool aims to monitor the reputation of a network in order
6+
to easily detect blacklisted IPs or IPs sending suspicious e-mails.
7+
Every day an e-mail is sent telling you the 10th IPs having the
8+
worst reputation among the network.
9+
10+
The monitoring is based over both RBL and FBL as described below.
11+
12+
An API is provided in order to query the reputation of a single
13+
IP using RBL and FBL aggregation. The API also offers an endpoint
14+
that checks DNS black list.
15+
16+
### RBL ###
17+
18+
A Realtime Blackhole List is composed of IP addresses considered as
19+
spammers. Several organizations are maintaining such list and this tool
20+
supports some of them: Microsoft SNDS, BlockList, CleanTalk, StopForumSpam.
21+
22+
Generally, those lists are released under CSV format. Unfortunately,
23+
CleanTalk does only release this list in HTML, so a HTML to CSV
24+
parser has been written to do so.
25+
26+
### FBL ###
27+
28+
A feedback loop is a realtime feedback about mails sent from observed
29+
network. Those mails can be sent by e-mail hosting providers or by
30+
foundations fighting against spams in order to give a feedback about
31+
suspicious mails issued from the network.
32+
The tool supports Abuse Reporting Format (ARF) which is a standard
33+
to report suspicious mails used by AOL and SignalSpam feebacks.
34+
35+
SpamCop feebacks are also supported by the tool, even if their mails
36+
do not follows ARF guidelines.
37+
38+
### DNS BL ###
39+
40+
The DNS-based blackhole list is a subset of RBL and, instead of being a
41+
CSV file containing an IP list, is a software mechanism allowing anyone
42+
to query the database using the DNS protocol whether an IP is blacklist.
43+
44+
Supported DNS BL are the following:
45+
- Abuse combined
46+
- Abuseat
47+
- Msrbl
48+
- Sorbs
49+
- Spamhaus ZEN
50+
- SpamCop
51+
- UCE Protect
52+
- Wpbl
53+
54+
### Spamhaus BL ###
55+
56+
Spamhaus is an organization tracking spam over Internet. Their website
57+
provides an easy way to keep an eye over active issues on a network giving
58+
the domain responsible of an IP set.
59+
60+
This tool provides a script able to parse the issues raised by Spamhaus to
61+
track network reputation.
62+
63+
## Installation ##
64+
65+
### Requirements ###
66+
67+
To setup this little tool, you'll need:
68+
69+
* A Linux environment (it might work under Windows but you'll need to rewrite
70+
shell scripts)
71+
* Python 2.7+
72+
* Packages `python-dev` and `python-pip`
73+
* A MongoDB database (2.6.x or greater with TLS support*)
74+
* A MX supporting IMAPS
75+
* A scheduler (cron, supervisor, ...)
76+
77+
*TLS support can be disabled by editing `settings/config.py`.
78+
79+
### Step by step ###
80+
81+
When all of these requirements are met, you can install the tool:
82+
83+
1. Download the zipfile or checkout the sources.
84+
2. Install python dependencies (apt-get install python-dev python-pip)
85+
3. Run `make install-deps`.
86+
87+
88+
## Configuration ##
89+
90+
### General settings ###
91+
92+
For security purpose, most of setting values must be defined as VARENV.
93+
So, to configure the tool, you just have to export following environment
94+
variables:
95+
96+
* `AS_NUMBER`: your AS number, i.e.: OVH one is 16276
97+
* `EMAIL_HOST`: ip or domain of your MX
98+
* `FBL_USER`: username used to poll incoming e-mails
99+
* `FBL_PASSWORD`: password for previous username
100+
* `FBL_PARTNER_HEADER`: Name of the header defining e-mail source (see next
101+
section)
102+
* `MONGO_HOST`: ip or domain of your MongoDB host
103+
* `MONGO_PORT`: port to reach MongoDB
104+
* `MONGO_DB`: name of the MongoDB database
105+
* `MONGO_USER`: MongoDB user
106+
* `MONGO_PASSWORD`: MongoDB password
107+
* `REPORTING_TARGET`: e-mail address where a daily report about ips with the
108+
worst reputation must be sent
109+
* `REPORTING_SENDER`: `From:` header value of the dail report e-mail
110+
* `SNDS_KEY`: your personal SNDS key
111+
* `SPAMHAUS_DOMAIN_NAME`: the domain your IPs are attached to, i.e.: OVH one
112+
is `ovh.net`
113+
114+
### Tagging incoming e-mails ###
115+
116+
As you can see, a required varenv is called `FBL_PARTNER_HEADER`.
117+
Since everybody is able to send an email pretending being Microsoft SNDS,
118+
NSA or whatever, it's important to check the identity of the mail send with
119+
a well-kept secret. The easier way to do so is to assign a single e-mail
120+
address per organization you keep secret.
121+
122+
Using the MX features, the mail must be validated and tagged with the previous
123+
`FBL_PARTNER_HEADER` header. We recommend to keep this header name secret too.
124+
The value of this header is the name of the FBL. (currently supported values:
125+
AOL, SignalSpam, SpamCop)
126+
127+
An example should help you to understand:
128+
129+
OVH wants to received spam report from AOL.
130+
131+
OVH creates a new e-mail address for AOL: [email protected].
132+
AOL uses it to send all spam report.
133+
OVH adds a new rule attached to this address: when receiving a new e-mail
134+
from <[email protected]>, add header "X-PARTNER-HEADER: AOL" and forward this
135+
e-mail to the FBL_USER varenv mailbox.
136+
137+
The monitoring tool is polling MX the FBL_USER varenv mailbox on EMAIL_HOST
138+
server and its "FBL_PARTNER_HEADER" has been set to "X-PARTNER-HEADER`.
139+
140+
141+
### Network IPs ###
142+
143+
At last, you need add your network addresses CIDRs (only one per line) in the
144+
`config/ips.list` file.
145+
146+
### Implementing its own RBL storage class ###
147+
148+
As you can see in the `config.py`, there is a way to customize the tool by
149+
providing its own implementation to store RBL parsed documents.
150+
By default, a basic implementation is provided and store everything on
151+
the filesystem, using the property `RBL_STORAGE_CONTEXT` to determine the
152+
root path to use.
153+
154+
You can code your own RBL storage service by implementing
155+
`adapters.service.storage.StorageServiceBase` and then, tell the tool to
156+
use this implementation by editing the property `CUSTOM_IMPLEMENTATIONS`.
157+
158+
### Implementing new parsers ###
159+
160+
Implementing new parsers is painless and you'll only have to implement an
161+
interface. If your parser is valid enough, it should be automatically
162+
registered and enabled as long as daemons are restarted.
163+
164+
**1. Implementing a new CSV parser**
165+
166+
For a brand new CSV parser, you'll need to implement
167+
`parser.csv.csvparser.CSVParser`. Here are the explanations of methods that
168+
must be implemented:
169+
170+
# -*- encoding: utf-8 -*-
171+
172+
from datetime import datetime
173+
from parser.csv.csvparser import CSVParser
174+
175+
class MyNewParser(CSVParser):
176+
177+
def __init__(self, path):
178+
# Consider the delimiter is a comma.
179+
CSVParser.__init__(self, path, ',')
180+
181+
def compute_weight(self, data):
182+
# The weight of this entry. All the weights are then summed to rank IPs.
183+
# Notice data is an array containing the splitted line.
184+
return 1
185+
186+
def get_date(self, data):
187+
# Date to use for this entry
188+
return datetime.now()
189+
190+
def get_source(self, data):
191+
# Source name
192+
return 'My new parser'
193+
194+
def get_ip(self, data):
195+
# IP the entry is talking about
196+
return data[0]
197+
198+
def get_description():
199+
# Mandatory method to be automatically registered !
200+
return {
201+
'name': 'My new parser',
202+
'shortened': 'MNP' # Shortened name, optionnal
203+
}
204+
205+
get_description # staticmethod(get_description)
206+
207+
**2. Implementing a new mail reader**
208+
209+
Unlike CSV parsers, mail reader are not automatically registered.
210+
That's why if you only want to add a new provider using ARF,
211+
you'll have to edit `parsing.mails.mailfactory.MailReaderFactory` and add the
212+
new source name. (This code can be greatly improved, your PR are welcomed !)
213+
214+
For a brand new mail reader, you'll need to edit this file too to add your
215+
source. And, you'll have to implement an abstract class to be able to read
216+
mails. Here is the default format:
217+
218+
# -*- encoding: utf-8 -*-
219+
220+
from datetime import datetime
221+
from parsing.mails.mailreader import AbstractMailReader
222+
223+
class MyNewReader(MailReader):
224+
225+
def __init__(self, raw):
226+
AbstractMailReader.__init__(self)
227+
# Raw is the received e-mail.
228+
self._data # raw
229+
230+
def compute_weight(self):
231+
# The weight of this entry. All the weights are then summed to rank IPs.
232+
return 1
233+
234+
def get_date(self):
235+
# Date to use for this entry.
236+
return datetime.now()
237+
238+
def get_source(self):
239+
# Source name
240+
return 'My new mail reader'
241+
242+
def get_ip(self):
243+
# IP the mail is talking about
244+
return "1.2.3.4"
245+
246+
### Extending DNS BL support ###
247+
248+
If you want to add new DNS BL that are not supported by default, you just have
249+
to edit the file `config/dnsbl.py` and add a new dictionnary providing needed
250+
information about the DNS BL.
251+
252+
Note that the shortened name is mandatory.
253+
254+
255+
## Running ##
256+
257+
You can now insert theses entries in your favorite scheduler:
258+
259+
* Schedule `reputation-rbl.sh` to be run once a day.
260+
* Schedule `spamhaus-bl.sh` to be run every hour.
261+
* Schedule `reputation-fbl.sh` and `api.sh` to be run as a daemon.
262+
263+
## API ##
264+
265+
Once everything is running, you can start using the API. By default, it's
266+
listening to the port 5000.
267+
Here are the few available endpoints:
268+
269+
* `GET /reputation/(ip)`: Query reputation of an IP for each registered source.
270+
* `GET /reputation/(ip)/details/(source)`: Query the detailed reputation of an
271+
IP for a given source. You must use the shortened name of the source (or its
272+
name if no shortened one has been provided). Default available source: AOL,
273+
BLCK, CTALK SCOP SFS, SGS, SNDS.
274+
* `GET /blacklist/(ip)`: Query DNS BL to know whether this IP is black listed
275+
or not.
276+
* `GET /spamhaus/active`: Query recorded Spamhaus active issues.
277+
* `GET /spamhaus/resolved`: Query recorded Spamhaus resolved issues.
278+
279+
280+
281+
Enjoy

0 commit comments

Comments
 (0)