2016-12-29 5 views
3

IPアドレスで構成されたファイルを読み込むためのシェルスクリプトを作成し、iptablesの助けを借りてブロックします。それはうまく動作しますが、スクリプトを2回実行すると、ルールが再度(重複して)書き込まれます。 IPがすでにブロックされているかどうかをチェックし、それ以外のブロックを無視するようにしたい。ここでのスクリプトは次のとおりです。初めてのスクリプトの実行後にファイルを読み取るためのシェルスクリプト

#!/bin/bash 
ipadds="/home/asad/Downloads/blacklist" 
dropit=$(grep -Ev "^#" $ipadds) 
for i in $dropit; do 
iptables -A INPUT -s $i -j DROP 
iptables -A FORWARD -s $i -j DROP 
done 

出力:二度目のスクリプトの実行後に

[email protected]:/home/asad/Downloads# iptables -L 
Chain INPUT (policy ACCEPT) 
target  prot opt source    destination 
DROP  all -- 192.168.248.2  anywhere 
DROP  all -- 192.168.232.20  anywhere 
DROP  all -- 192.168.232.5  anywhere 
DROP  all -- 192.168.232.190  anywhere 
Chain FORWARD (policy ACCEPT) 
target  prot opt source    destination 
DROP  all -- 192.168.248.2  anywhere 
DROP  all -- 192.168.232.20  anywhere 
DROP  all -- 192.168.232.5  anywhere 
DROP  all -- 192.168.232.190  anywhere 
Chain OUTPUT (policy ACCEPT) 
target  prot opt source    destination 

出力:この重複を避けるために、どのように

[email protected]:/home/asad/Downloads# iptables -L 
Chain INPUT (policy ACCEPT) 
target  prot opt source    destination 
DROP  all -- 192.168.248.2  anywhere 
DROP  all -- 192.168.232.20  anywhere 
DROP  all -- 192.168.232.5  anywhere 
DROP  all -- 192.168.232.190  anywhere 
DROP  all -- 192.168.248.2  anywhere 
DROP  all -- 192.168.232.20  anywhere 
DROP  all -- 192.168.232.5  anywhere 
DROP  all -- 192.168.232.190  anywhere 
Chain FORWARD (policy ACCEPT) 
target  prot opt source    destination 
DROP  all -- 192.168.248.2  anywhere 
DROP  all -- 192.168.232.20  anywhere 
DROP  all -- 192.168.232.5  anywhere 
DROP  all -- 192.168.232.190  anywhere 
DROP  all -- 192.168.248.2  anywhere 
DROP  all -- 192.168.232.20  anywhere 
DROP  all -- 192.168.232.5  anywhere 
DROP  all -- 192.168.232.190  anywhere 
Chain OUTPUT (policy ACCEPT) 
target  prot opt source    destination 

?すべてのヘルプは

+2

'while' – Inian

+0

@gniourf_gniourfでコマンド出力、使用プロセス置換をループするために' for'を使用しないでください試みることができる:それはちょうどそれが問題を解決していません実現します。 – Inian

+0

あなたの目的のコードはそのようには機能しません。コマンド出力を格納するための配列が必要でした。あなたの現在の構文では、シェルが単語の分割を行い、1つのスペースで区切られた行を複数のエントリに処理することができます – Inian

答えて

1
#!/bin/bash 
ipadds=/home/asad/Downloads/blacklist 
grep -v "^#" $ipadds | while read i; do 
if ! iptables -nL INPUT | grep -Fq "$i" ; then 
    iptables -A INPUT -s "$i" -j DROP 
    iptables -A FORWARD -s "$i" -j DROP 
fi 
done 

か(多分これはあなたに少し違いが)してください

#!/bin/bash 
ipadds=/home/asad/Downloads/blacklist 
while read i; do 
if ! iptables -nL INPUT | grep -Fq "$i" ; then 
    iptables -A INPUT -s "$i" -j DROP 
    iptables -A FORWARD -s "$i" -j DROP 
fi 
done < <(grep -v "^#" $ipadds) 

grepため-Eフラグは、この場合に必要とされていないことに注意してください。ホスト名ではなくIPを取得するには、-nフラグをiptables -Lに渡すことが重要です。パフォーマンスも向上します。あなたのINPUTチェーンとFORWARDチェーンは同期していると仮定していますので、そのうちの1つだけをチェックします。これが当てはまらない場合は、両方を確認する必要があります。

上記のスクリプトの正確なセマンティクスは、「既にINPUTチェーン内のどこにでも言及されていれば、新しい候補IPを挿入しないでください」です。これは「既にブロックされている場合」とは少し異なります。 iptables -Cに基づくより効率的なソリューションは、特定のルールを探しますが、チェーン内のIPの他の記述には適していません。いずれのアプローチが望ましいシナリオについて考えることができます。

iptablesチェーンにたくさんのIPがある場合は、チェーン全体をスキャンして、候補IPがすでに存在するかどうかを調べると効率が悪い可能性があります。これが問題になる場合は、より効率的なIPルックアップのために外部インデックスを構築するさまざまな方法がありますが、システム全体が維持するのが難しくなるため、外部インデックスを使用しないで実験を開始します。

+0

良い点! '$ i'を' $ i''として二重引用符を追加してより多くの迂回を追加するとよいでしょう – Inian

+0

@Inian '$ i'は有効なIPアドレス、すなわちドットと数字( ipV4環境で)、引用符で囲むと不正な文字しか保存されません。堅牢性を高めるには、それに応じて解析する必要があり、非効率的です。 '$ ip'が失敗し、' '$ ip''が成功するケースは考えられません。 – Dario

+1

引用符は傷ついていません。特に 'IFS'にピリオドまたは数字が含まれている場合。本当に、決して仮定しないでください。すべての単一展開を引用するだけです。しかし、より大きな問題は、ピリオドが「任意の1文字に一致する」と解釈されることです。別の問題は、正規表現がアンカーされていないことです。 –

0

あなたは

#!/bin/bash 

ipadds="/home/asad/Downloads/blacklist" 

while IFS='' read -r 
do 
    # check if the rule already exists - if not add it - and 
    # silently ignore warnings for rules that dont exist 
    if ! iptables -C INPUT -s "$REPLY" -j DROP 2> /dev/null 
    then 
     iptables -A INPUT -s "$REPLY" -j DROP 
    fi 

    if ! iptables -C FORWARD -s "$REPLY" -j DROP 2> /dev/null 
    then 
     iptables -A FORWARD -s "$REPLY" -j DROP 
    fi 
# Please note proper syntax for process substitution 
done < <(grep -Ev "^#" $ipadds) 
+0

非常に良い答えです(私はそれが必要な '<' -signが不足しているため編集しました)。 – Dario

+0

@Inianそれは動作しますが、多くの警告があります: "iptables v1.6.0:ホスト/ネットワーク' 'が見つかりません "。いずれにせよあなたの注意を払ってくれてありがとう –

関連する問題