回答:
#!/bin/bash
WHITELIST=/whitelist.txt
BLACKLIST=/blacklist.txt
#THIS WILL CLEAR ALL EXISTING RULES!
echo 'Clearing all rules'
iptables -F
#
## Whitelist
#
for x in `grep -v ^# $WHITELIST | awk '{print $1}'`; do
echo "Permitting $x..."
$IPTABLES -A INPUT -t filter -s $x -j ACCEPT
done
#
## Blacklist
#
for x in `grep -v ^# $BLACKLIST | awk '{print $1}'`; do
echo "Denying $x..."
$IPTABLES -A INPUT -t filter -s $x -j DROP
done
#!/bin/bash
ALLOWEDTCP="80 3128 3784"
ALLOWEDUDP="3128 3784"
#
## Permitted Ports
#
for port in $ALLOWEDTCP; do
echo "Accepting port TCP $port..."
$IPTABLES -A INPUT -t filter -p tcp --dport $port -j ACCEPT
done
for port in $ALLOWEDUDP; do
echo "Accepting port UDP $port..."
$IPTABLES -A INPUT -t filter -p udp --dport $port -j ACCEPT
done
# Attempt to block portscans
# Anyone who tried to portscan us is locked out for an entire day.
iptables -A INPUT -m recent --name portscan --rcheck --seconds 86400 -j DROP
iptables -A FORWARD -m recent --name portscan --rcheck --seconds 86400 -j DROP
# Once the day has passed, remove them from the portscan list
iptables -A INPUT -m recent --name portscan --remove
iptables -A FORWARD -m recent --name portscan --remove
# These rules add scanners to the portscan list, and log the attempt.
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP
iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP
# Reject spoofed packets
# These adresses are mostly used for LAN's, so if these would come to a WAN-only server, drop them.
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 127.0.0.0/8 -j DROP
#Multicast-adresses.
iptables -A INPUT -s 224.0.0.0/4 -j DROP
iptables -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -s 240.0.0.0/5 -j DROP
iptables -A INPUT -d 240.0.0.0/5 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -d 0.0.0.0/8 -j DROP
iptables -A INPUT -d 239.255.255.0/24 -j DROP
iptables -A INPUT -d 255.255.255.255 -j DROP
# Drop all invalid packets
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP
# Stop smurf attacks
iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m icmp -j DROP
# Drop excessive RST packets to avoid smurf attacks
iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT
# Don't allow pings through
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP
iptables
します。8行目にあり、それ$IPTABLES
以降です。iptables
どこでも使うだけで十分ですか?そうでなければ、あなたはIPTABLES=/sbin/iptables
正しいようなものを割り当てる必要があると思いますか?
ipset
単なるIP、ポート、またはその両方に基づいて同様のルールを多数作成する場合は、使用ipset
してnetfilterのパフォーマンスを最適化することを検討してください。
例えば:
iptables -s 192.168.1.11 -j ACCEPT
iptables -s 192.168.1.27 -j ACCEPT
iptables -s 192.168.1.44 -j ACCEPT
... hundreds of similar rules ...
iptables -s 192.168.251.177 -j ACCEPT
つまり、送信元アドレスが192.168.251.177のパケットは、ACCEPTの判定を取得する前に、まず数百のルールを通過する必要があります。
もちろん、経験豊富なシステム管理者は、サブネットごとにルールを分割します。しかし、それはまだ何百ものルールを意味します。
ipset
救助へ!
まず、ipmap
タイプのIPセットを定義します。
ipset -N Allowed_Hosts ipmap --network 192.168.0.0/16
次に、アドレスを入力します。
for ip in $LIST_OF_ALLOWED_IP; do ipset -A Allowed_Hosts $ip; done
最後に、上記の数百のiptablesルールを1つのルールに置き換えます。
iptables -m set --match-set Allowed_Hosts src -j ACCEPT
パケットが到着すると、netfilterはIPセットに対してパケットのソース(src)IPの非常に迅速なビットマップ検索を実行しAllowed_Hosts
ます。192.168.0.0/16からのすべてのパケットには1つのルールが適用されます。また、ビットマップの検索は、数百のiptablesルールチェックを実行するよりも少なくとも2桁高速であると信じています。
ipset
IPアドレスに限定されません。ポート、IPポートタプル、ネットワーク/サブネットアドレス、IP-MACタプルなどに基づいて照合することもできます。そして、ソースまたは宛先、または両方の組み合わせ(タプルの場合)としてこれらの基準に一致することができます。
最後に、ipset
IPアドレスをブラックリスト/ホワイトリストに自動的に追加できます。これらのブラックリスト/ホワイトリストは「エージング」することもできるため、設定可能な時間が経過するとIPアドレスが自動的に削除されます。
詳細については、ipset
のmanページを参照してください。
一部のLinuxディストリビューションには、「すぐに使用できる」サポートがない場合がありますipset
(たとえば、Ubuntu 10.04にはこの問題がありました)。これらのシステムではipset
、ソースコードからインストールする方法が1つあります。
代わりに、ipset
Webサイトhttp://ipset.netfilter.org/install.htmlからのソースをダウンロードしてください
または、を使用する場合xtables-addons
、ipset はソースに含まれます:http : //xtables-addons.sourceforge.net/
できれば次のルールを追加します -t raw -A PREROUTING
-p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
-p tcp --tcp-flags SYN,RST SYN,RST -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
ブロックされる攻撃はそれぞれ次のとおりです。
(上記の攻撃の名前を自由に編集してください)
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
除去することができ-p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
、それはブロックする可能性のすべてのパケットをキャッチします。
echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
ステップ1はカーネルパラメータを設定してIP転送を許可し、ステップ2はインターフェイスeth0でNATを有効にするiptablesルールを設定します。
/etc/sysctl.conf
net.ipv4.ip_forward = 1
。(Red Hatまたは派生物を想定)
できれば次のルールを追加します -t raw -A PREROUTING
-p icmp -m u32 ! --u32 "4&0x3FFF=0" -j DROP
-p icmp -m length --length 1492:65535 -j DROP
最初のルールブロックその「フラグメンテーションフラグ」0でないすべてのICMPパケット(ICMPがべき決して断片化しないこと;それらは小さなペイロードを搬送しなければなりません)
2番目のルールは、オーバーサイズの断片化されていないICMPパケットをブロックします。
FireHOLの使用-便利なiptablesラッパー
直接のiptablesコマンドよりもはるかに直感的であることがわかりました。特に、他のファイアウォールの過去の経験を持つ人々のために:
FireHOLは、任意の数のネットワークインターフェイス、任意の数のルート、任意の数のサービスを提供するLinuxホストおよびルーター上で、ステートフルなiptablesパケットフィルタリングファイアウォールを生成するiptablesファイアウォールジェネレーターです。式)。
(多くの場所から再コンパイルされたiptables_tricks.txtファイルから:P)
ポート22(SSH)の同じIPからの新しい接続間でiptablesを15秒待機させます。
iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP
iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 --rttl --name SSH -j DROP
IPTABLESビデオチュートリアル
エピソード1 http://www.youtube.com/watch?v=ldB8kDEtTZA&feature=player_embedded
エピソード2 http://www.youtube.com/watch?v=aDaEXxRHeXY&feature=related
最後のエピソード
http://www.youtube.com/watch?v=JojqHKcSxpo&feature=player_embedded
初心者にとっては良いスタートになります。
IPセットについて言及した回答が既にあります。ただし、従来のルールよりもパフォーマンスが向上し、IPセットがCIDR表記でサブネットとして簡単に表現できない多くの個々のIPアドレスの問題を緩和するという事実に焦点を当てているという点で、むしろ一次元です。
以下のためにipset
私は、表記で読み取りに使用するipset restore
とによって書かれたがipset save
。
iptables
(およびip6tables
)ルールに対応して、によって読み書きされる表記法を使用iptables-restore
しiptables-save
ます。これにより、表記が短くなり、IPv4専用(プレフィックス付き-4
)またはIPv6 専用(プレフィックス付き)の潜在的な-6
ルールを強調できます。
いくつかの例では、パケットフローを別のチェーンに迂回させます。チェーンはその時点で存在すると想定されているため、チェーンを作成するための行は生成されません(また、テーブル名のCOMMIT
記述や、最後にコマンド-ted はありません)。
IPセットは、他の回答で述べられているよりもはるかに多くのことができるので、ここのこの簡単なエントリに加えて、IPセットのドキュメント(ipset(8)
)を必ずお読みiptables-extensions(8)
ください。
たとえば、私は主に3つのセットタイプに焦点を当てます:hash:ip
、hash:net
およびlist:set
ですが、それ以上のものがあり、すべて有効なユースケースがあります。
たとえば、IPアドレスだけでなくポート番号も照合できます。
iptables-save
し、iptables-restore
IPセット宣言を一括で作成し、それらをにパイプしてインポートできますipset restore
。既存のエントリに対してコマンドの回復力を高めたい場合は、を使用しますipset -exist restore
。
default.set
使用するファイルにルールが含まれている場合:
ipset -exist restore < default.set
そのようなファイルにcreate
は、セットへのadd
エントリとセットへのエントリを含めることができます。しかし、一般的に、コマンドラインからのコマンドのほとんどは、ファイルに対応するバージョンがあるようです。例(一連のDNSサーバーの作成):
create dns4 hash:ip family inet
create dns6 hash:ip family inet6
# Google DNS servers
add dns4 8.8.8.8
add dns4 8.8.4.4
add dns6 2001:4860:4860::8888
add dns6 2001:4860:4860::8844
ここでは、IPv4(dns4
)とIPv6(dns6
)の1つのセットが作成されます。
IPセットのタイムアウトは、セットごとおよびエントリごとにデフォルトとして設定できます。これは、誰かを一時的にブロックしたい場合(ポートスキャンやSSHサーバーのブルートフォース試行など)に非常に便利です。
これが機能する方法は次のとおりです(IPセットの作成時のデフォルト)。
create ssh_loggedon4 hash:ip family inet timeout 5400
create ssh_loggedon6 hash:ip family inet6 timeout 5400
create ssh_dynblock4 hash:ip family inet timeout 1800
create ssh_dynblock6 hash:ip family inet6 timeout 1800
これらの特定のセットと、それらがどのように設定されているのかについての理論的根拠に戻ります。
特定のIPアドレスにタイムアウトを設定する場合は、次のように単純に言うことができます。
add ssh_dynblock4 1.2.3.4 timeout 7200
(設定された)デフォルトの30分ではなく、IP 1.2.3.4を2時間ブロックします。
ipset save ssh_dynblock4
しばらくしてそれを見ると、次のような行に沿って何かが表示されます。
create ssh_dynblock4 hash:ip family inet hashsize 1024 maxelem 65536 timeout 1800
add ssh_dynblock4 1.2.3.4 timeout 6954
Kernel error received: Unknown error -1
)が表示されます。sudo ipset add ssh_dynblock4 1.2.3.4 timeout $((120*60))
スクリプト内で、エントリがすでに存在するかどうかを確認すると便利です。これはipset test
、エントリが存在する場合はゼロを返し、そうでない場合はゼロ以外を返すことで実現できます。したがって、通常のチェックはスクリプトで適用できます。
if ipset test dns4 8.8.8.8; then
echo "Google DNS is in the set"
fi
ただし、多くの場合、既存のエントリについて文句を言わないように-exist
切り替えるためipset
に、スイッチを使用する方がよいでしょう。
iptables
ルールからIPセットを作成する私の意見では、これはIPセットの優れた機能の1つです。IPセットのエントリと照合できるだけでなく、既存のIPセットに新しいエントリを追加することもできます。
たとえば、この質問に対するこの回答には次のようなものがあります。
-A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP
-A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
... SSH(TCPポート22)への接続試行のレート制限を目的としています。使用されているモジュールrecent
は、最近の接続試行を追跡します。ただし、state
モジュールの代わりに、モジュールを好みconntrack
ます。
# Say on your input chain of the filter table you have
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
# Then inside the SSH chain you can
# 1. create an entry in the recent list on new connections
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
# 2. check whether 3 connection attempts were made within 2 minutes
# and if so add or update an entry in the ssh_dynblock4 IP set
-4 -A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock4 src --exist
-6 -A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock6 src --exist
# 3. last but not least reject the packets if the source IP is in our
# IP set
-4 -A SSH -m set --match-set ssh_dynblock4 src -j REJECT
-6 -A SSH -m set --match-set ssh_dynblock6 src -j REJECT
この場合、フローをSSH
チェーンにリダイレクトしている-p tcp --dport ssh
ため、ルールごとに繰り返す必要はありません。
繰り返します:
-m set
なりiptables
、我々はからスイッチを使用していることを認識してset
(IPセットを扱う)モジュール--match-set ssh_dynblock4 src
ソース()アドレスを名前付きセット()
iptables
と照合するように指示しますsrc
ssh_dynblock4
sudo ipset test ssh_dynblock4 $IP
($IP
パケットのソースIPアドレスを含む)に対応します-j SET --add-set ssh_dynblock4 src --exist
パケットからIPセットにソース(src
)アドレスを追加するか、アップデートしますssh_dynblock4
。エントリが存在する場合(--exist
)単に更新されます。
sudo ipset -exist add ssh_dynblock4 $IP
($IP
パケットのソースIPアドレスを含む)に対応します代わりにターゲット/宛先アドレスを一致させたい場合は、のdst
代わりに使用しますsrc
。その他のオプションについては、マニュアルを参照してください。
IPセットには他のセットを含めることができます。ここまでの記事をたどると、セットを組み合わせることが可能かどうか疑問に思うでしょう。そしてもちろんです。上記のIPセットの場合、2つのジョイントセットssh_dynblock
を作成し、ssh_loggedon
それぞれIPv4専用セットとIPv6専用セットを含めることができます。
create ssh_loggedon4 hash:ip family inet timeout 5400
create ssh_loggedon6 hash:ip family inet6 timeout 5400
create ssh_dynblock4 hash:ip family inet timeout 1800
create ssh_dynblock6 hash:ip family inet6 timeout 1800
# Sets of sets
create ssh_loggedon list:set
create ssh_dynblock list:set
# Populate the sets of sets
add ssh_loggedon ssh_loggedon4
add ssh_loggedon ssh_loggedon6
add ssh_dynblock ssh_dynblock4
add ssh_dynblock ssh_dynblock6
そして、あなたの心に浮かぶべき次の質問は、これがIPバージョンに依存しない方法でIPセットを一致させ、操作することを可能にするかどうかです。
そして、その答えは圧倒的です:はい!(また、これは前回チェックしたときに明示的に文書化されていませんでした)
したがって、前のセクションのルールは次のように書き換えることができます。
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
-A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock src --exist
-A SSH -m set --match-set ssh_dynblock src -j REJECT
はるかに簡潔です。そして、はい、これは試され、テストされ、魅力のように機能します。
私のサーバーでは、cron
一連のホスト名を取得してそれらをIPアドレスに解決するジョブとして実行されるスクリプトがあり、それを「信頼できるホスト」のIPセットに送ります。考えは、信頼できるホストはサーバーへのログイン試行をより多く取得し、他の誰かがいる限り必ずしもブロックされないということです。
逆に、信頼できるホストの(潜在的な)例外を除いて、国全体でSSHサーバーへの接続をブロックしています(ルールの順序が重要です)。
ただし、それは読者の演習として残されています。ここでは、セットに含まれるセットを使用しssh_loggedon
て、後続の接続試行が通過し、他のパケットと同じ精査の対象にならないようにするきちんとしたソリューションを追加します。
次のルールを見るときは、デフォルトのタイムアウトが90分ssh_loggedon
、30分であることssh_dynblock
に注意してiptables
ください。
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
-A SSH -m set --match-set ssh_loggedon src -j ACCEPT
-A SSH -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
-A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock src --exist
-A SSH -m set --match-set ssh_dynblock src -j REJECT
ここまでで、接続IPアドレスがssh_loggedon
サブセットでどのようになるかを自問する必要があります。読んでください...
sshrc
友人や実験をしたことがあるなら、その欠点を知っているでしょう。しかし、PAMが助けになります。という名前のモジュールをpam_exec.so
使用すると、ユーザーが許可されていることがわかっている時点でSSHログオン中にスクリプトを呼び出すことができます。
では/etc/pam.d/sshd
以下pam_env
とpam_selinux
エントリは次の行を追加します。
session optional pam_exec.so stdout /path/to/your/script
スクリプトのバージョン(/path/to/your/script
上記)が存在し、実行可能であることを確認してください。
PAMは環境変数を使用して何が行われているかを通信するため、次のような簡単なスクリプトを使用できます。
#!/bin/bash
# When called via pam_exec.so ...
SETNAME=ssh_loggedon
if [[ "$PAM_TYPE" == "open_session" ]] && [[ -n "$PAM_RHOST" ]]; then
[[ "x$PAM_RHOST" != "x${PAM_RHOST//:/}" ]] && SETNAME="${SETNAME}6" || SETNAME="${SETNAME}4"
ipset -exist add $SETNAME "$PAM_RHOST"
fi
残念ながら、このipset
ユーティリティにはnetfilterの組み込みスマート機能がないようです。そのため、エントリを追加するときに、IPv4とIPv6のIPセットを区別する必要があります。それ以外の場合、IPの代わりにipset
別のセットをセットのセットに追加することを想定します。そしてもちろん、IPにちなんで名付けられたセットがあることはまずありません:)
そのため:
、この6
ような場合などでは、IPアドレスをチェックしてセット名に追加し4
ます。
終わり。
iptablesの構成に使用できるもう1つのGUIはFirewall Builderです。データベース内のオブジェクトとしてルール要素を作成し、これらのオブジェクトをルールエディターにドラッグアンドドロップして、目的のファイアウォールポリシーを作成できます。次に、アプリケーションは、ルールの実装に必要なすべてのiptablesコマンドを含むスクリプトファイルを生成します。
一度に1つのiptables構成のみを管理できる他のiptables GUIソリューションとは異なり、Firewall Builderでは、単一のアプリケーションからすべてのiptables構成をすべて管理できます。Firewall BuilderはLinux、Windows、Mac OS Xで動作し、10年以上前から存在し、世界中に何千人ものアクティブユーザーがいます。
完全開示-私は、Firewall Builderを開発している会社であるNetCitadelの共同設立者です。
uidを使用した発信接続のログ
iptables -A OUTPUT -m state --state NEW -m tcp -p tcp -m limit --limit 5/m -j LOG --log-uid --log-prefix="outgoing connection: "
ポート/接続の転送:
iptables -A PREROUTING -t nat -i eth1 -p tcp --dport 80 -j DNAT --to 10.0.1.7:80
iptables -A INPUT -p tcp -m state --state NEW --dport 80 -i eth1 -j ACCEPT
NFLOG
ターゲットが好きです。より長い行プレフィックスを許可し、ユーザーモードデーモンはデータベースにもログを記録できます。
例:あなたが持っているeth0
と eth1
、それらの間のすべてのトラフィックを許可したいですか?
iptables -A FORWARD -i eth+ -o eth+ -j ACCEPT
過去にこれを使用して、veth<something>
LXCによって動的に作成され名前が付けられたインターフェースを一致させました。だから私は一度にすべてを一致させることができveth+
ます。
また、私は意図的にいくつかのインターフェイス_<something>
に名前を付けて一致させました_+
。
iptables -t mangle -A PREROUTING -p tcp \
-m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
このターゲットの目的は、SYNパケットを送信したホストが接続を確立するか、SYN接続を開始した後に何もしないかをチェックすることです。何もしない場合、最小限の労力でパケットを破棄します。
rawテーブルの接続追跡テーブルにsynパケットを設定します
iptables -t raw -A PREROUTING -p tcp -m tcp --dport 80 --syn -j CT --notrack
httpサーバーのsynproxyを有効にします。
iptables -A INPUT -p tcp -m tcp --dport 80 -m conntrack --ctstate INVALID,UNTRACKED \
-j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
リソース: RHELブログのSYNPROXYターゲット
すべての個々のIPアドレスをIPセットを使用したアウトバウンド帯域幅クォータに制限する
おそらく、ISPの従量制の帯域幅割り当てのために、帯域幅使用攻撃を反映または回避するために、サーバーが1か月あたり15GiByteの帯域幅使用のみを許可するようにサーバーを構成してください。次のように実現できます。
最初にIPv4およびIPv6のIPセットを作成します。
ipset create IP_QUOTA_SET_OUT hash:ip timeout 345600 counters
ipset create IP_QUOTA_SET_OUT_INET6 hash:ip timeout 345600 counters family inet6
次に、iptablesルールを追加します。最初の行では、IPがまだ設定されていない場合はセットに追加されます。セット内のIPに対して転送されたバイトが指定された量よりも大きい場合、2行目は一致しません。その後、IPv6でも同じことが行われます。
iptables -I OUTPUT -m set ! --match-set IP_QUOTA_SET_OUT dst -j SET --add-set IP_QUOTA_SET_OUT dst --timeout 345600
iptables -I OUTPUT -m set --match-set IP_QUOTA_SET_OUT dst --bytes-gt 16106127360 -j DROP
ip6tables -I OUTPUT -m set ! --match-set IP_QUOTA_SET_OUT_INET6 src -j SET --add-set IP_QUOTA_SET_OUT_INET6 src --timeout 345600
ip6tables -I OUTPUT -m set --match-set IP_QUOTA_SET_OUT_INET6 src --bytes-gt 16106127360 -j DROP
これにより、ユーザーがウェブサーバーから長時間にわたって大きなファイルを要求したり、そのサービスを利用したりするような攻撃を防ぐことができます。INPUTチェーンでも同じことができます。
主にエレガントなソリューションを知らないために私が行うことは、4時間ごとにNginxログを手動でチェックし、個々のIPによる過剰なアクセスについて2分ごとにメールサーバーログをチェックすることです。次のスクリプトをいくつか一緒に実行します。
access.log
サーバーへのヒット数ごとに整理された上位10個のIPをチェックして一覧表示します。iptables.save
これは次のようなものです。
autoBanIPs_mail.sh#!/bin/bash
# This script checks the last 2 minutes of log entries to see if any
# IP has made over 99 connections
now=$(date +"%m_%d_%Y")
/root/bin/checkBadIPs_mail.sh > /home/ipChecker/ipcheckMAIL_$now.txt
cat /home/ipChecker/ipcheckMAIL_$now.txt | \
grep " \\(\\([9][9]\\)\\|\\([0-9][0-9][0-9]\\+\\)\\) " | \
awk '{print $2}' > /home/ipChecker/badMailIPs_$now.sh
sed -i "s/^/\/usr\/local\/sbin\/blockIP /g" /home/ipChecker/badMailIPs_$now.sh
/bin/bash /home/ipChecker/badMailIPs_$now.sh
cat /home/ipChecker/ipcheckMAIL_$now.txt >> /home/ipChecker/ipcheckMAIL_$now.log
rm /home/ipChecker/ipcheckMAIL_$now.txt
rm /home/ipChecker/badMailIPs_$now.sh
checkBadIPs_mail.sh
ここで非常に重要なことの1つは、ホワイトリストを設定する必要があることです。または、他のログからIPアドレスを取得したり、他のログの場合に大量のメールを受信するサーバーから多くの本物のIPをブロックしたりすることです正当な理由でサーバーに頻繁にヒットするだけです。私のホワイトリストは、|の直後にgrepパイプを追加することにより、このスクリプトに組み込まれています。grep ']' | 「grep -v 127.0 |」のように見えるもの 。
どのトラフィックIPが正当であり、そうでないかをサーバーに教えるのに時間をかける必要があります。私にとってこれは、最初の1週間ほどログを数時間ごとに手動でチェックし、iplocation.netでトラフィックの多いIPを検索し、amazon、box.com、または自宅/オフィスなどの正当なものを追加する必要があることを意味しましたこのホワイトリストのIP範囲。そうしないと、おそらく自分のサーバーからブロックされるか、正当なメール/ Webサーバーのブロックを開始し、電子メールまたはトラフィックの中断を引き起こします。
cat /var/log/mail.log | awk \
-v d1="$(date --date="-2 min" "+%b %_d %H:%M")" \
-v d2="$(date "+%b %_d %H:%M")" \
'$0 > d1 && $0 < d2 || $0 ~ d2' | \
grep '\[' | grep '\]' | \
grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -v 127.0 | \
awk '{print $1}' | sort | uniq -c | sort -n | tail -10
BlockIP
#!/bin/bash
sudo iptables -I INPUT -s $1 -j DROP
sudo bash -c "iptables-save > /etc/network/iptables.save"
繰り返しますが、これは地獄のように粗雑であり、おそらくこれをすべて実行するきれいで効率的なプロトコルがありますが、私はそれを知らず、このことは1年または2年続いており、悪者を寄せ付けませんでした。私が非常にお勧めすることの1つは、メインサーバーにアクセスするために使用できるプロキシまたは別のサーバーが翼にあることです。理由は、ある日突然Web開発をしている場合、いくつかのテストでは、5時間以内に2000回、pingを実行し、プロキシを除いてブロックバックする方法があります。
checkBadIPs.sh
私はgrep -v 127.0を配置し、実際のファイルには自分のIPや他の信頼できるIP範囲の無視ルールがたくさんありますが、IPが変更され、更新を忘れてロックされていることがわかります自分のサーバーから。
とにかく、それが役立つことを願っています。
少し変更したので、数時間ごとにチェックする代わりに、2分ごとにいくつかのログ、主にssh認証ログとメールログがチェックされます:(
各ログファイルに特定のスクリプトを設定しますが、ログを調べたいときに自分で使用する手動のスクリプトからは簡単です。次のようになります。
#!/bin/bash
log=$1 time=$2
cat /var/log/${log} | awk \
-v d1="$(date --date="-${time} min" "+%b %_d %H:%M")" \
-v d2="$(date "+%b %_d %H:%M")" \
'$0 > d1 && $0 < d2 || $0 ~ d2' | \
grep '\[' | grep '\]' | \
grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | \
sort | uniq -c | sort -n | tail -10
これには、実行時に2つの入力、スキャンするログファイル、およびスキャンする過去の過去の入力が必要です。
したがって、mail.logでIPカウントを確認したい場合は、75分前までを実行します。
$ sudo script.sh mail.log 75
ipset
iptablesチェーンを延長するのではなく使用しますが、そのアイデアは素晴らしいものであり、運用サーバーに適用すると思います。共有してくれてありがとう!
ipsetsとtcpフラグに関するコメントには同意しますが、まだ多くの欠落があります。
国リストにはipsetsの代わりにxtables-addons geoip matchを使用します。geoipデータを定期的に(少なくとも月に1回)更新します。データは、fire-and-forget ipsetリストよりも動的です。
TCPフラグを使用した接続状態の追跡を検討してください。たとえば、tcp RSTまたはACKは、確立された接続に対してのみ意味があります。SYNは、新規および関連する接続に対してのみ意味があります。確立された接続のSYNは、SYN + ACKが失われたか、ハッキングの試みであり、接続の両側で状態が一致しないためリセットする必要があることを意味します。
どれも、SYN + RSTとFIN + RSTは不正な組み合わせですが、SYN + FINは、特にDNSの場合、TCP高速オープン(TCPオプション34)の下で有効です。SYNパケットは、ファストオープンでも、断片化されるべきではありません。PSHフラグとURGフラグを使用したルールは有用とは見なしません。接続追跡状態とTCP状態を混同しないでください。SYNパケットに対するRST応答は、追跡目的で確立されます。
SYNPROXYは転送されたパケット用であり、syncookieサポートを超えてローカルに配信されたパケットには何も追加しません。
ICMPエラーパケットは、関連する状態にあり、有効な場合は長さ48:576になります。IPv6の場合、長さ84:1280。その他はすべて無視する必要があります。最大サイズは最小MTUでもあるため、断片化しないでください。ICMP要求(ping、タイムスタンプなど)は常に新しく、応答が確立されます。他の状態のICMPパケットをドロップします。
最近のリストを使用し、後続のSYNパケットのみを受け入れるSSHの例のように、SMTPに対しても同じことを行う必要があり、IPアドレスデータのみの「グレーリスト」に似ています。
フィルターテーブルでは、入力チェーンと出力チェーンの最初の(確立された状態パケットを最初に受け入れる場合は2番目)ルールは、ループバックインターフェイス上のすべてを受け入れる必要があります。独自の内部パケットを信頼する必要があります。できない場合は、ファイアウォールソリューションを超える大きな問題があります。
最後に、ルールの動作を本当に理解しない限り、盲目的にルールをコピーしないでください。多くの類似したルールのリストがそれを行い、ほとんどの場合、結果は笑えます。
#!/bin/bash
# The following iptables/ip6tables configurations have
# been kindly shared with us from ArckWiki. There are
# a few additions apart from what has been defined.
#
#=================Flush current definitions==============
iptables -F
ip6tables -F
iptables -X
ip6tables -X
#
#=================Chains=================================
#
#----Define chains for opened ports
iptables -N TCP
ip6tables -N TCP
iptables -N UDP
ip6tables -N UDP
#
#----Setting up the filter table for NAT
# iptables -N fw-interfaces
# ip6tables -N fw-interfaces
# iptables -N fw-open
# ip6tables -N fw-open
#
#================Default Chain reactions=================
#
#----Default FORWARD reaction
iptables -P FORWARD DROP
ip6tables -P FORWARD DROP
#
#----Default OUTPUT reaction
iptables -P OUTPUT ACCEPT
ip6tables -P OUTPUT ACCEPT
#
#----Shellshock
iptables -A INPUT -m string --algo bm --hex-string '|28 29 20 7B|' -j DROP
ip6tables -A INPUT -m string --algo bm --hex-string '|28 29 20 7B|' -j DROP
#
#----Default INPUT reaction
iptables -P INPUT DROP
ip6tables -P INPUT DROP
#
#----Drop spoofing packets
iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -i wlan0 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -i wlan1 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 224.0.0.0/4 -j DROP
iptables -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -s 240.0.0.0/5 -j DROP
iptables -A INPUT -d 240.0.0.0/5 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -d 0.0.0.0/8 -j DROP
iptables -A INPUT -d 239.255.255.0/24 -j DROP
iptables -A INPUT -d 255.255.255.255 -j DROP
#
#================Ping rate limiting globally=============
iptables -A INPUT -p icmp --icmp-type 8 -m limit --limit 30/min --limit-burst 8 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type 8 --match limit --limit-burst 8 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 8 -j DROP
ip6tables -A INPUT -p icmpv6 --icmpv6-type 8 -j DROP
#
#----flooding RST packets, smurf attack Rejection
iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT
#
#----Bogus packet DROP
iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
ip6tables -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
ip6tables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
#
#================RELATED,ESTABLISHED reaction============
iptables -A INPUT --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
ip6tables -A INPUT --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
#
#================unfetered loopback======================
iptables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -i lo -j ACCEPT
#
#================INVALID catagory of packets=============
iptables -A INPUT -p 41 -j ACCEPT
iptables -A INPUT --match conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT --match conntrack --ctstate INVALID -j DROP
#
#================IPv6 reactions and definitions==========
ip6tables -A INPUT -s fe80::/10 -p icmpv6 -j ACCEPT
ip6tables -t raw -A PREROUTING -p icmpv6 -s fe80::/10 -j ACCEPT
ip6tables -t raw -A PREROUTING --match rpfilter -j ACCEPT
ip6tables -t raw -A PREROUTING -j DROP
#
#=======Acceptable INVALIDs and a curteous response======
iptables -A INPUT -p udp --match conntrack --ctstate NEW -j UDP
ip6tables -A INPUT -p udp --match conntrack --ctstate NEW -j UDP
iptables -A INPUT -p tcp --syn --match conntrack --ctstate NEW -j TCP
ip6tables -A INPUT -p tcp --syn --match conntrack --ctstate NEW -j TCP
#
#================Defining the TCP and UDP chains
#
#########################################################
# Notes for port open definitions #
# It is important to note that this should be config- #
# ured differently if you're providing any routing #
# activity for any purpose. it is up to you to actively #
# define what suites your needs to get the job done. #
# In this example, I'm exempting IPv6 from being able #
# to interact with SSH protocols for two reasons. The #
# first is because it is generally easier and more com- #
# for internal networks to be deployed with IPv4. The #
# second reason is, IPv6 can be deployed globally. #
#########################################################
#
#----SSH configured for eth0
iptables -A TCP -i eth0 -p tcp --dport ssh -j ACCEPT
#!---Blocking SSH interactions in IPv6
ip6tables -A TCP -p tcp --dport ssh -j DROP
#!---Leave commented for end service device
# iptables -A TCP -p tcp --dport 80 -j ACCEPT
# ip6tables -A TCP -p tcp --dport 80 -j ACCEPT
# iptables -A TCP -p tcp --dport 443 -j ACCEPT
# ip6tables -A TCP -p tcp --dport 443 -j ACCEPT
#
#!---Uncomment for remote service to this device
# iptables -A TCP -p tcp --dport 22 -j ACCEPT
# ip6tables -A TCP -p tcp --dport 22 -j ACCEPT
#
#!---Uncomment if you're providing routing services
# iptables -A UDP -p udp 53 -j ACCEPT
# ip6tables -A UDP -p udp 53 -j ACCEPT
#
#=================Tricking port scanners=================
#
#----SYN scans
iptables -I TCP -p tcp --match recent --update --seconds 60 --name TCP-PORTSCAN -j DROP
ip6tables -I TCP -p tcp --match recent --update --seconds 60 --name TCP-PORTSCAN -j DROP
iptables -A INPUT -p tcp --match recent --set --name TCP-PORTSCAN -j DROP
ip6tables -A INPUT -p tcp --match recent --set --name TCP-PORTSCAN -j DROP
#
#----UDP scans
iptables -I UDP -p udp --match recent --update --seconds 60 --name UDP-PORTSCAN -j DROP
ip6tables -I UDP -p udp --match recent --update --seconds 60 --name UDP-PORTSCAN -j DROP
iptables -A INPUT -p udp --match recent --set --name UDP-PORTSCAN -j DROP
ip6tables -A INPUT -p udp --match recent --set --name UDP-PORTSCAN -j DROP
#
#----For SMURF attack protection
iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m limit --limit 2/second --limit-burst 2 -j ACCEPT
ip6tables -A INPUT -p icmpv6 -m limit --limit 2/second --limit-burst 2 -j ACCEPT
#
#----Ending all other undefined connections
iptables -A INPUT -j DROP
ip6tables -A INPUT -j DROP
#
#=======Defining the IN_SSH chain for bruteforce of SSH==
#
#!---I've elected to keep IPv6 out of this realm for
#!---ease of use
iptables -N IN_SSH
iptables -A INPUT -p tcp --dport ssh --match conntrack --ctstate NEW -j IN_SSH
iptables -A IN_SSH --match recent --name sshbf --rttl --rcheck --hitcount 3 --seconds 10 -j DROP
iptables -A IN_SSH --match recent --name sshbf --rttl --rcheck --hitcount 4 --seconds 1800 -j DROP
iptables -A IN_SSH --match recent --name sshbf --set -j ACCEPT
iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH
#
#==================Setting up a NAT gateway==============
#
#########################################################
# #
# I commented this half out because it's not something #
# that will apply to all setups. Make note of all par- #
# tinate interfaces and what exactly is going on. #
# #
#########################################################
#
#----Setting up the FORWARD chain
# iptables -A FORWARD --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# ip6tables -A FORWARD --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
#
#
#----Defining the fw-interfaces/open chains for FORWARD
# iptables -A FORWARD -j fw-interfaces
# ip6tables -A FORWARD -j fw-interfaces
# iptables -A FORWARD -j fw-open
# ip6tables -A FORWARD -j fw-open
# iptables -A FORWARD -j DROP # Should be REJECT. But, fuck them
# ip6tables -A FORWARD -j DROP
# iptables -P FORWARD DROP
# ip6tables -P FORWARD DROP
#
#
#----Setting up the nat table
# iptables -A fw-interfaces -i ### -j ACCEPT
# ip6tables -A fw-interfaces -i ### -j ACCEPT
# iptables -t nat -A POSTROUTING -s w.x.y.z/S -o ppp0 -j MASQUERADE
# ip6tables -t nat -A POSTROUTING -s fe::/10 -o ppp0 -j MASQUERADE
#----The above lines should be repeated specifically for EACH interface
#
#----Setting up the PREROUTING chain
#
#######################################################
# #
# The PREROUTING chain will redirect either port #
# targets to be redirected. This can also redirect #
# traffic inbound to your network from the gateway #
# to this machine. This can be useful if you're using #
# a honeypot or have any service within your network #
# that you want to be pointed to a specific device. #
# #
#######################################################
#
#----SSH honeypot server
# iptables -A fw-open -d HONEYPOT_IP -p tcp --dport 22 -j ACCEPT
# ip6tables -A fw-open -d HONEYPOT_IP -p tcp --dport 22 -j ACCEPT
#----With intuition, you can configure the above to also direct specific
#----requests to other devices providing those services. The bellow will
#----be for a squid server
# iptables -A fw-open -d SQUID_IP -p tcp --dport 80 -j ACCEPT
# ip6tables -A fw-open -d SQUID_IP -p tcp --dport 80 -j ACCEPT
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to SQUID_IP
# ip6tables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to SQUID_IP
#
#===============Declare configurations=================
iptables -nvL
ip6tables -nvL