You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在不暴露端口的前提下安全远程访问Docker Swarm集群内服务?

你的思路其实非常靠谱——用OpenVPN接入集群内部网络确实是这类场景下的最优方案之一,甚至可以说是最贴合你需求的选择。下面我会详细拆解怎么落地这个方案,同时也补充几个替代思路供你参考:

方案一:基于OpenVPN的集群内部网络接入(首推)

这个方案完美匹配你的所有要求:不需要暴露3306到公网,支持用服务/容器名直接连接,且不需要给终端SSH权限。

具体落地步骤:

  1. 创建专属管理Overlay网络
    为了隔离管理流量和业务流量,建议单独建一个overlay网络(比如叫mgmt-overlay),把MySQL服务和后续的OpenVPN服务都拉进来:

    docker network create --driver overlay --attachable mgmt-overlay
    # 把已有的MySQL服务加入这个网络(假设服务名是mysql-db)
    docker service update --network-add mgmt-overlay mysql-db
    

    --attachable是为了让独立容器(比如OpenVPN容器)也能接入这个网络,方便后续配置。

  2. 部署OpenVPN服务到Swarm集群
    用官方维护的OpenVPN镜像封装成Swarm服务,示例命令如下:

    docker service create \
      --name openvpn-server \
      --network mgmt-overlay \
      --publish 1194:1194/udp \
      --cap-add NET_ADMIN \
      --mount type=volume,source=openvpn-config,target=/etc/openvpn \
      kylemanna/openvpn:latest
    

    关键说明:

    • --cap-add NET_ADMIN是必须的,OpenVPN需要网络管理权限才能正常工作
    • 用Docker Volume持久化配置和证书,避免容器重启后丢失数据
    • 只暴露UDP 1194端口(OpenVPN默认端口),防火墙只允许你远程工作站的IP访问这个端口,进一步缩小攻击面
  3. 初始化配置并生成客户端证书
    进入容器完成初始化和证书生成:

    # 初始化服务器配置,替换<你的集群公网IP>为实际地址
    docker exec -it $(docker ps -q -f name=openvpn-server) ovpn_genconfig -u udp://<你的集群公网IP>
    # 生成根证书(按提示设置密码,后续管理证书需要用到)
    docker exec -it $(docker ps -q -f name=openvpn-server) ovpn_initpki
    # 给你的工作站生成客户端证书(命名为workstation-client,nopass表示不需要客户端密码)
    docker exec -it $(docker ps -q -f name=openvpn-server) easyrsa build-client-full workstation-client nopass
    # 导出客户端配置文件
    docker exec -it $(docker ps -q -f name=openvpn-server) ovpn_getclient workstation-client > workstation-client.ovpn
    

    把生成的workstation-client.ovpn传到你的远程工作站,用OpenVPN客户端导入即可连接。

  4. 添加路由让VPN客户端访问整个Overlay网络
    默认情况下,VPN客户端只能访问OpenVPN容器所在节点的网络,需要添加路由让客户端能覆盖整个Overlay子网。编辑OpenVPN服务器的/etc/openvpn/server.conf,添加一行:

    push "route <你的Overlay网络子网> 255.255.0.0"
    

    比如你的Overlay子网是10.0.0.0/16,就填push "route 10.0.0.0 255.255.0.0",然后重启服务生效:

    docker service update --force openvpn-server
    
  5. 用Workbench直接连接MySQL
    当你的工作站连上VPN后,在Workbench里直接输入MySQL服务名(比如mysql-db)或者容器名,端口填3306就能连上了——Overlay网络内置的DNS会自动把服务名解析到对应的容器IP,完全不用手动查地址。

安全加固小技巧:

  • 坚持用证书认证,不要启用密码登录,避免暴力破解风险
  • 在集群防火墙(或云服务商安全组)里,严格限制只有你工作站的公网IP能访问1194端口
  • 定期轮换客户端证书,及时撤销不再使用的证书
  • 把OpenVPN服务部署在专门的管理节点,不要和业务节点混在一起
方案二:Tailscale零配置VPN(简化替代)

如果你觉得OpenVPN的配置有点繁琐,可以试试Tailscale——它基于WireGuard,是零配置的VPN工具,部署维护更简单,还天生支持服务名解析。

大致步骤:

  1. 在Swarm集群的每个节点安装Tailscale客户端,加入同一个Tailscale网络
  2. 确保Tailscale能访问你的Overlay网络(可以通过节点路由配置实现)
  3. 在远程工作站安装Tailscale客户端,加入同一个网络
  4. 之后你就能直接用MySQL服务名连接数据库,Tailscale会自动同步集群内部的DNS解析

这个方案的优点是几乎不需要手动配置,缺点是默认依赖Tailscale的公共服务;如果需要完全私有部署,可以用Headscale作为自托管的控制服务器。

不推荐的方案(不符合你的限制)
  • SSH隧道:虽然可以通过ssh -L 3306:mysql-db:3306 <集群节点IP>建立隧道,但你明确禁止给终端SSH权限,所以这个方案直接排除
  • 暴露数据库端口到公网:不管是直接暴露还是通过反向代理,都会带来巨大的安全风险,完全不符合你的核心需求

总的来说,你最初考虑的OpenVPN方案是完全正确的,也是最符合你安全和易用性要求的选择。落地后既能保证数据库不暴露到公网,又能实现用服务名直接连接的便捷性。

内容的提问来源于stack exchange,提问作者Misakira

火山引擎 最新活动