Skip to content

Commit ebe4332

Browse files
author
ldx
committed
Generate README.md from RST docs.
1 parent add95fc commit ebe4332

File tree

1 file changed

+298
-3
lines changed

1 file changed

+298
-3
lines changed

README.md

Lines changed: 298 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,300 @@
1-
[![Build Status](https://travis-ci.org/ldx/python-iptables.png?branch=master)](https://travis-ci.org/ldx/python-iptables)
1+
Introduction
2+
============
23

3-
Python-iptables is a pythonesque wrapper around the Linux iptables/ip6tables facility. It is meant primarily for dynamic and/or complex firewalls, where rules are often updated or changed. Python-iptables makes it possible to use Python to parse or change rules without the need to spawn processes to execute an iptables command.
4+
About python-iptables
5+
---------------------
46

5-
See [http://ldx.github.com/python-iptables/](http://ldx.github.com/python-iptables/) for documentation.
7+
**Iptables** is the tool that is used to manage **netfilter**, the
8+
standard packet filtering and manipulation framework under Linux. As the
9+
iptables manpage puts it:
10+
11+
> Iptables is used to set up, maintain, and inspect the tables of IPv4
12+
> packet filter rules in the Linux kernel. Several different tables may
13+
> be defined.
14+
>
15+
> Each table contains a number of built-in chains and may also contain
16+
> user- defined chains.
17+
>
18+
> Each chain is a list of rules which can match a set of packets. Each
19+
> rule specifies what to do with a packet that matches. This is called a
20+
> target, which may be a jump to a user-defined chain in the same table.
21+
22+
`Python-iptables` provides a pythonesque wrapper via python bindings to
23+
iptables under Linux. Interoperability with iptables is achieved via
24+
using the iptables C libraries (`libiptc`, `libxtables`, and the
25+
iptables extensions), not calling the iptables binary and parsing its
26+
output. It is meant primarily for dynamic and/or complex routers and
27+
firewalls, where rules are often updated or changed, or Python programs
28+
wish to interface with the Linux iptables framework..
29+
30+
![buildstatus](https://travis-ci.org/ldx/python-iptables.png?branch=master)
31+
32+
Compiling and installing
33+
------------------------
34+
35+
First make sure you have iptables installed (most Linux distributions
36+
install it by default). `Python-iptables` needs the shared libraries
37+
`libiptc.so` and `libxtables.so` coming with iptables, they are
38+
installed in `/lib` on Ubuntu.
39+
40+
You can compile `python-iptables` in the usual distutils way:
41+
42+
% cd python-iptables
43+
% python setup.py build
44+
45+
If you like, `python-iptables` can also be installed into a
46+
`virtualenv`:
47+
48+
% mkvirtualenv python-iptables
49+
% python setup.py install
50+
51+
If you install `python-iptables` as a system package, make sure the
52+
directory where `distutils` installs shared libraries is in the dynamic
53+
linker's search path (it's in `/etc/ld.so.conf` or in one of the files
54+
in the folder `/etc/ld.co.conf.d`). Under Ubuntu `distutils` by default
55+
installs into `/usr/local/lib`.
56+
57+
Now you can run the tests:
58+
59+
% sudo PATH=$PATH ./test.py
60+
WARNING: this test will manipulate iptables rules.
61+
Don't do this on a production machine.
62+
Would you like to continue? y/n y
63+
[...]
64+
65+
The `PATH=$PATH` part is necessary after `sudo` if you have installed
66+
into a `virtualenv`, since `sudo` will reset your environment to a
67+
system setting otherwise..
68+
69+
Once everything is in place you can fire up python to check whether the
70+
package can be imported:
71+
72+
% sudo PATH=$PATH python
73+
>>> import iptc
74+
>>>
75+
76+
Of course you need to be root to be able to use iptables.
77+
78+
What is supported
79+
-----------------
80+
81+
The basic iptables framework and all the match/target extensions are
82+
supported by `python-iptables`, including IPv4 and IPv6 ones. All IPv4
83+
and IPv6 tables are supported as well.
84+
85+
Full documentation with API reference is available
86+
[here](http://ldx.github.com/python-iptables/).
87+
88+
Examples
89+
========
90+
91+
Rules
92+
-----
93+
94+
In `python-iptables`, you usually first create a rule, and set any
95+
source/destination address, in/out interface and protocol specifiers,
96+
for example:
97+
98+
>>> import iptc
99+
>>> rule = iptc.Rule()
100+
>>> rule.in_interface = "eth0"
101+
>>> rule.src = "192.168.1.0/255.255.255.0"
102+
>>> rule.protocol = "tcp"
103+
104+
This creates a rule that will match TCP packets coming in on eth0, with
105+
a source IP address of 192.168.1.0/255.255.255.0.
106+
107+
A rule may contain matches and a target. A match is like a filter
108+
matching certain packet attributes, while a target tells what to do with
109+
the packet (drop it, accept it, transform it somehow, etc). One can
110+
create a match or target via a Rule:
111+
112+
>>> rule = iptc.Rule()
113+
>>> m = rule.create_match("tcp")
114+
>>> t = rule.create_target("DROP")
115+
116+
Match and target parameters can be changed after creating them. It is
117+
also perfectly valid to create a match or target via instantiating them
118+
with their constructor, but you still need a rule and you have to add
119+
the matches and the target to their rule manually:
120+
121+
>>> rule = iptc.Rule()
122+
>>> match = iptc.Match(rule, "tcp")
123+
>>> target = iptc.Target(rule, "DROP")
124+
>>> rule.add_match(match)
125+
>>> rule.target = target
126+
127+
Any parameters a match or target might take can be set via the
128+
attributes of the object. To set the destination port for a TCP match:
129+
130+
>>> rule = iptc.Rule()
131+
>>> rule.protocol = "tcp"
132+
>>> match = rule.create_match("tcp")
133+
>>> match.dport = "80"
134+
135+
To set up a rule that matches packets marked with 0xff:
136+
137+
>>> rule = iptc.Rule()
138+
>>> rule.protocol = "tcp"
139+
>>> match = rule.create_match("mark")
140+
>>> match.mark = "0xff"
141+
142+
Parameters are always strings.
143+
144+
When you are ready constructing your rule, add them to the chain you
145+
want it to show up in:
146+
147+
>>> chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), "INPUT")
148+
>>> chain.insert_rule(rule)
149+
150+
This will put your rule into the INPUT chain in the filter table.
151+
152+
Chains and tables
153+
-----------------
154+
155+
You can of course also check what a rule's source/destination address,
156+
in/out inteface etc is. To print out all rules in the FILTER table:
157+
158+
>>> import iptc
159+
>>> table = iptc.Table(iptc.Table.FILTER)
160+
>>> for chain in table.chains:
161+
>>> print "======================="
162+
>>> print "Chain ", chain.name
163+
>>> for rule in chain.rules:
164+
>>> print "Rule", "proto:", rule.protocol, "src:", rule.src, "dst:", \
165+
>>> rule.dst, "in:", rule.in_interface, "out:", rule.out_interface,
166+
>>> print "Matches:",
167+
>>> for match in rule.matches:
168+
>>> print match.name,
169+
>>> print "Target:",
170+
>>> print rule.target.name
171+
>>> print "======================="
172+
173+
As you see in the code snippet above, rules are organized into chains,
174+
and chains are in tables. You have a fixed set of tables; for IPv4:
175+
176+
- FILTER,
177+
- NAT,
178+
- MANGLE and
179+
- RAW.
180+
181+
For IPv6 the tables are:
182+
183+
- FILTER,
184+
- MANGLE,
185+
- RAW and
186+
- SECURITY.
187+
188+
To access a table:
189+
190+
>>> import iptc
191+
>>> table = iptc.Table(iptc.Table.FILTER)
192+
>>> print table.name
193+
filter
194+
195+
To create a new chain in the FILTER table:
196+
197+
>>> import iptc
198+
>>> table = iptc.Table(iptc.Table.FILTER)
199+
>>> chain = table.create_chain("testchain")
200+
201+
$ sudo iptables -L -n
202+
[...]
203+
Chain testchain (0 references)
204+
target prot opt source destination
205+
206+
To access an existing chain:
207+
208+
>>> import iptc
209+
>>> table = iptc.Table(iptc.Table.FILTER)
210+
>>> chain = iptc.Chain(table, "INPUT")
211+
>>> chain.name
212+
'INPUT'
213+
>>> len(chain.rules)
214+
10
215+
>>>
216+
217+
More about matches and targets
218+
------------------------------
219+
220+
There are basic targets, such as `DROP` and `ACCEPT`. E.g. to reject
221+
packets with source address `127.0.0.1/255.0.0.0` coming in on any of
222+
the `eth` interfaces:
223+
224+
>>> import iptc
225+
>>> chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), "INPUT")
226+
>>> rule = iptc.Rule()
227+
>>> rule.in_interface = "eth+"
228+
>>> rule.src = "127.0.0.1/255.0.0.0"
229+
>>> target = iptc.Target(rule, "DROP")
230+
>>> rule.target = target
231+
>>> chain.insert_rule(rule)
232+
233+
To instantiate a target or match, we can either create an object like
234+
above, or use the `rule.create_target(target_name)` and
235+
`rule.create_match(match_name)` methods. For example, in the code above
236+
target could have been created as:
237+
238+
>>> target = rule.create_target("DROP")
239+
240+
instead of:
241+
242+
>>> target = iptc.Target(rule, "DROP")
243+
>>> rule.target = target
244+
245+
The former also adds the match or target to the rule, saving a call.
246+
247+
Another example, using a target which takes parameters. Let's mark
248+
packets going to `192.168.1.2` UDP port `1234` with `0xffff`:
249+
250+
>>> import iptc
251+
>>> chain = iptc.Chain(iptc.Table(iptc.Table.MANGLE), "PREROUTING")
252+
>>> rule = iptc.Rule()
253+
>>> rule.dst = "192.168.1.2"
254+
>>> rule.protocol = "udp"
255+
>>> match = iptc.Match(rule, "udp")
256+
>>> match.dport = "1234"
257+
>>> rule.add_match(match)
258+
>>> target = iptc.Target(rule, "MARK")
259+
>>> target.set_mark = "0xffff"
260+
>>> rule.target = target
261+
>>> chain.insert_rule(rule)
262+
263+
Matches are optional (specifying a target is mandatory). E.g. to insert
264+
a rule to NAT TCP packets going out via `eth0`:
265+
266+
>>> import iptc
267+
>>> chain = iptc.Chain(iptc.Table(iptc.Table.NAT), "POSTROUTING")
268+
>>> rule = iptc.Rule()
269+
>>> rule.protocol = "tcp"
270+
>>> rule.out_interface = "eth0"
271+
>>> target = iptc.Target(rule, "MASQUERADE")
272+
>>> target.to_ports = "1234"
273+
>>> rule.target = target
274+
>>> chain.insert_rule(rule)
275+
276+
Here only the properties of the rule decide whether the rule will be
277+
applied to a packet.
278+
279+
Matches are optional, but we can add multiple matches to a rule. In the
280+
following example we will do that, using the `iprange` and the `tcp`
281+
matches:
282+
283+
>>> import iptc
284+
>>> rule = iptc.Rule()
285+
>>> rule.protocol = "tcp"
286+
>>> match = iptc.Match(rule, "tcp")
287+
>>> match.dport = "22"
288+
>>> rule.add_match(match)
289+
>>> match = iptc.Match(rule, "iprange")
290+
>>> match.src_range = "192.168.1.100-192.168.1.200"
291+
>>> match.dst_range = "172.22.33.106"
292+
>>> rule.add_match(match)
293+
>>> rule.target = iptc.Target(rule, "DROP")
294+
>>> chain = iptc.Chain(iptc.Table.(iptc.Table.FILTER), "INPUT")
295+
>>> chain.insert_rule(rule)
296+
297+
This is the `python-iptables` equivalent of the following iptables
298+
command:
299+
300+
# iptables -A INPUT -p tcp –destination-port 22 -m iprange –src-range 192.168.1.100-192.168.1.200 –dst-range 172.22.33.106 -j DROP

0 commit comments

Comments
 (0)