|
| 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