Iptablesを使用してLinuxゲートウェイ経由でポートを転送する方法

前書き

  • NAT *、またはネットワークアドレス変換は、パケットを代替アドレスにリダイレクトするためにパケットをマングリングするための一般的な用語です。 通常、これはトラフィックがネットワークの境界を越えることを許可するために使用されます。 NATを実装するホストは通常​​、2つ以上のネットワークにアクセスし、それらの間でトラフィックをルーティングするように構成されます。

*ポート転送*は、特定のポートの要求を別のホスト、ネットワーク、またはポートに転送するプロセスです。 このプロセスは飛行中のパケットの宛先を変更するため、NAT操作の一種と見なされます。

このガイドでは、NATテクニックを使用して、ファイアウォールの背後にあるホストにポートを転送するために「+ iptables +」を使用する方法を示します。 これは、プライベートネットワークを設定したが、指定されたゲートウェイマシンを介して内部の特定のトラフィックを許可したい場合に便利です。 これを実証するために、2つのUbuntu 14.04ホストを使用します。

前提条件と目標

このガイドに従うには、プライベートネットワークが有効になっている同じデータセンター内の2つのUbuntu 14.04ホストが必要です。 これらの各マシンで、 `+ sudo +`権限を持つ非rootユーザーアカウントを設定する必要があります。 Ubuntu 14.04初期サーバーセットアップガイド

最初のホストは、プライベートネットワークのファイアウォールおよびルーターとして機能します。 デモンストレーションの目的で、2番目のホストは、プライベートインターフェイスを使用してのみアクセス可能なWebサーバーで構成されます。 パブリックインターフェイスで受信した要求をWebサーバーに転送するようにファイアウォールマシンを構成し、Webサーバーはプライベートインターフェイスに到達します。

ホストの詳細

開始する前に、両方のサーバーで使用されているインターフェイスとアドレスを知る必要があります。

ネットワークの詳細を見つける

独自のシステムの詳細を取得するには、まずネットワークインターフェイスを見つけます。 次のように入力することで、マシン上のインターフェースとそれらに関連付けられたアドレスを見つけることができます。

ip -4 addr show scope global
Sample Output2: : <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
   inet /18 brd 45.55.191.255 scope global eth0
      valid_lft forever preferred_lft forever
3: : <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
   inet /16 brd 10.132.255.255 scope global eth1
      valid_lft forever preferred_lft forever

上記の強調表示された出力は、2つのインターフェイス( + eth0 +`と `+ eth1 +)とそれぞれに割り当てられたアドレス(それぞれ + 192.51.100.45 +`と `+ 192.168.1.5 +)を示しています。 これらのインターフェイスのどれがパブリックインターフェイスであるかを確認するには、次のように入力します。

ip route show | grep default
Outputdefault via 111.111.111.111

表示されるインターフェイス(この例では「+ eth0 +」)は、デフォルトゲートウェイに接続されたインターフェイスになります。 これはほぼ間違いなくあなたの公開インターフェースです。

各マシンでこれらの値を検索し、これらの値を使用して、このガイドに正しく従ってください。

このガイドのサンプルデータ

わかりやすくするために、このチュートリアルでは次のダミーアドレスとインターフェイスの割り当てを使用します。 以下に表示されている値を独自の値に置き換えてください。

Webサーバーネットワークの詳細:

  • パブリックIPアドレス: ++

  • プライベートIPアドレス: ++

  • 公開インターフェース: ++

  • プライベートインターフェイス: ++

ファイアウォールネットワークの詳細:

  • パブリックIPアドレス: ++

  • プライベートIPアドレス: ++

  • 公開インターフェース: ++

  • プライベートインターフェイス: ++

Webサーバーのセットアップ

Webサーバーホストから始めます。 開始するには、 `+ sudo +`ユーザーでログインします。

Nginxをインストールする

最初に行うプロセスは、Webサーバーホストに `+ Nginx +`をインストールし、プライベートインターフェイスのみをリッスンするようにロックダウンすることです。 これにより、ポートフォワーディングを正しく設定した場合にのみWebサーバーが使用可能になります。

ローカルパッケージキャッシュを更新し、 `+ apt +`を使用してソフトウェアをダウンロードおよびインストールすることから始めます。

sudo apt-get update
sudo apt-get install nginx

Nginxをプライベートネットワークに制限する

Nginxのインストール後、デフォルトのサーバーブロック構成ファイルを開き、プライベートインターフェイスのみをリッスンするようにします。 今すぐファイルを開きます。

sudo nano /etc/nginx/sites-enabled/default

内部で、 `+ listen +`ディレクティブを見つけます。 構成の上部に向かって2回連続で見つける必要があります。

/ etc / nginx / sites-enabled / default

server {
   listen 80 default_server;
   listen [::]:80 default_server ipv6only=on;

   . . .
}

最初の「+ listen」ディレクティブで、WebサーバーのプライベートIPアドレスとコロンを「80」の直前に追加して、Nginxにプライベートインターフェイスのみでリッスンするように指示します。 このガイドではIPv4転送のみを示しているため、IPv6用に構成されている2番目のlistenディレクティブを削除できます。

この例では、listenディレクティブを次のように変更します。

/ etc / nginx / sites-enabled / default

server {
   listen :80 default_server;

   . . .
}

完了したら、ファイルを保存して閉じます。 次のように入力して、ファイルの構文エラーをテストします。

sudo nginx -t

エラーが表示されない場合は、Nginxを再起動して新しい構成を有効にします。

sudo service nginx restart

ネットワーク制限を確認する

この時点で、ウェブサーバーへのアクセスレベルを確認すると便利です。

*ファイアウォール*サーバーから、プライベートインターフェイスからWebサーバーにアクセスしようとすると、動作するはずです。

curl --connect-timeout 5
Output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
   body {
       width: 35em;
       margin: 0 auto;
       font-family: Tahoma, Verdana, Arial, sans-serif;
   }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
. . .

パブリックインターフェイスを使用しようとすると、接続できないことがわかります。

curl --connect-timeout 5
curl: (7) Failed to connect to 203.0.113.2 port 80: Connection refused

これはまさに私たちが期待していることです。

ポート80を転送するためのファイアウォールの構成

これで、ファイアウォールマシンでのポート転送の実装に取り​​組むことができます。

カーネルで転送を有効にする

最初に行う必要があるのは、カーネルレベルでトラフィック転送を有効にすることです。 デフォルトでは、ほとんどのシステムで転送がオフになっています。

このセッションでのみポート転送をオンにするには、次を入力します。

echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

ポート転送を永続的に有効にするには、 `+ / etc / sysctl.conf `ファイルを編集する必要があります。 次を入力して、 ` sudo +`特権でファイルを開きます。

sudo nano /etc/sysctl.conf

内部で、次のような行を見つけてコメント解除します。

/etc/sysctl.conf

net.ipv4.ip_forward=1

完了したら、ファイルを保存して閉じます。 次のように入力して、このファイルの設定を適用します。

sudo sysctl -p
sudo sysctl --system

基本ファイアウォールのセットアップ

https://www.digitalocean.com/community/tutorials/how-to-implement-a-basic-firewall-template-with-iptables-on-ubuntu-14-04 [このガイド]でファイアウォールを使用しますこのチュートリアルのルールの基本的なフレームワーク。 ファイアウォールマシンで今すぐガイドを実行して、セットアップしてください。 終了すると、次のものが得られます。

  • `+ iptables-persistent +`をインストールしました

  • デフォルトのルールセットを「+ / etc / iptables / rules.v4 +」に保存しました

  • ルールファイルを編集するか、 `+ iptables +`コマンドを使用して、ルールを追加または調整する方法を学習しました

基本的なファイアウォールを設定したら、ポート転送用に調整できるように、以下に進んでください。

転送ルールの追加

ポート80のパブリックインターフェース( + eth0 +)に流れるトラフィックがプライベートインターフェース( + eth1 +)に転送されるようにファイアウォールを設定します。

基本的なファイアウォールには、デフォルトで `+ DROP `トラフィックに設定された ` FORWARD +`チェーンがあります。 Webサーバーへの接続の転送を許可するルールを追加する必要があります。 セキュリティのため、これをかなり厳密にロックダウンして、転送したい接続のみが許可されるようにします。

`+ FORWARD `チェーンでは、パブリックインターフェースからプライベートインターフェースに移動するポート80向けの新しい接続を受け入れます。 新しい接続は「 conntrack +」拡張機能によって識別され、具体的にはTCP SYNパケットで表されます。

sudo iptables -A FORWARD -i  -o  -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT

これにより、接続を確立するための最初のパケットがファイアウォールを通過できます。 また、その接続から生じる双方向の後続トラフィックを許可する必要があります。 パブリックインターフェイスとプライベートインターフェイスの間で「+ ESTABLISHED 」および「 RLEATED +」トラフィックを許可するには、次のように入力します。

iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i eth1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

次のように入力して、 `+ FORWARD `チェーンのポリシーが ` DROP`に設定されていることを再確認できます。

sudo iptables -P FORWARD DROP

この時点で、パブリックインターフェイスとプライベートインターフェイス間の特定のトラフィックがファイアウォールを通過できるようになりました。 ただし、実際にトラフィックを変換および転送する方法を「+ iptables +」に指示するルールはまだ設定していません。

NATルールを直接パケットに正しく追加する

次に、トラフィックをルーティングする方法を「+ iptables 」に伝えるルールを追加します。 クライアントがWebサーバーと通信できるように、 ` iptables +`がパケットを正しく変更するには、2つの別個の操作を実行する必要があります。

最初の操作は「+ DNAT i」と呼ばれ、「+ nat 」テーブルの「 PREROUTING」チェーンで実行されます。 「+ DNAT +」は、パケットがネットワーク間を通過するときに正しくルーティングされるように、パケットの宛先アドレスを変更する操作です。 パブリックネットワーク上のクライアントはファイアウォールサーバーに接続し、プライベートネットワークトポロジを認識しません。 各パケットの宛先アドレスを変更して、プライベートネットワークで送信されるときに、Webサーバーに正しく到達する方法を知る必要があります。

ポートフォワーディングのみを構成し、ファイアウォールにヒットするすべてのパケットでNATを実行しないため、ルールのポート80に一致させます。 ポート80を宛先とするパケットをWebサーバーのプライベートIPアドレス(この例では「192.0.2.2」)に一致させます。

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination

これにより、画像の半分が処理されます。 パケットはWebサーバーに正しくルーティングされるはずです。 ただし、現時点では、パケットには送信元アドレスとしてクライアントの元のアドレスが残っています。 サーバーはそのアドレスに直接応答を送信しようとするため、正当なTCP接続を確立できなくなります。

Note

適切なルーティングを設定するには、パケットの送信元アドレスを変更して、ファイアウォールからWebサーバーへの経路を抜ける必要があります。 送信元アドレスをファイアウォールサーバーのプライベートIPアドレス(この例では「192.0.2.15」)に変更する必要があります。 応答はファイアウォールに送り返され、ファイアウォールは期待どおりにクライアントに転送します。

この機能を有効にするには、ネットワーク上でパケットが送信される直前に評価される、「+ nat 」テーブルの「 POSTROUTING +」チェーンにルールを追加します。 Webサーバー宛てのパケットをIPアドレスとポートで照合します。

sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp --dport 80 -d  -j SNAT --to-source

このルールが適用されると、ファイアウォールマシンのパブリックアドレスでWebブラウザを指定することにより、Webサーバーにアクセスできるようになります。

curl
Output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
   body {
       width: 35em;
       margin: 0 auto;
       font-family: Tahoma, Verdana, Arial, sans-serif;
   }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
. . .

ポート転送のセットアップが完了しました。

永続的なルールセットの調整

ポート転送を設定したので、これを永続的なルールセットに保存できます。

現在のルールセットにあるコメントを失うことを気にしない場合は、 `+ iptables-persistent`サービスを使用してルールを保存します。

sudo service iptables-persistent save

ファイルにコメントを保持したい場合は、コメントを開いて手動で編集します。

sudo nano /etc/iptables/rules.v4

追加された `+ FORWARD `チェーンルールに合わせて、 ` filter `テーブルの設定を調整する必要があります。 また、 ` PREROUTING `および ` POSTROUTING `ルールを追加できるように、 ` nat +`テーブルを設定するセクションを調整する必要があります。 この例では、次のようになります。

/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



# Web server network details:

# * Public IP Address:
# * Private IP Address:
# * Public Interface:
# * Private Interface:
#
# Firewall network details:
#
# * Public IP Address:
# * Private IP Address:
# * Public Interface:
# * Private Interface:
-A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT
-A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -i eth1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT


# 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]





# Web server network details:

# * Public IP Address:
# * Private IP Address:
# * Public Interface:
# * Private Interface:
#
# Firewall network details:
#
# * Public IP Address:
# * Private IP Address:
# * Public Interface:
# * Private Interface:
-A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination
-A POSTROUTING -d  -o eth1 -p tcp --dport 80 -j SNAT --to-source

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

上記を追加し、独自のネットワーク環境を反映するように値を調整したら、ファイルを保存して閉じます。

次のように入力して、ルールファイルの構文をテストします。

sudo iptables-restore -t < /etc/iptables/rules.v4

エラーが検出されない場合は、ルールセットをロードします。

sudo service iptables-persistent reload

ファイアウォールのパブリックIPアドレスを介してWebサーバーにアクセスできることをテストします。

curl

これは以前と同じように機能するはずです。

結論

今では、 `+ iptables `でLinuxサーバー上のポートを転送することに慣れているはずです。 このプロセスには、カーネルレベルでの転送の許可、ファイアウォールシステム上の2つのインターフェイス間の特定のポートのトラフィックの転送を許可するアクセスの設定、およびパケットを正しくルーティングできるようにNATルールを構成することが含まれます。 これは扱いにくいプロセスのように思えるかもしれませんが、 ` netfilter `パケットフィルタリングフレームワークと ` iptables +`ファイアウォールの柔軟性も示しています。 これを使用して、プライベートネットワークトポロジを偽装し、ゲートウェイファイアウォールマシンを介してサービストラフィックが自由に流れるようにすることができます。

Related