• docker 映射端口穿透内置防火墙



    一、问题现象

    1、现象举例:

    # 自制的springboot项目的dockerfile
    # springboot 其实就是一个简单的hello-world程序,写了一个HelloController 做测试
    # dockerfile内容:
    FROM java:8 
    MAINTAINER shan <test@qq2363581677@163.com> 
    ADD ./demo.jar /demo.jar
    EXPOSE 8848
    CMD java -jar /demo.jar
    
    
    # 构建镜像
    docker build -f ./dockerfile -t demo .
    
    # 创建、映射端口、运行容器
    docker run -d --name=demo -p 8838:8848 demo
    

    在阿里云服务器上外置的防火墙或安全组放行端口 8838 后,在浏览器发现可以直接访问到数据

    ----问题在于咱还没有开启内置的防火墙firewalld,却出现了端口可以直接被访问的情况


    2、使用centos7 的防火墙firewalld查看放行端口情况

    使用 docker 来部署项目,发现直接使用 -p 映射端口,会出现问题:

    导致docker直接透过系统本机的防火墙,不用开端口可以直接外网访问 8838 端口。




    二、问题原因

    1、docker无视防火墙firewalld 的原因:其实docker并不是绕过了防火墙,只是因为它往iptables里写了规则,你在firewalld里看不到而已。(centos7系统既有iptables,也有firewalld)

    在docker安装完后,会接管iptables,只要你docker run的时候加入参数,他会自动向iptables里面添加规则。所以使用 -p 容器端口:主机端口,最终会在iptables中添加上容器的端口。



    ☺ 防火墙 iptables 和 firewalld 的关系

    Iptables:是centos6自带的防火墙工具,对服务器自身、网络通信流量进行控制,用于过滤数据包,属于网络层防火墙。

    FirewallD:是centos7自带的防火墙工具,但是也同样支持iptables。能够允许哪些服务可用,哪些端口可用,属于更高一层的防火墙。

    iptables 与 firewalld 都不是真正的防火墙, 它们都只是用来定义防火墙策略的防火墙管理工具。

    ● 对于 centos7 系统既有iptables,也有firewalld



    2、使用 iptables的命令可以查看到docker 容器的端口

    iptables -L DOCKER
    




    三、问题的解决

    1、依靠阿里云服务器提供的外置防火墙(推荐

    • 有的服务器叫防火墙,有的服务器叫安全组,都是一个东西,都是系统的外置防火墙。

    • 防火墙就像一个门,想象一下你的钱藏到你的房间,这时候有一个小偷想要来偷你的钱,小偷需要先溜进你家大门【外置防火墙(安全组/防火墙)】,然后再溜进你的房间【内置防火墙(iptables/firewalld)】。

    解决方式1:依靠阿里云服务器提供的外置防火墙放行需要暴露给外界的端口

    • 相当于关闭了你家大门

    虽然内置防火墙和外置防火墙一起使用更加安全,但是影响了数据访问的效率了,为了速度,有时候确保安全即可,不用更加安全。


    ☺ 购买了腾讯云服务的老铁要注意一下:

    配置安全组的时候,不要选择放行所有端口,要选择自定义,然后放行80、443、ping、ssh端口(ssh端口建议进行修改,不使用默认的22)



    2、端口映射时指定监听地址为本机

    对于那些只需要在本地访问,不需要向外暴露端口的服务,在进行端口映射的时候指定监听地址为127.0.0.1。

    # 创建、映射端口、运行容器
    docker run -d --name=demo -p 127.0.0.1:8838:8848 demo
    
    • 这时候,外界(通过浏览器)就无法访问了到8838 端口了,即使在外置防火墙放行了端口。



    3、禁用 docker 的 iptables 规则

    • 原因就是docker 在iptables 加入规则,才导致内置防火墙放行了docker容器的端口,现在咱就根治它,在docker配置文件禁止修改iptables 规则。

    ① docker 配置修改,禁止 iptables 规则

    # 编辑/lib/systemd/system/docker.service文件
    
    # 在ExecStart后添加 --iptables=false 
    

    ② 重载 docker 配置 & 重启 docker 服务

    systemctl daemon-reload
    systemctl restart docker
    

    完成上述两步以及可以采用系统 firewall 控制端口访问,但会出现 docker 容器间无法访问,而且容器内也无法访问外部网络

    ③ 使用类似 NAT 网络方式使得 docker 可以访问外部网络

    firewall-cmd --permanent --zone=public --add-masquerade
    
    • 使用该方法解决 docker 无视系统防火墙问题所带来的缺点:容器内无法获取得到客户端的真实 IP,由于是类似 NAT 网络,常常 nginx 日志上记录的是 docker0 网络的子网 IP,对于一些业务无法获取真实 IP 可能不能容忍,看个人的取舍吧。



    4、使用 expose 方式暴露端口,然后采用 nginx 代理转发(推荐)

    (1) 使用dockerCompose 编排+nginx代理转发

    ① dockerCompose 中编排内容:
    version: "3"
    services:
      app:
        image: app
        container_name: app
        build: ..
        expose:
         - "8888"
        depends_on:
          - mysql
          - redis
      nginx:
        image: nginx
        container_name: nginx
        ports:
          - 80:80
          - 443:443
        volumes:
          - /mnt/docker/nginx/:/etc/nginx/
        links:
          - app
        depends_on:
          - app
    
    ② nginx 中的配置:
    upstream appstream{
            server app:8888; #dockerCompose编排之后,app服务名相当于域名,可以通过app找到对应的ip地址
    }
    
    server{
            listen 80;
            server_name blog.yilele.site; 
            location /api {
    			proxy_pass http://appstream;#nginx代理转发
            }
    }
    

    (2) 上面例子的demo容器(使用dockerfile)+ nginx

    server{
            listen 80;
            server_name blog.yilele.site; 
            location /hello {# 启动docker的demo容器后,可以通过命令:docker inspect demo 找到demo对应的ip地址
    			proxy_pass http://demo的ip地址:8888;   # nginx代理转发
            }
    }
    



    ☺ ports 和 expose 区别:

    • ports: 暴露容器端口到主机的任意端口或指定端口。不管是否指定主机端口,使用ports都会将端口暴露给主机和其他容器

       - "9000:8080"     # 绑定容器的8080端口到主机的9000端口
        - "443"          # 绑定容器的443端口到主机的任意端口,容器启动时随机分配绑定的主机端口号
      
    • expose: 暴露容器给link到当前容器的容器。即暴露给处于同一个networks的容器。搭配link 进行使用。

      expose:
        - "8000"
      



    参考文章:《docker无视防火墙问题总结》 https://icharle.com/dockeriptables.html



    如果本文对你有帮助的话记得给一乐点个赞哦,感谢!

  • 相关阅读:
    CMAK学习
    Docker(三)、Dockerfile探究
    初探Hessian利用链为Dubbo-CVE占坑
    DC综合基本概念:uniquify
    langchain LLMRequestsChain
    对This 的指向的理解?
    线路质检用的到底多不多?
    高济健康:数字化科技创新与新零售碰撞 助推医疗产业优化升级
    R 语言 |普通矩阵怎么保存为稀疏矩阵的3列(i, j, x)格式?
    【广度优先搜索】leetcode 542. 01 矩阵
  • 原文地址:https://www.cnblogs.com/shan333/p/16422960.html