虚拟机安装nginx后无法访问,核心问题往往不在nginx本身,而在防火墙、网络适配器模式或监听地址这三处配置上,按顺序逐一排查,大多数情况下都能解决。
虚拟机nginx无法访问应该怎么排查
第一个要查的不是nginx的配置文件,而是虚拟机的防火墙,nginx装好了,进程也在跑,宿主机却怎么也打不开页面,十有八九是80端口被拦住了。
防火墙这个隐形门卫是最常见的原因
很多人在虚拟机里装完nginx,直接在虚拟机里用curl访问,发现通,然后换到宿主机浏览器一开,转圈,这个场景我见过太多次了,问题就出在虚拟机的firewalld或iptables上,firewalld是CentOS等系统的默认防火墙,拦截了宿主机来的请求。
解决方法不复杂,打开终端依次执行:
查看防火墙状态:
systemctl status firewalld
如果显示active (running),确认一下80端口有没有放行:
firewall-cmd --zone=public --list-all
看输出结果里ports部分有没有80/tcp,没有的话,执行开放命令:
firewall-cmd --zone=public --add-port=80/tcp --permanent
然后重新加载防火墙规则:
firewall-cmd --reload
再次查看,80端口放行了,宿主机再访问,一般就通了,行业共识认为,虚拟机网络访问问题中,防火墙因素占了相当一部分比重,这是排查虚拟机网络访问问题时优先关注的第一层。
如果系统用的是iptables,那就用:
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
service iptables save
nginx监听地址写对了没有
看一眼nginx.conf里listen这一行。
listen 80;
这样写等于监听所有网卡的80端口,但如果写成:
listen 127.0.0.1:80;
那只有虚拟机自己能访问,宿主机自然连不上,这个细节很隐蔽,很多教程里都不会提到,但它确实是经典坑位。
改完之后先测试配置,再重载:
nginx -t
nginx -s reload
虚拟机nginx外网无法访问,最常见的是网络适配器模式搞错了
防火墙没问题了,nginx也在监听,宿主机还是访问不了,那就要检查虚拟机的网络模式了,虚拟机的网络连接模式直接决定了宿主机能不能找到它。
NAT模式下宿主机怎么访问虚拟机里跑着的nginx
VMware和VirtualBox默认的网络模式都是NAT,NAT模式下,虚拟机对外是一个私网地址,宿主机可以访问虚拟机,但虚拟机里的服务对外不暴露。
很多人的虚拟机装的时候用的NAT,宿主机想直接访问nginx,通了才怪,解决思路有两条路:一条是改成桥接模式,另一条是配端口转发。
先说修改模式这条路,以VMware为例:
- 关闭虚拟机。
- 右键虚拟机名称,选“设置”。
- 找到“网络适配器”。
- 网络连接改成“桥接模式”。
- 启动虚拟机,用ip addr看一下IP是否变成和宿主机同一网段。
改完桥接模式,虚拟机在你的局域网里有了独立IP,宿主机直接访问这个IP就能打开nginx页面。
VirtualBox的操作类似,在“设置 → 网络 → 连接方式”里改成“桥接网卡”。
也可以设置端口转发,NAT模式下也能让宿主机访问虚拟机的nginx,在VirtualBox的NAT设置里添加一条转发规则,把宿主机的8080端口映射到虚拟机80端口,然后宿主机访问localhost:8080。
三种网络模式的访问差异
做个表格,一眼就看明白:
| 网络模式 | 宿主机访问虚拟机nginx | 局域网其它设备访问 | 典型场景 |
|---|---|---|---|
| NAT | 需配置端口转发 | 不可以 | 单机开发验证 |
| 桥接 | 直接访问虚拟机IP | 可以 | 模拟真实服务器环境 |
| 仅主机模式 | 可以 | 不可以 | 隔离调试 |
选了桥接模式后,如果虚拟机还是不通外网,检查虚拟机的网卡配置文件,CentOS里这个文件一般是:
/etc/sysconfig/network-scripts/ifcfg-ens33
确认BOOTPROTO="dhcp"没问题,ONBOOT="yes",改完重启网络服务:
systemctl restart network
网络这块的不通,还有一个容易忽略的点:虚拟机网卡是不是被禁用了,打开宿主机上的网络连接管理,确认VMnet1、VMnet8这些虚拟网卡没被禁。
nginx装上了但centos虚拟机nginx无法访问?查完网络查服务
有些情况是nginx压根没起来,或者起了一个多重冲突,页面自然打不开。
先看进程状态,执行:
ps -ef | grep nginx
有master和worker进程就说明nginx在运行,没有master进程,说明nginx没起来,去查错误日志,日志路径一般在:
/var/log/nginx/error.log
打开看看有没有binding地址冲突、权限不足、配置文件语法错误这些常见问题。
再看端口监听情况,确认nginx真的监听了80:
ss -lntp | grep 80
输出里有LISTEN状态和nginx进程名,说明监听正常,没有输出,检查nginx配置里server块的listen指令。
配置文件路径根据安装方式有区别,yum安装的在/etc/nginx/nginx.conf,源码编译的在/usr/local/nginx/conf/nginx.conf,改完配置记住先验证再重载:
/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx -s reload
现在还有一个坑:selinux,很多centos虚拟机nginx无法访问的问题,防火墙放行了,nginx也正常运行,但就是访问不了,原因就是SELinux拦截了HTTP流量。
查看SELinux状态:
getenforce
输出的结果是Enforcing,说明SELinux在强制模式,临时关闭SELinux试试:
setenforce 0
改完立刻在宿主机访问nginx,如果通了,说明SELinux确实是拦截的原因,不需要永久关闭SELinux,可以放行HTTP相关端口,据Red Hat官方文档说明,执行以下命令放行80端口:
semanage port -a -t http_port_t -p tcp 80
没有semanage命令就先装policycoreutils-python-utils再执行。
从无序到有序:一套完整的排查路径
把这些拆开讲可能还是让人发懵,实际操作中,按照下面这个顺序来排查,避免瞎猜浪费时间,这套经验的适用场景是:宿主机Windows或macOS,虚拟机里装的是Linux系统跑nginx。
第1步:宿主机和虚拟机之间能不能ping通
宿主机终端ping一下虚拟机的IP:
ping 虚拟机IP
ping不同,去查网卡、网络适配器模式、虚拟网络编辑器设置,网络都不通,nginx的问题只能靠后。
第2步:虚拟机里自测nginx能不能访问
在虚拟机里执行:
curl -I 127.0.0.1
这一步返回HTTP/1.1 200 OK,说明nginx进程正常、PHP或前后端分离的后端接口也正常,这一步不通,问题在nginx配置或依赖的服务没启动。
第3步:防火墙和SELinux双重排查
先放行80端口,再临时关闭SELinux,每做完一步就去宿主机访问一次试试,这一步解决这个问题的概率最大。
第4步:确认nginx监听地址是0.0.0.0而不是回环地址
ss -lntp | grep nginx
确认监听地址是不是0.0.0.0:80,监听在127.0.0.1:80,就要改nginx.conf。
第5步:虚拟机IP是否变了
桥接模式下,DHCP重新分配IP很正常,虚拟机IP变了,宿主机还访问旧IP,当然不通,IP变了就重新用新IP访问,或者给虚拟机配置静态IP,Windows宿主机上可以用ipconfig快速看一下网络情况,macOS用ifconfig。
Q&A
虚拟机nginx无法访问怎么快速定位?
速度最快的路径是:先在虚拟机里curl 127.0.0.1确认nginx本身没问题,然后curl虚拟机的IP确认端口监听正常,再检查firewalld的80端口放行状态,这三个动作做完,绝大部分的“装好了但访问不了”的问题都能定位到根因。
虚拟机nginx端口通着但就是打不开网页是什么原因?
进程在跑、端口也开着、防火墙也放行过了,页面还是打不开,优先排查nginx的server配置块,检查server_name是否写成域名,但宿主机hosts文件里没做映射,这种场景下,直接用IP访问时nginx会走到default_server对应的server块,而如果这个server块没配置对的root或index,就会返回403或404,用curl -I http://虚拟机IP看一下响应头和状态码,能告诉你更多信息。
虚拟机上nginx配置了多个server块,用IP访问却跳到第一个server块怎么办?
nginx默认按server_name匹配,IP请求如果没有匹配到具体server_name,会落到default_server,在需要作为默认站点的server块中显式添加default_server参数:listen 80 default_server,然后用nginx -t验证配置,再reload重载,指向偏移的问题在重载之后就会修正。