Linuxシステム管理者はiptables
、 netfilter
パケットフィルタリングフレームワークへのユーザーランドインターフェイスに精通していると思います。
さて、この「質問」は、iptables
の知恵のさまざまなビットn個をまとめるためのコミュニティWikiであることを意図しています。あまりにも一般的または不明瞭なものはありません。他の人がiptables
を最大限に活用するのに役立つと思う情報を投稿してください。
ipset
を使用してnetfilterのパフォーマンスを最適化する単なるIP、ポート、またはその両方に基づいて同様のルールのlotを記述する場合は、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の判定を得る前に、最初に何百のルールを通過する必要があります。
もちろん、経験豊富なシステム管理者は、ルールをサブネットごとに分割します。しかし、stillは何百ものルールを意味します。
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ルールをoneルールに置き換えます。
iptables -m set --match-set Allowed_Hosts src -j ACCEPT
パケットが到着すると、netfilterはAllowed_Hosts
IPセットに対してパケットのソース(src)IPの非常に速いビットマップ検索を実行します。 192.168.0.0/16からのすべてのパケットはoneルールを経験します。そして、ビットマップの検索は、何百ものiptablesルールチェックを実行するよりも少なくとも2桁速いと私は信じています。
ipset
はIPアドレスに限定されません。また、ポート、IPポートタプル、ネットワーク/サブネットアドレス、IP-MACタプルなどに基づいて照合することもできます。また、ソースまたは宛先、または両方の組み合わせ(タプルの場合)として、これらの基準に一致できます。
そして最後に、ipset
を使用すると、IPアドレスを自動的にブラックリスト/ホワイトリストに入れることができます。これらのブラックリスト/ホワイトリストは「エージング」することもできるため、構成可能な時間が経過するとIPアドレスが自動的に削除されます。
詳細は ipset
のmanページ を参照してください。
一部のLinuxディストリビューションはnotがipset
をすぐに使用できるようにサポートしている場合があります(たとえば、Ubuntu 10.04にこの問題がありました)。これらのシステムでの1つの方法は、ソースコードからipset
をインストールすることです。
代わりに、ipset
のソースをWebサイトからダウンロードします。 http://ipset.netfilter.org/install.html
または、xtables-addons
を使用する場合、ソースにipset isが含まれます: http://xtables-addons.sourceforge.net/ =
#!/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
ルールにコメントを追加します。
-m comment --comment "Comments help to read output of iptables -nvL"
以下のルールを、できれば-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
ブロックされる攻撃はそれぞれ次のとおりです。
(上記の攻撃の名前を自由に編集してください)
echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
ステップ1はカーネルパラメータを設定してIP転送を許可し、ステップ2はインターフェイスeth0でNATを有効にするiptablesルールを設定します。
(私のiptables_tricks.txtファイルから、多くの場所から再コンパイル:P)
Iptablesに、ポート22(SSH)の同じIPからの新しい接続間で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
FireHOL を使用-便利なiptablesラッパー
直接のiptablesコマンドよりもはるかに直感的です。特に他のファイアウォールでの過去の経験を持つ人々のために:
FireHOLは、任意の数のネットワークインターフェイス、任意の数のルート、任意の数のサービスを提供するLinuxホストおよびルーターで、ステートフルiptablesパケットフィルタリングファイアウォールを生成するiptablesファイアウォールジェネレーターです。式)。
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セットを保存および復元する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用に1セット(_dns4
_)とIPv6用に1セット(_dns6
_)が作成されます。
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セットに新しいエントリを追加することもできます。
たとえば this answer でこの質問に:
_-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
モジュール(IPセットを処理する)からのスイッチを使用していることをset
に認識させます。--match-set ssh_dynblock4 src
_は、iptables
にsource(src
)アドレスを名前付きセット(_ssh_dynblock4
_)と照合するように指示しますSudo ipset test ssh_dynblock4 $IP
_に対応します(_$IP
_にはパケットのソースIPアドレスが含まれます)-j SET --add-set ssh_dynblock4 src --exist
_は、source(src
)アドレスをパケットからIPセット_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セットを照合して操作することを可能にするかどうかです。
そして、その答えは正解です:YES!(残念ながら、これは私が前回チェックしたときに明示的に文書化されていませんでした)
したがって、前のセクションのルールは、次のように書き直すことができます。
_-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
_セットに含まれているセットを使用して、後続の接続試行を他のパケットと同じように受け渡さず、受け渡せるようにする適切なソリューションを追加したいと思います。
以下のiptables
ルールを確認する場合、_ssh_loggedon
_のデフォルトのタイムアウトは90分、_ssh_dynblock
_のデフォルトのタイムアウトは30分であることに注意してください。
_-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セットを区別する必要があります。そうでない場合、ipset
は、IPの代わりに別のsetをセットのセットに追加することを想定しています。そしてもちろん、IPにちなんで名付けられたセットが存在することはまずありません:)
そのため、IPアドレスで_:
_をチェックし、そのような場合はセット名に_6
_を追加し、そうでない場合は_4
_を追加します。
終わり。
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
初心者にとっては良いスタートになります。
Iptablesの設定に使用できる別のGUIは Firewall Builder です。ルール要素をデータベース内のオブジェクトとして作成し、これらのオブジェクトをルールエディターにドラッグアンドドロップして、目的のファイアウォールポリシーを作成できます。次に、アプリケーションは、ルールの実装に必要なすべてのiptablesコマンドを含むスクリプトファイルを生成します。
一度に1つのiptables構成しか管理できない他のいくつかのiptables GUIソリューションとは異なり、Firewall Builderでは、単一のアプリケーションから多数のiptables構成をすべて管理できます。 Firewall BuilderはLinux、Windows、Mac OS Xで動作し、10年以上使用されており、世界中に何千人ものアクティブユーザーがいます。
完全な開示-私は、ファイアウォールビルダーを開発している会社であるNetCitadelの共同創設者です。
例:eth0
andeth1
があり、それらの間のトラフィックを許可しますか?
iptables -A FORWARD -i eth+ -o eth+ -j ACCEPT
LXCによって動的に作成されて名前が付けられたveth<something>
インターフェースに一致させるために、これを過去に使用しました。したがって、veth+
と一度にすべてを照合できます。
また、_<something>
と照合するために、意図的にいくつかのインターフェイスに_+
と名前を付けました。
IPセットを使用して、すべての個別のIPアドレスを発信帯域幅割り当てに制限する
おそらくISPで測定された帯域幅割り当てに対して、帯域幅使用攻撃を反映または回避するために、毎月の帯域幅使用の個々のIP 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
これにより、ユーザーがWebサーバーから長期間にわたって大きなファイルを要求したり、サービスからサービスを要求したりするなどの攻撃を防ぐことができます。 INPUTチェーンについても同じことができます。
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
iptables -t mangle -A PREROUTING -p tcp \
-m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
このターゲットの目的は、SYNパケットを送信したホストが接続を確立したか、またはSYN接続を開始した後に何もしないかを確認することです。何もしない場合は、最小限の労力でパケットを破棄します。
生パケットの接続追跡テーブルに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ターゲット
Ipsetsとtcpフラグに関するコメントに同意しますが、まだ多くの点が不足しています。
国リストには、ipsetsの代わりにxtables-addons geoip matchを使用します。 geoipデータを定期的に(少なくとも月に1回)更新します。データは、ファイアアンドフォーゲットのipsetリストよりも動的です。
Tcpフラグを使用した接続状態の追跡を検討してください。たとえば、tcp RSTまたはACKは、確立された接続に対してのみ意味があります。 SYNは、新規および関連する接続に対してのみ意味があります。確立された接続のSYNは、SYN + ACKが失われたか、ハッキングの試みが行われたことを意味し、接続の両側が状態について合意していないため、リセットする必要があります。
なし、SYN + RSTおよびFIN + RSTは無効な組み合わせですが、SYN + FINは特にTCP fast-open(TCPオプション34)の下で有効です。特にDNSの場合、SYNパケットは高速-open、フラグメント化しないでください。PSHフラグとURGフラグのあるルールは役に立たないと思います。接続追跡状態とTCP状態)を混同しないでください:SYNパケットへのRST応答は追跡の目的で確立されました。
SYNPROXYは転送されたパケット用で、syncookieのサポートを超えてローカルに配信されたパケットには何も追加しません。
ICMPエラーパケットは、有効な場合、常に関連する状態で、長さが48:576になります。 IPv6の場合、長さ84:1280。他のすべては無視されるべきです。それらの最大サイズは最小MTUでもあるため、決してフラグメント化しないでください。 ICMP要求(ping、タイムスタンプなど)は常に新しく、応答が確立されます。他の状態のICMPパケットをドロップします。
最近のリストを使用し、後続のSYNパケットのみを受け入れるSSHの例のように、SMTPでも同じことが行われ、IPアドレスデータムのみの「グレーリスト」に似ています。
フィルターテーブルでは、入力チェーンと出力チェーンの最初の(確立された状態のパケットを最初に受け入れる場合は2番目の)ルールがループバックインターフェイスのすべてを受け入れる必要があります。自分の内部パケットを信頼する必要があります。できない場合は、ファイアウォールソリューションを超える大きな問題があります。
最後に、ルールの内容をよく理解していない限り、ルールを盲目的にコピーしないでください。多くの類似したルールのリストがそれを行っており、ほとんどの場合、結果は笑えるものです。