iptablesのルールの順序を入れ替える方法

コンピューターとネットワーク

まず、パケットフィルタリングにおける iptables の「基本中の基本」を頭に入れておく必要があります。

iptables コマンドの基本構文は「10分でできる iptables によるファイアウォール」で解説しています。

iptablesの基本

iptables について考えるとき次のことを念頭においてください。

  • ルールは設定した順序でパケットに適用される。
  • 最初にマッチしたルールを実行し、それ以降のルールは無視される。
  • 「iptables -P INPUT DROP」「iptables -P OUTPUT DROP」などのポリシーは最後に適用される。

なので「ルールの順序」は超重要です。

ルールの順序を入れ替える方法

ルールの順序は設定した順序ですが、ルールを並べ替えるために都度「iptables -F」で初期化して再設定する必要はありません。

iptables は「INPUT」「OUTPUT」「FORWARD」などのチェーンごとにルール順に「行番号」が付けられているので、「行番号」を指定してルールの「挿入」や「削除」を行うことでルールの順序を変えることができます。

コマンドは次の通りです。

指定した行番号のルールを削除する

iptables -D INPUT [行番号]

指定した行番号に新しいルールを挿入する

iptables -I INPUT [行番号] [新しいルールの内容]

ルールの入れ替えは一度には行えませんので「削除」「挿入」のセットを実行する必要があります。

具体的な実行例

以前の記事でファイアウォール設定について解説しました。

これを変更することを考えてみましょう。

設定内容は次の通りです。

iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# SSH
iptables -A INPUT -m state --state NEW -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
# DNS
iptables -A OUTPUT -p udp -m state --state NEW --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp -m state --state NEW --dport 53 -j ACCEPT
# NTP
iptables -A OUTPUT -p udp -m state --state NEW --dport 123 -j ACCEPT
# APT
iptables -A OUTPUT -p tcp -m state --state NEW --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp -m state --state NEW --dport 443 -j ACCEPT
# ICMP
iptables -A OUTPUT -m state --state NEW -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -m state --state NEW -p icmp -j ACCEPT

これを行番号付きで表示するには次のコマンドを実行します。

iptables -L --line-numbers

実行すると次のように表示されます。

Chain INPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
3    ACCEPT     tcp  --  192.168.1.0/24      anywhere             state NEW tcp dpt:ssh
4    ACCEPT     icmp --  anywhere             anywhere             state NEW

Chain FORWARD (policy DROP)
num  target     prot opt source               destination         

Chain OUTPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
3    ACCEPT     udp  --  anywhere             anywhere             state NEW udp dpt:domain
4    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:domain
5    ACCEPT     udp  --  anywhere             anywhere             state NEW udp dpt:ntp
6    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:http
7    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:https
8    ACCEPT     icmp --  anywhere             anywhere             state NEW icmp echo-request

次のようにNTP問い合わせを許可しています。

iptables -A OUTPUT -p udp -m state --state NEW --dport 123 -j ACCEPT

この設定ではipアドレスを問わずNTP問い合わせについてはすべての宛先に対して発信を許可しています。

ところが特定のipアドレスにはアクセスさせたくない場合はそうすればいいでしょうか。

指定の行番号にルールを追加する

例えば複数ある debian.pool.ntp.org プールのNTPサーバーで 133.243.238.163 にはアクセスしたくないといった場合です。

次のようにルールを追加してみます。

iptables -A OUTPUT -d 133.243.238.163 -j DROP

「iptables -L OUTPUT –line-numbers」のように「OUTPUT」チェーンを指定して行番号付きでルールを表示すると次のようになります。

# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
3    ACCEPT     udp  --  anywhere             anywhere             state NEW udp dpt:domain
4    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:domain
5    ACCEPT     udp  --  anywhere             anywhere             state NEW udp dpt:ntp
6    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:http
7    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:https
8    ACCEPT     icmp --  anywhere             anywhere             state NEW icmp echo-request
9    DROP       all  --  anywhere             ntp-b2.nict.go.jp   

ルールが最後の行番号「9」に追加されているのがわかります。

ntp-b2.nict.go.jp は iptables が ipアドレス をDNS逆引きしてホスト名を表示しています。

逆引き解決せずに表示させたい場合は「-n」オプションを追加して次のようにします。

# iptables -L OUTPUT -n --line-numbers
...
9    DROP       0    --  0.0.0.0/0            133.243.238.163     

iptables では「最初にマッチしたルールを実行し、それ以降のルールは無視される」ので、せっかくルールを追加したのですがNTP問い合わせについては行番号「5」でACCEPTされて、追加したルールは「無視」されます。

133.243.238.163 にアクセスさせないルールは行番号「5」以前に挿入しなければ意味がありません。

iptables -A OUTPUT -d 133.243.238.163 -j DROP

に替えて次のように実行します。

iptables -I OUTPUT 5 -d 133.243.238.163 -j DROP

表示してみます。

# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
3    ACCEPT     udp  --  anywhere             anywhere             state NEW udp dpt:domain
4    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:domain
5    DROP       all  --  anywhere             ntp-b2.nict.go.jp   
6    ACCEPT     udp  --  anywhere             anywhere             state NEW udp dpt:ntp
7    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:http
8    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:https
9    ACCEPT     icmp --  anywhere             anywhere             state NEW icmp echo-request
10   DROP       all  --  anywhere             ntp-b2.nict.go.jp   

NTP問い合わせをACCEPTする前に 133.243.238.163(ntp-b2.nict.go.jp) へのアクセスがDROPされています。

行番号「5」以降はインクリメントされて「挿入前の行番号+1」になりました。

これで目的が達成されました。

行番号「10」は意味が無いので「削除」しても問題ありません。

iptables -D OUTPUT 10

指定の行番号のルールを入れ替える

iptables では指定の行番号のルールを一発で入れ替えることは出来ません。

状況に応じて「削除」「追加」をセットで次のいずれかを実行する必要があります。

  • 指定の行番号のルールを「削除」→指定の行番号にルールを「追加」
  • 指定の行番号にルールを「追加」→[指定の行番号+1]のルールを「削除」
  • [指定の行番号+1]にルールを「追加」→指定の行番号にルールを「削除」

例えば ssh 接続の受け入れを 192.168.1.0/24 からに限定して次のように設定しました。

iptables -A INPUT -m state --state NEW -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT

ところが ssh は接続元を問わずACCEPTするように変更したくなりました。

どうすればいいでしょうか。

現在の状況を表示します。

# iptables -L INPUT --line-numbers
Chain INPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
3    ACCEPT     tcp  --  192.168.1.0/24      anywhere             state NEW tcp dpt:ssh
4    ACCEPT     icmp --  anywhere             anywhere             state NEW

ssh が途切れないようにするにはまずルールの「追加」から始めます。

行番号「3」にルールを追加します。

iptables -I INPUT 3 -m state --state NEW -p tcp --dport 22 -j ACCEPT

状態を表示します。

# iptables -L INPUT --line-numbers
Chain INPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
3    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
4    ACCEPT     tcp  --  192.168.1.0/24      anywhere             state NEW tcp dpt:ssh
5    ACCEPT     icmp --  anywhere             anywhere             state NEW

続いて行番号「4」を削除します。

iptables -D INPUT 4

これで目的が達成されます。

# iptables -L INPUT --line-numbers
Chain INPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
3    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
4    ACCEPT     icmp --  anywhere             anywhere             state NEW

ここで気が付くのは「INPUT」「OUTPUT」チェーンの行番号「1」です。

1    ACCEPT     all  --  anywhere             anywhere

すべてACCEPTになっているのでそれ以降は「無視」されるのでは?

ルールのいろんな表示法

次の表示はどういう意味なのか?

1    ACCEPT     all  --  anywhere             anywhere

これは次の設定が反映されているのではないかと疑ってしまうのですが、違います。

iptables -A INPUT -J ACCEPT
iptables -A OUTPUT -J ACCEPT

標準表示では表示項目が少ないので紛らわしいのですが、詳細表示にすればその意味が分かります。

詳細表示にするには「v」オプションを追加します。

# iptables -vL --line-numbers
Chain INPUT (policy DROP 180 packets, 21251 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 ACCEPT     all  --  lo     any     anywhere             anywhere            
2      645 44520 ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED
3        0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             state NEW tcp dpt:ssh
4        0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             state NEW

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

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 ACCEPT     all  --  any    lo      anywhere             anywhere            
2      422 44832 ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED
3        6   429 ACCEPT     udp  --  any    any     anywhere             anywhere             state NEW udp dpt:domain
4        0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             state NEW tcp dpt:domain
5        0     0 DROP       all  --  any    any     anywhere             ntp-b2.nict.go.jp   
6        6   456 ACCEPT     udp  --  any    any     anywhere             anywhere             state NEW udp dpt:ntp
7        0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             state NEW tcp dpt:http
8        0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             state NEW tcp dpt:https
9        0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             state NEW icmp echo-request

「in」「out」が表示項目に追加されることで納得できます。

つまり以下の反映だったんですね。

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

ほかにも「n」オプションを追加するとDNSで名前解決が行われません。

# iptables -vnL --line-numbers
Chain INPUT (policy DROP 210 packets, 26501 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 ACCEPT     0    --  lo     *       0.0.0.0/0            0.0.0.0/0           
2      727 49753 ACCEPT     0    --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
3        0     0 ACCEPT     6    --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
4        0     0 ACCEPT     1    --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW

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

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 ACCEPT     0    --  *      lo      0.0.0.0/0            0.0.0.0/0           
2      484 52336 ACCEPT     0    --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
3        7   503 ACCEPT     17   --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW udp dpt:53
4        0     0 ACCEPT     6    --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:53
5        0     0 DROP       0    --  *      *       0.0.0.0/0            133.243.238.163     
6        7   532 ACCEPT     17   --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW udp dpt:123
7        0     0 ACCEPT     6    --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:80
8        0     0 ACCEPT     6    --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:443
9        0     0 ACCEPT     1    --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW icmptype 8

まとめ

  • ルールは設定した順序でパケットに適用される。
  • 最初にマッチしたルールを実行し、それ以降のルールは無視される。
  • 「iptables -P INPUT DROP」「iptables -P OUTPUT DROP」などのポリシーは最後に適用される。

したがってルールの順序は非常に重要で、意図した通りにトラフィックを制御するためにはルールを慎重に配置する必要があるのです。

タイトルとURLをコピーしました