web-dev-qa-db-ja.com

iptablesルールの使用がDockerコンテナーで機能しない

ElasticSearchコンテナーを会社のLaravel app。上記のLaravelアプリの特定のIPからのみアクセスできます。

調査中、多くの人がDockerによって転送されたポートへのトラフィックが完全に公開され、適切にファイアウォールを設定できないというこれらの問題を抱えていることに気付きました。

私はいくつかのsolutionsを過去6時間で見つけましたが、どれも機能していませんでした。これはDockerがインバウンドトラフィックを処理/転送する方法に関係していると思います。iptablesの知識はそれほど大きくないため、自分で何が起こっているのかを理解できます。

これは私のdocker-compose.ymlです(価値あるもの):

version: '3.4'

services:

  elasticsearch:
    image: khezen/elasticsearch:6.1.1
    container_name: elasticsearch

    environment:
      NETWORK_Host: 0.0.0.0
      HOSTS: 127.0.0.1
      CLUSTER_NAME: fd-es
      NODE_NAME: node-1
      HEAP_SIZE: 31g
      HTTP_SSL: "true"
      ELASTIC_PWD: "somepasswd"
      HTTP_CORS_ENABLE: "true"
      HTTP_CORS_ALLOW_Origin: /https?:\/\/localhost(:[0-9]+)?/

    ulimits:
      memlock:
       soft: -1
       hard: -1

    volumes:
      - ./config/elasticsearch.yml:/elasticsearch/config/elasticsearch.yml
      - ./data:/elasticsearch/data
      - ./logs:/elasticsearch/logs

    ports:
      - 9200:9200

    networks:
      - es-network

    restart: always

networks:
  es-network:
    driver: bridge

これらは現在使用しているiptablesルールで、ある程度は必要ですが、任意のクライアントからポート9200へのすべてのトラフィックは、アプリからのみアクセスできるのではなく、そのまま通過します。

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [779:162776]
:DOCKER - [0:0]
-A DOCKER -s xxx.xxx.xxx.xxx -p tcp -m tcp --dport 9200 -j ACCEPT
-A DOCKER -o docker0 -p tcp -m tcp --dport 9200 -j ACCEPT
-A DOCKER -p tcp --dport 9200 -j DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -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 ACCEPT
-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 44344 -j ACCEPT
-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
-A INPUT -j DROP

Dockerのiptablesサポートを無効にし、ブリッジネットワークを無効にして、iptablesルールを数十回微調整しましたが、役に立ちませんでした。

私はこの問題のアイデアと検索結果が足りないので、どんな提案やこれを実現する手助けをいただければ幸いです。

前もって感謝します!

3
dzhi

この問題の解決策を探しているすべての人にとって、答えはこれです。

*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:FILTERS - [0:0]
:DOCKER-USER - [0:0]

-F INPUT
-F DOCKER-USER
-F FILTERS

-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp --icmp-type any -j ACCEPT
-A INPUT -j FILTERS

-A DOCKER-USER -i ens33 -j FILTERS

-A FILTERS -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FILTERS -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A FILTERS -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A FILTERS -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A FILTERS -j REJECT --reject-with icmp-Host-prohibited

COMMIT

ここで見つかりました: https://unrouted.io/2017/08/15/docker-firewall/

完璧に動作します。

2
dzhi

私があなたが達成したいことをテストした私のシナリオを説明します。

ポート9010がポート8080に転送されるDockerコンテナーを起動しました。

docker run -p 9010:8080 swaggerapi/swagger-editor

Dockerは、ポート9010からポート8080にトラフィックを転送するPREROUTINGチェーンのDNATルールを作成します。

DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:9010 to:172.17.0.5:8080

Dockerは、DOCKERチェーンにルールを作成し、コンテナーのIPアドレスとポート8080に送信されるすべてのトラフィックを許可します。

ACCEPT     tcp  --  !docker0 docker0  0.0.0.0/0            172.17.0.5           tcp dpt:8080

DOCKERチェーンはFORWARDチェーンで使用され、docker0ブリッジに送信されるすべてのトラフィックはDOCKERチェーンのルールによって処理されます。

DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0

次に、ポート8080に送信されるトラフィック(ポート9010へのトラフィックはPREROUTINGによって処理され、ポート8080に送信されるトラフィックです)をフィルター処理して、IP 192.168.1.142からのトラフィックを許可しながらすべてのIPアドレスをブロックします。もちろん、コンテナのIPアドレスをこれらのルールに追加して、より細かい粒度にすることもできます。

[〜#〜] forward [〜#〜]チェーンの先頭に次のルールを追加します。または、FORWARDをDOCKERに置き換えることもできます。

iptables -I FORWARD -p tcp --dport 8080 -j DROP
iptables -I FORWARD -p tcp -s 192.168.1.142 --dport 8080 -j ACCEPT

これらのルールのおかげで、コンテナが使用する8080ポートに到達できるのはIP 192.168.1.142だけです。

この回答にアクセスする場合、1つの特定のIPアドレスにのみコンテナーへのアクセスを許可する場合は、 Docker docs で提案されているiptablesコマンドを使用します。

1
Miguel A. C.