python-iptablesとはiptablesをPythonで操作するためのモジュールです。
環境
- Ubuntu 18.04
- Python 3.6
- python-iptables 0.13.0
ソースコード
ソースコードはManipulate iptables using python-iptablesにあります。
1 import iptc
2 import ipaddress
3
4
5 def format_address(address):
6 """
7 Support IPv4 only yet.
8 Return IPv4 with prefix length (e.g. 192.168.0.1/32)
9 """
10
11 if isinstance(address, (str, ipaddress.IPv4Address)):
12 try:
13 address = ipaddress.ip_network(address)
14 except ValueError:
15 raise
16 elif isinstance(address, ipaddress.IPv4Network):
17 pass
18 else:
19 raise TypeError
20
21 return address.with_prefixlen
22
23
24 def display_matches(matches=[]):
25 print("Match:", end=' ')
26 for match in matches:
27 for key, value in match.get_all_parameters().items():
28 if isinstance(value, list):
29 value = ', '.join(value)
30
31 print("[{}] {}".format(key, value))
32
33
34 def display_rule(rule):
35 print('+'*40)
36 print("Target:", rule.target.name)
37 print("Protocol:", rule.protocol)
38 print("Source address:", format_address(rule.src))
39 print("Destination address:", format_address(rule.dst))
40 display_matches(rule.matches)
41 print('+'*40)
42
43
44 def delete_rule(chain, rule):
45 chain.delete_rule(rule)
46
47 if __name__ == '__main__':
48 # Create rule
49 rule1 = iptc.Rule()
50 rule1.out_interface = 'eth0'
51 rule1.dst = "192.168.0.1"
52 rule1.protocol = 'icmp'
53 match_for_rule1 = rule1.create_match('icmp')
54 match_for_rule1.icmp_type = 'echo-request'
55 rule1.create_target('DROP')
56
57 rule2 = iptc.Rule()
58 rule2.out_interface = 'eth0'
59 rule2.dst = "192.168.0.2"
60 rule2.protocol = 'icmp'
61 match_for_rule2 = rule2.create_match('icmp')
62 match_for_rule2.icmp_type = 'echo-reply'
63 rule2.create_target('DROP')
64
65 # Create chain
66 chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'OUTPUT')
67 # Apply rule to chain
68 chain.insert_rule(rule1)
69 chain.insert_rule(rule2, position=1)
70
71 for rule in chain.rules:
72 try:
73 display_rule(rule)
74 except:
75 from traceback import print_exc
76 print_exc()
5~21行目
モジュールから返される送信元/宛先アドレスは192.168.0.0/255.255.255.0のようなフォーマットなので、これを192.168.0.0/24のようにネットマスクをプレフィックス長に変換するための関数
24~31行目
iptablesのmatch extensionsを表示するための関数
match.get_all_parameters()で設定されている全ての値を取得
34~41行目
設定したルールを表示するための関数
44~45行目
特定のchainに設定されているルールを削除するための関数
49~63行目
ルールの作成
66行目
FilterテーブルのOUTPUT Chainの作成
68~69行目
作成したルールをchainに適用
69行目の第2引数のposition
はchainの何番目にルールを挿入するか指定
71行目
chain.rulesによって、chainに設定されている全てのルールを取得
返り値はRuleオブジェクトであり、Ruleオブジェクトには__str__
や__repr__
が書かれていないので素のオブジェクト情報が返されます
つまり、詳細なルール情報を表示したい場合は34~41行目にあるように自作する必要があります
検証
$ python3 demo.py
++++++++++++++++++++++++++++++++++++++++
Target: DROP
Protocol: icmp
Source address: 0.0.0.0/0
Destination address: 192.168.0.1/32
Match: [icmp-type] 8
++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++
Target: DROP
Protocol: icmp
Source address: 0.0.0.0/0
Destination address: 192.168.0.2/32
Match: [icmp-type] 0
++++++++++++++++++++++++++++++++++++++++
$ iptables -L OUTPUT
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DROP icmp -- anywhere 192.168.0.1 icmp echo-request
DROP icmp -- anywhere 192.168.0.2 icmp echo-reply
ちゃんとiptablesにルールがコミットされました。