「シンプルなステートフルファイアウォール」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
 
(→‎IPv6: 翻訳)
 
(4人の利用者による、間の18版が非表示)
3行目: 3行目:
 
[[es:Simple stateful firewall]]
 
[[es:Simple stateful firewall]]
 
[[ru:Simple stateful firewall]]
 
[[ru:Simple stateful firewall]]
  +
[[zh-hans:Simple stateful firewall]]
 
{{Related articles start}}
 
{{Related articles start}}
{{Related3|Internet sharing|インターネット共有}}
 
{{Related3|Router|ルーター}}
 
 
{{Related|ファイアウォール}}
 
{{Related|ファイアウォール}}
  +
{{Related|インターネット共有}}
  +
{{Related|Nftables#シンプルなステートフルファイアウォール}}
  +
{{Related|ルーター}}
 
{{Related|Uncomplicated Firewall}}
 
{{Related|Uncomplicated Firewall}}
 
{{Related articles end}}
 
{{Related articles end}}
 
このページでは [[iptables]] を使ってステートフルファイアウォールを設定する方法を説明します。また、ルールの意味と理由の説明も行います。シンプルに説明するため、大きく2つのセクションにページは分かれています。最初のセクションではシングルマシンのためのファイアウォールを扱い、2番目のセクションでは最初のセクションのファイアウォールに加えて NAT ゲートウェイを設定します。
 
このページでは [[iptables]] を使ってステートフルファイアウォールを設定する方法を説明します。また、ルールの意味と理由の説明も行います。シンプルに説明するため、大きく2つのセクションにページは分かれています。最初のセクションではシングルマシンのためのファイアウォールを扱い、2番目のセクションでは最初のセクションのファイアウォールに加えて NAT ゲートウェイを設定します。
   
{{Warning|記述されているルールは順番通りに実行してください。リモートマシンにログインしている場合、ルールを設定している間にマシンから閉めだされてしまう可能性があります。以下の手順に従うのはローカルでログインしている場合に限ります。[[#Example iptables.rules file|サンプル設定ファイル]]を使うことでこの問題を回避することが可能です。}}
+
{{Warning|記述されているルールは順番通りに実行してください。リモートマシンにログインしている場合、ルールを設定している間にマシンから閉めだされてしまう可能性があります。以下の手順に従うのはローカルでログインしている場合に限ります。[[#iptables.rules のサンプルファイル|サンプル設定ファイル]]を使うことでこの問題を回避することが可能です。}}
   
 
== 前提要件 ==
 
== 前提要件 ==
   
  +
{{Note|iptables のサポートを有効にしてカーネルがコンパイルされている必要があります。Arch Linux の標準カーネルには iptables のサポートが含まれています。}}
{{Note|Your kernel needs to be compiled with iptables support. All stock Arch Linux kernels have iptables support.}}
 
   
  +
まず、ユーザーランドユーティリティ {{Pkg|iptables}} をインストールしてください。もしくは既にインストール済みかどうか確認してください。
First, install the userland utilities {{Pkg|iptables}} or verify that they are already installed.
 
   
  +
この記事では iptables のルールセットが全く存在しないことを前提としています。現在のルールセットをチェックして、ルールが存在しないことを確認するには、次を実行:
This article assumes that there are currently no iptables rules set. To check the current ruleset and verify that there are currently no rules run the following:
 
   
 
{{hc|# iptables-save|<nowiki>
 
{{hc|# iptables-save|<nowiki>
31行目: 33行目:
 
</nowiki>}}
 
</nowiki>}}
   
  +
もしくは
or
 
   
 
{{hc|# iptables -nvL --line-numbers|<nowiki>
 
{{hc|# iptables -nvL --line-numbers|<nowiki>
44行目: 46行目:
 
</nowiki>}}
 
</nowiki>}}
   
  +
ルールが存在する場合、デフォルトのルールセットをロードすることでルールをリセットすることが可能です:
If there are rules, you may be able to reset the rules by loading a default rule set:
 
   
 
# iptables-restore < /etc/iptables/empty.rules
 
# iptables-restore < /etc/iptables/empty.rules
   
  +
もしくは、[[Iptables#ルールをリセットする]] を参照。
Otherwise, see [[Iptables#Resetting_rules]].
 
   
  +
== シングルマシン用のファイアウォール ==
== Firewall for a single machine ==
 
   
  +
{{Note|iptables はチェインの上から下の順番でルールを処理していくため、よくヒットするルールをチェインの初めに置くことを推奨します。もちろん、実行されるロジックによって制約は出て来ます。また、ルールにはランタイムコストもあるため、バイト/パケット数のカウンタだけを見てルールの順番を並び替えるのは賢いとは言えません。}}
{{Note|Because iptables processes rules in linear order, from top to bottom within a chain, it is advised to put frequently-hit rules near the start of the chain. Of course there is a limit, depending on the logic that is being implemented. Also, rules have an associated runtime cost, so rules should not be reordered solely based upon empirical observations of the byte/packet counters.}}
 
   
=== Creating necessary chains ===
+
=== 必要なチェインの作成 ===
   
  +
基本的なセットアップとして、2つのユーザー定義チェインを作成し、それを使ってファイアウォールのポートを開きます。
For this basic setup, we will create two user-defined chains that we will use to open up ports in the firewall.
 
   
 
# iptables -N TCP
 
# iptables -N TCP
 
# iptables -N UDP
 
# iptables -N UDP
   
  +
もちろんチェインの名前は何でもかまいません。ここでは後のルールで使用するプロトコルに沿うように名前を決めています。
The chains can of course have arbitrary names. We pick these just to match the protocols we want handle with them in the later rules, which are specified with the protocol options, e.g. {{ic|-p tcp}}, always.
 
   
=== The FORWARD chain ===
+
=== FORWARD チェイン ===
   
  +
マシンを NAT ゲートウェイとしてセットアップしたい場合、[[#NAT ゲートウェイの設定]]を見て下さい。シングルマシンの場合、'''FORWARD''' チェインのポリシーをとりあえず '''DROP''' に設定して先に進みます:
If you want to set up your machine as a NAT gateway, please look at [[#Setting up a NAT gateway]]. For a single machine, however, we simply set the policy of the '''FORWARD''' chain to '''DROP''' and move on:
 
   
 
# iptables -P FORWARD DROP
 
# iptables -P FORWARD DROP
   
=== The OUTPUT chain ===
+
=== OUTPUT チェイン ===
   
  +
送信トラフィックはフィルタリングしません。セットアップがとても複雑になってしまい、いろいろと考える必要が出てくるからです。ここではシンプルに、'''OUTPUT''' ポリシーを '''ACCEPT''' に設定します。
We have no intention of filtering any outgoing traffic, as this would make the setup much more complicated and would require some extra thought. In this simple case, we set the '''OUTPUT''' policy to '''ACCEPT'''.
 
   
 
# iptables -P OUTPUT ACCEPT
 
# iptables -P OUTPUT ACCEPT
   
=== The INPUT chain ===
+
=== INPUT チェイン ===
   
  +
上記のチェインと同じように、勝手にルールを通過してしまわないように '''INPUT''' チェインのデフォルトポリシーは '''DROP''' に設定します。セキュアなファイアウォールを設定するときは、全てのトラフィックをドロップしてから、許可するトラフィックを指定するのがベストです。
Similar to the previous chains, we set the default policy for the '''INPUT''' chain to '''DROP''' in case something somehow slips by our rules. Dropping all traffic and specifying what is allowed is the best way to make a secure firewall.
 
   
  +
{{Warning|SSH でログインしている場合、以下の設定をすると SSH セッションが即座に切断されます。切断されないようにするには: (1) 下の INPUT チェインのルールを先に追加 (それでセッションが開いたままになります), (2) インバウンド SSH を許可するルールを追加 (接続が終了した場合に再接続できるようにするため) (3) ポリシーを設定。}}
{{Warning|If you are logged in via SSH, the following will immediately disconnect the SSH session. To avoid it: (1) add the first INPUT chain rule below (it will keep the session open), (2) add a regular rule to allow inbound SSH (to be able to reconnect in case of a connection drop) and (3) set the policy.}}
 
   
 
# iptables -P INPUT DROP
 
# iptables -P INPUT DROP
   
  +
あらゆるネットワークインターフェイスから受信されたパケットは全て '''INPUT''' チェインをまず通過します (パケットの送信先が対象のマシンになっている場合)。このチェインの中では、問題ないと思われるパケットだけを許可するようにします。
Every packet that is received by any network interface will pass the '''INPUT''' chain first, if it is destined for this machine. In this chain, we make sure that only the packets that we want are accepted.
 
   
  +
INPUT チェインにはまず、確立済みの接続に属するトラフィックや、ICMP エラーまたはエコー応答 (ping されたときにホストが返すパケット) などの接続に関連する正当なトラフィックを許可するルールを追加します。'''ICMP''' は '''Internet Control Message Protocol''' の略です。ICMP メッセージは輻輳制御や MTU にとても重要なので、このルールによって通してやります。
The first rule added to the INPUT chain will allow traffic that belongs to established connections, or new valid traffic that is related to these connections such as ICMP errors, or echo replies (the packets a host returns when pinged). '''ICMP''' stands for '''Internet Control Message Protocol'''. Some ICMP messages are very important and help to manage congestion and MTU, and are accepted by this rule.
 
   
  +
接続ステート {{ic|ESTABLISHED}} は最初の ({{ic|--ctstate NEW}}) 接続試行で許可された以前の他のルール、またはルールの設定時にアクティブになっていた接続 (例えばアクティブな SSH リモート接続) を示します:
The connection state {{ic|ESTABLISHED}} implies that either another rule previously allowed the initial ({{ic|--ctstate NEW}}) connection attempt or the connection was already active (for example an active remote SSH connection) when setting the rule:
 
   
 
# iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 
# iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
   
  +
次のルールでは "loopback" (lo) インターフェイスからのトラフィックを全て許可します。多くのアプリケーションやサービスで必須となります。
The second rule will accept all traffic from the "loopback" (lo) interface, which is necessary for many applications and services.
 
   
  +
{{Note|ファイアウォールでトラフィックを規制したくない場合 "eth1" など信頼できるインターフェイスを追加することもできます。ただし、ネットワーク上のあらゆる場所 (例えばルーターなど) からのあらゆるトラフィックを転送する NAT 構成にしている場合、他の設定は無関係になるため注意してください。}}
{{Note|You can add more trusted interfaces here such as "eth1" if you do not want/need the traffic filtered by the firewall, but be warned that if you have a NAT setup that redirects any kind of traffic to this interface from anywhere else in the network (let's say a router), it'll get through, regardless of any other settings you may have.}}
 
   
 
# iptables -A INPUT -i lo -j ACCEPT
 
# iptables -A INPUT -i lo -j ACCEPT
   
  +
3番目のルールでは "INVALID" ステートに一致する全てのトラフィックを破棄します。トラフィックは4つの "state" カテゴリに分けることができます: NEW, ESTABLISHED, RELATED, INVALID。これによって "stateless" ファイアウォールではなく "stateful" ファイアウォールと呼称しています。ステートは "nf_conntrack_*" カーネルモジュールによって追跡されます。カーネルモジュールはルールを追加したときにカーネルによって自動的にロードされます。
The third rule will drop all traffic with an "INVALID" state match. Traffic can fall into four "state" categories: NEW, ESTABLISHED, RELATED or INVALID and this is what makes this a "stateful" firewall rather than a less secure "stateless" one. States are tracked using the "nf_conntrack_*" kernel modules which are loaded automatically by the kernel as you add rules.
 
   
 
{{Note|
 
{{Note|
  +
* 以下のルールはヘッダーやチェック、TCP フラグがおかしいパケットや不適切な ICMP メッセージ (ホストに何も送信していないのにポート到達不可など)、シーケンス番号予測攻撃などによるシーケンス外のパケットを全て破棄します。"DROP" ターゲットは何も返答せずにパケットを破棄します。それに対して REJECT は礼儀正しくパケットを拒否します。INVALID なパケットに対する適切な "REJECT" レスポンスはありえないため、パケットを受信したことを誰にも分からないように DROP を使っています。
* This rule will drop all packets with invalid headers or checksums, invalid TCP flags, invalid ICMP messages (such as a port unreachable when we did not send anything to the host), and out of sequence packets which can be caused by sequence prediction or other similar attacks. The "DROP" target will drop a packet without any response, contrary to REJECT which politely refuses the packet. We use DROP because there is no proper "REJECT" response to packets that are INVALID, and we do not want to acknowledge that we received these packets.
 
* ICMPv6 Neighbor Discovery packets remain untracked, and will always be classified "INVALID" though they are not corrupted or the like. Keep this in mind, and accept them before this rule! iptables -A INPUT -p 41 -j ACCEPT
+
* ICMPv6 近隣探索パケットは未追跡のまま、たとえ壊れていなくても常に "INVALID" に分類されます。次のコマンドで承認することができます: {{ic|iptables -A INPUT -p 41 -j ACCEPT}}。
 
}}
 
}}
   
 
# iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
 
# iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
   
  +
次のルールでは '''ICMP エコー要求''' (ping) を全て許可します。最初のパケットだけを NEW としてカウントし、後は全て RELATED,ESTABLISHED ルールで処理します。コンピュータはルーターではないので、他の ICMP トラフィックをステート NEW で許可する必要はありません。
The next rule will accept all new incoming '''ICMP echo requests''', also known as pings. Only the first packet will count as NEW, the rest will be handled by the RELATED,ESTABLISHED rule. Since the computer is not a router, no other ICMP traffic with state NEW needs to be allowed.
 
   
 
# iptables -A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
 
# iptables -A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
   
  +
新しい接続を処理するために、INPUT チェインに TCP チェインと UDP チェインを適用します。いったん TCP チェインや UDP チェインで接続が許可されると、以降は
Now we attach the TCP and UDP chains to the INPUT chain to handle all new incoming connections. Once a connection is accepted by either TCP or UDP chain, it is handled by the RELATED/ESTABLISHED traffic rule. The TCP and UDP chains will either accept new incoming connections, or politely reject them. New TCP connections must be started with SYN packets.
 
  +
RELATED/ESTABLISHED のルールで処理されます。TCP チェインと UDP チェインはどちらも新しい接続を許可するか、または丁寧にそれらを REJECT します。新しい TCP 接続は必ず SYN
  +
パケットから始まります。
   
  +
{{Note|SYN ビットが設定されていない NEW は INVALID ステートに含まれない唯一の不正な TCP フラグです。悪意のあるパケットである可能性がほとんどないため、破棄せずに、次のルールで TCP RESET を使って拒否するようにします。}}
{{Note| NEW but not SYN is the only invalid TCP flag not covered by the INVALID state. The reason is because they are rarely malicious packets, and they should not just be dropped. Instead, we simply do not accept them, so they are rejected with a TCP RST by the next rule.}}
 
   
 
# iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
 
# iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
 
# iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
 
# iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
   
  +
ポートを開いていない場合、TCP 接続は TCP RESET パケットで、UDP ストリームは ICMP port unreachable メッセージで拒否します。デフォルトの Linux の挙動と同じであるため (RFC 準拠)、送信者はすみやかに接続を閉じることができます。
We reject TCP connections with TCP RST packets and UDP streams with ICMP port unreachable messages if the ports are not opened. This imitates default Linux behavior (RFC compliant), and it allows the sender to quickly close the connection and clean up.
 
   
 
# iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
 
# iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
# iptables -A INPUT -p tcp -j REJECT --reject-with tcp-rst
+
# iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
   
  +
他のプロトコルのために、icmp protocol unreachable メッセージで残りの受信トラフィックを拒否する最終ルールを INPUT チェインに追加します。Linux のデフォルトの挙動を真似ています。
For other protocols, we add a final rule to the INPUT chain to reject all remaining incoming traffic with icmp protocol unreachable messages. This imitates Linux's default behavior.
 
   
 
# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable
 
# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable
   
=== Example iptables.rules file===
+
=== iptables.rules のサンプルファイル ===
   
  +
上記のコマンドを全て実行した時に作成される {{ic|iptables.rules}} ファイルの例:
Example of {{ic|iptables.rules}} file after running all the commands from above:
 
   
 
{{hc|/etc/iptables/iptables.rules|
 
{{hc|/etc/iptables/iptables.rules|
151行目: 155行目:
 
}}
 
}}
   
  +
このファイルは次のコマンドで生成できます:
This file can be generated with:
 
   
 
# iptables-save > /etc/iptables/iptables.rules
 
# iptables-save > /etc/iptables/iptables.rules
   
  +
生成したファイルは下のセクションで使うことができます。SSH 経由でリモートからファイアウォールを設定する場合、先に進む前に新しい SSH 接続を許可するため以下のルールを追加してください (ポート番号は必要に応じて変更してください):
and can be used to continue with the following sections. If you are setting up the firewall remotely via SSH, append the following rule to allow new SSH connections before continuing (adjust port as required):
 
   
 
-A TCP -p tcp --dport 22 -j ACCEPT
 
-A TCP -p tcp --dport 22 -j ACCEPT
   
=== The TCP and UDP chains ===
+
=== TCP UDP チェイン ===
   
  +
TCP と UDP チェインには特定のポートで新規接続の TCP 接続と UDP ストリームを許可するルールを作成します。
The TCP and UDP chains contain rules for accepting new incoming TCP connections and UDP streams to specific ports.
 
   
  +
{{Note|リモートからアクセスする SSH や HTTP などのサービスの接続を許可するためのルールを追加する必要があります。}}
{{Note|This is where you need to add rules to accept incoming connections, such as SSH, HTTP or other services that you want to access remotely.}}
 
   
==== Opening ports to incoming connections ====
+
==== 接続要求でポートを開く ====
   
  +
ウェブサーバーへの TCP 接続を許可するには (ポート 80):
To accept incoming TCP connections on port 80 for a web server:
 
   
 
# iptables -A TCP -p tcp --dport 80 -j ACCEPT
 
# iptables -A TCP -p tcp --dport 80 -j ACCEPT
   
  +
ウェブサーバーへの TCP 接続 (HTTPS) を許可するには (ポート 443):
To accept incoming TCP connections on port 443 for a web server (HTTPS):
 
   
 
# iptables -A TCP -p tcp --dport 443 -j ACCEPT
 
# iptables -A TCP -p tcp --dport 443 -j ACCEPT
   
  +
SSH のリモート接続を許可するには (ポート 22):
To allow remote SSH connections (on port 22):
 
   
 
# iptables -A TCP -p tcp --dport 22 -j ACCEPT
 
# iptables -A TCP -p tcp --dport 22 -j ACCEPT
   
  +
DNS サーバーへの TCP/UDP リクエストを許可するには (ポート 53):
To accept incoming UDP streams on port 53 for a DNS server:
 
   
  +
# iptables -A TCP -p tcp --dport 53 -j ACCEPT
 
# iptables -A UDP -p udp --dport 53 -j ACCEPT
 
# iptables -A UDP -p udp --dport 53 -j ACCEPT
   
  +
複数のポートにマッチするような、高度なルールについては {{man|8|iptables}} を見て下さい。
See {{Ic|man iptables}} for more advanced rules, like matching multiple ports.
 
   
==== Port knocking ====
+
==== ポートノッキング ====
  +
デフォルトではファイアウォールによって閉じられているポートを、外部から開く方法がポートノッキングです。予め決めておいたポートに連続して接続試行することで行います。正しいポート"ノック" (接続試行) がなされた場合、ファイアウォールは特定のポートを開いて接続できるようにします。詳しくは[[ポートノッキング]]を見て下さい。
Port knocking is a method to externally open ports that, by default, the firewall keeps closed. It works by requiring connection attempts to a series of predefined closed ports. When the correct sequence of port "knocks" (connection attempts) is received, the firewall opens certain port(s) to allow a connection. See [[Port Knocking]] for more information.
 
   
  +
=== なりすまし攻撃からの防護 ===
=== Protection against spoofing attacks ===
 
   
{{Note|{{ic|rp_filter}} is currently set to {{ic|1}} by default in {{ic|/usr/lib/sysctl.d/50-default.conf}}, so the following step is not necessary.}}
+
{{Note|現在 {{ic|rp_filter}} はデフォルトで {{ic|/usr/lib/sysctl.d/50-default.conf}} {{ic|1}} に設定されているため、以下の手順は必要ありません。}}
   
  +
インターネットやローカルネットワークからの予約ローカルアドレスの使用は sysctl で {{Ic|rp_filter}} (Reverse Path Filter) を 1 に設定することでブロックされます。以下の行を {{Ic|/etc/sysctl.d/90-firewall.conf}} ファイルに追加することで Linux カーネルに組み込まれている送信元アドレス検証が有効になります (詳しくは [[sysctl]] を参照)。カーネルによる検証は個別の iptables ルールよりもなりすましを上手く処理します:
Blocking reserved local addresses incoming from the internet or local network is normally done through setting {{Ic|rp_filter}} (Reverse Path Filter) in sysctl to 1. To do so, add the following line to your {{Ic|/etc/sysctl.d/90-firewall.conf}} file (see [[sysctl]] for details) to enable source address verification which is built into Linux kernel itself. The verification by the kernel will handle spoofing better than individual iptables rules for each case.
 
   
 
net.ipv4.conf.all.rp_filter=1
 
net.ipv4.conf.all.rp_filter=1
   
  +
統計が必要な場合、netfilter で設定することもできます:
Only when asynchronous routing or {{ic|1=rp_filter=0}} is used, extra checks are necessary:
 
   
# iptables -I INPUT ! -i lo -s 127.0.0.0/8 -j DROP
+
# iptables -t raw -I PREROUTING -m rpfilter --invert -j DROP
   
  +
{{Note|両方を有効にする意味はありません。netfilter の方法のほうが新しく IPv6 でも機能します。}}
=== "Hide" your computer ===
 
   
  +
非同期ルーティングを使用する構成の場合、代わりに {{ic|1=rp_filter=2}} sysctl オプションを使用する必要があります。{{ic|--loose}} スイッチを {{ic|rpfilter}} モジュールに渡すことで netfilter と同じ設定ができます。
If you are running a desktop machine, it might be a good idea to block some incoming requests.
 
   
  +
=== コンピュータを"隠匿"する ===
==== Block ping request ====
 
   
  +
デスクトップマシンとして使っている場合、特定の接続要求はブロックするのが好ましいでしょう。
A 'Ping' request is an ICMP packet sent to the destination address to ensure connectivity between the devices. If your network works well, you can safely block all ping requests. It is important to note that this ''does not'' actually hide your computer — any packet sent to you is rejected, so you will still show up in a simple nmap "ping scan" of an IP range.
 
   
  +
==== ping リクエストのブロック ====
This is rudimentary "protection" and makes life difficult when debugging issues in the future. You should only do this for education purposes.
 
   
  +
'Ping' リクエストはデバイス間の通信状態を確認するために送信先アドレスに送られる ICMP パケットです。ネットワークが問題ないようでしたら、ping リクエストは全てブロックしてもかまいません。リクエストをブロックするだけではコンピュータを隠匿することにはならないので注意してください。たとえコンピュータに送られた全てのパケットを拒否したとしても、シンプルな nmap による IP 範囲の "ping スキャン" で露顕してしまいます。
To block echo requests, add the following line to your {{Ic|/etc/sysctl.d/90-firewall.conf}} file (see [[sysctl]] for details):
 
   
  +
ブロックは初歩的な"防護"であり、将来問題が起こった時にデバッグするのが困難になります。あくまで勉強用にやってみるくらいにしてください。
net.ipv4.icmp_echo_ignore_all = 1
 
   
  +
エコー要求をブロックするには、次の行を {{Ic|/etc/sysctl.d/90-firewall.conf}} ファイルに追加してください (詳しくは [[sysctl]] を参照):
Rate-limiting is a better way to control possible abuse. This first method implements a global limit (ie, only X packets per minute for all source addresses):
 
   
  +
net.ipv4.icmp_echo_ignore_all = 1
# iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 30/min --limit-burst 8 -j ACCEPT
 
# iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
 
   
  +
詳しくは iptables の man ページや http://www.snowman.net/projects/ipt_recent/ のドキュメントやサンプルを読んでください。
Or using the 'recent' module, you can impose a limit per source address:
 
   
  +
==== ポートスキャナを騙す ====
# iptables -A INPUT -p icmp --icmp-type echo-request -m recent --name ping_limiter --set
 
# iptables -A INPUT -p icmp --icmp-type echo-request -m recent --name ping_limiter --update --hitcount 6 --seconds 4 -j DROP
 
# iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
 
   
  +
{{Note|
If you choose to use either the rate limiting or the source limiting rules the PING rule that already exists in the INPUT chain needs to be deleted. This can be done as shown below, or alternatively don't use it in the first place.
 
  +
* 以下の設定は [[Wikipedia:ja:DoS攻撃|DoS]] 攻撃に悪用される可能性があります。偽装した IP でパケットを送信してサービスへの接続をブロックさせてしまうという攻撃が考えられます。
# iptables -D INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
 
  +
* conntrack モジュールによってパケットが INVALID と認識され正当な IP アドレスがブロックされる可能性もあります。ブラックリスト化を防ぐには、特定の宛先ポートへのパケットを全て許可してください。}}
   
  +
攻撃者はポートスキャンを使ってコンピュータの開いているポートを確認します。ポートスキャンによって攻撃者は稼働しているサービスを調査することができ、場合によってはサービスの脆弱性を利用してくる可能性があります。
Next you need to decide where you wish to place the rate limiting or source limiting rules. If you place the rules below the RELATED,ESTABLISHED rule then you will be counting and limiting new ping connections, not each ping sent to your machine. If you place them before the RELATED,ESTABLISHED rule then these rules will count and limit each ping sent to your machine, not each ping connection made.
 
   
  +
INVALID ステートルールは UDP, ACK, SYN スキャン以外の全てのポートスキャンを処理します (nmap ではそれぞれ -sU, -sA, -sS)。
More information is in the iptables man page, or reading the docs and examples on the webpage http://snowman.net/projects/ipt_recent/
 
   
  +
''ACK スキャン''は開いているポートを確認するのには使われませんが、ファイアウォールによってフィルタリングされているポートを識別するのには使われます。NEW ステートの TCP 接続は全て SYN チェックするため、ACK スキャンによって送信されたパケットは全て TCP RESET パケットで拒否されます。一部のファイアウォールはパケットを破棄するため、攻撃者はファイアウォールのルールを暴き出すことができます。
==== Tricking port scanners ====
 
   
  +
recent モジュールを使うことで他の2種類のポートスキャンを騙すことができます。recent モジュールでホストを "recent" リストに追加して、特定の種類の攻撃を停止させます。現在の recent リストは {{Ic|/proc/net/xt_recent/}} で確認できます。
{{Note|This opens you up to a form of [[Wikipedia:Denial-of-service attack|DoS]]. An attack can send packets with spoofed IPs and get them blocked from connecting to your services.}}
 
   
  +
===== SYN スキャン =====
Port scans are used by attackers to identify open ports on your computer. This allows them to identify and fingerprint your running services and possibly launch exploits against them.
 
   
  +
SYN スキャンでは、ポートスキャナは全てのポートに TCP 接続を開始する SYN (synchronization) パケットを送信します。閉じられているポートは TCP RESET パケットを返しますが、厳格なファイアウォールはパケットを破棄します。開いているポートは、ファイアウォールがあるかどうかに関わらず、SYN ACK パケットを返します。
The INVALID state rule will take care of every type of port scan except UDP, ACK and SYN scans (-sU, -sA and -sS in nmap respectively).
 
   
  +
{{ic|recent}} モジュールを使うことで接続を拒否されたホストの記録をつけることができ、開いているポートに SYN パケットが送信されたときにポートが閉じているかのように TCP RESET を返すことが可能です。開かれているポートが最初にスキャンされた場合、SYN ACK が返されてしまうため、確実にポートを隠匿するには標準以外のポートを ssh などのアプリケーションで使用する必要があります。
''ACK scans'' are not used to identify open ports, but to identify ports filtered by a firewall. Due to the SYN check for all TCP connections with the state NEW, every single packet sent by an ACK scan will be correctly rejected by a TCP RST packet. Some firewalls drop these packets instead, and this allows an attacker to map out the firewall rules.
 
   
  +
まず、TCP チェインの一番上にルールを追加します。以下のルールは過去60秒以内に {{ic|TCP-PORTSCAN}} リストに入ったホストに対して TCP RESET で応答します。{{Ic|--update}} スイッチで recent リストが更新され、60秒のカウンターがリセットされます。
The recent module can be used to trick the remaining two types of port scans. The recent module is used to add hosts to a "recent" list which can be used to fingerprint and stop certain types of attacks. Current recent lists can be viewed in {{Ic|/proc/net/xt_recent/}}.
 
   
  +
# iptables -I TCP -p tcp -m recent --update --rsource --seconds 60 --name TCP-PORTSCAN -j REJECT --reject-with tcp-reset
===== SYN scans =====
 
   
  +
そして TCP パケットを拒否するルールを修正して拒否されたパケットを送信したホストを {{ic|TCP-PORTSCAN}} リストに追加するようにしてください:
In a SYN scan, the port scanner sends SYN packet to every port. Closed ports return a TCP RST packet, or get dropped by a strict firewall. Open ports return a SYN ACK packet regardless of the presence of a firewall.
 
   
  +
# iptables -D INPUT -p tcp -j REJECT --reject-with tcp-reset
The recent module can be used to keep track of hosts with rejected connection attempts and return a TCP RST for any SYN packet they send to open ports as if the port was closed. If an open port is the first to be scanned, a SYN ACK will still be returned, so running applications such as ssh on non-standard ports is required for this to work consistently.
 
  +
# iptables -A INPUT -p tcp -m recent --set --rsource --name TCP-PORTSCAN -j REJECT --reject-with tcp-reset
   
  +
===== UDP スキャン =====
First, insert a rule at the top of the TCP chain. This rule responds with a TCP RST to any host that got onto the TCP-PORTSCAN list in the past sixty seconds. The {{Ic|--update}} switch causes the recent list to be updated, meaning the 60 second counter is reset.
 
   
  +
UDP ポートスキャンは TCP の SYN スキャンと似ていますが UDP は "connectionless" プロトコルです。ハンドシェイクや ACK は存在しません。代わりに、スキャナは各 UDP ポートに UDP パケットを送信します。ポートが閉じていると ICMP のポート到達不可メッセージが返ってきますが、ポートが開いている場合、何も返答が返ってきません。UDP は "reliable" プロトコルではないので、パケットが消失したかどうか知る手段がスキャナにはなく、返答がないポートを何度も確認する必要があります。
# iptables -I TCP -p tcp -m recent --update --seconds 60 --name TCP-PORTSCAN -j REJECT --reject-with tcp-rst
 
   
  +
Linux カーネルは ICMP ポートの到達不可メッセージを非常にゆっくりと送信するため、Linux マシンに対して完全な UDP スキャンをかけようとすると10時間以上かかります。それでも、一般的なポートは識別できるため、SYN スキャンに対してと同じ対抗策を UDP スキャンに対しても設定すると良いでしょう。
Next, the rule for rejecting TCP packets need to be modified to add hosts with rejected packets to the TCP-PORTSCAN list.
 
   
  +
まず {{ic|UDP-PORTSCAN}} リストのホストからのパケットを拒否するルールを UDP チェインの一番上に追加してください:
# iptables -D INPUT -p tcp -j REJECT --reject-with tcp-rst
 
# iptables -A INPUT -p tcp -m recent --set --name TCP-PORTSCAN -j REJECT --reject-with tcp-rst
 
   
  +
# iptables -I UDP -p udp -m recent --update --rsource --seconds 60 --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
===== UDP scans =====
 
   
  +
そして、UDP の拒否パケットルールを以下のように修正します:
UDP port scans are similar to TCP SYN scans except that UDP is a "connectionless" protocol. There are no handshakes or acknowledgements. Instead, the scanner sends UDP packets to each UDP port. Closed ports should return ICMP port unreachable messages, and open ports do not return a response. Since UDP is not a "reliable" protocol, the scanner has no way of knowing if packets were lost, and has to do multiple checks for each port that does not return a response.
 
 
The Linux kernel sends out ICMP port unreachable messages very slowly, so a full UDP scan against a Linux machine would take over 10 hours. However, common ports could still be identified, so applying the same countermeasures against UDP scans as SYN scans is a good idea.
 
 
First, add a rule to reject packets from hosts on the UDP-PORTSCAN list to the top of the UDP chain.
 
 
# iptables -I UDP -p udp -m recent --update --seconds 60 --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
 
 
Next, modify the reject packets rule for UDP:
 
   
 
# iptables -D INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
 
# iptables -D INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
# iptables -A INPUT -p udp -m recent --set --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
+
# iptables -A INPUT -p udp -m recent --set --rsource --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
   
===== Restore the Final Rule =====
+
===== 最終ルールのリストア =====
   
  +
上記のポートスキャンに対抗するテクニックを使用した場合、デフォルトの最終ルールが INPUT チェインの最後のルールではなくなります。最後のルールにしないとポートスキャン対策のルールが遮断されてルールが使われなくなってしまいます。ルールを一度削除 (-D) してから、もういちど追加 (-A) することでチェインの最後に配置することが可能です:
If either or both of the portscanning tricks above were used the final default rule is no longer the last rule in the INPUT chain. It needs to be the last rule otherwise it will intercept the trick port scanner rules you just added and they will never be used. Simply delete the rule (-D), then add it once again using append (-A) which will place it at the end of the chain.
 
   
 
# iptables -D INPUT -j REJECT --reject-with icmp-proto-unreachable
 
# iptables -D INPUT -j REJECT --reject-with icmp-proto-unreachable
 
# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable
 
# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable
   
  +
=== 他の攻撃からの防護 ===
=== Protection against other attacks ===
 
   
  +
関連するカーネルパラメータは [[sysctl#TCP/IP スタックの防御]] に載っています。
See the [[sysctl#TCP/IP stack hardening]] for relevant kernel parameters.
 
   
==== Bruteforce attacks ====
+
==== ブルートフォース攻撃 ====
   
  +
残念ながら、外部 IP アドレスからアクセスできるサービスにはよくブルートフォース攻撃が行われます。ブルートフォース攻撃が普遍的な理由としては、攻撃を行うのがとても簡単で、攻撃用のツールが数多く存在するということが挙げられます。幸いに、ブルートフォース攻撃からサービスを守るための方法はいろいろあります。その一つとして、適切な {{ic|iptables}} ルールを使って接続を開始しようとするパケットが一定数あったときに IP をブラックリストに入れる方法があります。また、ログファイルを監視して、試行失敗からブラックリストを作成する専用のデーモンを使うこともできます。
Unfortunately, bruteforce attacks on services accessible via an external IP address are common. One reason for this is that the attacks are easy to do with the many tools available. Fortunately, there are a number of ways to protect the services against them. One is the use of appropriate {{ic|iptables}} rules which activate and blacklist an IP after a set number of packets attempt to initiate a connection. Another is the use of specialised daemons that monitor the logfiles for failed attempts and blacklist accordingly.
 
  +
{{Warning|IP ブラックリストを使うことで攻撃を多少止めることはできますが、別段にデーモンを使う必要があり、ログがちゃんと記録されてないと上手くいきません (攻撃者が執拗にサーバーを攻撃した場合、{{ic|/var}} を含むパーティションが満杯になる可能性があります)。さらに、攻撃者にあなたの IP アドレスが知られてしまったら、攻撃者はソースヘッダを偽装してパケットを送りつけることができるため、サーバーから締め出される恐れもあります。ブルートフォース攻撃については [[SSH 鍵]]がスマートな解決法になるでしょう。}}
{{Warning| Using an IP blacklist will stop trivial attacks but it relies on an additional daemon and successful logging (the partition containing /var can become full, especially if an attacker is pounding on the server). Additionally, if the attacker knows your IP address, they can send packets with a spoofed source header and get you locked out of the server. [[SSH keys]] provide an elegant solution to the problem of brute forcing without these problems.}}
 
  +
パスワード認証 (特に {{ic|sshd}}) が何回も失敗した時にその IP を接続不可にするパッケージとして [[Fail2ban]] と [[Sshguard]] が存在します。どちらも iptables のルールを更新することで、ブラックリストに入っている IP アドレスからの接続を一時的に拒否します。
Two packages that ban IPs after too many password failures are [[Fail2ban]] or, for {{ic|sshd}} in particular, [[Sshguard]]. These two applications update iptables rules to reject future connections from blacklisted IP addresses.
 
   
  +
以下は {{ic|iptables}} を使って SSH のブルートフォース攻撃を止めるための設定例です:
The following rules give an example configuration to mitigate SSH bruteforce attacks using {{ic|iptables}}.
 
   
 
# iptables -N IN_SSH
 
# iptables -N IN_SSH
  +
# iptables -N LOG_AND_DROP
 
# iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH
 
# iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH
# iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 3 --seconds 10 -j DROP
+
# iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 3 --seconds 10 -j LOG_AND_DROP
# iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 4 --seconds 1800 -j DROP
+
# iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 4 --seconds 1800 -j LOG_AND_DROP
 
# iptables -A IN_SSH -m recent --name sshbf --set -j ACCEPT
 
# iptables -A IN_SSH -m recent --name sshbf --set -j ACCEPT
  +
# iptables -A LOG_AND_DROP -j LOG --log-prefix "iptables deny: " --log-level 7
  +
# iptables -A LOG_AND_DROP -j DROP
   
  +
ほとんどのルールは特に説明を要しないはずです。最初のルールは最大で10秒間で最大3回までの接続パケットを許可し、同じ IP からの4回以上のパケットは破棄します。次のルールでは30分以内で最大4回のパケットを許可するように規則を追加します。一部のブルートフォース攻撃はゆっくりと実行されることがあり、短い時間で何度も試行されないことがあるためです。上記のルールは追加のオプションを使用しています。オプションについて詳しくは [http://compilefailure.blogspot.com/2011/04/better-ssh-brute-force-prevention-with.html compilefailure.blogspot.com] を参照してください。
Most of the options should be self-explanatory, they allow for three connection packets in ten seconds. Further tries in that time will blacklist the IP. The next rule adds a quirk by allowing a total of four attempts in 30 minutes. This is done because some bruteforce attacks are actually performed slow and not in a burst of attempts. The rules employ a number of additional options. To read more about them, check the original reference for this example: [http://compilefailure.blogspot.com/2011/04/better-ssh-brute-force-prevention-with.html compilefailure.blogspot.com]
 
   
  +
上のルールはどんなサービスでも保護することができますが、最も保護が必要なデーモンはおそらく SSH デーモンでしょう。
Using the above rules, now ensure that:
 
# iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH
 
is in an appropriate position in the iptables.rules file.
 
   
  +
順序に関しては、{{ic|-A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH}} が iptables シーケンスの正しい位置にあることを確認する必要があります。最初に新しい SSH 接続をキャッチするために、TCP チェーンが INPUT に接続されます。このウィキのこれまでのすべての手順が完了している場合、次のポジショニングが機能します。
This arrangement works for the IN_SSH rule if you followed this entire wiki so far:
 
*
+
...
  +
-A INPUT -m conntrack --ctstate INVALID -j DROP
 
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
 
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j IN_SSH
+
'''-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j IN_SSH'''
 
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
 
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
  +
-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
*
 
  +
...
   
  +
{{Tip|セットアップ後にルールを自己テストする場合、実際のブラックリスト登録によってテストが遅くなり、パラメーターの微調整が難しくなる可能性があります。{{ic|cat /proc/net/xt_recent/sshbf}} を介して着信試行を監視できます。テスト中に自分の IP のブロックを解除するには、ルートが必要です {{ic|echo / > /proc/net/xt_recent/sshbf}}}}
The above rules can, of course, be used to protect any service, though protecting the SSH daemon is probably the most often required one.
 
   
  +
=== IPv6 ===
{{Tip|For self-testing the rules after setup, the actual blacklist happening can slow the test making it difficult to fine-tune parameters. One can watch the incoming attempts via {{ic|cat /proc/net/xt_recent/sshbf}}. To unblock the own IP during testing, root is needed {{ic|# echo / > /proc/net/xt_recent/sshbf}}}}
 
   
  +
IPv6 を使用しない場合 (ほとんどの ISP は IPv6 をサポートしていません)、[[IPv6#IPv6 の無効化|無効化]]したほうが良いでしょう。
=== Saving the rules ===
 
   
  +
使用する場合、IPv6 のファイアウォールルールを有効にしてください。まず IPv4 のルールをベースとしてコピー:
The ruleset is now finished and should be saved to your hard drive so that it can be loaded on every boot.
 
  +
# cp /etc/iptables/iptables.rules /etc/iptables/ip6tables.rules
  +
最初に、ルールの中で記述している IP を IPv4 のフォーマットから IPv6 のフォーマットに変換します。
   
  +
次に、ルールの一部を改変する必要があります (この記事のルールは IPv4 用になっています)。IPv6 では ICMP を置き換えて新しい ICMPv6 プロトコルを使います。拒否エラーのリターンコード {{ic|--reject-with icmp-port-unreachable}} と {{ic|--reject-with icmp-proto-unreachable}} は ICMPv6 のコードに変えてください。
The systemd unit file points to the location where the rule configuration will be saved:
 
   
  +
利用可能な ICMPv6 エラーコードは [https://tools.ietf.org/html/rfc4443#section-3.1 RFC 4443] に記載されており、ファイアウォールのルールによって接続をブロックしたときは {{ic|--reject-with icmp6-adm-prohibited}} を使うように定義されています。この場合、リモートのマシンにサービスではなくファイアウォールによって接続が拒否されたことを知らせることになります。
iptables=/etc/iptables/iptables.rules
 
ip6tables=/etc/iptables/ip6tables.rules
 
   
  +
ファイアウォールフィルターが存在することを明らかにしたくない場合、メッセージを付けずにパケットを拒否することも可能です:
Save the rules with this command:
 
   
  +
-A INPUT -j REJECT
# iptables-save > /etc/iptables/iptables.rules
 
   
  +
上記の設定だとデフォルトのリターンエラー {{ic|--reject-with-icmp6-port-unreachable}} で拒否します。ただし、ファイアウォールの識別はポートスキャンアプリケーションの基本機能であり、大抵のポートスキャナは上記のように設定していても識別してしまうので注意してください。
and make sure your rules are loaded on boot enabling the '''iptables''' [[daemon]].
 
   
  +
次のステップでは、すべての新しい着信 ICMP エコー要求 (ping) に関するルールに適した IPv6 になるように、プロトコルと拡張子が変更されていることを確認します。
Check that the rules load correctly using:
 
   
  +
# ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 128 -m conntrack --ctstate NEW -j ACCEPT
# systemctl start iptables.service && systemctl status iptables.service
 
   
  +
Netfilter conntrack は ICMPv6 近隣探索プロトコル (IPv6 における ARP) を追跡しないため、ステートに関わらず直接接続されたサブネットでは ICMPv6 を全て許可する必要があります。以下のルールを {{ic|--ctstate INVALID}} の破棄の後、ただし他の DROP または REJECT ターゲットの前に、それぞれの直接接続されたサブネットの行と一緒に挿入してください:
=== IPv6 ===
 
   
  +
# ip6tables -A INPUT -s fe80::/10 -p ipv6-icmp -j ACCEPT
If you do not use IPv6 (most ISPs do not support it), you should [[Disabling IPv6|disable it]].
 
   
  +
IPv6 用のカーネルの戻り経路フィルタは存在しないため、以下のコマンドで ''ip6tables'' のフィルタを有効にすると良いでしょう:
Otherwise, you should enable the firewall rules for IPv6. After copying the IPv4 rules as a base:
 
   
  +
# ip6tables -t raw -A PREROUTING -m rpfilter -j ACCEPT
# cp /etc/iptables/iptables.rules /etc/iptables/ip6tables.rules
 
  +
# ip6tables -t raw -A PREROUTING -j DROP
the first step is to change IPs referenced in the rules from IPv4 format to IPv6 format.
 
   
  +
設定が完了したら、''ip6tables'' サービスを[[有効化]]してください。''iptables'' とは別個に実行させます。
Next, a few of the rules (built as example in this article for IPv4) have to be adapted. IPv6 obtained a new ICMPv6 protocol, replacing ICMP. Hence, the reject error return codes {{ic|--reject-with icmp-port-unreachable}} and {{ic|--reject-with icmp-proto-unreachable}} have to be converted to ICMPv6 codes.
 
   
  +
=== ルールの保存 ===
The available ICMPv6 error codes are listed in [https://tools.ietf.org/html/rfc4443#section-3.1 RFC 4443], which specifies connection attempts blocked by a firewall rule should use {{ic|--reject-with icmp6-adm-prohibited}}. Doing so will basically inform the remote system that the connection was rejected by a firewall, rather than a listening service.
 
   
  +
ルールセットの設定が完了したら、ハードドライブに保存して、マシンを起動する度にロードされるようにします。
If it is preferred not to explicitly inform about the existence of a firewall filter, the packet may also be rejected without the message:
 
   
  +
ルールの設定を保存する場所は systemd のユニットファイルで指定します:
-A INPUT -j REJECT
 
   
  +
iptables=/etc/iptables/iptables.rules
The above will reject with the default return error of {{ic|--reject-with-icmp6-port-unreachable}}. You should note though, that identifying a firewall is a basic feature of port scanning applications and most will identify it regardless.
 
  +
ip6tables=/etc/iptables/ip6tables.rules
   
  +
次のコマンドでルールを保存します:
In the next step make sure the protocol and extension are changed to be IPv6 appropriate for the rule regarding all new incoming ICMP echo requests (pings):
 
   
  +
# iptables-save > /etc/iptables/iptables.rules
# ip6tables -A INPUT -p icmpv6 --icmpv6-type 128 -m conntrack --ctstate NEW -j ACCEPT
 
   
  +
そして {{ic|iptables.service}} を[[起動]]・[[有効化]]して、起動時にルールがロードされるようにしてください。
Netfilter conntrack does not appear to track ICMPv6 Neighbor Discovery Protocol (the IPv6 equivalent of ARP), so we need to allow ICMPv6 traffic regardless of state for all directly attached subnets. The following should be inserted after dropping {{ic|--ctstate INVALID}}, but before any other DROP or REJECT targets, along with a corresponding line for each directly attached subnet:
 
   
  +
=== ip6tables.rules ファイル ===
# ip6tables -A INPUT -s fe80::/10 -p icmpv6 -j ACCEPT
 
   
  +
上記のすべてのコマンドを実行した後の {{ic|ip6tables.rules}} ファイルの例:
Since there is no kernel reverse path filter for IPv6, you may want to enable one in ''ip6tables'' with the following, the first rule is necessary to retain usually needed link local ICMPv6 unicasts:
 
   
  +
{{hc|/etc/iptables/ip6tables.rules|
# ip6tables -t raw -A PREROUTING -p icmpv6 -s fe80::/10 -j ACCEPT
 
# ip6tables -t raw -A PREROUTING -m rpfilter -j ACCEPT
+
# Generated by ip6tables-save v1.8.2 on Sat Apr 20 10:53:41 2019
  +
*filter
# ip6tables -t raw -A PREROUTING -j DROP
 
  +
:INPUT DROP [0:0]
  +
:FORWARD DROP [0:0]
  +
:OUTPUT ACCEPT [0:0]
  +
:TCP - [0:0]
  +
:UDP - [0:0]
  +
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
  +
-A INPUT -i lo -j ACCEPT
  +
-A INPUT -m conntrack --ctstate INVALID -j DROP
  +
-A INPUT -s fe80::/10 -p ipv6-icmp -j ACCEPT
  +
-A INPUT -p udp --sport 547 --dport 546 -j ACCEPT
  +
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
  +
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
  +
-A INPUT -p udp -j REJECT --reject-with icmp6-adm-prohibited
  +
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
  +
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
  +
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 128 -m conntrack --ctstate NEW -j ACCEPT
  +
COMMIT
  +
# Completed on Sat Apr 20 10:53:41 2019
  +
}}
   
  +
次に、{{ic|iptables.service}} と {{ic|ip6tables.service}} を [[有効化]] して [[起動]] します。サービスのステータスをチェックし、ルールが正しくロードされていることを確認します。
After the configuration is done, [[Enable|enable]] the '''ip6tables''' service, it is meant to run in parallel to ''iptables''.
 
   
  +
== NAT ゲートウェイの設定 ==
== Setting up a NAT gateway ==
 
   
  +
このセクションでは NAT ゲートウェイについて扱います。[[#シングルマシン用のファイアウォール|ガイドの前半部分]]を読んで '''INPUT''', '''OUTPUT''', '''TCP''', '''UDP''' チェインを設定していることが前提です。これまで全てのルールは '''filter''' テーブルに作成していました。このセクションでは、'''nat''' テーブルも使用していきます。
This section of the guide deals with NAT gateways. It is assumed that you already read the [[#Firewall for a single machine|first part of the guide]] and set up the '''INPUT''', '''OUTPUT''', '''TCP''' and '''UDP''' chains like described above. All rules so far have been created in the '''filter''' table. In this section, we will also have to use the '''nat''' table.
 
   
  +
=== フィルターテーブルの設定 ===
=== Setting up the filter table ===
 
   
==== Creating necessary chains ====
+
==== 必要なチェインの作成 ====
   
  +
以下の設定では、2つの異なるチェインをフィルターテーブルで使用します: '''fw-interfaces''' と '''fw-open''' チェインです。以下のコマンドでチェインを作成してください:
In our setup, we will use another two chains in the filter table, the '''fw-interfaces''' and '''fw-open''' chains. Create them with the commands
 
   
 
# iptables -N fw-interfaces
 
# iptables -N fw-interfaces
 
# iptables -N fw-open
 
# iptables -N fw-open
   
==== Setting up the FORWARD chain ====
+
==== FORWARD チェインの設定 ====
   
  +
'''FORWARD''' チェインの設定は上のセクションにある '''INPUT''' チェインの設定と大体同じです。
Setting up the '''FORWARD''' chain is similar to the '''INPUT''' chain in the first section.
 
   
  +
'''INPUT''' チェインと同じように '''conntrack''' マッチのルールを設定します:
Now we set up a rule with the '''conntrack''' match, identical to the one in the '''INPUT''' chain:
 
   
 
# iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 
# iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
   
  +
次のステップは、信頼できるインターフェースの転送を有効にし、すべてのパケットが '''fw-open''' チェーンを通過するようにすることです。
The next step is to enable forwarding for trusted interfaces and to make all packets pass the '''fw-open''' chain.
 
   
 
# iptables -A FORWARD -j fw-interfaces
 
# iptables -A FORWARD -j fw-interfaces
 
# iptables -A FORWARD -j fw-open
 
# iptables -A FORWARD -j fw-open
   
  +
後のパケットは '''ICMP''' メッセージで拒否します:
The remaining packets are denied with an '''ICMP''' message:
 
   
 
# iptables -A FORWARD -j REJECT --reject-with icmp-host-unreachable
 
# iptables -A FORWARD -j REJECT --reject-with icmp-host-unreachable
 
# iptables -P FORWARD DROP
 
# iptables -P FORWARD DROP
   
==== Setting up the fw-interfaces and fw-open chains ====
+
==== fw-interfaces fw-open チェインの設定 ====
   
The meaning of the '''fw-interfaces''' and '''fw-open''' chains is explained later, when we deal with the '''POSTROUTING''' and '''PREROUTING''' chains in the '''nat''' table, respectively.
+
'''fw-interfaces''' '''fw-open''' チェインの意味については後で '''nat''' テーブルで '''POSTROUTING''' '''PREROUTING''' チェインを扱うときに説明します。
   
=== Setting up the nat table ===
+
=== nat テーブルの設定 ===
   
  +
このセクションでは、出力インターフェイス (公のインターネット IP が付与されるインターフェイス) の名前を '''ppp0''' とします。使用する出力インターフェイスが別の名前の場合、以下のルールで使われている名前もそれにあわせて変更するようにしてください。
All over this section, we assume that the outgoing interface (the one with the public internet IP) is '''ppp0'''. Keep in mind that you have to change the name in all following rules if your outgoing interface has another name.
 
   
==== Setting up the POSTROUTING chain ====
+
==== POSTROUTING チェインの設定 ====
   
  +
次に、インターネットへの接続を誰に許可するかを定義する必要があります。'''eth0''' にサブネット '''192.168.0.0/24''' (192.168.0.* の形式のすべてのアドレスを意味する) があるとします。まず、FORWARD テーブルでこのインターフェースのマシンを受け入れる必要があります。これが、上記の '''fw-interfaces''' チェーンを作成した理由です。
Now, we have to define who is allowed to connect to the internet. Let's assume we have the subnet '''192.168.0.0/24''' (which means all addresses that are of the form 192.168.0.*) on '''eth0'''. We first need to accept the machines on this interface in the FORWARD table, that is why we created the '''fw-interfaces''' chain above:
 
   
 
# iptables -A fw-interfaces -i eth0 -j ACCEPT
 
# iptables -A fw-interfaces -i eth0 -j ACCEPT
   
  +
ここで、ローカル LAN アドレスではなく、送信元アドレスとしてパブリック IP アドレスを持つように、すべての発信パケットを変更する必要があります。これを行うには、'''MASQUERADE''' ターゲットを使用します。
Now, we have to alter all outgoing packets so that they have our public IP address as the source address, instead of the local LAN address. To do this, we use the '''MASQUERADE''' target:
 
   
 
# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o ppp0 -j MASQUERADE
 
# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o ppp0 -j MASQUERADE
   
  +
上記の '''-o ppp0''' パラメータは必ず必要なので忘れないでください。パラメータを記述しなかった場合、ネットワークが接続できなくなります。
Do not forget the '''-o ppp0''' parameter above. If you omit it, your network will be screwed up.
 
   
  +
インターフェイス '''eth1''' 上に別のサブネット '''10.3.0.0/16''' (すべてのアドレスが 10.3.*.* であることを意味します) があるとします。上記と同じルールを再度追加します。
Let's assume we have another subnet, '''10.3.0.0/16''' (which means all addresses 10.3.*.*), on the interface '''eth1'''. We add the same rules as above again:
 
   
 
# iptables -A fw-interfaces -i eth1 -j ACCEPT
 
# iptables -A fw-interfaces -i eth1 -j ACCEPT
 
# iptables -t nat -A POSTROUTING -s 10.3.0.0/16 -o ppp0 -j MASQUERADE
 
# iptables -t nat -A POSTROUTING -s 10.3.0.0/16 -o ppp0 -j MASQUERADE
   
  +
最後に [[インターネット共有#パケット転送の有効化|パケット転送を有効化]] してください (既に有効にしている場合は必要ありません)
The last step is to enable IP Forwarding (if it is not already enabled):
 
 
# echo 1 > /proc/sys/net/ipv4/ip_forward
 
 
Then edit the relevant line in {{ic|/etc/sysctl.d/90-firewall.conf}} so it persists through reboot (see [[sysctl]] for details):
 
 
net.ipv4.ip_forward = 1
 
   
  +
これらのサブネットのマシンは、新しい NAT マシンをゲートウェイとして使用できるようになりました。'''dnsmasq''' や '''bind''' と '''dhcpd''' の組み合わせのような DNS と DHCP サーバーをセットアップして、クライアントマシンでのネットワーク設定の DNS 解決を簡略化することができます。これは、このガイドのトピックではありません。
Machines from these subnets can now use your new NAT machine as their gateway. Note that you may want to set up a DNS and DHCP server like '''dnsmasq''' or a combination of '''bind''' and '''dhcpd''' to simplify network settings DNS resolution on the client machines. This is not the topic of this guide.
 
   
==== Setting up the PREROUTING chain ====
+
==== PREROUTING チェインの設定 ====
   
  +
ときとして、ゲートウェイからの受信パケットのアドレスを LAN マシンに変更したい場合があります。そのようなときに、上記で定義した '''fw-open''' チェインと、以下の2つのサンプルで使っている '''nat''' テーブルの '''PREROUTING''' チェインを使用します。
Sometimes, we want to change the address of an incoming packet from the gateway to a LAN machine. To do this, we use the '''fw-open''' chain defined above, as well as the '''PREROUTING''' chain in the '''nat''' table in the following two simple examples.
 
   
  +
まず、SSH の受信パケット (ポート 22) を全て '''192.168.0.5''' マシンの ssh サーバーに変更したい場合:
First, we want to change all incoming SSH packets (port 22) to the ssh server of the machine '''192.168.0.5''':
 
   
 
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 22 -j DNAT --to 192.168.0.5
 
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 22 -j DNAT --to 192.168.0.5
 
# iptables -A fw-open -d 192.168.0.5 -p tcp --dport 22 -j ACCEPT
 
# iptables -A fw-open -d 192.168.0.5 -p tcp --dport 22 -j ACCEPT
   
  +
2番目の例では受信ポートと異なるポートにパケットを変更する方法を説明します。ポート '''8000''' から受信した接続を '''192.168.0.6''' のポート '''80''' のウェブサーバーに変更するには:
The second example will show you how to change packets to a different port than the incoming port. We want to change any incoming connection on port '''8000''' to our web server on '''192.168.0.6''', port '''80''':
 
   
 
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to 192.168.0.6:80
 
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to 192.168.0.6:80
 
# iptables -A fw-open -d 192.168.0.6 -p tcp --dport 80 -j ACCEPT
 
# iptables -A fw-open -d 192.168.0.6 -p tcp --dport 80 -j ACCEPT
   
  +
上記の設定は udp パケットでも機能します。
The same setup also works with udp packets.
 
   
=== Saving the rules ===
+
=== ルールの保存 ===
   
  +
ルールを保存してください:
Save the rules:
 
   
 
# iptables-save > /etc/iptables/iptables.rules
 
# iptables-save > /etc/iptables/iptables.rules
   
  +
そして '''iptables''' [[デーモン]]を有効にすることで、起動時にルールがロードされるようにします。
and make sure your rules are loaded when you boot enabling the '''iptables''' [[daemon]].
 
   
 
== 参照 ==
 
== 参照 ==
464行目: 477行目:
 
*[http://www.webhostingtalk.com/showthread.php?t=456571 Methods to block SSH attacks]
 
*[http://www.webhostingtalk.com/showthread.php?t=456571 Methods to block SSH attacks]
 
*[http://www.ducea.com/2006/06/28/using-iptables-to-block-brute-force-attacks/ Using iptables to block brute force attacks]
 
*[http://www.ducea.com/2006/06/28/using-iptables-to-block-brute-force-attacks/ Using iptables to block brute force attacks]
*[http://linuxconfig.org/collection-of-basic-linux-firewall-iptables-rules 20 Iptables Examples For New SysAdmins]
+
*[http://linuxconfig.org/collection-of-basic-linux-firewall-iptables-rules 初心のシステム管理者のための20個の Iptables サンプル]
 
*[http://www.thegeekstuff.com/2011/06/iptables-rules-examples/ 25 Most Frequently Used Linux IPTables Rules Examples]
 
*[http://www.thegeekstuff.com/2011/06/iptables-rules-examples/ 25 Most Frequently Used Linux IPTables Rules Examples]

2023年4月6日 (木) 22:44時点における最新版

関連記事

このページでは iptables を使ってステートフルファイアウォールを設定する方法を説明します。また、ルールの意味と理由の説明も行います。シンプルに説明するため、大きく2つのセクションにページは分かれています。最初のセクションではシングルマシンのためのファイアウォールを扱い、2番目のセクションでは最初のセクションのファイアウォールに加えて NAT ゲートウェイを設定します。

警告: 記述されているルールは順番通りに実行してください。リモートマシンにログインしている場合、ルールを設定している間にマシンから閉めだされてしまう可能性があります。以下の手順に従うのはローカルでログインしている場合に限ります。サンプル設定ファイルを使うことでこの問題を回避することが可能です。

前提要件

ノート: iptables のサポートを有効にしてカーネルがコンパイルされている必要があります。Arch Linux の標準カーネルには iptables のサポートが含まれています。

まず、ユーザーランドユーティリティ iptables をインストールしてください。もしくは既にインストール済みかどうか確認してください。

この記事では iptables のルールセットが全く存在しないことを前提としています。現在のルールセットをチェックして、ルールが存在しないことを確認するには、次を実行:

# iptables-save
# Generated by iptables-save v1.4.19.1 on Thu Aug  1 19:28:53 2013
*filter
:INPUT ACCEPT [50:3763]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [30:3472]
COMMIT
# Completed on Thu Aug  1 19:28:53 2013

もしくは

# iptables -nvL --line-numbers
Chain INPUT (policy ACCEPT 156 packets, 12541 bytes)
num   pkts bytes target     prot opt in     out     source               destination

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

Chain OUTPUT (policy ACCEPT 82 packets, 8672 bytes)
num   pkts bytes target     prot opt in     out     source               destination

ルールが存在する場合、デフォルトのルールセットをロードすることでルールをリセットすることが可能です:

# iptables-restore < /etc/iptables/empty.rules

もしくは、Iptables#ルールをリセットする を参照。

シングルマシン用のファイアウォール

ノート: iptables はチェインの上から下の順番でルールを処理していくため、よくヒットするルールをチェインの初めに置くことを推奨します。もちろん、実行されるロジックによって制約は出て来ます。また、ルールにはランタイムコストもあるため、バイト/パケット数のカウンタだけを見てルールの順番を並び替えるのは賢いとは言えません。

必要なチェインの作成

基本的なセットアップとして、2つのユーザー定義チェインを作成し、それを使ってファイアウォールのポートを開きます。

# iptables -N TCP
# iptables -N UDP

もちろんチェインの名前は何でもかまいません。ここでは後のルールで使用するプロトコルに沿うように名前を決めています。

FORWARD チェイン

マシンを NAT ゲートウェイとしてセットアップしたい場合、#NAT ゲートウェイの設定を見て下さい。シングルマシンの場合、FORWARD チェインのポリシーをとりあえず DROP に設定して先に進みます:

# iptables -P FORWARD DROP

OUTPUT チェイン

送信トラフィックはフィルタリングしません。セットアップがとても複雑になってしまい、いろいろと考える必要が出てくるからです。ここではシンプルに、OUTPUT ポリシーを ACCEPT に設定します。

# iptables -P OUTPUT ACCEPT

INPUT チェイン

上記のチェインと同じように、勝手にルールを通過してしまわないように INPUT チェインのデフォルトポリシーは DROP に設定します。セキュアなファイアウォールを設定するときは、全てのトラフィックをドロップしてから、許可するトラフィックを指定するのがベストです。

警告: SSH でログインしている場合、以下の設定をすると SSH セッションが即座に切断されます。切断されないようにするには: (1) 下の INPUT チェインのルールを先に追加 (それでセッションが開いたままになります), (2) インバウンド SSH を許可するルールを追加 (接続が終了した場合に再接続できるようにするため) (3) ポリシーを設定。
# iptables -P INPUT DROP

あらゆるネットワークインターフェイスから受信されたパケットは全て INPUT チェインをまず通過します (パケットの送信先が対象のマシンになっている場合)。このチェインの中では、問題ないと思われるパケットだけを許可するようにします。

INPUT チェインにはまず、確立済みの接続に属するトラフィックや、ICMP エラーまたはエコー応答 (ping されたときにホストが返すパケット) などの接続に関連する正当なトラフィックを許可するルールを追加します。ICMPInternet Control Message Protocol の略です。ICMP メッセージは輻輳制御や MTU にとても重要なので、このルールによって通してやります。

接続ステート ESTABLISHED は最初の (--ctstate NEW) 接続試行で許可された以前の他のルール、またはルールの設定時にアクティブになっていた接続 (例えばアクティブな SSH リモート接続) を示します:

# iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

次のルールでは "loopback" (lo) インターフェイスからのトラフィックを全て許可します。多くのアプリケーションやサービスで必須となります。

ノート: ファイアウォールでトラフィックを規制したくない場合 "eth1" など信頼できるインターフェイスを追加することもできます。ただし、ネットワーク上のあらゆる場所 (例えばルーターなど) からのあらゆるトラフィックを転送する NAT 構成にしている場合、他の設定は無関係になるため注意してください。
# iptables -A INPUT -i lo -j ACCEPT

3番目のルールでは "INVALID" ステートに一致する全てのトラフィックを破棄します。トラフィックは4つの "state" カテゴリに分けることができます: NEW, ESTABLISHED, RELATED, INVALID。これによって "stateless" ファイアウォールではなく "stateful" ファイアウォールと呼称しています。ステートは "nf_conntrack_*" カーネルモジュールによって追跡されます。カーネルモジュールはルールを追加したときにカーネルによって自動的にロードされます。

ノート:
  • 以下のルールはヘッダーやチェック、TCP フラグがおかしいパケットや不適切な ICMP メッセージ (ホストに何も送信していないのにポート到達不可など)、シーケンス番号予測攻撃などによるシーケンス外のパケットを全て破棄します。"DROP" ターゲットは何も返答せずにパケットを破棄します。それに対して REJECT は礼儀正しくパケットを拒否します。INVALID なパケットに対する適切な "REJECT" レスポンスはありえないため、パケットを受信したことを誰にも分からないように DROP を使っています。
  • ICMPv6 近隣探索パケットは未追跡のまま、たとえ壊れていなくても常に "INVALID" に分類されます。次のコマンドで承認することができます: iptables -A INPUT -p 41 -j ACCEPT
# iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

次のルールでは ICMP エコー要求 (ping) を全て許可します。最初のパケットだけを NEW としてカウントし、後は全て RELATED,ESTABLISHED ルールで処理します。コンピュータはルーターではないので、他の ICMP トラフィックをステート NEW で許可する必要はありません。

# iptables -A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT

新しい接続を処理するために、INPUT チェインに TCP チェインと UDP チェインを適用します。いったん TCP チェインや UDP チェインで接続が許可されると、以降は RELATED/ESTABLISHED のルールで処理されます。TCP チェインと UDP チェインはどちらも新しい接続を許可するか、または丁寧にそれらを REJECT します。新しい TCP 接続は必ず SYN パケットから始まります。

ノート: SYN ビットが設定されていない NEW は INVALID ステートに含まれない唯一の不正な TCP フラグです。悪意のあるパケットである可能性がほとんどないため、破棄せずに、次のルールで TCP RESET を使って拒否するようにします。
# iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
# iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP

ポートを開いていない場合、TCP 接続は TCP RESET パケットで、UDP ストリームは ICMP port unreachable メッセージで拒否します。デフォルトの Linux の挙動と同じであるため (RFC 準拠)、送信者はすみやかに接続を閉じることができます。

# iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
# iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset

他のプロトコルのために、icmp protocol unreachable メッセージで残りの受信トラフィックを拒否する最終ルールを INPUT チェインに追加します。Linux のデフォルトの挙動を真似ています。

# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

iptables.rules のサンプルファイル

上記のコマンドを全て実行した時に作成される iptables.rules ファイルの例:

/etc/iptables/iptables.rules
# Generated by iptables-save v1.4.18 on Sun Mar 17 14:21:12 2013
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:TCP - [0:0]
:UDP - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
COMMIT
# Completed on Sun Mar 17 14:21:12 2013

このファイルは次のコマンドで生成できます:

# iptables-save > /etc/iptables/iptables.rules

生成したファイルは下のセクションで使うことができます。SSH 経由でリモートからファイアウォールを設定する場合、先に進む前に新しい SSH 接続を許可するため以下のルールを追加してください (ポート番号は必要に応じて変更してください):

-A TCP -p tcp --dport 22 -j ACCEPT

TCP と UDP チェイン

TCP と UDP チェインには特定のポートで新規接続の TCP 接続と UDP ストリームを許可するルールを作成します。

ノート: リモートからアクセスする SSH や HTTP などのサービスの接続を許可するためのルールを追加する必要があります。

接続要求でポートを開く

ウェブサーバーへの TCP 接続を許可するには (ポート 80):

# iptables -A TCP -p tcp --dport 80 -j ACCEPT

ウェブサーバーへの TCP 接続 (HTTPS) を許可するには (ポート 443):

# iptables -A TCP -p tcp --dport 443 -j ACCEPT

SSH のリモート接続を許可するには (ポート 22):

# iptables -A TCP -p tcp --dport 22 -j ACCEPT

DNS サーバーへの TCP/UDP リクエストを許可するには (ポート 53):

# iptables -A TCP -p tcp --dport 53 -j ACCEPT
# iptables -A UDP -p udp --dport 53 -j ACCEPT

複数のポートにマッチするような、高度なルールについては iptables(8) を見て下さい。

ポートノッキング

デフォルトではファイアウォールによって閉じられているポートを、外部から開く方法がポートノッキングです。予め決めておいたポートに連続して接続試行することで行います。正しいポート"ノック" (接続試行) がなされた場合、ファイアウォールは特定のポートを開いて接続できるようにします。詳しくはポートノッキングを見て下さい。

なりすまし攻撃からの防護

ノート: 現在 rp_filter はデフォルトで /usr/lib/sysctl.d/50-default.conf1 に設定されているため、以下の手順は必要ありません。

インターネットやローカルネットワークからの予約ローカルアドレスの使用は sysctl で rp_filter (Reverse Path Filter) を 1 に設定することでブロックされます。以下の行を /etc/sysctl.d/90-firewall.conf ファイルに追加することで Linux カーネルに組み込まれている送信元アドレス検証が有効になります (詳しくは sysctl を参照)。カーネルによる検証は個別の iptables ルールよりもなりすましを上手く処理します:

net.ipv4.conf.all.rp_filter=1

統計が必要な場合、netfilter で設定することもできます:

# iptables -t raw -I PREROUTING -m rpfilter --invert -j DROP
ノート: 両方を有効にする意味はありません。netfilter の方法のほうが新しく IPv6 でも機能します。

非同期ルーティングを使用する構成の場合、代わりに rp_filter=2 sysctl オプションを使用する必要があります。--loose スイッチを rpfilter モジュールに渡すことで netfilter と同じ設定ができます。

コンピュータを"隠匿"する

デスクトップマシンとして使っている場合、特定の接続要求はブロックするのが好ましいでしょう。

ping リクエストのブロック

'Ping' リクエストはデバイス間の通信状態を確認するために送信先アドレスに送られる ICMP パケットです。ネットワークが問題ないようでしたら、ping リクエストは全てブロックしてもかまいません。リクエストをブロックするだけではコンピュータを隠匿することにはならないので注意してください。たとえコンピュータに送られた全てのパケットを拒否したとしても、シンプルな nmap による IP 範囲の "ping スキャン" で露顕してしまいます。

ブロックは初歩的な"防護"であり、将来問題が起こった時にデバッグするのが困難になります。あくまで勉強用にやってみるくらいにしてください。

エコー要求をブロックするには、次の行を /etc/sysctl.d/90-firewall.conf ファイルに追加してください (詳しくは sysctl を参照):

net.ipv4.icmp_echo_ignore_all = 1

詳しくは iptables の man ページや http://www.snowman.net/projects/ipt_recent/ のドキュメントやサンプルを読んでください。

ポートスキャナを騙す

ノート:
  • 以下の設定は DoS 攻撃に悪用される可能性があります。偽装した IP でパケットを送信してサービスへの接続をブロックさせてしまうという攻撃が考えられます。
  • conntrack モジュールによってパケットが INVALID と認識され正当な IP アドレスがブロックされる可能性もあります。ブラックリスト化を防ぐには、特定の宛先ポートへのパケットを全て許可してください。

攻撃者はポートスキャンを使ってコンピュータの開いているポートを確認します。ポートスキャンによって攻撃者は稼働しているサービスを調査することができ、場合によってはサービスの脆弱性を利用してくる可能性があります。

INVALID ステートルールは UDP, ACK, SYN スキャン以外の全てのポートスキャンを処理します (nmap ではそれぞれ -sU, -sA, -sS)。

ACK スキャンは開いているポートを確認するのには使われませんが、ファイアウォールによってフィルタリングされているポートを識別するのには使われます。NEW ステートの TCP 接続は全て SYN チェックするため、ACK スキャンによって送信されたパケットは全て TCP RESET パケットで拒否されます。一部のファイアウォールはパケットを破棄するため、攻撃者はファイアウォールのルールを暴き出すことができます。

recent モジュールを使うことで他の2種類のポートスキャンを騙すことができます。recent モジュールでホストを "recent" リストに追加して、特定の種類の攻撃を停止させます。現在の recent リストは /proc/net/xt_recent/ で確認できます。

SYN スキャン

SYN スキャンでは、ポートスキャナは全てのポートに TCP 接続を開始する SYN (synchronization) パケットを送信します。閉じられているポートは TCP RESET パケットを返しますが、厳格なファイアウォールはパケットを破棄します。開いているポートは、ファイアウォールがあるかどうかに関わらず、SYN ACK パケットを返します。

recent モジュールを使うことで接続を拒否されたホストの記録をつけることができ、開いているポートに SYN パケットが送信されたときにポートが閉じているかのように TCP RESET を返すことが可能です。開かれているポートが最初にスキャンされた場合、SYN ACK が返されてしまうため、確実にポートを隠匿するには標準以外のポートを ssh などのアプリケーションで使用する必要があります。

まず、TCP チェインの一番上にルールを追加します。以下のルールは過去60秒以内に TCP-PORTSCAN リストに入ったホストに対して TCP RESET で応答します。--update スイッチで recent リストが更新され、60秒のカウンターがリセットされます。

# iptables -I TCP -p tcp -m recent --update --rsource --seconds 60 --name TCP-PORTSCAN -j REJECT --reject-with tcp-reset

そして TCP パケットを拒否するルールを修正して拒否されたパケットを送信したホストを TCP-PORTSCAN リストに追加するようにしてください:

# iptables -D INPUT -p tcp -j REJECT --reject-with tcp-reset
# iptables -A INPUT -p tcp -m recent --set --rsource --name TCP-PORTSCAN -j REJECT --reject-with tcp-reset
UDP スキャン

UDP ポートスキャンは TCP の SYN スキャンと似ていますが UDP は "connectionless" プロトコルです。ハンドシェイクや ACK は存在しません。代わりに、スキャナは各 UDP ポートに UDP パケットを送信します。ポートが閉じていると ICMP のポート到達不可メッセージが返ってきますが、ポートが開いている場合、何も返答が返ってきません。UDP は "reliable" プロトコルではないので、パケットが消失したかどうか知る手段がスキャナにはなく、返答がないポートを何度も確認する必要があります。

Linux カーネルは ICMP ポートの到達不可メッセージを非常にゆっくりと送信するため、Linux マシンに対して完全な UDP スキャンをかけようとすると10時間以上かかります。それでも、一般的なポートは識別できるため、SYN スキャンに対してと同じ対抗策を UDP スキャンに対しても設定すると良いでしょう。

まず UDP-PORTSCAN リストのホストからのパケットを拒否するルールを UDP チェインの一番上に追加してください:

# iptables -I UDP -p udp -m recent --update --rsource --seconds 60 --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable

そして、UDP の拒否パケットルールを以下のように修正します:

# iptables -D INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
# iptables -A INPUT -p udp -m recent --set --rsource --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
最終ルールのリストア

上記のポートスキャンに対抗するテクニックを使用した場合、デフォルトの最終ルールが INPUT チェインの最後のルールではなくなります。最後のルールにしないとポートスキャン対策のルールが遮断されてルールが使われなくなってしまいます。ルールを一度削除 (-D) してから、もういちど追加 (-A) することでチェインの最後に配置することが可能です:

# iptables -D INPUT -j REJECT --reject-with icmp-proto-unreachable
# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

他の攻撃からの防護

関連するカーネルパラメータは sysctl#TCP/IP スタックの防御 に載っています。

ブルートフォース攻撃

残念ながら、外部 IP アドレスからアクセスできるサービスにはよくブルートフォース攻撃が行われます。ブルートフォース攻撃が普遍的な理由としては、攻撃を行うのがとても簡単で、攻撃用のツールが数多く存在するということが挙げられます。幸いに、ブルートフォース攻撃からサービスを守るための方法はいろいろあります。その一つとして、適切な iptables ルールを使って接続を開始しようとするパケットが一定数あったときに IP をブラックリストに入れる方法があります。また、ログファイルを監視して、試行失敗からブラックリストを作成する専用のデーモンを使うこともできます。

警告: IP ブラックリストを使うことで攻撃を多少止めることはできますが、別段にデーモンを使う必要があり、ログがちゃんと記録されてないと上手くいきません (攻撃者が執拗にサーバーを攻撃した場合、/var を含むパーティションが満杯になる可能性があります)。さらに、攻撃者にあなたの IP アドレスが知られてしまったら、攻撃者はソースヘッダを偽装してパケットを送りつけることができるため、サーバーから締め出される恐れもあります。ブルートフォース攻撃については SSH 鍵がスマートな解決法になるでしょう。

パスワード認証 (特に sshd) が何回も失敗した時にその IP を接続不可にするパッケージとして Fail2banSshguard が存在します。どちらも iptables のルールを更新することで、ブラックリストに入っている IP アドレスからの接続を一時的に拒否します。

以下は iptables を使って SSH のブルートフォース攻撃を止めるための設定例です:

# iptables -N IN_SSH
# iptables -N LOG_AND_DROP
# iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH
# iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 3 --seconds 10 -j LOG_AND_DROP
# iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 4 --seconds 1800 -j LOG_AND_DROP 
# iptables -A IN_SSH -m recent --name sshbf --set -j ACCEPT
# iptables -A LOG_AND_DROP -j LOG --log-prefix "iptables deny: " --log-level 7
# iptables -A LOG_AND_DROP -j DROP

ほとんどのルールは特に説明を要しないはずです。最初のルールは最大で10秒間で最大3回までの接続パケットを許可し、同じ IP からの4回以上のパケットは破棄します。次のルールでは30分以内で最大4回のパケットを許可するように規則を追加します。一部のブルートフォース攻撃はゆっくりと実行されることがあり、短い時間で何度も試行されないことがあるためです。上記のルールは追加のオプションを使用しています。オプションについて詳しくは compilefailure.blogspot.com を参照してください。

上のルールはどんなサービスでも保護することができますが、最も保護が必要なデーモンはおそらく SSH デーモンでしょう。

順序に関しては、-A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH が iptables シーケンスの正しい位置にあることを確認する必要があります。最初に新しい SSH 接続をキャッチするために、TCP チェーンが INPUT に接続されます。このウィキのこれまでのすべての手順が完了している場合、次のポジショニングが機能します。

...
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j IN_SSH
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
...
ヒント: セットアップ後にルールを自己テストする場合、実際のブラックリスト登録によってテストが遅くなり、パラメーターの微調整が難しくなる可能性があります。cat /proc/net/xt_recent/sshbf を介して着信試行を監視できます。テスト中に自分の IP のブロックを解除するには、ルートが必要です echo / > /proc/net/xt_recent/sshbf

IPv6

IPv6 を使用しない場合 (ほとんどの ISP は IPv6 をサポートしていません)、無効化したほうが良いでしょう。

使用する場合、IPv6 のファイアウォールルールを有効にしてください。まず IPv4 のルールをベースとしてコピー:

# cp /etc/iptables/iptables.rules /etc/iptables/ip6tables.rules

最初に、ルールの中で記述している IP を IPv4 のフォーマットから IPv6 のフォーマットに変換します。

次に、ルールの一部を改変する必要があります (この記事のルールは IPv4 用になっています)。IPv6 では ICMP を置き換えて新しい ICMPv6 プロトコルを使います。拒否エラーのリターンコード --reject-with icmp-port-unreachable--reject-with icmp-proto-unreachable は ICMPv6 のコードに変えてください。

利用可能な ICMPv6 エラーコードは RFC 4443 に記載されており、ファイアウォールのルールによって接続をブロックしたときは --reject-with icmp6-adm-prohibited を使うように定義されています。この場合、リモートのマシンにサービスではなくファイアウォールによって接続が拒否されたことを知らせることになります。

ファイアウォールフィルターが存在することを明らかにしたくない場合、メッセージを付けずにパケットを拒否することも可能です:

-A INPUT -j REJECT

上記の設定だとデフォルトのリターンエラー --reject-with-icmp6-port-unreachable で拒否します。ただし、ファイアウォールの識別はポートスキャンアプリケーションの基本機能であり、大抵のポートスキャナは上記のように設定していても識別してしまうので注意してください。

次のステップでは、すべての新しい着信 ICMP エコー要求 (ping) に関するルールに適した IPv6 になるように、プロトコルと拡張子が変更されていることを確認します。

# ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 128 -m conntrack --ctstate NEW -j ACCEPT

Netfilter conntrack は ICMPv6 近隣探索プロトコル (IPv6 における ARP) を追跡しないため、ステートに関わらず直接接続されたサブネットでは ICMPv6 を全て許可する必要があります。以下のルールを --ctstate INVALID の破棄の後、ただし他の DROP または REJECT ターゲットの前に、それぞれの直接接続されたサブネットの行と一緒に挿入してください:

# ip6tables -A INPUT -s fe80::/10 -p ipv6-icmp -j ACCEPT

IPv6 用のカーネルの戻り経路フィルタは存在しないため、以下のコマンドで ip6tables のフィルタを有効にすると良いでしょう:

# ip6tables -t raw -A PREROUTING -m rpfilter -j ACCEPT
# ip6tables -t raw -A PREROUTING -j DROP

設定が完了したら、ip6tables サービスを有効化してください。iptables とは別個に実行させます。

ルールの保存

ルールセットの設定が完了したら、ハードドライブに保存して、マシンを起動する度にロードされるようにします。

ルールの設定を保存する場所は systemd のユニットファイルで指定します:

iptables=/etc/iptables/iptables.rules
ip6tables=/etc/iptables/ip6tables.rules

次のコマンドでルールを保存します:

# iptables-save > /etc/iptables/iptables.rules

そして iptables.service起動有効化して、起動時にルールがロードされるようにしてください。

ip6tables.rules ファイル

上記のすべてのコマンドを実行した後の ip6tables.rules ファイルの例:

/etc/iptables/ip6tables.rules
# Generated by ip6tables-save v1.8.2 on Sat Apr 20 10:53:41 2019
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:TCP - [0:0]
:UDP - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -s fe80::/10 -p ipv6-icmp -j ACCEPT
-A INPUT -p udp --sport 547 --dport 546 -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
-A INPUT -p udp -j REJECT --reject-with icmp6-adm-prohibited
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 128 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
# Completed on Sat Apr 20 10:53:41 2019

次に、iptables.serviceip6tables.service有効化 して 起動 します。サービスのステータスをチェックし、ルールが正しくロードされていることを確認します。

NAT ゲートウェイの設定

このセクションでは NAT ゲートウェイについて扱います。ガイドの前半部分を読んで INPUT, OUTPUT, TCP, UDP チェインを設定していることが前提です。これまで全てのルールは filter テーブルに作成していました。このセクションでは、nat テーブルも使用していきます。

フィルターテーブルの設定

必要なチェインの作成

以下の設定では、2つの異なるチェインをフィルターテーブルで使用します: fw-interfacesfw-open チェインです。以下のコマンドでチェインを作成してください:

# iptables -N fw-interfaces
# iptables -N fw-open

FORWARD チェインの設定

FORWARD チェインの設定は上のセクションにある INPUT チェインの設定と大体同じです。

INPUT チェインと同じように conntrack マッチのルールを設定します:

# iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

次のステップは、信頼できるインターフェースの転送を有効にし、すべてのパケットが fw-open チェーンを通過するようにすることです。

# iptables -A FORWARD -j fw-interfaces 
# iptables -A FORWARD -j fw-open 

後のパケットは ICMP メッセージで拒否します:

# iptables -A FORWARD -j REJECT --reject-with icmp-host-unreachable
# iptables -P FORWARD DROP

fw-interfaces と fw-open チェインの設定

fw-interfacesfw-open チェインの意味については後で nat テーブルで POSTROUTINGPREROUTING チェインを扱うときに説明します。

nat テーブルの設定

このセクションでは、出力インターフェイス (公のインターネット IP が付与されるインターフェイス) の名前を ppp0 とします。使用する出力インターフェイスが別の名前の場合、以下のルールで使われている名前もそれにあわせて変更するようにしてください。

POSTROUTING チェインの設定

次に、インターネットへの接続を誰に許可するかを定義する必要があります。eth0 にサブネット 192.168.0.0/24 (192.168.0.* の形式のすべてのアドレスを意味する) があるとします。まず、FORWARD テーブルでこのインターフェースのマシンを受け入れる必要があります。これが、上記の fw-interfaces チェーンを作成した理由です。

# iptables -A fw-interfaces -i eth0 -j ACCEPT

ここで、ローカル LAN アドレスではなく、送信元アドレスとしてパブリック IP アドレスを持つように、すべての発信パケットを変更する必要があります。これを行うには、MASQUERADE ターゲットを使用します。

# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o ppp0 -j MASQUERADE

上記の -o ppp0 パラメータは必ず必要なので忘れないでください。パラメータを記述しなかった場合、ネットワークが接続できなくなります。

インターフェイス eth1 上に別のサブネット 10.3.0.0/16 (すべてのアドレスが 10.3.*.* であることを意味します) があるとします。上記と同じルールを再度追加します。

# iptables -A fw-interfaces -i eth1 -j ACCEPT
# iptables -t nat -A POSTROUTING -s 10.3.0.0/16 -o ppp0 -j MASQUERADE

最後に パケット転送を有効化 してください (既に有効にしている場合は必要ありません)

これらのサブネットのマシンは、新しい NAT マシンをゲートウェイとして使用できるようになりました。dnsmasqbinddhcpd の組み合わせのような DNS と DHCP サーバーをセットアップして、クライアントマシンでのネットワーク設定の DNS 解決を簡略化することができます。これは、このガイドのトピックではありません。

PREROUTING チェインの設定

ときとして、ゲートウェイからの受信パケットのアドレスを LAN マシンに変更したい場合があります。そのようなときに、上記で定義した fw-open チェインと、以下の2つのサンプルで使っている nat テーブルの PREROUTING チェインを使用します。

まず、SSH の受信パケット (ポート 22) を全て 192.168.0.5 マシンの ssh サーバーに変更したい場合:

# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 22 -j DNAT --to 192.168.0.5
# iptables -A fw-open -d 192.168.0.5 -p tcp --dport 22 -j ACCEPT

2番目の例では受信ポートと異なるポートにパケットを変更する方法を説明します。ポート 8000 から受信した接続を 192.168.0.6 のポート 80 のウェブサーバーに変更するには:

# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to 192.168.0.6:80
# iptables -A fw-open -d 192.168.0.6 -p tcp --dport 80 -j ACCEPT

上記の設定は udp パケットでも機能します。

ルールの保存

ルールを保存してください:

# iptables-save > /etc/iptables/iptables.rules

そして iptables デーモンを有効にすることで、起動時にルールがロードされるようにします。

参照