Docker コンテナのポートマッピングアクセス制限

Docker コンテナを使用する際、コンテナのポートをホストマシンにマッピングする必要が頻繁にあります。基本的なポートマッピングは "PORT:PORT" の形式で設定できます。例えば "6379:6379" は、コンテナの 6379 ポートをホストマシンの 6379 ポートにマッピングします。

しかし、この基本的なポートマッピングには重要な問題があります:デフォルトでは、ホストマシンにアクセスできるクライアントは誰でもこのポートにアクセスできます。本番環境では、通常特定の IP アドレスまたはネットワークセグメントのみがコンテナのポートにアクセスできるように制限する必要があります。

0x00 Docker ネットワークの動作原理

コンテナのポートをマッピングする際、Dockeriptables に関連するルールを追加します。データパケットの流れは以下の通りです:

flowchart TD A[クライアント] --eth0--> B[ホストマシン] --iptables NAT--> C[docker0 ブリッジ] --転送--> D[コンテナ] アクセスを制限するには、トラフィックを制御するために DOCKER-USER チェーンにルールを追加する必要があります。DOCKER-USER チェーンのルールは DOCKER チェーンのルールより前に実行されます。詳細なドキュメントは Packet filtering and firewalls を参照してください。

0x01 設定例

まずテスト用の Redis コンテナを作成します:

services:
  redis:
    image: redis:latest
    restart: unless-stopped
    ports:
      - 6379:6379
    volumes:
      - /etc/localtime:/etc/localtime:ro

アクセシビリティをテストします

マシン1 (IP: 192.168.1.10):

マシン2 (IP: 192.168.2.10):

アクセス制御ルールの追加

以下のルールは、マシン1のネットワークセグメントのみが 6379 ポートにアクセスできるようにします:

# 既に確立された接続を許可
sudo iptables -I DOCKER-USER -m state --state ESTABLISHED,RELATED -j ACCEPT

# 特定のネットワークセグメントが特定のポートにアクセスすることを許可
sudo iptables -I DOCKER-USER -i eth0 -p tcp -s 192.168.1.0/24 --dport 6379 -j ACCEPT

# docker0 ブリッジが指定ポートへのトラフィックを転送することを許可
sudo iptables -I DOCKER-USER -i docker0 -p tcp --dport 6379 -j ACCEPT
sudo iptables -I DOCKER-USER -o docker0 -p tcp --dport 6379 -j ACCEPT

# その他のすべての該当ポートへのアクセス要求を拒否
sudo iptables -A DOCKER-USER -p tcp --dport 6379 -j DROP

# その他のポートのトラフィックを許可(オプション)
sudo iptables -A DOCKER-USER -j RETURN

複数ポート設定例

複数のポートを制限する必要がある場合は、複数ポートマッチを使用できます:

# 複数のポートへのアクセスを許可
sudo iptables -I DOCKER-USER -i eth0 -p tcp -s 192.168.1.0/24 -m multiport --dports 6379,8080,3306 -j ACCEPT

# docker0 ブリッジが複数のポートへのトラフィックを転送することを許可
sudo iptables -I DOCKER-USER -i docker0 -p tcp -m multiport --dports 6379,8080,3306 -j ACCEPT
sudo iptables -I DOCKER-USER -o docker0 -p tcp -m multiport --dports 6379,8080,3306 -j ACCEPT

# その他のすべてのこれらのポートへのアクセス要求を拒否
sudo iptables -A DOCKER-USER -p tcp -m multiport --dports 6379,8080,3306 -j DROP

ルールの検証

ルールが正しく設定されているか確認します:

# ルールリストを表示
➜  sudo iptables -L DOCKER-USER -n -v --line-numbers
Chain DOCKER-USER (1 references)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 ACCEPT     tcp  --  *      docker0  0.0.0.0/0            0.0.0.0/0            tcp dpt:6379
2        0     0 ACCEPT     tcp  --  docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:6379
3       28  1478 ACCEPT     tcp  --  eth0   *       192.168.1.0/24       0.0.0.0/0            tcp dpt:6379
4        9   540 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:6379
5       21  1107 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0

マシン1 (IP: 192.168.1.10):

マシン2 (IP: 192.168.2.10):

0x02 ルールの永続化

再起動後もルールが失われないように、設定した iptables ルールを保存する必要があります:

# Ubuntu/Debian システム
sudo netfilter-persistent save

# CentOS/RHEL システム
sudo service iptables save

0x03 ルールのクリーンアップ

ルールを削除する必要がある場合は、以下のコマンドを使用できます:

# DOCKER-USER チェーン内のすべてのルールをクリア
sudo iptables -F DOCKER-USER

# デフォルトルールに戻す(すべてのトラフィックを許可)
sudo iptables -A DOCKER-USER -j RETURN

0x04 注意事項

  1. ルールの順序が正しいことを確認し、ACCEPT ルールは DROP ルールの前に配置する必要があります
  2. ルールを追加する際には、コンテナ間の通信要件を考慮する必要があります
  3. カスタム Docker ネットワークを使用している場合は、ブリッジインターフェース名を適宜調整する必要があります
  4. 本番環境へのデプロイ前に、ルールの有効性を十分にテストすることを推奨します

タグ: Docker iptables ネットワークセキュリティ ポートマッピング コンテナセキュリティ

5月19日 08:54 投稿