サーバー間のトラフィックを保護するためにIptablesファイアウォールを設定する方法
序章
アプリケーションセットアップの個別のコンポーネントを異なるノードにデプロイすることは、負荷を減らし、水平方向のスケーリングを開始するための一般的な方法です。 典型的な例は、アプリケーションとは別のサーバーでデータベースを構成することです。 この設定には多くの利点がありますが、ネットワークを介した接続には、新しい一連のセキュリティ上の懸念が伴います。
このガイドでは、分散セットアップで各サーバーに単純なファイアウォールをセットアップする方法を示します。 他のトラフィックを拒否しながら、コンポーネント間の正当なトラフィックを許可するようにポリシーを構成します。
このガイドのデモでは、2台のUbuntu14.04サーバーを使用します。 1つはNginxで提供されるWordPressインスタンスを持ち、もう1つはアプリケーションのMySQLデータベースをホストします。 この設定を例として使用しますが、独自のサーバー要件に適合するように関連する手法を推定できるはずです。
前提条件
開始するには、2台の新しいUbuntu14.04サーバーが必要です。 で通常のユーザーアカウントを追加します sudo
それぞれの特権。 これを正しく行う方法については、Ubuntu14.04初期サーバーセットアップガイドに従ってください。
保護するアプリケーションのセットアップは、このガイドに基づいています。 フォローする場合は、そのチュートリアルに示されているように、アプリケーションサーバーとデータベースサーバーをセットアップします。
基本的なファイアウォールの設定
まず、各サーバーにベースラインファイアウォール構成を実装します。 実装するポリシーは、セキュリティファーストのアプローチを採用しています。 SSHトラフィック以外のほとんどすべてをロックダウンしてから、特定のアプリケーション用にファイアウォールに穴を開けます。
このガイドのファイアウォールは、必要な基本的なセットアップを提供します。 をインストールします iptables-persistent
基本的なルールをパッケージ化して貼り付けます /etc/iptables/rules.v4
ファイル:
- sudo apt-get update
- sudo apt-get install iptables-persistent
- sudo nano /etc/iptables/rules.v4
*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]
# Acceptable UDP traffic
# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
# Acceptable ICMP traffic
# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT
# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP
# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP
# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-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 the changes
COMMIT
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
これをライブ環境で実装している場合ファイアウォールルールをまだリロードしないでください。 ここで概説されている基本的なルールセットをロードすると、アプリケーションとデータベースサーバー間の接続がすぐに切断されます。 リロードする前に、運用上のニーズを反映するようにルールを調整する必要があります。
サービスで使用されているポートを確認する
コンポーネント間の通信を可能にする例外を追加するには、使用されているネットワークポートを知る必要があります。 構成ファイルを調べることで正しいネットワークポートを見つけることができますが、アプリケーションに依存しない正しいポートを見つける方法は、各マシンで接続をリッスンしているサービスを確認することです。
使用できます netstat
これを見つけるためのツール。 私たちのアプリケーションはIPv4を介してのみ通信しているため、 -4
引数ですが、IPv6を使用している場合は、それを削除できます。 実行中のサービスを見つけるために必要な他の引数は次のとおりです。 -plunt
.
Webサーバーでは、次のように表示されます。
- sudo netstat -4plunt
OutputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1058/sshd
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx
最初に強調表示されている列は、回線の終わりに向かって強調表示されているサービスがリッスンしているIPアドレスとポートを示しています。 特別な 0.0.0.0
アドレスは、問題のサービスが利用可能なすべてのアドレスをリッスンしていることを意味します。
データベースサーバーでは、次のように表示されます。
- sudo netstat -4plunt
OutputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1097/sshd
tcp 0 0 192.0.2.30:3306 0.0.0.0:* LISTEN 3112/mysqld
これらの列はまったく同じように読み取ることができます。 上記の例では、 192.0.2.30
addressは、データベースサーバーのプライベートIPアドレスを表します。 アプリケーションのセットアップでは、セキュリティ上の理由からMySQLをプライベートインターフェイスにロックダウンしました。
このステップで見つけた値に注意してください。 これらは、ファイアウォール構成を調整するために必要なネットワークの詳細です。
このシナリオ例では、Webサーバーで、次のポートにアクセスできることを確認する必要があることに注意してください。
- すべてのアドレスのポート80
- すべてのアドレスのポート22(ファイアウォールルールですでに考慮されています)
データベースサーバーは、次のポートにアクセスできることを確認する必要があります。
- アドレスのポート3306
192.0.2.30
(またはそれに関連付けられたインターフェイス) - すべてのアドレスのポート22(ファイアウォールルールですでに考慮されています)
Webサーバーファイアウォールルールを調整する
必要なポート情報が得られたので、Webサーバーのファイアウォールルールセットを調整します。 次のコマンドを使用して、エディタでルールファイルを開きます。 sudo
特権:
- sudo nano /etc/iptables/rules.v4
Webサーバーでは、受け入れ可能なトラフィックのリストにポート80を追加する必要があります。 サーバーは使用可能なすべてのアドレスをリッスンしているため、インターフェースまたは宛先アドレスによってルールを制限することはありません。
Web訪問者は、TCPプロトコルを使用して接続します。 私たちの基本的なフレームワークには、すでに TCP
TCPアプリケーションの例外の場合。 SSHポートの例外のすぐ下にあるそのチェーンにポート80を追加できます。
*filter
. . .
# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 80 -j ACCEPT
. . .
Webサーバーがデータベースサーバーとの接続を開始します。 発信トラフィックはファイアウォールで制限されておらず、確立された接続に関連付けられた着信トラフィックが許可されているため、このサーバーで追加のポートを開いてこの接続を許可する必要はありません。
終了したら、ファイルを保存して閉じます。 現在、Webサーバーには、他のすべてをブロックしながらすべての正当なトラフィックを許可するファイアウォールポリシーがあります。
ルールファイルの構文エラーをテストします。
- sudo iptables-restore -t < /etc/iptables/rules.v4
構文エラーが表示されない場合は、ファイアウォールをリロードして新しいルールセットを実装します。
- sudo service iptables-persistent reload
データベースサーバーのファイアウォールルールを調整する
データベースサーバーでは、ポートへのアクセスを許可する必要があります 3306
サーバーのプライベートIPアドレス。 私たちの場合、そのアドレスは 192.0.2.30
. このアドレス宛てのアクセスを具体的に制限することも、そのアドレスが割り当てられているインターフェイスと照合してアクセスを制限することもできます。
そのアドレスに関連付けられているネットワークインターフェイスを見つけるには、次のように入力します。
- ip -4 addr show scope global
Output2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 203.0.113.5/24 brd 104.236.113.255 scope global eth0
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.0.2.30/24 brd 192.0.2.255 scope global eth1
valid_lft forever preferred_lft forever
強調表示された領域は、 eth1
インターフェイスはそのアドレスに関連付けられています。
次に、データベースサーバーのファイアウォールルールを調整します。 でルールファイルを開きます sudo
データベースサーバーの特権:
- sudo nano /etc/iptables/rules.v4
繰り返しになりますが、ルールを追加します TCP
Webサーバーとデータベースサーバー間の接続の例外を形成するためのチェーン。
問題の実際のアドレスに基づいてアクセスを制限する場合は、次のようなルールを追加します。
*filter
. . .
# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -d 192.0.2.30 -j ACCEPT
. . .
そのアドレスを収容するインターフェースに基づいて例外を許可したい場合は、代わりに次のようなルールを追加できます。
*filter
. . .
# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -i eth1 -j ACCEPT
. . .
終了したら、ファイルを保存して閉じます。
次のコマンドで構文エラーを確認します。
- sudo iptables-restore -t < /etc/iptables/rules.v4
準備ができたら、ファイアウォールルールをリロードします。
- sudo service iptables-persistent reload
これで、サーバー間の必要なデータフローを制限することなく、両方のサーバーを保護する必要があります。
結論
適切なファイアウォールの実装は、アプリケーションをセットアップするときに常に展開計画の一部である必要があります。 NginxとMySQLを実行している2つのサーバーを使用してWordPressインスタンスを提供するこの構成を示しましたが、上記の手法は、特定のテクノロジーの選択に関係なく適用できます。
ファイアウォールと iptables
具体的には、次のガイドをご覧ください。