EC2のiptablesでPostgreSQLへのポートフォワードを設定する

  • AWS
  • EC2
  • iptables
  • PostgreSQL
  • Networking

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

内部ネットワークにしか置いてないPostgreSQLに、外からアクセスしたいことがあった。踏み台を用意するほどでもない場合、EC2にiptablesでNAT設定を入れてポートフォワードするだけで済む。手順をメモしておく。

やりたいこと

外部 → EC2(グローバルIP) → 内部のPostgreSQLインスタンス、という経路で特定ポートだけ転送する。

flowchart LR
  A[外部クライアント] --> B[EC2<br>iptables NAT]
  B --> C[内部 PostgreSQL]

手順

1. iptables-servicesのインストール

Amazon Linux 1にはiptablesの永続化サービスが入っていないので、まずこれを入れる。

sudo yum install iptables-services

2. IPフォワードを有効化

まず現状確認。

cat /proc/sys/net/ipv4/ip_forward
0

有効化する。

sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

確認。

cat /proc/sys/net/ipv4/ip_forward
1

ここで注意点がひとつ。/proc/sys/net/ipv4/ip_forward への書き込みはその場限りの設定で、再起動すると 0 に戻る。永続化するには /etc/sysctl.conf(もしくは /etc/sysctl.d/ 配下)に以下を追記しておく必要がある。

net.ipv4.ip_forward=1

これは「なくても動くから不要」ではなく、再起動後もIPフォワードを維持するために必須の設定だった。

3. IPマスカレード・DNAT設定

内部のPostgreSQLへ、EC2を経由してポートフォワードする。

sudo iptables -t nat -A PREROUTING -p tcp --dport <port> -j DNAT --to <ipaddress>:<port>
sudo iptables -A FORWARD -p tcp -d <ipaddress> --dport <port> -j ACCEPT
sudo iptables -t nat -A POSTROUTING -j MASQUERADE

<port> <ipaddress> は環境に合わせて置き換える。

4. 設定の保存

sudo service iptables save

5. iptablesの起動・自動起動設定

sudo systemctl start iptables
sudo systemctl enable iptables
sudo systemctl status iptables

status でactiveになっていることを確認しておく。

6. 送信元/送信先チェックの停止

EC2インスタンスの「送信元/送信先の変更チェック」を停止(無効化)する必要がある。デフォルトでは自分宛て以外のパケットを破棄する設定になっているため、これを止めないとフォワードされたパケットが弾かれる。

7. セキュリティグループの開放

接続元IPと対象ポートをセキュリティグループのインバウンドルールで開放する。

つまずきやすい点

  • ip_forward を有効にしただけで満足して、sysctl.conf への追記を忘れる → 次の再起動で転送が止まる
  • 送信元/送信先チェックを止め忘れる → iptablesの設定自体は正しくてもパケットが最初の時点で弾かれる
  • セキュリティグループを開け忘れる → iptables云々の前にそもそも到達しない

この3つは別レイヤーの話なので、どれか1つだけ見ても原因が分かりにくい。切り分けるときはこの順番(SG → 送信元/送信先チェック → iptables)で疑うとよさそう。

なお、この手順はAmazon Linux 1での確認内容。ディストリビューションやOSバージョンが変わると、iptables周りのパッケージ構成が変わっている可能性がある。