返回

解决VMware虚拟机MariaDB 3306端口无法访问难题

Linux

解决 VMware Workstation 虚拟机端口无法访问的疑难杂症 (以 MariaDB 3306 端口为例)

哥们儿,你是不是也遇到过这种情况:在 VMware Workstation 里跑了个 Ubuntu 服务器,装好了 MariaDB,结果从宿主机死活连不上虚拟机的 3306 端口?用 nmap 一扫,嘿,显示个 closed,明明 ufw 防火墙规则也加了,VMware 的 NAT 端口转发也配了,就是不通,让人挺头疼。

别急,这事儿通常不是啥玄学问题,一层一层捋清楚,总能找到原因。

问题在哪儿?可能的原因分析

端口访问不了,问题可能出在链条上的任何一环,从里到外排查一下:

  1. 服务本身压根没监听对地方: MariaDB 服务可能没启动,或者启动了但是只监听了本地回环地址 (127.0.0.1),这样的话,虚拟机内部自己能访问,但外面(包括宿主机)肯定访问不了。
  2. 虚拟机防火墙拦住了: 虽然 ufw status 看起来规则加对了,但防火墙可能没启用?或者规则没生效?或者有其他防火墙软件(比如直接操作 iptables)在捣乱?
  3. VMware 网络配置搞错了: 用的是 NAT 模式?那端口转发的规则配置对了吗?虚拟机 IP 地址填对了没?宿主机端口和虚拟机端口映射关系清楚吗?
  4. 宿主机防火墙出来挡路: 宿主机自己的防火墙(比如 Windows Firewall 或 Linux 上的 iptables/firewalld)可能阻止了到 VMware 虚拟网卡或者那个转发端口的访问。

知道了大概方向,咱们就一个个来解决。

动手!解决方案走起

一、 先确保 MariaDB 服务真的在监听

这是最常见但也最容易忽略的点。服务没跑起来,或者监听错了地址,后面的一切都是白搭。

原理与作用:

应用服务(像 MariaDB)需要绑定到一个 IP 地址和端口上,才能接收网络连接。

  • 127.0.0.1 (或者 localhost):意思是只接受来自虚拟机 内部 的连接。
  • 0.0.0.0:意思是监听本机所有可用的网络接口,接受来自任何地址的连接(只要防火墙允许)。
  • <虚拟机的具体IP地址>:只监听指定的那个 IP 地址,接受发往该 IP 的连接。

对于需要从宿主机或局域网其他机器访问的场景,通常需要监听 0.0.0.0 或者虚拟机在相应虚拟网络中的 IP 地址。

操作步骤:

  1. 检查服务状态:
    登录你的 Ubuntu 虚拟机,打开终端,执行:

    sudo systemctl status mariadb
    

    确保服务是 active (running) 状态。如果不是,尝试启动它:

    sudo systemctl start mariadb
    # 设置开机自启(如果需要)
    sudo systemctl enable mariadb
    
  2. 检查监听地址和端口:
    ss 命令 (比老的 netstat 更推荐) 查看哪个进程在监听 3306 端口:

    sudo ss -tulnp | grep 3306
    

    或者,如果你习惯 netstat

    sudo netstat -tulnp | grep 3306
    

    看仔细输出结果!

    • 正确的监听 (允许外部访问):

      tcp   LISTEN  0       80             0.0.0.0:3306        0.0.0.0:*      users:(("mariadbd",pid=1234,fd=20))
      # 或者监听了具体的 VM IP 地址 (假设 VM IP 是 192.168.75.128)
      tcp   LISTEN  0       80      192.168.75.128:3306        0.0.0.0:*      users:(("mariadbd",pid=1234,fd=20))
      

      看到 0.0.0.0:3306<vm_ip>:3306 就对了。

    • 错误的监听 (只允许本机访问):

      tcp   LISTEN  0       80           127.0.0.1:3306        0.0.0.0:*      users:(("mariadbd",pid=1234,fd=20))
      

      如果看到监听地址是 127.0.0.1,那从宿主机肯定连不上。

  3. 修改监听地址 (如果需要):
    如果发现 bind-address 设置成了 127.0.0.1,你需要修改 MariaDB 的配置文件。配置文件通常在 /etc/mysql/mariadb.conf.d/ 目录下,可能是 50-server.cnf 这个文件。

    sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
    

    找到 [mysqld] 段落下的 bind-address 配置项。

    • 注释掉它: 在行首加 #,让它监听所有地址 (0.0.0.0)。
      #bind-address           = 127.0.0.1
      
    • 或者改成 0.0.0.0:
      bind-address            = 0.0.0.0
      
    • 或者改成虚拟机的 IP 地址: (不推荐,除非你很清楚为什么这么做)
      bind-address            = <你的虚拟机IP地址>
      

    修改完保存文件 (在 nano 中按 Ctrl+X,然后按 Y,再按 Enter)。

  4. 重启 MariaDB 服务:
    让配置生效,必须重启服务:

    sudo systemctl restart mariadb
    

    重启后,再次用 ss -tulnp | grep 3306 确认监听地址是否正确。

安全建议:

  • bind-address 设为 0.0.0.0 会让数据库监听所有网络接口。确保你的虚拟机防火墙 (ufw) 配置得当,只允许受信任的 IP 地址访问 3306 端口。
  • 数据库安全不仅仅是端口访问。强烈建议为你的应用创建专门的数据库用户,并限制该用户的来源 IP (CREATE USER 'appuser'@'your_host_ip' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON your_database.* TO 'appuser'@'your_host_ip'; FLUSH PRIVILEGES;),而不是使用 root 用户或者允许任何主机 ('user'@'%') 连接。

二、 再捋一遍虚拟机防火墙 (UFW)

你已经在问题里展示了 ufw status 的输出,看起来 3306 端口(TCP 和 UDP)是 ALLOW Anywhere 的。但还是有几个点需要确认下。

原理与作用:

ufw (Uncomplicated Firewall) 是 Ubuntu 上管理 iptables 规则的前端工具。它通过定义规则来允许或拒绝特定端口、协议或来源 IP 的网络流量。即使规则添加了,如果 ufw 服务没启用,或者规则没被正确加载,那也是白搭。

操作步骤:

  1. 确认 UFW 是否启用:

    sudo ufw status
    

    如果输出是 Status: inactive,那你的规则根本没生效。需要启用它:

    sudo ufw enable
    # 它会提示可能断开现有连接,输入 y 继续
    

    启用后,它会自动加载 /etc/ufw/user.rules 等配置文件里的规则。

  2. 再次检查规则列表 (详细):
    verbose 参数看得更清楚点:

    sudo ufw status verbose
    

    确保你看到的 3306/tcp ALLOW IN Anywhere (以及对应的 IPv6 规则,如果你需要的话) 确实存在并且状态是激活的。

  3. 重载规则 (以防万一):
    有时候,虽然你看不到问题,但重载一下规则能解决一些奇怪的情况。

    sudo ufw reload
    

安全建议:

  • ALLOW Anywhere 太宽松了!如果你的宿主机 IP 地址是固定的或者在一个固定子网内,最好把规则改成只允许那个 IP 或子网访问。例如,如果你的宿主机通过 NAT 访问时,在 VM 看来其源 IP 通常是 VMware NAT 的网关 IP (可以在 Virtual Network Editor 里看到 NAT 设置的 Gateway IP),或者干脆就是你的宿主机连接到虚拟 NAT 网络的 IP (如果 VMware 做了某些透明处理)。更简单的情况是在使用桥接模式时,直接用你宿主机的局域网 IP。
    假设你的宿主机 IP 是 192.168.1.100
    # 先删除旧的宽松规则 (用 ufw status numbered 找到规则编号)
    # sudo ufw delete <rule_number>
    # 添加更严格的规则
    sudo ufw allow from 192.168.1.100 to any port 3306 proto tcp
    sudo ufw reload
    
    如果是桥接模式,192.168.1.100 就换成你宿主机真实的局域网 IP。如果是 NAT 模式,这个源 IP 可能需要试验一下,或者直接允许来自整个 VMware NAT 子网的 IP (例如 192.168.75.0/24,具体子网看 Virtual Network Editor)。

进阶技巧:

  • ufw 底层还是用的 iptables。如果你之前手动配置过 iptables 规则,可能会和 ufw 冲突。尽量只用一种工具管理防火墙。可以用 sudo iptables -L -n -v 查看实际生效的 iptables 规则,看有没有 REJECTDROP 3306 端口的规则排在 ACCEPT 规则前面。

三、 检查 VMware 网络配置 (NAT 模式下的端口转发)

既然你提到了 NAT 模式和端口转发,那这块也得好好检查。

原理与作用:

NAT (Network Address Translation) 模式下,虚拟机共享宿主机的 IP 地址对外通信。虚拟机本身在一个私有子网内(比如默认的 192.168.75.0/24),宿主机充当了路由器和网关。外部网络(包括宿主机本身)不能直接访问虚拟机的私有 IP。端口转发就像在宿主机这个“路由器”上打了个洞:告诉 VMware,发往宿主机某个特定端口的流量,请你帮我转发给虚拟机内部某个 IP 的某个端口。

操作步骤:

  1. 打开 VMware Workstation 的虚拟网络编辑器:
    在 VMware Workstation 菜单栏,找到 Edit -> Virtual Network Editor...。可能需要管理员权限才能修改设置。

  2. 选择 NAT 网络:
    在列表中找到类型为 NAT 的网络适配器,通常是 VMnet8。选中它。

  3. 配置 NAT 设置:
    点击 NAT Settings... 按钮。

  4. 添加或检查端口转发规则:
    Port Forwarding 部分,点击 Add... (或者找到你已经添加的规则进行编辑)。
    你需要填写的关键信息:

    • Host Port: 这是你希望在 宿主机 上访问的端口。可以和虚拟机端口一样(比如 3306),也可以不一样(比如 33060)。用 nmap 或者数据库客户端连接时,要用的是 这个 端口。
    • Type: 选择 TCP (因为 MySQL/MariaDB 使用 TCP 协议)。
    • Virtual machine IP address: 极其重要! 这里必须填对你 Ubuntu 虚拟机的 准确 IP 地址。在虚拟机终端里用 ip addr 命令查看,找到类似 inet 192.168.75.128/24 这样的地址,填入 192.168.75.128 部分。每次虚拟机重启 IP 地址可能会变 (如果用 DHCP)! 最好给虚拟机设置静态 IP。
    • Virtual machine port: 这里填写真正的服务端口,也就是 MariaDB 监听的 3306

    举例:
    假设宿主机想通过访问自己的 3306 端口来连接虚拟机 (192.168.75.128) 的 3306 端口,配置如下:

    • Host Port: 3306
    • Type: TCP
    • Virtual machine IP address: 192.168.75.128
    • Virtual machine port: 3306

    配置好后,点 OK 保存 NAT 设置,再点 OK 关闭虚拟网络编辑器。

给虚拟机设置静态 IP (推荐):
为了避免虚拟机 IP 变动导致端口转发失效,建议给它配个静态 IP。
编辑 /etc/netplan/ 目录下的 yaml 文件(文件名可能类似 00-installer-config.yaml50-cloud-init.yaml):

sudo nano /etc/netplan/00-installer-config.yaml # 文件名可能不同

修改内容类似(根据你的实际网络接口名和VMware NAT 子网调整):

network:
  ethernets:
    ensXX: # 这里替换成你的网卡名,用 ip a 查看
      dhcp4: no # 关闭DHCP
      addresses: [192.168.75.150/24] # 设置静态IP和子网掩码
      gateway4: 192.168.75.2 # 网关地址,看虚拟网络编辑器里的 NAT Settings
      nameservers:
        addresses: [8.8.8.8, 192.168.75.2] # DNS服务器,可以用公共DNS或网关
  version: 2

修改后应用配置:

sudo netplan apply

再用 ip addr 确认 IP 是否变成你设置的静态 IP。别忘了回头更新 VMware 端口转发规则里的虚拟机 IP 地址。

安全建议:

  • 宿主机上开放的那个 Host Port 现在是对外部开放的(如果宿主机防火墙允许)。请确保宿主机防火墙也配置得当。
  • 选择一个不常用的 Host Port (比如 33306 转发到 VM 的 3306) 可以轻微降低被扫描到的风险,但这并非真正的安全措施。

四、 检查宿主机防火墙

最后一道关卡,也可能是被忽略的。宿主机自身的防火墙可能阻止了访问转发端口的连接。

原理与作用:

无论是 Windows Defender Firewall、Linux 的 iptables/firewalld/ufw,还是 macOS 的 PF,宿主机上的防火墙负责控制进入和流出宿主机自身的流量。当你尝试连接宿主机的 Host Port (在 NAT 端口转发里设置的那个) 时,宿主机防火墙需要允许这个入站连接。

操作步骤:

  • Windows 系统:

    1. 搜索 "Windows Defender Firewall with Advanced Security" (高级安全 Windows Defender 防火墙)。
    2. 在左侧选择 "入站规则"。
    3. 在右侧点击 "新建规则..."。
    4. 选择 "端口",点击 "下一步"。
    5. 选择 "TCP",并在 "特定本地端口" 中输入你在 VMware NAT 设置里配置的 Host Port (例如 3306),点击 "下一步"。
    6. 选择 "允许连接",点击 "下一步"。
    7. 选择适用的网络配置文件 (域、私有、公用 - 根据你的网络环境选择,私有通常是家用/办公网络),点击 "下一步"。
    8. 给规则起个名字 (例如 "Allow MariaDB VM Access"),点击 "完成"。

    或者用 PowerShell (以管理员身份运行):

    New-NetFirewallRule -DisplayName "Allow MariaDB VM Access (TCP 3306)" -Direction Inbound -Protocol TCP -LocalPort 3306 -Action Allow -Profile Private,Domain
    

    (根据需要调整端口 -LocalPort 和配置文件 -Profile)

  • Linux 宿主机 (以 ufw 为例):
    如果在宿主机上也使用 ufw

    # 允许特定端口 (假设 Host Port 是 3306)
    sudo ufw allow 3306/tcp
    sudo ufw reload
    

    如果使用的是 firewalld:

    sudo firewall-cmd --permanent --add-port=3306/tcp
    sudo firewall-cmd --reload
    
  • macOS 宿主机:
    macOS 默认防火墙 (System Settings > Network > Firewall) 通常不阻止这种类型的连接,除非你手动添加了阻止规则。如果使用了第三方防火墙或 pfctl 手动配置,需要相应检查。

安全建议:

  • 和虚拟机防火墙一样,宿主机防火墙规则也应该尽可能严格。如果可能,只允许来自特定 IP (例如你的开发机 IP) 访问这个转发端口。Windows 防火墙规则的属性里可以设置远程 IP 地址范围。Linux ufw 可以用 ufw allow from <source_ip> to any port <host_port> proto tcp

如何测试连接?

排查过程中,你需要反复测试端口是否通了。

  • 从宿主机测试 (NAT + Port Forwarding):
    nmap (如果宿主机安装了) 或者 telnet (Windows 需要手动安装 telnet 客户端功能):

    # 使用你在 VMware 端口转发中设置的 Host Port
    nmap <宿主机自己的IP或localhost> -p <Host_Port>
    
    # 或者
    telnet <宿主机自己的IP或localhost> <Host_Port>
    # 如果连接成功,屏幕会变黑或者显示 Connected to ...
    # 按 Ctrl + ] 然后输入 quit 退出 telnet
    

    如果 nmap 显示 open,或者 telnet 连接成功,说明网络通路基本打通了。接下来用你的数据库客户端连接 <宿主机IP>:<Host_Port> 应该就可以了。

  • 测试失败时的提示:

    • nmap 显示 closed:表示 TCP 握手的 SYN 包收到了 RST/ACK 包回应。通常意味着到达了目标 IP,但是该端口上没有服务在监听,或者 有防火墙明确拒绝了连接 (REJECT)。—— 这时候要重点检查 步骤一 (服务监听)步骤二/四 (防火墙配置,确保不是 REJECT 规则)
    • nmap 显示 filtered:表示 SYN 包发出去后石沉大海,没有收到任何回应 (超时)。通常意味着有防火墙 丢弃 了数据包 (DROP),可能是虚拟机防火墙、VMware 网络配置问题、或宿主机防火墙。—— 这时候要重点检查 步骤二/三/四 (防火墙/网络配置)
    • telnet 提示 Connect failedUnable to connect to remote host:跟 nmapclosedfiltered 情况类似。

实在搞不定?试试桥接模式

如果 NAT 模式加端口转发把你绕晕了,或者就是配不好,可以考虑换成桥接模式 (Bridged Mode)。

原理与作用:

桥接模式下,VMware 会把虚拟机的网络适配器直接桥接到宿主机的一个物理网络适配器上(比如你的有线网卡或无线网卡)。虚拟机就像是插在和你宿主机同一个路由器或交换机上的另一台独立电脑,它会从你的局域网 DHCP 服务器(通常是你的路由器)获取一个和宿主机在同一个网段的 IP 地址。

操作步骤:

  1. 关闭虚拟机。
  2. 编辑虚拟机设置:
    在 VMware Workstation 中选中你的虚拟机,点击 VM -> Settings... -> Network Adapter
  3. 选择桥接模式:
    在右侧 Network connection 部分,选择 Bridged: Connected directly to the physical network
    • (可选) 如果你的宿主机有多个物理网卡,可以通过 Configure Adapters... 按钮选择桥接到哪个物理网卡。一般保持默认自动选择即可。
  4. 启动虚拟机。
  5. 获取新的 IP 地址:
    虚拟机启动后,登录进去,用 ip addr 查看它获取到的新的 IP 地址。这个 IP 地址应该和你宿主机的 IP 地址在同一个子网内(比如都是 192.168.1.x)。
  6. 配置虚拟机防火墙:
    因为虚拟机现在直接暴露在局域网了,更要确保 ufw 防火墙规则配置正确,允许来自你宿主机或其他需要访问的机器 IP 访问 3306 端口。
    # 假设宿主机 IP 是 192.168.1.100
    sudo ufw allow from 192.168.1.100 to any port 3306 proto tcp
    sudo ufw reload
    
  7. 从宿主机直接连接:
    现在不需要经过 VMware 的端口转发了。直接使用虚拟机的 新 IP 地址 和 MariaDB 的 原始端口 3306 来连接。
    nmap <虚拟机新的IP地址> -p 3306
    telnet <虚拟机新的IP地址> 3306
    # 用数据库客户端连接 <虚拟机新的IP地址>:3306
    

桥接模式的优缺点:

  • 优点: 网络配置相对简单直接,没有 VMware 端口转发这层。性能可能略好一点。
  • 缺点: 虚拟机直接暴露在局域网上,安全性更依赖虚拟机自身的防火墙。需要在局域网里有可用的 IP 地址。在某些受限的网络环境(比如公司网络)可能不允许或无法正常工作。

一步步排查下来,总能找到卡住你的那个环节。祝你好运!