python-iptablesを使ってみた


pythonでiptablesを操作する便利モジュール無いかなと探していたらpython-iptablesを見つけたので触ってみました。

python-iptables

https://github.com/ldx/python-iptables

ドキュメント

http://ldx.github.io/python-iptables/index.html

環境

項目 内容
CentOS 7.4
python 3.4

インストール

必要なパッケージをインストール

[root@localhost ~]# yum -y install epel-release
[root@localhost ~]# yum -y install python34 python34-devel python34-pip gcc

python-iptablesインストール

[root@localhost ~]# pip3 install python-iptables

つかってみる

例としてSSHの許可設定を入れてみます。

モジュールを読み込む

In [1]: import iptc

INルールを作る

In [2]: in_rule = iptc.Rule()
In [3]: in_rule.src = '192.168.0.0/24'
In [4]: in_rule.dst = '192.168.0.231'
In [6]: in_rule.protocol = 'tcp'
In [24]: in_rule.target = iptc.Target(in_rule, 'ACCEPT')

OUTルールを作る

In [7]: out_rule = iptc.Rule()
In [8]: out_rule.src = '192.168.0.231'
In [9]: out_rule.dst = '192.168.0.0/24'
In [10]: out_rule.protocol = 'tcp'
In [25]: out_rule.target = iptc.Target(out_rule, 'ACCEPT')

ルールに詳細な条件を追加する

In [11]: in_rule_match = iptc.Match(in_rule, 'tcp')
In [15]: in_rule_match.dport = '22'
In [16]: in_rule.add_match(in_rule_match)
In [17]: out_rule_match = iptc.Match(out_rule, 'tcp')
In [19]: out_rule_match.sport = '22'
In [20]: out_rule.add_match(out_rule_match)

またはiptc.Rule()のメソッドにcreate_matchがあるので、そちらでも設定が可能です。

In [4]: in_rule.create_match('tcp').dport = '22'
In [7]: out_rule.create_match('tcp').sport = '22'

チェインへ挿入する

In [21]: input_chain = iptc.Chain(iptc.Table('filter'), 'INPUT')
In [26]: input_chain.insert_rule(in_rule)
In [29]: output_chain = iptc.Chain(iptc.Table('filter'), 'OUTPUT')
In [30]: output_chain.insert_rule(out_rule)

チェインポリシーを設定する

INPUTOUTPUTのルールは入ったことが確認できます。

[root@localhost ~]# iptables -nL -v
Chain INPUT (policy ACCEPT 103 packets, 6640 bytes)
 pkts bytes target     prot opt in     out     source               destination
 1035 73905 ACCEPT     tcp  --  *      *       192.168.0.0/24       192.168.0.231        tcp dpt:22

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 289 packets, 41652 bytes)
 pkts bytes target     prot opt in     out     source               destination
    5   832 ACCEPT     tcp  --  *      *       192.168.0.231        192.168.0.0/24       tcp spt:22

ただし、チェインのポリシーがACCEPTのままなのでDROPに変更します。

In [39]: input_chain.set_policy('DROP')
In [40]: output_chain.set_policy('DROP')

こするとINPUT OUTPUT共にDROPに設定されます。

[root@localhost ~]# iptables -nL -v
Chain INPUT (policy DROP 42 packets, 2646 bytes)
 pkts bytes target     prot opt in     out     source               destination
 1293 91625 ACCEPT     tcp  --  *      *       192.168.0.0/24       192.168.0.231        tcp dpt:22

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy DROP 1 packets, 76 bytes)
 pkts bytes target     prot opt in     out     source               destination
  145 23312 ACCEPT     tcp  --  *      *       192.168.0.231        192.168.0.0/24       tcp spt:22

YAMLでiptablesを設定してみる

YAMLでルールが管理できると便利かなと思ってpython-iptablesの使い方お勉強のために簡易ツールを作ってみました。

https://github.com/sky-joker/iptables-yml

使い方

YAMLファイル

example.yaml
Loopback Interface Rule:
  INPUT:
    in_interface: lo
    target: ACCEPT
  OUTPUT:
    out_interface: lo
    target: ACCEPT
SSH Rule:
  INPUT:
    dst: 192.168.0.231
    src: 192.168.0.0/24
    target: ACCEPT
    protocol_options:
      protocol: tcp
      dport: 22
  OUTPUT:
    dst: 192.168.0.0/24
    src: 192.168.0.231
    target: ACCEPT
    protocol_options:
      protocol: tcp
      sport: 22

設定を入れてみる

[root@localhost ~]# ./iptables-yml.py init -f example.yaml

結果

[root@localhost ~]# iptables -nL -v
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0            /* Loopback Interface Rule */
   25  1720 ACCEPT     tcp  --  *      *       192.168.0.0/24       192.168.0.231        tcp dpt:22 /* SSH Rule */

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0            /* Loopback Interface Rule */
   14  2304 ACCEPT     tcp  --  *      *       192.168.0.231        192.168.0.0/24       tcp spt:22 /* SSH Rule */

YAMLで設定を標準化

よくよく調べてみれば、Ansibleのiptablesモジュールを使えば使えばYAMLで標準化ができそうです。
iptablesモジュール
こっも触ってみようと思います

python-iptablesは、既存の設定を抜き出してまとめるのに使えそうかも
ちなみに既存の設定を抜き出す場合は以下のようにすればできます。

In [4]: table = iptc.Table('filter')
In [46]: for chain in table.chains:
    ...:     print(chain.name)
    ...:     for rule in chain.rules:
    ...:         print('------')
    ...:         print('comment: ' + str(list(filter(lambda x: hasattr(x, 'comment') and x.comment , rule.matches))[0].comment))
    ...:         print('dst: ' + rule.dst)
    ...:         print('src: ' + rule.src)
    ...:     print("")
    ...:
INPUT
------
comment: Loopback Interface Rule
dst: 0.0.0.0/0.0.0.0
src: 0.0.0.0/0.0.0.0
------
comment: SSH Rule
dst: 192.168.0.231/255.255.255.255
src: 192.168.0.0/255.255.255.0

FORWARD

OUTPUT
------
comment: Loopback Interface Rule
dst: 0.0.0.0/0.0.0.0
src: 0.0.0.0/0.0.0.0
------
comment: SSH Rule
dst: 192.168.0.0/255.255.255.0
src: 192.168.0.231/255.255.255.255