rfw 0.2.2
Remote firewall as a web service. REST API for iptables.
License: MIT
Keywords: rfw remote firewall iptables REST web service drop accept ban allow whitelist fail2ban

rfw - remote firewall
=====================

**Remote firewall with REST API.**
 
``rfw`` is the RESTful server which applies iptables rules to block or allow IP addresses on request from a remote client. ``rfw`` maintains the list of blocked IP addresses which may be updated on the fly from many sources. ``rfw`` also solves the problem of concurrent modifications to iptables since the requests are serialized.

Typical use cases
-----------------

1. You manage a group of machines which are deployed/controlled/monitored from a central server or admin panel. You need to react quickly/automatically to abuse/DDOS with the rules generated by the intelligence/analytics/geolocation-aware server. You push the IP blocklist updates to other machines in real time.

2. You build the Peer-to-Peer network of servers or Distributed Autonomous Organization (see Ethereum). The DAO, apart from running contracts on Ethereum, may need to run a P2P network. The servers cannot rely on the centralized firewall. With rfw the peer servers can share info about botnet IP sets and current sources of abuse to more efficiently protect against DDOS and other attacks.

See the `tutorial with example <http://www.securitykiss.com/resources/tutorials/rfw_project/>`__

Features
--------

- block/allow IP addresses with iptables on request from remote host
- handle individual IP or CIDR ranges (xx.xx.xx.xx/mask)
- apply action permanently or with expiry timeout
- keep IP/range whitelist - actions related to whitelisted IPs are ignored what prevents locking out the legitmate clients
- serialize requests to prevent concurrency issues with iptables
- REST API
- secured with SSL
- authenticated with basic authentication over SSL and by client IP address
- idempotent - actions resulting in duplicate entries are ignored
- do not interfere with more general iptables rules

Examples:
---------

+------------------------------------------------+-----------------------------------------------------------------------------------------+
| rfw REST API                                   | iptables command                                                                        |
+================================================+=========================================================================================+
|                                                | Block incoming packets from 11.22.33.44 on eth0. In other words:                        |
|                                                | Insert the DROP rule on INPUT chain to drop packets with source IP 11.22.33.44          |
|                                                | on network interface eth0. Translates to the command::                                  | 
|                                                |                                                                                         |
| PUT /drop/input/eth0/11.22.33.44               |     iptables -I INPUT -i eth0 -s 11.22.33.44 -j DROP                                    |
|                                                |                                                                                         |
+------------------------------------------------+-----------------------------------------------------------------------------------------+
|                                                | Delete the above rule. Translates to::                                                  |
|                                                |                                                                                         |
| DELETE /drop/input/eth0/11.22.33.44            |     iptables -D INPUT -i eth0 -s 11.22.33.44 -j DROP                                    |
+------------------------------------------------+-----------------------------------------------------------------------------------------+
| PUT /accept/output/any/192.168.0.0/24          | Allow outgoing traffic to 192.168.0.0/24 subnet on any interface. Translates to::       |
|                                                |                                                                                         |
|                                                |     iptables -I OUTPUT -d 192.168.0.0/24 -j ACCEPT                                      |
+------------------------------------------------+-----------------------------------------------------------------------------------------+
| PUT /accept/forward/ppp/1.2.3.0/24/eth0/5.5.5.5| Allow forwarding packets with source address in subnet 1.2.3.0/24                       |
|                                                | and destination address 5.5.5.5 from any ppp interface to eth0. Translates to::         |
|                                                |                                                                                         |
|                                                |     iptables -I FORWARD -i ppp+ -o eth0                                                 |
|                                                |     -s 1.2.3.0/24 -d 5.5.5.5 -j ACCEPT                                                  |
+------------------------------------------------+-----------------------------------------------------------------------------------------+
|                                                | Block incoming packets from 11.22.33.44 on any interface for 10 minutes::               |
|                                                |                                                                                         |
| PUT /drop/input/any/11.22.33.44/?expire=600    |     iptables -I INPUT -s 11.22.33.44 -j DROP                                            |
+------------------------------------------------+-----------------------------------------------------------------------------------------+
|                                                | Return the list of existing rules in JSON format. Sample output::                       |
|                                                |                                                                                         |
| GET /list/input                                |    [{"chain": "INPUT", "num": "1", "pkts": "0",                                         |
|                                                |      "bytes": "0", "target": "DROP", "prot": "all",                                     |
|                                                |      "opt": "--", "inp": "*", "out": "*",                                               |
|                                                |      "source": "22.22.22.0/24",                                                         |
|                                                |      "destination": "0.0.0.0/0", "extra": ""},                                          |
|                                                |     {"chain": "INPUT", "num": "2", "pkts": "0",                                         |
|                                                |      "bytes": "0", "target": "DROP", "prot": "all",                                     |
|                                                |      "opt": "--", "inp": "*", "out": "*",                                               |
|                                                |      "source": "11.22.33.44",                                                           |
|                                                |      "destination": "0.0.0.0/0", "extra": ""}]                                          |
|                                                |                                                                                         |
+------------------------------------------------+-----------------------------------------------------------------------------------------+



Deployment
----------

Requires Python 2.7

Install from PyPI::

    pip install rfw

or from tarball::

    tar xf rfw-X.X.X.tar.gz
    cd rfw-X.X.X
    ./setup.py install


Generate keys and certificates with config/deploy/rfwgen::

    ./rfwgen <server_ip>

See `rfwgen README <https://github.com/securitykiss-com/rfw/blob/master/config/deploy/README.rst>`__ for more details.


Fill blanks in configuration file /etc/rfw/rfw.conf and /etc/rfw/white.list.


Run in verbose mode with default config file::

    rfw -v

Test with curl::

    curl -v --cacert config/deploy/client/ca.crt --user myuser:mypasswd -XPUT https://<server_ip>:7393/drop/input/eth0/1.2.3.4

or when testing on localhost you can skip certificate verification::

    curl -v --insecure --user myuser:mypasswd -XPUT https://127.0.0.1:7393/drop/input/eth0/1.2.3.4

or when ``local.server`` enabled there is no authentication::

    curl -v -XPUT http://localhost:7390/drop/input/eth0/1.2.3.4

Run rfw without installing
--------------------------

You still need to be root. Unzip tarball, cd to project folder::

    sudo bin/rfw -f config/rfw.conf --logfile=rfw.log


FAQ
---

**Q: Why not use chef/puppet/ansible/salt/fabric/ssh for remote management instead?**

| For a couple of reasons:

- Security, trust and permission management. The above tools require giving a remote client the ssh root acces. Often we want to allow the IP analytics server to be able to block selected IPs without giving admin rights. 
- Performance 
- Handle frequent and concurrent requests 
- No dependencies and easy to talk to from any platform and language via REST API
- Protection against locking yourself out by applying wrong rule

Note that when the rules come from variuos sources they may interact badly. For firewalls the order of rules matters. That's why the functionality of remote rfw is limited to blocking individual IPs inserted in front of the ruleset. 

**Q: rfw limits REST client access by IP whitelisting. What if I need to connect from dynamic IP?**

rfw is intended for hosts with static IP addresses. It includes both servers and clients. For clients it is not as strong requirement as it seems since in typical rfw deployment the client is a data center collocated machine with static IP. If you really need to use REST client from various locations or from dynamic IP, you have a couple of options:

-  If you have any server with static IP with SSH access use it as a gateway client to rfw.
-  If you have dynamic IP from particular address pool assigned to your Internet Service Provider you may whitelist the entire address range.
-  You can connect through VPN with static IP and whitelist that IP.

**Q: Is it secure?**

Tampering with the core firewall should never be taken lightly. rfw must be run with root privileges in order to modify iptables so it requires a lot of trust in the software. Sometimes there is no choice and you have to automate firewall actions across individual boxes anyway. Then rfw makes it more secure because the remote client does not need to have full access to the host and can only block/allow IP addresses using rfw API. While rfw is designed with distributed system in mind, it may also improve security even for a single box by: 

- limiting iptables functionality to only simple rules
- whitelisting selected IP addresses to prevent lock out 
- serializing iptables modifications

Security of rfw was the primary concern from the very beginning and influenced these design decisions: 

- simplicity 
- no fancy features 
- no external dependencies except iptables 
- limited functionality 
- no generic rules 
- not performance-optimal but conservative choice of time-proven crypto: 2048-bit RSA based SSL with HTTP Basic Authentication


License
-------

Copyrite (c) 2014 `SecurityKISS Ltd <http://www.securitykiss.com>`__,
released under the `MIT License <https://github.com/securitykiss-com/rfw/blob/master/LICENSE.txt>`__

| Yes, Mr patent attorney, you have nothing to do here. Find a decent job instead.
| Fight intellectual "property".

CHANGES
---------------------------------

v0.0.1,  2014-03-05 -- Initial release.

v0.1.2,  2014-03-25 -- Deployment ready.

v0.1.19, 2014-03-26 -- Multiple fixes: non-restful mode, README, PUT/DELETE actions, error handling

v0.2.2,  2014-04-08 -- Fixes: umask, remove install warnings. Docs: link to the tutorial