【发布时间】:2020-12-21 19:56:13
【问题描述】:
我的应用有一个 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 might be exposing ports to the world、Beware of exposing ports in Docker 和Docker not blocked by macOS firewall,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"]
还有 docker-compose:
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 containers on Docker for Mac 和上述参考资料。所以我将这些添加到 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 的解决方案? (或者也许有一个合适的命令来启动后端?)
【问题讨论】:
-
您应该能够设置
ports: ['127.0.0.1:5078:5078']和类似的设置 Docker 不对外发布端口。iptables无法在 MacOS 主机或 Dockerfile 上运行。 (你能用原生 Javascript 重写“后端”部分,并拥有一个独立的非 Docker Electron 应用程序吗?) -
@DavidMaze 在后端有很多 python 统计/数字运算的东西,所以在 JS 中很难做到。 AFAIK Electron/GUI 不适合放入 docker。但是设置 ports: ['127.0.0.1:5078:5078'] 会解决问题吗?即,仍然从 Electron 收到消息但没有互联网连接? – 薛定谔科德
-
使用
127.0.0.1:5078将只允许 Mac 上运行的进程进行连接。链接的出口问题解决了另一个问题,即来自容器的出站流量。
标签: macos docker security flask docker-compose