首页 > 解决方案 > 保护 Flask/Celery 应用程序的 localhost 端口,该应用程序在 MacOS 上的 Docker 中的 0.0.0.0 上本地运行

问题描述

我的应用程序有一个 Flask 后端和一个 Angular/Electron 前端。该应用程序在 Mac Catalina 上本地运行。Flask、Celery 和 Redis 位于单独的 docker 容器中,而前端位于 Docker 之外。Flask 容器正在侦听端口 0.0.0.0:5078。我已将 CORS 策略设置为仅允许来自“127.0.0.1:4200”的消息由前端发送。无需互联网连接。后端容器将由前端通过模拟终端命令来启动。我将在非技术用户的 Catalina MacBook 上远程安装该应用程序。

问题:根据Docker 可能正在向世界公开端口,注意在 DockerDocker 中暴露端口并没有被 macOS 防火墙阻止,这种使用 0.0.0.0:5078 是一种安全威胁。我怎样才能解决这个威胁,例如通过阻止任何外部连接到这个端口?

这是一些python 3.8代码

# imports: waitress, flask_cors, blueprint
cors = CORS(blueprint, resources={r"/*": {"origins":["http://127.0.0.1:4200"]}})
if __name__ == "__main__":
      serve(flask_app, host= '0.0.0.0', port=5078, threads=8)

这是 Dockerfile:

FROM python:3.8.3-slim-buster
WORKDIR /app
COPY requirements.txt requirements.txt
ENV BUILD_DEPS="build-essential" \
    APP_DEPS="curl libpq-dev"

RUN apt-get update \
  && apt-get install -y ${BUILD_DEPS} ${APP_DEPS} --no-install-recommends \
  && pip install --default-timeout=10000 -r requirements.txt

ARG FLASK_ENV="development"
ENV FLASK_ENV="${FLASK_ENV}" \
    FLASK_APP="back5x.api.app" \
    PYTHONUNBUFFERED="true"\
    FLASK_DEBUG=1
COPY  . .

RUN ["chmod", "+x", "/app/docker-entrypoint.sh"]
ENTRYPOINT ["/app/docker-entrypoint.sh"]
EXPOSE 5078
CMD ["python", "main.py"]

和码头工人组成:

version: "3.8"
services:
  redis:
 #    ...

  web:
    build:
      context: "."
      args:
        - "FLASK_ENV=development"
    depends_on:
      - "redis"
      - "worker"
    env_file:
      - ".env"
    environment:
      FLASK_DEBUG: 1
      FLASK_APP: back5x.api.app.py
    healthcheck:
      test: "${DOCKER_HEALTHCHECK_TEST:-curl localhost:5078/healthy}"
        ...
    ports:
      - "5078:5078"
    restart: "unless-stopped"
    volumes:
       - ".:/app"

  worker: #celery worker
    ...
volumes:
  redis: {}

尝试过: 我发现的基于 Docker 的解决方案使用 Linux iptables,例如Disallow egress from Docker for Mac 上的 Docker 容器和上述参考资料。所以我将这些添加到 Dockerfile 中:

RUN apt-get install -y iptables  --no-install-recommends   #after pip install
RUN iptables -N DOCKER-USER   #after COPY . .
RUN iptables -I FORWARD -j DOCKER-USER
RUN iptables -A DOCKER-USER -j RETURN
RUN iptables -I DOCKER-USER -i eth0 ! -s 0.0.0.0 -j DROP

没有中间三行,我得到一个错误,找不到 DOCKER-USER;与他们一起,我必须以 root 身份运行。我已经尝试过特权模式和app_cap,但是由于我是 Docker 新手,所以我还没有让它工作。

我还研究了在 Mac 的 PF 防火墙中定义一条规则,以阻止与相关端口的外部连接。但是,这对于将使用我的应用程序的人来说并不理想。类似的情况是安装付费的“小飞贼”应用程序。

在走这条路之前,是否有代码或基于 Docker 的解决方案?(或者也许有适当的命令来启动后端?)

标签: macosdockersecurityflaskdocker-compose

解决方案


一个可行的解决方案是基于 David Maze 和 Matt 的评论以及这个问题。这些是步骤:

  1. 打开Docker for MacPreferencesDocker Engine。添加 "ip": "127.0.0.1"到 json 配置文件。
  2. docker-compose中,为 服务设置 ports为。 "127.0.0.1:5078:5078"web
  3. 保持Dockerfile和python代码和以前一样:即flask主机仍然是0.0.0.0

当我检查时,来自 Electron 的 localhost 4201 的消息通过了。此外,运行 netstat -anvp tcp | awk 'NR<3 || /LISTEN/表明不安全的端口0.0.0.0.5078不再暴露在外部。`


推荐阅读